Version 2.3.2-dev.0.1
Merge commit '55d3bbf13f81552c33fe0dc6a9557233b85b8f97' into dev
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4de047e..4221276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,70 @@
+## 2.3.2-dev.0.1
+(Add new changes here, and they will be copied to the change section for the
+ next dev version)
+
+### Language
+
+* **Breaking change:** Covariance of type variables used in super-interfaces
+ is now enforced (issue [35097][]). For example, the following code was
+ previously accepted and will now be rejected:
+
+```dart
+class A<X> {};
+class B<X> extends A<void Function(X)> {};
+```
+
+* The identifier `async` can now be used in asynchronous and generator
+ functions.
+
+[35097]: https://github.com/dart-lang/sdk/issues/35097
+
+### Core libraries
+
+#### `dart:developer`
+* Exposed `result`, `errorCode` and `errorDetail` getters in
+ `ServiceExtensionResponse` to allow for better debugging of VM service
+ extension RPC results.
+
+#### `dart:io`
+
+* Fixed `Cookie` class interoperability with certain websites by allowing the
+ cookie values to be the empty string (Issue [35804][]) and not stripping
+ double quotes from the value (Issue [33327][]) in accordance with RFC 6265.
+
+ [33327]: https://github.com/dart-lang/sdk/issues/33327
+ [35804]: https://github.com/dart-lang/sdk/issues/35804
+
+* The `HttpClientResponse` interface has been extended with the addition of a
+ new `compressionState` getter, which specifies whether the body of a
+ response was compressed when it was received and whether it has been
+ automatically uncompressed via `HttpClient.autoUncompress` (Issue [36971][]).
+
+ As part of this change, a corresponding new enum was added to `dart:io`:
+ `HttpClientResponseCompressionState`.
+
+ [36971]: https://github.com/dart-lang/sdk/issues/36971
+
+ * **Breaking change**: For those implementing the `HttpClientResponse`
+ interface, this is a breaking change, as implementing classes will need to
+ implement the new getter.
+
+### Dart VM
+
+### Tools
+
+#### Linter
+
+The Linter was updated to `0.1.90`, which includes the following changes:
+
+* fixed null-reference in `unrelated_type_equality_checks`
+* new lint: `unsafe_html`
+
+#### Pub
+
+* `pub publish` will no longer warn about missing dependencies for import
+ statements in `example/`.
+* OAuth2 authentication will explicitely ask for the `openid` scope.
+
## 2.3.2-dev.0.0
### Tools
@@ -285,7 +352,7 @@
`.g.dart`, etc.).
* Fixed false positives in `unnecessary_parenthesis`.
-#### Pub client
+#### Pub
* Added a CHANGELOG validator that complains if you `pub publish` without
mentioning the current version.
diff --git a/DEPS b/DEPS
index e9f2353..efa5353 100644
--- a/DEPS
+++ b/DEPS
@@ -96,7 +96,7 @@
"intl_tag": "0.15.7",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "2.0.9",
- "linter_tag": "0.1.89",
+ "linter_tag": "0.1.90",
"logging_tag": "0.11.3+2",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
"markdown_tag": "2.0.3",
@@ -113,7 +113,7 @@
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "1.3.6",
"protobuf_rev": "7d34c9e4e552a4f66acce32e4344ae27756a1949",
- "pub_rev": "8c363fe26f059c3063f1129adbb3c4e22a8ce954",
+ "pub_rev": "ecd5b413271f2699f8cd9e23aa4eebb5030c964f",
"pub_semver_tag": "1.4.2",
"quiver-dart_tag": "2.0.0+1",
"resource_rev": "2.1.5",
@@ -133,7 +133,7 @@
"test_process_tag": "1.0.3",
"term_glyph_tag": "1.0.1",
"test_reflective_loader_tag": "0.1.8",
- "test_tag": "test-v1.6.1",
+ "test_tag": "test-v1.6.4",
"typed_data_tag": "1.1.6",
"unittest_rev": "2b8375bc98bb9dc81c539c91aaea6adce12e1072",
"usage_tag": "3.4.0",
@@ -168,7 +168,6 @@
}],
"dep_type": "cipd",
},
-
Var("dart_root") + "/tests/co19_2/src": {
"packages": [{
"package": "dart/third_party/co19",
@@ -176,11 +175,16 @@
}],
"dep_type": "cipd",
},
-
Var("dart_root") + "/third_party/markupsafe":
Var("chromium_git") + "/chromium/src/third_party/markupsafe.git" +
"@" + Var("markupsafe_rev"),
-
+ Var("dart_root") + "/third_party/babel": {
+ "packages": [{
+ "package": "dart/third_party/babel",
+ "version": "version:7.4.5",
+ }],
+ "dep_type": "cipd",
+ },
Var("dart_root") + "/third_party/zlib":
Var("chromium_git") + "/chromium/src/third_party/zlib.git" +
"@" + Var("zlib_rev"),
diff --git a/README.md b/README.md
index 51f129a..195667d 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,43 @@
# Dart
-[Dart][website] is an open-source, scalable programming language, with robust
-libraries and runtimes, for building web, server, and mobile apps.
+## A client-optimized language for fast apps on any platform
+
+Dart is:
+
+ * **Optimized for UI**:
+ Develop with a programming language specialized around the needs of user interface creation
+
+ * **Productive**:
+ Make changes iteratively: use hot reload to see the result instantly in your running app
+
+ * **Fast on all platforms**:
+ Compile to ARM & x64 machine code for mobile, desktop, and backend. Or compile to JavaScript for the web
+
+Dart has flexible compiler technology lets you run Dart code in different ways,
+depending on your target platform and goals:
+
+ * **Dart Native**: For programs targeting devices (mobile, desktop, server, and more),
+ Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an
+ AOT (ahead-of-time) compiler for producing machine code.
+
+ * **Dart Web**: For programs targeting the web, Dart Web includes both a development time
+ compiler (dartdevc) and a production time compiler (dart2js).
+
+![Dart platforms illustration](https://dart.dev/assets/platforms-7f4d540acf9fe801b456ad74f9f855230a385014d05d9f5997c878b889a67a0f.svg)
+
+## License & patents
+
+Dart is free and open source.
+
+See [LICENSE][license] and [PATENTS][patents].
## Using Dart
-Visit the [dartlang.org][website] to learn more about the
+Visit the [dart.dev][website] to learn more about the
[language][lang], [tools][tools],
[getting started][codelab], and more.
-Browse [pub.dartlang.org][pubsite] for more packages and libraries contributed
+Browse [pub.dev][pubsite] for more packages and libraries contributed
by the community and the Dart team.
## Building Dart
@@ -26,11 +54,7 @@
You can also contribute patches, as described in [Contributing][contrib].
-## License & patents
-
-See [LICENSE][license] and [PATENTS][patents].
-
-[website]: https://www.dartlang.org
+[website]: https://dart.dev
[license]: https://github.com/dart-lang/sdk/blob/master/LICENSE
[repo]: https://github.com/dart-lang/sdk
[lang]: https://www.dartlang.org/docs/dart-up-and-running/ch02.html
@@ -38,6 +62,5 @@
[codelab]: https://www.dartlang.org/codelabs/darrrt/
[dartbug]: http://dartbug.com
[contrib]: https://github.com/dart-lang/sdk/wiki/Contributing
-[pubsite]: https://pub.dartlang.org
+[pubsite]: https://pub.dev
[patents]: https://github.com/dart-lang/sdk/blob/master/PATENTS
-
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index baa7bc3..f073da1 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -433,8 +433,10 @@
]
}
- # Android standard library setup.
- if (is_android) {
+ if (is_linux) {
+ libs += [ "dl" ]
+ } else if (is_android) {
+ # Android standard library setup.
if (is_clang) {
# Work around incompatibilities between bionic and clang headers.
defines += [ "__compiler_offsetof=__builtin_offsetof" ]
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 918ff0b..9a5386a 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.26.1
+ 1.27.0
</h1>
<p>
This document contains a specification of the API provided by the
@@ -1455,6 +1455,7 @@
+
<h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
"id": String
"method": "completion.getSuggestions"
@@ -1612,6 +1613,7 @@
"<b>replacementLength</b>": int
"<b>results</b>": List<<a href="#type_CompletionSuggestion">CompletionSuggestion</a>>
"<b>isLast</b>": bool
+ "<b>libraryFile</b>": <span style="color:#999999">optional</span> <a href="#type_FilePath">FilePath</a>
"<b>includedSuggestionSets</b>": <span style="color:#999999">optional</span> List<<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>>
"<b>includedElementKinds</b>": <span style="color:#999999">optional</span> List<<a href="#type_ElementKind">ElementKind</a>>
"<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List<<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>>
@@ -1663,6 +1665,16 @@
True if this is that last set of results that will be
returned for the indicated completion.
</p>
+ </dd><dt class="field"><b>libraryFile: <a href="#type_FilePath">FilePath</a><span style="color:#999999"> (optional)</span></b></dt><dd>
+
+ <p>
+ The library file that contains the file where completion was
+ requested. The client might use it for example together with the
+ <tt>existingImports</tt> notification to filter out available
+ suggestions. If there were changes to existing imports in the library,
+ the corresponding <tt>existingImports</tt> notification will be sent
+ before the completion notification.
+ </p>
</dd><dt class="field"><b>includedSuggestionSets: List<<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>><span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
@@ -1720,6 +1732,29 @@
<p>
A list of library ids that no longer apply.
</p>
+ </dd></dl></dd><dt class="notification"><a name="notification_completion.existingImports">completion.existingImports</a></dt><dd><div class="box"><pre>notification: {
+ "event": "completion.existingImports"
+ "params": {
+ "<b>file</b>": <a href="#type_FilePath">FilePath</a>
+ "<b>imports</b>": <a href="#type_ExistingImports">ExistingImports</a>
+ }
+}</pre></div>
+ <p>
+ Reports existing imports in a library. This notification may be sent
+ multiple times for a library. When a notification is processed, clients
+ should replace any previous information for the library.
+ </p>
+
+ <h4>parameters:</h4><dl><dt class="field"><b>file: <a href="#type_FilePath">FilePath</a></b></dt><dd>
+
+ <p>
+ The defining file of the library.
+ </p>
+ </dd><dt class="field"><b>imports: <a href="#type_ExistingImports">ExistingImports</a></b></dt><dd>
+
+ <p>
+ The existing imports in the library.
+ </p>
</dd></dl></dd></dl>
<h2 class="domain"><a name="domain_search">search domain</a></h2>
<p>
@@ -2833,6 +2868,9 @@
+
+
+
<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
@@ -3182,11 +3220,15 @@
<dl><dt class="value">AVAILABLE_SUGGESTION_SETS</dt><dd>
<p>
- The client will receive notifications once subscribed with completion suggestion sets from
- the libraries of interest. The client should keep an up-to-date record of these in
+ The client will receive <tt>availableSuggestions</tt> notifications
+ once subscribed with completion suggestion sets from the libraries of
+ interest. The client should keep an up-to-date record of these in
memory so that it will be able to union these candidates with other
completion suggestions when applicable at completion time.
</p>
+ <p>
+ The client will also receive <tt>existingImports</tt> notifications.
+ </p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_CompletionSuggestion">CompletionSuggestion: object</a></dt><dd>
<p>
A suggestion for how to complete partially entered text. Many of the
@@ -3602,7 +3644,40 @@
domain.
</p>
- <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
+ <dl><dt class="value">LAUNCH_DATA</dt></dl></dd><dt class="typeDefinition"><a name="type_ExistingImport">ExistingImport: object</a></dt><dd>
+ <p>
+ Information about an existing import, with elements that it provides.
+ </p>
+
+ <dl><dt class="field"><b>uri: int</b></dt><dd>
+
+ <p>
+ The URI of the imported library.
+ It is an index in the <tt>strings</tt> field, in the enclosing
+ <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+ </p>
+ </dd><dt class="field"><b>elements: List<int></b></dt><dd>
+
+ <p>
+ The list of indexes of elements, in the enclosing
+ <tt>ExistingImports</tt> object.
+ </p>
+ </dd></dl></dd><dt class="typeDefinition"><a name="type_ExistingImports">ExistingImports: object</a></dt><dd>
+ <p>
+ Information about all existing imports in a library.
+ </p>
+
+ <dl><dt class="field"><b>elements: <a href="#type_ImportedElementSet">ImportedElementSet</a></b></dt><dd>
+
+ <p>
+ The set of all unique imported elements for all imports.
+ </p>
+ </dd><dt class="field"><b>imports: List<<a href="#type_ExistingImport">ExistingImport</a>></b></dt><dd>
+
+ <p>
+ The list of imports in the library.
+ </p>
+ </dd></dl></dd><dt class="typeDefinition"><a name="type_FileKind">FileKind: String</a></dt><dd>
<p>
An enumeration of the kinds of files.
</p>
@@ -3851,10 +3926,10 @@
</dd><dt class="field"><b>containingLibraryName: String<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
- The name of the library in which the referenced element is
- declared. This data is omitted if there is no referenced
- element, or if the element is declared inside an HTML
- file.
+ The URI of the containing library, examples here include
+ "dart:core", "package:.." and file uris represented by the
+ path on disk, "/..". The data is omitted if the element is
+ declared inside an HTML file.
</p>
</dd><dt class="field"><b>containingClassDescription: String<span style="color:#999999"> (optional)</span></b></dt><dd>
@@ -3945,6 +4020,30 @@
<p>
The length of the name of the implemented member.
</p>
+ </dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElementSet">ImportedElementSet: object</a></dt><dd>
+ <p>
+ The set of top-level elements encoded as pairs of the defining library
+ URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+ and <tt>elementNames</tt>.
+ </p>
+
+ <dl><dt class="field"><b>strings: List<String></b></dt><dd>
+
+ <p>
+ The list of unique strings in this object.
+ </p>
+ </dd><dt class="field"><b>uris: List<int></b></dt><dd>
+
+ <p>
+ The library URI part of the element.
+ It is an index in the <tt>strings</tt> field.
+ </p>
+ </dd><dt class="field"><b>names: List<int></b></dt><dd>
+
+ <p>
+ The name part of a the element.
+ It is an index in the <tt>strings</tt> field.
+ </p>
</dd></dl></dd><dt class="typeDefinition"><a name="type_ImportedElements">ImportedElements: object</a></dt><dd>
<p>
A description of the elements that are referenced in a region of a file
@@ -5430,7 +5529,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></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.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></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.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><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_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</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_FileKind">FileKind</a></li><li><a href="#type_FilePath">FilePath</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_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></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.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.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><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_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</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_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/lsp_protocol/protocol_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
index 8ae18ae..de7720a2 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_generated.dart
@@ -8415,7 +8415,9 @@
}
static TextDocumentChangeRegistrationOptions fromJson(
Map<String, dynamic> json) {
- final syncKind = json['syncKind'];
+ final syncKind = json['syncKind'] != null
+ ? TextDocumentSyncKind.fromJson(json['syncKind'])
+ : null;
final documentSelector = json['documentSelector']
?.map((item) => item != null ? DocumentFilter.fromJson(item) : null)
?.cast<DocumentFilter>()
@@ -8430,7 +8432,7 @@
/// How documents are synced to the server. See TextDocumentSyncKind.Full and
/// TextDocumentSyncKind.Incremental.
- final num syncKind;
+ final TextDocumentSyncKind syncKind;
Map<String, dynamic> toJson() {
Map<String, dynamic> __result = {};
@@ -8443,7 +8445,7 @@
static bool canParse(Object obj) {
return obj is Map<String, dynamic> &&
obj.containsKey('syncKind') &&
- obj['syncKind'] is num &&
+ TextDocumentSyncKind.canParse(obj['syncKind']) &&
obj.containsKey('documentSelector') &&
(obj['documentSelector'] == null ||
(obj['documentSelector'] is List &&
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
index 7093987..ca304eb 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
@@ -8,6 +8,17 @@
const jsonRpcVersion = '2.0';
+const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
+
+ErrorOr<R> cancelled<R>([R t]) =>
+ error(ErrorCodes.RequestCancelled, 'Request was cancelled', null);
+
+ErrorOr<R> error<R>(ErrorCodes code, String message, [String data]) =>
+ new ErrorOr<R>.error(new ResponseError(code, message, data));
+
+ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
+ new ErrorOr<R>.error(error.error);
+
Object specToJson(Object obj) {
if (obj is ToJsonable) {
return obj.toJson();
@@ -16,6 +27,12 @@
}
}
+ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
+
+Null _alwaysNull(_) => null;
+
+bool _alwaysTrue(_) => true;
+
class Either2<T1, T2> {
final int _which;
final T1 _t1;
@@ -39,6 +56,9 @@
Object toJson() => map(specToJson, specToJson);
+ @override
+ String toString() => map((t) => t.toString(), (t) => t.toString());
+
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) => map((t) => t == o, (t) => t == o);
}
@@ -83,6 +103,13 @@
Object toJson() => map(specToJson, specToJson, specToJson);
+ @override
+ String toString() => map(
+ (t) => t.toString(),
+ (t) => t.toString(),
+ (t) => t.toString(),
+ );
+
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) => map((t) => t == o, (t) => t == o, (t) => t == o);
}
@@ -144,6 +171,14 @@
Object toJson() => map(specToJson, specToJson, specToJson, specToJson);
+ @override
+ String toString() => map(
+ (t) => t.toString(),
+ (t) => t.toString(),
+ (t) => t.toString(),
+ (t) => t.toString(),
+ );
+
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) =>
map((t) => t == o, (t) => t == o, (t) => t == o, (t) => t == o);
@@ -198,10 +233,6 @@
const LspJsonHandler(this.validateParams, this.convertParams);
}
-bool _alwaysTrue(_) => true;
-Null _alwaysNull(_) => null;
-const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
-
abstract class ToJsonable {
Object toJson();
}
diff --git a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
index fb3c5ec..499c925 100644
--- a/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
+++ b/pkg/analysis_server/lib/plugin/edit/fix/fix_dart.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -21,4 +22,10 @@
* The workspace in which the fix contributor operates.
*/
ChangeWorkspace get workspace;
+
+ /**
+ * Return top-level declarations with the [name] in libraries that are
+ * available to this context.
+ */
+ List<TopLevelDeclaration> getTopLevelDeclarations(String name);
}
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index af958c9..b944f0f 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.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
'changedLibraries';
const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+ 'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
'includedSuggestionSets';
const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
'replacementLength';
const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 6e7da59..fbaaf97 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
}
/**
+ * completion.existingImports params
+ *
+ * {
+ * "file": FilePath
+ * "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+ String _file;
+
+ ExistingImports _imports;
+
+ /**
+ * The defining file of the library.
+ */
+ String get file => _file;
+
+ /**
+ * The defining file of the library.
+ */
+ void set file(String value) {
+ assert(value != null);
+ this._file = value;
+ }
+
+ /**
+ * The existing imports in the library.
+ */
+ ExistingImports get imports => _imports;
+
+ /**
+ * The existing imports in the library.
+ */
+ void set imports(ExistingImports value) {
+ assert(value != null);
+ this._imports = value;
+ }
+
+ CompletionExistingImportsParams(String file, ExistingImports imports) {
+ this.file = file;
+ this.imports = imports;
+ }
+
+ factory CompletionExistingImportsParams.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ String file;
+ if (json.containsKey("file")) {
+ file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "file");
+ }
+ ExistingImports imports;
+ if (json.containsKey("imports")) {
+ imports = new ExistingImports.fromJson(
+ jsonDecoder, jsonPath + ".imports", json["imports"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "imports");
+ }
+ return new CompletionExistingImportsParams(file, imports);
+ } else {
+ throw jsonDecoder.mismatch(
+ jsonPath, "completion.existingImports params", json);
+ }
+ }
+
+ factory CompletionExistingImportsParams.fromNotification(
+ Notification notification) {
+ return new CompletionExistingImportsParams.fromJson(
+ new ResponseDecoder(null), "params", notification.params);
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["file"] = file;
+ result["imports"] = imports.toJson();
+ return result;
+ }
+
+ Notification toNotification() {
+ return new Notification("completion.existingImports", toJson());
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is CompletionExistingImportsParams) {
+ return file == other.file && imports == other.imports;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, file.hashCode);
+ hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* completion.getSuggestionDetails params
*
* {
@@ -6593,6 +6703,7 @@
* "replacementLength": int
* "results": List<CompletionSuggestion>
* "isLast": bool
+ * "libraryFile": optional FilePath
* "includedSuggestionSets": optional List<IncludedSuggestionSet>
* "includedElementKinds": optional List<ElementKind>
* "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
bool _isLast;
+ String _libraryFile;
+
List<IncludedSuggestionSet> _includedSuggestionSets;
List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
}
/**
+ * The library file that contains the file where completion was requested.
+ * The client might use it for example together with the existingImports
+ * notification to filter out available suggestions. If there were changes to
+ * existing imports in the library, the corresponding existingImports
+ * notification will be sent before the completion notification.
+ */
+ String get libraryFile => _libraryFile;
+
+ /**
+ * The library file that contains the file where completion was requested.
+ * The client might use it for example together with the existingImports
+ * notification to filter out available suggestions. If there were changes to
+ * existing imports in the library, the corresponding existingImports
+ * notification will be sent before the completion notification.
+ */
+ void set libraryFile(String value) {
+ this._libraryFile = value;
+ }
+
+ /**
* References to AvailableSuggestionSet objects previously sent to the
* client. The client can include applicable names from the referenced
* library in code completion suggestions.
@@ -6765,7 +6898,8 @@
CompletionResultsParams(String id, int replacementOffset,
int replacementLength, List<CompletionSuggestion> results, bool isLast,
- {List<IncludedSuggestionSet> includedSuggestionSets,
+ {String libraryFile,
+ List<IncludedSuggestionSet> includedSuggestionSets,
List<ElementKind> includedElementKinds,
List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
this.id = id;
@@ -6773,6 +6907,7 @@
this.replacementLength = replacementLength;
this.results = results;
this.isLast = isLast;
+ this.libraryFile = libraryFile;
this.includedSuggestionSets = includedSuggestionSets;
this.includedElementKinds = includedElementKinds;
this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
} else {
throw jsonDecoder.mismatch(jsonPath, "isLast");
}
+ String libraryFile;
+ if (json.containsKey("libraryFile")) {
+ libraryFile = jsonDecoder.decodeString(
+ jsonPath + ".libraryFile", json["libraryFile"]);
+ }
List<IncludedSuggestionSet> includedSuggestionSets;
if (json.containsKey("includedSuggestionSets")) {
includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
}
return new CompletionResultsParams(
id, replacementOffset, replacementLength, results, isLast,
+ libraryFile: libraryFile,
includedSuggestionSets: includedSuggestionSets,
includedElementKinds: includedElementKinds,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
result["results"] =
results.map((CompletionSuggestion value) => value.toJson()).toList();
result["isLast"] = isLast;
+ if (libraryFile != null) {
+ result["libraryFile"] = libraryFile;
+ }
if (includedSuggestionSets != null) {
result["includedSuggestionSets"] = includedSuggestionSets
.map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
listEqual(results, other.results,
(CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
isLast == other.isLast &&
+ libraryFile == other.libraryFile &&
listEqual(includedSuggestionSets, other.includedSuggestionSets,
(IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
hash = JenkinsSmiHash.combine(hash, results.hashCode);
hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+ hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
hash =
@@ -6946,11 +7092,13 @@
*/
class CompletionService implements Enum {
/**
- * The client will receive notifications once subscribed with completion
- * suggestion sets from the libraries of interest. The client should keep an
- * up-to-date record of these in memory so that it will be able to union
- * these candidates with other completion suggestions when applicable at
- * completion time.
+ * The client will receive availableSuggestions notifications once subscribed
+ * with completion suggestion sets from the libraries of interest. The client
+ * should keep an up-to-date record of these in memory so that it will be
+ * able to union these candidates with other completion suggestions when
+ * applicable at completion time.
+ *
+ * The client will also receive existingImports notifications.
*/
static const CompletionService AVAILABLE_SUGGESTION_SETS =
const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -13011,6 +13159,214 @@
}
/**
+ * ExistingImport
+ *
+ * {
+ * "uri": int
+ * "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+ int _uri;
+
+ List<int> _elements;
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in
+ * the enclosing ExistingImports and its ImportedElementSet object.
+ */
+ int get uri => _uri;
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in
+ * the enclosing ExistingImports and its ImportedElementSet object.
+ */
+ void set uri(int value) {
+ assert(value != null);
+ this._uri = value;
+ }
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ List<int> get elements => _elements;
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ void set elements(List<int> value) {
+ assert(value != null);
+ this._elements = value;
+ }
+
+ ExistingImport(int uri, List<int> elements) {
+ this.uri = uri;
+ this.elements = elements;
+ }
+
+ factory ExistingImport.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ int uri;
+ if (json.containsKey("uri")) {
+ uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "uri");
+ }
+ List<int> elements;
+ if (json.containsKey("elements")) {
+ elements = jsonDecoder.decodeList(
+ jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "elements");
+ }
+ return new ExistingImport(uri, elements);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["uri"] = uri;
+ result["elements"] = elements;
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExistingImport) {
+ return uri == other.uri &&
+ listEqual(elements, other.elements, (int a, int b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+ hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ * "elements": ImportedElementSet
+ * "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+ ImportedElementSet _elements;
+
+ List<ExistingImport> _imports;
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ ImportedElementSet get elements => _elements;
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ void set elements(ImportedElementSet value) {
+ assert(value != null);
+ this._elements = value;
+ }
+
+ /**
+ * The list of imports in the library.
+ */
+ List<ExistingImport> get imports => _imports;
+
+ /**
+ * The list of imports in the library.
+ */
+ void set imports(List<ExistingImport> value) {
+ assert(value != null);
+ this._imports = value;
+ }
+
+ ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+ this.elements = elements;
+ this.imports = imports;
+ }
+
+ factory ExistingImports.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ ImportedElementSet elements;
+ if (json.containsKey("elements")) {
+ elements = new ImportedElementSet.fromJson(
+ jsonDecoder, jsonPath + ".elements", json["elements"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "elements");
+ }
+ List<ExistingImport> imports;
+ if (json.containsKey("imports")) {
+ imports = jsonDecoder.decodeList(
+ jsonPath + ".imports",
+ json["imports"],
+ (String jsonPath, Object json) =>
+ new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "imports");
+ }
+ return new ExistingImports(elements, imports);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["elements"] = elements.toJson();
+ result["imports"] =
+ imports.map((ExistingImport value) => value.toJson()).toList();
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExistingImports) {
+ return elements == other.elements &&
+ listEqual(imports, other.imports,
+ (ExistingImport a, ExistingImport b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+ hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* extractLocalVariable feedback
*
* {
@@ -15586,16 +15942,16 @@
}
/**
- * The name of the library in which the referenced element is declared. This
- * data is omitted if there is no referenced element, or if the element is
- * declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core",
+ * "package:.." and file uris represented by the path on disk, "/..". The
+ * data is omitted if the element is declared inside an HTML file.
*/
String get containingLibraryName => _containingLibraryName;
/**
- * The name of the library in which the referenced element is declared. This
- * data is omitted if there is no referenced element, or if the element is
- * declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core",
+ * "package:.." and file uris represented by the path on disk, "/..". The
+ * data is omitted if the element is declared inside an HTML file.
*/
void set containingLibraryName(String value) {
this._containingLibraryName = value;
@@ -16109,6 +16465,135 @@
}
/**
+ * ImportedElementSet
+ *
+ * {
+ * "strings": List<String>
+ * "uris": List<int>
+ * "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+ List<String> _strings;
+
+ List<int> _uris;
+
+ List<int> _names;
+
+ /**
+ * The list of unique strings in this object.
+ */
+ List<String> get strings => _strings;
+
+ /**
+ * The list of unique strings in this object.
+ */
+ void set strings(List<String> value) {
+ assert(value != null);
+ this._strings = value;
+ }
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ List<int> get uris => _uris;
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ void set uris(List<int> value) {
+ assert(value != null);
+ this._uris = value;
+ }
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ List<int> get names => _names;
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ void set names(List<int> value) {
+ assert(value != null);
+ this._names = value;
+ }
+
+ ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+ this.strings = strings;
+ this.uris = uris;
+ this.names = names;
+ }
+
+ factory ImportedElementSet.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ List<String> strings;
+ if (json.containsKey("strings")) {
+ strings = jsonDecoder.decodeList(
+ jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "strings");
+ }
+ List<int> uris;
+ if (json.containsKey("uris")) {
+ uris = jsonDecoder.decodeList(
+ jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "uris");
+ }
+ List<int> names;
+ if (json.containsKey("names")) {
+ names = jsonDecoder.decodeList(
+ jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "names");
+ }
+ return new ImportedElementSet(strings, uris, names);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["strings"] = strings;
+ result["uris"] = uris;
+ result["names"] = names;
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ImportedElementSet) {
+ return listEqual(
+ strings, other.strings, (String a, String b) => a == b) &&
+ listEqual(uris, other.uris, (int a, int b) => a == b) &&
+ listEqual(names, other.names, (int a, int b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+ hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+ hash = JenkinsSmiHash.combine(hash, names.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* ImportedElements
*
* {
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index ca242a8..587adc4 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -42,6 +42,7 @@
import 'package:analysis_server/src/search/search_domain.dart';
import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
import 'package:analysis_server/src/utilities/null_string_sink.dart';
@@ -206,10 +207,12 @@
analysisDriverScheduler.status.listen(sendStatusNotificationNew);
analysisDriverScheduler.start();
- declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
- declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
- analysisDriverScheduler.outOfBandWorker =
- CompletionLibrariesWorker(declarationsTracker);
+ if (options.featureSet.completion) {
+ declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+ declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+ analysisDriverScheduler.outOfBandWorker =
+ CompletionLibrariesWorker(declarationsTracker);
+ }
contextManager = new ContextManagerImpl(
resourceProvider,
@@ -485,7 +488,7 @@
/// projects/contexts support.
void setAnalysisRoots(String requestId, List<String> includedPaths,
List<String> excludedPaths, Map<String, String> packageRoots) {
- declarationsTracker.discardContexts();
+ declarationsTracker?.discardContexts();
if (notificationManager != null) {
notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
}
@@ -739,6 +742,9 @@
/// Whether to enable parsing via the Fasta parser.
bool useFastaParser = true;
+
+ /// The set of enabled features.
+ FeatureSet featureSet = FeatureSet();
}
class ServerContextManagerCallbacks extends ContextManagerCallbacks {
@@ -886,6 +892,11 @@
}
@override
+ void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+ analysisServer.updateContextInDeclarationsTracker(driver);
+ }
+
+ @override
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
if (analysisDriver != null) {
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index c56a762..d1aa497d 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -136,7 +136,7 @@
void addContextsToDeclarationsTracker() {
for (var driver in driverMap.values) {
- declarationsTracker.addContext(driver.analysisContext);
+ declarationsTracker?.addContext(driver.analysisContext);
driver.resetUriResolution();
}
}
@@ -189,7 +189,7 @@
DartdocDirectiveInfo getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
return declarationsTracker
- .getContext(result.session.analysisContext)
+ ?.getContext(result.session.analysisContext)
?.dartdocDirectiveInfo ??
new DartdocDirectiveInfo();
}
@@ -288,7 +288,12 @@
/// Notify the declarations tracker that the file with the given [path] was
/// changed - added, updated, or removed. Schedule processing of the file.
void notifyDeclarationsTracker(String path) {
- declarationsTracker.changeFile(path);
+ declarationsTracker?.changeFile(path);
analysisDriverScheduler.notify(null);
}
+
+ void updateContextInDeclarationsTracker(nd.AnalysisDriver driver) {
+ declarationsTracker?.discardContext(driver.analysisContext);
+ declarationsTracker?.addContext(driver.analysisContext);
+ }
}
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index 1dd0b83..c4e1f34 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -72,7 +72,15 @@
// containing library
LibraryElement library = element.library;
if (library != null) {
- hover.containingLibraryName = library.name;
+ Uri uri = library.source.uri;
+ if (uri.scheme != '' && uri.scheme == 'file') {
+ // for 'file:' URIs, use the path (contents after 'file:///')
+ hover.containingLibraryName = _unit
+ .declaredElement.session.resourceProvider.pathContext
+ .fromUri(uri);
+ } else {
+ hover.containingLibraryName = uri.toString();
+ }
hover.containingLibraryPath = library.source.fullName;
}
}
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index fa1d36f..dfb5db4 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -355,6 +355,11 @@
void afterWatchEvent(WatchEvent event);
/**
+ * Called when analysis options or URI resolution in the [driver] are changed.
+ */
+ void analysisOptionsUpdated(AnalysisDriver driver);
+
+ /**
* Called when the set of files associated with a context have changed (or
* some of those files have been modified). [changeSet] is the set of
* changes that need to be applied to the context.
@@ -1630,6 +1635,7 @@
contextRoot: driver.contextRoot);
SourceFactory factory = builder.createSourceFactory(contextRoot, options);
driver.configure(analysisOptions: options, sourceFactory: factory);
+ callbacks.analysisOptionsUpdated(driver);
}
void _updateContextPackageUriResolver(Folder contextFolder) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 26461fc..4f91833 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -264,6 +264,14 @@
@override
Response handleRequest(Request request) {
+ if (!server.options.featureSet.completion) {
+ return Response.invalidParameter(
+ request,
+ 'request',
+ 'The completion feature is not enabled',
+ );
+ }
+
return runZoned(() {
String requestName = request.method;
@@ -335,8 +343,6 @@
* Process a `completion.getSuggestions` request.
*/
Future<void> processRequest(Request request) async {
- // TODO(brianwilkerson) Determine whether this await is necessary.
- await null;
performance = new CompletionPerformance();
// extract and validate params
@@ -389,8 +395,13 @@
includedElementKinds,
includedSuggestionRelevanceTags,
).then((CompletionResult result) {
+ String libraryFile;
List<IncludedSuggestionSet> includedSuggestionSets;
if (includedElementKinds != null && resolvedUnit != null) {
+ libraryFile = resolvedUnit.libraryElement.source.fullName;
+ server.sendNotification(
+ createExistingImportsNotification(resolvedUnit),
+ );
includedSuggestionSets = computeIncludedSetList(
server.declarationsTracker,
resolvedUnit,
@@ -406,6 +417,7 @@
result.replacementOffset,
result.replacementLength,
result.suggestions,
+ libraryFile,
includedSuggestionSets,
includedElementKinds?.toList(),
includedSuggestionRelevanceTags,
@@ -444,6 +456,7 @@
int replacementOffset,
int replacementLength,
Iterable<CompletionSuggestion> results,
+ String libraryFile,
List<IncludedSuggestionSet> includedSuggestionSets,
List<ElementKind> includedElementKinds,
List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
@@ -455,6 +468,7 @@
replacementLength,
results,
true,
+ libraryFile: libraryFile,
includedSuggestionSets: includedSuggestionSets,
includedElementKinds: includedElementKinds,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
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 ce8b297..305907c 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -4,7 +4,9 @@
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/src/services/available_declarations.dart';
/// Compute which suggestion sets should be included into completion inside
@@ -79,6 +81,81 @@
).toNotification();
}
+/// Compute existing imports and elements that they provide.
+protocol.Notification createExistingImportsNotification(
+ ResolvedUnitResult resolvedUnit,
+) {
+ var uniqueStrings = _UniqueImportedStrings();
+ var uniqueElements = _UniqueImportedElements();
+ var existingImports = <protocol.ExistingImport>[];
+
+ var importElementList = resolvedUnit.libraryElement.imports;
+ for (var import in importElementList) {
+ var importedLibrary = import.importedLibrary;
+ if (importedLibrary == null) continue;
+
+ var importedUriStr = '${importedLibrary.librarySource.uri}';
+
+ var existingImportElements = <int>[];
+ for (var element in import.namespace.definedNames.values) {
+ if (element.librarySource != null) {
+ var index = uniqueElements.indexOf(uniqueStrings, element);
+ existingImportElements.add(index);
+ }
+ }
+
+ existingImports.add(protocol.ExistingImport(
+ uniqueStrings.indexOf(importedUriStr),
+ existingImportElements,
+ ));
+ }
+
+ return protocol.CompletionExistingImportsParams(
+ resolvedUnit.libraryElement.source.fullName,
+ protocol.ExistingImports(
+ protocol.ImportedElementSet(
+ uniqueStrings.values,
+ uniqueElements.uriList,
+ uniqueElements.nameList,
+ ),
+ existingImports,
+ ),
+ ).toNotification();
+}
+
+/// TODO(dantup): We need to expose this because the Declarations code currently
+/// returns declarations with DeclarationKinds but the DartCompletionManager
+/// gives us a list of "included ElementKinds". Maybe it would be better to expose
+/// includedDeclarationKinds and then just map that list to ElementKinds once in
+/// domain_completion for the original protocol?
+protocol.ElementKind protocolElementKind(DeclarationKind kind) {
+ switch (kind) {
+ case DeclarationKind.CLASS:
+ return protocol.ElementKind.CLASS;
+ case DeclarationKind.CLASS_TYPE_ALIAS:
+ return protocol.ElementKind.CLASS_TYPE_ALIAS;
+ case DeclarationKind.CONSTRUCTOR:
+ return protocol.ElementKind.CONSTRUCTOR;
+ case DeclarationKind.ENUM:
+ return protocol.ElementKind.ENUM;
+ case DeclarationKind.ENUM_CONSTANT:
+ return protocol.ElementKind.ENUM_CONSTANT;
+ case DeclarationKind.FUNCTION:
+ return protocol.ElementKind.FUNCTION;
+ case DeclarationKind.FUNCTION_TYPE_ALIAS:
+ return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+ case DeclarationKind.GETTER:
+ return protocol.ElementKind.GETTER;
+ case DeclarationKind.MIXIN:
+ return protocol.ElementKind.MIXIN;
+ case DeclarationKind.SETTER:
+ return protocol.ElementKind.SETTER;
+ case DeclarationKind.VARIABLE:
+ return protocol.ElementKind.TOP_LEVEL_VARIABLE;
+ }
+ return protocol.ElementKind.UNKNOWN;
+}
+
/// Computes the best URI to import [what] into the [unit] library.
String _getRelativeFileUri(ResolvedUnitResult unit, Uri what) {
if (what.scheme == 'file') {
@@ -173,39 +250,6 @@
);
}
-// TODO(dantup): We need to expose this because the Declarations code currently
-// returns declarations with DeclarationKinds but the DartCompletionManager
-// gives us a list of "included ElementKinds". Maybe it would be better to expose
-// includedDeclarationKinds and then just map that list to ElementKinds once in
-// domain_completion for the original protocol?
-protocol.ElementKind protocolElementKind(DeclarationKind kind) {
- switch (kind) {
- case DeclarationKind.CLASS:
- return protocol.ElementKind.CLASS;
- case DeclarationKind.CLASS_TYPE_ALIAS:
- return protocol.ElementKind.CLASS_TYPE_ALIAS;
- case DeclarationKind.CONSTRUCTOR:
- return protocol.ElementKind.CONSTRUCTOR;
- case DeclarationKind.ENUM:
- return protocol.ElementKind.ENUM;
- case DeclarationKind.ENUM_CONSTANT:
- return protocol.ElementKind.ENUM_CONSTANT;
- case DeclarationKind.FUNCTION:
- return protocol.ElementKind.FUNCTION;
- case DeclarationKind.FUNCTION_TYPE_ALIAS:
- return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
- case DeclarationKind.GETTER:
- return protocol.ElementKind.GETTER;
- case DeclarationKind.MIXIN:
- return protocol.ElementKind.MIXIN;
- case DeclarationKind.SETTER:
- return protocol.ElementKind.SETTER;
- case DeclarationKind.VARIABLE:
- return protocol.ElementKind.TOP_LEVEL_VARIABLE;
- }
- return protocol.ElementKind.UNKNOWN;
-}
-
class CompletionLibrariesWorker implements SchedulerWorker {
final DeclarationsTracker tracker;
@@ -277,3 +321,56 @@
_listener = null;
}
}
+
+class _ImportedElement {
+ final int uri;
+ final int name;
+
+ @override
+ final int hashCode;
+
+ _ImportedElement(this.uri, this.name)
+ : hashCode = JenkinsSmiHash.hash2(uri, name);
+
+ @override
+ bool operator ==(other) {
+ return other is _ImportedElement && other.uri == uri && other.name == name;
+ }
+}
+
+class _UniqueImportedElements {
+ final map = <_ImportedElement, int>{};
+
+ List<int> get nameList => map.keys.map((e) => e.name).toList();
+
+ List<int> get uriList => map.keys.map((e) => e.uri).toList();
+
+ int indexOf(_UniqueImportedStrings strings, Element element) {
+ var uriStr = '${element.librarySource.uri}';
+ var wrapper = _ImportedElement(
+ strings.indexOf(uriStr),
+ strings.indexOf(element.name),
+ );
+ var index = map[wrapper];
+ if (index == null) {
+ index = map.length;
+ map[wrapper] = index;
+ }
+ return index;
+ }
+}
+
+class _UniqueImportedStrings {
+ final map = <String, int>{};
+
+ List<String> get values => map.keys.toList();
+
+ int indexOf(String str) {
+ var index = map[str];
+ if (index == null) {
+ index = map.length;
+ map[str] = index;
+ }
+ return index;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 99a39bd..5941656 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -23,6 +23,7 @@
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
import 'package:analysis_server/src/services/correction/fix/analysis_options/fix_generator.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/fix/manifest/fix_generator.dart';
import 'package:analysis_server/src/services/correction/fix/pubspec/fix_generator.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
@@ -634,7 +635,16 @@
int errorLine = lineInfo.getLocation(error.offset).lineNumber;
if (errorLine == requestLine) {
var workspace = DartChangeWorkspace(server.currentSessions);
- var context = new DartFixContextImpl(workspace, result, error);
+ var context =
+ new DartFixContextImpl(workspace, result, error, (name) {
+ var tracker = server.declarationsTracker;
+ var provider = TopLevelDeclarationsProvider(tracker);
+ return provider.get(
+ result.session.analysisContext,
+ result.path,
+ name,
+ );
+ });
List<Fix> fixes =
await new DartFixContributor().computeFixes(context);
if (fixes.isNotEmpty) {
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
index e71fd1d..378b3b1 100644
--- a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
@@ -28,7 +28,12 @@
Future<void> fixError(ResolvedUnitResult result, AnalysisError error) async {
final workspace = DartChangeWorkspace(listener.server.currentSessions);
- final dartContext = new DartFixContextImpl(workspace, result, error);
+ final dartContext = new DartFixContextImpl(
+ workspace,
+ result,
+ error,
+ (name) => [],
+ );
final processor = new FixProcessor(dartContext);
Fix fix = await processor.computeFix();
final location = listener.locationFor(result, error.offset, error.length);
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index 61d3984..62161e4 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -105,6 +105,7 @@
content = '''
- non-nullable''';
+ return null;
},
);
}
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index 277658d..6330e82 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -63,7 +63,20 @@
var flutterDartOutline = _convert(dartOutline);
// Create outlines for widgets.
- resolvedUnit.unit.accept(new _FlutterOutlineBuilder(this));
+ var visitor = new _FlutterOutlineBuilder(this);
+ resolvedUnit.unit.accept(visitor);
+
+ // Associate Flutter outlines with Dart outlines.
+ for (var outline in visitor.outlines) {
+ for (var parent in _depthFirstOrder) {
+ if (parent.offset < outline.offset &&
+ outline.offset + outline.length < parent.offset + parent.length) {
+ parent.children ??= <protocol.FlutterOutline>[];
+ parent.children.add(outline);
+ break;
+ }
+ }
+ }
// Compute instrumented code.
if (widgets.values.any((w) => w.hasDesignTimeConstructor)) {
@@ -224,8 +237,14 @@
}
}
} else {
- ParameterElement parameter = argument.staticParameterElement;
- _addAttribute(attributes, argument, parameter);
+ var visitor = _FlutterOutlineBuilder(this);
+ argument.accept(visitor);
+ if (visitor.outlines.isNotEmpty) {
+ children.addAll(visitor.outlines);
+ } else {
+ ParameterElement parameter = argument.staticParameterElement;
+ _addAttribute(attributes, argument, parameter);
+ }
}
}
@@ -385,6 +404,7 @@
class _FlutterOutlineBuilder extends GeneralizingAstVisitor<void> {
final FlutterOutlineComputer computer;
+ final List<protocol.FlutterOutline> outlines = [];
_FlutterOutlineBuilder(this.computer);
@@ -392,14 +412,7 @@
void visitExpression(Expression node) {
var outline = computer._createOutline(node, false);
if (outline != null) {
- for (var parent in computer._depthFirstOrder) {
- if (parent.offset < outline.offset &&
- outline.offset + outline.length < parent.offset + parent.length) {
- parent.children ??= <protocol.FlutterOutline>[];
- parent.children.add(outline);
- return;
- }
- }
+ outlines.add(outline);
} else {
super.visitExpression(node);
}
diff --git a/pkg/analysis_server/lib/src/lsp/constants.dart b/pkg/analysis_server/lib/src/lsp/constants.dart
index 904feeb..54b1805 100644
--- a/pkg/analysis_server/lib/src/lsp/constants.dart
+++ b/pkg/analysis_server/lib/src/lsp/constants.dart
@@ -4,6 +4,36 @@
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+/// Set the characters that will cause the editor to automatically
+/// trigger completion.
+/// TODO(dantup): There are several characters that we want to conditionally
+/// allow to trigger completion, but they can only be added when the completion
+/// provider is able to handle them in context:
+///
+/// { trigger if being typed in a string immediately after a $
+/// ' trigger if the opening quote for an import/export
+/// " trigger if the opening quote for an import/export
+/// / trigger if as part of a path in an import/export
+/// \ trigger if as part of a path in an import/export
+/// : don't trigger when typing case expressions (`case x:`)
+///
+/// Additionally, we need to prefix `filterText` on completion items
+/// with spaces for those that can follow whitespace (eg. `foo` in
+/// `myArg: foo`) to ensure they're not filtered away when the user
+/// types space.
+///
+/// See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
+/// for the VS Code implementation of this.
+const dartCompletionTriggerCharacters = ['.', '=', '(', r'$'];
+
+/// TODO(dantup): Signature help triggering is even more sensitive to
+/// bad chars, so we'll need to implement the logic described here:
+/// https://github.com/dart-lang/sdk/issues/34241
+const dartSignatureHelpTriggerCharacters = <String>[];
+
+/// Characters to trigger formatting when format-on-type is enabled.
+const dartTypeFormattingCharacters = ['}', ';'];
+
/// Constants for command IDs that are exchanged between LSP client/server.
abstract class Commands {
/// A list of all commands IDs that can be sent to the client to inform which
@@ -19,6 +49,11 @@
static const sendWorkspaceEdit = 'edit.sendWorkspaceEdit';
}
+abstract class CustomMethods {
+ static const DiagnosticServer = const Method('dart/diagnosticServer');
+ static const AnalyzerStatus = const Method(r'$/analyzerStatus');
+}
+
/// CodeActionKinds supported by the server that are not declared in the LSP spec.
abstract class DartCodeActionKind {
/// A list of all supported CodeAction kinds, supplied to the client during
@@ -61,8 +96,3 @@
/// if it crashes 5 times in the last 180 seconds."
static const ClientServerInconsistentState = const ErrorCodes(-32010);
}
-
-abstract class CustomMethods {
- static const DiagnosticServer = const Method('dart/diagnosticServer');
- static const AnalyzerStatus = const Method(r'$/analyzerStatus');
-}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
index 5d75dde..e4f255e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/custom/handler_diagnostic_server.dart
@@ -20,7 +20,8 @@
LspJsonHandler<void> get jsonHandler => NullJsonHandler;
@override
- Future<ErrorOr<DartDiagnosticServer>> handle(void _) async {
+ Future<ErrorOr<DartDiagnosticServer>> handle(
+ void _, CancellationToken token) async {
final port = await server.diagnosticServer.getServerPort();
return success(new DartDiagnosticServer(port));
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
new file mode 100644
index 0000000..c21782c
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_cancel_request.dart
@@ -0,0 +1,37 @@
+// 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/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+
+class CancelRequestHandler extends MessageHandler<CancelParams, void> {
+ Map<String, CancelableToken> _tokens = {};
+
+ CancelRequestHandler(LspAnalysisServer server) : super(server);
+
+ Method get handlesMessage => Method.cancelRequest;
+
+ @override
+ LspJsonHandler<CancelParams> get jsonHandler => CancelParams.jsonHandler;
+
+ void clearToken(RequestMessage message) {
+ _tokens.remove(message.id.toString());
+ }
+
+ CancelableToken createToken(RequestMessage message) {
+ final token = new CancelableToken();
+ _tokens[message.id.toString()] = token;
+ return token;
+ }
+
+ ErrorOr<void> handle(CancelParams params, CancellationToken token) {
+ // Don't assume this is in the map as it's possible the client sent a
+ // cancellation that we processed after already starting to send the response
+ // and cleared the token.
+ _tokens[params.id.toString()]?.cancel();
+ return success();
+ }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index c43057f..c518c93 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -21,7 +21,8 @@
LspJsonHandler<DidChangeWorkspaceFoldersParams> get jsonHandler =>
DidChangeWorkspaceFoldersParams.jsonHandler;
- ErrorOr<void> handle(DidChangeWorkspaceFoldersParams params) {
+ ErrorOr<void> handle(
+ DidChangeWorkspaceFoldersParams params, CancellationToken token) {
// Don't do anything if our analysis roots are not based on open workspaces.
if (!updateAnalysisRoots) {
return success();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index b7b5f72..326b25a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -17,6 +17,7 @@
import 'package:analysis_server/src/services/correction/assist_internal.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart'
@@ -33,13 +34,16 @@
CodeActionParams.jsonHandler;
Future<ErrorOr<List<Either2<Command, CodeAction>>>> handle(
- CodeActionParams params) async {
+ CodeActionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
final capabilities = server?.clientCapabilities?.textDocument?.codeAction;
+ final clientSupportsWorkspaceApplyEdit =
+ server?.clientCapabilities?.workspace?.applyEdit == true;
+
final clientSupportsLiteralCodeActions =
capabilities?.codeActionLiteralSupport != null;
@@ -59,6 +63,7 @@
return _getCodeActions(
clientSupportedCodeActionKinds,
clientSupportsLiteralCodeActions,
+ clientSupportsWorkspaceApplyEdit,
path.result,
params.range,
offset,
@@ -148,6 +153,7 @@
Future<ErrorOr<List<Either2<Command, CodeAction>>>> _getCodeActions(
HashSet<CodeActionKind> kinds,
bool supportsLiterals,
+ bool supportsWorkspaceApplyEdit,
String path,
Range range,
int offset,
@@ -155,7 +161,8 @@
ResolvedUnitResult unit,
) async {
final results = await Future.wait([
- _getSourceActions(kinds, supportsLiterals, path),
+ _getSourceActions(
+ kinds, supportsLiterals, supportsWorkspaceApplyEdit, path),
_getAssistActions(kinds, supportsLiterals, offset, length, unit),
_getRefactorActions(kinds, supportsLiterals, path, range, unit),
_getFixActions(kinds, supportsLiterals, range, unit),
@@ -186,7 +193,14 @@
int errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
if (errorLine >= range.start.line && errorLine <= range.end.line) {
var workspace = DartChangeWorkspace(server.currentSessions);
- var context = new DartFixContextImpl(workspace, unit, error);
+ var context = new DartFixContextImpl(workspace, unit, error, (name) {
+ var tracker = server.declarationsTracker;
+ return TopLevelDeclarationsProvider(tracker).get(
+ unit.session.analysisContext,
+ unit.path,
+ name,
+ );
+ });
final fixes = await fixContributor.computeFixes(context);
if (fixes.isNotEmpty) {
fixes.sort(Fix.SORT_BY_RELEVANCE);
@@ -236,18 +250,25 @@
Future<List<Either2<Command, CodeAction>>> _getSourceActions(
HashSet<CodeActionKind> clientSupportedCodeActionKinds,
bool clientSupportsLiteralCodeActions,
+ bool clientSupportsWorkspaceApplyEdit,
String path,
) async {
// The source actions supported are only valid for Dart files.
if (!AnalysisEngine.isDartFileName(path)) {
- return [];
+ return const [];
}
// If the client told us what kinds they support but it does not include
// Source then don't return any.
if (clientSupportsLiteralCodeActions &&
!clientSupportedCodeActionKinds.contains(CodeActionKind.Source)) {
- return [];
+ return const [];
+ }
+
+ // If the client does not support workspace/applyEdit, we won't be able to
+ // run any of these.
+ if (!clientSupportsWorkspaceApplyEdit) {
+ return const [];
}
return [
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 ea2b0a2..0602df0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -55,7 +55,8 @@
LspJsonHandler<CompletionParams> get jsonHandler =>
CompletionParams.jsonHandler;
- Future<ErrorOr<List<CompletionItem>>> handle(CompletionParams params) async {
+ Future<ErrorOr<List<CompletionItem>>> handle(
+ CompletionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
@@ -82,6 +83,7 @@
includeSuggestionSets,
unit.result,
offset,
+ token,
));
}
@@ -91,6 +93,7 @@
bool includeSuggestionSets,
ResolvedUnitResult unit,
int offset,
+ CancellationToken token,
) async {
final performance = new CompletionPerformance();
performance.path = unit.path;
@@ -114,6 +117,11 @@
);
final suggestions =
await contributor.computeSuggestions(completionRequest);
+
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
+
final results = suggestions
.map((item) => toCompletionItem(
completionCapabilities,
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 df26ab8..c4b764c 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
@@ -29,7 +29,8 @@
@override
LspJsonHandler<CompletionItem> get jsonHandler => CompletionItem.jsonHandler;
- Future<ErrorOr<CompletionItem>> handle(CompletionItem item) async {
+ Future<ErrorOr<CompletionItem>> handle(
+ CompletionItem item, CancellationToken token) async {
// If this isn't an item with resolution data, return the same item back.
if (item.data == null) {
return success(item);
@@ -80,6 +81,10 @@
var resolvedLibrary = await session.getResolvedLibrary(libraryPath);
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
+
analyzer.LibraryElement requestedLibraryElement;
try {
requestedLibraryElement = await session.getLibraryByUri(
@@ -93,6 +98,10 @@
);
}
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
+
var requestedElement =
requestedLibraryElement.exportNamespace.get(requestedName);
if (requestedElement == null) {
@@ -118,6 +127,10 @@
}
});
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
+
final changes = builder.sourceChange;
final thisFilesChanges =
changes.edits.where((e) => e.file == data.file).toList();
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 ead355a..c6df90c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -23,7 +23,7 @@
TextDocumentPositionParams.jsonHandler;
Future<ErrorOr<List<Location>>> handle(
- TextDocumentPositionParams params) async {
+ TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index 5be52b6..6a59beb 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -22,7 +22,7 @@
TextDocumentPositionParams.jsonHandler;
Future<ErrorOr<List<DocumentHighlight>>> handle(
- TextDocumentPositionParams params) async {
+ TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
index a4c623b..3de909c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_symbols.dart
@@ -48,7 +48,7 @@
DocumentSymbolParams.jsonHandler;
Future<ErrorOr<Either2<List<DocumentSymbol>, List<SymbolInformation>>>>
- handle(DocumentSymbolParams params) async {
+ handle(DocumentSymbolParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(
Either2<List<DocumentSymbol>, List<SymbolInformation>>.t2([]),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
index c440afe..f552cf6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_execute_command.dart
@@ -33,7 +33,8 @@
LspJsonHandler<ExecuteCommandParams> get jsonHandler =>
ExecuteCommandParams.jsonHandler;
- Future<ErrorOr<Object>> handle(ExecuteCommandParams params) async {
+ Future<ErrorOr<Object>> handle(
+ ExecuteCommandParams params, CancellationToken token) async {
final handler = commandHandlers[params.command];
if (handler == null) {
return error(ServerErrorCodes.UnknownCommand,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
index c301118..699931d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_exit.dart
@@ -24,7 +24,7 @@
LspJsonHandler<void> get jsonHandler => NullJsonHandler;
@override
- Future<ErrorOr<void>> handle(void _) async {
+ Future<ErrorOr<void>> handle(void _, CancellationToken token) async {
// Set a flag that the server shutdown is being controlled here to ensure
// that the normal code that shuts down the server when the channel closes
// does not fire.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
index 7ad848d..bfea14c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_folding.dart
@@ -20,7 +20,8 @@
LspJsonHandler<FoldingRangeParams> get jsonHandler =>
FoldingRangeParams.jsonHandler;
- Future<ErrorOr<List<FoldingRange>>> handle(FoldingRangeParams params) async {
+ Future<ErrorOr<List<FoldingRange>>> handle(
+ FoldingRangeParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
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 7426410..2760984 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
@@ -32,7 +32,7 @@
}
Future<ErrorOr<List<TextEdit>>> handle(
- DocumentOnTypeFormattingParams params) async {
+ DocumentOnTypeFormattingParams params, CancellationToken token) async {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) => formatFile(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 effe549..a0587b7 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,7 +32,7 @@
}
Future<ErrorOr<List<TextEdit>>> handle(
- DocumentFormattingParams params) async {
+ DocumentFormattingParams params, CancellationToken token) async {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) => formatFile(path));
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index bd70948..b724b1a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -23,7 +23,8 @@
LspJsonHandler<TextDocumentPositionParams> get jsonHandler =>
TextDocumentPositionParams.jsonHandler;
- Future<ErrorOr<Hover>> handle(TextDocumentPositionParams params) async {
+ Future<ErrorOr<Hover>> handle(
+ TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
index e131307..d6e7643 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_implementation.dart
@@ -23,7 +23,7 @@
@override
Future<ErrorOr<List<Location>>> handle(
- TextDocumentPositionParams params) async {
+ TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
@@ -33,13 +33,16 @@
final unit = await path.mapResult(requireResolvedUnit);
final offset = await unit.mapResult((unit) => toOffset(unit.lineInfo, pos));
return offset
- .mapResult((offset) => _getImplementations(path.result, offset));
+ .mapResult((offset) => _getImplementations(path.result, offset, token));
}
Future<ErrorOr<List<Location>>> _getImplementations(
- String file, int offset) async {
+ String file, int offset, CancelableToken token) async {
final element = await server.getElementAtOffset(file, offset);
final computer = new TypeHierarchyComputer(server.searchEngine, element);
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
final items = await computer.compute();
if (items == null || items.isEmpty) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index ea1ed19..5b104b8 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -19,7 +19,8 @@
LspJsonHandler<InitializeParams> get jsonHandler =>
InitializeParams.jsonHandler;
- ErrorOr<InitializeResult> handle(InitializeParams params) {
+ ErrorOr<InitializeResult> handle(
+ InitializeParams params, CancellationToken token) {
final openWorkspacePaths = <String>[];
// The onlyAnalyzeProjectsWithOpenFiles flag allows opening huge folders
@@ -69,6 +70,12 @@
final renameOptionsSupport =
params.capabilities.textDocument?.rename?.prepareSupport ?? false;
+ // When adding new capabilities to the server that may apply to specific file
+ // types, it's important to update
+ // [IntializedMessageHandler._performDynamicRegistration()] to notify
+ // supporting clients of this. This avoids clients needing to hard-code the
+ // list of what files types we support (and allows them to avoid sending
+ // requests where we have only partial support for some types).
server.capabilities = new ServerCapabilities(
Either2<TextDocumentSyncOptions, num>.t1(new TextDocumentSyncOptions(
true,
@@ -80,33 +87,10 @@
true, // hoverProvider
new CompletionOptions(
true, // resolveProvider
- // Set the characters that will cause the editor to automatically
- // trigger completion.
- // TODO(dantup): There are several characters that we want to conditionally
- // allow to trigger completion, but they can only be added when the completion
- // provider is able to handle them in context:
- //
- // { trigger if being typed in a string immediately after a $
- // ' trigger if the opening quote for an import/export
- // " trigger if the opening quote for an import/export
- // / trigger if as part of a path in an import/export
- // \ trigger if as part of a path in an import/export
- // : don't trigger when typing case expressions (`case x:`)
- //
- // Additionally, we need to prefix `filterText` on completion items
- // with spaces for those that can follow whitespace (eg. `foo` in
- // `myArg: foo`) to ensure they're not filtered away when the user
- // types space.
- //
- // See https://github.com/Dart-Code/Dart-Code/blob/68d1cd271e88a785570257d487adbdec17abd6a3/src/providers/dart_completion_item_provider.ts#L36-L64
- // for the VS Code implementation of this.
- r'''.=($'''.split(''),
+ dartCompletionTriggerCharacters,
),
new SignatureHelpOptions(
- // TODO(dantup): Signature help triggering is even more sensitive to
- // bad chars, so we'll need to implement the logic described here:
- // https://github.com/dart-lang/sdk/issues/34241
- [],
+ dartSignatureHelpTriggerCharacters,
),
true, // definitionProvider
null,
@@ -125,7 +109,8 @@
null,
true, // documentFormattingProvider
false, // documentRangeFormattingProvider
- new DocumentOnTypeFormattingOptions('}', [';']),
+ new DocumentOnTypeFormattingOptions(dartTypeFormattingCharacters.first,
+ dartTypeFormattingCharacters.skip(1).toList()),
renameOptionsSupport
? Either2<bool, RenameOptions>.t2(new RenameOptions(true))
: Either2<bool, RenameOptions>.t1(true),
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index ea74fc5..27cf61a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -4,6 +4,7 @@
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:analysis_server/src/lsp/handlers/handler_states.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
@@ -23,17 +24,161 @@
LspJsonHandler<InitializedParams> get jsonHandler =>
InitializedParams.jsonHandler;
- ErrorOr<void> handle(InitializedParams params) {
+ ErrorOr<void> handle(InitializedParams params, CancellationToken token) {
server.messageHandler = new InitializedStateMessageHandler(
server,
onlyAnalyzeProjectsWithOpenFiles,
suggestFromUnimportedLibraries,
);
+ _performDynamicRegistration();
+
if (!onlyAnalyzeProjectsWithOpenFiles) {
server.setAnalysisRoots(openWorkspacePaths);
}
return success();
}
+
+ /// If the client supports dynamic registrations we can tell it what methods
+ /// we support for which documents. For example, this allows us to ask for
+ /// file edits for .dart as well as pubspec.yaml but only get hover/completion
+ /// calls for .dart. This functionality may not be supported by the client, in
+ /// which case they will use the ServerCapabilities to know which methods we
+ /// support and it will be up to them to decide which file types they will
+ /// send requests for.
+ Future<void> _performDynamicRegistration() async {
+ final dartFiles = DocumentFilter('dart', 'file', null);
+ final pubspecFile = DocumentFilter('yaml', 'file', '**/pubspec.yaml');
+ final analysisOptionsFile =
+ DocumentFilter('yaml', 'file', '**/analysis_options.yaml');
+ final allTypes = [dartFiles, pubspecFile, analysisOptionsFile];
+
+ // TODO(dantup): When we support plugins, we will need to collect their
+ // requirements too. For example, the Angular plugin might wish to add HTML
+ // `DocumentFilter('html', 'file', null)` to many of these requests.
+
+ int _lastRegistrationId = 1;
+ final registrations = <Registration>[];
+
+ /// Helper for creating registrations with IDs.
+ void register(bool condition, Method method, [ToJsonable options]) {
+ if (condition == true) {
+ registrations.add(Registration(
+ (_lastRegistrationId++).toString(), method.toJson(), options));
+ }
+ }
+
+ final textCapabilities = server.clientCapabilities?.textDocument;
+
+ register(
+ textCapabilities?.synchronization?.dynamicRegistration,
+ Method.textDocument_didOpen,
+ TextDocumentRegistrationOptions(allTypes),
+ );
+ register(
+ textCapabilities?.synchronization?.dynamicRegistration,
+ Method.textDocument_didClose,
+ TextDocumentRegistrationOptions(allTypes),
+ );
+ register(
+ textCapabilities?.synchronization?.dynamicRegistration,
+ Method.textDocument_didChange,
+ TextDocumentChangeRegistrationOptions(
+ TextDocumentSyncKind.Incremental, allTypes),
+ );
+ register(
+ server.clientCapabilities?.textDocument?.completion?.dynamicRegistration,
+ Method.textDocument_completion,
+ CompletionRegistrationOptions(
+ dartCompletionTriggerCharacters,
+ null,
+ true,
+ [dartFiles],
+ ),
+ );
+ register(
+ textCapabilities?.hover?.dynamicRegistration,
+ Method.textDocument_hover,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ textCapabilities?.signatureHelp?.dynamicRegistration,
+ Method.textDocument_signatureHelp,
+ SignatureHelpRegistrationOptions(
+ dartSignatureHelpTriggerCharacters, [dartFiles]),
+ );
+ register(
+ server.clientCapabilities?.textDocument?.references?.dynamicRegistration,
+ Method.textDocument_references,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ textCapabilities?.documentHighlight?.dynamicRegistration,
+ Method.textDocument_documentHighlight,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ textCapabilities?.documentSymbol?.dynamicRegistration,
+ Method.textDocument_documentSymbol,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ server.clientCapabilities?.textDocument?.formatting?.dynamicRegistration,
+ Method.textDocument_formatting,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ textCapabilities?.onTypeFormatting?.dynamicRegistration,
+ Method.textDocument_onTypeFormatting,
+ DocumentOnTypeFormattingRegistrationOptions(
+ dartTypeFormattingCharacters.first,
+ dartTypeFormattingCharacters.skip(1).toList(),
+ [dartFiles],
+ ),
+ );
+ register(
+ server.clientCapabilities?.textDocument?.definition?.dynamicRegistration,
+ Method.textDocument_definition,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ textCapabilities?.implementation?.dynamicRegistration,
+ Method.textDocument_implementation,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+ register(
+ server.clientCapabilities?.textDocument?.codeAction?.dynamicRegistration,
+ Method.textDocument_codeAction,
+ CodeActionRegistrationOptions(
+ [dartFiles], DartCodeActionKind.serverSupportedKinds),
+ );
+ register(
+ textCapabilities?.rename?.dynamicRegistration,
+ Method.textDocument_rename,
+ RenameRegistrationOptions(true, [dartFiles]),
+ );
+ register(
+ textCapabilities?.foldingRange?.dynamicRegistration,
+ Method.textDocument_foldingRange,
+ TextDocumentRegistrationOptions([dartFiles]),
+ );
+
+ // Only send the registration request if we have at least one (since
+ // otherwise we don't know that the client supports registerCapability).
+ if (registrations.isNotEmpty) {
+ final registrationResponse = await server.sendRequest(
+ Method.client_registerCapability,
+ RegistrationParams(registrations),
+ );
+
+ if (registrationResponse.error != null) {
+ server.logErrorToClient(
+ 'Failed to register capabilities with client: '
+ '(${registrationResponse.error.code}) '
+ '${registrationResponse.error.message}',
+ );
+ }
+ }
+ }
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index f410e9f..c6660f4 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -28,7 +28,8 @@
ReferenceParams.jsonHandler;
@override
- Future<ErrorOr<List<Location>>> handle(ReferenceParams params) async {
+ Future<ErrorOr<List<Location>>> handle(
+ ReferenceParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(const []);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
index b006c00..37c7916 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_reject.dart
@@ -21,7 +21,7 @@
LspJsonHandler<void> get jsonHandler => NullJsonHandler;
@override
- ErrorOr<void> handle(void _) {
+ ErrorOr<void> handle(void _, CancellationToken token) {
return error(errorCode, errorMessage, null);
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
index d997719..799eab6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -21,7 +21,7 @@
@override
Future<ErrorOr<RangeAndPlaceholder>> handle(
- TextDocumentPositionParams params) async {
+ TextDocumentPositionParams params, CancellationToken token) async {
final pos = params.position;
final path = pathOfDoc(params.textDocument);
final unit = await path.mapResult(requireResolvedUnit);
@@ -71,7 +71,8 @@
LspJsonHandler<RenameParams> get jsonHandler => RenameParams.jsonHandler;
@override
- Future<ErrorOr<WorkspaceEdit>> handle(RenameParams params) async {
+ Future<ErrorOr<WorkspaceEdit>> handle(
+ RenameParams params, CancellationToken token) async {
final pos = params.position;
final path = pathOfDoc(params.textDocument);
// If the client provided us a version doc identifier, we'll use it to ensure
@@ -106,6 +107,9 @@
// Check the rename is valid here.
final initStatus = await refactoring.checkInitialConditions();
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
if (initStatus.hasError) {
return error(
ServerErrorCodes.RenameNotValid, initStatus.problem.message, null);
@@ -121,6 +125,9 @@
// Final validation.
final finalStatus = await refactoring.checkFinalConditions();
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
if (finalStatus.hasError) {
return error(
ServerErrorCodes.RenameNotValid, finalStatus.problem.message, null);
@@ -128,6 +135,9 @@
// Compute the actual change.
final change = await refactoring.createChange();
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
// Before we send anything back, ensure the original file didn't change
// while we were computing changes.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
index c16a394..9349240 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_shutdown.dart
@@ -16,7 +16,7 @@
LspJsonHandler<void> get jsonHandler => NullJsonHandler;
@override
- ErrorOr<void> handle(void _) {
+ ErrorOr<void> handle(void _, CancellationToken token) {
// Move to the Shutting Down state so we won't process any more
// requests and the Exit notification will know it was a clean shutdown.
server.messageHandler = new ShuttingDownStateMessageHandler(server);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index cde88c9..642e77f 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -21,7 +21,7 @@
TextDocumentPositionParams.jsonHandler;
Future<ErrorOr<SignatureHelp>> handle(
- TextDocumentPositionParams params) async {
+ TextDocumentPositionParams params, CancellationToken token) async {
if (!isDartDocument(params.textDocument)) {
return success(null);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index 60b6f53..3bcf9fd 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -41,7 +41,7 @@
@override
FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
- return failure(
+ return error(
ErrorCodes.InternalError,
'An unrecoverable error occurred and the server cannot process messages',
null);
@@ -117,7 +117,7 @@
if (message is! RequestMessage) {
return success();
}
- return failure(
+ return error(
ErrorCodes.ServerNotInitialized,
'Unable to handle ${message.method} before the server is initialized '
'and the client has sent the initialized notification');
@@ -137,7 +137,7 @@
if (message is! RequestMessage) {
return success();
}
- return failure(ErrorCodes.ServerNotInitialized,
+ return error(ErrorCodes.ServerNotInitialized,
'Unable to handle ${message.method} before client has sent initialize request');
}
}
@@ -154,7 +154,7 @@
if (message is! RequestMessage) {
return success();
}
- return failure(ErrorCodes.InvalidRequest,
+ return error(ErrorCodes.InvalidRequest,
'Unable to handle ${message.method} after shutdown request');
}
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
index e083f5d..46ab686 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_text_document_changes.dart
@@ -23,7 +23,8 @@
LspJsonHandler<DidChangeTextDocumentParams> get jsonHandler =>
DidChangeTextDocumentParams.jsonHandler;
- ErrorOr<void> handle(DidChangeTextDocumentParams params) {
+ ErrorOr<void> handle(
+ DidChangeTextDocumentParams params, CancellationToken token) {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) => _changeFile(path, params));
}
@@ -66,7 +67,8 @@
LspJsonHandler<DidCloseTextDocumentParams> get jsonHandler =>
DidCloseTextDocumentParams.jsonHandler;
- ErrorOr<void> handle(DidCloseTextDocumentParams params) {
+ ErrorOr<void> handle(
+ DidCloseTextDocumentParams params, CancellationToken token) {
final path = pathOfDoc(params.textDocument);
return path.mapResult((path) {
server.removePriorityFile(path);
@@ -111,7 +113,8 @@
LspJsonHandler<DidOpenTextDocumentParams> get jsonHandler =>
DidOpenTextDocumentParams.jsonHandler;
- ErrorOr<void> handle(DidOpenTextDocumentParams params) {
+ ErrorOr<void> handle(
+ DidOpenTextDocumentParams params, CancellationToken token) {
final doc = params.textDocument;
final path = pathOfDocItem(doc);
return path.mapResult((path) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
index 0f748d5..c53327a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
@@ -24,7 +24,7 @@
WorkspaceSymbolParams.jsonHandler;
Future<ErrorOr<List<SymbolInformation>>> handle(
- WorkspaceSymbolParams params) async {
+ WorkspaceSymbolParams params, CancellationToken token) async {
// Respond to empty queries with an empty list. The spec says this should
// be non-empty, however VS Code's client sends empty requests (but then
// appears to not render the results we supply anyway).
@@ -55,6 +55,9 @@
for (var driver in server.driverMap.values) {
final driverResults = await driver.search
.declarations(regex, remainingResults, filePathsHashSet);
+ if (token.isCancellationRequested) {
+ return cancelled();
+ }
declarations.addAll(driverResults);
remainingResults -= driverResults.length;
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
index 29d6800..89a8c1b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handlers.dart
@@ -7,6 +7,7 @@
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:analysis_server/src/lsp/handlers/handler_cancel_request.dart';
import 'package:analysis_server/src/lsp/handlers/handler_reject.dart';
import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
import 'package:analyzer/dart/analysis/results.dart';
@@ -19,6 +20,22 @@
return items.map(converter).where((item) => item != null);
}
+class CancelableToken extends CancellationToken {
+ bool _isCancelled = false;
+
+ @override
+ bool get isCancellationRequested => _isCancelled;
+
+ void cancel() => _isCancelled = true;
+}
+
+/// A token used to signal cancellation of an operation. This allows computation
+/// to be skipped when a caller is no longer interested in the result, for example
+/// when a $/cancel request is recieved for an in-progress request.
+abstract class CancellationToken {
+ bool get isCancellationRequested;
+}
+
abstract class CommandHandler<P, R> with Handler<P, R> {
CommandHandler(LspAnalysisServer server) {
this.server = server;
@@ -30,12 +47,6 @@
mixin Handler<P, R> {
LspAnalysisServer server;
- ErrorOr<R> error<R>(ErrorCodes code, String message, String data) =>
- new ErrorOr<R>.error(new ResponseError(code, message, data));
-
- ErrorOr<R> failure<R>(ErrorOr<dynamic> error) =>
- new ErrorOr<R>.error(error.error);
-
Future<ErrorOr<ResolvedUnitResult>> requireResolvedUnit(String path) async {
final result = await server.getResolvedUnit(path);
if (result?.state != ResultState.VALID) {
@@ -51,8 +62,6 @@
}
return success(result);
}
-
- ErrorOr<R> success<R>([R t]) => new ErrorOr<R>.success(t);
}
/// An object that can handle messages and produce responses for requests.
@@ -69,41 +78,69 @@
/// A handler that can parse and validate JSON params.
LspJsonHandler<P> get jsonHandler;
- FutureOr<ErrorOr<R>> handle(P params);
+ FutureOr<ErrorOr<R>> handle(P params, CancellationToken token);
/// Handle the given [message]. If the [message] is a [RequestMessage], then the
/// return value will be sent back in a [ResponseMessage].
/// [NotificationMessage]s are not expected to return results.
- FutureOr<ErrorOr<R>> handleMessage(IncomingMessage message) {
+ FutureOr<ErrorOr<R>> handleMessage(
+ IncomingMessage message, CancellationToken token) {
if (!jsonHandler.validateParams(message.params)) {
return error(ErrorCodes.InvalidParams,
'Invalid params for ${message.method}', null);
}
final params = jsonHandler.convertParams(message.params);
- return handle(params);
+ return handle(params, token);
}
}
+class NotCancelableToken extends CancellationToken {
+ @override
+ bool get isCancellationRequested => false;
+}
+
/// A message handler that handles all messages for a given server state.
abstract class ServerStateMessageHandler {
final LspAnalysisServer server;
final Map<Method, MessageHandler> _messageHandlers = {};
+ final CancelRequestHandler _cancelHandler;
+ final NotCancelableToken _notCancelableToken = NotCancelableToken();
- ServerStateMessageHandler(this.server);
-
- ErrorOr<Object> failure<Object>(ErrorCodes code, String message,
- [String data]) =>
- new ErrorOr<Object>.error(new ResponseError(code, message, data));
+ ServerStateMessageHandler(this.server)
+ : _cancelHandler = CancelRequestHandler(server) {
+ registerHandler(_cancelHandler);
+ }
/// Handle the given [message]. If the [message] is a [RequestMessage], then the
/// return value will be sent back in a [ResponseMessage].
/// [NotificationMessage]s are not expected to return results.
FutureOr<ErrorOr<Object>> handleMessage(IncomingMessage message) async {
final handler = _messageHandlers[message.method];
- return handler != null
- ? handler.handleMessage(message)
- : handleUnknownMessage(message);
+ if (handler == null) {
+ return handleUnknownMessage(message);
+ }
+
+ if (message is! RequestMessage) {
+ return handler.handleMessage(message, _notCancelableToken);
+ }
+
+ // Create a cancellation token that will allow us to cancel this request if
+ // requested to save processing (the handler will need to specifically
+ // check the token after `await` points).
+ final token = _cancelHandler.createToken(message);
+ try {
+ final result = await handler.handleMessage(message, token);
+ // Do a final check before returning the result, because if the request was
+ // cancelled we can save the overhead of serialising everything to JSON
+ // and the client to deserialising the same in order to read the ID to see
+ // that it was a request it didn't need (in the case of completions this
+ // can be quite large).
+ await Future.delayed(Duration.zero);
+ return token.isCancellationRequested ? cancelled() : result;
+ } finally {
+ _cancelHandler.clearToken(message);
+ }
}
FutureOr<ErrorOr<Object>> handleUnknownMessage(IncomingMessage message) {
@@ -112,8 +149,7 @@
// to so they don't leave open requests on the client.
return _isOptionalNotification(message)
? success()
- : failure(
- ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
+ : error(ErrorCodes.MethodNotFound, 'Unknown method ${message.method}');
}
registerHandler(MessageHandler handler) {
@@ -129,8 +165,6 @@
registerHandler(new RejectMessageHandler(server, method, code, message));
}
- ErrorOr<Object> success<Object>([Object t]) => new ErrorOr<Object>.success(t);
-
bool _isOptionalNotification(IncomingMessage message) {
// Not a notification.
if (message is! NotificationMessage) {
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index e8f5112..7fff986 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -88,9 +88,6 @@
*/
RefactoringWorkspace _refactoringWorkspace;
- RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
- new RefactoringWorkspace(driverMap.values, searchEngine);
-
/**
* The versions of each document known to the server (keyed by path), used to
* send back to the client for server-initiated edits so that the client can
@@ -172,10 +169,12 @@
analysisDriverScheduler.status.listen(sendStatusNotification);
analysisDriverScheduler.start();
- declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
- declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
- analysisDriverScheduler.outOfBandWorker =
- CompletionLibrariesWorker(declarationsTracker);
+ if (options.featureSet.completion) {
+ declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+ declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+ analysisDriverScheduler.outOfBandWorker =
+ CompletionLibrariesWorker(declarationsTracker);
+ }
contextManager = new ContextManagerImpl(
resourceProvider,
@@ -197,6 +196,9 @@
Future<void> get exited => channel.closed;
+ RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
+ new RefactoringWorkspace(driverMap.values, searchEngine);
+
addPriorityFile(String path) {
final didAdd = priorityFiles.add(path);
assert(didAdd);
@@ -326,6 +328,28 @@
));
}
+ /// Logs an exception by sending it to the client (window/logMessage) and
+ /// recording it in a buffer on the server for diagnostics.
+ void logException(String message, exception, stackTrace) {
+ if (exception is CaughtException) {
+ stackTrace ??= exception.stackTrace;
+ }
+
+ final fullError = stackTrace == null ? message : '$message\n$stackTrace';
+
+ // Log the full message since showMessage above may be truncated or formatted
+ // badly (eg. VS Code takes the newlines out).
+ logErrorToClient(fullError);
+
+ // remember the last few exceptions
+ exceptions.add(new ServerException(
+ message,
+ exception,
+ stackTrace is StackTrace ? stackTrace : null,
+ false,
+ ));
+ }
+
void publishDiagnostics(String path, List<Diagnostic> errors) {
final params =
new PublishDiagnosticsParams(Uri.file(path).toString(), errors);
@@ -414,28 +438,6 @@
logException(message, exception, stackTrace);
}
- /// Logs an exception by sending it to the client (window/logMessage) and
- /// recording it in a buffer on the server for diagnostics.
- void logException(String message, exception, stackTrace) {
- if (exception is CaughtException) {
- stackTrace ??= exception.stackTrace;
- }
-
- final fullError = stackTrace == null ? message : '$message\n$stackTrace';
-
- // Log the full message since showMessage above may be truncated or formatted
- // badly (eg. VS Code takes the newlines out).
- logErrorToClient(fullError);
-
- // remember the last few exceptions
- exceptions.add(new ServerException(
- message,
- exception,
- stackTrace is StackTrace ? stackTrace : null,
- false,
- ));
- }
-
/// Send status notification to the client. The state of analysis is given by
/// the [status] information.
void sendStatusNotification(nd.AnalysisStatus status) {
@@ -447,7 +449,7 @@
}
void setAnalysisRoots(List<String> includedPaths) {
- declarationsTracker.discardContexts();
+ declarationsTracker?.discardContexts();
final uniquePaths = HashSet<String>.of(includedPaths ?? const []);
contextManager.setRoots(uniquePaths.toList(), [], {});
addContextsToDeclarationsTracker();
@@ -574,6 +576,11 @@
}
@override
+ void analysisOptionsUpdated(nd.AnalysisDriver driver) {
+ // TODO: implement analysisOptionsUpdated
+ }
+
+ @override
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
nd.AnalysisDriver analysisDriver = analysisServer.driverMap[contextFolder];
if (analysisDriver != null) {
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type.dart b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
index 81abe99..0dbc5ac 100644
--- a/pkg/analysis_server/lib/src/nullability/decorated_type.dart
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
@@ -35,29 +35,26 @@
/// TODO(paulberry): how should we handle generic typedefs?
final List<DecoratedType> typeArguments;
- DecoratedType(this.type, this.node, NullabilityGraph graph,
+ DecoratedType(this.type, this.node,
{this.returnType,
this.positionalParameters = const [],
this.namedParameters = const {},
this.typeArguments = const []}) {
assert(node != null);
// The type system doesn't have a non-nullable version of `dynamic`. So if
- // the type is `dynamic`, verify that the node is directly downstream from
- // Nullability.always.
- assert(!type.isDynamic ||
- graph
- .getUnconditionalUpstreamNodes(node)
- .contains(NullabilityNode.always));
+ // the type is `dynamic`, verify that the node was initially placed into a
+ // nullable state.
+ assert(!type.isDynamic || node.isNullable);
}
/// Creates a [DecoratedType] corresponding to the given [element], which is
/// presumed to have come from code that is already migrated.
- factory DecoratedType.forElement(Element element, NullabilityGraph graph) {
+ factory DecoratedType.forElement(Element element) {
DecoratedType decorate(DartType type) {
assert((type as TypeImpl).nullabilitySuffix ==
NullabilitySuffix.star); // TODO(paulberry)
if (type is FunctionType) {
- var decoratedType = DecoratedType(type, NullabilityNode.never, graph,
+ var decoratedType = DecoratedType(type, NullabilityNode.never,
returnType: decorate(type.returnType), positionalParameters: []);
for (var parameter in type.parameters) {
assert(parameter.isPositional); // TODO(paulberry)
@@ -66,7 +63,7 @@
return decoratedType;
} else if (type is InterfaceType) {
assert(type.typeParameters.isEmpty); // TODO(paulberry)
- return DecoratedType(type, NullabilityNode.never, graph);
+ return DecoratedType(type, NullabilityNode.never);
} else {
throw type.runtimeType; // TODO(paulberry)
}
@@ -75,6 +72,8 @@
DecoratedType decoratedType;
if (element is MethodElement) {
decoratedType = decorate(element.type);
+ } else if (element is PropertyAccessorElement) {
+ decoratedType = decorate(element.type);
} else {
throw element.runtimeType; // TODO(paulberry)
}
@@ -86,11 +85,10 @@
/// [undecoratedResult] is the result of the substitution, as determined by
/// the normal type system.
DecoratedType substitute(
- NullabilityGraph graph,
Map<TypeParameterElement, DecoratedType> substitution,
DartType undecoratedResult) {
if (substitution.isEmpty) return this;
- return _substitute(graph, substitution, undecoratedResult);
+ return _substitute(substitution, undecoratedResult);
}
@override
@@ -121,7 +119,6 @@
/// Internal implementation of [_substitute], used as a recursion target.
DecoratedType _substitute(
- NullabilityGraph graph,
Map<TypeParameterElement, DecoratedType> substitution,
DartType undecoratedResult) {
var type = this.type;
@@ -136,16 +133,16 @@
: undecoratedResult
.optionalParameterTypes[i - numRequiredParameters];
newPositionalParameters.add(positionalParameters[i]
- ._substitute(graph, substitution, undecoratedParameterType));
+ ._substitute(substitution, undecoratedParameterType));
}
- return DecoratedType(undecoratedResult, node, graph,
+ return DecoratedType(undecoratedResult, node,
returnType: returnType._substitute(
- graph, substitution, undecoratedResult.returnType),
+ substitution, undecoratedResult.returnType),
positionalParameters: newPositionalParameters);
} else if (type is TypeParameterType) {
var inner = substitution[type.element];
return DecoratedType(undecoratedResult,
- NullabilityNode.forSubstitution(inner?.node, node), graph);
+ NullabilityNode.forSubstitution(inner?.node, node));
} else if (type is VoidType) {
return this;
}
@@ -162,10 +159,10 @@
implements PotentialModification {
final int _offset;
- DecoratedTypeAnnotation(DartType type, NullabilityNode nullabilityNode,
- this._offset, NullabilityGraph graph,
+ DecoratedTypeAnnotation(
+ DartType type, NullabilityNode nullabilityNode, this._offset,
{List<DecoratedType> typeArguments = const []})
- : super(type, nullabilityNode, graph, typeArguments: typeArguments);
+ : super(type, nullabilityNode, typeArguments: typeArguments);
@override
bool get isEmpty => !node.isNullable;
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
index 59164ce..0788209 100644
--- a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
@@ -2,8 +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 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart b/pkg/analysis_server/lib/src/nullability/graph_builder.dart
similarity index 85%
rename from pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
rename to pkg/analysis_server/lib/src/nullability/graph_builder.dart
index 20532c1..c2f4bfa 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/graph_builder.dart
@@ -3,11 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
@@ -18,22 +17,20 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
-/// Visitor that gathers nullability migration constraints from code to be
+/// Visitor that builds nullability graph edges by examining code to be
/// migrated.
///
/// The return type of each `visit...` method is a [DecoratedType] indicating
/// the static type of the visited expression, along with the constraint
/// variables that will determine its nullability. For `visit...` methods that
/// don't visit expressions, `null` will be returned.
-class ConstraintGatherer extends GeneralizingAstVisitor<DecoratedType> {
+class GraphBuilder extends GeneralizingAstVisitor<DecoratedType> {
/// The repository of constraint variables and decorated types (from a
/// previous pass over the source code).
final VariableRepository _variables;
final bool _permissive;
- final NullabilityMigrationAssumptions assumptions;
-
final NullabilityGraph _graph;
/// The file being analyzed.
@@ -76,16 +73,16 @@
/// or expression.
bool _inConditionalControlFlow = false;
- ConstraintGatherer(TypeProvider typeProvider, this._variables, this._graph,
- this._source, this._permissive, this.assumptions)
- : _notNullType = DecoratedType(
- typeProvider.objectType, NullabilityNode.never, _graph),
+ GraphBuilder(TypeProvider typeProvider, this._variables, this._graph,
+ this._source, this._permissive)
+ : _notNullType =
+ DecoratedType(typeProvider.objectType, NullabilityNode.never),
_nonNullableBoolType =
- DecoratedType(typeProvider.boolType, NullabilityNode.never, _graph),
+ DecoratedType(typeProvider.boolType, NullabilityNode.never),
_nonNullableTypeType =
- DecoratedType(typeProvider.typeType, NullabilityNode.never, _graph),
- _nullType = DecoratedType(
- typeProvider.nullType, NullabilityNode.always, _graph);
+ DecoratedType(typeProvider.typeType, NullabilityNode.never),
+ _nullType =
+ DecoratedType(typeProvider.nullType, NullabilityNode.always);
/// Gets the decorated type of [element] from [_variables], performing any
/// necessary substitutions.
@@ -121,7 +118,7 @@
} else {
throw element.runtimeType; // TODO(paulberry)
}
- return decoratedBaseType.substitute(_graph, substitution, elementType);
+ return decoratedBaseType.substitute(substitution, elementType);
} else {
return decoratedBaseType;
}
@@ -184,7 +181,7 @@
@override
DecoratedType visitBooleanLiteral(BooleanLiteral node) {
- return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+ return DecoratedType(node.staticType, NullabilityNode.never);
}
@override
@@ -201,10 +198,8 @@
assert(_isSimple(thenType)); // TODO(paulberry)
var elseType = node.elseExpression.accept(this);
assert(_isSimple(elseType)); // TODO(paulberry)
- var overallType = DecoratedType(
- node.staticType,
- NullabilityNode.forLUB(node, thenType.node, elseType.node, _graph),
- _graph);
+ var overallType = DecoratedType(node.staticType,
+ NullabilityNode.forLUB(node, thenType.node, elseType.node, _graph));
_variables.recordDecoratedExpressionType(node, overallType);
return overallType;
}
@@ -216,18 +211,10 @@
if (node.declaredElement.hasRequired) {
// Nothing to do; the implicit default value of `null` will never be
// reached.
- } else if (node.declaredElement.isOptionalPositional ||
- assumptions.namedNoDefaultParameterHeuristic ==
- NamedNoDefaultParameterHeuristic.assumeNullable) {
- NullabilityNode.recordAssignment(
- NullabilityNode.always,
- getOrComputeElementType(node.declaredElement).node,
- _guards,
- _graph,
- false);
} else {
- assert(assumptions.namedNoDefaultParameterHeuristic ==
- NamedNoDefaultParameterHeuristic.assumeRequired);
+ NullabilityNode.recordAssignment(NullabilityNode.always,
+ getOrComputeElementType(node.declaredElement).node, _guards, _graph,
+ hard: false);
}
} else {
_handleAssignment(
@@ -297,12 +284,12 @@
@override
DecoratedType visitIntegerLiteral(IntegerLiteral node) {
- return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+ return DecoratedType(node.staticType, NullabilityNode.never);
}
@override
DecoratedType visitMethodDeclaration(MethodDeclaration node) {
- node.parameters.accept(this);
+ node.parameters?.accept(this);
assert(_currentFunctionType == null);
_currentFunctionType =
_variables.decoratedElementType(node.declaredElement);
@@ -319,12 +306,16 @@
DecoratedType visitMethodInvocation(MethodInvocation node) {
DecoratedType targetType;
if (node.target != null) {
- assert(node.operator.type == TokenType.PERIOD);
+ if (node.operator.type != TokenType.PERIOD) {
+ throw new UnimplementedError('TODO(paulberry)');
+ }
_checkNonObjectMember(node.methodName.name); // TODO(paulberry)
targetType = _handleAssignment(_notNullType, node.target);
}
var callee = node.methodName.staticElement;
- assert(callee != null); // TODO(paulberry)
+ if (callee == null) {
+ throw new UnimplementedError('TODO(paulberry)');
+ }
var calleeType = getOrComputeElementType(callee, targetType: targetType);
// TODO(paulberry): substitute if necessary
var arguments = node.argumentList.arguments;
@@ -374,6 +365,20 @@
}
@override
+ DecoratedType visitPrefixedIdentifier(PrefixedIdentifier node) {
+ if (node.prefix.staticElement is ImportElement) {
+ throw new UnimplementedError('TODO(paulberry)');
+ } else {
+ return _handlePropertyAccess(node.prefix, node.period, node.identifier);
+ }
+ }
+
+ @override
+ DecoratedType visitPropertyAccess(PropertyAccess node) {
+ return _handlePropertyAccess(node.target, node.operator, node.propertyName);
+ }
+
+ @override
DecoratedType visitReturnStatement(ReturnStatement node) {
if (node.expression == null) {
_checkAssignment(_currentFunctionType.returnType, _nullType, null);
@@ -398,19 +403,19 @@
@override
DecoratedType visitStringLiteral(StringLiteral node) {
- return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+ return DecoratedType(node.staticType, NullabilityNode.never);
}
@override
DecoratedType visitThisExpression(ThisExpression node) {
- return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+ return DecoratedType(node.staticType, NullabilityNode.never);
}
@override
DecoratedType visitThrowExpression(ThrowExpression node) {
node.expression.accept(this);
// TODO(paulberry): do we need to check the expression type? I think not.
- return DecoratedType(node.staticType, NullabilityNode.never, _graph);
+ return DecoratedType(node.staticType, NullabilityNode.never);
}
@override
@@ -426,13 +431,12 @@
} else {
throw new UnimplementedError('TODO(paulberry)');
}
- _checkAssignment(
- bound,
- _variables.decoratedTypeAnnotation(_source, typeArguments[i]),
- null);
+ _checkAssignment(bound,
+ _variables.decoratedTypeAnnotation(_source, typeArguments[i]), null,
+ hard: true);
}
}
- return DecoratedType(typeName.type, NullabilityNode.never, _graph);
+ return DecoratedType(typeName.type, NullabilityNode.never);
}
/// Creates the necessary constraint(s) for an assignment from [sourceType] to
@@ -440,7 +444,8 @@
/// [sourceType]; it is the expression we will have to null-check in the case
/// where a nullable source is assigned to a non-nullable destination.
void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
- Expression expression) {
+ Expression expression,
+ {bool hard}) {
if (expression != null) {
_variables.recordExpressionChecks(
_source,
@@ -448,8 +453,11 @@
ExpressionChecks(
expression.end, sourceType.node, destinationType.node, _guards));
}
- NullabilityNode.recordAssignment(sourceType.node, destinationType.node,
- _guards, _graph, _inConditionalControlFlow);
+ NullabilityNode.recordAssignment(
+ sourceType.node, destinationType.node, _guards, _graph,
+ hard: hard ??
+ (_isVariableOrParameterReference(expression) &&
+ !_inConditionalControlFlow));
// TODO(paulberry): it's a cheat to pass in expression=null for the
// recursive checks. Really we want to unify all the checks in a single
// ExpressionChecks object.
@@ -497,6 +505,22 @@
return sourceType;
}
+ DecoratedType _handlePropertyAccess(
+ Expression target, Token operator, SimpleIdentifier propertyName) {
+ if (operator.type != TokenType.PERIOD) {
+ throw new UnimplementedError('TODO(paulberry)');
+ }
+ _checkNonObjectMember(propertyName.name); // TODO(paulberry)
+ var targetType = _handleAssignment(_notNullType, target);
+ var callee = propertyName.staticElement;
+ if (callee == null) {
+ throw new UnimplementedError('TODO(paulberry)');
+ }
+ var calleeType = getOrComputeElementType(callee, targetType: targetType);
+ // TODO(paulberry): substitute if necessary
+ return calleeType.returnType;
+ }
+
/// Double checks that [type] is sufficiently simple for this naive prototype
/// implementation.
///
@@ -509,6 +533,15 @@
if ((type.type as InterfaceType).typeParameters.isNotEmpty) return false;
return true;
}
+
+ bool _isVariableOrParameterReference(Expression expression) {
+ if (expression is SimpleIdentifier) {
+ var element = expression.staticElement;
+ if (element is LocalVariableElement) return true;
+ if (element is ParameterElement) return true;
+ }
+ return false;
+ }
}
/// Information about a binary expression whose boolean value could possibly
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/node_builder.dart
similarity index 89%
rename from pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
rename to pkg/analysis_server/lib/src/nullability/node_builder.dart
index fbabd5a..b85765b 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/node_builder.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
-import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -15,14 +14,13 @@
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
-/// Visitor that gathers constraint variables for nullability migration from
-/// code to be migrated.
+/// Visitor that builds nullability nodes based on visiting code to be migrated.
///
/// The return type of each `visit...` method is a [DecoratedType] indicating
/// the static type of the element declared by the visited node, along with the
/// constraint variables that will determine its nullability. For `visit...`
/// methods that don't visit declarations, `null` will be returned.
-class ConstraintVariableGatherer extends GeneralizingAstVisitor<DecoratedType> {
+class NodeBuilder extends GeneralizingAstVisitor<DecoratedType> {
/// Constraint variables and decorated types are stored here.
final VariableRecorder _variables;
@@ -39,14 +37,12 @@
final bool _permissive;
- final NullabilityMigrationAssumptions assumptions;
-
final NullabilityGraph _graph;
final TypeProvider _typeProvider;
- ConstraintVariableGatherer(this._variables, this._source, this._permissive,
- this.assumptions, this._graph, this._typeProvider);
+ NodeBuilder(this._variables, this._source, this._permissive, this._graph,
+ this._typeProvider);
/// Creates and stores a [DecoratedType] object corresponding to the given
/// [type] AST, and returns it.
@@ -58,8 +54,7 @@
? new DecoratedType(
DynamicTypeImpl.instance,
NullabilityNode.forInferredDynamicType(
- _graph, enclosingNode.offset),
- _graph)
+ _graph, enclosingNode.offset))
: type.accept(this);
}
@@ -132,8 +127,8 @@
assert(node is NamedType); // TODO(paulberry)
var type = node.type;
if (type.isVoid) {
- return DecoratedType(type,
- NullabilityNode.forTypeAnnotation(node.end, always: true), _graph);
+ return DecoratedType(
+ type, NullabilityNode.forTypeAnnotation(node.end, always: true));
}
assert(
type is InterfaceType || type is TypeParameterType); // TODO(paulberry)
@@ -152,7 +147,6 @@
NullabilityNode.forTypeAnnotation(node.end,
always: node.question != null),
node.end,
- _graph,
typeArguments: typeArguments);
_variables.recordDecoratedTypeAnnotation(_source, node, decoratedType);
return decoratedType;
@@ -165,10 +159,8 @@
DecoratedType visitTypeParameter(TypeParameter node) {
var element = node.declaredElement;
var decoratedBound = node.bound?.accept(this) ??
- DecoratedType(
- element.bound ?? _typeProvider.objectType,
- NullabilityNode.forInferredDynamicType(_graph, node.offset),
- _graph);
+ DecoratedType(element.bound ?? _typeProvider.objectType,
+ NullabilityNode.forInferredDynamicType(_graph, node.offset));
_variables.recordDecoratedElementType(element, decoratedBound);
return null;
}
@@ -184,13 +176,13 @@
// TODO(paulberry): test that it's correct to use `null` for the nullability
// of the function type
var functionType = DecoratedType(
- declaredElement.type, NullabilityNode.never, _graph,
+ declaredElement.type, NullabilityNode.never,
returnType: decoratedReturnType,
positionalParameters: [],
namedParameters: {});
_currentFunctionType = functionType;
try {
- parameters.accept(this);
+ parameters?.accept(this);
} finally {
_currentFunctionType = previousFunctionType;
}
@@ -202,7 +194,7 @@
/// code being migrated.
///
/// This data structure records the results of the first pass of migration
-/// ([ConstraintVariableGatherer], which finds all the variables that need to be
+/// ([NodeBuilder], which finds all the variables that need to be
/// constrained).
abstract class VariableRecorder {
/// Associates decorated type information with the given [element].
@@ -224,7 +216,7 @@
///
/// This data structure allows the second pass of migration
/// ([ConstraintGatherer], which builds all the constraints) to access the
-/// results of the first ([ConstraintVariableGatherer], which finds all the
+/// results of the first ([NodeBuilder], which finds all the
/// variables that need to be constrained).
abstract class VariableRepository {
/// Retrieves the [DecoratedType] associated with the static type of the given
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_node.dart b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
index ebd221c..453887d 100644
--- a/pkg/analysis_server/lib/src/nullability/nullability_node.dart
+++ b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
@@ -5,28 +5,60 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:meta/meta.dart';
+/// Data structure to keep track of the relationship from one [NullabilityNode]
+/// object to another [NullabilityNode] that is "downstream" from it (meaning
+/// that if the former node is nullable, then the latter node will either have
+/// to be nullable, or null checks will have to be added).
+class NullabilityEdge {
+ /// The node that is downstream.
+ final NullabilityNode destinationNode;
+
+ /// A set of source nodes. By convention, the first node is the primary
+ /// source and the other nodes are "guards". The destination node will only
+ /// need to be made nullable if all the source nodes are nullable.
+ final List<NullabilityNode> sources;
+
+ final bool hard;
+
+ NullabilityEdge(this.destinationNode, this.sources, this.hard);
+
+ Iterable<NullabilityNode> get guards => sources.skip(1);
+
+ NullabilityNode get primarySource => sources.first;
+}
+
/// Data structure to keep track of the relationship between [NullabilityNode]
/// objects.
class NullabilityGraph {
+ /// Set this const to `true` to dump the nullability graph just before
+ /// propagation.
+ static const _debugBeforePropagation = false;
+
/// Set containing all [NullabilityNode]s that have been passed as the
/// `sourceNode` argument to [connect].
final _allSourceNodes = Set<NullabilityNode>.identity();
- /// List of [_NullabilityEdge] objects that are downstream from
+ /// List of [NullabilityEdge] objects that are downstream from
/// [NullabilityNode.always]. (They can't be stored in
/// [NullabilityNode.always] directly because it is immutable).
- final _downstreamFromAlways = <_NullabilityEdge>[];
+ final _downstreamFromAlways = <NullabilityEdge>[];
- /// List of [NullabilityNodes] that are "upstream" from
+ /// List of [NullabilityEdge] objects that are upstream from
/// [NullabilityNode.never] due to unconditional control flow. (They can't be
/// stored in [NullabilityNode.never] directly because it is immutable).
- final _unconditionalUpstreamFromNever = <NullabilityNode>[];
+ final _upstreamFromNever = <NullabilityEdge>[];
+
+ /// List of [NullabilityNodeMutable] objects that were set into the nullable
+ /// state by a process other than nullability propagation. The next time
+ /// nullability is propagated, the propagation algorithm will ensure that
+ /// edges originating at these nodes are examined.
+ final _pendingDownstreamNodes = <NullabilityNodeMutable>[];
/// Records that [sourceNode] is immediately upstream from [destinationNode].
void connect(NullabilityNode sourceNode, NullabilityNode destinationNode,
- {bool unconditional: false, List<NullabilityNode> guards: const []}) {
+ {bool hard: false, List<NullabilityNode> guards: const []}) {
var sources = [sourceNode]..addAll(guards);
- var edge = _NullabilityEdge(destinationNode, sources);
+ var edge = NullabilityEdge(destinationNode, sources, hard);
for (var source in sources) {
_allSourceNodes.add(source);
if (source is NullabilityNodeMutable) {
@@ -39,16 +71,14 @@
assert(source == NullabilityNode.never);
}
}
- if (unconditional) {
- if (destinationNode is NullabilityNodeMutable) {
- destinationNode._unconditionalUpstreamNodes.add(sourceNode);
- } else if (destinationNode == NullabilityNode.never) {
- _unconditionalUpstreamFromNever.add(sourceNode);
- } else {
- // We don't need to track nodes that are upstream from `always` because
- // `always` will never have non-null intent.
- assert(destinationNode == NullabilityNode.always);
- }
+ if (destinationNode is NullabilityNodeMutable) {
+ destinationNode._upstreamEdges.add(edge);
+ } else if (destinationNode == NullabilityNode.never) {
+ _upstreamFromNever.add(edge);
+ } else {
+ // We don't need to track nodes that are upstream from `always` because
+ // `always` will never have non-null intent.
+ assert(destinationNode == NullabilityNode.always);
}
}
@@ -58,46 +88,27 @@
var destinations =
edges.where((edge) => edge.primarySource == source).map((edge) {
var suffixes = <Object>[];
- if (getUnconditionalUpstreamNodes(edge.destinationNode)
- .contains(source)) {
- suffixes.add('unconditional');
+ if (edge.hard) {
+ suffixes.add('hard');
}
suffixes.addAll(edge.guards);
var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
return '${edge.destinationNode}$suffix';
});
- var suffixes = <String>[];
- if (source.isNullable) {
- suffixes.add('nullable');
- }
- if (source.hasNonNullIntent) {
- suffixes.add('non-null intent');
- }
- var suffix = suffixes.isNotEmpty ? ' (${suffixes.join(', ')})' : '';
- print('$source$suffix -> ${destinations.join(', ')}');
+ var state = source._state;
+ print('$source ($state) -> ${destinations.join(', ')}');
}
}
- /// Iterates through all nodes that are "downstream" of [node] (i.e. if
- /// [node] is nullable, then all the iterated nodes will either have to be
- /// nullable, or null checks will have to be added).
- ///
- /// There is no guarantee of uniqueness of the iterated nodes.
- Iterable<NullabilityNode> getDownstreamNodes(NullabilityNode node) =>
- _getDownstreamEdges(node)
- .where((edge) => edge.primarySource == node)
- .map((edge) => edge.destinationNode);
-
/// Iterates through all nodes that are "upstream" of [node] due to
/// unconditional control flow.
///
/// There is no guarantee of uniqueness of the iterated nodes.
- Iterable<NullabilityNode> getUnconditionalUpstreamNodes(
- NullabilityNode node) {
+ Iterable<NullabilityEdge> getUpstreamEdges(NullabilityNode node) {
if (node is NullabilityNodeMutable) {
- return node._unconditionalUpstreamNodes;
+ return node._upstreamEdges;
} else if (node == NullabilityNode.never) {
- return _unconditionalUpstreamFromNever;
+ return _upstreamFromNever;
} else {
// No nodes are upstream from `always`.
assert(node == NullabilityNode.always);
@@ -128,11 +139,12 @@
/// Determines the nullability of each node in the graph by propagating
/// nullability information from one node to another.
void propagate() {
+ if (_debugBeforePropagation) debugDump();
_propagateUpstream();
_propagateDownstream();
}
- Iterable<_NullabilityEdge> _getDownstreamEdges(NullabilityNode node) {
+ Iterable<NullabilityEdge> _getDownstreamEdges(NullabilityNode node) {
if (node is NullabilityNodeMutable) {
return node._downstreamEdges;
} else if (node == NullabilityNode.always) {
@@ -146,15 +158,19 @@
/// Propagates nullability downstream.
void _propagateDownstream() {
- var pendingEdges = <_NullabilityEdge>[]..addAll(_downstreamFromAlways);
+ var pendingEdges = <NullabilityEdge>[]..addAll(_downstreamFromAlways);
+ for (var node in _pendingDownstreamNodes) {
+ pendingEdges.addAll(node._downstreamEdges);
+ }
+ _pendingDownstreamNodes.clear();
var pendingSubstitutions = <NullabilityNodeForSubstitution>[];
while (true) {
nextEdge:
while (pendingEdges.isNotEmpty) {
var edge = pendingEdges.removeLast();
var node = edge.destinationNode;
- if (node.hasNonNullIntent) {
- // Non-null intent nodes are never made nullable; a null check will need
+ if (node._state == _NullabilityState.nonNullable) {
+ // Non-nullable nodes are never made nullable; a null check will need
// to be added instead.
continue;
}
@@ -164,7 +180,8 @@
continue nextEdge;
}
}
- if (node is NullabilityNodeMutable && node._becomeNullable()) {
+ if (node is NullabilityNodeMutable && !node.isNullable) {
+ node._state = _NullabilityState.ordinaryNullable;
// Was not previously nullable, so we need to propagate.
pendingEdges.addAll(node._downstreamEdges);
if (node is NullabilityNodeForSubstitution) {
@@ -181,25 +198,24 @@
}
// Heuristically choose to propagate to the inner node since this seems
// to lead to better quality migrations.
- pendingEdges.add(_NullabilityEdge(node.innerNode, const []));
+ pendingEdges.add(NullabilityEdge(node.innerNode, const [], false));
}
}
/// Propagates non-null intent upstream along unconditional control flow
/// lines.
void _propagateUpstream() {
- var pendingNodes = <NullabilityNode>[]
- ..addAll(_unconditionalUpstreamFromNever);
- while (pendingNodes.isNotEmpty) {
- var node = pendingNodes.removeLast();
- if (node == NullabilityNode.always) {
- // The "always" node cannot have non-null intent.
- continue;
- }
- if (node is NullabilityNodeMutable && node._setNonNullIntent()) {
+ var pendingEdges = <NullabilityEdge>[]..addAll(_upstreamFromNever);
+ while (pendingEdges.isNotEmpty) {
+ var edge = pendingEdges.removeLast();
+ if (!edge.hard) continue;
+ var node = edge.primarySource;
+ if (node is NullabilityNodeMutable &&
+ node._state == _NullabilityState.undetermined) {
+ node._state = _NullabilityState.nonNullable;
// Was not previously in the set of non-null intent nodes, so we need to
// propagate.
- pendingNodes.addAll(node._unconditionalUpstreamNodes);
+ pendingEdges.addAll(node._upstreamEdges);
}
}
}
@@ -235,8 +251,9 @@
/// inferred type rather than assuming `dynamic`.
factory NullabilityNode.forInferredDynamicType(
NullabilityGraph graph, int offset) {
- var node = _NullabilityNodeSimple('inferredDynamic($offset)');
- graph.connect(NullabilityNode.always, node, unconditional: true);
+ var node = _NullabilityNodeSimple('inferredDynamic($offset)',
+ initialState: _NullabilityState.ordinaryNullable);
+ graph._pendingDownstreamNodes.add(node);
return node;
}
@@ -281,8 +298,6 @@
String get debugSuffix =>
this == always ? '?' : this == never ? '' : '?($this)';
- bool get hasNonNullIntent;
-
/// After nullability propagation, this getter can be used to query whether
/// the type associated with this node should be considered nullable.
bool get isNullable;
@@ -293,6 +308,8 @@
String get _debugPrefix;
+ _NullabilityState get _state;
+
/// Records the fact that an invocation was made to a function with named
/// parameters, and the named parameter associated with this node was not
/// supplied.
@@ -305,7 +322,7 @@
void recordNonNullIntent(
List<NullabilityNode> guards, NullabilityGraph graph) {
- graph.connect(this, NullabilityNode.never, unconditional: true);
+ graph.connect(this, NullabilityNode.never, hard: true);
}
String toString() {
@@ -348,9 +365,8 @@
NullabilityNode destinationNode,
List<NullabilityNode> guards,
NullabilityGraph graph,
- bool inConditionalControlFlow) {
- graph.connect(sourceNode, destinationNode,
- guards: guards, unconditional: !inConditionalControlFlow);
+ {@required bool hard}) {
+ graph.connect(sourceNode, destinationNode, guards: guards, hard: hard);
}
}
@@ -400,70 +416,27 @@
/// Nearly all nullability nodes derive from this class; the only exceptions are
/// the fixed nodes [NullabilityNode.always] and [NullabilityNode.never].
abstract class NullabilityNodeMutable extends NullabilityNode {
- bool _isNullable = false;
+ _NullabilityState _state;
- bool _hasNonNullIntent = false;
-
- /// List of [_NullabilityEdge] objects describing this node's relationship to
+ /// List of [NullabilityEdge] objects describing this node's relationship to
/// other nodes that are "downstream" from it (meaning that if a key node is
/// nullable, then all the nodes in the corresponding value will either have
/// to be nullable, or null checks will have to be added).
- final _downstreamEdges = <_NullabilityEdge>[];
+ final _downstreamEdges = <NullabilityEdge>[];
/// List of nodes that are "upstream" from this node via unconditional control
/// flow (meaning that if a node in the list is nullable, then there exists
/// code that is unguarded by an "if" statement that indicates that this node
/// will have to be nullable, or null checks will have to be added).
- final _unconditionalUpstreamNodes = <NullabilityNode>[];
+ final _upstreamEdges = <NullabilityEdge>[];
- NullabilityNodeMutable._() : super._();
+ NullabilityNodeMutable._(
+ {_NullabilityState initialState: _NullabilityState.undetermined})
+ : _state = initialState,
+ super._();
@override
- bool get hasNonNullIntent => _hasNonNullIntent;
-
- @override
- bool get isNullable => _isNullable;
-
- /// During nullability propagation, this method marks the type as nullable, or
- /// does nothing if the type was already nullable.
- ///
- /// Return value indicates whether a change was made.
- bool _becomeNullable() {
- if (_isNullable) return false;
- _isNullable = true;
- return true;
- }
-
- /// During nullability propagation, this method marks the type as having
- /// non-null intent, or does nothing if the type was already marked as having
- /// non-null intent.
- ///
- /// Return value indicates whether a change was made.
- bool _setNonNullIntent() {
- if (_hasNonNullIntent) return false;
- _hasNonNullIntent = true;
- return true;
- }
-}
-
-/// Data structure to keep track of the relationship from one [NullabilityNode]
-/// object to another [NullabilityNode] that is "downstream" from it (meaning
-/// that if the former node is nullable, then the latter node will either have
-/// to be nullable, or null checks will have to be added).
-class _NullabilityEdge {
- /// The node that is downstream.
- final NullabilityNode destinationNode;
-
- /// A set of source nodes. By convention, the first node is the primary
- /// source and the other nodes are "guards". The destination node will only
- /// need to be made nullable if all the source nodes are nullable.
- final List<NullabilityNode> sources;
-
- _NullabilityEdge(this.destinationNode, this.sources);
-
- Iterable<NullabilityNode> get guards => sources.skip(1);
-
- NullabilityNode get primarySource => sources.first;
+ bool get isNullable => _state.isNullable;
}
class _NullabilityNodeImmutable extends NullabilityNode {
@@ -476,12 +449,50 @@
_NullabilityNodeImmutable(this._debugPrefix, this.isNullable) : super._();
@override
- bool get hasNonNullIntent => !isNullable;
+ _NullabilityState get _state => isNullable
+ ? _NullabilityState.ordinaryNullable
+ : _NullabilityState.nonNullable;
}
class _NullabilityNodeSimple extends NullabilityNodeMutable {
@override
final String _debugPrefix;
- _NullabilityNodeSimple(this._debugPrefix) : super._();
+ _NullabilityNodeSimple(this._debugPrefix,
+ {_NullabilityState initialState: _NullabilityState.undetermined})
+ : super._(initialState: initialState);
+}
+
+/// State of a nullability node.
+class _NullabilityState {
+ /// State of a nullability node whose nullability hasn't been decided yet.
+ static const undetermined = _NullabilityState._('undetermined', false);
+
+ /// State of a nullability node that has been determined to be non-nullable
+ /// by propagating upstream.
+ static const nonNullable = _NullabilityState._('non-nullable', false);
+
+ /// State of a nullability node that has been determined to be nullable by
+ /// propagating downstream.
+ static const ordinaryNullable =
+ _NullabilityState._('ordinary nullable', true);
+
+ /// State of a nullability node that has been determined to be nullable by
+ /// propagating upstream from a contravariant use of a generic.
+ static const exactNullable = _NullabilityState._('exact nullable', true);
+
+ /// Name of the state (for use in debugging).
+ final String name;
+
+ /// Indicates whether the given state should be considered nullable.
+ ///
+ /// After propagation, any nodes that remain in the undetermined state are
+ /// considered to be non-nullable, so this field is returns `false` for nodes
+ /// in that state.
+ final bool isNullable;
+
+ const _NullabilityState._(this.name, this.isNullable);
+
+ @override
+ String toString() => name;
}
diff --git a/pkg/analysis_server/lib/src/nullability/provisional_api.dart b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
index 36b741b..02b8921 100644
--- a/pkg/analysis_server/lib/src/nullability/provisional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
@@ -13,9 +13,6 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:meta/meta.dart';
-export 'package:analysis_server/src/nullability/transitional_api.dart'
- show NamedNoDefaultParameterHeuristic, NullabilityMigrationAssumptions;
-
/// Kinds of fixes that might be performed by nullability migration.
class NullabilityFixKind {
/// An import needs to be added.
@@ -73,12 +70,9 @@
/// as far as possible even though the migration algorithm is not yet
/// complete. TODO(paulberry): remove this mode once the migration algorithm
/// is fully implemented.
- NullabilityMigration(this.listener,
- {bool permissive: false,
- analyzer.NullabilityMigrationAssumptions assumptions:
- const analyzer.NullabilityMigrationAssumptions()})
- : _analyzerMigration = analyzer.NullabilityMigration(
- permissive: permissive, assumptions: assumptions);
+ NullabilityMigration(this.listener, {bool permissive: false})
+ : _analyzerMigration =
+ analyzer.NullabilityMigration(permissive: permissive);
void finish() {
for (var entry in _analyzerMigration.finish().entries) {
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
index f49c106..69b4d89 100644
--- a/pkg/analysis_server/lib/src/nullability/transitional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
@@ -3,10 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/graph_builder.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -89,38 +89,6 @@
}
}
-/// Enum encapsulating the various options proposed at
-/// https://github.com/dart-lang/language/issues/156#issuecomment-460525075
-enum DefaultParameterHandling {
- /// Option 2: Add required named parameters
- ///
- /// - `{int x}` implicitly means `x` is required
- /// - required-ness goes into the function type:
- /// `int Function({required int x})`
- /// - `{required int? x}` is allowed
- /// - means that something must be passed
- /// - passing null is allowed
- /// - `{int x = 3}` is allowed
- /// - `x` is optional
- /// - passing null to it is an error
- /// - passing nothing to it results in it getting the default value
- /// - `[int x]` is an error
- /// - `[int x = 3]` is allowed
- option2_addRequiredNamedParameters,
-}
-
-/// Enum representing the possible heuristics for handling named parameters with
-/// no default value.
-enum NamedNoDefaultParameterHeuristic {
- /// Assume that the parameter should be considered nullable, unless the user
- /// has explicitly marked it as `@required`.
- assumeNullable,
-
- /// Assume that the parameter should be considered required, unless the user
- /// has explicitly marked it as nullable.
- assumeRequired,
-}
-
/// Transitional migration API.
///
/// Usage: pass each input source file to [prepareInput]. Then pass each input
@@ -132,8 +100,6 @@
class NullabilityMigration {
final bool _permissive;
- final NullabilityMigrationAssumptions assumptions;
-
final Variables _variables;
final NullabilityGraph _graph;
@@ -144,13 +110,10 @@
/// as far as possible even though the migration algorithm is not yet
/// complete. TODO(paulberry): remove this mode once the migration algorithm
/// is fully implemented.
- NullabilityMigration(
- {bool permissive: false,
- NullabilityMigrationAssumptions assumptions:
- const NullabilityMigrationAssumptions()})
- : this._(permissive, assumptions, NullabilityGraph());
+ NullabilityMigration({bool permissive: false})
+ : this._(permissive, NullabilityGraph());
- NullabilityMigration._(this._permissive, this.assumptions, this._graph)
+ NullabilityMigration._(this._permissive, this._graph)
: _variables = Variables(_graph);
Map<Source, List<PotentialModification>> finish() {
@@ -159,42 +122,16 @@
}
void prepareInput(CompilationUnit unit, TypeProvider typeProvider) {
- unit.accept(ConstraintVariableGatherer(
- _variables,
- unit.declaredElement.source,
- _permissive,
- assumptions,
- _graph,
- typeProvider));
+ unit.accept(NodeBuilder(_variables, unit.declaredElement.source,
+ _permissive, _graph, typeProvider));
}
void processInput(CompilationUnit unit, TypeProvider typeProvider) {
- unit.accept(ConstraintGatherer(typeProvider, _variables, _graph,
- unit.declaredElement.source, _permissive, assumptions));
+ unit.accept(GraphBuilder(typeProvider, _variables, _graph,
+ unit.declaredElement.source, _permissive));
}
}
-/// Assumptions affecting the behavior of the nullability migration tool.
-///
-/// These options generally reflect design decisions that have not yet been
-/// made. They don't reflect behavioral differences we would want to expose to
-/// the user.
-///
-/// TODO(paulberry): hardcode these assumptions once decisions have been made.
-class NullabilityMigrationAssumptions {
- /// Handling of default parameters.
- final DefaultParameterHandling defaultParameterHandling;
-
- /// Heuristic for handling named parameters with no default value.
- final NamedNoDefaultParameterHeuristic namedNoDefaultParameterHeuristic;
-
- const NullabilityMigrationAssumptions(
- {this.defaultParameterHandling:
- DefaultParameterHandling.option2_addRequiredNamedParameters,
- this.namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable});
-}
-
/// Records information about the possible addition of an import
/// to the source code.
class PotentiallyAddImport extends PotentialModification {
@@ -274,7 +211,7 @@
@override
DecoratedType decoratedElementType(Element element, {bool create: false}) =>
_decoratedElementTypes[element] ??= create
- ? DecoratedType.forElement(element, _graph)
+ ? DecoratedType.forElement(element)
: throw StateError('No element found');
@override
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index 2937dee..4aad023 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -14,6 +14,7 @@
import 'package:analysis_server/src/server/detachable_filesystem_manager.dart';
import 'package:analysis_server/src/server/dev_server.dart';
import 'package:analysis_server/src/server/diagnostic_server.dart';
+import 'package:analysis_server/src/server/features.dart';
import 'package:analysis_server/src/server/http_server.dart';
import 'package:analysis_server/src/server/lsp_stdio_server.dart';
import 'package:analysis_server/src/server/stdio_server.dart';
@@ -29,6 +30,7 @@
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/plugin/resolver_provider.dart';
import 'package:args/args.dart';
+import 'package:front_end/src/fasta/compiler_context.dart';
import 'package:linter/src/rules.dart' as linter;
import 'package:telemetry/crash_reporting.dart';
import 'package:telemetry/telemetry.dart' as telemetry;
@@ -195,6 +197,18 @@
static const String DARTPAD_OPTION = "dartpad";
/**
+ * The name of the option to disable the completion feature.
+ */
+ static const String DISABLE_SERVER_FEATURE_COMPLETION =
+ "disable-server-feature-completion";
+
+ /**
+ * The name of the option to disable the search feature.
+ */
+ static const String DISABLE_SERVER_FEATURE_SEARCH =
+ "disable-server-feature-search";
+
+ /**
* The name of the option used to enable instrumentation.
*/
static const String ENABLE_INSTRUMENTATION_OPTION = "enable-instrumentation";
@@ -354,6 +368,17 @@
UriContributor.suggestFilePaths = false;
}
+ {
+ bool disableCompletion = results[DISABLE_SERVER_FEATURE_COMPLETION];
+ bool disableSearch = results[DISABLE_SERVER_FEATURE_SEARCH];
+ if (disableCompletion || disableSearch) {
+ analysisServerOptions.featureSet = FeatureSet(
+ completion: !disableCompletion,
+ search: !disableSearch,
+ );
+ }
+ }
+
if (results[HELP_OPTION]) {
_printUsage(parser.parser, analytics, fromHelp: true);
return null;
@@ -404,19 +429,21 @@
}
}
- if (analysisServerOptions.useLanguageServerProtocol) {
- startLspServer(results, analysisServerOptions, dartSdkManager,
- instrumentationService, diagnosticServerPort);
- } else {
- startAnalysisServer(
- results,
- analysisServerOptions,
- parser,
- dartSdkManager,
- instrumentationService,
- analytics,
- diagnosticServerPort);
- }
+ CompilerContext.runWithDefaultOptions((_) async {
+ if (analysisServerOptions.useLanguageServerProtocol) {
+ startLspServer(results, analysisServerOptions, dartSdkManager,
+ instrumentationService, diagnosticServerPort);
+ } else {
+ startAnalysisServer(
+ results,
+ analysisServerOptions,
+ parser,
+ dartSdkManager,
+ instrumentationService,
+ analytics,
+ diagnosticServerPort);
+ }
+ });
}
void startAnalysisServer(
@@ -632,6 +659,10 @@
help: 'enable DartPad specific functionality',
defaultsTo: false,
hide: true);
+ parser.addFlag(DISABLE_SERVER_FEATURE_COMPLETION,
+ help: 'disable all completion features', defaultsTo: false, hide: true);
+ parser.addFlag(DISABLE_SERVER_FEATURE_SEARCH,
+ help: 'disable all search features', defaultsTo: false, hide: true);
parser.addFlag(ENABLE_INSTRUMENTATION_OPTION,
help: "enable sending instrumentation information to a server",
defaultsTo: false,
diff --git a/pkg/analysis_server/lib/src/server/features.dart b/pkg/analysis_server/lib/src/server/features.dart
new file mode 100644
index 0000000..fd02aa1
--- /dev/null
+++ b/pkg/analysis_server/lib/src/server/features.dart
@@ -0,0 +1,17 @@
+// 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.
+
+/// The set of features enabled in a server session.
+///
+/// When some features are not enabled, the server might avoid doing work
+/// that is only required for these features.
+class FeatureSet {
+ final bool completion;
+ final bool search;
+
+ FeatureSet({
+ this.completion = true,
+ this.search = true,
+ });
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index 82555b4..1d86d94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -11,6 +11,7 @@
show DartCompletionRequestImpl;
import 'package:analysis_server/src/services/correction/name_suggestion.dart';
import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
/**
@@ -59,17 +60,25 @@
// Resolution not needed for this completion
AstNode node = request.target.containingNode;
+ int offset = request.target.offset;
+
+ // Use the refined node.
+ if (node is FormalParameterList) {
+ node = CompletionTarget.findFormalParameter(node, offset);
+ }
String strName = null;
if (node is ExpressionStatement) {
- if (node.expression is Identifier) {
- strName = _getStringName(node.expression as Identifier);
+ var expression = node.expression;
+ if (expression is Identifier) {
+ strName = _getStringName(expression);
}
+ } else if (node is SimpleFormalParameter) {
+ var identifier = _formalParameterTypeIdentifier(node);
+ strName = _getStringName(identifier);
} else if (node is VariableDeclarationList) {
- TypeAnnotation typeAnnotation = node.type;
- if (typeAnnotation is TypeName) {
- strName = _getStringName(typeAnnotation.name);
- }
+ var identifier = _typeAnnotationIdentifier(node.type);
+ strName = _getStringName(identifier);
} else if (node is TopLevelVariableDeclaration) {
// The parser parses 'Foo ' and 'Foo ;' differently, resulting in the
// following.
@@ -79,9 +88,8 @@
VariableDeclarationList varDeclarationList = node.variables;
TypeAnnotation typeAnnotation = varDeclarationList.type;
if (typeAnnotation != null) {
- if (typeAnnotation is TypeName) {
- strName = _getStringName(typeAnnotation.name);
- }
+ var identifier = _typeAnnotationIdentifier(typeAnnotation);
+ strName = _getStringName(identifier);
} else {
NodeList<VariableDeclaration> varDeclarations =
varDeclarationList.variables;
@@ -95,9 +103,8 @@
return const <CompletionSuggestion>[];
}
- var doIncludePrivateVersion = !optype.inMethodBody &&
- !optype.inFunctionBody &&
- !optype.inConstructorBody;
+ var doIncludePrivateVersion =
+ optype.inFieldDeclaration || optype.inTopLevelVariableDeclaration;
List<String> variableNameSuggestions = getCamelWordCombinations(strName);
variableNameSuggestions.remove(strName);
@@ -119,4 +126,22 @@
}
return const <CompletionSuggestion>[];
}
+
+ static Identifier _formalParameterTypeIdentifier(FormalParameter node) {
+ if (node is SimpleFormalParameter) {
+ var type = node.type;
+ if (type != null) {
+ return _typeAnnotationIdentifier(type);
+ }
+ return node.identifier;
+ }
+ return null;
+ }
+
+ static Identifier _typeAnnotationIdentifier(TypeAnnotation type) {
+ if (type is TypeName) {
+ return type.name;
+ }
+ return null;
+ }
}
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index d24108b..e46f525 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -205,6 +205,13 @@
'dart.assist.convert.ifElseToConditional',
30,
"Replace 'if-else' with conditional ('c ? x : y')");
+ static const SORT_CHILD_PROPERTY_LAST = const AssistKind(
+ 'dart.assist.sort.child.properties.last',
+ 30,
+ "Move child property to end of arguments",
+ associatedErrorCodes: <String>[
+ 'sort_child_properties_last',
+ ]);
static const SPLIT_AND_CONDITION = const AssistKind(
'dart.assist.splitIfConjunction', 30, "Split && condition");
static const SPLIT_VARIABLE_DECLARATION = const AssistKind(
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 b420fd0..b465c69 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -145,6 +145,7 @@
await _addProposal_reparentFlutterList();
await _addProposal_replaceConditionalWithIfElse();
await _addProposal_replaceIfElseWithConditional();
+ await _addProposal_sortChildPropertyLast();
await _addProposal_splitAndCondition();
await _addProposal_splitVariableDeclaration();
await _addProposal_surroundWith();
@@ -3547,6 +3548,47 @@
}
}
+ Future<void> _addProposal_sortChildPropertyLast() async {
+ NamedExpression childProp = flutter.findNamedExpression(node, 'child');
+ if (childProp == null) {
+ childProp = flutter.findNamedExpression(node, 'children');
+ }
+ if (childProp == null) {
+ return;
+ }
+
+ var parent = childProp.parent?.parent;
+ if (parent is! InstanceCreationExpression ||
+ !flutter.isWidgetCreation(parent)) {
+ return;
+ }
+
+ InstanceCreationExpression creationExpression = parent;
+ var args = creationExpression.argumentList;
+
+ var last = args.arguments.last;
+ if (last == childProp) {
+ // Already sorted.
+ return;
+ }
+
+ var changeBuilder = _newDartChangeBuilder();
+ await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+ var start = childProp.beginToken.previous.end;
+ var end = childProp.endToken.next.end;
+ var childRange = range.startOffsetEndOffset(start, end);
+
+ var childText = utils.getRangeText(childRange);
+ builder.addSimpleReplacement(childRange, '');
+ builder.addSimpleInsertion(last.end + 1, childText);
+
+ changeBuilder.setSelection(new Position(file, last.end + 1));
+ });
+
+ _addAssistFromBuilder(
+ changeBuilder, DartAssistKind.SORT_CHILD_PROPERTY_LAST);
+ }
+
Future<void> _addProposal_splitAndCondition() async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 7ca77e9..adfc446 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/error/error.dart';
@@ -119,7 +120,16 @@
@override
final AnalysisError error;
- DartFixContextImpl(this.workspace, this.resolveResult, this.error);
+ final List<TopLevelDeclaration> Function(String name)
+ getTopLevelDeclarationsFunction;
+
+ DartFixContextImpl(this.workspace, this.resolveResult, this.error,
+ this.getTopLevelDeclarationsFunction);
+
+ @override
+ List<TopLevelDeclaration> getTopLevelDeclarations(String name) {
+ return getTopLevelDeclarationsFunction(name);
+ }
}
/// An enumeration of quick fix kinds found in a Dart file.
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
new file mode 100644
index 0000000..ef4b987
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/fix/dart/top_level_declarations.dart
@@ -0,0 +1,107 @@
+// 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:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
+
+/// Information about a single top-level declaration.
+class TopLevelDeclaration {
+ /// The path of the library that exports this declaration.
+ final String path;
+
+ /// The URI of the library that exports this declaration.
+ final Uri uri;
+
+ final TopLevelDeclarationKind kind;
+
+ final String name;
+
+ /// Is `true` if the declaration is exported, not declared in the [path].
+ final bool isExported;
+
+ TopLevelDeclaration(
+ this.path,
+ this.uri,
+ this.kind,
+ this.name,
+ this.isExported,
+ );
+
+ @override
+ String toString() => '($path, $uri, $kind, $name, $isExported)';
+}
+
+/// Kind of a top-level declaration.
+///
+/// We don't need it to be precise, just enough to support quick fixes.
+enum TopLevelDeclarationKind { type, function, variable }
+
+class TopLevelDeclarationsProvider {
+ final DeclarationsTracker tracker;
+
+ TopLevelDeclarationsProvider(this.tracker);
+
+ void doTrackerWork() {
+ while (tracker.hasWork) {
+ tracker.doWork();
+ }
+ }
+
+ List<TopLevelDeclaration> get(
+ AnalysisContext analysisContext,
+ String path,
+ String name,
+ ) {
+ var declarations = <TopLevelDeclaration>[];
+
+ void addDeclarations(Library library) {
+ for (var declaration in library.declarations) {
+ if (declaration.name != name) continue;
+
+ var kind = _getTopKind(declaration.kind);
+ if (kind == null) continue;
+
+ declarations.add(
+ TopLevelDeclaration(
+ library.path,
+ library.uri,
+ kind,
+ name,
+ declaration.locationLibraryUri != library.uri,
+ ),
+ );
+ }
+ }
+
+ var declarationsContext = tracker.getContext(analysisContext);
+ var libraries = declarationsContext.getLibraries(path);
+ libraries.context.forEach(addDeclarations);
+ libraries.dependencies.forEach(addDeclarations);
+ libraries.sdk.forEach(addDeclarations);
+
+ return declarations;
+ }
+
+ TopLevelDeclarationKind _getTopKind(DeclarationKind kind) {
+ switch (kind) {
+ case DeclarationKind.CLASS:
+ case DeclarationKind.CLASS_TYPE_ALIAS:
+ case DeclarationKind.ENUM:
+ case DeclarationKind.FUNCTION_TYPE_ALIAS:
+ case DeclarationKind.MIXIN:
+ return TopLevelDeclarationKind.type;
+ break;
+ case DeclarationKind.FUNCTION:
+ return TopLevelDeclarationKind.function;
+ break;
+ case DeclarationKind.GETTER:
+ case DeclarationKind.SETTER:
+ case DeclarationKind.VARIABLE:
+ return TopLevelDeclarationKind.variable;
+ break;
+ default:
+ return null;
+ }
+ }
+}
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 dc43fd4..4cd9e33 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -10,6 +10,7 @@
import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
import 'package:analysis_server/src/services/completion/dart/utilities.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/levenshtein.dart';
import 'package:analysis_server/src/services/correction/namespace.dart';
import 'package:analysis_server/src/services/correction/strings.dart';
@@ -26,7 +27,6 @@
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
@@ -105,7 +105,11 @@
// For each fix, put the fix into the HashMap.
for (int i = 0; i < allAnalysisErrors.length; i++) {
final FixContext fixContextI = new DartFixContextImpl(
- context.workspace, context.resolveResult, allAnalysisErrors[i]);
+ context.workspace,
+ context.resolveResult,
+ allAnalysisErrors[i],
+ (name) => [],
+ );
final FixProcessor processorI = new FixProcessor(fixContextI);
final List<Fix> fixesListI = await processorI.compute();
for (Fix f in fixesListI) {
@@ -2412,7 +2416,7 @@
}
// may be there is an existing import,
// but it is with prefix and we don't use this prefix
- Set<Source> alreadyImportedWithPrefix = new Set<Source>();
+ var alreadyImportedWithPrefix = new Set<String>();
for (ImportElement imp in unitLibraryElement.imports) {
// prepare element
LibraryElement libraryElement = imp.importedLibrary;
@@ -2454,7 +2458,7 @@
libraryName = libraryElement.source.shortName;
}
// don't add this library again
- alreadyImportedWithPrefix.add(libraryElement.source);
+ alreadyImportedWithPrefix.add(libraryElement.source.fullName);
// update library
String newShowCode = 'show ${showNames.join(', ')}';
int offset = showCombinator.offset;
@@ -2473,25 +2477,21 @@
}
// Find new top-level declarations.
{
- var declarations = await session.getTopLevelDeclarations(name);
- for (TopLevelDeclarationInSource declaration in declarations) {
+ var declarations = await context.getTopLevelDeclarations(name);
+ for (var declaration in declarations) {
// Check the kind.
- if (!kinds2.contains(declaration.declaration.kind)) {
+ if (!kinds2.contains(declaration.kind)) {
continue;
}
// Check the source.
- Source librarySource = declaration.source;
- if (alreadyImportedWithPrefix.contains(librarySource)) {
- continue;
- }
- if (!_isSourceVisibleToLibrary(librarySource)) {
+ if (alreadyImportedWithPrefix.contains(declaration.path)) {
continue;
}
// Compute the fix kind.
FixKind fixKind;
- if (librarySource.isInSystemLibrary) {
+ if (declaration.uri.isScheme('dart')) {
fixKind = DartFixKind.IMPORT_LIBRARY_SDK;
- } else if (_isLibSrcPath(librarySource.fullName)) {
+ } else if (_isLibSrcPath(declaration.path)) {
// Bad: non-API.
fixKind = DartFixKind.IMPORT_LIBRARY_PROJECT3;
} else if (declaration.isExported) {
@@ -2503,8 +2503,8 @@
}
// Add the fix.
var relativeURI =
- _getRelativeURIFromLibrary(unitLibraryElement, librarySource);
- await _addFix_importLibrary(fixKind, librarySource.uri, relativeURI);
+ _getRelativeURIFromLibrary(unitLibraryElement, declaration.path);
+ await _addFix_importLibrary(fixKind, declaration.uri, relativeURI);
}
}
}
@@ -4246,21 +4246,20 @@
}
/**
- * Return the relative uri from the passed [library] to the passed
- * [source]. If the [source] is not in the LibraryElement, `null` is returned.
+ * Return the relative uri from the passed [library] to the given [path].
+ * If the [path] is not in the LibraryElement, `null` is returned.
*/
- String _getRelativeURIFromLibrary(LibraryElement library, Source source) {
+ String _getRelativeURIFromLibrary(LibraryElement library, String path) {
var librarySource = library?.librarySource;
if (librarySource == null) {
return null;
}
var pathCtx = resourceProvider.pathContext;
var libraryDirectory = pathCtx.dirname(librarySource.fullName);
- var sourceDirectory = pathCtx.dirname(source.fullName);
- if (pathCtx.isWithin(libraryDirectory, source.fullName) ||
+ var sourceDirectory = pathCtx.dirname(path);
+ if (pathCtx.isWithin(libraryDirectory, path) ||
pathCtx.isWithin(sourceDirectory, libraryDirectory)) {
- String relativeFile =
- pathCtx.relative(source.fullName, from: libraryDirectory);
+ String relativeFile = pathCtx.relative(path, from: libraryDirectory);
return pathCtx.split(relativeFile).join('/');
}
return null;
@@ -4469,30 +4468,6 @@
return false;
}
- /**
- * Return `true` if the [source] can be imported into current library.
- */
- bool _isSourceVisibleToLibrary(Source source) {
- String path = source.fullName;
-
- var contextRoot = context.resolveResult.session.analysisContext.contextRoot;
- if (contextRoot == null) {
- return true;
- }
-
- // We don't want to use private libraries of other packages.
- if (source.uri.isScheme('package') && _isLibSrcPath(path)) {
- return contextRoot.root.contains(path);
- }
-
- // We cannot use relative URIs to reference files outside of our package.
- if (source.uri.isScheme('file')) {
- return contextRoot.root.contains(path);
- }
-
- return true;
- }
-
bool _isToListMethodElement(MethodElement method) {
if (method.name != 'toList') {
return false;
diff --git a/pkg/analysis_server/lib/src/utilities/flutter.dart b/pkg/analysis_server/lib/src/utilities/flutter.dart
index b803440..867a30b 100644
--- a/pkg/analysis_server/lib/src/utilities/flutter.dart
+++ b/pkg/analysis_server/lib/src/utilities/flutter.dart
@@ -284,6 +284,7 @@
if (isWidgetExpression(node)) {
var parent = node.parent;
if (parent is ArgumentList ||
+ parent is ExpressionFunctionBody && parent.expression == node ||
parent is ListLiteral ||
parent is NamedExpression && parent.expression == node ||
parent is Statement) {
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 7dc1119..be52e27 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -3,9 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:io';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:path/path.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -20,6 +22,9 @@
@reflectiveTest
class AnalysisHoverTest extends AbstractAnalysisTest {
+ /// If windows, return 'C:', otherwise return the empty string
+ String get windowsCColon => Platform.isWindows ? 'C:' : '';
+
Future<HoverInformation> prepareHover(String search) {
int offset = findOffset(search);
return prepareHoverAt(offset);
@@ -87,7 +92,7 @@
expect(hover.length, 'new A.named()'.length);
// element
expect(hover.dartdoc, 'my doc');
- expect(hover.elementDescription, 'A.named() → A');
+ expect(hover.elementDescription, 'A A.named()');
expect(hover.elementKind, 'constructor');
}
@@ -116,10 +121,11 @@
expect(hover.offset, findOffset('A(0)'));
expect(hover.length, 'A(0)'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, '(const) A(int i) → A');
+ expect(hover.elementDescription, '(const) A A(int i)');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -141,10 +147,11 @@
expect(hover.offset, findOffset('A()'));
expect(hover.length, 'A()'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, '(new) A() → A');
+ expect(hover.elementDescription, '(new) A A()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -167,10 +174,11 @@
expect(hover.offset, findOffset('new A'));
expect(hover.length, 'new A()'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, 'A() → A');
+ expect(hover.elementDescription, 'A A()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -192,10 +200,11 @@
expect(hover.offset, findOffset('new A<String>'));
expect(hover.length, 'new A<String>()'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.dartdoc, isNull);
- expect(hover.elementDescription, 'A() → A<String>');
+ expect(hover.elementDescription, 'A<String> A()');
expect(hover.elementKind, 'constructor');
// types
expect(hover.staticType, isNull);
@@ -214,6 +223,7 @@
}
{
HoverInformation hover = await prepareHover('String>');
+ expect(hover.containingLibraryName, 'dart:core');
expect(hover.offset, findOffset('String>'));
expect(hover.length, 'String'.length);
expect(hover.elementKind, 'class');
@@ -329,11 +339,12 @@
''');
HoverInformation hover = await prepareHover('fff(int a');
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.containingClassDescription, isNull);
expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
- expect(hover.elementDescription, 'fff(int a, String b) → List<String>');
+ expect(hover.elementDescription, 'List<String> fff(int a, String b)');
expect(hover.elementKind, 'function');
// types
expect(hover.staticType, isNull);
@@ -356,7 +367,8 @@
''');
HoverInformation hover = await prepareHover('fff);');
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
@@ -494,11 +506,12 @@
''');
HoverInformation hover = await prepareHover('mmm(int a');
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.containingClassDescription, 'A');
expect(hover.dartdoc, '''doc aaa\ndoc bbb''');
- expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
expect(hover.elementKind, 'method');
// types
expect(hover.staticType, isNull);
@@ -523,13 +536,14 @@
expect(hover.offset, findOffset('mmm(42, '));
expect(hover.length, 'mmm'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
- expect(hover.elementDescription, 'mmm(int a, String b) → List<String>');
+ expect(hover.elementDescription, 'List<String> mmm(int a, String b)');
expect(hover.elementKind, 'method');
expect(hover.isDeprecated, isFalse);
// types
- expect(hover.staticType, '(int, String) → List<String>');
+ expect(hover.staticType, 'List<String> Function(int, String)');
expect(hover.propagatedType, isNull);
// no parameter
expect(hover.parameter, isNull);
@@ -548,7 +562,7 @@
HoverInformation hover = await prepareHover('test();');
// element
expect(hover.containingLibraryPath, testFile);
- expect(hover.elementDescription, 'test() → void');
+ expect(hover.elementDescription, 'void test()');
expect(hover.elementKind, 'method');
expect(hover.isDeprecated, isTrue);
}
@@ -571,15 +585,16 @@
expect(hover.offset, findOffset('transform(n'));
expect(hover.length, 'transform'.length);
// element
- expect(hover.containingLibraryName, 'my.library');
+ expect(hover.containingLibraryName,
+ normalize('$windowsCColon/project/bin/test.dart'));
expect(hover.containingLibraryPath, testFile);
expect(hover.elementDescription,
- 'Stream.transform<S>(StreamTransformer<int, S> streamTransformer) → Stream<S>');
+ 'Stream<S> Stream.transform<S>(StreamTransformer<int, S> streamTransformer)');
expect(hover.elementKind, 'method');
expect(hover.isDeprecated, isFalse);
// types
expect(hover.staticType,
- '(StreamTransformer<int, dynamic>) → Stream<dynamic>');
+ 'Stream<dynamic> Function(StreamTransformer<int, dynamic>)');
expect(hover.propagatedType, isNull);
// no parameter
expect(hover.parameter, isNull);
diff --git a/pkg/analysis_server/test/analysis_abstract.dart b/pkg/analysis_server/test/analysis_abstract.dart
index f4593b4..22715a4 100644
--- a/pkg/analysis_server/test/analysis_abstract.dart
+++ b/pkg/analysis_server/test/analysis_abstract.dart
@@ -135,6 +135,12 @@
handleSuccessfulRequest(request, handler: analysisHandler);
}
+ void doAllDeclarationsTrackerWork() {
+ while (server.declarationsTracker.hasWork) {
+ server.declarationsTracker.doWork();
+ }
+ }
+
/**
* Returns the offset of [search] in [testCode].
* Fails if not found.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index f30a1c3..228ec3f 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -2519,6 +2519,9 @@
void afterWatchEvent(WatchEvent event) {}
@override
+ void analysisOptionsUpdated(AnalysisDriver driver) {}
+
+ @override
void applyChangesToContext(Folder contextFolder, ChangeSet changeSet) {
AnalysisDriver driver = driverMap[contextFolder.path];
if (driver != null) {
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 2fa8a24..22a7245 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -40,6 +40,7 @@
}
''');
await waitForTasksFinished();
+ doAllDeclarationsTrackerWork();
List<AnalysisErrorFixes> errorFixes =
await _getFixesAt('Completer<String>');
expect(errorFixes, hasLength(1));
@@ -133,17 +134,20 @@
}
test_suggestImportFromDifferentAnalysisRoot() async {
- String asFileUri(String input) =>
- new Uri.file(convertPath(input)).toString();
newFolder('/aaa');
newFile('/aaa/.packages', content: '''
-aaa:${asFileUri('/aaa/lib')}
-bbb:${asFileUri('/bbb/lib')}
+aaa:${toUri('/aaa/lib')}
+bbb:${toUri('/bbb/lib')}
''');
- // Ensure that the target is analyzed as an implicit source.
- newFile('/aaa/lib/foo.dart', content: 'import "package:bbb/target.dart";');
+ newFile('/aaa/pubspec.yaml', content: r'''
+dependencies:
+ bbb: any
+''');
newFolder('/bbb');
+ newFile('/bbb/.packages', content: '''
+bbb:${toUri('/bbb/lib')}
+''');
newFile('/bbb/lib/target.dart', content: 'class Foo() {}');
handleSuccessfulRequest(
@@ -157,6 +161,7 @@
_addOverlay(testFile, testCode);
await waitForTasksFinished();
+ doAllDeclarationsTrackerWork();
List<String> fixes = (await _getFixesAt('Foo()'))
.single
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 0a7948b..7d5cd76 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -18,6 +18,24 @@
@reflectiveTest
class AnalysisErrorIntegrationTest
extends AbstractAnalysisServerIntegrationTest {
+ test_analysisRootDoesNotExist() async {
+ String packagePath = sourcePath('package');
+ String filePath = sourcePath('package/lib/test.dart');
+ String content = '''
+main() {
+ print(null) // parse error: missing ';'
+}''';
+ await sendServerSetSubscriptions([ServerService.STATUS]);
+ await sendAnalysisUpdateContent({filePath: AddContentOverlay(content)});
+ await sendAnalysisSetAnalysisRoots([packagePath], []);
+ await analysisFinished;
+
+ expect(currentAnalysisErrors[filePath], isList);
+ List<AnalysisError> errors = currentAnalysisErrors[filePath];
+ expect(errors, hasLength(1));
+ expect(errors[0].location.file, equals(filePath));
+ }
+
test_detect_simple_error() {
String pathname = sourcePath('test.dart');
writeFile(pathname, '''
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index e2f25af..ae7e4db 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -81,13 +81,13 @@
expect(info.length, equals(length));
if (isCore) {
expect(path.basename(info.containingLibraryPath), equals('core.dart'));
- expect(info.containingLibraryName, equals('dart.core'));
+ expect(info.containingLibraryName, equals('dart:core'));
} else if (isLocal || isLiteral) {
expect(info.containingLibraryPath, isNull);
expect(info.containingLibraryName, isNull);
} else {
expect(info.containingLibraryPath, equals(pathname));
- expect(info.containingLibraryName, equals('lib.test'));
+ expect(info.containingLibraryName, isNotNull);
}
if (docRegexp == null) {
expect(info.dartdoc, isNull);
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 6331b59..6df0629 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -31,6 +31,7 @@
## completion domain
- [ ] completion.availableSuggestions
+- [ ] completion.existingImports
- [ ] completion.getSuggestionDetails
- [x] completion.getSuggestions
- [x] completion.listTokenDetails
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 fe67037..65c2ca5 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1219,6 +1219,14 @@
* True if this is that last set of results that will be returned for the
* indicated completion.
*
+ * libraryFile: FilePath (optional)
+ *
+ * The library file that contains the file where completion was requested.
+ * The client might use it for example together with the existingImports
+ * notification to filter out available suggestions. If there were changes
+ * to existing imports in the library, the corresponding existingImports
+ * notification will be sent before the completion notification.
+ *
* includedSuggestionSets: List<IncludedSuggestionSet> (optional)
*
* References to AvailableSuggestionSet objects previously sent to the
@@ -1279,6 +1287,29 @@
_onCompletionAvailableSuggestions;
/**
+ * Reports existing imports in a library. This notification may be sent
+ * multiple times for a library. When a notification is processed, clients
+ * should replace any previous information for the library.
+ *
+ * Parameters
+ *
+ * file: FilePath
+ *
+ * The defining file of the library.
+ *
+ * imports: ExistingImports
+ *
+ * The existing imports in the library.
+ */
+ Stream<CompletionExistingImportsParams> onCompletionExistingImports;
+
+ /**
+ * Stream controller for [onCompletionExistingImports].
+ */
+ StreamController<CompletionExistingImportsParams>
+ _onCompletionExistingImports;
+
+ /**
* Perform a search for references to the element defined or referenced at
* the given offset in the given file.
*
@@ -2702,6 +2733,10 @@
new StreamController<CompletionAvailableSuggestionsParams>(sync: true);
onCompletionAvailableSuggestions =
_onCompletionAvailableSuggestions.stream.asBroadcastStream();
+ _onCompletionExistingImports =
+ new StreamController<CompletionExistingImportsParams>(sync: true);
+ onCompletionExistingImports =
+ _onCompletionExistingImports.stream.asBroadcastStream();
_onSearchResults = new StreamController<SearchResultsParams>(sync: true);
onSearchResults = _onSearchResults.stream.asBroadcastStream();
_onExecutionLaunchData =
@@ -2804,6 +2839,12 @@
new CompletionAvailableSuggestionsParams.fromJson(
decoder, 'params', params));
break;
+ case "completion.existingImports":
+ outOfTestExpect(params, isCompletionExistingImportsParams);
+ _onCompletionExistingImports.add(
+ new CompletionExistingImportsParams.fromJson(
+ decoder, 'params', params));
+ break;
case "search.results":
outOfTestExpect(params, isSearchResultsParams);
_onSearchResults
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 23e34a7..70dc041 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -560,6 +560,29 @@
new MatchesEnum("ExecutionService", ["LAUNCH_DATA"]);
/**
+ * ExistingImport
+ *
+ * {
+ * "uri": int
+ * "elements": List<int>
+ * }
+ */
+final Matcher isExistingImport = new LazyMatcher(() => new MatchesJsonObject(
+ "ExistingImport", {"uri": isInt, "elements": isListOf(isInt)}));
+
+/**
+ * ExistingImports
+ *
+ * {
+ * "elements": ImportedElementSet
+ * "imports": List<ExistingImport>
+ * }
+ */
+final Matcher isExistingImports = new LazyMatcher(() => new MatchesJsonObject(
+ "ExistingImports",
+ {"elements": isImportedElementSet, "imports": isListOf(isExistingImport)}));
+
+/**
* FileKind
*
* enum {
@@ -948,6 +971,22 @@
"ImplementedMember", {"offset": isInt, "length": isInt}));
/**
+ * ImportedElementSet
+ *
+ * {
+ * "strings": List<String>
+ * "uris": List<int>
+ * "names": List<int>
+ * }
+ */
+final Matcher isImportedElementSet = new LazyMatcher(() =>
+ new MatchesJsonObject("ImportedElementSet", {
+ "strings": isListOf(isString),
+ "uris": isListOf(isInt),
+ "names": isListOf(isInt)
+ }));
+
+/**
* ImportedElements
*
* {
@@ -2192,6 +2231,18 @@
}));
/**
+ * completion.existingImports params
+ *
+ * {
+ * "file": FilePath
+ * "imports": ExistingImports
+ * }
+ */
+final Matcher isCompletionExistingImportsParams = new LazyMatcher(() =>
+ new MatchesJsonObject("completion.existingImports params",
+ {"file": isFilePath, "imports": isExistingImports}));
+
+/**
* completion.getSuggestionDetails params
*
* {
@@ -2288,6 +2339,7 @@
* "replacementLength": int
* "results": List<CompletionSuggestion>
* "isLast": bool
+ * "libraryFile": optional FilePath
* "includedSuggestionSets": optional List<IncludedSuggestionSet>
* "includedElementKinds": optional List<ElementKind>
* "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -2301,6 +2353,7 @@
"results": isListOf(isCompletionSuggestion),
"isLast": isBool
}, optionalFields: {
+ "libraryFile": isFilePath,
"includedSuggestionSets": isListOf(isIncludedSuggestionSet),
"includedElementKinds": isListOf(isElementKind),
"includedSuggestionRelevanceTags":
diff --git a/pkg/analysis_server/test/lsp/cancel_request_test.dart b/pkg/analysis_server/test/lsp/cancel_request_test.dart
new file mode 100644
index 0000000..033f671
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/cancel_request_test.dart
@@ -0,0 +1,54 @@
+// 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/lsp_protocol/protocol_generated.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';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(CancelRequestTest);
+ });
+}
+
+@reflectiveTest
+class CancelRequestTest extends AbstractLspAnalysisServerTest {
+ test_cancel() async {
+ final content = '''
+main() {
+ InOtherF^
+}
+ ''';
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await initialize();
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+
+ // Create a completion request that we'll cancel.
+ final completionRequest = makeRequest(
+ Method.textDocument_completion,
+ new CompletionParams(
+ null,
+ new TextDocumentIdentifier(mainFileUri.toString()),
+ positionFromMarker(content),
+ ),
+ );
+ // And a request to cancel it.
+ final cancelNotification = makeNotification(
+ Method.cancelRequest, new CancelParams(completionRequest.id));
+
+ // Send both (without waiting for the results of the first).
+ final completionRequestFuture = sendRequestToServer(completionRequest);
+ await sendNotificationToServer(cancelNotification);
+
+ final result = await completionRequestFuture;
+ expect(result.result, isNull);
+ expect(result.error, isNotNull);
+ expect(result.error, isResponseError(ErrorCodes.RequestCancelled));
+ }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_source_test.dart b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
index 22c11ab..fb1daa5 100644
--- a/pkg/analysis_server/test/lsp/code_actions_source_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_source_test.dart
@@ -37,8 +37,8 @@
''';
await newFile(mainFilePath, content: content);
await initialize(
- workspaceCapabilities:
- withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+ workspaceCapabilities: withApplyEditSupport(
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -95,7 +95,9 @@
int minified(int x, int y) => min(x, y);
''';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -138,9 +140,10 @@
test_availableAsCodeActionLiteral() async {
await newFile(mainFilePath);
await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
- );
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
await checkCodeActionAvailable(
mainFileUri,
@@ -152,7 +155,9 @@
test_availableAsCommand() async {
await newFile(mainFilePath);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
await checkCodeActionAvailable(
mainFileUri,
@@ -165,7 +170,9 @@
test_failsIfFileHasErrors() async {
final content = 'invalid dart code';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -191,7 +198,9 @@
int minified(int x, int y) => min(x, y);
''';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -212,9 +221,19 @@
test_unavailableWhenNotRequested() async {
await newFile(mainFilePath);
await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
- );
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+ final codeActions = await getCodeActions(mainFileUri.toString());
+ final codeAction = findCommand(codeActions, Commands.organizeImports);
+ expect(codeAction, isNull);
+ }
+
+ test_unavailableWithoutApplyEditSupport() async {
+ await newFile(mainFilePath);
+ await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.organizeImports);
@@ -235,8 +254,8 @@
''';
await newFile(mainFilePath, content: content);
await initialize(
- workspaceCapabilities:
- withDocumentChangesSupport(emptyWorkspaceClientCapabilities));
+ workspaceCapabilities: withApplyEditSupport(
+ withDocumentChangesSupport(emptyWorkspaceClientCapabilities)));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -286,7 +305,9 @@
String b;
''';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -329,9 +350,10 @@
test_availableAsCodeActionLiteral() async {
await newFile(mainFilePath);
await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
- );
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
await checkCodeActionAvailable(
mainFileUri,
@@ -343,7 +365,9 @@
test_availableAsCommand() async {
await newFile(mainFilePath);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
await checkCodeActionAvailable(
mainFileUri,
@@ -359,7 +383,9 @@
String a;
''';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -390,7 +416,9 @@
test_failsIfFileHasErrors() async {
final content = 'invalid dart code';
await newFile(mainFilePath, content: content);
- await initialize();
+ await initialize(
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.sortMembers);
@@ -410,9 +438,10 @@
test_nonDartFile() async {
await newFile(pubspecFilePath, content: simplePubspecContent);
await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
- );
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Source]),
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
final codeActions =
await getCodeActions(pubspecFileUri.toString(), range: startOfDocRange);
@@ -422,9 +451,19 @@
test_unavailableWhenNotRequested() async {
await newFile(mainFilePath);
await initialize(
- textDocumentCapabilities: withCodeActionKinds(
- emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
- );
+ textDocumentCapabilities: withCodeActionKinds(
+ emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
+
+ final codeActions = await getCodeActions(mainFileUri.toString());
+ final codeAction = findCommand(codeActions, Commands.sortMembers);
+ expect(codeAction, isNull);
+ }
+
+ test_unavailableWithoutApplyEditSupport() async {
+ await newFile(mainFilePath);
+ await initialize();
final codeActions = await getCodeActions(mainFileUri.toString());
final codeAction = findCommand(codeActions, Commands.sortMembers);
diff --git a/pkg/analysis_server/test/lsp/hover_test.dart b/pkg/analysis_server/test/lsp/hover_test.dart
index 6b9be51..7f06e69 100644
--- a/pkg/analysis_server/test/lsp/hover_test.dart
+++ b/pkg/analysis_server/test/lsp/hover_test.dart
@@ -2,8 +2,11 @@
// 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/src/lsp/constants.dart';
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,6 +21,9 @@
@reflectiveTest
class HoverTest extends AbstractLspAnalysisServerTest {
+ /// If windows, return 'C:/', otherwise return the empty string
+ String get windowsCColon => Platform.isWindows ? 'C:/' : '';
+
test_dartDoc_macros() async {
final content = '''
/// {@template template_name}
@@ -63,10 +69,15 @@
String [[a^bc]];
''';
+ final containingLibraryName =
+ path.normalize("$windowsCColon/project/lib/main.dart");
+
final expectedHoverContent = '''
```dart
String abc
```
+*$containingLibraryName*
+
---
This is a string.
@@ -161,10 +172,14 @@
String [[a^bc]];
''';
+ final containingLibraryName =
+ path.normalize("$windowsCColon/project/lib/main.dart");
+
final expectedHoverContent = '''
```dart
String abc
```
+*$containingLibraryName*
'''
.trim();
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index aa19b1d..7b147df 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -170,6 +170,7 @@
const Duration(seconds: 1),
onTimeout: () {
didTimeout = true;
+ return null;
},
);
@@ -185,4 +186,94 @@
expect(response.error, isNotNull);
expect(response.error.code, ErrorCodes.ServerNotInitialized);
}
+
+ test_dynamicRegistration_notSupportedByClient() async {
+ // If the client doesn't send any dynamicRegistration settings then there
+ // should be no `client/registerCapability` calls.
+
+ // Set a flag if any registerCapability request comes through.
+ bool didGetRegisterCapabilityRequest = false;
+ requestsFromServer
+ .firstWhere((n) => n.method == Method.client_registerCapability)
+ .then((params) {
+ didGetRegisterCapabilityRequest = true;
+ });
+
+ // Initialize with no dynamic registrations advertised.
+ await initialize();
+ await pumpEventQueue();
+
+ expect(didGetRegisterCapabilityRequest, isFalse);
+ }
+
+ test_dynamicRegistration_onlyForClientSupportedMethods() async {
+ // Check that when the server calls client/registerCapability it only includes
+ // the items we advertised dynamic registration support for.
+ List<Registration> registrations;
+ await handleExpectedRequest<void, RegistrationParams, void>(
+ Method.client_registerCapability,
+ () => initialize(
+ textDocumentCapabilities: withHoverDynamicRegistration(
+ emptyTextDocumentClientCapabilities)),
+ handler: (registrationParams) =>
+ registrations = registrationParams.registrations,
+ );
+
+ expect(registrations, hasLength(1));
+ expect(registrations.single.method,
+ equals(Method.textDocument_hover.toJson()));
+ }
+
+ test_dynamicRegistration_containsAppropriateSettings() async {
+ // Basic check that the server responds with the capabilities we'd expect,
+ // for ex including analysis_options.yaml in text synchronization but not
+ // for hovers.
+ List<Registration> registrations;
+ await handleExpectedRequest<void, RegistrationParams, void>(
+ Method.client_registerCapability,
+ () => initialize(
+ // Support dynamic registration for both text sync + hovers.
+ textDocumentCapabilities: withTextSyncDynamicRegistration(
+ withHoverDynamicRegistration(
+ emptyTextDocumentClientCapabilities))),
+ handler: (registrationParams) =>
+ registrations = registrationParams.registrations,
+ );
+
+ // Should container Hover, DidOpen, DidClose, DidChange.
+ expect(registrations, hasLength(4));
+ final hover =
+ registrationOptionsFor(registrations, Method.textDocument_hover);
+ final change =
+ registrationOptionsFor(registrations, Method.textDocument_didChange);
+ expect(registrationOptionsFor(registrations, Method.textDocument_didOpen),
+ isNotNull);
+ expect(registrationOptionsFor(registrations, Method.textDocument_didClose),
+ isNotNull);
+
+ // The hover capability should only specific Dart.
+ expect(hover, isNotNull);
+ expect(hover.documentSelector, hasLength(1));
+ expect(hover.documentSelector.single.language, equals('dart'));
+
+ // didChange should also include pubspec + analysis_options.
+ expect(change, isNotNull);
+ expect(change.documentSelector, hasLength(greaterThanOrEqualTo(3)));
+ expect(change.documentSelector.any((ds) => ds.language == 'dart'), isTrue);
+ expect(change.documentSelector.any((ds) => ds.pattern == '**/pubspec.yaml'),
+ isTrue);
+ expect(
+ change.documentSelector
+ .any((ds) => ds.pattern == '**/analysis_options.yaml'),
+ isTrue);
+ }
+
+ TextDocumentRegistrationOptions registrationOptionsFor(
+ List<Registration> registrations,
+ Method method,
+ ) {
+ return registrations
+ .singleWhere((r) => r.method == method.toJson(), orElse: () => null)
+ ?.registerOptions;
+ }
}
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 9c15da4..d2e229f 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
@@ -193,7 +194,7 @@
changes,
),
);
- sendNotificationToServer(notification);
+ await sendNotificationToServer(notification);
}
Future changeWorkspaceFolders({List<Uri> add, List<Uri> remove}) async {
@@ -206,7 +207,7 @@
),
),
);
- sendNotificationToServer(notification);
+ await sendNotificationToServer(notification);
}
Future closeFile(Uri uri) async {
@@ -215,7 +216,7 @@
new DidCloseTextDocumentParams(
new TextDocumentIdentifier(uri.toString())),
);
- sendNotificationToServer(notification);
+ await sendNotificationToServer(notification);
}
Future<Object> executeCommand(Command command) async {
@@ -567,7 +568,7 @@
if (response.error == null) {
final notification =
makeNotification(Method.initialized, new InitializedParams());
- sendNotificationToServer(notification);
+ await sendNotificationToServer(notification);
await pumpEventQueue();
} else if (throwOnFailure) {
throw 'Error during initialize request: '
@@ -604,7 +605,7 @@
new DidOpenTextDocumentParams(new TextDocumentItem(
uri.toString(), dartLanguageId, version, content)),
);
- sendNotificationToServer(notification);
+ await sendNotificationToServer(notification);
await pumpEventQueue();
}
@@ -886,7 +887,12 @@
TextDocumentClientCapabilities source,
Map<String, dynamic> textDocumentCapabilities,
) {
- final json = source.toJson();
+ // TODO(dantup): Figure out why we need to do this to get a map...
+ // source.toJson() doesn't recursively called toJson() so we end up with
+ // objects (instead of maps) in child properties, which means multiple
+ // calls to this function do not work correctly. For now, calling jsonEncode
+ // then jsonDecode will force recursive serialisation.
+ final json = jsonDecode(jsonEncode(source));
if (textDocumentCapabilities != null) {
textDocumentCapabilities.keys.forEach((key) {
json[key] = textDocumentCapabilities[key];
@@ -899,7 +905,9 @@
WorkspaceClientCapabilities source,
Map<String, dynamic> workspaceCapabilities,
) {
- final json = source.toJson();
+ // TODO(dantup): As above - it seems like this round trip should be
+ // unnecessary.
+ final json = jsonDecode(jsonEncode(source));
if (workspaceCapabilities != null) {
workspaceCapabilities.keys.forEach((key) {
json[key] = workspaceCapabilities[key];
@@ -963,6 +971,14 @@
});
}
+ TextDocumentClientCapabilities withHoverDynamicRegistration(
+ TextDocumentClientCapabilities source,
+ ) {
+ return extendTextDocumentCapabilities(source, {
+ 'hover': {'dynamicRegistration': true}
+ });
+ }
+
TextDocumentClientCapabilities withSignatureHelpContentFormat(
TextDocumentClientCapabilities source,
List<MarkupKind> formats,
@@ -976,6 +992,14 @@
});
}
+ TextDocumentClientCapabilities withTextSyncDynamicRegistration(
+ TextDocumentClientCapabilities source,
+ ) {
+ return extendTextDocumentCapabilities(source, {
+ 'synchronization': {'dynamicRegistration': true}
+ });
+ }
+
TextDocumentClientCapabilities withHierarchicalDocumentSymbolSupport(
TextDocumentClientCapabilities source,
) {
diff --git a/pkg/analysis_server/test/lsp/server_test.dart b/pkg/analysis_server/test/lsp/server_test.dart
index eb79236..17cea13 100644
--- a/pkg/analysis_server/test/lsp/server_test.dart
+++ b/pkg/analysis_server/test/lsp/server_test.dart
@@ -75,6 +75,7 @@
const Duration(seconds: 1),
onTimeout: () {
didTimeout = true;
+ return null;
},
);
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index 54c5d7d..7973bac 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -6,6 +6,7 @@
import '../src/lsp/lsp_packet_transformer_test.dart' as lsp_packet_transformer;
import 'analyzer_status_test.dart' as analyzer_status;
+import 'cancel_request_test.dart' as cancel_request;
import 'change_workspace_folders_test.dart' as change_workspace_folders;
import 'code_actions_assists_test.dart' as code_actions_assists;
import 'code_actions_fixes_test.dart' as code_actions_fixes;
@@ -32,6 +33,7 @@
main() {
defineReflectiveSuite(() {
analyzer_status.main();
+ cancel_request.main();
change_workspace_folders.main();
code_actions_assists.main();
code_actions_fixes.main();
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
index 72cad45..8bf1e30 100644
--- a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -10,7 +11,9 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(WorkspaceSymbolsTest);
+ if (!AnalysisDriver.useSummary2) {
+ defineReflectiveTests(WorkspaceSymbolsTest);
+ }
});
}
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index 367e52e..6daf2ec 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -107,7 +107,8 @@
notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
- _clientToServer.add(notification);
+ // Wrap send request in future to simulate WebSocket.
+ new Future(() => _clientToServer.add(notification));
}
@override
diff --git a/pkg/analysis_server/test/search/declarations_test.dart b/pkg/analysis_server/test/search/declarations_test.dart
index 000ba70..3d505be 100644
--- a/pkg/analysis_server/test/search/declarations_test.dart
+++ b/pkg/analysis_server/test/search/declarations_test.dart
@@ -6,6 +6,7 @@
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,7 +15,9 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(DeclarationsTest);
+ if (!AnalysisDriver.useSummary2) {
+ defineReflectiveTests(DeclarationsTest);
+ }
});
}
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 9d9a40d..dd6b22f 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
@@ -582,16 +582,20 @@
//
addTestSource('main() { int.parse("16", ^);}');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ });
}
test_ArgumentList_imported_function_named_param1() async {
//
addTestSource('main() { int.parse("16", r^);}');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ });
}
test_ArgumentList_imported_function_named_param2() async {
@@ -599,7 +603,7 @@
addTestSource('main() { int.parse("16", radix: 7, ^);}');
await computeSuggestions();
assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'onError': '(String) → int'});
+ namedArgumentsWithTypes: {'onError': 'int Function(String)'});
}
test_ArgumentList_imported_function_named_param2a() async {
@@ -613,9 +617,10 @@
//
addTestSource('main() { int.parse("16", r^: 16);}');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'},
- includeColon: false);
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ }, includeColon: false);
}
test_ArgumentList_imported_function_named_param_label2() async {
@@ -629,8 +634,10 @@
//
addTestSource('main() { int.parse("16", ^: 16);}');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ });
}
test_ArgumentList_local_constructor_named_fieldFormal_documentation() async {
@@ -886,8 +893,10 @@
f(v,{int radix, int onError(String s)}){}
main() { f("16", ^);}''');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ });
}
test_ArgumentList_local_function_named_param1() async {
@@ -896,8 +905,10 @@
f(v,{int radix, int onError(String s)}){}
main() { f("16", r^);}''');
await computeSuggestions();
- assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'radix': 'int', 'onError': '(String) → int'});
+ assertSuggestArgumentsAndTypes(namedArgumentsWithTypes: {
+ 'radix': 'int',
+ 'onError': 'int Function(String)'
+ });
}
test_ArgumentList_local_function_named_param2() async {
@@ -907,7 +918,7 @@
main() { f("16", radix: 7, ^);}''');
await computeSuggestions();
assertSuggestArgumentsAndTypes(
- namedArgumentsWithTypes: {'onError': '(String) → int'});
+ namedArgumentsWithTypes: {'onError': 'int Function(String)'});
}
test_ArgumentList_local_function_named_param2a() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index ed57fbe..49a2d65 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -269,6 +269,30 @@
assertNotSuggested('_name');
}
+ test_SimpleFormalParameter_FormalParameterList() async {
+ addTestSource('''
+f(A ^) {}
+''');
+ await computeSuggestions();
+ expect(replacementOffset, 4);
+ expect(replacementLength, 0);
+ assertSuggestName('a');
+ // private version
+ assertNotSuggested('_a');
+ }
+
+ test_SimpleFormalParameter_itself() async {
+ addTestSource('''
+f(A n^) {}
+''');
+ await computeSuggestions();
+ expect(replacementOffset, 4);
+ expect(replacementLength, 1);
+ assertSuggestName('a');
+ // private version
+ assertNotSuggested('_a');
+ }
+
test_TopLevelVariableDeclaration_dont_suggest_type() async {
addTestSource('''
a ^
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
index 97064f5..469ba02 100644
--- a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
@@ -21,6 +21,7 @@
final Map<int, AvailableSuggestionSet> idToSetMap = {};
final Map<String, AvailableSuggestionSet> uriToSetMap = {};
final Map<String, CompletionResultsParams> idToSuggestions = {};
+ final Map<String, ExistingImports> fileToExistingImports = {};
void assertJsonText(Object object, String expected) {
expected = expected.trimRight();
@@ -56,6 +57,13 @@
} else if (notification.event == COMPLETION_RESULTS) {
var params = CompletionResultsParams.fromNotification(notification);
idToSuggestions[params.id] = params;
+ } else if (notification.event == COMPLETION_NOTIFICATION_EXISTING_IMPORTS) {
+ var params = CompletionExistingImportsParams.fromNotification(
+ notification,
+ );
+ fileToExistingImports[params.file] = params.imports;
+ } else if (notification.event == SERVER_NOTIFICATION_ERROR) {
+ fail('${notification.toJson()}');
}
}
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
index 600a33a..47c59ec 100644
--- a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -10,12 +10,50 @@
main() {
defineReflectiveSuite(() {
+ defineReflectiveTests(ExistingImportsNotification);
defineReflectiveTests(GetSuggestionAvailableTest);
});
}
@reflectiveTest
-class GetSuggestionAvailableTest extends AvailableSuggestionsBase {
+class ExistingImportsNotification extends GetSuggestionsBase {
+ test_dart() async {
+ addTestFile(r'''
+import 'dart:math';
+''');
+ await _getSuggestions(testFile, 0);
+ _assertHasImport('dart:math', 'dart:math', 'Random');
+ }
+
+ test_invalidUri() async {
+ addTestFile(r'''
+import 'ht:';
+''');
+ await _getSuggestions(testFile, 0);
+ // We should not get 'server.error' notification.
+ }
+
+ void _assertHasImport(String exportingUri, String declaringUri, String name) {
+ var existingImports = fileToExistingImports[testFile];
+ expect(existingImports, isNotNull);
+
+ var existingImport = existingImports.imports.singleWhere((import) =>
+ existingImports.elements.strings[import.uri] == exportingUri);
+
+ var elements = existingImport.elements.map((index) {
+ var uriIndex = existingImports.elements.uris[index];
+ var nameIndex = existingImports.elements.names[index];
+ var uri = existingImports.elements.strings[uriIndex];
+ var name = existingImports.elements.strings[nameIndex];
+ return '$uri::$name';
+ }).toList();
+
+ expect(elements, contains('$declaringUri::$name'));
+ }
+}
+
+@reflectiveTest
+class GetSuggestionAvailableTest extends GetSuggestionsBase {
test_dart() async {
addTestFile('');
var mathSet = await waitForSetWithUri('dart:math');
@@ -284,7 +322,9 @@
]
''');
}
+}
+abstract class GetSuggestionsBase extends AvailableSuggestionsBase {
Future<CompletionResultsParams> _getSuggestions(
String path,
int offset,
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 fe6ebd6..2ab09bd 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
@@ -205,6 +205,73 @@
}
}
+ test_children_closure_blockBody() async {
+ newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+ final Widget Function(bool) factory;
+
+ WidgetA(this.factory);
+}
+''');
+ FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new WidgetA((b) {
+ if (b) {
+ return const Text('aaa'),
+ } else {
+ return const Container(),
+ }
+ }); // WidgetA
+ }
+}
+''');
+ expect(_toText(unitOutline), r'''
+(D) MyWidget
+ (D) build
+ WidgetA
+ Text
+ Container
+''');
+ }
+
+ test_children_closure_expressionBody() async {
+ newFile('/home/test/lib/a.dart', content: r'''
+import 'package:flutter/widgets.dart';
+
+class WidgetA extends StatelessWidget {
+ final Widget Function() factory;
+
+ WidgetA(this.factory);
+}
+''');
+ FlutterOutline unitOutline = await _computeOutline('''
+import 'package:flutter/widgets.dart';
+import 'a.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new WidgetA(
+ () => const Text('aaa'),
+ ); // WidgetA
+ }
+}
+''');
+ expect(_toText(unitOutline), r'''
+(D) MyWidget
+ (D) build
+ WidgetA
+ Text
+''');
+ }
+
test_children_withCollectionElements() async {
FlutterOutline unitOutline = await _computeOutline('''
import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
index b143f73..357b500 100644
--- a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
+++ b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
@@ -3,16 +3,17 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/nullability/conditional_discard.dart';
-import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
-import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
import 'package:analysis_server/src/nullability/decorated_type.dart';
import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/graph_builder.dart';
+import 'package:analysis_server/src/nullability/node_builder.dart';
import 'package:analysis_server/src/nullability/nullability_node.dart';
import 'package:analysis_server/src/nullability/transitional_api.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:meta/meta.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -20,13 +21,23 @@
main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ConstraintGathererTest);
- defineReflectiveTests(ConstraintVariableGathererTest);
+ defineReflectiveTests(GraphBuilderTest);
+ defineReflectiveTests(NodeBuilderTest);
});
}
@reflectiveTest
-class ConstraintGathererTest extends ConstraintsTestBase {
+class GraphBuilderTest extends MigrationVisitorTestBase {
+ /// Analyzes the given source code, producing constraint variables and
+ /// constraints for it.
+ @override
+ Future<CompilationUnit> analyze(String code) async {
+ var unit = await super.analyze(code);
+ unit.accept(
+ GraphBuilder(typeProvider, _variables, graph, testSource, false));
+ return unit;
+ }
+
void assertConditional(
NullabilityNode node, NullabilityNode left, NullabilityNode right) {
var conditionalNode = node as NullabilityNodeForLUB;
@@ -34,23 +45,6 @@
expect(conditionalNode.right, same(right));
}
- /// Checks that there is a connection from [sourceNode] to [destinationNode].
- void assertConnection(
- NullabilityNode sourceNode, NullabilityNode destinationNode) {
- expect(graph.getDownstreamNodes(sourceNode).toList(),
- contains(destinationNode));
- }
-
- void assertNonNullIntent(NullabilityNode node, bool expected) {
- if (expected) {
- expect(graph.getUnconditionalUpstreamNodes(NullabilityNode.never),
- contains(node));
- } else {
- expect(graph.getUnconditionalUpstreamNodes(NullabilityNode.never),
- isNot(contains(node)));
- }
- }
-
/// Checks that there are no nullability nodes upstream from [node] that could
/// cause it to become nullable.
void assertNoUpstreamNullability(NullabilityNode node) {
@@ -112,7 +106,7 @@
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
+ assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
}
test_binaryExpression_add_left_check() async {
@@ -301,55 +295,25 @@
void f({int i = null}) {}
''');
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
+ assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+ hard: false);
}
- test_functionDeclaration_parameter_named_no_default_assume_nullable() async {
+ test_functionDeclaration_parameter_named_no_default() async {
await analyze('''
void f({int i}) {}
-''',
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
+''');
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
+ assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+ hard: false);
}
- test_functionDeclaration_parameter_named_no_default_assume_required() async {
- await analyze('''
-void f({int i}) {}
-''',
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
-
- assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
- }
-
- test_functionDeclaration_parameter_named_no_default_required_assume_nullable() async {
+ test_functionDeclaration_parameter_named_no_default_required() async {
addMetaPackage();
await analyze('''
import 'package:meta/meta.dart';
void f({@required int i}) {}
-''',
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
-
- assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
- }
-
- test_functionDeclaration_parameter_named_no_default_required_assume_required() async {
- addMetaPackage();
- await analyze('''
-import 'package:meta/meta.dart';
-void f({@required int i}) {}
-''',
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
+''');
assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
}
@@ -367,8 +331,8 @@
void f([int i = null]) {}
''');
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
+ assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+ hard: false);
}
test_functionDeclaration_parameter_positionalOptional_no_default() async {
@@ -376,22 +340,8 @@
void f([int i]) {}
''');
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
- }
-
- test_functionDeclaration_parameter_positionalOptional_no_default_assume_required() async {
- // Note: the `assumeRequired` behavior shouldn't affect the behavior here
- // because it only affects named parameters.
- await analyze('''
-void f([int i]) {}
-''',
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
-
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
+ assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+ hard: false);
}
test_functionDeclaration_resets_unconditional_control_flow() async {
@@ -405,9 +355,9 @@
assert(k != null);
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
- assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
- assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
+ assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+ assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+ assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
}
test_functionInvocation_parameter_fromLocalParameter() async {
@@ -422,8 +372,7 @@
var int_2 = decoratedTypeAnnotation('int/*2*/');
var i_3 = checkExpression('i/*3*/');
assertNullCheck(i_3, int_2.node, contextNode: int_1.node);
- expect(
- graph.getUnconditionalUpstreamNodes(int_1.node), contains(int_2.node));
+ assertEdge(int_2.node, int_1.node, hard: true);
}
test_functionInvocation_parameter_named() async {
@@ -447,7 +396,7 @@
}
''');
var optional_i = possiblyOptionalParameter('int i');
- assertConnection(NullabilityNode.always, optional_i);
+ expect(getEdges(NullabilityNode.always, optional_i), isNotEmpty);
}
test_functionInvocation_parameter_named_missing_required() async {
@@ -513,7 +462,7 @@
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
+ assertNoEdge(always, decoratedTypeAnnotation('int i').node);
}
test_if_conditional_control_flow_within() async {
@@ -528,7 +477,7 @@
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('int i').node, false);
+ assertNoEdge(always, decoratedTypeAnnotation('int i').node);
}
test_if_guard_equals_null() async {
@@ -613,9 +562,9 @@
}
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('int i').node, true);
- assertNonNullIntent(decoratedTypeAnnotation('int j').node, false);
- assertNonNullIntent(decoratedTypeAnnotation('int k').node, true);
+ assertEdge(decoratedTypeAnnotation('int i').node, never, hard: true);
+ assertNoEdge(always, decoratedTypeAnnotation('int j').node);
+ assertEdge(decoratedTypeAnnotation('int k').node, never, hard: true);
}
test_methodInvocation_parameter_contravariant() async {
@@ -649,8 +598,9 @@
}
''');
- assertConnection(decoratedTypeAnnotation('int/*3*/').node,
- decoratedTypeAnnotation('int/*1*/').node);
+ assertEdge(decoratedTypeAnnotation('int/*3*/').node,
+ decoratedTypeAnnotation('int/*1*/').node,
+ hard: false);
assertNullCheck(checkExpression('c/*check*/'),
decoratedTypeAnnotation('C<int/*3*/>/*4*/').node,
contextNode: decoratedTypeAnnotation('C<int/*1*/>/*2*/').node);
@@ -671,6 +621,18 @@
contextNode: nullable_i);
}
+ test_methodInvocation_return_type() async {
+ await analyze('''
+class C {
+ bool m() => true;
+}
+bool f(C c) => c.m();
+''');
+ assertEdge(decoratedTypeAnnotation('bool m').node,
+ decoratedTypeAnnotation('bool f').node,
+ hard: false);
+ }
+
test_methodInvocation_target_check() async {
await analyze('''
class C {
@@ -695,7 +657,7 @@
}
''');
- assertNonNullIntent(decoratedTypeAnnotation('C c').node, true);
+ assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
}
test_never() async {
@@ -715,6 +677,71 @@
contextNode: decoratedTypeAnnotation('int').node);
}
+ test_prefixedIdentifier_return_type() async {
+ await analyze('''
+class C {
+ bool get b => true;
+}
+bool f(C c) => c.b;
+''');
+ assertEdge(decoratedTypeAnnotation('bool get').node,
+ decoratedTypeAnnotation('bool f').node,
+ hard: false);
+ }
+
+ test_prefixedIdentifier_target_check() async {
+ await analyze('''
+class C {
+ int get x => 1;
+}
+void test(C c) {
+ c.x;
+}
+''');
+
+ assertNullCheck(
+ checkExpression('c.x'), decoratedTypeAnnotation('C c').node);
+ }
+
+ test_prefixedIdentifier_target_demonstrates_non_null_intent() async {
+ await analyze('''
+class C {
+ int get x => 1;
+}
+void test(C c) {
+ c.x;
+}
+''');
+
+ assertEdge(decoratedTypeAnnotation('C c').node, never, hard: true);
+ }
+
+ test_propertyAccess_return_type() async {
+ await analyze('''
+class C {
+ bool get b => true;
+}
+bool f(C c) => (c).b;
+''');
+ assertEdge(decoratedTypeAnnotation('bool get').node,
+ decoratedTypeAnnotation('bool f').node,
+ hard: false);
+ }
+
+ test_propertyAccess_target_check() async {
+ await analyze('''
+class C {
+ int get x => 1;
+}
+void test(C c) {
+ (c).x;
+}
+''');
+
+ assertNullCheck(
+ checkExpression('c).x'), decoratedTypeAnnotation('C c').node);
+ }
+
test_return_implicit_null() async {
verifyNoTestUnitErrors = false;
await analyze('''
@@ -723,8 +750,8 @@
}
''');
- assertConnection(
- NullabilityNode.always, decoratedTypeAnnotation('int').node);
+ assertEdge(NullabilityNode.always, decoratedTypeAnnotation('int').node,
+ hard: false);
}
test_return_null() async {
@@ -738,6 +765,15 @@
contextNode: decoratedTypeAnnotation('int').node);
}
+ test_soft_edge_for_non_variable_reference() async {
+ // Edges originating in things other than variable references should be
+ // soft.
+ await analyze('''
+int f() => null;
+''');
+ assertEdge(always, decoratedTypeAnnotation('int').node, hard: false);
+ }
+
test_stringLiteral() async {
// TODO(paulberry): also test string interpolations
await analyze('''
@@ -772,8 +808,9 @@
class C<T extends Object> {}
void f(C<int> c) {}
''');
- assertConnection(decoratedTypeAnnotation('int>').node,
- decoratedTypeAnnotation('Object>').node);
+ assertEdge(decoratedTypeAnnotation('int>').node,
+ decoratedTypeAnnotation('Object>').node,
+ hard: true);
}
test_typeName() async {
@@ -786,22 +823,79 @@
}
}
-abstract class ConstraintsTestBase extends MigrationVisitorTestBase {
- /// Analyzes the given source code, producing constraint variables and
- /// constraints for it.
- @override
- Future<CompilationUnit> analyze(String code,
- {NullabilityMigrationAssumptions assumptions:
- const NullabilityMigrationAssumptions()}) async {
- var unit = await super.analyze(code);
- unit.accept(ConstraintGatherer(
- typeProvider, _variables, graph, testSource, false, assumptions));
- return unit;
+class MigrationVisitorTestBase extends AbstractSingleUnitTest {
+ final _Variables _variables;
+
+ FindNode findNode;
+
+ final NullabilityGraph graph;
+
+ MigrationVisitorTestBase() : this._(NullabilityGraph());
+
+ MigrationVisitorTestBase._(this.graph) : _variables = _Variables(graph);
+
+ NullabilityNode get always => NullabilityNode.always;
+
+ NullabilityNode get never => NullabilityNode.never;
+
+ TypeProvider get typeProvider => testAnalysisResult.typeProvider;
+
+ Future<CompilationUnit> analyze(String code) async {
+ await resolveTestUnit(code);
+ testUnit.accept(
+ NodeBuilder(_variables, testSource, false, graph, typeProvider));
+ findNode = FindNode(code, testUnit);
+ return testUnit;
+ }
+
+ void assertEdge(NullabilityNode source, NullabilityNode destination,
+ {@required bool hard}) {
+ var edges = getEdges(source, destination);
+ if (edges.length == 0) {
+ fail('Expected edge $source -> $destination, found none');
+ } else if (edges.length != 1) {
+ fail('Found multiple edges $source -> $destination');
+ } else {
+ var edge = edges[0];
+ expect(edge.hard, hard);
+ }
+ }
+
+ void assertNoEdge(NullabilityNode source, NullabilityNode destination) {
+ var edges = getEdges(source, destination);
+ if (edges.isNotEmpty) {
+ fail('Expected no edge $source -> $destination, found ${edges.length}');
+ }
+ }
+
+ /// Gets the [DecoratedType] associated with the type annotation whose text
+ /// is [text].
+ DecoratedType decoratedTypeAnnotation(String text) {
+ return _variables.decoratedTypeAnnotation(
+ testSource, findNode.typeAnnotation(text));
+ }
+
+ List<NullabilityEdge> getEdges(
+ NullabilityNode source, NullabilityNode destination) =>
+ graph
+ .getUpstreamEdges(destination)
+ .where((e) => e.primarySource == source)
+ .toList();
+
+ NullabilityNode possiblyOptionalParameter(String text) {
+ return _variables
+ .possiblyOptionalParameter(findNode.defaultParameter(text));
+ }
+
+ /// Gets the [ConditionalDiscard] information associated with the statement
+ /// whose text is [text].
+ ConditionalDiscard statementDiscard(String text) {
+ return _variables.conditionalDiscard(findNode.statement(text));
}
}
@reflectiveTest
-class ConstraintVariableGathererTest extends MigrationVisitorTestBase {
+class NodeBuilderTest extends MigrationVisitorTestBase {
/// Gets the [DecoratedType] associated with the function declaration whose
/// name matches [search].
DecoratedType decoratedFunctionType(String search) =>
@@ -835,8 +929,7 @@
expect(decoratedFunctionType('f').positionalParameters[0],
same(decoratedType));
expect(decoratedType.type.isDynamic, isTrue);
- expect(graph.getUpstreamNodesForTesting(decoratedType.node),
- contains(NullabilityNode.always));
+ expect(decoratedType.node.isNullable, isTrue);
}
test_topLevelFunction_parameterType_named_no_default() async {
@@ -907,8 +1000,7 @@
''');
var decoratedType = decoratedFunctionType('f').returnType;
expect(decoratedType.type.isDynamic, isTrue);
- expect(graph.getUpstreamNodesForTesting(decoratedType.node),
- contains(NullabilityNode.always));
+ expect(decoratedType.node.isNullable, isTrue);
}
test_topLevelFunction_returnType_simple() async {
@@ -939,54 +1031,11 @@
class C<T> {}
''');
var bound = decoratedTypeParameterBound('T');
- expect(graph.getUnconditionalUpstreamNodes(bound.node),
- contains(NullabilityNode.always));
+ expect(bound.node.isNullable, isTrue);
expect(bound.type, same(typeProvider.objectType));
}
}
-class MigrationVisitorTestBase extends AbstractSingleUnitTest {
- final _Variables _variables;
-
- FindNode findNode;
-
- final NullabilityGraph graph;
-
- MigrationVisitorTestBase() : this._(NullabilityGraph());
-
- MigrationVisitorTestBase._(this.graph) : _variables = _Variables(graph);
-
- TypeProvider get typeProvider => testAnalysisResult.typeProvider;
-
- Future<CompilationUnit> analyze(String code,
- {NullabilityMigrationAssumptions assumptions:
- const NullabilityMigrationAssumptions()}) async {
- await resolveTestUnit(code);
- testUnit.accept(ConstraintVariableGatherer(
- _variables, testSource, false, assumptions, graph, typeProvider));
- findNode = FindNode(code, testUnit);
- return testUnit;
- }
-
- /// Gets the [DecoratedType] associated with the type annotation whose text
- /// is [text].
- DecoratedType decoratedTypeAnnotation(String text) {
- return _variables.decoratedTypeAnnotation(
- testSource, findNode.typeAnnotation(text));
- }
-
- NullabilityNode possiblyOptionalParameter(String text) {
- return _variables
- .possiblyOptionalParameter(findNode.defaultParameter(text));
- }
-
- /// Gets the [ConditionalDiscard] information associated with the statement
- /// whose text is [text].
- ConditionalDiscard statementDiscard(String text) {
- return _variables.conditionalDiscard(findNode.statement(text));
- }
-}
-
/// Mock representation of constraint variables.
class _Variables extends Variables {
final _conditionalDiscard = <AstNode, ConditionalDiscard>{};
diff --git a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
index 8a4bb19..f6ba883 100644
--- a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
+++ b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
@@ -36,15 +36,13 @@
/// Verifies that migration of the files in [input] produces the output in
/// [expectedOutput].
Future<void> _checkMultipleFileChanges(
- Map<String, String> input, Map<String, String> expectedOutput,
- {NullabilityMigrationAssumptions assumptions:
- const NullabilityMigrationAssumptions()}) async {
+ Map<String, String> input, Map<String, String> expectedOutput) async {
for (var path in input.keys) {
newFile(path, content: input[path]);
}
var listener = new _TestMigrationListener();
- var migration = NullabilityMigration(listener,
- permissive: _usePermissiveMode, assumptions: assumptions);
+ var migration =
+ NullabilityMigration(listener, permissive: _usePermissiveMode);
for (var path in input.keys) {
migration.prepareInput(await session.getResolvedUnit(path));
}
@@ -69,13 +67,10 @@
/// Verifies that migraiton of the single file with the given [content]
/// produces the [expected] output.
- Future<void> _checkSingleFileChanges(String content, String expected,
- {NullabilityMigrationAssumptions assumptions:
- const NullabilityMigrationAssumptions()}) async {
+ Future<void> _checkSingleFileChanges(String content, String expected) async {
var sourcePath = convertPath('/home/test/lib/test.dart');
await _checkMultipleFileChanges(
- {sourcePath: content}, {sourcePath: expected},
- assumptions: assumptions);
+ {sourcePath: content}, {sourcePath: expected});
}
}
@@ -318,7 +313,7 @@
await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_unused_option2_assume_nullable() async {
+ test_named_parameter_no_default_unused() async {
var content = '''
void f({String s}) {}
main() {
@@ -331,13 +326,10 @@
f();
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
+ await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_unused_option2_assume_nullable_propagate() async {
+ test_named_parameter_no_default_unused_propagate() async {
var content = '''
void f(String s) {}
void g({String s}) {
@@ -356,57 +348,10 @@
g();
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
+ await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_unused_option2_assume_required() async {
- var content = '''
-void f({String s}) {}
-main() {
- f();
-}
-''';
- var expected = '''
-void f({String? s}) {}
-main() {
- f();
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
- }
-
- test_named_parameter_no_default_unused_option2_assume_required_propagate() async {
- var content = '''
-void f(String s) {}
-void g({String s}) {
- f(s);
-}
-main() {
- g();
-}
-''';
- var expected = '''
-void f(String? s) {}
-void g({String? s}) {
- f(s);
-}
-main() {
- g();
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
- }
-
- test_named_parameter_no_default_unused_required_option2_assume_nullable() async {
+ test_named_parameter_no_default_unused_required() async {
// The `@required` annotation overrides the assumption of nullability.
// The call at `f()` is presumed to be in error.
addMetaPackage();
@@ -424,38 +369,10 @@
f();
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
+ await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_unused_required_option2_assume_required() async {
- // Since the `@required` annotation is already present, it is not added
- // again.
- // The call at `f()` is presumed to be in error.
- addMetaPackage();
- var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f();
-}
-''';
- var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f();
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
- }
-
- test_named_parameter_no_default_used_non_null_option2_assume_nullable() async {
+ test_named_parameter_no_default_used_non_null() async {
var content = '''
void f({String s}) {}
main() {
@@ -468,13 +385,10 @@
f(s: 'x');
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
+ await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_used_non_null_option2_assume_nullable_propagate() async {
+ test_named_parameter_no_default_used_non_null_propagate() async {
var content = '''
void f(String s) {}
void g({String s}) {
@@ -493,80 +407,7 @@
g(s: 'x');
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
- }
-
- test_named_parameter_no_default_used_non_null_option2_assume_required() async {
- var content = '''
-void f({String s}) {}
-main() {
- f(s: 'x');
-}
-''';
- var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f(s: 'x');
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
- }
-
- test_named_parameter_no_default_used_non_null_option2_assume_required_propagate() async {
- var content = '''
-void f(String s) {}
-void g({String s}) {
- f(s);
-}
-main() {
- g(s: 'x');
-}
-''';
- var expected = '''
-import 'package:meta/meta.dart';
-void f(String s) {}
-void g({@required String s}) {
- f(s);
-}
-main() {
- g(s: 'x');
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
- }
-
- test_named_parameter_no_default_used_non_null_required_option2_assume_required() async {
- // Even if we are using the "assumeRequired" heuristic, we should not add a
- // duplicate `@required` annotation.
- addMetaPackage();
- var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f(s: 'x');
-}
-''';
- var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f(s: 'x');
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
+ await _checkSingleFileChanges(content, expected);
}
test_named_parameter_no_default_used_null_option2() async {
@@ -585,7 +426,7 @@
await _checkSingleFileChanges(content, expected);
}
- test_named_parameter_no_default_used_null_required_option2_assume_nullable() async {
+ test_named_parameter_no_default_used_null_required() async {
// Explicitly passing `null` forces the parameter to be nullable even though
// it is required.
addMetaPackage();
@@ -603,34 +444,7 @@
f(s: null);
}
''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeNullable));
- }
-
- test_named_parameter_no_default_used_null_required_option2_assume_required() async {
- // Explicitly passing `null` forces the parameter to be nullable even though
- // it is required.
- addMetaPackage();
- var content = '''
-import 'package:meta/meta.dart';
-void f({@required String s}) {}
-main() {
- f(s: null);
-}
-''';
- var expected = '''
-import 'package:meta/meta.dart';
-void f({@required String? s}) {}
-main() {
- f(s: null);
-}
-''';
- await _checkSingleFileChanges(content, expected,
- assumptions: NullabilityMigrationAssumptions(
- namedNoDefaultParameterHeuristic:
- NamedNoDefaultParameterHeuristic.assumeRequired));
+ await _checkSingleFileChanges(content, expected);
}
test_named_parameter_with_non_null_default_unused_option2() async {
@@ -816,7 +630,7 @@
await _checkSingleFileChanges(content, expected);
}
- test_unconditional_dereference_implies_non_null_intent() async {
+ test_unconditional_method_call_implies_non_null_intent() async {
var content = '''
void f(int i) {
i.abs();
@@ -868,6 +682,32 @@
await _checkSingleFileChanges(content, expected);
}
+ test_unconditional_property_access_implies_non_null_intent() async {
+ var content = '''
+void f(int i) {
+ i.isEven;
+}
+void g(bool b, int i) {
+ if (b) f(i);
+}
+main() {
+ g(false, null);
+}
+''';
+ var expected = '''
+void f(int i) {
+ i.isEven;
+}
+void g(bool b, int? i) {
+ if (b) f(i!);
+}
+main() {
+ g(false, null);
+}
+''';
+ await _checkSingleFileChanges(content, expected);
+ }
+
test_unconditional_usage_propagates_non_null_intent() async {
var content = '''
void f(int i) {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
index f51ffa7..4e1af86 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_wrap_center_test.dart
@@ -81,4 +81,20 @@
}
''');
}
+
+ test_expressionFunctionBody() async {
+ addFlutterPackage();
+ await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+ main() => /*caret*/Container();
+}
+''');
+ await assertHasAssist('''
+import 'package:flutter/widgets.dart';
+class FakeFlutter {
+ main() => Center(child: Container());
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
new file mode 100644
index 0000000..4cc5973
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/sort_child_property_last_test.dart
@@ -0,0 +1,100 @@
+// 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/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SortChildPropertyLastTest);
+ });
+}
+
+@reflectiveTest
+class SortChildPropertyLastTest extends AssistProcessorTest {
+ @override
+ AssistKind get kind => DartAssistKind.SORT_CHILD_PROPERTY_LAST;
+
+ test_already_sorted() async {
+ addFlutterPackage();
+ await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: <Widget>[
+ Text('aaa'),
+ Text('bbbbbb'),
+ Text('ccccccccc'),
+ ],
+ );
+}
+''');
+ await assertNoAssist();
+ }
+
+ test_already_sorted_one_prop() async {
+ addFlutterPackage();
+ await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+ Column(
+ children: <Widget>[
+ Text('aaa'),
+ Text('bbbbbb'),
+ Text('ccccccccc'),
+ ],
+ );
+}
+''');
+ await assertNoAssist();
+ }
+
+ test_no_children() async {
+ addFlutterPackage();
+ await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ );
+}
+''');
+ await assertNoAssist();
+ }
+
+ test_sort() async {
+ addFlutterPackage();
+ await resolveTestUnit('''
+import 'package:flutter/material.dart';
+main() {
+ Column(
+ /*caret*/children: <Widget>[
+ Text('aaa'),
+ Text('bbbbbb'),
+ Text('ccccccccc'),
+ ],
+ crossAxisAlignment: CrossAxisAlignment.center,
+ );
+}
+''');
+ await assertHasAssist('''
+import 'package:flutter/material.dart';
+main() {
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: <Widget>[
+ Text('aaa'),
+ Text('bbbbbb'),
+ Text('ccccccccc'),
+ ],
+ );
+}
+''');
+ assertExitPosition(after: "],");
+ }
+}
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 d76f97b..7a7f079 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
@@ -67,6 +67,7 @@
as replace_conditional_with_if_else;
import 'replace_if_else_with_conditional_test.dart'
as replace_if_else_with_conditional;
+import 'sort_child_property_last_test.dart' as sort_child_property_last;
import 'split_and_condition_test.dart' as split_and_condition;
import 'split_variable_declaration_test.dart' as split_variable_declaration;
import 'surround_with_block_test.dart' as surround_with_block;
@@ -135,6 +136,7 @@
remove_type_annotation.main();
replace_conditional_with_if_else.main();
replace_if_else_with_conditional.main();
+ sort_child_property_last.main();
split_and_condition.main();
split_variable_declaration.main();
surround_with_block.main();
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 beb7025..4dbfa14 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
@@ -7,9 +7,12 @@
import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
import 'package:analysis_server/src/services/correction/change_workspace.dart';
import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/error/lint_codes.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
hide AnalysisError;
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
@@ -250,7 +253,19 @@
/// Computes fixes for the given [error] in [testUnit].
Future<List<Fix>> _computeFixes(AnalysisError error) async {
- var context = new DartFixContextImpl(workspace, testAnalysisResult, error);
+ var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
+ tracker.addContext(driver.analysisContext);
+
+ var context = new DartFixContextImpl(
+ workspace,
+ testAnalysisResult,
+ error,
+ (name) {
+ var provider = TopLevelDeclarationsProvider(tracker);
+ provider.doTrackerWork();
+ return provider.get(driver.analysisContext, testFile, name);
+ },
+ );
return await new DartFixContributor().computeFixes(context);
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
index f1d1710..6c11ac8 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/import_library_project_test.dart
@@ -18,8 +18,7 @@
}
@reflectiveTest
-class ImportLibraryProject1Test extends FixProcessorTest
- with ImportLibraryTestMixin {
+class ImportLibraryProject1Test extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT1;
@@ -39,6 +38,45 @@
await assertNoFix();
}
+ test_lib() async {
+ addPackageFile('my_pkg', 'a.dart', 'class Test {}');
+ newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+ my_pkg: any
+''');
+
+ await resolveTestUnit('''
+main() {
+ Test test = null;
+ print(test);
+}
+''');
+
+ await assertHasFix('''
+import 'package:my_pkg/a.dart';
+
+main() {
+ Test test = null;
+ print(test);
+}
+''', expectedNumberOfFixesForKind: 1);
+ }
+
+ test_lib_src() async {
+ addPackageFile('my_pkg', 'src/a.dart', 'class Test {}');
+ newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+ my_pkg: any
+''');
+ await resolveTestUnit('''
+main() {
+ Test test = null;
+ print(test);
+}
+''');
+ await assertNoFix();
+ }
+
test_notInLib() async {
addSource('/home/other/test/lib.dart', 'class Test {}');
await resolveTestUnit('''
@@ -50,66 +88,40 @@
await assertNoFix();
}
- test_preferDirectOverExport() async {
- _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
- await resolveTestUnit('''
-main() {
- Test test = null;
- print(test);
-}
-''');
- await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
- Test test = null;
- print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
- }
-
- test_preferDirectOverExport_src() async {
- _configureMyPkg({'b.dart': 'class Test {}', 'a.dart': "export 'b.dart';"});
- await resolveTestUnit('''
-main() {
- Test test = null;
- print(test);
-}
-''');
- await assertHasFix('''
-import 'package:my_pkg/b.dart';
-
-main() {
- Test test = null;
- print(test);
-}
-''', expectedNumberOfFixesForKind: 1);
- }
-
test_relativeDirective() async {
addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
- addSource('/home/test/lib/b.dart', '''
class Foo {}
''');
await resolveTestUnit('''
main() { new Foo(); }
''');
await assertHasFix('''
-import 'b.dart';
+import 'a.dart';
main() { new Foo(); }
''',
expectedNumberOfFixesForKind: 2,
- matchFixMessage: "Import library 'b.dart'");
+ matchFixMessage: "Import library 'a.dart'");
+ }
+
+ test_relativeDirective_downOneDirectory() async {
+ addSource('/home/test/lib/dir/a.dart', '''
+class Foo {}
+''');
+ await resolveTestUnit('''
+main() { new Foo(); }
+''');
+ await assertHasFix('''
+import 'dir/a.dart';
+
+main() { new Foo(); }
+''',
+ expectedNumberOfFixesForKind: 2,
+ matchFixMessage: "Import library 'dir/a.dart'");
}
test_relativeDirective_upOneDirectory() async {
addSource('/home/test/lib/a.dart', '''
-import "b.dart";
-''');
- addSource('/home/test/lib/b.dart', '''
class Foo {}
''');
testFile = convertPath('/home/test/lib/dir/test.dart');
@@ -117,31 +129,12 @@
main() { new Foo(); }
''');
await assertHasFix('''
-import '../b.dart';
+import '../a.dart';
main() { new Foo(); }
''',
expectedNumberOfFixesForKind: 2,
- matchFixMessage: "Import library '../b.dart'");
- }
-
- test_relativeDirective_downOneDirectory() async {
- addSource('/home/test/lib/dir/a.dart', '''
-import "b.dart";
-''');
- addSource('/home/test/lib/dir/b.dart', '''
-class Foo {}
-''');
- await resolveTestUnit('''
-main() { new Foo(); }
-''');
- await assertHasFix('''
-import 'dir/b.dart';
-
-main() { new Foo(); }
-''',
- expectedNumberOfFixesForKind: 2,
- matchFixMessage: "Import library 'dir/b.dart'");
+ matchFixMessage: "Import library '../a.dart'");
}
test_withClass_annotation() async {
@@ -395,7 +388,6 @@
@failingTest
test_withFunction_nonFunctionType() async {
- // TODO Remove preferFunctionOverTopLevelVariable test once this is passing
addSource('/home/test/lib/lib.dart', 'int zero = 0;');
await resolveTestUnit('''
main() {
@@ -405,25 +397,6 @@
await assertNoFix();
}
- test_withFunction_preferFunctionOverTopLevelVariable() async {
- _configureMyPkg({
- 'b.dart': 'var myFunction = () {};',
- 'a.dart': 'myFunction() {}',
- });
- await resolveTestUnit('''
-main() {
- myFunction();
-}
-''');
- await assertHasFix('''
-import 'package:my_pkg/a.dart';
-
-main() {
- myFunction();
-}
-''');
- }
-
test_withFunction_unresolvedMethod() async {
addSource('/home/test/lib/lib.dart', '''
library lib;
@@ -505,16 +478,17 @@
}
@reflectiveTest
-class ImportLibraryProject2Test extends FixProcessorTest
- with ImportLibraryTestMixin {
+class ImportLibraryProject2Test extends FixProcessorTest {
@override
FixKind get kind => DartFixKind.IMPORT_LIBRARY_PROJECT2;
- test_preferDirectOverExport() async {
- _configureMyPkg({
- 'b.dart': 'class Test {}',
- 'a.dart': "export 'b.dart';",
- });
+ test_lib() async {
+ addPackageFile('my_pkg', 'a.dart', "export 'b.dart';");
+ addPackageFile('my_pkg', 'b.dart', 'class Test {}');
+ newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+ my_pkg: any
+''');
await resolveTestUnit('''
main() {
Test test = null;
@@ -531,11 +505,13 @@
''');
}
- test_preferDirectOverExport_src() async {
- _configureMyPkg({
- 'b.dart': 'class Test {}',
- 'a.dart': "export 'b.dart';",
- });
+ test_lib_src() async {
+ addPackageFile('my_pkg', 'a.dart', "export 'src/b.dart';");
+ addPackageFile('my_pkg', 'src/b.dart', 'class Test {}');
+ newFile('/home/test/pubspec.yaml', content: r'''
+dependencies:
+ my_pkg: any
+''');
await resolveTestUnit('''
main() {
Test test = null;
@@ -593,15 +569,3 @@
''');
}
}
-
-mixin ImportLibraryTestMixin on FixProcessorTest {
- /// Configures the source factory to have a package named 'my_pkg' and for
- /// the package to contain all of the files described by the [pathToCode] map.
- /// The keys in the map are paths relative to the root of the package, and the
- /// values are the contents of the files at those paths.
- void _configureMyPkg(Map<String, String> pathToCode) {
- pathToCode.forEach((path, code) {
- addPackageFile('my_pkg', path, code);
- });
- }
-}
diff --git a/pkg/analysis_server/test/src/utilities/flutter_test.dart b/pkg/analysis_server/test/src/utilities/flutter_test.dart
index 6bb17e3..5a558ac 100644
--- a/pkg/analysis_server/test/src/utilities/flutter_test.dart
+++ b/pkg/analysis_server/test/src/utilities/flutter_test.dart
@@ -279,6 +279,16 @@
expect(flutter.identifyWidgetExpression(expression), expression);
}
+ test_identifyWidgetExpression_parent_expressionFunctionBody() async {
+ await resolveTestUnit('''
+import 'package:flutter/widgets.dart';
+
+main(Widget widget) => widget; // ref
+''');
+ Expression expression = findNodeAtString("widget; // ref");
+ expect(flutter.identifyWidgetExpression(expression), expression);
+ }
+
test_identifyWidgetExpression_parent_expressionStatement() async {
await resolveTestUnit('''
import 'package:flutter/widgets.dart';
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5cfc02b..f44d5ea 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -36,14 +36,14 @@
| initialize | ✅ | ✅ | ✅ | ✅ | trace and other options NYI
| initialized | ✅ | ✅ | ✅ | ✅ |
| shutdown | ✅ | ✅ | ✅ | ✅ | supported but does nothing |
-| exit | | | | | |
-| $/cancelRequest | | | | | ignored (unsupported) |
+| exit | ✅ | ✅ | ✅ | ✅ |
+| $/cancelRequest | ✅ | ✅ | ✅ | ✅ |
| window/showMessage | ✅ | | | |
| window/showMessageRequest | | | | |
| window/logMessage | ✅ | | | |
| telemetry/event | | | | |
-| client/registerCapability | | | | | unused, but should be used for DocumentSelector at least
-| client/unregisterCapability | | | | |
+| client/registerCapability | ✅ | ✅ | ✅ | ✅ |
+| client/unregisterCapability | | | | | (unused, capabilities don't change currently)
| workspace/workspaceFolders | | | | |
| workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ |
| workspace/configuration | | | | |
diff --git a/pkg/analysis_server/tool/lsp_spec/typescript.dart b/pkg/analysis_server/tool/lsp_spec/typescript.dart
index 130cbe2..f80733d 100644
--- a/pkg/analysis_server/tool/lsp_spec/typescript.dart
+++ b/pkg/analysis_server/tool/lsp_spec/typescript.dart
@@ -50,6 +50,9 @@
"TextDocumentSyncOptions": {
"change": "TextDocumentSyncKind",
},
+ "TextDocumentChangeRegistrationOptions": {
+ "syncKind": "TextDocumentSyncKind",
+ },
"FileSystemWatcher": {
"kind": "WatchKind",
},
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
index 5007ebd..8de0a91 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
@@ -16,10 +16,12 @@
public class CompletionService {
/**
- * The client will receive notifications once subscribed with completion suggestion sets from the
- * libraries of interest. The client should keep an up-to-date record of these in memory so that it
- * will be able to union these candidates with other completion suggestions when applicable at
- * completion time.
+ * The client will receive availableSuggestions notifications once subscribed with completion
+ * suggestion sets from the libraries of interest. The client should keep an up-to-date record of
+ * these in memory so that it will be able to union these candidates with other completion
+ * suggestions when applicable at completion time.
+ *
+ * The client will also receive existingImports notifications.
*/
public static final String AVAILABLE_SUGGESTION_SETS = "AVAILABLE_SUGGESTION_SETS";
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
new file mode 100644
index 0000000..a9055d0
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImport.java
@@ -0,0 +1,132 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about an existing import, with elements that it provides.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImport {
+
+ public static final ExistingImport[] EMPTY_ARRAY = new ExistingImport[0];
+
+ public static final List<ExistingImport> EMPTY_LIST = Lists.newArrayList();
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in the enclosing
+ * ExistingImports and its ImportedElementSet object.
+ */
+ private final int uri;
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ private final int[] elements;
+
+ /**
+ * Constructor for {@link ExistingImport}.
+ */
+ public ExistingImport(int uri, int[] elements) {
+ this.uri = uri;
+ this.elements = elements;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExistingImport) {
+ ExistingImport other = (ExistingImport) obj;
+ return
+ other.uri == uri &&
+ Arrays.equals(other.elements, elements);
+ }
+ return false;
+ }
+
+ public static ExistingImport fromJson(JsonObject jsonObject) {
+ int uri = jsonObject.get("uri").getAsInt();
+ int[] elements = JsonUtilities.decodeIntArray(jsonObject.get("elements").getAsJsonArray());
+ return new ExistingImport(uri, elements);
+ }
+
+ public static List<ExistingImport> fromJsonArray(JsonArray jsonArray) {
+ if (jsonArray == null) {
+ return EMPTY_LIST;
+ }
+ ArrayList<ExistingImport> list = new ArrayList<ExistingImport>(jsonArray.size());
+ Iterator<JsonElement> iterator = jsonArray.iterator();
+ while (iterator.hasNext()) {
+ list.add(fromJson(iterator.next().getAsJsonObject()));
+ }
+ return list;
+ }
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ public int[] getElements() {
+ return elements;
+ }
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in the enclosing
+ * ExistingImports and its ImportedElementSet object.
+ */
+ public int getUri() {
+ return uri;
+ }
+
+ @Override
+ public int hashCode() {
+ HashCodeBuilder builder = new HashCodeBuilder();
+ builder.append(uri);
+ builder.append(elements);
+ return builder.toHashCode();
+ }
+
+ public JsonObject toJson() {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("uri", uri);
+ JsonArray jsonArrayElements = new JsonArray();
+ for (int elt : elements) {
+ jsonArrayElements.add(new JsonPrimitive(elt));
+ }
+ jsonObject.add("elements", jsonArrayElements);
+ return jsonObject;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("uri=");
+ builder.append(uri + ", ");
+ builder.append("elements=");
+ builder.append(StringUtils.join(elements, ", "));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
new file mode 100644
index 0000000..7473d829
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExistingImports.java
@@ -0,0 +1,130 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Information about all existing imports in a library.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExistingImports {
+
+ public static final ExistingImports[] EMPTY_ARRAY = new ExistingImports[0];
+
+ public static final List<ExistingImports> EMPTY_LIST = Lists.newArrayList();
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ private final ImportedElementSet elements;
+
+ /**
+ * The list of imports in the library.
+ */
+ private final List<ExistingImport> imports;
+
+ /**
+ * Constructor for {@link ExistingImports}.
+ */
+ public ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+ this.elements = elements;
+ this.imports = imports;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExistingImports) {
+ ExistingImports other = (ExistingImports) obj;
+ return
+ ObjectUtilities.equals(other.elements, elements) &&
+ ObjectUtilities.equals(other.imports, imports);
+ }
+ return false;
+ }
+
+ public static ExistingImports fromJson(JsonObject jsonObject) {
+ ImportedElementSet elements = ImportedElementSet.fromJson(jsonObject.get("elements").getAsJsonObject());
+ List<ExistingImport> imports = ExistingImport.fromJsonArray(jsonObject.get("imports").getAsJsonArray());
+ return new ExistingImports(elements, imports);
+ }
+
+ public static List<ExistingImports> fromJsonArray(JsonArray jsonArray) {
+ if (jsonArray == null) {
+ return EMPTY_LIST;
+ }
+ ArrayList<ExistingImports> list = new ArrayList<ExistingImports>(jsonArray.size());
+ Iterator<JsonElement> iterator = jsonArray.iterator();
+ while (iterator.hasNext()) {
+ list.add(fromJson(iterator.next().getAsJsonObject()));
+ }
+ return list;
+ }
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ public ImportedElementSet getElements() {
+ return elements;
+ }
+
+ /**
+ * The list of imports in the library.
+ */
+ public List<ExistingImport> getImports() {
+ return imports;
+ }
+
+ @Override
+ public int hashCode() {
+ HashCodeBuilder builder = new HashCodeBuilder();
+ builder.append(elements);
+ builder.append(imports);
+ return builder.toHashCode();
+ }
+
+ public JsonObject toJson() {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("elements", elements.toJson());
+ JsonArray jsonArrayImports = new JsonArray();
+ for (ExistingImport elt : imports) {
+ jsonArrayImports.add(elt.toJson());
+ }
+ jsonObject.add("imports", jsonArrayImports);
+ return jsonObject;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("elements=");
+ builder.append(elements + ", ");
+ builder.append("imports=");
+ builder.append(StringUtils.join(imports, ", "));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
index 463b420..88e6f0b 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/HoverInformation.java
@@ -55,8 +55,9 @@
private final String containingLibraryPath;
/**
- * The name of the library in which the referenced element is declared. This data is omitted if
- * there is no referenced element, or if the element is declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+ * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+ * HTML file.
*/
private final String containingLibraryName;
@@ -185,8 +186,9 @@
}
/**
- * The name of the library in which the referenced element is declared. This data is omitted if
- * there is no referenced element, or if the element is declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core", "package:.." and file uris
+ * represented by the path on disk, "/..". The data is omitted if the element is declared inside an
+ * HTML file.
*/
public String getContainingLibraryName() {
return containingLibraryName;
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
new file mode 100644
index 0000000..50ca031
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ImportedElementSet.java
@@ -0,0 +1,158 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import com.google.common.collect.Lists;
+import com.google.dart.server.utilities.general.JsonUtilities;
+import com.google.dart.server.utilities.general.ObjectUtilities;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import java.util.ArrayList;
+import java.util.Iterator;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * The set of top-level elements encoded as pairs of the defining library URI and the name, and
+ * stored in the parallel lists elementUris and elementNames.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ImportedElementSet {
+
+ public static final ImportedElementSet[] EMPTY_ARRAY = new ImportedElementSet[0];
+
+ public static final List<ImportedElementSet> EMPTY_LIST = Lists.newArrayList();
+
+ /**
+ * The list of unique strings in this object.
+ */
+ private final List<String> strings;
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ private final int[] uris;
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ private final int[] names;
+
+ /**
+ * Constructor for {@link ImportedElementSet}.
+ */
+ public ImportedElementSet(List<String> strings, int[] uris, int[] names) {
+ this.strings = strings;
+ this.uris = uris;
+ this.names = names;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ImportedElementSet) {
+ ImportedElementSet other = (ImportedElementSet) obj;
+ return
+ ObjectUtilities.equals(other.strings, strings) &&
+ Arrays.equals(other.uris, uris) &&
+ Arrays.equals(other.names, names);
+ }
+ return false;
+ }
+
+ public static ImportedElementSet fromJson(JsonObject jsonObject) {
+ List<String> strings = JsonUtilities.decodeStringList(jsonObject.get("strings").getAsJsonArray());
+ int[] uris = JsonUtilities.decodeIntArray(jsonObject.get("uris").getAsJsonArray());
+ int[] names = JsonUtilities.decodeIntArray(jsonObject.get("names").getAsJsonArray());
+ return new ImportedElementSet(strings, uris, names);
+ }
+
+ public static List<ImportedElementSet> fromJsonArray(JsonArray jsonArray) {
+ if (jsonArray == null) {
+ return EMPTY_LIST;
+ }
+ ArrayList<ImportedElementSet> list = new ArrayList<ImportedElementSet>(jsonArray.size());
+ Iterator<JsonElement> iterator = jsonArray.iterator();
+ while (iterator.hasNext()) {
+ list.add(fromJson(iterator.next().getAsJsonObject()));
+ }
+ return list;
+ }
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ public int[] getNames() {
+ return names;
+ }
+
+ /**
+ * The list of unique strings in this object.
+ */
+ public List<String> getStrings() {
+ return strings;
+ }
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ public int[] getUris() {
+ return uris;
+ }
+
+ @Override
+ public int hashCode() {
+ HashCodeBuilder builder = new HashCodeBuilder();
+ builder.append(strings);
+ builder.append(uris);
+ builder.append(names);
+ return builder.toHashCode();
+ }
+
+ public JsonObject toJson() {
+ JsonObject jsonObject = new JsonObject();
+ JsonArray jsonArrayStrings = new JsonArray();
+ for (String elt : strings) {
+ jsonArrayStrings.add(new JsonPrimitive(elt));
+ }
+ jsonObject.add("strings", jsonArrayStrings);
+ JsonArray jsonArrayUris = new JsonArray();
+ for (int elt : uris) {
+ jsonArrayUris.add(new JsonPrimitive(elt));
+ }
+ jsonObject.add("uris", jsonArrayUris);
+ JsonArray jsonArrayNames = new JsonArray();
+ for (int elt : names) {
+ jsonArrayNames.add(new JsonPrimitive(elt));
+ }
+ jsonObject.add("names", jsonArrayNames);
+ return jsonObject;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("strings=");
+ builder.append(StringUtils.join(strings, ", ") + ", ");
+ builder.append("uris=");
+ builder.append(StringUtils.join(uris, ", ") + ", ");
+ builder.append("names=");
+ builder.append(StringUtils.join(names, ", "));
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 362a389..e49442e 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.26.1</version>
+ <version>1.27.0</version>
</h1>
<p>
This document contains a specification of the API provided by the
@@ -1588,6 +1588,17 @@
returned for the indicated completion.
</p>
</field>
+ <field name="libraryFile" optional="true">
+ <ref>FilePath</ref>
+ <p>
+ The library file that contains the file where completion was
+ requested. The client might use it for example together with the
+ <tt>existingImports</tt> notification to filter out available
+ suggestions. If there were changes to existing imports in the library,
+ the corresponding <tt>existingImports</tt> notification will be sent
+ before the completion notification.
+ </p>
+ </field>
<field name="includedSuggestionSets" optional="true">
<list>
<ref>IncludedSuggestionSet</ref>
@@ -1658,6 +1669,27 @@
</field>
</params>
</notification>
+ <notification event="existingImports">
+ <p>
+ Reports existing imports in a library. This notification may be sent
+ multiple times for a library. When a notification is processed, clients
+ should replace any previous information for the library.
+ </p>
+ <params>
+ <field name="file">
+ <ref>FilePath</ref>
+ <p>
+ The defining file of the library.
+ </p>
+ </field>
+ <field name="imports">
+ <ref>ExistingImports</ref>
+ <p>
+ The existing imports in the library.
+ </p>
+ </field>
+ </params>
+ </notification>
</domain>
<domain name="search">
<p>
@@ -3669,6 +3701,86 @@
</field>
</object>
</type>
+ <type name="ExistingImport">
+ <p>
+ Information about an existing import, with elements that it provides.
+ </p>
+ <object>
+ <field name="uri">
+ <ref>int</ref>
+ <p>
+ The URI of the imported library.
+ It is an index in the <tt>strings</tt> field, in the enclosing
+ <tt>ExistingImports</tt> and its <tt>ImportedElementSet</tt> object.
+ </p>
+ </field>
+ <field name="elements">
+ <list>
+ <ref>int</ref>
+ </list>
+ <p>
+ The list of indexes of elements, in the enclosing
+ <tt>ExistingImports</tt> object.
+ </p>
+ </field>
+ </object>
+ </type>
+ <type name="ExistingImports">
+ <p>
+ Information about all existing imports in a library.
+ </p>
+ <object>
+ <field name="elements">
+ <ref>ImportedElementSet</ref>
+ <p>
+ The set of all unique imported elements for all imports.
+ </p>
+ </field>
+ <field name="imports">
+ <list>
+ <ref>ExistingImport</ref>
+ </list>
+ <p>
+ The list of imports in the library.
+ </p>
+ </field>
+ </object>
+ </type>
+ <type name="ImportedElementSet">
+ <p>
+ The set of top-level elements encoded as pairs of the defining library
+ URI and the name, and stored in the parallel lists <tt>elementUris</tt>
+ and <tt>elementNames</tt>.
+ </p>
+ <object>
+ <field name="strings">
+ <list>
+ <ref>String</ref>
+ </list>
+ <p>
+ The list of unique strings in this object.
+ </p>
+ </field>
+ <field name="uris">
+ <list>
+ <ref>int</ref>
+ </list>
+ <p>
+ The library URI part of the element.
+ It is an index in the <tt>strings</tt> field.
+ </p>
+ </field>
+ <field name="names">
+ <list>
+ <ref>int</ref>
+ </list>
+ <p>
+ The name part of a the element.
+ It is an index in the <tt>strings</tt> field.
+ </p>
+ </field>
+ </object>
+ </type>
<type name="IncludedSuggestionSet">
<p>
A reference to an <tt>AvailableSuggestionSet</tt> noting
@@ -3737,11 +3849,15 @@
<value>
<code>AVAILABLE_SUGGESTION_SETS</code>
<p>
- The client will receive notifications once subscribed with completion suggestion sets from
- the libraries of interest. The client should keep an up-to-date record of these in
+ The client will receive <tt>availableSuggestions</tt> notifications
+ once subscribed with completion suggestion sets from the libraries of
+ interest. The client should keep an up-to-date record of these in
memory so that it will be able to union these candidates with other
completion suggestions when applicable at completion time.
</p>
+ <p>
+ The client will also receive <tt>existingImports</tt> notifications.
+ </p>
</value>
</enum>
</type>
@@ -4212,10 +4328,10 @@
<field name="containingLibraryName" optional="true">
<ref>String</ref>
<p>
- The name of the library in which the referenced element is
- declared. This data is omitted if there is no referenced
- element, or if the element is declared inside an HTML
- file.
+ The URI of the containing library, examples here include
+ "dart:core", "package:.." and file uris represented by the
+ path on disk, "/..". The data is omitted if the element is
+ declared inside an HTML file.
</p>
</field>
<field name="containingClassDescription" optional="true">
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
index 97ec840..b85aa31 100644
--- a/pkg/analysis_server_client/lib/handler/notification_handler.dart
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -72,6 +72,11 @@
new CompletionAvailableSuggestionsParams.fromJson(
decoder, 'params', params));
break;
+ case COMPLETION_NOTIFICATION_EXISTING_IMPORTS:
+ onCompletionExistingImports(
+ new CompletionExistingImportsParams.fromJson(
+ decoder, 'params', params));
+ break;
case COMPLETION_NOTIFICATION_RESULTS:
onCompletionResults(
new CompletionResultsParams.fromJson(decoder, 'params', params));
@@ -221,6 +226,11 @@
void onCompletionAvailableSuggestions(
CompletionAvailableSuggestionsParams params) {}
+ /// Reports existing imports in a library. This notification may be sent
+ /// multiple times for a library. When a notification is processed, clients
+ /// should replace any previous information for the library.
+ void onCompletionExistingImports(CompletionExistingImportsParams params) {}
+
/// Reports the completion suggestions that should be presented
/// to the user. The set of suggestions included in the
/// notification is always a complete list that supersedes any
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 af958c9..b944f0f 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.26.1';
+const String PROTOCOL_VERSION = '1.27.0';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -116,6 +116,10 @@
'changedLibraries';
const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
'removedLibraries';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS =
+ 'completion.existingImports';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_FILE = 'file';
+const String COMPLETION_NOTIFICATION_EXISTING_IMPORTS_IMPORTS = 'imports';
const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_ELEMENT_KINDS =
@@ -126,6 +130,7 @@
const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
'includedSuggestionSets';
const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
+const String COMPLETION_NOTIFICATION_RESULTS_LIBRARY_FILE = 'libraryFile';
const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
'replacementLength';
const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_OFFSET =
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 5d1b076..44ef533e 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5803,6 +5803,116 @@
}
/**
+ * completion.existingImports params
+ *
+ * {
+ * "file": FilePath
+ * "imports": ExistingImports
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionExistingImportsParams implements HasToJson {
+ String _file;
+
+ ExistingImports _imports;
+
+ /**
+ * The defining file of the library.
+ */
+ String get file => _file;
+
+ /**
+ * The defining file of the library.
+ */
+ void set file(String value) {
+ assert(value != null);
+ this._file = value;
+ }
+
+ /**
+ * The existing imports in the library.
+ */
+ ExistingImports get imports => _imports;
+
+ /**
+ * The existing imports in the library.
+ */
+ void set imports(ExistingImports value) {
+ assert(value != null);
+ this._imports = value;
+ }
+
+ CompletionExistingImportsParams(String file, ExistingImports imports) {
+ this.file = file;
+ this.imports = imports;
+ }
+
+ factory CompletionExistingImportsParams.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ String file;
+ if (json.containsKey("file")) {
+ file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "file");
+ }
+ ExistingImports imports;
+ if (json.containsKey("imports")) {
+ imports = new ExistingImports.fromJson(
+ jsonDecoder, jsonPath + ".imports", json["imports"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "imports");
+ }
+ return new CompletionExistingImportsParams(file, imports);
+ } else {
+ throw jsonDecoder.mismatch(
+ jsonPath, "completion.existingImports params", json);
+ }
+ }
+
+ factory CompletionExistingImportsParams.fromNotification(
+ Notification notification) {
+ return new CompletionExistingImportsParams.fromJson(
+ new ResponseDecoder(null), "params", notification.params);
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["file"] = file;
+ result["imports"] = imports.toJson();
+ return result;
+ }
+
+ Notification toNotification() {
+ return new Notification("completion.existingImports", toJson());
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is CompletionExistingImportsParams) {
+ return file == other.file && imports == other.imports;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, file.hashCode);
+ hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* completion.getSuggestionDetails params
*
* {
@@ -6593,6 +6703,7 @@
* "replacementLength": int
* "results": List<CompletionSuggestion>
* "isLast": bool
+ * "libraryFile": optional FilePath
* "includedSuggestionSets": optional List<IncludedSuggestionSet>
* "includedElementKinds": optional List<ElementKind>
* "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
@@ -6611,6 +6722,8 @@
bool _isLast;
+ String _libraryFile;
+
List<IncludedSuggestionSet> _includedSuggestionSets;
List<ElementKind> _includedElementKinds;
@@ -6703,6 +6816,26 @@
}
/**
+ * The library file that contains the file where completion was requested.
+ * The client might use it for example together with the existingImports
+ * notification to filter out available suggestions. If there were changes to
+ * existing imports in the library, the corresponding existingImports
+ * notification will be sent before the completion notification.
+ */
+ String get libraryFile => _libraryFile;
+
+ /**
+ * The library file that contains the file where completion was requested.
+ * The client might use it for example together with the existingImports
+ * notification to filter out available suggestions. If there were changes to
+ * existing imports in the library, the corresponding existingImports
+ * notification will be sent before the completion notification.
+ */
+ void set libraryFile(String value) {
+ this._libraryFile = value;
+ }
+
+ /**
* References to AvailableSuggestionSet objects previously sent to the
* client. The client can include applicable names from the referenced
* library in code completion suggestions.
@@ -6765,7 +6898,8 @@
CompletionResultsParams(String id, int replacementOffset,
int replacementLength, List<CompletionSuggestion> results, bool isLast,
- {List<IncludedSuggestionSet> includedSuggestionSets,
+ {String libraryFile,
+ List<IncludedSuggestionSet> includedSuggestionSets,
List<ElementKind> includedElementKinds,
List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
this.id = id;
@@ -6773,6 +6907,7 @@
this.replacementLength = replacementLength;
this.results = results;
this.isLast = isLast;
+ this.libraryFile = libraryFile;
this.includedSuggestionSets = includedSuggestionSets;
this.includedElementKinds = includedElementKinds;
this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
@@ -6820,6 +6955,11 @@
} else {
throw jsonDecoder.mismatch(jsonPath, "isLast");
}
+ String libraryFile;
+ if (json.containsKey("libraryFile")) {
+ libraryFile = jsonDecoder.decodeString(
+ jsonPath + ".libraryFile", json["libraryFile"]);
+ }
List<IncludedSuggestionSet> includedSuggestionSets;
if (json.containsKey("includedSuggestionSets")) {
includedSuggestionSets = jsonDecoder.decodeList(
@@ -6848,6 +6988,7 @@
}
return new CompletionResultsParams(
id, replacementOffset, replacementLength, results, isLast,
+ libraryFile: libraryFile,
includedSuggestionSets: includedSuggestionSets,
includedElementKinds: includedElementKinds,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
@@ -6870,6 +7011,9 @@
result["results"] =
results.map((CompletionSuggestion value) => value.toJson()).toList();
result["isLast"] = isLast;
+ if (libraryFile != null) {
+ result["libraryFile"] = libraryFile;
+ }
if (includedSuggestionSets != null) {
result["includedSuggestionSets"] = includedSuggestionSets
.map((IncludedSuggestionSet value) => value.toJson())
@@ -6905,6 +7049,7 @@
listEqual(results, other.results,
(CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
isLast == other.isLast &&
+ libraryFile == other.libraryFile &&
listEqual(includedSuggestionSets, other.includedSuggestionSets,
(IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
listEqual(includedElementKinds, other.includedElementKinds,
@@ -6927,6 +7072,7 @@
hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
hash = JenkinsSmiHash.combine(hash, results.hashCode);
hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+ hash = JenkinsSmiHash.combine(hash, libraryFile.hashCode);
hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
hash = JenkinsSmiHash.combine(hash, includedElementKinds.hashCode);
hash =
@@ -6946,11 +7092,13 @@
*/
class CompletionService implements Enum {
/**
- * The client will receive notifications once subscribed with completion
- * suggestion sets from the libraries of interest. The client should keep an
- * up-to-date record of these in memory so that it will be able to union
- * these candidates with other completion suggestions when applicable at
- * completion time.
+ * The client will receive availableSuggestions notifications once subscribed
+ * with completion suggestion sets from the libraries of interest. The client
+ * should keep an up-to-date record of these in memory so that it will be
+ * able to union these candidates with other completion suggestions when
+ * applicable at completion time.
+ *
+ * The client will also receive existingImports notifications.
*/
static const CompletionService AVAILABLE_SUGGESTION_SETS =
const CompletionService._("AVAILABLE_SUGGESTION_SETS");
@@ -13011,6 +13159,214 @@
}
/**
+ * ExistingImport
+ *
+ * {
+ * "uri": int
+ * "elements": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImport implements HasToJson {
+ int _uri;
+
+ List<int> _elements;
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in
+ * the enclosing ExistingImports and its ImportedElementSet object.
+ */
+ int get uri => _uri;
+
+ /**
+ * The URI of the imported library. It is an index in the strings field, in
+ * the enclosing ExistingImports and its ImportedElementSet object.
+ */
+ void set uri(int value) {
+ assert(value != null);
+ this._uri = value;
+ }
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ List<int> get elements => _elements;
+
+ /**
+ * The list of indexes of elements, in the enclosing ExistingImports object.
+ */
+ void set elements(List<int> value) {
+ assert(value != null);
+ this._elements = value;
+ }
+
+ ExistingImport(int uri, List<int> elements) {
+ this.uri = uri;
+ this.elements = elements;
+ }
+
+ factory ExistingImport.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ int uri;
+ if (json.containsKey("uri")) {
+ uri = jsonDecoder.decodeInt(jsonPath + ".uri", json["uri"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "uri");
+ }
+ List<int> elements;
+ if (json.containsKey("elements")) {
+ elements = jsonDecoder.decodeList(
+ jsonPath + ".elements", json["elements"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "elements");
+ }
+ return new ExistingImport(uri, elements);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ExistingImport", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["uri"] = uri;
+ result["elements"] = elements;
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExistingImport) {
+ return uri == other.uri &&
+ listEqual(elements, other.elements, (int a, int b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+ hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
+ * ExistingImports
+ *
+ * {
+ * "elements": ImportedElementSet
+ * "imports": List<ExistingImport>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExistingImports implements HasToJson {
+ ImportedElementSet _elements;
+
+ List<ExistingImport> _imports;
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ ImportedElementSet get elements => _elements;
+
+ /**
+ * The set of all unique imported elements for all imports.
+ */
+ void set elements(ImportedElementSet value) {
+ assert(value != null);
+ this._elements = value;
+ }
+
+ /**
+ * The list of imports in the library.
+ */
+ List<ExistingImport> get imports => _imports;
+
+ /**
+ * The list of imports in the library.
+ */
+ void set imports(List<ExistingImport> value) {
+ assert(value != null);
+ this._imports = value;
+ }
+
+ ExistingImports(ImportedElementSet elements, List<ExistingImport> imports) {
+ this.elements = elements;
+ this.imports = imports;
+ }
+
+ factory ExistingImports.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ ImportedElementSet elements;
+ if (json.containsKey("elements")) {
+ elements = new ImportedElementSet.fromJson(
+ jsonDecoder, jsonPath + ".elements", json["elements"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "elements");
+ }
+ List<ExistingImport> imports;
+ if (json.containsKey("imports")) {
+ imports = jsonDecoder.decodeList(
+ jsonPath + ".imports",
+ json["imports"],
+ (String jsonPath, Object json) =>
+ new ExistingImport.fromJson(jsonDecoder, jsonPath, json));
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "imports");
+ }
+ return new ExistingImports(elements, imports);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ExistingImports", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["elements"] = elements.toJson();
+ result["imports"] =
+ imports.map((ExistingImport value) => value.toJson()).toList();
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExistingImports) {
+ return elements == other.elements &&
+ listEqual(imports, other.imports,
+ (ExistingImport a, ExistingImport b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, elements.hashCode);
+ hash = JenkinsSmiHash.combine(hash, imports.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* extractLocalVariable feedback
*
* {
@@ -15586,16 +15942,16 @@
}
/**
- * The name of the library in which the referenced element is declared. This
- * data is omitted if there is no referenced element, or if the element is
- * declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core",
+ * "package:.." and file uris represented by the path on disk, "/..". The
+ * data is omitted if the element is declared inside an HTML file.
*/
String get containingLibraryName => _containingLibraryName;
/**
- * The name of the library in which the referenced element is declared. This
- * data is omitted if there is no referenced element, or if the element is
- * declared inside an HTML file.
+ * The URI of the containing library, examples here include "dart:core",
+ * "package:.." and file uris represented by the path on disk, "/..". The
+ * data is omitted if the element is declared inside an HTML file.
*/
void set containingLibraryName(String value) {
this._containingLibraryName = value;
@@ -16109,6 +16465,135 @@
}
/**
+ * ImportedElementSet
+ *
+ * {
+ * "strings": List<String>
+ * "uris": List<int>
+ * "names": List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ImportedElementSet implements HasToJson {
+ List<String> _strings;
+
+ List<int> _uris;
+
+ List<int> _names;
+
+ /**
+ * The list of unique strings in this object.
+ */
+ List<String> get strings => _strings;
+
+ /**
+ * The list of unique strings in this object.
+ */
+ void set strings(List<String> value) {
+ assert(value != null);
+ this._strings = value;
+ }
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ List<int> get uris => _uris;
+
+ /**
+ * The library URI part of the element. It is an index in the strings field.
+ */
+ void set uris(List<int> value) {
+ assert(value != null);
+ this._uris = value;
+ }
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ List<int> get names => _names;
+
+ /**
+ * The name part of a the element. It is an index in the strings field.
+ */
+ void set names(List<int> value) {
+ assert(value != null);
+ this._names = value;
+ }
+
+ ImportedElementSet(List<String> strings, List<int> uris, List<int> names) {
+ this.strings = strings;
+ this.uris = uris;
+ this.names = names;
+ }
+
+ factory ImportedElementSet.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ List<String> strings;
+ if (json.containsKey("strings")) {
+ strings = jsonDecoder.decodeList(
+ jsonPath + ".strings", json["strings"], jsonDecoder.decodeString);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "strings");
+ }
+ List<int> uris;
+ if (json.containsKey("uris")) {
+ uris = jsonDecoder.decodeList(
+ jsonPath + ".uris", json["uris"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "uris");
+ }
+ List<int> names;
+ if (json.containsKey("names")) {
+ names = jsonDecoder.decodeList(
+ jsonPath + ".names", json["names"], jsonDecoder.decodeInt);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "names");
+ }
+ return new ImportedElementSet(strings, uris, names);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "ImportedElementSet", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["strings"] = strings;
+ result["uris"] = uris;
+ result["names"] = names;
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ImportedElementSet) {
+ return listEqual(
+ strings, other.strings, (String a, String b) => a == b) &&
+ listEqual(uris, other.uris, (int a, int b) => a == b) &&
+ listEqual(names, other.names, (int a, int b) => a == b);
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, strings.hashCode);
+ hash = JenkinsSmiHash.combine(hash, uris.hashCode);
+ hash = JenkinsSmiHash.combine(hash, names.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* ImportedElements
*
* {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index e305a68..37ac0ad 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -4,6 +4,15 @@
`featureSet` parameter.
* Refined the return type of the getter `TypeParameter.declaredElement`. It is
always guaranteed to return a `TypeParameterElement`.
+* Deprecated the `abstract` setter in `ClassElementImpl`, `EnumElementImpl`,
+ `MethodElementImpl`, and `PropertyAccessorElementImpl`. `isAbstract` should
+ be used instead.
+* Changed the way function types are displayed from e.g. `(int) -> void` to
+ `void Function(int)`. This is more consistent with the syntax of Dart, and it
+ will avoid ambiguities when nullability is added to the type system. This
+ impacts to value returned by `FunctionType.displayName` and
+ `FunctionType.toString` and `ExecutableElement.toString`. Client code might be
+ broken if it depends on the content of the returned value.
## 0.36.3
* Deprecated `AstFactory.compilationUnit`. In a future analyzer release, this
diff --git a/pkg/analyzer/doc/tutorial/analysis.md b/pkg/analyzer/doc/tutorial/analysis.md
index a44d6a5..e71d245 100644
--- a/pkg/analyzer/doc/tutorial/analysis.md
+++ b/pkg/analyzer/doc/tutorial/analysis.md
@@ -24,9 +24,14 @@
main() {
List<String> includedPaths = <String>[/* ... */];
AnalysisContextCollection collection =
- new AnalysisContextCollection(includedPaths);
+ new AnalysisContextCollection(includedPaths: includedPaths);
analyzeSomeFiles(collection, includedPaths);
}
+
+analyzeSomeFiles(
+ AnalysisContextCollection collection, List<String> includedPaths) {
+ // See below.
+}
```
The collection will create one or more analysis contexts that can be used to
@@ -52,6 +57,10 @@
analyzeSingleFile(context, path);
}
}
+
+analyzeSingleFile(AnalysisContext context, String path) {
+ // See below.
+}
```
## Analyzing Multiple Files
@@ -68,6 +77,10 @@
}
}
}
+
+analyzeSingleFile(AnalysisContext context, String path) {
+ // See below.
+}
```
The files returned this way will include _all_ of the files in all of the
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index fd41d31..57af577 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -50,21 +50,12 @@
to get the compilation unit for a file at a known `path`, then you can ask the
analysis session for an AST.
-If you need an unresolved AST, then you can use either a synchronous or
-asynchronous method to access the AST:
+If you need an unresolved AST, then you can use the following method to access
+the AST:
```dart
-main() async {
- ParseResult result = await session.getParsedAst(path);
- CompilationUnit unit = result.unit;
-}
-```
-
-or
-
-```dart
-main() {
- ParseResult result = session.getParsedAstSync(path);
+processFile(AnalysisSession session, String path) {
+ ParsedUnitResult result = session.getParsedUnit(path);
CompilationUnit unit = result.unit;
}
```
@@ -73,8 +64,8 @@
method to access it:
```dart
-main() async {
- ResolveResult result = await session.getResolvedAst(path);
+processFile(AnalysisSession session, String path) async {
+ ResolvedUnitResult result = await session.getResolvedUnit(path);
CompilationUnit unit = result.unit;
}
```
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 6f31a7b..542661b 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -122,11 +121,6 @@
/// complete with [SourceKind.UNKNOWN].
Future<SourceKind> getSourceKind(String path);
- /// Return a future that will complete with a list of the top-level
- /// declarations with the given [name] in all known libraries.
- Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
- String name);
-
/// Return a future that will complete with information about the results of
/// building the element model for the file with the given absolute,
/// normalized[path].
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 008e727..a34b97c 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -500,6 +500,8 @@
R visitExtendsClause(ExtendsClause node);
+ R visitExtensionDeclaration(ExtensionDeclaration node);
+
R visitFieldDeclaration(FieldDeclaration node);
R visitFieldFormalParameter(FieldFormalParameter node);
@@ -2108,6 +2110,37 @@
void set superclass(TypeName name);
}
+/// The declaration of an extension of a type.
+///
+/// extension ::=
+/// 'extension' [SimpleIdentifier] [TypeParameterList]?
+/// 'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExtensionDeclaration implements NamedCompilationUnitMember {
+ /// Return the type that is being extended.
+ TypeAnnotation get extendedType;
+
+ /// Return the token representing the 'extension' keyword.
+ Token get extensionKeyword;
+
+ /// Return the left curly bracket.
+ Token get leftBracket;
+
+ /// Return the members being added to the extended class.
+ NodeList<ClassMember> get members;
+
+ /// Return the token representing the 'on' keyword.
+ Token get onKeyword;
+
+ /// Return the right curly bracket.
+ Token get rightBracket;
+
+ /// Return the type parameters for the extension, or `null` if the extension
+ /// does not have any type parameters.
+ TypeParameterList get typeParameters;
+}
+
/// The declaration of one or more fields of the same type.
///
/// fieldDeclaration ::=
@@ -2777,7 +2810,8 @@
/// A function-typed formal parameter.
///
/// functionSignature ::=
-/// [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+/// [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]?
+/// [FormalParameterList] '?'?
///
/// Clients may not extend, implement or mix-in this class.
abstract class FunctionTypedFormalParameter implements NormalFormalParameter {
@@ -2788,6 +2822,11 @@
/// [parameters].
void set parameters(FormalParameterList parameters);
+ /// Return the question mark indicating that the function type is nullable, or
+ /// `null` if there is no question mark. Having a nullable function type means
+ /// that the parameter can be null.
+ Token get question;
+
/// Return the return type of the function, or `null` if the function does not
/// have a return type.
TypeAnnotation get returnType;
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index 815ad03..2796e1a 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -339,6 +339,20 @@
/// Returns a newly created extends clause.
ExtendsClause extendsClause(Token extendsKeyword, TypeName superclass);
+ /// Return a newly created extention declaration. The list of [typeParameters]
+ /// can be `null` if there are no type parameters.
+ ExtensionDeclaration extensionDeclaration(
+ {Comment comment,
+ List<Annotation> metadata,
+ Token extensionKeyword,
+ @required SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ Token onKeyword,
+ @required TypeAnnotation extendedType,
+ Token leftBracket,
+ List<ClassMember> members,
+ Token rightBracket});
+
/// 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
@@ -535,7 +549,8 @@
TypeAnnotation returnType,
@required SimpleIdentifier identifier,
TypeParameterList typeParameters,
- @required FormalParameterList parameters});
+ @required FormalParameterList parameters,
+ Token question});
/// Initialize a newly created generic function type.
GenericFunctionType genericFunctionType(
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index 6646631..68f4621 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -277,6 +277,10 @@
R visitExtendsClause(ExtendsClause node) => visitNode(node);
@override
+ R visitExtensionDeclaration(ExtensionDeclaration node) =>
+ visitNamedCompilationUnitMember(node);
+
+ @override
R visitFieldDeclaration(FieldDeclaration node) => visitClassMember(node);
@override
@@ -839,6 +843,12 @@
}
@override
+ R visitExtensionDeclaration(ExtensionDeclaration node) {
+ node.visitChildren(this);
+ return null;
+ }
+
+ @override
R visitFieldDeclaration(FieldDeclaration node) {
node.visitChildren(this);
return null;
@@ -1447,6 +1457,9 @@
R visitExtendsClause(ExtendsClause node) => null;
@override
+ R visitExtensionDeclaration(ExtensionDeclaration node) => null;
+
+ @override
R visitFieldDeclaration(FieldDeclaration node) => null;
@override
@@ -1822,6 +1835,9 @@
R visitExtendsClause(ExtendsClause node) => _throw(node);
@override
+ R visitExtensionDeclaration(ExtensionDeclaration node) => _throw(node);
+
+ @override
R visitFieldDeclaration(FieldDeclaration node) => _throw(node);
@override
@@ -2406,6 +2422,14 @@
}
@override
+ T visitExtensionDeclaration(ExtensionDeclaration node) {
+ stopwatch.start();
+ T result = _baseVisitor.visitExtensionDeclaration(node);
+ stopwatch.stop();
+ return result;
+ }
+
+ @override
T visitFieldDeclaration(FieldDeclaration node) {
stopwatch.start();
T result = _baseVisitor.visitFieldDeclaration(node);
@@ -3181,6 +3205,9 @@
R visitExtendsClause(ExtendsClause node) => visitNode(node);
@override
+ R visitExtensionDeclaration(ExtensionDeclaration node) => visitNode(node);
+
+ @override
R visitFieldDeclaration(FieldDeclaration node) => visitNode(node);
@override
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index ce67ab7..7c2812a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -29,6 +29,9 @@
abstract class DartType {
/// Return the name of this type as it should appear when presented to users
/// in contexts such as error messages.
+ ///
+ /// Clients should not depend on the content of the returned value as it will
+ /// be changed if doing so would improve the UX.
String get displayName;
/// Return the element representing the declaration of this type, or `null` if
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 8902935..ed09816 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -290,6 +290,7 @@
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR,
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
CompileTimeErrorCode.YIELD_EACH_IN_NON_GENERATOR,
CompileTimeErrorCode.YIELD_IN_NON_GENERATOR,
HintCode.CAN_BE_NULL_AFTER_NULL_AWARE,
@@ -423,6 +424,7 @@
ParserErrorCode.EMPTY_ENUM_BODY,
ParserErrorCode.ENUM_IN_CLASS,
ParserErrorCode.EQUALITY_CANNOT_BE_EQUALITY_OPERAND,
+ ParserErrorCode.EXPECTED_BODY,
ParserErrorCode.EXPECTED_CASE_OR_DEFAULT,
ParserErrorCode.EXPECTED_CLASS_MEMBER,
ParserErrorCode.EXPECTED_ELSE_OR_COMMA,
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index e179115..414ab6c 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -5,6 +5,7 @@
import 'dart:async';
import 'dart:collection';
import 'dart:convert';
+import 'dart:typed_data';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -19,7 +20,7 @@
class MemoryResourceProvider implements ResourceProvider {
final Map<String, _MemoryResource> _pathToResource =
new HashMap<String, _MemoryResource>();
- final Map<String, List<int>> _pathToBytes = new HashMap<String, List<int>>();
+ final Map<String, Uint8List> _pathToBytes = new HashMap<String, Uint8List>();
final Map<String, int> _pathToTimestamp = new HashMap<String, int>();
final Map<String, List<StreamController<WatchEvent>>> _pathToWatchers =
new HashMap<String, List<StreamController<WatchEvent>>>();
@@ -128,7 +129,7 @@
void modifyFile(String path, String content) {
_checkFileAtPath(path);
- _pathToBytes[path] = utf8.encode(content);
+ _pathToBytes[path] = utf8.encode(content) as Uint8List;
_pathToTimestamp[path] = nextStamp++;
_notifyWatchers(path, ChangeType.MODIFY);
}
@@ -150,7 +151,7 @@
File newFile(String path, String content, [int stamp]) {
_ensureAbsoluteAndNormalized(path);
_MemoryFile file = _newFile(path);
- _pathToBytes[path] = utf8.encode(content);
+ _pathToBytes[path] = utf8.encode(content) as Uint8List;
_pathToTimestamp[path] = stamp ?? nextStamp++;
_notifyWatchers(path, ChangeType.ADD);
return file;
@@ -159,7 +160,7 @@
File newFileWithBytes(String path, List<int> bytes, [int stamp]) {
_ensureAbsoluteAndNormalized(path);
_MemoryFile file = _newFile(path);
- _pathToBytes[path] = bytes;
+ _pathToBytes[path] = Uint8List.fromList(bytes);
_pathToTimestamp[path] = stamp ?? nextStamp++;
_notifyWatchers(path, ChangeType.ADD);
return file;
@@ -196,7 +197,7 @@
newFolder(pathContext.dirname(path));
_MemoryFile file = new _MemoryFile(this, path);
_pathToResource[path] = file;
- _pathToBytes[path] = utf8.encode(content);
+ _pathToBytes[path] = utf8.encode(content) as Uint8List;
_pathToTimestamp[path] = stamp ?? nextStamp++;
_notifyWatchers(path, ChangeType.MODIFY);
return file;
@@ -300,7 +301,7 @@
void _setFileContent(_MemoryFile file, List<int> bytes) {
String path = file.path;
_pathToResource[path] = file;
- _pathToBytes[path] = bytes;
+ _pathToBytes[path] = Uint8List.fromList(bytes);
_pathToTimestamp[path] = nextStamp++;
_notifyWatchers(path, ChangeType.MODIFY);
}
@@ -357,7 +358,7 @@
}
@override
- List<int> readAsBytesSync() {
+ Uint8List readAsBytesSync() {
throw new FileSystemException(path, 'File could not be read');
}
@@ -436,8 +437,8 @@
}
@override
- List<int> readAsBytesSync() {
- List<int> content = _provider._pathToBytes[path];
+ Uint8List readAsBytesSync() {
+ Uint8List content = _provider._pathToBytes[path];
if (content == null) {
throw new FileSystemException(path, 'File "$path" does not exist.');
}
@@ -446,7 +447,7 @@
@override
String readAsStringSync() {
- List<int> content = _provider._pathToBytes[path];
+ Uint8List content = _provider._pathToBytes[path];
if (content == null) {
throw new FileSystemException(path, 'File "$path" does not exist.');
}
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 76879be..3628b8f 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
+import 'dart:convert';
import 'dart:core';
+import 'dart:typed_data';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -70,6 +72,11 @@
@override
Resource getResource(String path) {
+ if (hasOverlay(path)) {
+ return new _OverlayResource._from(this, baseProvider.getFile(path));
+ } else if (_hasOverlayIn(path)) {
+ return new _OverlayResource._from(this, baseProvider.getFolder(path));
+ }
return new _OverlayResource._from(this, baseProvider.getResource(path));
}
@@ -140,14 +147,18 @@
}
/**
- * Return the paths of all of the overlaid files that are immediate children
- * of the given [folder].
+ * Return `true` if there is an overlay associated with at least one file
+ * contained inside the folder with the given [folderPath].
*/
- Iterable<String> _overlaysInFolder(Folder folder) {
- String folderPath = folder.path;
- return _overlayContent.keys
- .where((path) => pathContext.dirname(path) == folderPath);
- }
+ bool _hasOverlayIn(String folderPath) => _overlayContent.keys
+ .any((filePath) => pathContext.isWithin(folderPath, filePath));
+
+ /**
+ * Return the paths of all of the overlaid files that are children of the
+ * given [folder], either directly or indirectly.
+ */
+ Iterable<String> _overlaysInFolder(String folderPath) => _overlayContent.keys
+ .where((filePath) => pathContext.isWithin(folderPath, filePath));
}
/**
@@ -221,10 +232,10 @@
}
@override
- List<int> readAsBytesSync() {
+ Uint8List readAsBytesSync() {
String content = _provider._getOverlayContent(path);
if (content != null) {
- return content.codeUnits;
+ return utf8.encode(content) as Uint8List;
}
return _file.readAsBytesSync();
}
@@ -281,7 +292,7 @@
Stream<WatchEvent> get changes => _folder.changes;
@override
- bool get exists => _resource.exists;
+ bool get exists => _provider._hasOverlayIn(path) || _resource.exists;
/**
* Return the folder from the base resource provider that corresponds to this
@@ -330,12 +341,24 @@
@override
List<Resource> getChildren() {
- List<Resource> children = _folder
- .getChildren()
- .map((child) => new _OverlayResource._from(_provider, child))
- .toList();
- for (String overlayPath in _provider._overlaysInFolder(this)) {
- children.add(_provider.getFile(overlayPath));
+ List<Resource> children;
+ try {
+ children = _folder
+ .getChildren()
+ .map((child) => new _OverlayResource._from(_provider, child))
+ .toList();
+ } on FileSystemException {
+ children = [];
+ }
+ for (String overlayPath in _provider._overlaysInFolder(path)) {
+ pathos.Context context = _provider.pathContext;
+ if (context.dirname(overlayPath) == path) {
+ children.add(_provider.getFile(overlayPath));
+ } else {
+ String relativePath = context.relative(overlayPath, from: path);
+ String folderName = context.split(relativePath)[0];
+ children.add(_provider.getFolder(context.join(path, folderName)));
+ }
}
return children;
}
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index eb28314..83a34de 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -4,6 +4,7 @@
import 'dart:async';
import 'dart:io' as io;
+import 'dart:typed_data';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/source_io.dart';
@@ -193,7 +194,7 @@
}
@override
- List<int> readAsBytesSync() {
+ Uint8List readAsBytesSync() {
_throwIfWindowsDeviceDriver();
try {
return _file.readAsBytesSync();
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index f92f743..94d0216 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -28,7 +28,6 @@
import 'package:analyzer/src/dart/analysis/search.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart'
show
@@ -105,7 +104,7 @@
/**
* Whether summary2 should be used to resynthesize elements.
*/
- static final bool useSummary2 = false;
+ static bool useSummary2 = false;
/**
* The scheduler that schedules analysis work in this, and possibly other
@@ -217,11 +216,6 @@
final _referencingNameTasks = <_FilesReferencingNameTask>[];
/**
- * The list of tasks to compute top-level declarations of a name.
- */
- final _topLevelNameDeclarationsTasks = <_TopLevelNameDeclarationsTask>[];
-
- /**
* The mapping from the files for which the index was requested using
* [getIndex] to the [Completer]s to report the result.
*/
@@ -519,9 +513,6 @@
if (_unitElementRequestedFiles.isNotEmpty) {
return AnalysisDriverPriority.interactive;
}
- if (_topLevelNameDeclarationsTasks.isNotEmpty) {
- return AnalysisDriverPriority.interactive;
- }
if (_priorityFiles.isNotEmpty) {
for (String path in _priorityFiles) {
if (_fileTracker.isFilePending(path)) {
@@ -971,19 +962,6 @@
}
/**
- * Return a [Future] that completes with top-level declarations with the
- * given [name] in all known libraries.
- */
- Future<List<TopLevelDeclarationInSource>> getTopLevelNameDeclarations(
- String name) {
- _discoverAvailableFiles();
- var task = new _TopLevelNameDeclarationsTask(this, name);
- _topLevelNameDeclarationsTasks.add(task);
- _scheduler.notify(this);
- return task.completer.future;
- }
-
- /**
* Return a [Future] that completes with the [UnitElementResult] for the
* file with the given [path], or with `null` if the file cannot be analyzed.
*/
@@ -1208,16 +1186,6 @@
return;
}
- // Compute top-level declarations.
- if (_topLevelNameDeclarationsTasks.isNotEmpty) {
- _TopLevelNameDeclarationsTask task = _topLevelNameDeclarationsTasks.first;
- bool isDone = task.perform();
- if (isDone) {
- _topLevelNameDeclarationsTasks.remove(task);
- }
- return;
- }
-
// Analyze a priority file.
if (_priorityFiles.isNotEmpty) {
for (String path in _priorityFiles) {
@@ -2546,66 +2514,3 @@
return true;
}
}
-
-/**
- * Task that computes top-level declarations for a certain name in all
- * known libraries.
- */
-class _TopLevelNameDeclarationsTask {
- final AnalysisDriver driver;
- final String name;
- final Completer<List<TopLevelDeclarationInSource>> completer =
- new Completer<List<TopLevelDeclarationInSource>>();
-
- final List<TopLevelDeclarationInSource> libraryDeclarations =
- <TopLevelDeclarationInSource>[];
- final Set<String> checkedFiles = new Set<String>();
- final List<String> filesToCheck = <String>[];
-
- _TopLevelNameDeclarationsTask(this.driver, this.name);
-
- /**
- * Perform a single piece of work, and either complete the [completer] and
- * return `true` to indicate that the task is done, return `false` to indicate
- * that the task should continue to be run.
- */
- bool perform() {
- // Prepare files to check.
- if (filesToCheck.isEmpty) {
- filesToCheck.addAll(driver.addedFiles.difference(checkedFiles));
- filesToCheck.addAll(driver.knownFiles.difference(checkedFiles));
- }
-
- // If no more files to check, complete and done.
- if (filesToCheck.isEmpty) {
- completer.complete(libraryDeclarations);
- return true;
- }
-
- // Check the next file.
- String path = filesToCheck.removeLast();
- if (checkedFiles.add(path)) {
- FileState file = driver._fsState.getFileForPath(path);
- if (!file.isPart) {
- bool isExported = false;
-
- TopLevelDeclaration declaration;
- for (FileState part in file.libraryFiles) {
- declaration ??= part.topLevelDeclarations[name];
- }
-
- if (declaration == null) {
- declaration = file.exportedTopLevelDeclarations[name];
- isExported = true;
- }
- if (declaration != null) {
- libraryDeclarations.add(new TopLevelDeclarationInSource(
- file.source, declaration, isExported));
- }
- }
- }
-
- // We're not done yet.
- return false;
- }
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 1df560f..a0e0eb6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/referenced_names.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -82,11 +81,6 @@
* should be called.
*/
class FileState {
- /**
- * The next value for [_exportDeclarationsId].
- */
- static int _exportDeclarationsNextId = 0;
-
final FileSystemState _fsState;
/**
@@ -140,10 +134,6 @@
String _transitiveSignature;
String _transitiveSignatureLinked;
- Map<String, TopLevelDeclaration> _topLevelDeclarations;
- Map<String, TopLevelDeclaration> _exportedTopLevelDeclarations;
- int _exportDeclarationsId = 0;
-
/**
* The flag that shows whether the file has an error or warning that
* might be fixed by a change to another file.
@@ -214,15 +204,6 @@
*/
List<FileState> get exportedFiles => _exportedFiles;
- /**
- * Return [TopLevelDeclaration]s exported from the this library file. The
- * keys to the map are names of declarations.
- */
- Map<String, TopLevelDeclaration> get exportedTopLevelDeclarations {
- _exportDeclarationsNextId = 1;
- return _computeExportedDeclarations().declarations;
- }
-
@override
int get hashCode => uri.hashCode;
@@ -321,59 +302,6 @@
FileStateTestView get test => new FileStateTestView(this);
/**
- * Return public top-level declarations declared in the file. The keys to the
- * map are names of declarations.
- */
- Map<String, TopLevelDeclaration> get topLevelDeclarations {
- if (_topLevelDeclarations == null) {
- _topLevelDeclarations = <String, TopLevelDeclaration>{};
-
- void addDeclaration(TopLevelDeclarationKind kind, String name) {
- if (!name.startsWith('_')) {
- _topLevelDeclarations[name] = new TopLevelDeclaration(kind, name);
- }
- }
-
- // Add types.
- for (UnlinkedClass type in unlinked.classes) {
- addDeclaration(TopLevelDeclarationKind.type, type.name);
- }
- for (UnlinkedEnum type in unlinked.enums) {
- addDeclaration(TopLevelDeclarationKind.type, type.name);
- }
- for (UnlinkedClass type in unlinked.mixins) {
- addDeclaration(TopLevelDeclarationKind.type, type.name);
- }
- for (UnlinkedTypedef type in unlinked.typedefs) {
- addDeclaration(TopLevelDeclarationKind.type, type.name);
- }
- // Add functions and variables.
- Set<String> addedVariableNames = new Set<String>();
- for (UnlinkedExecutable executable in unlinked.executables) {
- String name = executable.name;
- if (executable.kind == UnlinkedExecutableKind.functionOrMethod) {
- addDeclaration(TopLevelDeclarationKind.function, name);
- } else if (executable.kind == UnlinkedExecutableKind.getter ||
- executable.kind == UnlinkedExecutableKind.setter) {
- if (executable.kind == UnlinkedExecutableKind.setter) {
- name = name.substring(0, name.length - 1);
- }
- if (addedVariableNames.add(name)) {
- addDeclaration(TopLevelDeclarationKind.variable, name);
- }
- }
- }
- for (UnlinkedVariable variable in unlinked.variables) {
- String name = variable.name;
- if (addedVariableNames.add(name)) {
- addDeclaration(TopLevelDeclarationKind.variable, name);
- }
- }
- }
- return _topLevelDeclarations;
- }
-
- /**
* Return the set of transitive files - the file itself and all of the
* directly or indirectly referenced files.
*/
@@ -537,10 +465,6 @@
library.libraryCycle?.invalidate();
}
}
-
- for (FileState file in _fsState._uriToFile.values) {
- file._exportedTopLevelDeclarations = null;
- }
}
// This file is potentially not a library for its previous parts anymore.
@@ -619,69 +543,6 @@
@override
String toString() => path ?? '<unresolved>';
- /**
- * Compute the full or partial map of exported declarations for this library.
- */
- _ExportedDeclarations _computeExportedDeclarations() {
- // If we know exported declarations, return them.
- if (_exportedTopLevelDeclarations != null) {
- return new _ExportedDeclarations(0, _exportedTopLevelDeclarations);
- }
-
- // If we are already computing exported declarations for this library,
- // report that we found a cycle.
- if (_exportDeclarationsId != 0) {
- return new _ExportedDeclarations(_exportDeclarationsId, null);
- }
-
- var declarations = <String, TopLevelDeclaration>{};
-
- // Give each library a unique identifier.
- _exportDeclarationsId = _exportDeclarationsNextId++;
-
- // Append the exported declarations.
- int firstCycleId = 0;
- for (int i = 0; i < _exportedFiles.length; i++) {
- var exported = _exportedFiles[i]._computeExportedDeclarations();
- if (exported.declarations != null) {
- for (TopLevelDeclaration t in exported.declarations.values) {
- if (_exportFilters[i].accepts(t.name)) {
- declarations[t.name] = t;
- }
- }
- }
- if (exported.firstCycleId > 0) {
- if (firstCycleId == 0 || firstCycleId > exported.firstCycleId) {
- firstCycleId = exported.firstCycleId;
- }
- }
- }
-
- // If this library is the first component of the cycle, then we are at
- // the beginning of this cycle, and combination of partial export
- // namespaces of other exported libraries and declarations of this library
- // is the full export namespace of this library.
- if (firstCycleId != 0 && firstCycleId == _exportDeclarationsId) {
- firstCycleId = 0;
- }
-
- // We're done with this library, successfully or not.
- _exportDeclarationsId = 0;
-
- // Append the library declarations.
- for (FileState file in libraryFiles) {
- declarations.addAll(file.topLevelDeclarations);
- }
-
- // Record the declarations only if it is the full result.
- if (firstCycleId == 0) {
- _exportedTopLevelDeclarations = declarations;
- }
-
- // Return the full or partial result.
- return new _ExportedDeclarations(firstCycleId, declarations);
- }
-
CompilationUnit _createEmptyCompilationUnit(FeatureSet featureSet) {
var token = new Token.eof(0);
return astFactory.compilationUnit2(
@@ -717,7 +578,6 @@
_definedTopLevelNames = null;
_definedClassMemberNames = null;
_referencedNames = null;
- _topLevelDeclarations = null;
if (_driverUnlinkedUnit != null) {
for (var name in _driverUnlinkedUnit.subtypedNames) {
@@ -833,10 +693,6 @@
library.libraryCycle?.invalidate();
}
}
-
- for (FileState file in _fsState._uriToFile.values) {
- file._exportedTopLevelDeclarations = null;
- }
}
// This file is potentially not a library for its previous parts anymore.
@@ -1253,23 +1109,6 @@
.where((f) => f._libraryCycle == null)
.toSet();
}
-
- Set<FileState> get librariesWithComputedExportedDeclarations {
- return state._uriToFile.values
- .where((f) => !f.isPart && f._exportedTopLevelDeclarations != null)
- .toSet();
- }
-}
-
-/**
- * The result of computing exported top-level declarations.
- * It can be full (when [firstCycleId] is zero), or partial (when a cycle)
- */
-class _ExportedDeclarations {
- final int firstCycleId;
- final Map<String, TopLevelDeclaration> declarations;
-
- _ExportedDeclarations(this.firstCycleId, this.declarations);
}
/**
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index f8f7f01..89066af 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -51,6 +51,7 @@
final PerformanceLog logger;
final ByteStore byteStore;
final AnalysisSession analysisSession;
+ final SummaryDataStore externalSummaries;
final SummaryDataStore store = new SummaryDataStore([]);
/// The size of the linked data that is loaded by this context.
@@ -73,7 +74,7 @@
@required AnalysisOptions analysisOptions,
@required DeclaredVariables declaredVariables,
@required SourceFactory sourceFactory,
- @required SummaryDataStore externalSummaries,
+ @required this.externalSummaries,
@required FileState targetLibrary,
@required bool useSummary2,
}) : this.logger = logger,
@@ -150,6 +151,10 @@
/// Load data required to access elements of the given [targetLibrary].
void load(FileState targetLibrary) {
+ if (AnalysisDriver.useSummary2) {
+ throw StateError('Unexpected with summary2.');
+ }
+
// The library is already a part of the context, nothing to do.
if (store.linkedMap.containsKey(targetLibrary.uriStr)) {
return;
@@ -352,10 +357,13 @@
analysisSession,
Reference.root(),
);
-
- var dartCoreRef = elementFactory.rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+ if (externalSummaries != null) {
+ for (var bundle in externalSummaries.bundles) {
+ elementFactory.addBundle(
+ LinkedBundleContext(elementFactory, bundle.bundle2),
+ );
+ }
+ }
}
void _createElementFactoryTypeProvider() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 908cc96..dd29d9d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -133,10 +133,13 @@
Future<List<Declaration>> declarations(
RegExp regExp, int maxResults, LinkedHashSet<String> files,
{String onlyForFile}) async {
- // TODO(brianwilkerson) Determine whether this await is necessary.
- await null;
List<Declaration> declarations = <Declaration>[];
+ // TODO(scheglov) Not implemented.
+ if (AnalysisDriver.useSummary2) {
+ return declarations;
+ }
+
DeclarationKind getExecutableKind(
UnlinkedExecutable executable, bool topLevel) {
switch (executable.kind) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 30db6fa..376e315 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -12,7 +12,6 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart' as driver;
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/dart/analysis/uri_converter.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/resolver.dart';
@@ -159,13 +158,6 @@
}
@override
- Future<List<TopLevelDeclarationInSource>> getTopLevelDeclarations(
- String name) {
- _checkConsistency();
- return _driver.getTopLevelNameDeclarations(name);
- }
-
- @override
Future<UnitElementResult> getUnitElement(String path) {
_checkConsistency();
return _driver.getUnitElement(path);
diff --git a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart b/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
deleted file mode 100644
index 1658aad..0000000
--- a/pkg/analyzer/lib/src/dart/analysis/top_level_declaration.dart
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2016, 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/src/generated/source.dart';
-
-/**
- * Information about a single top-level declaration.
- */
-class TopLevelDeclaration {
- final TopLevelDeclarationKind kind;
- final String name;
-
- TopLevelDeclaration(this.kind, this.name);
-
- @override
- String toString() => '($kind, $name)';
-}
-
-/**
- * A declaration in a source.
- */
-class TopLevelDeclarationInSource {
- /**
- * The declaring source.
- */
- final Source source;
-
- /**
- * The declaration.
- */
- final TopLevelDeclaration declaration;
-
- /**
- * Is `true` if the [declaration] is exported, not declared in the [source].
- */
- final bool isExported;
-
- TopLevelDeclarationInSource(this.source, this.declaration, this.isExported);
-
- @override
- String toString() => '($source, $declaration, $isExported)';
-}
-
-/**
- * Kind of a top-level declaration.
- *
- * We don't need it to be precise, just enough to support quick fixes.
- */
-enum TopLevelDeclarationKind { type, function, variable }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index e3064ce..8a79218 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3821,6 +3821,109 @@
}
}
+/// The declaration of an extension of a type.
+///
+/// extension ::=
+/// 'extension' [SimpleIdentifier] [TypeParameterList]?
+/// 'on' [TypeAnnotation] '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+class ExtensionDeclarationImpl extends NamedCompilationUnitMemberImpl
+ implements ExtensionDeclaration {
+ @override
+ Token extensionKeyword;
+
+ /// The type parameters for the extension, or `null` if the extension
+ /// does not have any type parameters.
+ TypeParameterListImpl _typeParameters;
+
+ @override
+ Token onKeyword;
+
+ /// The type that is being extended.
+ TypeAnnotationImpl _extendedType;
+
+ @override
+ Token leftBracket;
+
+ /// The members being added to the extended class.
+ NodeList<ClassMember> _members;
+
+ @override
+ Token rightBracket;
+
+ ExtensionDeclarationImpl(
+ CommentImpl comment,
+ List<Annotation> metadata,
+ this.extensionKeyword,
+ SimpleIdentifierImpl name,
+ TypeParameterListImpl typeParameters,
+ this.onKeyword,
+ TypeAnnotationImpl extendedType,
+ this.leftBracket,
+ List<ClassMember> members,
+ this.rightBracket)
+ : super(comment, metadata, name) {
+ _typeParameters = _becomeParentOf(typeParameters);
+ _extendedType = _becomeParentOf(extendedType);
+ _members = new NodeListImpl<ClassMember>(this, members);
+ }
+
+ @override
+ Token get beginToken => extensionKeyword;
+
+ @override
+ Iterable<SyntacticEntity> get childEntities => new ChildEntities()
+ ..add(extensionKeyword)
+ ..add(name)
+ ..add(typeParameters)
+ ..add(onKeyword)
+ ..add(extendedType)
+ ..add(leftBracket)
+ ..addAll(members)
+ ..add(rightBracket);
+
+ @override
+ Element get declaredElement => name.staticElement;
+
+ @override
+ Element get element => name.staticElement;
+
+ @override
+ Token get endToken => rightBracket;
+
+ @override
+ TypeAnnotation get extendedType => _extendedType;
+
+ void set extendedType(TypeAnnotation extendedClass) {
+ _extendedType = _becomeParentOf(extendedClass as TypeAnnotationImpl);
+ }
+
+ @override
+ Token get firstTokenAfterCommentAndMetadata => name.beginToken;
+
+ @override
+ NodeList<ClassMember> get members => _members;
+
+ @override
+ TypeParameterList get typeParameters => _typeParameters;
+
+ void set typeParameters(TypeParameterList typeParameters) {
+ _typeParameters = _becomeParentOf(typeParameters as TypeParameterListImpl);
+ }
+
+ @override
+ E accept<E>(AstVisitor<E> visitor) => visitor.visitExtensionDeclaration(this);
+
+ @override
+ void visitChildren(AstVisitor visitor) {
+ name?.accept(visitor);
+ _typeParameters?.accept(visitor);
+ _extendedType?.accept(visitor);
+ _members.accept(visitor);
+ }
+}
+
/// The declaration of one or more fields of the same type.
///
/// fieldDeclaration ::=
@@ -5083,6 +5186,9 @@
/// The parameters of the function-typed parameter.
FormalParameterListImpl _parameters;
+ @override
+ Token question;
+
/// Initialize a newly created formal parameter. Either or both of the
/// [comment] and [metadata] can be `null` if the parameter does not have the
/// corresponding attribute. The [returnType] can be `null` if no return type
@@ -5095,7 +5201,8 @@
TypeAnnotationImpl returnType,
SimpleIdentifierImpl identifier,
TypeParameterListImpl typeParameters,
- FormalParameterListImpl parameters)
+ FormalParameterListImpl parameters,
+ this.question)
: super(
comment, metadata, covariantKeyword, requiredKeyword, identifier) {
_returnType = _becomeParentOf(returnType);
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index 95b5867..1cd13f3 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -370,6 +370,30 @@
new ExtendsClauseImpl(extendsKeyword, superclass);
@override
+ ExtensionDeclaration extensionDeclaration(
+ {Comment comment,
+ List<Annotation> metadata,
+ Token extensionKeyword,
+ @required SimpleIdentifier name,
+ TypeParameterList typeParameters,
+ Token onKeyword,
+ @required TypeAnnotation extendedType,
+ Token leftBracket,
+ List<ClassMember> members,
+ Token rightBracket}) =>
+ new ExtensionDeclarationImpl(
+ comment,
+ metadata,
+ extensionKeyword,
+ name,
+ typeParameters,
+ onKeyword,
+ extendedType,
+ leftBracket,
+ members,
+ rightBracket);
+
+ @override
FieldDeclaration fieldDeclaration(
Comment comment,
List<Annotation> metadata,
@@ -564,7 +588,7 @@
TypeParameterList typeParameters,
FormalParameterList parameters) =>
new FunctionTypedFormalParameterImpl(comment, metadata, null, null,
- returnType, identifier, typeParameters, parameters);
+ returnType, identifier, typeParameters, parameters, null);
@override
FunctionTypedFormalParameter functionTypedFormalParameter2(
@@ -575,9 +599,18 @@
TypeAnnotation returnType,
@required SimpleIdentifier identifier,
TypeParameterList typeParameters,
- @required FormalParameterList parameters}) =>
- new FunctionTypedFormalParameterImpl(comment, metadata, covariantKeyword,
- requiredKeyword, returnType, identifier, typeParameters, parameters);
+ @required FormalParameterList parameters,
+ Token question}) =>
+ new FunctionTypedFormalParameterImpl(
+ comment,
+ metadata,
+ covariantKeyword,
+ requiredKeyword,
+ returnType,
+ identifier,
+ typeParameters,
+ parameters,
+ question);
@override
GenericFunctionType genericFunctionType(
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 5ac34d1..807d3c6 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -450,6 +450,20 @@
cloneToken(node.extendsKeyword), cloneNode(node.superclass));
@override
+ ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+ astFactory.extensionDeclaration(
+ comment: cloneNode(node.documentationComment),
+ metadata: cloneNodeList(node.metadata),
+ extensionKeyword: cloneToken(node.extensionKeyword),
+ name: cloneNode(node.name),
+ typeParameters: cloneNode(node.typeParameters),
+ onKeyword: cloneToken(node.onKeyword),
+ extendedType: cloneNode(node.extendedType),
+ leftBracket: cloneToken(node.leftBracket),
+ members: cloneNodeList(node.members),
+ rightBracket: cloneToken(node.rightBracket));
+
+ @override
FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
astFactory.fieldDeclaration2(
comment: cloneNode(node.documentationComment),
@@ -586,7 +600,8 @@
returnType: cloneNode(node.returnType),
identifier: cloneNode(node.identifier),
typeParameters: cloneNode(node.typeParameters),
- parameters: cloneNode(node.parameters));
+ parameters: cloneNode(node.parameters),
+ question: cloneToken(node.question));
@override
AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -1577,6 +1592,22 @@
}
@override
+ bool visitExtensionDeclaration(ExtensionDeclaration node) {
+ ExtensionDeclaration other = _other as ExtensionDeclaration;
+ return isEqualNodes(
+ node.documentationComment, other.documentationComment) &&
+ _isEqualNodeLists(node.metadata, other.metadata) &&
+ isEqualTokens(node.extensionKeyword, other.extensionKeyword) &&
+ isEqualNodes(node.name, other.name) &&
+ isEqualNodes(node.typeParameters, other.typeParameters) &&
+ isEqualTokens(node.onKeyword, other.onKeyword) &&
+ isEqualNodes(node.extendedType, other.extendedType) &&
+ isEqualTokens(node.leftBracket, other.leftBracket) &&
+ _isEqualNodeLists(node.members, other.members) &&
+ isEqualTokens(node.rightBracket, other.rightBracket);
+ }
+
+ @override
bool visitFieldDeclaration(FieldDeclaration node) {
FieldDeclaration other = _other as FieldDeclaration;
return isEqualNodes(
@@ -2817,6 +2848,20 @@
_mapToken(node.extendsKeyword), _cloneNode(node.superclass));
@override
+ ExtensionDeclaration visitExtensionDeclaration(ExtensionDeclaration node) =>
+ astFactory.extensionDeclaration(
+ comment: _cloneNode(node.documentationComment),
+ metadata: _cloneNodeList(node.metadata),
+ extensionKeyword: _mapToken(node.extensionKeyword),
+ name: _cloneNode(node.name),
+ typeParameters: _cloneNode(node.typeParameters),
+ onKeyword: _mapToken(node.onKeyword),
+ extendedType: _cloneNode(node.extendedType),
+ leftBracket: _mapToken(node.leftBracket),
+ members: _cloneNodeList(node.members),
+ rightBracket: _mapToken(node.rightBracket));
+
+ @override
FieldDeclaration visitFieldDeclaration(FieldDeclaration node) =>
astFactory.fieldDeclaration2(
comment: _cloneNode(node.documentationComment),
@@ -2965,7 +3010,8 @@
returnType: _cloneNode(node.returnType),
identifier: _cloneNode(node.identifier),
typeParameters: _cloneNode(node.typeParameters),
- parameters: _cloneNode(node.parameters));
+ parameters: _cloneNode(node.parameters),
+ question: _mapToken(node.question));
@override
AstNode visitGenericFunctionType(GenericFunctionType node) =>
@@ -4230,6 +4276,29 @@
return visitNode(node);
}
+ bool visitExtensionDeclaration(ExtensionDeclaration node) {
+ if (identical(node.documentationComment, _oldNode)) {
+ node.documentationComment = _newNode as Comment;
+ return true;
+ } else if (_replaceInList(node.metadata)) {
+ return true;
+ } else if (identical(node.name, _oldNode)) {
+ (node as ExtensionDeclarationImpl).name = _newNode as SimpleIdentifier;
+ return true;
+ } else if (identical(node.typeParameters, _oldNode)) {
+ (node as ExtensionDeclarationImpl).typeParameters =
+ _newNode as TypeParameterList;
+ return true;
+ } else if (identical(node.extendedType, _oldNode)) {
+ (node as ExtensionDeclarationImpl).extendedType =
+ _newNode as TypeAnnotation;
+ return true;
+ } else if (_replaceInList(node.members)) {
+ return true;
+ }
+ return visitNode(node);
+ }
+
@override
bool visitFieldDeclaration(FieldDeclaration node) {
if (identical(node.fields, _oldNode)) {
@@ -5585,6 +5654,25 @@
}
@override
+ bool visitExtensionDeclaration(ExtensionDeclaration node) {
+ ExtensionDeclaration toNode = this._toNode as ExtensionDeclaration;
+ if (_and(
+ _isEqualNodes(node.documentationComment, toNode.documentationComment),
+ _isEqualNodeLists(node.metadata, toNode.metadata),
+ _isEqualTokens(node.extensionKeyword, toNode.extensionKeyword),
+ _isEqualNodes(node.name, toNode.name),
+ _isEqualNodes(node.typeParameters, toNode.typeParameters),
+ _isEqualTokens(node.onKeyword, toNode.onKeyword),
+ _isEqualNodes(node.extendedType, toNode.extendedType),
+ _isEqualTokens(node.leftBracket, toNode.leftBracket),
+ _isEqualNodeLists(node.members, toNode.members),
+ _isEqualTokens(node.rightBracket, toNode.rightBracket))) {
+ return true;
+ }
+ return false;
+ }
+
+ @override
bool visitFieldDeclaration(FieldDeclaration node) {
FieldDeclaration toNode = this._toNode as FieldDeclaration;
return _and(
@@ -7155,6 +7243,21 @@
}
@override
+ void visitExtensionDeclaration(ExtensionDeclaration node) {
+ _visitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+ _visitTokenWithSuffix(node.extensionKeyword, ' ');
+ _visitNode(node.name);
+ _visitNode(node.typeParameters);
+ _writer.print(' ');
+ _visitToken(node.onKeyword);
+ _writer.print(' ');
+ _visitNodeWithSuffix(node.extendedType, ' ');
+ _visitToken(node.leftBracket);
+ _visitNodeListWithSeparator(node.members, ' ');
+ _visitToken(node.rightBracket);
+ }
+
+ @override
void visitFieldDeclaration(FieldDeclaration node) {
_visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
_visitTokenWithSuffix(node.staticKeyword, " ");
@@ -7305,6 +7408,9 @@
_visitNode(node.identifier);
_visitNode(node.typeParameters);
_visitNode(node.parameters);
+ if (node.question != null) {
+ _writer.print('?');
+ }
}
@override
@@ -7927,6 +8033,15 @@
}
/**
+ * Safely visit the given [token].
+ */
+ void _visitToken(Token token) {
+ if (token != null) {
+ _writer.print(token.lexeme);
+ }
+ }
+
+ /**
* Safely visit the given [token], printing the [suffix] after the token if it
* is non-`null`.
*/
@@ -8076,6 +8191,16 @@
}
/**
+ * Safely visit the given [token].
+ */
+ @protected
+ void safelyVisitToken(Token token) {
+ if (token != null) {
+ sink.write(token.lexeme);
+ }
+ }
+
+ /**
* Safely visit the given [token], printing the [suffix] after the token if it
* is non-`null`.
*/
@@ -8420,6 +8545,21 @@
}
@override
+ void visitExtensionDeclaration(ExtensionDeclaration node) {
+ safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, ' ', ' ');
+ safelyVisitTokenWithSuffix(node.extensionKeyword, ' ');
+ safelyVisitNode(node.name);
+ safelyVisitNode(node.typeParameters);
+ sink.write(' ');
+ safelyVisitToken(node.onKeyword);
+ sink.write(' ');
+ safelyVisitNodeWithSuffix(node.extendedType, ' ');
+ safelyVisitToken(node.leftBracket);
+ safelyVisitNodeListWithSeparator(node.members, ' ');
+ safelyVisitToken(node.rightBracket);
+ }
+
+ @override
void visitFieldDeclaration(FieldDeclaration node) {
safelyVisitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
safelyVisitTokenWithSuffix(node.staticKeyword, " ");
@@ -8570,6 +8710,9 @@
safelyVisitNode(node.identifier);
safelyVisitNode(node.typeParameters);
safelyVisitNode(node.parameters);
+ if (node.question != null) {
+ sink.write('?');
+ }
}
@override
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 3c98239..53e8356 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1606,6 +1606,7 @@
typeSystem.isAssignableTo(staticType, _typeProvider.boolType)) {
// If the static type is not assignable, then we will have already
// reported this error.
+ // TODO(mfairhurst) get the FeatureSet to suppress this for nnbd too.
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, condition);
}
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index b917123..8086e2c 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -83,7 +83,7 @@
SimpleIdentifier className = node.name;
ClassElementImpl element = new ClassElementImpl.forNode(className);
className.staticElement = element;
- element.abstract = node.isAbstract;
+ element.isAbstract = node.isAbstract;
_fillClassElement(node, element, holder);
_currentHolder.addType(element);
@@ -97,7 +97,7 @@
ClassElementImpl element = new ClassElementImpl.forNode(className);
_setCodeRange(element, node);
element.metadata = _createElementAnnotations(node.metadata);
- element.abstract = node.abstractKeyword != null;
+ element.isAbstract = node.abstractKeyword != null;
element.mixinApplication = true;
element.typeParameters = holder.typeParameters;
setElementDocumentationComment(element, node);
@@ -430,7 +430,7 @@
_setCodeRange(element, node);
element.metadata = _createElementAnnotations(node.metadata);
setElementDocumentationComment(element, node);
- element.abstract = node.isAbstract;
+ element.isAbstract = node.isAbstract;
if (node.externalKeyword != null || body is NativeFunctionBody) {
element.external = true;
}
@@ -482,7 +482,7 @@
getter.generator = true;
}
getter.variable = field;
- getter.abstract = node.isAbstract;
+ getter.isAbstract = node.isAbstract;
getter.getter = true;
getter.isStatic = isStatic;
field.getter = getter;
@@ -511,7 +511,7 @@
setter.generator = true;
}
setter.variable = field;
- setter.abstract = node.isAbstract;
+ setter.isAbstract = node.isAbstract;
setter.setter = true;
setter.isStatic = isStatic;
if (node.returnType == null) {
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 3543c8e..53cd4f7 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -18,6 +18,7 @@
import 'package:analyzer/src/dart/constant/value.dart';
import 'package:analyzer/src/dart/element/handle.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/generated/constant.dart' show EvaluationResultImpl;
import 'package:analyzer/src/generated/engine.dart'
show AnalysisContext, AnalysisEngine, AnalysisOptionsImpl;
@@ -479,9 +480,9 @@
: super.forSerialized(enclosingUnit);
/// Set whether this class is abstract.
+ @Deprecated('Use isAbstract instead')
void set abstract(bool isAbstract) {
- _assertNotResynthesized(_unlinkedClass);
- setModifier(Modifier.ABSTRACT, isAbstract);
+ this.isAbstract = isAbstract;
}
@override
@@ -824,6 +825,12 @@
return hasModifier(Modifier.ABSTRACT);
}
+ /// Set whether this class is abstract.
+ void set isAbstract(bool isAbstract) {
+ _assertNotResynthesized(_unlinkedClass);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
@override
bool get isMixinApplication {
if (linkedNode != null) {
@@ -2608,6 +2615,15 @@
@override
int get nameEnd {
+ if (linkedNode != null) {
+ var node = linkedNode as ConstructorDeclaration;
+ if (node.name != null) {
+ return node.name.end;
+ } else {
+ return node.returnType.end;
+ }
+ }
+
if (serializedExecutable != null) {
if (serializedExecutable.name.isNotEmpty) {
return serializedExecutable.nameEnd;
@@ -2625,6 +2641,11 @@
@override
int get periodOffset {
+ if (linkedNode != null) {
+ var node = linkedNode as ConstructorDeclaration;
+ return node.period?.offset;
+ }
+
if (serializedExecutable != null) {
if (serializedExecutable.name.isNotEmpty) {
return serializedExecutable.periodOffset;
@@ -2703,6 +2724,7 @@
@override
void appendTo(StringBuffer buffer) {
+ String name;
if (enclosingElement == null) {
String message;
String name = displayName;
@@ -2713,16 +2735,15 @@
message = 'Found unnamed constructor element with no enclosing element';
}
AnalysisEngine.instance.logger.logError(message);
- buffer.write('<unknown class>');
+ name = '<unknown class>';
} else {
- buffer.write(enclosingElement.displayName);
+ name = enclosingElement.displayName;
}
- String name = displayName;
- if (name != null && !name.isEmpty) {
- buffer.write(".");
- buffer.write(name);
+ String constructorName = displayName;
+ if (constructorName != null && !constructorName.isEmpty) {
+ name = '$name.$constructorName';
}
- super.appendTo(buffer);
+ appendToWithName(buffer, name);
}
@deprecated
@@ -3207,6 +3228,7 @@
/// A base class for concrete implementations of an [Element].
abstract class ElementImpl implements Element {
/// An Unicode right arrow.
+ @deprecated
static final String RIGHT_ARROW = " \u2192 ";
static int _NEXT_ID = 0;
@@ -4016,6 +4038,7 @@
: super.forSerialized(enclosingUnit);
/// Set whether this class is abstract.
+ @Deprecated('This setter will be removed')
void set abstract(bool isAbstract) {
_assertNotResynthesized(_unlinkedEnum);
}
@@ -4617,6 +4640,23 @@
@override
void appendTo(StringBuffer buffer) {
+ appendToWithName(buffer, displayName);
+ }
+
+ /// Append a textual representation of this element to the given [buffer]. The
+ /// [name] is the name of the executable element or `null` if the element has
+ /// no name. If [includeType] is `true` then the return type will be included.
+ void appendToWithName(StringBuffer buffer, String name) {
+ FunctionType functionType = type;
+ if (functionType != null) {
+ buffer.write(functionType.returnType);
+ if (name != null) {
+ buffer.write(' ');
+ buffer.write(name);
+ }
+ } else if (name != null) {
+ buffer.write(name);
+ }
if (this.kind != ElementKind.GETTER) {
int typeParameterCount = typeParameters.length;
if (typeParameterCount > 0) {
@@ -4665,10 +4705,6 @@
}
buffer.write(')');
}
- if (type != null) {
- buffer.write(ElementImpl.RIGHT_ARROW);
- buffer.write(type.returnType);
- }
}
@override
@@ -5178,15 +5214,6 @@
@override
T accept<T>(ElementVisitor<T> visitor) => visitor.visitFunctionElement(this);
- @override
- void appendTo(StringBuffer buffer) {
- String name = displayName;
- if (name != null) {
- buffer.write(name);
- }
- super.appendTo(buffer);
- }
-
@deprecated
@override
FunctionDeclaration computeNode() =>
@@ -5795,15 +5822,23 @@
return null;
}
FunctionType functionType = function.type;
+
List<TypeParameterElement> parameterElements = element.typeParameters;
- List<DartType> parameterTypes =
- TypeParameterTypeImpl.getTypes(parameterElements);
- int parameterCount = parameterTypes.length;
+ int parameterCount = parameterElements.length;
+
if (typeArguments == null ||
parameterElements.length != typeArguments.length) {
DartType dynamicType = DynamicElementImpl.instance.type;
typeArguments = new List<DartType>.filled(parameterCount, dynamicType);
}
+
+ if (element is GenericTypeAliasElementImpl && element.linkedNode != null) {
+ return Substitution.fromPairs(parameterElements, typeArguments)
+ .substituteType(functionType);
+ }
+
+ List<DartType> parameterTypes =
+ TypeParameterTypeImpl.getTypes(parameterElements);
return functionType.substitute2(typeArguments, parameterTypes);
}
}
@@ -7185,9 +7220,9 @@
: super.forSerialized(serializedExecutable, enclosingClass);
/// Set whether this method is abstract.
+ @Deprecated('Use isAbstract instead')
void set abstract(bool isAbstract) {
- _assertNotResynthesized(serializedExecutable);
- setModifier(Modifier.ABSTRACT, isAbstract);
+ this.isAbstract = isAbstract;
}
@override
@@ -7206,6 +7241,12 @@
TypeParameterizedElementMixin get enclosingTypeParameterContext =>
super.enclosingElement as ClassElementImpl;
+ /// Set whether this class is abstract.
+ void set isAbstract(bool isAbstract) {
+ _assertNotResynthesized(serializedExecutable);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
@override
bool get isOperator {
String name = displayName;
@@ -7251,12 +7292,6 @@
@override
T accept<T>(ElementVisitor<T> visitor) => visitor.visitMethodElement(this);
- @override
- void appendTo(StringBuffer buffer) {
- buffer.write(displayName);
- super.appendTo(buffer);
- }
-
@deprecated
@override
MethodDeclaration computeNode() =>
@@ -8897,9 +8932,9 @@
}
/// Set whether this accessor is abstract.
+ @Deprecated('Use isAbstract instead')
void set abstract(bool isAbstract) {
- _assertNotResynthesized(serializedExecutable);
- setModifier(Modifier.ABSTRACT, isAbstract);
+ this.isAbstract = isAbstract;
}
@override
@@ -8946,6 +8981,12 @@
return "$name$suffix";
}
+ /// Set whether this class is abstract.
+ void set isAbstract(bool isAbstract) {
+ _assertNotResynthesized(serializedExecutable);
+ setModifier(Modifier.ABSTRACT, isAbstract);
+ }
+
@override
bool get isGetter {
if (linkedNode != null) {
@@ -9024,9 +9065,8 @@
@override
void appendTo(StringBuffer buffer) {
- buffer.write(isGetter ? "get " : "set ");
- buffer.write(variable.displayName);
- super.appendTo(buffer);
+ super.appendToWithName(
+ buffer, (isGetter ? 'get ' : 'set ') + variable.displayName);
}
@deprecated
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index fc58f4f..f818145 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -73,26 +73,27 @@
ConstructorElement baseElement = this.baseElement;
List<ParameterElement> parameters = this.parameters;
FunctionType type = this.type;
+
StringBuffer buffer = new StringBuffer();
+ if (type != null) {
+ buffer.write(type.returnType);
+ buffer.write(' ');
+ }
buffer.write(baseElement.enclosingElement.displayName);
String name = displayName;
if (name != null && !name.isEmpty) {
- buffer.write(".");
+ buffer.write('.');
buffer.write(name);
}
- buffer.write("(");
+ buffer.write('(');
int parameterCount = parameters.length;
for (int i = 0; i < parameterCount; i++) {
if (i > 0) {
- buffer.write(", ");
+ buffer.write(', ');
}
buffer.write(parameters[i]);
}
- buffer.write(")");
- if (type != null) {
- buffer.write(ElementImpl.RIGHT_ARROW);
- buffer.write(type.returnType);
- }
+ buffer.write(')');
return buffer.toString();
}
@@ -621,28 +622,33 @@
MethodElement baseElement = this.baseElement;
List<ParameterElement> parameters = this.parameters;
FunctionType type = this.type;
+
StringBuffer buffer = new StringBuffer();
+ if (type != null) {
+ buffer.write(type.returnType);
+ buffer.write(' ');
+ }
buffer.write(baseElement.enclosingElement.displayName);
- buffer.write(".");
+ buffer.write('.');
buffer.write(baseElement.displayName);
int typeParameterCount = typeParameters.length;
if (typeParameterCount > 0) {
buffer.write('<');
for (int i = 0; i < typeParameterCount; i++) {
if (i > 0) {
- buffer.write(", ");
+ buffer.write(', ');
}
(typeParameters[i] as TypeParameterElementImpl).appendTo(buffer);
}
buffer.write('>');
}
- buffer.write("(");
+ buffer.write('(');
String closing = null;
ParameterKind kind = ParameterKind.REQUIRED;
int parameterCount = parameters.length;
for (int i = 0; i < parameterCount; i++) {
if (i > 0) {
- buffer.write(", ");
+ buffer.write(', ');
}
ParameterElement parameter = parameters[i];
// ignore: deprecated_member_use_from_same_package
@@ -652,11 +658,11 @@
buffer.write(closing);
}
if (parameter.isOptionalPositional) {
- buffer.write("[");
- closing = "]";
+ buffer.write('[');
+ closing = ']';
} else if (parameter.isNamed) {
- buffer.write("{");
- closing = "}";
+ buffer.write('{');
+ closing = '}';
} else {
closing = null;
}
@@ -667,11 +673,7 @@
if (closing != null) {
buffer.write(closing);
}
- buffer.write(")");
- if (type != null) {
- buffer.write(ElementImpl.RIGHT_ARROW);
- buffer.write(type.returnType);
- }
+ buffer.write(')');
return buffer.toString();
}
@@ -852,28 +854,29 @@
PropertyAccessorElement baseElement = this.baseElement;
List<ParameterElement> parameters = this.parameters;
FunctionType type = this.type;
+
StringBuffer builder = new StringBuffer();
+ if (type != null) {
+ builder.write(type.returnType);
+ builder.write(' ');
+ }
if (isGetter) {
- builder.write("get ");
+ builder.write('get ');
} else {
- builder.write("set ");
+ builder.write('set ');
}
builder.write(baseElement.enclosingElement.displayName);
- builder.write(".");
+ builder.write('.');
builder.write(baseElement.displayName);
- builder.write("(");
+ builder.write('(');
int parameterCount = parameters.length;
for (int i = 0; i < parameterCount; i++) {
if (i > 0) {
- builder.write(", ");
+ builder.write(', ');
}
builder.write(parameters[i]);
}
- builder.write(")");
- if (type != null) {
- builder.write(ElementImpl.RIGHT_ARROW);
- builder.write(type.returnType);
- }
+ builder.write(')');
return builder.toString();
}
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index ec7f129..de53916 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -56,15 +56,34 @@
*/
class BottomTypeImpl extends TypeImpl {
/**
- * The unique instance of this class.
+ * The unique instance of this class, nullable.
+ *
+ * This behaves equivalently to the `Null` type, but we distinguish it for two
+ * reasons: (1) there are circumstances where we need access to this type, but
+ * we don't have access to the type provider, so using `Never?` is a
+ * convenient solution. (2) we may decide that the distinction is convenient
+ * in diagnostic messages (this is TBD).
*/
- static final BottomTypeImpl instance = new BottomTypeImpl._();
+ static final BottomTypeImpl instanceNullable =
+ new BottomTypeImpl._(NullabilitySuffix.question);
+
+ /**
+ * The unique instance of this class, non-nullable.
+ */
+ static final BottomTypeImpl instance =
+ new BottomTypeImpl._(NullabilitySuffix.none);
+
+ @override
+ final NullabilitySuffix nullabilitySuffix;
/**
* Prevent the creation of instances of this class.
*/
- BottomTypeImpl._() : super(new NeverElementImpl(), "Never") {
- (element as NeverElementImpl).type = this;
+ BottomTypeImpl._(this.nullabilitySuffix)
+ : super(new NeverElementImpl(), "Never") {
+ if (nullabilitySuffix == NullabilitySuffix.none) {
+ (element as NeverElementImpl).type = this;
+ }
}
@override
@@ -74,7 +93,10 @@
bool get isBottom => true;
@override
- NullabilitySuffix get nullabilitySuffix => NullabilitySuffix.none;
+ bool get isDartCoreNull {
+ // `Never?` is equivalent to `Null`, so make sure it behaves the same.
+ return nullabilitySuffix == NullabilitySuffix.question;
+ }
@override
bool operator ==(Object object) => identical(object, this);
@@ -119,8 +141,22 @@
@override
TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) {
- // The bottom type is always non-nullable.
- return this;
+ switch (nullabilitySuffix) {
+ case NullabilitySuffix.question:
+ return instanceNullable;
+ case NullabilitySuffix.star:
+ // This should never happen. Converting `Never` to a legacy type should
+ // yield `Null`, because prior to NNBD, `Null` was at the bottom of the
+ // type hierarchy.
+ //
+ // However, due to bugs elsewhere in the analyzer, this does still
+ // happen sometimes, so for now just coerce to `Never?`.
+ // TODO(paulberry): change this to throw an exception.
+ return instanceNullable;
+ case NullabilitySuffix.none:
+ return instance;
+ }
+ throw StateError('Unexpected nullabilitySuffix: $nullabilitySuffix');
}
}
@@ -242,6 +278,12 @@
TypeImpl withNullability(NullabilitySuffix nullabilitySuffix) => this;
@override
+ void _appendToWithTypeParameters(StringBuffer buffer,
+ Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+ throw StateError('We should never get here.');
+ }
+
+ @override
void _forEachParameterType(
ParameterKind kind, callback(String name, DartType type)) {
// There are no parameters.
@@ -309,8 +351,10 @@
DeferredFunctionTypeImpl(this._computeElement, String name,
List<DartType> typeArguments, bool isInstantiated,
- {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star})
- : super._(null, name, null, typeArguments, null, null, isInstantiated,
+ {NullabilitySuffix nullabilitySuffix = NullabilitySuffix.star,
+ FunctionTypedElement computedElement})
+ : _computedElement = computedElement,
+ super._(null, name, null, typeArguments, null, null, isInstantiated,
nullabilitySuffix: nullabilitySuffix);
@override
@@ -327,6 +371,7 @@
if (this.nullabilitySuffix == nullabilitySuffix) return this;
return DeferredFunctionTypeImpl(
_computeElement, name, typeArguments, isInstantiated,
+ computedElement: _computedElement,
nullabilitySuffix: nullabilitySuffix);
}
}
@@ -680,11 +725,11 @@
@override
void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
{bool withNullability = false}) {
- // TODO(paulberry): update to use the new "Function" syntax to avoid
- // ambiguity with NNBD, and eliminate code duplication with
+ // TODO(paulberry): eliminate code duplication with
// _ElementWriter.writeType. See issue #35818.
if (visitedTypes.add(this)) {
if (typeFormals.isNotEmpty) {
+ StringBuffer typeParametersBuffer = StringBuffer();
// To print a type with type variables, first make sure we have unique
// variable names to print.
Set<TypeParameterType> freeVariables = new HashSet<TypeParameterType>();
@@ -699,10 +744,10 @@
List<DartType> instantiateTypeArgs = <DartType>[];
List<DartType> variables = <DartType>[];
- buffer.write("<");
+ typeParametersBuffer.write('<');
for (TypeParameterElement e in typeFormals) {
if (e != typeFormals[0]) {
- buffer.write(",");
+ typeParametersBuffer.write(',');
}
String name = e.name;
int counter = 0;
@@ -717,89 +762,27 @@
}
TypeParameterTypeImpl t =
new TypeParameterTypeImpl(new TypeParameterElementImpl(name, -1));
- t.appendTo(buffer, visitedTypes, withNullability: withNullability);
+ t.appendTo(typeParametersBuffer, visitedTypes,
+ withNullability: withNullability);
instantiateTypeArgs.add(t);
variables.add(e.type);
if (e.bound != null) {
- buffer.write(" extends ");
+ typeParametersBuffer.write(' extends ');
TypeImpl renamed =
e.bound.substitute2(instantiateTypeArgs, variables);
- renamed.appendTo(buffer, visitedTypes);
+ renamed.appendTo(typeParametersBuffer, visitedTypes);
}
}
- buffer.write(">");
+ typeParametersBuffer.write('>');
- // Instantiate it and print the resulting type. After instantiation, it
- // will no longer have typeFormals, so we will continue below.
- this
- .instantiate(instantiateTypeArgs)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
- return;
- }
-
- List<DartType> normalParameterTypes = this.normalParameterTypes;
- List<DartType> optionalParameterTypes = this.optionalParameterTypes;
- Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
- DartType returnType = this.returnType;
-
- bool needsComma = false;
- void writeSeparator() {
- if (needsComma) {
- buffer.write(", ");
- } else {
- needsComma = true;
- }
- }
-
- void startOptionalParameters() {
- if (needsComma) {
- buffer.write(", ");
- needsComma = false;
- }
- }
-
- buffer.write("(");
- if (normalParameterTypes.isNotEmpty) {
- for (DartType type in normalParameterTypes) {
- writeSeparator();
- (type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
- }
- }
- if (optionalParameterTypes.isNotEmpty) {
- startOptionalParameters();
- buffer.write("[");
- for (DartType type in optionalParameterTypes) {
- writeSeparator();
- (type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
- }
- buffer.write("]");
- needsComma = true;
- }
- if (namedParameterTypes.isNotEmpty) {
- startOptionalParameters();
- buffer.write("{");
- namedParameterTypes.forEach((String name, DartType type) {
- writeSeparator();
- buffer.write(name);
- buffer.write(": ");
- (type as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
- });
- buffer.write("}");
- needsComma = true;
- }
- buffer.write(")");
- buffer.write(ElementImpl.RIGHT_ARROW);
- if (returnType == null) {
- buffer.write("null");
+ // Instantiate it and print the resulting type.
+ this.instantiate(instantiateTypeArgs)._appendToWithTypeParameters(
+ buffer,
+ visitedTypes,
+ withNullability,
+ typeParametersBuffer.toString());
} else {
- (returnType as TypeImpl)
- .appendTo(buffer, visitedTypes, withNullability: withNullability);
- }
- if (withNullability) {
- _appendNullability(buffer);
+ _appendToWithTypeParameters(buffer, visitedTypes, withNullability, '');
}
visitedTypes.remove(this);
} else {
@@ -902,6 +885,76 @@
FunctionTypeImpl substitute3(List<DartType> argumentTypes) =>
substitute2(argumentTypes, typeArguments);
+ void _appendToWithTypeParameters(StringBuffer buffer,
+ Set<TypeImpl> visitedTypes, bool withNullability, String typeParameters) {
+ List<DartType> normalParameterTypes = this.normalParameterTypes;
+ List<DartType> optionalParameterTypes = this.optionalParameterTypes;
+ Map<String, DartType> namedParameterTypes = this.namedParameterTypes;
+ DartType returnType = this.returnType;
+
+ if (returnType == null) {
+ buffer.write('null');
+ } else {
+ (returnType as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ }
+ buffer.write(' Function');
+ buffer.write(typeParameters);
+ bool needsComma = false;
+
+ void writeSeparator() {
+ if (needsComma) {
+ buffer.write(', ');
+ } else {
+ needsComma = true;
+ }
+ }
+
+ void startOptionalParameters() {
+ if (needsComma) {
+ buffer.write(', ');
+ needsComma = false;
+ }
+ }
+
+ buffer.write('(');
+ if (normalParameterTypes.isNotEmpty) {
+ for (DartType type in normalParameterTypes) {
+ writeSeparator();
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ }
+ }
+ if (optionalParameterTypes.isNotEmpty) {
+ startOptionalParameters();
+ buffer.write('[');
+ for (DartType type in optionalParameterTypes) {
+ writeSeparator();
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ }
+ buffer.write(']');
+ needsComma = true;
+ }
+ if (namedParameterTypes.isNotEmpty) {
+ startOptionalParameters();
+ buffer.write('{');
+ namedParameterTypes.forEach((String name, DartType type) {
+ writeSeparator();
+ buffer.write(name);
+ buffer.write(': ');
+ (type as TypeImpl)
+ .appendTo(buffer, visitedTypes, withNullability: withNullability);
+ });
+ buffer.write('}');
+ needsComma = true;
+ }
+ buffer.write(')');
+ if (withNullability) {
+ _appendNullability(buffer);
+ }
+ }
+
/**
* Invokes [callback] for each parameter of [kind] with the parameter's [name]
* and type after any type parameters have been applied.
@@ -2924,11 +2977,17 @@
*
* If the nullability of `this` already matches [nullabilitySuffix], `this`
* is returned.
+ *
+ * Note: this method just does low-level manipulations of the underlying type,
+ * so it is what you want if you are constructing a fresh type and want it to
+ * have the correct nullability suffix, but it is generally *not* what you
+ * want if you're manipulating existing types. For manipulating existing
+ * types, please use the methods in [TypeSystem].
*/
TypeImpl withNullability(NullabilitySuffix nullabilitySuffix);
void _appendNullability(StringBuffer buffer) {
- if (isDynamic || isBottom || isVoid) {
+ if (isDynamic || isVoid) {
// These types don't have nullability variations, so don't append
// anything.
return;
@@ -3181,7 +3240,21 @@
return objectType;
}
- return element.bound.resolveToBound(objectType);
+ NullabilitySuffix newNullabilitySuffix;
+ if (nullabilitySuffix == NullabilitySuffix.question ||
+ (element.bound as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.question) {
+ newNullabilitySuffix = NullabilitySuffix.question;
+ } else if (nullabilitySuffix == NullabilitySuffix.star ||
+ (element.bound as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.star) {
+ newNullabilitySuffix = NullabilitySuffix.star;
+ } else {
+ newNullabilitySuffix = NullabilitySuffix.none;
+ }
+
+ return (element.bound.resolveToBound(objectType) as TypeImpl)
+ .withNullability(newNullabilitySuffix);
}
@override
@@ -3190,7 +3263,8 @@
[List<FunctionTypeAliasElement> prune]) {
int length = parameterTypes.length;
for (int i = 0; i < length; i++) {
- if (parameterTypes[i] == this) {
+ var parameterType = parameterTypes[i];
+ if (parameterType is TypeParameterTypeImpl && parameterType == this) {
TypeImpl argumentType = argumentTypes[i];
// TODO(scheglov) It should not happen, but sometimes arguments are null.
@@ -3200,15 +3274,29 @@
// TODO(scheglov) Proposed substitution rules for nullability.
NullabilitySuffix resultNullability;
+ NullabilitySuffix parameterNullability =
+ parameterType.nullabilitySuffix;
NullabilitySuffix argumentNullability = argumentType.nullabilitySuffix;
- if (argumentNullability == NullabilitySuffix.question ||
- nullabilitySuffix == NullabilitySuffix.question) {
- resultNullability = NullabilitySuffix.question;
- } else if (argumentNullability == NullabilitySuffix.star ||
- nullabilitySuffix == NullabilitySuffix.star) {
- resultNullability = NullabilitySuffix.star;
+ if (parameterNullability == NullabilitySuffix.none) {
+ if (argumentNullability == NullabilitySuffix.question ||
+ nullabilitySuffix == NullabilitySuffix.question) {
+ resultNullability = NullabilitySuffix.question;
+ } else if (argumentNullability == NullabilitySuffix.star ||
+ nullabilitySuffix == NullabilitySuffix.star) {
+ resultNullability = NullabilitySuffix.star;
+ } else {
+ resultNullability = NullabilitySuffix.none;
+ }
+ } else if (parameterNullability == NullabilitySuffix.star) {
+ if (argumentNullability == NullabilitySuffix.question ||
+ nullabilitySuffix == NullabilitySuffix.question) {
+ resultNullability = NullabilitySuffix.question;
+ } else {
+ resultNullability = argumentNullability;
+ }
} else {
- resultNullability = NullabilitySuffix.none;
+ // We should never be substituting for `T?`.
+ throw new StateError('Tried to substitute for T?');
}
return argumentType.withNullability(resultNullability);
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index a4376d3..0b16500 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -571,7 +571,7 @@
static const HintCode SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
'SDK_VERSION_AS_EXPRESSION_IN_CONST_CONTEXT',
"The use of an as expression in a constant expression wasn't "
- "supported until version 2.2.2, but this code is required to be able "
+ "supported until version 2.3.2, but this code is required to be able "
"to run on earlier versions.",
correction: "Try updating the SDK constraints.");
@@ -582,7 +582,7 @@
static const HintCode SDK_VERSION_BOOL_OPERATOR = const HintCode(
'SDK_VERSION_BOOL_OPERATOR',
"Using the operator '{0}' for 'bool's was not supported until version "
- "2.2.2, but this code is required to be able to run on earlier versions.",
+ "2.3.2, but this code is required to be able to run on earlier versions.",
correction: "Try updating the SDK constraints.");
/**
@@ -592,7 +592,7 @@
static const HintCode SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT = const HintCode(
'SDK_VERSION_EQ_EQ_OPERATOR_IN_CONST_CONTEXT',
"Using the operator '==' for non-primitive types was not supported until "
- "version 2.2.2, but this code is required to be able to run on earlier "
+ "version 2.3.2, but this code is required to be able to run on earlier "
"versions.",
correction: "Try updating the SDK constraints.");
@@ -602,7 +602,7 @@
*/
static const HintCode SDK_VERSION_GT_GT_GT_OPERATOR = const HintCode(
'SDK_VERSION_GT_GT_GT_OPERATOR',
- "The operator '>>>' was not supported until version 2.2.2, but this code "
+ "The operator '>>>' was not supported until version 2.3.2, but this code "
"is required to be able to run on earlier versions.",
correction: "Try updating the SDK constraints.");
@@ -613,7 +613,7 @@
static const HintCode SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT = const HintCode(
'SDK_VERSION_IS_EXPRESSION_IN_CONST_CONTEXT',
"The use of an is expression in a constant expression wasn't "
- "supported until version 2.2.2, but this code is required to be able "
+ "supported until version 2.3.2, but this code is required to be able "
"to run on earlier versions.",
correction: "Try updating the SDK constraints.");
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index 5110557..cec3fe1 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -51,8 +51,8 @@
static const ParserErrorCode ASYNC_KEYWORD_USED_AS_IDENTIFIER =
const ParserErrorCode(
'ASYNC_KEYWORD_USED_AS_IDENTIFIER',
- "The keywords 'async', 'await', and 'yield' can't be used as "
- "identifiers in an asynchronous or generator function.");
+ "The keywords 'await' and 'yield' can't be used as "
+ "identifiers in an asynchronous or generator function.");
static const ParserErrorCode BREAK_OUTSIDE_OF_LOOP = _BREAK_OUTSIDE_OF_LOOP;
@@ -109,7 +109,7 @@
// TODO(danrubel): Remove this unused error code
static const ParserErrorCode COVARIANT_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
- static const ParserErrorCode COVARIANT_AFTER_VAR = _COVARIANT_AFTER_VAR;
+ static const ParserErrorCode COVARIANT_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
static const ParserErrorCode COVARIANT_AND_STATIC = _COVARIANT_AND_STATIC;
@@ -161,6 +161,8 @@
static const ParserErrorCode EQUALITY_CANNOT_BE_EQUALITY_OPERAND =
_EQUALITY_CANNOT_BE_EQUALITY_OPERAND;
+ static const ParserErrorCode EXPECTED_BODY = _EXPECTED_BODY;
+
static const ParserErrorCode EXPECTED_CASE_OR_DEFAULT = const ParserErrorCode(
'EXPECTED_CASE_OR_DEFAULT', "Expected 'case' or 'default'.",
correction: "Try placing this code inside a case clause.");
@@ -202,11 +204,11 @@
static const ParserErrorCode EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE =
_EXPORT_DIRECTIVE_AFTER_PART_DIRECTIVE;
- static const ParserErrorCode EXTERNAL_AFTER_CONST = _EXTERNAL_AFTER_CONST;
+ static const ParserErrorCode EXTERNAL_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
- static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _EXTERNAL_AFTER_FACTORY;
+ static const ParserErrorCode EXTERNAL_AFTER_FACTORY = _MODIFIER_OUT_OF_ORDER;
- static const ParserErrorCode EXTERNAL_AFTER_STATIC = _EXTERNAL_AFTER_STATIC;
+ static const ParserErrorCode EXTERNAL_AFTER_STATIC = _MODIFIER_OUT_OF_ORDER;
static const ParserErrorCode EXTERNAL_CLASS = _EXTERNAL_CLASS;
@@ -340,7 +342,7 @@
static const ParserErrorCode INVALID_COMMENT_REFERENCE = const ParserErrorCode(
'INVALID_COMMENT_REFERENCE',
"Comment references should contain a possibly prefixed identifier and "
- "can start with 'new', but shouldn't contain anything else.");
+ "can start with 'new', but shouldn't contain anything else.");
static const ParserErrorCode INVALID_CONSTRUCTOR_NAME = const ParserErrorCode(
'INVALID_CONSTRUCTOR_NAME',
@@ -415,11 +417,7 @@
static const ParserErrorCode MISSING_CATCH_OR_FINALLY =
_MISSING_CATCH_OR_FINALLY;
- /// TODO(danrubel): Consider splitting this into two separate error messages.
- static const ParserErrorCode MISSING_CLASS_BODY = const ParserErrorCode(
- 'MISSING_CLASS_BODY',
- "A class or mixin definition must have a body, even if it is empty.",
- correction: "Try adding a body to your class or mixin.");
+ static const ParserErrorCode MISSING_CLASS_BODY = _EXPECTED_BODY;
static const ParserErrorCode MISSING_CLOSING_PARENTHESIS =
const ParserErrorCode(
@@ -564,7 +562,7 @@
const ParserErrorCode(
'MULTIPLE_VARIABLES_IN_FOR_EACH',
"A single loop variable must be declared in a for-each loop before "
- "the 'in', but {0} were found.",
+ "the 'in', but {0} were found.",
correction:
"Try moving all but one of the declarations inside the loop body.");
@@ -588,14 +586,14 @@
const ParserErrorCode(
'NATIVE_CLAUSE_IN_NON_SDK_CODE',
"Native clause can only be used in the SDK and code that is loaded "
- "through native extensions.",
+ "through native extensions.",
correction: "Try removing the native clause.");
static const ParserErrorCode NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE =
const ParserErrorCode(
'NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE',
"Native functions can only be declared in the SDK and code that is "
- "loaded through native extensions.",
+ "loaded through native extensions.",
correction: "Try removing the word 'native'.");
static const ParserErrorCode NATIVE_CLAUSE_SHOULD_BE_ANNOTATION =
@@ -665,11 +663,11 @@
static const ParserErrorCode STACK_OVERFLOW = _STACK_OVERFLOW;
- static const ParserErrorCode STATIC_AFTER_CONST = _STATIC_AFTER_CONST;
+ static const ParserErrorCode STATIC_AFTER_CONST = _MODIFIER_OUT_OF_ORDER;
- static const ParserErrorCode STATIC_AFTER_FINAL = _STATIC_AFTER_FINAL;
+ static const ParserErrorCode STATIC_AFTER_FINAL = _MODIFIER_OUT_OF_ORDER;
- static const ParserErrorCode STATIC_AFTER_VAR = _STATIC_AFTER_VAR;
+ static const ParserErrorCode STATIC_AFTER_VAR = _MODIFIER_OUT_OF_ORDER;
static const ParserErrorCode STATIC_CONSTRUCTOR = _STATIC_CONSTRUCTOR;
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 25c445b..80d4ee8b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -15,7 +15,7 @@
_EXTERNAL_ENUM,
_PREFIX_AFTER_COMBINATOR,
_TYPEDEF_IN_CLASS,
- _COVARIANT_AFTER_VAR,
+ _EXPECTED_BODY,
_INVALID_AWAIT_IN_FOR,
_IMPORT_DIRECTIVE_AFTER_PART_DIRECTIVE,
_WITH_BEFORE_EXTENDS,
@@ -25,9 +25,9 @@
_SWITCH_HAS_MULTIPLE_DEFAULT_CASES,
_SWITCH_HAS_CASE_AFTER_DEFAULT_CASE,
_STATIC_OPERATOR,
- _STATIC_AFTER_VAR,
- _STATIC_AFTER_FINAL,
- _STATIC_AFTER_CONST,
+ _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
+ _STACK_OVERFLOW,
+ _MISSING_CATCH_OR_FINALLY,
_REDIRECTION_IN_NON_FACTORY_CONSTRUCTOR,
_REDIRECTING_CONSTRUCTOR_WITH_BODY,
_NATIVE_CLAUSE_SHOULD_BE_ANNOTATION,
@@ -53,9 +53,9 @@
_IMPLEMENTS_BEFORE_ON,
_IMPLEMENTS_BEFORE_EXTENDS,
_ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE,
- _EXTERNAL_AFTER_CONST,
- _EXTERNAL_AFTER_FACTORY,
- _EXTERNAL_AFTER_STATIC,
+ _EXPECTED_ELSE_OR_COMMA,
+ _INVALID_SUPER_IN_INITIALIZER,
+ _EXPERIMENT_NOT_ENABLED,
_EXTERNAL_METHOD_WITH_BODY,
_EXTERNAL_FIELD,
_ABSTRACT_CLASS_MEMBER,
@@ -97,12 +97,6 @@
_EXTERNAL_CONSTRUCTOR_WITH_BODY,
_FIELD_INITIALIZED_OUTSIDE_DECLARING_CLASS,
_VAR_AND_TYPE,
- _INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER,
- _STACK_OVERFLOW,
- _MISSING_CATCH_OR_FINALLY,
- _EXPERIMENT_NOT_ENABLED,
- _EXPECTED_ELSE_OR_COMMA,
- _INVALID_SUPER_IN_INITIALIZER,
];
const ParserErrorCode _ABSTRACT_CLASS_MEMBER = const ParserErrorCode(
@@ -174,11 +168,6 @@
correction:
"Try adding a label associated with one of the case clauses to the continue statement.");
-const ParserErrorCode _COVARIANT_AFTER_VAR = const ParserErrorCode(
- 'COVARIANT_AFTER_VAR',
- r"The modifier 'covariant' should be before the modifier 'var'.",
- correction: "Try re-ordering the modifiers.");
-
const ParserErrorCode _COVARIANT_AND_STATIC = const ParserErrorCode(
'COVARIANT_AND_STATIC',
r"Members can't be declared to be both 'covariant' and 'static'.",
@@ -227,6 +216,10 @@
r"An equality expression can't be an operand of another equality expression.",
correction: "Try re-writing the expression.");
+const ParserErrorCode _EXPECTED_BODY = const ParserErrorCode(
+ 'EXPECTED_BODY', r"A #string must have a body, even if it is empty.",
+ correction: "Try adding an empty body.");
+
const ParserErrorCode _EXPECTED_ELSE_OR_COMMA = const ParserErrorCode(
'EXPECTED_ELSE_OR_COMMA', r"Expected 'else' or comma.");
@@ -245,21 +238,6 @@
correction:
"Try moving the export directives before the part directives.");
-const ParserErrorCode _EXTERNAL_AFTER_CONST = const ParserErrorCode(
- 'EXTERNAL_AFTER_CONST',
- r"The modifier 'external' should be before the modifier 'const'.",
- correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_FACTORY = const ParserErrorCode(
- 'EXTERNAL_AFTER_FACTORY',
- r"The modifier 'external' should be before the modifier 'factory'.",
- correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _EXTERNAL_AFTER_STATIC = const ParserErrorCode(
- 'EXTERNAL_AFTER_STATIC',
- r"The modifier 'external' should be before the modifier 'static'.",
- correction: "Try re-ordering the modifiers.");
-
const ParserErrorCode _EXTERNAL_CLASS = const ParserErrorCode(
'EXTERNAL_CLASS', r"Classes can't be declared to be 'external'.",
correction: "Try removing the keyword 'external'.");
@@ -492,21 +470,6 @@
r"The file has too many nested expressions or statements.",
correction: "Try simplifying the code.");
-const ParserErrorCode _STATIC_AFTER_CONST = const ParserErrorCode(
- 'STATIC_AFTER_CONST',
- r"The modifier 'static' should be before the modifier 'const'.",
- correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_FINAL = const ParserErrorCode(
- 'STATIC_AFTER_FINAL',
- r"The modifier 'static' should be before the modifier 'final'.",
- correction: "Try re-ordering the modifiers.");
-
-const ParserErrorCode _STATIC_AFTER_VAR = const ParserErrorCode(
- 'STATIC_AFTER_VAR',
- r"The modifier 'static' should be before the modifier 'var'.",
- correction: "Try re-ordering the modifiers.");
-
const ParserErrorCode _STATIC_CONSTRUCTOR = const ParserErrorCode(
'STATIC_CONSTRUCTOR', r"Constructors can't be static.",
correction: "Try removing the keyword 'static'.");
diff --git a/pkg/analyzer/lib/src/dart/resolver/variance.dart b/pkg/analyzer/lib/src/dart/resolver/variance.dart
new file mode 100644
index 0000000..69bc580
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/variance.dart
@@ -0,0 +1,112 @@
+// 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:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+
+/// Computes the variance of the [typeParameter] in the [type].
+int computeVariance(TypeParameterElement typeParameter, DartType type) {
+ if (type is TypeParameterType) {
+ if (type.element == typeParameter) {
+ return Variance.covariant;
+ } else {
+ return Variance.unrelated;
+ }
+ } else if (type is InterfaceType) {
+ var result = Variance.unrelated;
+ for (var argument in type.typeArguments) {
+ result = Variance.meet(
+ result,
+ computeVariance(typeParameter, argument),
+ );
+ }
+ return result;
+ } else if (type is FunctionType) {
+ var result = computeVariance(typeParameter, type.returnType);
+
+ for (var parameter in type.typeFormals) {
+ // If [parameter] is referenced in the bound at all, it makes the
+ // variance of [parameter] in the entire type invariant. The invocation
+ // of [computeVariance] below is made to simply figure out if [variable]
+ // occurs in the bound.
+ var bound = parameter.bound;
+ if (bound != null &&
+ computeVariance(typeParameter, bound) != Variance.unrelated) {
+ result = Variance.invariant;
+ }
+ }
+
+ for (var parameter in type.parameters) {
+ result = Variance.meet(
+ result,
+ Variance.combine(
+ Variance.contravariant,
+ computeVariance(typeParameter, parameter.type),
+ ),
+ );
+ }
+ return result;
+ }
+ return Variance.unrelated;
+}
+
+/// Value set for variance of a type parameter `X` in a type `T`.
+class Variance {
+ /// Used when `X` does not occur free in `T`.
+ static const int unrelated = 0;
+
+ /// Used when `X` occurs free in `T`, and `U <: V` implies `[U/X]T <: [V/X]T`.
+ static const int covariant = 1;
+
+ /// Used when `X` occurs free in `T`, and `U <: V` implies `[V/X]T <: [U/X]T`.
+ static const int contravariant = 2;
+
+ /// Used when there exists a pair `U` and `V` such that `U <: V`, but
+ /// `[U/X]T` and `[V/X]T` are incomparable.
+ static const int invariant = 3;
+
+ /// Combines variances of `X` in `T` and `Y` in `S` into variance of `X` in
+ /// `[Y/T]S`.
+ ///
+ /// Consider the following examples:
+ ///
+ /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y`
+ /// in `List<Y>` is [covariant], so variance of `X` in `List<Function(X)>` is
+ /// [contravariant];
+ ///
+ /// * variance of `X` in `List<X>` is [covariant], variance of `Y` in
+ /// `Function(Y)` is [contravariant], so variance of `X` in
+ /// `Function(List<X>)` is [contravariant];
+ ///
+ /// * variance of `X` in `Function(X)` is [contravariant], variance of `Y` in
+ /// `Function(Y)` is [contravariant], so variance of `X` in
+ /// `Function(Function(X))` is [covariant];
+ ///
+ /// * let the following be declared:
+ ///
+ /// typedef F<Z> = Function();
+ ///
+ /// then variance of `X` in `F<X>` is [unrelated], variance of `Y` in
+ /// `List<Y>` is [covariant], so variance of `X` in `List<F<X>>` is
+ /// [unrelated];
+ ///
+ /// * let the following be declared:
+ ///
+ /// typedef G<Z> = Z Function(Z);
+ ///
+ /// then variance of `X` in `List<X>` is [covariant], variance of `Y` in
+ /// `G<Y>` is [invariant], so variance of `X` in `G<List<X>>` is [invariant].
+ static int combine(int a, int b) {
+ if (a == unrelated || b == unrelated) return unrelated;
+ if (a == invariant || b == invariant) return invariant;
+ return a == b ? covariant : contravariant;
+ }
+
+ /// Variance values form a lattice where [unrelated] is the top, [invariant]
+ /// is the bottom, and [covariant] and [contravariant] are incomparable.
+ /// [meet] calculates the meet of two elements of such lattice. It can be
+ /// used, for example, to calculate the variance of a typedef type parameter
+ /// if it's encountered on the RHS of the typedef multiple times.
+ static int meet(int a, int b) => a | b;
+}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 8a3e142..5b05f7a 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -2880,6 +2880,20 @@
"Setters should declare exactly one required parameter.");
/**
+ * Let `C` be a generic class that declares a formal type parameter `X`, and
+ * assume that `T` is a direct superinterface of `C`. It is a compile-time
+ * error if `X` occurs contravariantly or invariantly in `T`.
+ */
+ static const CompileTimeErrorCode
+ WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE =
+ const CompileTimeErrorCode(
+ 'WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE',
+ "'{0}' can't be used contravariantly or invariantly in '{1}'.",
+ correction: "Try not using class type parameters in types of formal "
+ "parameters of function types.",
+ );
+
+ /**
* ?? Yield: It is a compile-time error if a yield statement appears in a
* function that is not a generator function.
*/
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d120057..4edfcba 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.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:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -37,6 +38,7 @@
typeProvider: _typeProvider,
inheritance: _inheritance,
reporter: _reporter,
+ featureSet: unit.featureSet,
library: library,
classNameNode: declaration.name,
implementsClause: declaration.implementsClause,
@@ -50,6 +52,7 @@
typeProvider: _typeProvider,
inheritance: _inheritance,
reporter: _reporter,
+ featureSet: unit.featureSet,
library: library,
classNameNode: declaration.name,
implementsClause: declaration.implementsClause,
@@ -62,6 +65,7 @@
typeProvider: _typeProvider,
inheritance: _inheritance,
reporter: _reporter,
+ featureSet: unit.featureSet,
library: library,
classNameNode: declaration.name,
implementsClause: declaration.implementsClause,
@@ -85,6 +89,7 @@
final InheritanceManager2 inheritance;
final ErrorReporter reporter;
+ final FeatureSet featureSet;
final LibraryElement library;
final Uri libraryUri;
final ClassElementImpl classElement;
@@ -108,6 +113,7 @@
this.typeProvider,
this.inheritance,
this.reporter,
+ this.featureSet,
this.library,
this.classNameNode,
this.implementsClause,
@@ -382,7 +388,8 @@
if (setter != null && setter.parameters.length == 1) {
var getterType = getter.returnType;
var setterType = setter.parameters[0].type;
- if (!typeSystem.isAssignableTo(getterType, setterType)) {
+ if (!typeSystem.isAssignableTo(getterType, setterType,
+ featureSet: featureSet)) {
var getterElement = getter.element;
var setterElement = setter.element;
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index 89dcdce..ba32987 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.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:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -15,6 +16,7 @@
final TypeProvider typeProvider;
final TypeSystem typeSystem;
final ErrorReporter errorReporter;
+ final FeatureSet featureSet;
final bool Function(Expression) checkForUseOfVoidResult;
final bool forList;
@@ -36,6 +38,7 @@
this.forMap = false,
this.mapKeyType,
this.mapValueType,
+ this.featureSet,
});
void verify(CollectionElement element) {
@@ -45,7 +48,7 @@
/// Check that the given [type] is assignable to the [elementType], otherwise
/// report the list or set error on the [errorNode].
void _checkAssignableToElementType(DartType type, AstNode errorNode) {
- if (!typeSystem.isAssignableTo(type, elementType)) {
+ if (!typeSystem.isAssignableTo(type, elementType, featureSet: featureSet)) {
var errorCode = forList
? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
: StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -106,7 +109,8 @@
}
var keyType = entry.key.staticType;
- if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+ if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+ featureSet: featureSet)) {
errorReporter.reportTypeErrorForNode(
StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
entry.key,
@@ -115,7 +119,8 @@
}
var valueType = entry.value.staticType;
- if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+ if (!typeSystem.isAssignableTo(valueType, mapValueType,
+ featureSet: featureSet)) {
errorReporter.reportTypeErrorForNode(
StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
entry.value,
@@ -157,7 +162,8 @@
}
var iterableElementType = iterableType.typeArguments[0];
- if (!typeSystem.isAssignableTo(iterableElementType, elementType)) {
+ if (!typeSystem.isAssignableTo(iterableElementType, elementType,
+ featureSet: featureSet)) {
var errorCode = forList
? StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE
: StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE;
@@ -200,7 +206,8 @@
}
var keyType = mapType.typeArguments[0];
- if (!typeSystem.isAssignableTo(keyType, mapKeyType)) {
+ if (!typeSystem.isAssignableTo(keyType, mapKeyType,
+ featureSet: featureSet)) {
errorReporter.reportTypeErrorForNode(
StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
expression,
@@ -209,7 +216,8 @@
}
var valueType = mapType.typeArguments[1];
- if (!typeSystem.isAssignableTo(valueType, mapValueType)) {
+ if (!typeSystem.isAssignableTo(valueType, mapValueType,
+ featureSet: featureSet)) {
errorReporter.reportTypeErrorForNode(
StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
expression,
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index df9bd69..2d4fad3 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -12,8 +12,8 @@
import 'package:analyzer/src/dart/ast/ast.dart'
show
ClassDeclarationImpl,
- ClassOrMixinDeclarationImpl,
CompilationUnitImpl,
+ ExtensionDeclarationImpl,
MixinDeclarationImpl;
import 'package:analyzer/src/fasta/error_converter.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
@@ -86,6 +86,9 @@
/// The mixin currently being parsed, or `null` if no mixin is being parsed.
MixinDeclarationImpl mixinDeclaration;
+ /// The extension currently being parsed, or `null` if none.
+ ExtensionDeclarationImpl extensionDeclaration;
+
/// If true, this is building a full AST. Otherwise, only create method
/// bodies.
final bool isFullAst;
@@ -127,6 +130,26 @@
: this.errorReporter = new FastaErrorReporter(errorReporter),
uri = uri ?? fileUri;
+ NodeList<ClassMember> get currentDeclarationMembers {
+ if (classDeclaration != null) {
+ return classDeclaration.members;
+ } else if (mixinDeclaration != null) {
+ return mixinDeclaration.members;
+ } else {
+ return extensionDeclaration.members;
+ }
+ }
+
+ SimpleIdentifier get currentDeclarationName {
+ if (classDeclaration != null) {
+ return classDeclaration.name;
+ } else if (mixinDeclaration != null) {
+ return mixinDeclaration.name;
+ } else {
+ return extensionDeclaration.name;
+ }
+ }
+
@override
void addProblem(Message message, int charOffset, int length,
{bool wasHandled: false, List<LocatedMessage> context}) {
@@ -155,7 +178,9 @@
@override
void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
- assert(classDeclaration == null && mixinDeclaration == null);
+ assert(classDeclaration == null &&
+ mixinDeclaration == null &&
+ extensionDeclaration == null);
push(new _Modifiers()..abstractKeyword = abstractToken);
}
@@ -165,6 +190,30 @@
}
@override
+ void beginExtensionDeclaration(Token extensionKeyword, Token nameToken) {
+ assert(optional('extension', extensionKeyword));
+ assert(classDeclaration == null &&
+ mixinDeclaration == null &&
+ extensionDeclaration == null);
+ debugEvent("ExtensionHeader");
+
+ TypeParameterList typeParameters = pop();
+ SimpleIdentifier name = pop();
+ List<Annotation> metadata = pop();
+ Comment comment = _findComment(metadata, extensionKeyword);
+
+ extensionDeclaration = ast.extensionDeclaration(
+ comment: comment,
+ metadata: metadata,
+ name: name,
+ typeParameters: typeParameters,
+ extendedType: null, // extendedType is set in [endExtensionDeclaration]
+ ) as ExtensionDeclarationImpl;
+
+ declarations.add(extensionDeclaration);
+ }
+
+ @override
void beginFactoryMethod(
Token lastConsumed, Token externalToken, Token constToken) {
push(new _Modifiers()
@@ -234,7 +283,9 @@
@override
void beginMixinDeclaration(Token mixinKeyword, Token name) {
- assert(classDeclaration == null && mixinDeclaration == null);
+ assert(classDeclaration == null &&
+ mixinDeclaration == null &&
+ extensionDeclaration == null);
}
@override
@@ -481,14 +532,25 @@
@override
void endClassOrMixinBody(
int memberCount, Token leftBracket, Token rightBracket) {
+ // TODO(danrubel): consider renaming endClassOrMixinBody
+ // to endClassOrMixinOrExtensionBody
assert(optional('{', leftBracket));
assert(optional('}', rightBracket));
debugEvent("ClassOrMixinBody");
- ClassOrMixinDeclarationImpl declaration =
- classDeclaration ?? mixinDeclaration;
- declaration.leftBracket = leftBracket;
- declaration.rightBracket = rightBracket;
+ if (classDeclaration != null) {
+ classDeclaration
+ ..leftBracket = leftBracket
+ ..rightBracket = rightBracket;
+ } else if (mixinDeclaration != null) {
+ mixinDeclaration
+ ..leftBracket = leftBracket
+ ..rightBracket = rightBracket;
+ } else {
+ extensionDeclaration
+ ..leftBracket = leftBracket
+ ..rightBracket = rightBracket;
+ }
}
@override
@@ -643,6 +705,15 @@
}
@override
+ void endExtensionDeclaration(Token onKeyword, Token token) {
+ TypeAnnotation type = pop();
+ extensionDeclaration
+ ..extendedType = type
+ ..onKeyword = onKeyword;
+ extensionDeclaration = null;
+ }
+
+ @override
void endFactoryMethod(
Token beginToken, Token factoryKeyword, Token endToken) {
assert(optional('factory', factoryKeyword));
@@ -694,21 +765,20 @@
ast.simpleIdentifier(typeName.identifier.token, isDeclaration: true);
}
- (classDeclaration ?? mixinDeclaration).members.add(
- ast.constructorDeclaration(
- comment,
- metadata,
- modifiers?.externalKeyword,
- modifiers?.finalConstOrVarKeyword,
- factoryKeyword,
- ast.simpleIdentifier(returnType.token),
- period,
- name,
- parameters,
- separator,
- null,
- redirectedConstructor,
- body));
+ currentDeclarationMembers.add(ast.constructorDeclaration(
+ comment,
+ metadata,
+ modifiers?.externalKeyword,
+ modifiers?.finalConstOrVarKeyword,
+ factoryKeyword,
+ ast.simpleIdentifier(returnType.token),
+ period,
+ name,
+ parameters,
+ separator,
+ null,
+ redirectedConstructor,
+ body));
}
void endFieldInitializer(Token assignment, Token token) {
@@ -737,7 +807,7 @@
Token covariantKeyword = covariantToken;
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, beginToken);
- (classDeclaration ?? mixinDeclaration).members.add(ast.fieldDeclaration2(
+ currentDeclarationMembers.add(ast.fieldDeclaration2(
comment: comment,
metadata: metadata,
covariantKeyword: covariantKeyword,
@@ -1415,9 +1485,6 @@
beginToken.charOffset, uri);
}
- ClassOrMixinDeclarationImpl declaration =
- classDeclaration ?? mixinDeclaration;
-
void constructor(
SimpleIdentifier prefixOrName, Token period, SimpleIdentifier name) {
if (typeParameters != null) {
@@ -1453,7 +1520,7 @@
initializers,
redirectedConstructor,
body);
- declaration.members.add(constructor);
+ currentDeclarationMembers.add(constructor);
if (mixinDeclaration != null) {
// TODO (danrubel): Report an error if this is a mixin declaration.
}
@@ -1466,7 +1533,7 @@
messageConstMethod, modifiers.constKeyword, modifiers.constKeyword);
}
checkFieldFormalParameters(parameters);
- declaration.members.add(ast.methodDeclaration(
+ currentDeclarationMembers.add(ast.methodDeclaration(
comment,
metadata,
modifiers?.externalKeyword,
@@ -1481,9 +1548,9 @@
}
if (name is SimpleIdentifier) {
- if (name.name == declaration.name.name && getOrSet == null) {
+ if (name.name == currentDeclarationName.name && getOrSet == null) {
constructor(name, null, null);
- } else if (initializers.isNotEmpty) {
+ } else if (initializers.isNotEmpty && getOrSet == null) {
constructor(name, null, null);
} else {
method(null, name);
@@ -1941,8 +2008,7 @@
}
}
- void finishFunction(
- List annotations, formals, AsyncMarker asyncModifier, FunctionBody body) {
+ void finishFunction(formals, AsyncMarker asyncModifier, FunctionBody body) {
debugEvent("finishFunction");
Statement bodyStatement;
@@ -2291,10 +2357,7 @@
if (variableOrDeclaration is! SimpleIdentifier) {
// Parser has already reported the error.
if (!leftParenthesis.next.isIdentifier) {
- parser.rewriter.insertToken(
- leftParenthesis,
- new SyntheticStringToken(
- TokenType.IDENTIFIER, '', leftParenthesis.next.charOffset));
+ parser.rewriter.insertSyntheticIdentifier(leftParenthesis);
}
variableOrDeclaration = ast.simpleIdentifier(leftParenthesis.next);
}
@@ -2686,7 +2749,9 @@
@override
void handleMixinHeader(Token mixinKeyword) {
assert(optional('mixin', mixinKeyword));
- assert(classDeclaration == null && mixinDeclaration == null);
+ assert(classDeclaration == null &&
+ mixinDeclaration == null &&
+ extensionDeclaration == null);
debugEvent("MixinHeader");
ImplementsClause implementsClause = pop(NullValue.IdentifierList);
diff --git a/pkg/analyzer/lib/src/fasta/error_converter.dart b/pkg/analyzer/lib/src/fasta/error_converter.dart
index 16f6f09..132cb54 100644
--- a/pkg/analyzer/lib/src/fasta/error_converter.dart
+++ b/pkg/analyzer/lib/src/fasta/error_converter.dart
@@ -205,10 +205,6 @@
errorReporter?.reportErrorForOffset(
StrongModeCode.INVALID_SUPER_INVOCATION, offset, length);
return;
- case "MISSING_CLASS_BODY":
- errorReporter?.reportErrorForOffset(
- ParserErrorCode.MISSING_CLASS_BODY, offset, length);
- return;
case "MISSING_DIGIT":
errorReporter?.reportErrorForOffset(
ScannerErrorCode.MISSING_DIGIT, offset, length);
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 16e265d..e336eb9 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -245,6 +245,9 @@
_setGenericFunctionType(node.returnType, element.returnType);
(node.functionExpression as FunctionExpressionImpl).declaredElement =
element;
+ if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+ node.returnType?.accept(this);
+ }
_walker._elementHolder?.addFunction(element);
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitFunctionDeclaration(node);
@@ -378,6 +381,9 @@
}
}
_setGenericFunctionType(node.returnType, element.returnType);
+ if (AnalysisDriver.useSummary2 && _enclosingUnit.linkedContext != null) {
+ node.returnType?.accept(this);
+ }
_walk(new ElementWalker.forExecutable(element, _enclosingUnit), () {
super.visitMethodDeclaration(node);
});
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index a5e2927..3791919 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -22,6 +22,7 @@
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/variance.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/error/literal_element_verifier.dart';
@@ -291,7 +292,8 @@
/// fixed.
final bool disableConflictingGenericsCheck;
- bool _isNonNullable = false;
+ /// The features enabled in the unit currently being checked for errors.
+ FeatureSet _featureSet;
/**
* Initialize a newly created error verifier.
@@ -343,6 +345,9 @@
_enclosingClass = classElement;
}
+ bool get _isNonNullable =>
+ _featureSet?.isEnabled(Feature.non_nullable) ?? false;
+
@override
void visitAnnotation(Annotation node) {
_checkForInvalidAnnotationFromDeferredLibrary(node);
@@ -415,9 +420,10 @@
_checkForUseOfVoidResult(node.rightOperand);
_checkForNullableDereference(node.leftOperand);
_checkForNullableDereference(node.rightOperand);
- } else if (type != TokenType.EQ_EQ &&
- type != TokenType.BANG_EQ &&
- type != TokenType.QUESTION_QUESTION) {
+ } else if (type == TokenType.EQ_EQ || type == TokenType.BANG_EQ) {
+ _checkForArgumentTypeNotAssignableForArgument(node.rightOperand,
+ promoteParameterToNullable: true);
+ } else if (type != TokenType.QUESTION_QUESTION) {
_checkForArgumentTypeNotAssignableForArgument(node.rightOperand);
_checkForNullableDereference(node.leftOperand);
} else {
@@ -523,6 +529,7 @@
_initializeInitialFieldElementsMap(_enclosingClass.fields);
_checkForFinalNotInitializedInClass(members);
_checkForBadFunctionUse(node);
+ _checkForWrongTypeParameterVarianceInSuperinterfaces();
super.visitClassDeclaration(node);
} finally {
_isInNativeClass = false;
@@ -540,6 +547,7 @@
_enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
_checkClassInheritance(
node, node.superclass, node.withClause, node.implementsClause);
+ _checkForWrongTypeParameterVarianceInSuperinterfaces();
} finally {
_enclosingClass = outerClassElement;
}
@@ -558,11 +566,11 @@
@override
void visitCompilationUnit(CompilationUnit node) {
- _isNonNullable = node.featureSet.isEnabled(Feature.non_nullable);
+ _featureSet = node.featureSet;
_checkDuplicateUnitMembers(node);
_checkForDeferredPrefixCollisions(node);
super.visitCompilationUnit(node);
- _isNonNullable = false;
+ _featureSet = null;
}
@override
@@ -1101,6 +1109,7 @@
_initializeInitialFieldElementsMap(_enclosingClass.fields);
_checkForFinalNotInitializedInClass(members);
+ _checkForWrongTypeParameterVarianceInSuperinterfaces();
// _checkForBadFunctionUse(node);
super.visitMixinDeclaration(node);
} finally {
@@ -2103,8 +2112,8 @@
FunctionType constructorType =
resolutionMap.elementDeclaredByConstructorDeclaration(declaration).type;
DartType constructorReturnType = constructorType.returnType;
- if (!_typeSystem.isAssignableTo(
- redirectedReturnType, constructorReturnType)) {
+ if (!_typeSystem.isAssignableTo(redirectedReturnType, constructorReturnType,
+ featureSet: _featureSet)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.REDIRECT_TO_INVALID_RETURN_TYPE,
redirectedConstructor,
@@ -2256,13 +2265,17 @@
*
* See [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE].
*/
- void _checkForArgumentTypeNotAssignableForArgument(Expression argument) {
+ void _checkForArgumentTypeNotAssignableForArgument(Expression argument,
+ {bool promoteParameterToNullable = false}) {
if (argument == null) {
return;
}
ParameterElement staticParameterElement = argument.staticParameterElement;
DartType staticParameterType = staticParameterElement?.type;
+ if (promoteParameterToNullable && staticParameterType != null) {
+ staticParameterType = _typeSystem.makeNullable(staticParameterType);
+ }
_checkForArgumentTypeNotAssignableWithExpectedTypes(argument,
staticParameterType, StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE);
}
@@ -2323,7 +2336,8 @@
if (expressionType == null) {
return;
}
- if (_typeSystem.isAssignableTo(expressionType, type)) {
+ if (_typeSystem.isAssignableTo(expressionType, type,
+ featureSet: _featureSet)) {
return;
}
_errorReporter.reportErrorForNode(errorCode, expression, arguments);
@@ -2342,7 +2356,8 @@
DartType actualStaticType,
DartType expectedStaticType,
ErrorCode errorCode) {
- if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType)) {
+ if (!_typeSystem.isAssignableTo(actualStaticType, expectedStaticType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
errorCode, expression, [actualStaticType, expectedStaticType]);
return false;
@@ -3049,7 +3064,8 @@
StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
node.iterable,
[iterableType, loopTypeName]);
- } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+ } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
node.iterable,
@@ -3223,7 +3239,8 @@
if (staticType == null) {
return;
}
- if (_typeSystem.isAssignableTo(staticType, fieldType)) {
+ if (_typeSystem.isAssignableTo(staticType, fieldType,
+ featureSet: _featureSet)) {
return;
}
// report problem
@@ -3847,7 +3864,8 @@
}
DartType leftType = getStaticType(lhs);
DartType rightType = getStaticType(assignment);
- if (!_typeSystem.isAssignableTo(rightType, leftType)) {
+ if (!_typeSystem.isAssignableTo(rightType, leftType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.INVALID_ASSIGNMENT, rhs, [rightType, leftType]);
}
@@ -3960,6 +3978,7 @@
_checkForUseOfVoidResult,
forList: true,
elementType: listElementType,
+ featureSet: _featureSet,
);
for (CollectionElement element in literal.elements) {
verifier.verify(element);
@@ -3995,6 +4014,7 @@
forMap: true,
mapKeyType: keyType,
mapValueType: valueType,
+ featureSet: _featureSet,
);
for (CollectionElement element in literal.elements) {
verifier.verify(element);
@@ -4069,7 +4089,8 @@
// (if the getter is null, it is dynamic which is assignable to everything).
if (setterType != null &&
getterType != null &&
- !_typeSystem.isAssignableTo(getterType, setterType)) {
+ !_typeSystem.isAssignableTo(getterType, setterType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES,
accessorDeclaration,
@@ -4539,7 +4560,8 @@
if (!_checkForNullableDereference(condition) &&
!_checkForUseOfVoidResult(condition) &&
conditionType != null &&
- !_typeSystem.isAssignableTo(conditionType, _boolType)) {
+ !_typeSystem.isAssignableTo(conditionType, _boolType,
+ featureSet: _featureSet)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_CONDITION, condition);
}
@@ -4555,7 +4577,8 @@
Expression expression = assertion.condition;
DartType type = getStaticType(expression);
if (type is InterfaceType) {
- if (!_typeSystem.isAssignableTo(type, _boolType)) {
+ if (!_typeSystem.isAssignableTo(type, _boolType,
+ featureSet: _featureSet)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_EXPRESSION, expression);
}
@@ -4573,7 +4596,8 @@
void _checkForNonBoolNegationExpression(Expression expression) {
DartType conditionType = getStaticType(expression);
if (conditionType != null &&
- !_typeSystem.isAssignableTo(conditionType, _boolType)) {
+ !_typeSystem.isAssignableTo(conditionType, _boolType,
+ featureSet: _featureSet)) {
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.NON_BOOL_NEGATION_EXPRESSION, expression);
}
@@ -4660,8 +4684,8 @@
if (expression == null ||
!_isNonNullable ||
expression.staticType == null ||
- (expression.staticType as TypeImpl).nullabilitySuffix !=
- NullabilitySuffix.question) {
+ expression.staticType.isDynamic ||
+ !_typeSystem.isPotentiallyNullable(expression.staticType)) {
return false;
}
@@ -5162,7 +5186,8 @@
var checkWithType = (!_inAsync)
? fromType
: _typeProvider.futureType.instantiate(<DartType>[fromType]);
- if (_typeSystem.isAssignableTo(checkWithType, expectedType)) {
+ if (_typeSystem.isAssignableTo(checkWithType, expectedType,
+ featureSet: _featureSet)) {
return;
}
}
@@ -5200,6 +5225,7 @@
_checkForUseOfVoidResult,
forSet: true,
elementType: setElementType,
+ featureSet: _featureSet,
);
for (CollectionElement element in literal.elements) {
verifier.verify(element);
@@ -5266,7 +5292,8 @@
DartType caseType = getStaticType(caseExpression);
// check types
- if (!_typeSystem.isAssignableTo(expressionType, caseType)) {
+ if (!_typeSystem.isAssignableTo(expressionType, caseType,
+ featureSet: _featureSet)) {
_errorReporter.reportErrorForNode(
StaticWarningCode.SWITCH_EXPRESSION_NOT_ASSIGNABLE,
expression,
@@ -5592,7 +5619,8 @@
[parameter.identifier.name]);
} else if (declaredType != null &&
fieldType != null &&
- !_typeSystem.isAssignableTo(declaredType, fieldType)) {
+ !_typeSystem.isAssignableTo(declaredType, fieldType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
StaticWarningCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
parameter,
@@ -5703,6 +5731,30 @@
}
}
+ void _checkForWrongTypeParameterVarianceInSuperinterfaces() {
+ void checkOne(DartType superInterface) {
+ if (superInterface != null) {
+ for (var typeParameter in _enclosingClass.typeParameters) {
+ var variance = computeVariance(typeParameter, superInterface);
+ if (variance == Variance.contravariant ||
+ variance == Variance.invariant) {
+ _errorReporter.reportErrorForElement(
+ CompileTimeErrorCode
+ .WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ typeParameter,
+ [typeParameter.name, superInterface],
+ );
+ }
+ }
+ }
+ }
+
+ checkOne(_enclosingClass.supertype);
+ _enclosingClass.interfaces.forEach(checkOne);
+ _enclosingClass.mixins.forEach(checkOne);
+ _enclosingClass.superclassConstraints.forEach(checkOne);
+ }
+
/**
* Check for a type mis-match between the yielded type and the declared
* return type of a generator function.
@@ -5741,7 +5793,8 @@
} else {
requiredReturnType = _typeProvider.iterableDynamicType;
}
- if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType)) {
+ if (!_typeSystem.isAssignableTo(impliedReturnType, requiredReturnType,
+ featureSet: _featureSet)) {
_errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.YIELD_OF_INVALID_TYPE,
yieldExpression,
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index 21a62ae..d494c4e 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -6976,8 +6976,7 @@
SimpleIdentifier _parseSimpleIdentifierUnchecked(
{bool isDeclaration: false}) {
String lexeme = _currentToken.lexeme;
- if ((_inAsync || _inGenerator) &&
- (lexeme == ASYNC || lexeme == _AWAIT || lexeme == _YIELD)) {
+ if ((_inAsync || _inGenerator) && (lexeme == _AWAIT || lexeme == _YIELD)) {
_reportErrorForCurrentToken(
ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER);
}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index f66ceb7..91657b9 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -92,15 +92,6 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- InterfaceType type = getType(typeSystem, element, node.typeArguments);
- ConstructorElement constructorElement =
- type.lookUpConstructor(null, definingLibrary);
- methodName.staticElement = element;
- methodName.staticType = type;
- typeName.type = type;
- constructorName.staticElement = constructorElement;
- instanceCreationExpression.staticType = type;
- instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
} else if (target is SimpleIdentifier) {
@@ -130,17 +121,6 @@
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList,
typeArguments: typeArguments);
- InterfaceType type = getType(typeSystem, element, null);
- constructorElement =
- type.lookUpConstructor(methodName.name, definingLibrary);
- methodName.staticElement = element;
- methodName.staticType = type;
- target.staticElement = element;
- target.staticType = type; // TODO(scheglov) remove this
- typeName.type = type;
- constructorName.staticElement = constructorElement;
- instanceCreationExpression.staticType = type;
- instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
} else if (element is PrefixElement) {
@@ -160,16 +140,6 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- InterfaceType type =
- getType(typeSystem, prefixedElement, node.typeArguments);
- ConstructorElement constructorElement =
- type.lookUpConstructor(null, definingLibrary);
- methodName.staticElement = element;
- methodName.staticType = type;
- typeName.type = type;
- constructorName.staticElement = constructorElement;
- instanceCreationExpression.staticType = type;
- instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
}
@@ -197,16 +167,6 @@
InstanceCreationExpression instanceCreationExpression =
astFactory.instanceCreationExpression(
_getKeyword(node), constructorName, node.argumentList);
- InterfaceType type = getType(typeSystem, element, typeArguments);
- constructorElement =
- type.lookUpConstructor(methodName.name, definingLibrary);
- methodName.staticElement = element;
- methodName.staticType = type;
- target.identifier.staticElement = element;
- typeName.type = type;
- constructorName.staticElement = constructorElement;
- instanceCreationExpression.staticType = type;
- instanceCreationExpression.staticElement = constructorElement;
NodeReplacer.replace(node, instanceCreationExpression);
}
}
@@ -513,6 +473,14 @@
}
@override
+ void visitFunctionExpression(FunctionExpression node) {
+ if (node.parent is! FunctionDeclaration) {
+ _checkForMissingReturn(null, node.body, node.element, node);
+ }
+ super.visitFunctionExpression(node);
+ }
+
+ @override
void visitImportDirective(ImportDirective node) {
_checkForDeprecatedMemberUse(node.uriElement, node);
ImportElement importElement = node.element;
@@ -1074,7 +1042,27 @@
var flattenedType =
body.isAsynchronous ? _typeSystem.flatten(returnType) : returnType;
- // dynamic/Null/void are allowed to omit a return.
+ // Function expressions without a return will have their return type set
+ // to `Null` regardless of their context type. So we need to figure out
+ // if a return type was expected from the original downwards context.
+ //
+ // This helps detect hint cases like `int Function() f = () {}`.
+ // See https://github.com/dart-lang/sdk/issues/28233 for context.
+ if (flattenedType.isDartCoreNull && functionNode is FunctionExpression) {
+ var contextType = InferenceContext.getContext(functionNode);
+ if (contextType is FunctionType) {
+ returnType = contextType.returnType;
+ flattenedType = body.isAsynchronous
+ ? returnType.flattenFutures(_typeSystem)
+ : returnType;
+ }
+ }
+
+ // dynamic, Null, void, and FutureOr<T> where T is (dynamic, Null, void)
+ // are allowed to omit a return.
+ if (flattenedType.isDartAsyncFutureOr) {
+ flattenedType = (flattenedType as InterfaceType).typeArguments[0];
+ }
if (flattenedType.isDynamic ||
flattenedType.isDartCoreNull ||
flattenedType.isVoid) {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index dc2e4ce..1ce52ef 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -602,8 +602,10 @@
var context = InferenceContext.getContext(
(node as IntegerLiteralImpl).immediatelyNegated ? node.parent : node);
if (context == null ||
- _typeSystem.isAssignableTo(_typeProvider.intType, context) ||
- !_typeSystem.isAssignableTo(_typeProvider.doubleType, context)) {
+ _typeSystem.isAssignableTo(_typeProvider.intType, context,
+ featureSet: _featureSet) ||
+ !_typeSystem.isAssignableTo(_typeProvider.doubleType, context,
+ featureSet: _featureSet)) {
_recordStaticType(node, _nonNullable(_typeProvider.intType));
} else {
_recordStaticType(node, _nonNullable(_typeProvider.doubleType));
@@ -776,9 +778,7 @@
TypeImpl staticType = _getStaticType(operand, read: true);
if (node.operator.type == TokenType.BANG) {
- // TODO(paulberry): This does the wrong thing if staticType is a type
- // parameter type.
- staticType = staticType.withNullability(NullabilitySuffix.none);
+ staticType = _typeSystem.promoteToNonNull(staticType);
} else {
// No need to check for `intVar++`, the result is `int`.
if (!staticType.isDartCoreInt) {
@@ -914,8 +914,7 @@
if (node.operator.type == TokenType.QUESTION_PERIOD &&
_nonNullableEnabled) {
- staticType =
- (staticType as TypeImpl).withNullability(NullabilitySuffix.question);
+ staticType = _typeSystem.makeNullable(staticType);
}
staticType = _inferGenericInstantiationFromContext(node, staticType);
@@ -1165,7 +1164,8 @@
void _checkForInvalidAssignmentIncDec(
AstNode node, Expression operand, DartType type) {
var operandWriteType = _getStaticType(operand);
- if (!_typeSystem.isAssignableTo(type, operandWriteType)) {
+ if (!_typeSystem.isAssignableTo(type, operandWriteType,
+ featureSet: _featureSet)) {
_resolver.errorReporter.reportTypeErrorForNode(
StaticTypeWarningCode.INVALID_ASSIGNMENT,
node,
@@ -1232,22 +1232,24 @@
* Compute the return type of the method or function represented by the given
* type that is being invoked.
*/
- DartType _computeInvokeReturnType(DartType type,
+ DartType /*!*/ _computeInvokeReturnType(DartType type,
{@required bool isNullableInvoke}) {
- TypeImpl returnType;
+ TypeImpl /*!*/ returnType;
if (type is InterfaceType) {
MethodElement callMethod = type.lookUpMethod(
FunctionElement.CALL_METHOD_NAME, _resolver.definingLibrary);
- returnType = callMethod?.type?.returnType;
+ returnType = callMethod?.type?.returnType ?? _dynamicType;
} else if (type is FunctionType) {
- returnType = type.returnType;
+ returnType = type.returnType ?? _dynamicType;
+ } else {
+ returnType = _dynamicType;
}
if (isNullableInvoke && _nonNullableEnabled) {
- returnType = returnType?.withNullability(NullabilitySuffix.question);
+ returnType = _typeSystem.makeNullable(returnType);
}
- return returnType ?? _dynamicType;
+ return returnType;
}
/**
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 ab12e27..469e29c 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/generated/testing/token_factory.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
+import 'package:meta/meta.dart';
/**
* The class `AstTestFactory` defines utility methods that can be used to create AST nodes. The
@@ -469,6 +470,24 @@
static ExtendsClause extendsClause(TypeName type) => astFactory.extendsClause(
TokenFactory.tokenFromKeyword(Keyword.EXTENDS), type);
+ static ExtensionDeclaration extensionDeclaration(
+ {@required String name,
+ TypeParameterList typeParameters,
+ @required TypeAnnotation extendedType,
+ List<ClassMember> members}) =>
+ astFactory.extensionDeclaration(
+ comment: null,
+ metadata: null,
+ extensionKeyword: TokenFactory.tokenFromKeyword(Keyword.EXTENSION),
+ name: identifier3(name),
+ typeParameters: typeParameters,
+ onKeyword: TokenFactory.tokenFromKeyword(Keyword.ON),
+ extendedType: extendedType,
+ leftBracket: TokenFactory.tokenFromType(TokenType.OPEN_CURLY_BRACKET),
+ members: members,
+ rightBracket:
+ TokenFactory.tokenFromType(TokenType.CLOSE_CURLY_BRACKET));
+
static FieldDeclaration fieldDeclaration(bool isStatic, Keyword keyword,
TypeAnnotation type, List<VariableDeclaration> variables) =>
astFactory.fieldDeclaration2(
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 4ef1a61..f3dce0d 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -51,7 +51,9 @@
bool _isBottom(DartType t) {
return t.isBottom ||
- t.isDartCoreNull ||
+ // TODO(mfairhurst): Remove the exception treating Null* as Top.
+ t.isDartCoreNull &&
+ (t as TypeImpl).nullabilitySuffix == NullabilitySuffix.star ||
identical(t, UnknownInferredType.instance);
}
@@ -60,7 +62,8 @@
return _isTop((t as InterfaceType).typeArguments[0]);
}
return t.isDynamic ||
- t.isObject ||
+ (t.isObject &&
+ (t as TypeImpl).nullabilitySuffix != NullabilitySuffix.none) ||
t.isVoid ||
identical(t, UnknownInferredType.instance);
}
@@ -75,7 +78,8 @@
new HashSet<TypeComparison>();
/**
- * True if implicit casts should be allowed, otherwise false.
+ * False if implicit casts should always be disallowed, otherwise the
+ * [FeatureSet] will be used.
*
* This affects the behavior of [isAssignableTo].
*/
@@ -448,7 +452,8 @@
}
@override
- bool isAssignableTo(DartType fromType, DartType toType) {
+ bool isAssignableTo(DartType fromType, DartType toType,
+ {FeatureSet featureSet}) {
// An actual subtype
if (isSubtypeOf(fromType, toType)) {
return true;
@@ -457,15 +462,23 @@
// A call method tearoff
if (fromType is InterfaceType && acceptsFunctionType(toType)) {
var callMethodType = getCallMethodType(fromType);
- if (callMethodType != null && isAssignableTo(callMethodType, toType)) {
+ if (callMethodType != null &&
+ isAssignableTo(callMethodType, toType, featureSet: featureSet)) {
return true;
}
}
+ // First make sure --no-implicit-casts disables all downcasts, including
+ // dynamic casts.
if (!implicitCasts) {
return false;
}
+ // Now handle NNBD default behavior, where we disable non-dynamic downcasts.
+ if (featureSet != null && featureSet.isEnabled(Feature.non_nullable)) {
+ return fromType.isDynamic;
+ }
+
// Don't allow implicit downcasts between function types
// and call method objects, as these will almost always fail.
if (fromType is FunctionType && getCallMethodType(toType) != null) {
@@ -484,8 +497,7 @@
return false;
}
- // If the subtype relation goes the other way, allow the implicit
- // downcast.
+ // If the subtype relation goes the other way, allow the implicit downcast.
if (isSubtypeOf(toType, fromType)) {
// TODO(leafp,jmesserly): we emit warnings/hints for these in
// src/task/strong/checker.dart, which is a bit inconsistent. That
@@ -550,12 +562,23 @@
p1.isCovariant && isSubtypeOf(p1.type, p2.type);
}
+ /// Check if [_t1] is a subtype of [_t2].
+ ///
+ /// Partially updated to reflect
+ /// https://github.com/dart-lang/language/blob/da5adf7eb5f2d479069d8660ed7ca7b230098510/resources/type-system/subtyping.md
+ ///
+ /// However, it does not correllate 1:1 and does not specialize Null vs Never
+ /// cases. It also is not guaranteed to be exactly accurate vs the "spec"
+ /// because it has slightly different order of operations. These should be
+ /// brought in line or proven equivalent.
@override
- bool isSubtypeOf(DartType t1, DartType t2) {
+ bool isSubtypeOf(DartType _t1, DartType _t2) {
+ var t1 = _t1 as TypeImpl;
+ var t2 = _t2 as TypeImpl;
+
if (identical(t1, t2)) {
return true;
}
-
// The types are void, dynamic, bottom, interface types, function types,
// FutureOr<T> and type parameters.
//
@@ -574,10 +597,36 @@
return false;
}
+ // TODO(mfairhurst): Convert Null to Never?, to simplify the algorithm, and
+ // remove this check.
+ if (t1.isDartCoreNull) {
+ if (t2.nullabilitySuffix != NullabilitySuffix.none) {
+ return true;
+ }
+ }
+
+ // Handle T1? <: T2
+ if (t1.nullabilitySuffix == NullabilitySuffix.question) {
+ if (t2.nullabilitySuffix == NullabilitySuffix.none) {
+ // If T2 is not FutureOr<S2>, then subtype is false.
+ if (!t2.isDartAsyncFutureOr) {
+ return false;
+ }
+
+ // T1? <: FutureOr<T2> is true if T2 is S2?.
+ // TODO(mfairhurst): handle T1? <: FutureOr<dynamic>, etc.
+ if (t2 is InterfaceTypeImpl &&
+ (t2.typeArguments[0] as TypeImpl).nullabilitySuffix ==
+ NullabilitySuffix.none) {
+ return false;
+ }
+ }
+ }
+
// Handle FutureOr<T> union type.
- if (t1 is InterfaceType && t1.isDartAsyncFutureOr) {
+ if (t1 is InterfaceTypeImpl && t1.isDartAsyncFutureOr) {
var t1TypeArg = t1.typeArguments[0];
- if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+ if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
var t2TypeArg = t2.typeArguments[0];
// FutureOr<A> <: FutureOr<B> iff A <: B
return isSubtypeOf(t1TypeArg, t2TypeArg);
@@ -589,7 +638,7 @@
return isSubtypeOf(t1Future, t2) && isSubtypeOf(t1TypeArg, t2);
}
- if (t2 is InterfaceType && t2.isDartAsyncFutureOr) {
+ if (t2 is InterfaceTypeImpl && t2.isDartAsyncFutureOr) {
// given t2 is Future<A> | A, then:
// t1 <: (Future<A> | A) iff t1 <: Future<A> or t1 <: A
var t2TypeArg = t2.typeArguments[0];
@@ -601,23 +650,26 @@
// T is not dynamic or object (handled above)
// True if T == S
// Or true if bound of S is S' and S' <: T
- if (t1 is TypeParameterType) {
- if (t2 is TypeParameterType &&
+ if (t1 is TypeParameterTypeImpl) {
+ if (t2 is TypeParameterTypeImpl &&
t1.definition == t2.definition &&
_typeParameterBoundsSubtype(t1.bound, t2.bound, true)) {
return true;
}
+
DartType bound = t1.element.bound;
return bound == null
? false
: _typeParameterBoundsSubtype(bound, t2, false);
}
+
if (t2 is TypeParameterType) {
return false;
}
- // We've eliminated void, dynamic, bottom, type parameters, and FutureOr.
- // The only cases are the combinations of interface type and function type.
+ // We've eliminated void, dynamic, bottom, type parameters, FutureOr,
+ // nullable, and legacy nullable types. The only cases are the combinations
+ // of interface type and function type.
// A function type can only subtype an interface type if
// the interface type is Function
@@ -628,11 +680,11 @@
if (t1 is InterfaceType && t2 is FunctionType) return false;
// Two interface types
- if (t1 is InterfaceType && t2 is InterfaceType) {
+ if (t1 is InterfaceTypeImpl && t2 is InterfaceTypeImpl) {
return _isInterfaceSubtypeOf(t1, t2, null);
}
- return _isFunctionSubtypeOf(t1, t2);
+ return _isFunctionSubtypeOf(t1 as FunctionType, t2 as FunctionType);
}
/// Given a [type] T that may have an unknown type `?`, returns a type
@@ -1978,9 +2030,11 @@
/**
* Return `true` if the [leftType] is assignable to the [rightType] (that is,
- * if leftType <==> rightType).
+ * if leftType <==> rightType). Accepts a [FeatureSet] to correctly handle
+ * NNBD implicit downcasts.
*/
- bool isAssignableTo(DartType leftType, DartType rightType);
+ bool isAssignableTo(DartType leftType, DartType rightType,
+ {FeatureSet featureSet});
/**
* Return `true` if the [leftType] is more specific than the [rightType]
@@ -2035,6 +2089,13 @@
return getLeastUpperBound(leftType, rightType);
}
+ /// Returns a nullable version of [type]. The result would be equivalent to
+ /// the union `type | Null` (if we supported union types).
+ DartType makeNullable(TypeImpl type) {
+ // TODO(paulberry): handle type parameter types
+ return type.withNullability(NullabilitySuffix.question);
+ }
+
/// Attempts to find the appropriate substitution for [typeParameters] that can
/// be applied to [src] to make it equal to [dest]. If no such substitution can
/// be found, `null` is returned.
@@ -2089,7 +2150,10 @@
return null;
}
+ /// Returns a non-nullable version of [type]. This is equivalent to the
+ /// operation `NonNull` defined in the spec.
DartType promoteToNonNull(TypeImpl type) {
+ if (type.isDartCoreNull) return typeProvider.bottomType;
// TODO(mfairhurst): handle type parameter types
return type.withNullability(NullabilitySuffix.none);
}
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index 938d454..98a39ae 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -72,10 +72,14 @@
VersionRange get before_2_2_2 =>
new VersionRange(max: Version.parse('2.2.2'), includeMax: false);
+ /// Return a range covering every version up to, but not including, 2.3.2.
+ VersionRange get before_2_3_2 =>
+ new VersionRange(max: Version.parse('2.3.2'), includeMax: false);
+
/// Return `true` if references to the constant-update-2018 features need to
/// be checked.
bool get checkConstantUpdate2018 => _checkConstantUpdate2018 ??=
- !before_2_2_2.intersect(_versionConstraint).isEmpty;
+ !before_2_3_2.intersect(_versionConstraint).isEmpty;
/// Return `true` if references to Future and Stream need to be checked.
bool get checkFutureAndStream => _checkFutureAndStream ??=
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index 1f18466..6de334c 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -57,6 +57,7 @@
final String typeParameters;
List<String> _relevanceTags;
+ Uri _locationLibraryUri;
Declaration({
@required this.children,
@@ -84,6 +85,8 @@
@required this.typeParameters,
}) : _relevanceTags = relevanceTags;
+ Uri get locationLibraryUri => _locationLibraryUri;
+
List<String> get relevanceTags => _relevanceTags;
@override
@@ -474,6 +477,12 @@
_changedPaths.add(path);
}
+ /// Discard the [analysisContext], but don't discard any libraries that it
+ /// might have in its dependencies.
+ void discardContext(AnalysisContext analysisContext) {
+ _contexts.remove(analysisContext);
+ }
+
/// Discard all contexts and libraries, notify the [changes] stream that
/// these libraries are removed.
void discardContexts() {
@@ -1104,6 +1113,7 @@
libraryDeclarations.addAll(part.file.fileDeclarations);
}
_computeRelevanceTags(libraryDeclarations);
+ _setLocationLibraryUri();
}
}
@@ -1377,6 +1387,19 @@
returnType: _getTypeAnnotationString(functionType.returnType),
typeParameters: functionType.typeParameters?.toSource(),
);
+ } else if (node is FunctionTypeAlias) {
+ var parameters = node.parameters;
+ addDeclaration(
+ isDeprecated: isDeprecated,
+ kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
+ name: node.name,
+ parameters: parameters.toSource(),
+ parameterNames: _getFormalParameterNames(parameters),
+ parameterTypes: _getFormalParameterTypes(parameters),
+ requiredParameterCount: _getFormalParameterRequiredCount(parameters),
+ returnType: _getTypeAnnotationString(node.returnType),
+ typeParameters: node.typeParameters?.toSource(),
+ );
} else if (node is MixinDeclaration) {
addDeclaration(
isDeprecated: isDeprecated,
@@ -1503,6 +1526,12 @@
templateValues = idlFile.directiveInfo.templateValues.toList();
}
+ void _setLocationLibraryUri() {
+ for (var declaration in libraryDeclarations) {
+ declaration._locationLibraryUri = uri;
+ }
+ }
+
static _DefaultArguments _computeDefaultArguments(
FormalParameterList parameters) {
var buffer = StringBuffer();
diff --git a/pkg/analyzer/lib/src/summary/flat_buffers.dart b/pkg/analyzer/lib/src/summary/flat_buffers.dart
index da60445..96d0719 100644
--- a/pkg/analyzer/lib/src/summary/flat_buffers.dart
+++ b/pkg/analyzer/lib/src/summary/flat_buffers.dart
@@ -89,6 +89,16 @@
final int initialSize;
/**
+ * The list of field tails, reused by [_VTable] instances.
+ */
+ final Int32List _reusedFieldTails = Int32List(1024);
+
+ /**
+ * The list of field offsets, reused by [_VTable] instances.
+ */
+ final Int32List _reusedFieldOffsets = Int32List(1024);
+
+ /**
* The list of existing VTable(s).
*/
final List<_VTable> _vTables = <_VTable>[];
@@ -248,6 +258,7 @@
}
// Write a new VTable.
if (vTableTail == null) {
+ _currentVTable.takeFieldOffsets();
_prepare(2, _currentVTable.numOfUint16);
vTableTail = _tail;
_currentVTable.tail = vTableTail;
@@ -332,7 +343,7 @@
if (_currentVTable != null) {
throw new StateError('Inline tables are not supported.');
}
- _currentVTable = new _VTable();
+ _currentVTable = new _VTable(_reusedFieldTails, _reusedFieldOffsets);
_currentTableEndTail = _tail;
}
@@ -570,6 +581,19 @@
}
/**
+ * The reader of 64-bit floats.
+ */
+class Float64Reader extends Reader<double> {
+ const Float64Reader() : super();
+
+ @override
+ int get size => 8;
+
+ @override
+ double read(BufferContext bc, int offset) => bc._getFloat64(offset);
+}
+
+/**
* The reader of signed 32-bit integers.
*/
class Int32Reader extends Reader<int> {
@@ -768,19 +792,6 @@
}
/**
- * The reader of 64-bit floats.
- */
-class Float64Reader extends Reader<double> {
- const Float64Reader() : super();
-
- @override
- int get size => 8;
-
- @override
- double read(BufferContext bc, int offset) => bc._getFloat64(offset);
-}
-
-/**
* List of booleans backed by 8-bit unsigned integers.
*/
class _FbBoolList with ListMixin<bool> implements List<bool> {
@@ -905,8 +916,19 @@
* Class that describes the structure of a table.
*/
class _VTable {
- final List<int> fieldTails = <int>[];
- List<int> fieldOffsets;
+ final Int32List _reusedFieldTails;
+ final Int32List _reusedFieldOffsets;
+
+ /**
+ * The number of fields in [_reusedFieldTails].
+ */
+ int _fieldCount = 0;
+
+ /**
+ * The private copy of [_reusedFieldOffsets], which is made only when we
+ * find that this table is unique.
+ */
+ Int32List _fieldOffsets;
/**
* The size of the table that uses this VTable.
@@ -919,13 +941,15 @@
*/
int tail;
- int get numOfUint16 => 1 + 1 + fieldTails.length;
+ _VTable(this._reusedFieldTails, this._reusedFieldOffsets);
+
+ int get numOfUint16 => 1 + 1 + _fieldCount;
void addField(int field, int offset) {
- while (fieldTails.length <= field) {
- fieldTails.add(null);
+ while (_fieldCount <= field) {
+ _reusedFieldTails[_fieldCount++] = -1;
}
- fieldTails[field] = offset;
+ _reusedFieldTails[field] = offset;
}
/**
@@ -935,9 +959,9 @@
assert(tail == null);
assert(existing.tail != null);
if (tableSize == existing.tableSize &&
- fieldOffsets.length == existing.fieldOffsets.length) {
- for (int i = 0; i < fieldOffsets.length; i++) {
- if (fieldOffsets[i] != existing.fieldOffsets[i]) {
+ _fieldCount == existing._fieldCount) {
+ for (int i = 0; i < _fieldCount; i++) {
+ if (_reusedFieldOffsets[i] != existing._fieldOffsets[i]) {
return false;
}
}
@@ -947,14 +971,12 @@
}
/**
- * Fill the [fieldOffsets] field.
+ * Fill the [_reusedFieldOffsets] field.
*/
void computeFieldOffsets(int tableTail) {
- assert(fieldOffsets == null);
- fieldOffsets = List<int>(fieldTails.length);
- for (int i = 0; i < fieldTails.length; ++i) {
- int fieldTail = fieldTails[i];
- fieldOffsets[i] = fieldTail == null ? 0 : tableTail - fieldTail;
+ for (int i = 0; i < _fieldCount; ++i) {
+ int fieldTail = _reusedFieldTails[i];
+ _reusedFieldOffsets[i] = fieldTail == -1 ? 0 : tableTail - fieldTail;
}
}
@@ -970,9 +992,20 @@
buf.setUint16(bufOffset, tableSize, Endian.little);
bufOffset += 2;
// Field offsets.
- for (int fieldOffset in fieldOffsets) {
+ for (int fieldOffset in _fieldOffsets) {
buf.setUint16(bufOffset, fieldOffset, Endian.little);
bufOffset += 2;
}
}
+
+ /**
+ * Fill the [_fieldOffsets] field.
+ */
+ void takeFieldOffsets() {
+ assert(_fieldOffsets == null);
+ _fieldOffsets = Int32List(_fieldCount);
+ for (int i = 0; i < _fieldCount; ++i) {
+ _fieldOffsets[i] = _reusedFieldOffsets[i];
+ }
+ }
}
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index bcfbc8c..2b5c069 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -4737,11 +4737,12 @@
LinkedNodeBuilder _variantField_12;
List<LinkedNodeBuilder> _variantField_5;
LinkedNodeBuilder _variantField_13;
- int _variantField_34;
int _variantField_33;
- List<String> _variantField_36;
+ int _variantField_32;
+ List<String> _variantField_35;
idl.LinkedNodeCommentType _variantField_29;
List<LinkedNodeBuilder> _variantField_3;
+ int _variantField_19;
LinkedNodeBuilder _variantField_10;
idl.LinkedNodeFormalParameterKind _variantField_26;
double _variantField_21;
@@ -4752,14 +4753,12 @@
String _variantField_30;
LinkedNodeBuilder _variantField_14;
idl.LinkedNodeKind _kind;
- String _name;
+ List<String> _variantField_36;
String _variantField_20;
bool _variantField_31;
- idl.UnlinkedTokenType _variantField_38;
- TopLevelInferenceErrorBuilder _variantField_35;
+ idl.UnlinkedTokenType _variantField_37;
+ TopLevelInferenceErrorBuilder _variantField_34;
String _variantField_22;
- int _variantField_19;
- LinkedNodeVariablesDeclarationBuilder _variantField_32;
@override
LinkedNodeTypeBuilder get actualReturnType {
@@ -5376,6 +5375,12 @@
}
@override
+ LinkedNodeBuilder get enumConstantDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+ return _variantField_6;
+ }
+
+ @override
LinkedNodeBuilder get expressionFunctionBody_expression {
assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
return _variantField_6;
@@ -5811,6 +5816,11 @@
_variantField_6 = value;
}
+ set enumConstantDeclaration_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+ _variantField_6 = value;
+ }
+
set expressionFunctionBody_expression(LinkedNodeBuilder value) {
assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
_variantField_6 = value;
@@ -6143,6 +6153,12 @@
}
@override
+ LinkedNodeBuilder get constructorDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ return _variantField_7;
+ }
+
+ @override
LinkedNodeBuilder get constructorFieldInitializer_fieldName {
assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
return _variantField_7;
@@ -6341,6 +6357,18 @@
}
@override
+ LinkedNodeBuilder get typeParameter_name {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ return _variantField_7;
+ }
+
+ @override
+ LinkedNodeBuilder get variableDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ return _variantField_7;
+ }
+
+ @override
LinkedNodeBuilder get whileStatement_condition {
assert(kind == idl.LinkedNodeKind.whileStatement);
return _variantField_7;
@@ -6401,6 +6429,11 @@
_variantField_7 = value;
}
+ set constructorDeclaration_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ _variantField_7 = value;
+ }
+
set constructorFieldInitializer_fieldName(LinkedNodeBuilder value) {
assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
_variantField_7 = value;
@@ -6567,6 +6600,16 @@
_variantField_7 = value;
}
+ set typeParameter_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ _variantField_7 = value;
+ }
+
+ set variableDeclaration_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_7 = value;
+ }
+
set whileStatement_condition(LinkedNodeBuilder value) {
assert(kind == idl.LinkedNodeKind.whileStatement);
_variantField_7 = value;
@@ -6579,6 +6622,16 @@
}
@override
+ int get directive_keywordOffset {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.libraryDirective ||
+ kind == idl.LinkedNodeKind.partDirective ||
+ kind == idl.LinkedNodeKind.partOfDirective);
+ return _variantField_17 ??= 0;
+ }
+
+ @override
int get genericFunctionType_id {
assert(kind == idl.LinkedNodeKind.genericFunctionType);
return _variantField_17 ??= 0;
@@ -6590,6 +6643,16 @@
_variantField_17 = value;
}
+ set directive_keywordOffset(int value) {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.libraryDirective ||
+ kind == idl.LinkedNodeKind.partDirective ||
+ kind == idl.LinkedNodeKind.partOfDirective);
+ assert(value == null || value >= 0);
+ _variantField_17 = value;
+ }
+
set genericFunctionType_id(int value) {
assert(kind == idl.LinkedNodeKind.genericFunctionType);
assert(value == null || value >= 0);
@@ -7198,6 +7261,14 @@
return _variantField_9;
}
+ @override
+ LinkedNodeBuilder get normalFormalParameter_identifier {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ return _variantField_9;
+ }
+
set catchClause_stackTraceParameter(LinkedNodeBuilder value) {
assert(kind == idl.LinkedNodeKind.catchClause);
_variantField_9 = value;
@@ -7223,6 +7294,13 @@
_variantField_9 = value;
}
+ set normalFormalParameter_identifier(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_9 = value;
+ }
+
@override
LinkedNodeBuilder get classOrMixinDeclaration_implementsClause {
assert(kind == idl.LinkedNodeKind.classDeclaration ||
@@ -7306,52 +7384,10 @@
kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.typeParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- return _variantField_34 ??= 0;
- }
-
- set codeLength(int value) {
- assert(kind == idl.LinkedNodeKind.classDeclaration ||
- kind == idl.LinkedNodeKind.classTypeAlias ||
- kind == idl.LinkedNodeKind.compilationUnit ||
- kind == idl.LinkedNodeKind.constructorDeclaration ||
- kind == idl.LinkedNodeKind.defaultFormalParameter ||
- kind == idl.LinkedNodeKind.enumDeclaration ||
- kind == idl.LinkedNodeKind.fieldFormalParameter ||
- kind == idl.LinkedNodeKind.functionDeclaration ||
- kind == idl.LinkedNodeKind.functionTypeAlias ||
- kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
- kind == idl.LinkedNodeKind.genericTypeAlias ||
- kind == idl.LinkedNodeKind.methodDeclaration ||
- kind == idl.LinkedNodeKind.mixinDeclaration ||
- kind == idl.LinkedNodeKind.simpleFormalParameter ||
- kind == idl.LinkedNodeKind.typeParameter ||
- kind == idl.LinkedNodeKind.variableDeclaration);
- assert(value == null || value >= 0);
- _variantField_34 = value;
- }
-
- @override
- int get codeOffset {
- assert(kind == idl.LinkedNodeKind.classDeclaration ||
- kind == idl.LinkedNodeKind.classTypeAlias ||
- kind == idl.LinkedNodeKind.compilationUnit ||
- kind == idl.LinkedNodeKind.constructorDeclaration ||
- kind == idl.LinkedNodeKind.defaultFormalParameter ||
- kind == idl.LinkedNodeKind.enumDeclaration ||
- kind == idl.LinkedNodeKind.fieldFormalParameter ||
- kind == idl.LinkedNodeKind.functionDeclaration ||
- kind == idl.LinkedNodeKind.functionTypeAlias ||
- kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
- kind == idl.LinkedNodeKind.genericTypeAlias ||
- kind == idl.LinkedNodeKind.methodDeclaration ||
- kind == idl.LinkedNodeKind.mixinDeclaration ||
- kind == idl.LinkedNodeKind.simpleFormalParameter ||
- kind == idl.LinkedNodeKind.typeParameter ||
- kind == idl.LinkedNodeKind.variableDeclaration);
return _variantField_33 ??= 0;
}
- set codeOffset(int value) {
+ set codeLength(int value) {
assert(kind == idl.LinkedNodeKind.classDeclaration ||
kind == idl.LinkedNodeKind.classTypeAlias ||
kind == idl.LinkedNodeKind.compilationUnit ||
@@ -7373,40 +7409,56 @@
}
@override
+ int get codeOffset {
+ assert(kind == idl.LinkedNodeKind.classDeclaration ||
+ kind == idl.LinkedNodeKind.classTypeAlias ||
+ kind == idl.LinkedNodeKind.compilationUnit ||
+ kind == idl.LinkedNodeKind.constructorDeclaration ||
+ kind == idl.LinkedNodeKind.defaultFormalParameter ||
+ kind == idl.LinkedNodeKind.enumDeclaration ||
+ kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionDeclaration ||
+ kind == idl.LinkedNodeKind.functionTypeAlias ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.genericTypeAlias ||
+ kind == idl.LinkedNodeKind.methodDeclaration ||
+ kind == idl.LinkedNodeKind.mixinDeclaration ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter ||
+ kind == idl.LinkedNodeKind.typeParameter ||
+ kind == idl.LinkedNodeKind.variableDeclaration);
+ return _variantField_32 ??= 0;
+ }
+
+ set codeOffset(int value) {
+ assert(kind == idl.LinkedNodeKind.classDeclaration ||
+ kind == idl.LinkedNodeKind.classTypeAlias ||
+ kind == idl.LinkedNodeKind.compilationUnit ||
+ kind == idl.LinkedNodeKind.constructorDeclaration ||
+ kind == idl.LinkedNodeKind.defaultFormalParameter ||
+ kind == idl.LinkedNodeKind.enumDeclaration ||
+ kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionDeclaration ||
+ kind == idl.LinkedNodeKind.functionTypeAlias ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.genericTypeAlias ||
+ kind == idl.LinkedNodeKind.methodDeclaration ||
+ kind == idl.LinkedNodeKind.mixinDeclaration ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter ||
+ kind == idl.LinkedNodeKind.typeParameter ||
+ kind == idl.LinkedNodeKind.variableDeclaration);
+ assert(value == null || value >= 0);
+ _variantField_32 = value;
+ }
+
+ @override
List<String> get comment_tokens {
assert(kind == idl.LinkedNodeKind.comment);
- return _variantField_36 ??= <String>[];
- }
-
- @override
- List<String> get mixinDeclaration_superInvokedNames {
- assert(kind == idl.LinkedNodeKind.mixinDeclaration);
- return _variantField_36 ??= <String>[];
- }
-
- @override
- List<String> get names {
- assert(kind == idl.LinkedNodeKind.hideCombinator ||
- kind == idl.LinkedNodeKind.showCombinator ||
- kind == idl.LinkedNodeKind.symbolLiteral);
- return _variantField_36 ??= <String>[];
+ return _variantField_35 ??= <String>[];
}
set comment_tokens(List<String> value) {
assert(kind == idl.LinkedNodeKind.comment);
- _variantField_36 = value;
- }
-
- set mixinDeclaration_superInvokedNames(List<String> value) {
- assert(kind == idl.LinkedNodeKind.mixinDeclaration);
- _variantField_36 = value;
- }
-
- set names(List<String> value) {
- assert(kind == idl.LinkedNodeKind.hideCombinator ||
- kind == idl.LinkedNodeKind.showCombinator ||
- kind == idl.LinkedNodeKind.symbolLiteral);
- _variantField_36 = value;
+ _variantField_35 = value;
}
@override
@@ -7480,16 +7532,78 @@
}
@override
+ int get constructorDeclaration_periodOffset {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ return _variantField_19 ??= 0;
+ }
+
+ @override
+ int get uriBasedDirective_uriElement {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.partDirective);
+ return _variantField_19 ??= 0;
+ }
+
+ set constructorDeclaration_periodOffset(int value) {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ assert(value == null || value >= 0);
+ _variantField_19 = value;
+ }
+
+ set uriBasedDirective_uriElement(int value) {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.partDirective);
+ assert(value == null || value >= 0);
+ _variantField_19 = value;
+ }
+
+ @override
LinkedNodeBuilder get constructorDeclaration_returnType {
assert(kind == idl.LinkedNodeKind.constructorDeclaration);
return _variantField_10;
}
+ @override
+ LinkedNodeBuilder get methodDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ return _variantField_10;
+ }
+
+ @override
+ LinkedNodeBuilder get namedCompilationUnitMember_name {
+ assert(kind == idl.LinkedNodeKind.classDeclaration ||
+ kind == idl.LinkedNodeKind.classTypeAlias ||
+ kind == idl.LinkedNodeKind.enumDeclaration ||
+ kind == idl.LinkedNodeKind.functionDeclaration ||
+ kind == idl.LinkedNodeKind.functionTypeAlias ||
+ kind == idl.LinkedNodeKind.genericTypeAlias ||
+ kind == idl.LinkedNodeKind.mixinDeclaration);
+ return _variantField_10;
+ }
+
set constructorDeclaration_returnType(LinkedNodeBuilder value) {
assert(kind == idl.LinkedNodeKind.constructorDeclaration);
_variantField_10 = value;
}
+ set methodDeclaration_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ _variantField_10 = value;
+ }
+
+ set namedCompilationUnitMember_name(LinkedNodeBuilder value) {
+ assert(kind == idl.LinkedNodeKind.classDeclaration ||
+ kind == idl.LinkedNodeKind.classTypeAlias ||
+ kind == idl.LinkedNodeKind.enumDeclaration ||
+ kind == idl.LinkedNodeKind.functionDeclaration ||
+ kind == idl.LinkedNodeKind.functionTypeAlias ||
+ kind == idl.LinkedNodeKind.genericTypeAlias ||
+ kind == idl.LinkedNodeKind.mixinDeclaration);
+ _variantField_10 = value;
+ }
+
@override
idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
@@ -7607,25 +7721,8 @@
}
@override
- int get nameOffset {
- assert(kind == idl.LinkedNodeKind.classDeclaration ||
- kind == idl.LinkedNodeKind.classTypeAlias ||
- kind == idl.LinkedNodeKind.constructorDeclaration ||
- kind == idl.LinkedNodeKind.enumConstantDeclaration ||
- kind == idl.LinkedNodeKind.enumDeclaration ||
- kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.fieldFormalParameter ||
- kind == idl.LinkedNodeKind.functionDeclaration ||
- kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
- kind == idl.LinkedNodeKind.functionTypeAlias ||
- kind == idl.LinkedNodeKind.genericTypeAlias ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.methodDeclaration ||
- kind == idl.LinkedNodeKind.mixinDeclaration ||
- kind == idl.LinkedNodeKind.partDirective ||
- kind == idl.LinkedNodeKind.simpleFormalParameter ||
- kind == idl.LinkedNodeKind.typeParameter ||
- kind == idl.LinkedNodeKind.variableDeclaration);
+ int get simpleIdentifier_offset {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
return _variantField_16 ??= 0;
}
@@ -7635,25 +7732,8 @@
_variantField_16 = value;
}
- set nameOffset(int value) {
- assert(kind == idl.LinkedNodeKind.classDeclaration ||
- kind == idl.LinkedNodeKind.classTypeAlias ||
- kind == idl.LinkedNodeKind.constructorDeclaration ||
- kind == idl.LinkedNodeKind.enumConstantDeclaration ||
- kind == idl.LinkedNodeKind.enumDeclaration ||
- kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.fieldFormalParameter ||
- kind == idl.LinkedNodeKind.functionDeclaration ||
- kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
- kind == idl.LinkedNodeKind.functionTypeAlias ||
- kind == idl.LinkedNodeKind.genericTypeAlias ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.methodDeclaration ||
- kind == idl.LinkedNodeKind.mixinDeclaration ||
- kind == idl.LinkedNodeKind.partDirective ||
- kind == idl.LinkedNodeKind.simpleFormalParameter ||
- kind == idl.LinkedNodeKind.typeParameter ||
- kind == idl.LinkedNodeKind.variableDeclaration);
+ set simpleIdentifier_offset(int value) {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
assert(value == null || value >= 0);
_variantField_16 = value;
}
@@ -7720,10 +7800,29 @@
}
@override
- String get name => _name ??= '';
+ List<String> get mixinDeclaration_superInvokedNames {
+ assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+ return _variantField_36 ??= <String>[];
+ }
- set name(String value) {
- this._name = value;
+ @override
+ List<String> get names {
+ assert(kind == idl.LinkedNodeKind.hideCombinator ||
+ kind == idl.LinkedNodeKind.showCombinator ||
+ kind == idl.LinkedNodeKind.symbolLiteral);
+ return _variantField_36 ??= <String>[];
+ }
+
+ set mixinDeclaration_superInvokedNames(List<String> value) {
+ assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+ _variantField_36 = value;
+ }
+
+ set names(List<String> value) {
+ assert(kind == idl.LinkedNodeKind.hideCombinator ||
+ kind == idl.LinkedNodeKind.showCombinator ||
+ kind == idl.LinkedNodeKind.symbolLiteral);
+ _variantField_36 = value;
}
@override
@@ -7734,6 +7833,12 @@
}
@override
+ String get simpleIdentifier_name {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+ return _variantField_20 ??= '';
+ }
+
+ @override
String get simpleStringLiteral_value {
assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
return _variantField_20 ??= '';
@@ -7745,6 +7850,11 @@
_variantField_20 = value;
}
+ set simpleIdentifier_name(String value) {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+ _variantField_20 = value;
+ }
+
set simpleStringLiteral_value(String value) {
assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
_variantField_20 = value;
@@ -7772,25 +7882,25 @@
@override
idl.UnlinkedTokenType get spreadElement_spreadOperator {
assert(kind == idl.LinkedNodeKind.spreadElement);
- return _variantField_38 ??= idl.UnlinkedTokenType.NOTHING;
+ return _variantField_37 ??= idl.UnlinkedTokenType.NOTHING;
}
set spreadElement_spreadOperator(idl.UnlinkedTokenType value) {
assert(kind == idl.LinkedNodeKind.spreadElement);
- _variantField_38 = value;
+ _variantField_37 = value;
}
@override
TopLevelInferenceErrorBuilder get topLevelTypeInferenceError {
assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- return _variantField_35;
+ return _variantField_34;
}
set topLevelTypeInferenceError(TopLevelInferenceErrorBuilder value) {
assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_35 = value;
+ _variantField_34 = value;
}
@override
@@ -7808,713 +7918,11 @@
_variantField_22 = value;
}
- @override
- int get uriBasedDirective_uriElement {
- assert(kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.partDirective);
- return _variantField_19 ??= 0;
- }
-
- set uriBasedDirective_uriElement(int value) {
- assert(kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.partDirective);
- assert(value == null || value >= 0);
- _variantField_19 = value;
- }
-
- @override
- LinkedNodeVariablesDeclarationBuilder get variableDeclaration_declaration {
- assert(kind == idl.LinkedNodeKind.variableDeclaration);
- return _variantField_32;
- }
-
- set variableDeclaration_declaration(
- LinkedNodeVariablesDeclarationBuilder value) {
- assert(kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_32 = value;
- }
-
- LinkedNodeBuilder.functionDeclaration({
- LinkedNodeTypeBuilder actualReturnType,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder functionDeclaration_functionExpression,
- LinkedNodeBuilder functionDeclaration_returnType,
- int codeLength,
- int codeOffset,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.functionDeclaration,
- _variantField_24 = actualReturnType,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = functionDeclaration_functionExpression,
- _variantField_7 = functionDeclaration_returnType,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.functionExpression({
- LinkedNodeTypeBuilder actualReturnType,
- LinkedNodeBuilder functionExpression_body,
- LinkedNodeBuilder functionExpression_formalParameters,
- LinkedNodeBuilder functionExpression_typeParameters,
- }) : _kind = idl.LinkedNodeKind.functionExpression,
- _variantField_24 = actualReturnType,
- _variantField_6 = functionExpression_body,
- _variantField_7 = functionExpression_formalParameters,
- _variantField_8 = functionExpression_typeParameters;
-
- LinkedNodeBuilder.functionTypeAlias({
- LinkedNodeTypeBuilder actualReturnType,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder functionTypeAlias_formalParameters,
- LinkedNodeBuilder functionTypeAlias_returnType,
- LinkedNodeBuilder functionTypeAlias_typeParameters,
- bool typeAlias_hasSelfReference,
- int codeLength,
- int codeOffset,
- int nameOffset,
- bool simplyBoundable_isSimplyBounded,
- }) : _kind = idl.LinkedNodeKind.functionTypeAlias,
- _variantField_24 = actualReturnType,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = functionTypeAlias_formalParameters,
- _variantField_7 = functionTypeAlias_returnType,
- _variantField_8 = functionTypeAlias_typeParameters,
- _variantField_27 = typeAlias_hasSelfReference,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_31 = simplyBoundable_isSimplyBounded;
-
- LinkedNodeBuilder.genericFunctionType({
- LinkedNodeTypeBuilder actualReturnType,
- LinkedNodeBuilder genericFunctionType_typeParameters,
- LinkedNodeBuilder genericFunctionType_returnType,
- int genericFunctionType_id,
- LinkedNodeBuilder genericFunctionType_formalParameters,
- LinkedNodeTypeBuilder genericFunctionType_type,
- }) : _kind = idl.LinkedNodeKind.genericFunctionType,
- _variantField_24 = actualReturnType,
- _variantField_6 = genericFunctionType_typeParameters,
- _variantField_7 = genericFunctionType_returnType,
- _variantField_17 = genericFunctionType_id,
- _variantField_8 = genericFunctionType_formalParameters,
- _variantField_25 = genericFunctionType_type;
-
- LinkedNodeBuilder.methodDeclaration({
- LinkedNodeTypeBuilder actualReturnType,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder methodDeclaration_body,
- LinkedNodeBuilder methodDeclaration_formalParameters,
- LinkedNodeBuilder methodDeclaration_returnType,
- LinkedNodeBuilder methodDeclaration_typeParameters,
- int codeLength,
- int codeOffset,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.methodDeclaration,
- _variantField_24 = actualReturnType,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = methodDeclaration_body,
- _variantField_7 = methodDeclaration_formalParameters,
- _variantField_8 = methodDeclaration_returnType,
- _variantField_9 = methodDeclaration_typeParameters,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.fieldFormalParameter({
- LinkedNodeTypeBuilder actualType,
- List<LinkedNodeBuilder> normalFormalParameter_metadata,
- LinkedNodeBuilder fieldFormalParameter_type,
- LinkedNodeBuilder fieldFormalParameter_typeParameters,
- LinkedNodeBuilder fieldFormalParameter_formalParameters,
- bool inheritsCovariant,
- int codeLength,
- int codeOffset,
- int nameOffset,
- LinkedNodeBuilder normalFormalParameter_comment,
- }) : _kind = idl.LinkedNodeKind.fieldFormalParameter,
- _variantField_24 = actualType,
- _variantField_4 = normalFormalParameter_metadata,
- _variantField_6 = fieldFormalParameter_type,
- _variantField_7 = fieldFormalParameter_typeParameters,
- _variantField_8 = fieldFormalParameter_formalParameters,
- _variantField_27 = inheritsCovariant,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_14 = normalFormalParameter_comment;
-
- LinkedNodeBuilder.functionTypedFormalParameter({
- LinkedNodeTypeBuilder actualType,
- List<LinkedNodeBuilder> normalFormalParameter_metadata,
- LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
- LinkedNodeBuilder functionTypedFormalParameter_returnType,
- LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
- bool inheritsCovariant,
- int codeLength,
- int codeOffset,
- int nameOffset,
- LinkedNodeBuilder normalFormalParameter_comment,
- }) : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
- _variantField_24 = actualType,
- _variantField_4 = normalFormalParameter_metadata,
- _variantField_6 = functionTypedFormalParameter_formalParameters,
- _variantField_7 = functionTypedFormalParameter_returnType,
- _variantField_8 = functionTypedFormalParameter_typeParameters,
- _variantField_27 = inheritsCovariant,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_14 = normalFormalParameter_comment;
-
- LinkedNodeBuilder.simpleFormalParameter({
- LinkedNodeTypeBuilder actualType,
- List<LinkedNodeBuilder> normalFormalParameter_metadata,
- LinkedNodeBuilder simpleFormalParameter_type,
- bool inheritsCovariant,
- int codeLength,
- int codeOffset,
- int nameOffset,
- LinkedNodeBuilder normalFormalParameter_comment,
- TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
- }) : _kind = idl.LinkedNodeKind.simpleFormalParameter,
- _variantField_24 = actualType,
- _variantField_4 = normalFormalParameter_metadata,
- _variantField_6 = simpleFormalParameter_type,
- _variantField_27 = inheritsCovariant,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_14 = normalFormalParameter_comment,
- _variantField_35 = topLevelTypeInferenceError;
-
- LinkedNodeBuilder.variableDeclaration({
- LinkedNodeTypeBuilder actualType,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder variableDeclaration_initializer,
- bool inheritsCovariant,
- int codeLength,
- int codeOffset,
- int nameOffset,
- TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
- LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
- }) : _kind = idl.LinkedNodeKind.variableDeclaration,
- _variantField_24 = actualType,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = variableDeclaration_initializer,
- _variantField_27 = inheritsCovariant,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_35 = topLevelTypeInferenceError,
- _variantField_32 = variableDeclaration_declaration;
-
- LinkedNodeBuilder.binaryExpression({
- LinkedNodeTypeBuilder binaryExpression_invokeType,
- LinkedNodeBuilder binaryExpression_leftOperand,
- LinkedNodeBuilder binaryExpression_rightOperand,
- LinkedNodeTypeBuilder binaryExpression_elementType,
- int binaryExpression_element,
- idl.UnlinkedTokenType binaryExpression_operator,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.binaryExpression,
- _variantField_24 = binaryExpression_invokeType,
- _variantField_6 = binaryExpression_leftOperand,
- _variantField_7 = binaryExpression_rightOperand,
- _variantField_23 = binaryExpression_elementType,
- _variantField_15 = binaryExpression_element,
- _variantField_28 = binaryExpression_operator,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.functionExpressionInvocation({
- LinkedNodeTypeBuilder invocationExpression_invokeType,
- LinkedNodeBuilder functionExpressionInvocation_function,
- LinkedNodeBuilder invocationExpression_typeArguments,
- LinkedNodeTypeBuilder expression_type,
- LinkedNodeBuilder invocationExpression_arguments,
- }) : _kind = idl.LinkedNodeKind.functionExpressionInvocation,
- _variantField_24 = invocationExpression_invokeType,
- _variantField_6 = functionExpressionInvocation_function,
- _variantField_12 = invocationExpression_typeArguments,
- _variantField_25 = expression_type,
- _variantField_14 = invocationExpression_arguments;
-
- LinkedNodeBuilder.methodInvocation({
- LinkedNodeTypeBuilder invocationExpression_invokeType,
- LinkedNodeBuilder methodInvocation_methodName,
- LinkedNodeBuilder methodInvocation_target,
- LinkedNodeBuilder invocationExpression_typeArguments,
- LinkedNodeTypeBuilder expression_type,
- LinkedNodeBuilder invocationExpression_arguments,
- }) : _kind = idl.LinkedNodeKind.methodInvocation,
- _variantField_24 = invocationExpression_invokeType,
- _variantField_6 = methodInvocation_methodName,
- _variantField_7 = methodInvocation_target,
- _variantField_12 = invocationExpression_typeArguments,
- _variantField_25 = expression_type,
- _variantField_14 = invocationExpression_arguments;
-
LinkedNodeBuilder.adjacentStrings({
List<LinkedNodeBuilder> adjacentStrings_strings,
}) : _kind = idl.LinkedNodeKind.adjacentStrings,
_variantField_2 = adjacentStrings_strings;
- LinkedNodeBuilder.argumentList({
- List<LinkedNodeBuilder> argumentList_arguments,
- }) : _kind = idl.LinkedNodeKind.argumentList,
- _variantField_2 = argumentList_arguments;
-
- LinkedNodeBuilder.block({
- List<LinkedNodeBuilder> block_statements,
- }) : _kind = idl.LinkedNodeKind.block,
- _variantField_2 = block_statements;
-
- LinkedNodeBuilder.cascadeExpression({
- List<LinkedNodeBuilder> cascadeExpression_sections,
- LinkedNodeBuilder cascadeExpression_target,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.cascadeExpression,
- _variantField_2 = cascadeExpression_sections,
- _variantField_6 = cascadeExpression_target,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.comment({
- List<LinkedNodeBuilder> comment_references,
- List<String> comment_tokens,
- idl.LinkedNodeCommentType comment_type,
- }) : _kind = idl.LinkedNodeKind.comment,
- _variantField_2 = comment_references,
- _variantField_36 = comment_tokens,
- _variantField_29 = comment_type;
-
- LinkedNodeBuilder.compilationUnit({
- List<LinkedNodeBuilder> compilationUnit_declarations,
- LinkedNodeBuilder compilationUnit_scriptTag,
- int codeLength,
- int codeOffset,
- List<LinkedNodeBuilder> compilationUnit_directives,
- }) : _kind = idl.LinkedNodeKind.compilationUnit,
- _variantField_2 = compilationUnit_declarations,
- _variantField_6 = compilationUnit_scriptTag,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_3 = compilationUnit_directives;
-
- LinkedNodeBuilder.constructorDeclaration({
- List<LinkedNodeBuilder> constructorDeclaration_initializers,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder constructorDeclaration_body,
- LinkedNodeBuilder constructorDeclaration_parameters,
- LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
- int codeLength,
- int codeOffset,
- LinkedNodeBuilder constructorDeclaration_returnType,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.constructorDeclaration,
- _variantField_2 = constructorDeclaration_initializers,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = constructorDeclaration_body,
- _variantField_8 = constructorDeclaration_parameters,
- _variantField_9 = constructorDeclaration_redirectedConstructor,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_10 = constructorDeclaration_returnType,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.dottedName({
- List<LinkedNodeBuilder> dottedName_components,
- }) : _kind = idl.LinkedNodeKind.dottedName,
- _variantField_2 = dottedName_components;
-
- LinkedNodeBuilder.enumDeclaration({
- List<LinkedNodeBuilder> enumDeclaration_constants,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- int codeLength,
- int codeOffset,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.enumDeclaration,
- _variantField_2 = enumDeclaration_constants,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.formalParameterList({
- List<LinkedNodeBuilder> formalParameterList_parameters,
- }) : _kind = idl.LinkedNodeKind.formalParameterList,
- _variantField_2 = formalParameterList_parameters;
-
- LinkedNodeBuilder.implementsClause({
- List<LinkedNodeBuilder> implementsClause_interfaces,
- }) : _kind = idl.LinkedNodeKind.implementsClause,
- _variantField_2 = implementsClause_interfaces;
-
- LinkedNodeBuilder.instanceCreationExpression({
- List<LinkedNodeBuilder> instanceCreationExpression_arguments,
- LinkedNodeBuilder instanceCreationExpression_constructorName,
- LinkedNodeBuilder instanceCreationExpression_typeArguments,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.instanceCreationExpression,
- _variantField_2 = instanceCreationExpression_arguments,
- _variantField_7 = instanceCreationExpression_constructorName,
- _variantField_8 = instanceCreationExpression_typeArguments,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.labeledStatement({
- List<LinkedNodeBuilder> labeledStatement_labels,
- LinkedNodeBuilder labeledStatement_statement,
- }) : _kind = idl.LinkedNodeKind.labeledStatement,
- _variantField_2 = labeledStatement_labels,
- _variantField_6 = labeledStatement_statement;
-
- LinkedNodeBuilder.libraryIdentifier({
- List<LinkedNodeBuilder> libraryIdentifier_components,
- }) : _kind = idl.LinkedNodeKind.libraryIdentifier,
- _variantField_2 = libraryIdentifier_components;
-
- LinkedNodeBuilder.exportDirective({
- List<LinkedNodeBuilder> namespaceDirective_combinators,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- List<LinkedNodeBuilder> namespaceDirective_configurations,
- int nameOffset,
- LinkedNodeBuilder uriBasedDirective_uri,
- String namespaceDirective_selectedUri,
- String uriBasedDirective_uriContent,
- int uriBasedDirective_uriElement,
- }) : _kind = idl.LinkedNodeKind.exportDirective,
- _variantField_2 = namespaceDirective_combinators,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_3 = namespaceDirective_configurations,
- _variantField_16 = nameOffset,
- _variantField_14 = uriBasedDirective_uri,
- _variantField_20 = namespaceDirective_selectedUri,
- _variantField_22 = uriBasedDirective_uriContent,
- _variantField_19 = uriBasedDirective_uriElement;
-
- LinkedNodeBuilder.importDirective({
- List<LinkedNodeBuilder> namespaceDirective_combinators,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- int importDirective_prefixOffset,
- List<LinkedNodeBuilder> namespaceDirective_configurations,
- String importDirective_prefix,
- int nameOffset,
- LinkedNodeBuilder uriBasedDirective_uri,
- String namespaceDirective_selectedUri,
- String uriBasedDirective_uriContent,
- int uriBasedDirective_uriElement,
- }) : _kind = idl.LinkedNodeKind.importDirective,
- _variantField_2 = namespaceDirective_combinators,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_15 = importDirective_prefixOffset,
- _variantField_3 = namespaceDirective_configurations,
- _variantField_1 = importDirective_prefix,
- _variantField_16 = nameOffset,
- _variantField_14 = uriBasedDirective_uri,
- _variantField_20 = namespaceDirective_selectedUri,
- _variantField_22 = uriBasedDirective_uriContent,
- _variantField_19 = uriBasedDirective_uriElement;
-
- LinkedNodeBuilder.onClause({
- List<LinkedNodeBuilder> onClause_superclassConstraints,
- }) : _kind = idl.LinkedNodeKind.onClause,
- _variantField_2 = onClause_superclassConstraints;
-
- LinkedNodeBuilder.stringInterpolation({
- List<LinkedNodeBuilder> stringInterpolation_elements,
- }) : _kind = idl.LinkedNodeKind.stringInterpolation,
- _variantField_2 = stringInterpolation_elements;
-
- LinkedNodeBuilder.switchStatement({
- List<LinkedNodeBuilder> switchStatement_members,
- LinkedNodeBuilder switchStatement_expression,
- }) : _kind = idl.LinkedNodeKind.switchStatement,
- _variantField_2 = switchStatement_members,
- _variantField_7 = switchStatement_expression;
-
- LinkedNodeBuilder.tryStatement({
- List<LinkedNodeBuilder> tryStatement_catchClauses,
- LinkedNodeBuilder tryStatement_body,
- LinkedNodeBuilder tryStatement_finallyBlock,
- }) : _kind = idl.LinkedNodeKind.tryStatement,
- _variantField_2 = tryStatement_catchClauses,
- _variantField_6 = tryStatement_body,
- _variantField_7 = tryStatement_finallyBlock;
-
- LinkedNodeBuilder.typeArgumentList({
- List<LinkedNodeBuilder> typeArgumentList_arguments,
- }) : _kind = idl.LinkedNodeKind.typeArgumentList,
- _variantField_2 = typeArgumentList_arguments;
-
- LinkedNodeBuilder.listLiteral({
- List<LinkedNodeBuilder> typedLiteral_typeArguments,
- List<LinkedNodeBuilder> listLiteral_elements,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.listLiteral,
- _variantField_2 = typedLiteral_typeArguments,
- _variantField_3 = listLiteral_elements,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.setOrMapLiteral({
- List<LinkedNodeBuilder> typedLiteral_typeArguments,
- List<LinkedNodeBuilder> setOrMapLiteral_elements,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.setOrMapLiteral,
- _variantField_2 = typedLiteral_typeArguments,
- _variantField_3 = setOrMapLiteral_elements,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.typeName({
- List<LinkedNodeBuilder> typeName_typeArguments,
- LinkedNodeBuilder typeName_name,
- LinkedNodeTypeBuilder typeName_type,
- }) : _kind = idl.LinkedNodeKind.typeName,
- _variantField_2 = typeName_typeArguments,
- _variantField_6 = typeName_name,
- _variantField_23 = typeName_type;
-
- LinkedNodeBuilder.typeParameterList({
- List<LinkedNodeBuilder> typeParameterList_typeParameters,
- }) : _kind = idl.LinkedNodeKind.typeParameterList,
- _variantField_2 = typeParameterList_typeParameters;
-
- LinkedNodeBuilder.variableDeclarationList({
- List<LinkedNodeBuilder> variableDeclarationList_variables,
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder variableDeclarationList_type,
- }) : _kind = idl.LinkedNodeKind.variableDeclarationList,
- _variantField_2 = variableDeclarationList_variables,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = variableDeclarationList_type;
-
- LinkedNodeBuilder.withClause({
- List<LinkedNodeBuilder> withClause_mixinTypes,
- }) : _kind = idl.LinkedNodeKind.withClause,
- _variantField_2 = withClause_mixinTypes;
-
- LinkedNodeBuilder.classDeclaration({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder classDeclaration_extendsClause,
- LinkedNodeBuilder classDeclaration_withClause,
- LinkedNodeBuilder classDeclaration_nativeClause,
- bool classDeclaration_isDartObject,
- LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
- List<LinkedNodeBuilder> classOrMixinDeclaration_members,
- LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
- int codeLength,
- int codeOffset,
- int nameOffset,
- bool simplyBoundable_isSimplyBounded,
- }) : _kind = idl.LinkedNodeKind.classDeclaration,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = classDeclaration_extendsClause,
- _variantField_7 = classDeclaration_withClause,
- _variantField_8 = classDeclaration_nativeClause,
- _variantField_27 = classDeclaration_isDartObject,
- _variantField_12 = classOrMixinDeclaration_implementsClause,
- _variantField_5 = classOrMixinDeclaration_members,
- _variantField_13 = classOrMixinDeclaration_typeParameters,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_31 = simplyBoundable_isSimplyBounded;
-
- LinkedNodeBuilder.classTypeAlias({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder classTypeAlias_typeParameters,
- LinkedNodeBuilder classTypeAlias_superclass,
- LinkedNodeBuilder classTypeAlias_withClause,
- LinkedNodeBuilder classTypeAlias_implementsClause,
- int codeLength,
- int codeOffset,
- int nameOffset,
- bool simplyBoundable_isSimplyBounded,
- }) : _kind = idl.LinkedNodeKind.classTypeAlias,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = classTypeAlias_typeParameters,
- _variantField_7 = classTypeAlias_superclass,
- _variantField_8 = classTypeAlias_withClause,
- _variantField_9 = classTypeAlias_implementsClause,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_31 = simplyBoundable_isSimplyBounded;
-
- LinkedNodeBuilder.declaredIdentifier({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder declaredIdentifier_identifier,
- LinkedNodeBuilder declaredIdentifier_type,
- }) : _kind = idl.LinkedNodeKind.declaredIdentifier,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = declaredIdentifier_identifier,
- _variantField_7 = declaredIdentifier_type;
-
- LinkedNodeBuilder.enumConstantDeclaration({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.fieldDeclaration({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder fieldDeclaration_fields,
- }) : _kind = idl.LinkedNodeKind.fieldDeclaration,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = fieldDeclaration_fields;
-
- LinkedNodeBuilder.genericTypeAlias({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder genericTypeAlias_typeParameters,
- LinkedNodeBuilder genericTypeAlias_functionType,
- bool typeAlias_hasSelfReference,
- int codeLength,
- int codeOffset,
- int nameOffset,
- bool simplyBoundable_isSimplyBounded,
- }) : _kind = idl.LinkedNodeKind.genericTypeAlias,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = genericTypeAlias_typeParameters,
- _variantField_7 = genericTypeAlias_functionType,
- _variantField_27 = typeAlias_hasSelfReference,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset,
- _variantField_31 = simplyBoundable_isSimplyBounded;
-
- LinkedNodeBuilder.libraryDirective({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder libraryDirective_name,
- }) : _kind = idl.LinkedNodeKind.libraryDirective,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = libraryDirective_name;
-
- LinkedNodeBuilder.mixinDeclaration({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder mixinDeclaration_onClause,
- LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
- List<LinkedNodeBuilder> classOrMixinDeclaration_members,
- LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
- int codeLength,
- int codeOffset,
- List<String> mixinDeclaration_superInvokedNames,
- int nameOffset,
- bool simplyBoundable_isSimplyBounded,
- }) : _kind = idl.LinkedNodeKind.mixinDeclaration,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = mixinDeclaration_onClause,
- _variantField_12 = classOrMixinDeclaration_implementsClause,
- _variantField_5 = classOrMixinDeclaration_members,
- _variantField_13 = classOrMixinDeclaration_typeParameters,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_36 = mixinDeclaration_superInvokedNames,
- _variantField_16 = nameOffset,
- _variantField_31 = simplyBoundable_isSimplyBounded;
-
- LinkedNodeBuilder.partDirective({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- int nameOffset,
- LinkedNodeBuilder uriBasedDirective_uri,
- String uriBasedDirective_uriContent,
- int uriBasedDirective_uriElement,
- }) : _kind = idl.LinkedNodeKind.partDirective,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_16 = nameOffset,
- _variantField_14 = uriBasedDirective_uri,
- _variantField_22 = uriBasedDirective_uriContent,
- _variantField_19 = uriBasedDirective_uriElement;
-
- LinkedNodeBuilder.partOfDirective({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder partOfDirective_libraryName,
- LinkedNodeBuilder partOfDirective_uri,
- }) : _kind = idl.LinkedNodeKind.partOfDirective,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = partOfDirective_libraryName,
- _variantField_7 = partOfDirective_uri;
-
- LinkedNodeBuilder.topLevelVariableDeclaration({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder topLevelVariableDeclaration_variableList,
- }) : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = topLevelVariableDeclaration_variableList;
-
- LinkedNodeBuilder.typeParameter({
- LinkedNodeBuilder annotatedNode_comment,
- List<LinkedNodeBuilder> annotatedNode_metadata,
- LinkedNodeBuilder typeParameter_bound,
- LinkedNodeTypeBuilder typeParameter_defaultType,
- int codeLength,
- int codeOffset,
- int nameOffset,
- }) : _kind = idl.LinkedNodeKind.typeParameter,
- _variantField_11 = annotatedNode_comment,
- _variantField_4 = annotatedNode_metadata,
- _variantField_6 = typeParameter_bound,
- _variantField_23 = typeParameter_defaultType,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
- _variantField_16 = nameOffset;
-
- LinkedNodeBuilder.switchCase({
- List<LinkedNodeBuilder> switchMember_statements,
- LinkedNodeBuilder switchCase_expression,
- List<LinkedNodeBuilder> switchMember_labels,
- }) : _kind = idl.LinkedNodeKind.switchCase,
- _variantField_4 = switchMember_statements,
- _variantField_6 = switchCase_expression,
- _variantField_3 = switchMember_labels;
-
- LinkedNodeBuilder.switchDefault({
- List<LinkedNodeBuilder> switchMember_statements,
- List<LinkedNodeBuilder> switchMember_labels,
- }) : _kind = idl.LinkedNodeKind.switchDefault,
- _variantField_4 = switchMember_statements,
- _variantField_3 = switchMember_labels;
-
LinkedNodeBuilder.annotation({
LinkedNodeBuilder annotation_arguments,
LinkedNodeBuilder annotation_constructorName,
@@ -8528,6 +7936,11 @@
_variantField_23 = annotation_elementType,
_variantField_8 = annotation_name;
+ LinkedNodeBuilder.argumentList({
+ List<LinkedNodeBuilder> argumentList_arguments,
+ }) : _kind = idl.LinkedNodeKind.argumentList,
+ _variantField_2 = argumentList_arguments;
+
LinkedNodeBuilder.asExpression({
LinkedNodeBuilder asExpression_expression,
LinkedNodeBuilder asExpression_type,
@@ -8573,16 +7986,52 @@
_variantField_6 = awaitExpression_expression,
_variantField_25 = expression_type;
+ LinkedNodeBuilder.binaryExpression({
+ LinkedNodeTypeBuilder binaryExpression_invokeType,
+ LinkedNodeBuilder binaryExpression_leftOperand,
+ LinkedNodeBuilder binaryExpression_rightOperand,
+ LinkedNodeTypeBuilder binaryExpression_elementType,
+ int binaryExpression_element,
+ idl.UnlinkedTokenType binaryExpression_operator,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.binaryExpression,
+ _variantField_24 = binaryExpression_invokeType,
+ _variantField_6 = binaryExpression_leftOperand,
+ _variantField_7 = binaryExpression_rightOperand,
+ _variantField_23 = binaryExpression_elementType,
+ _variantField_15 = binaryExpression_element,
+ _variantField_28 = binaryExpression_operator,
+ _variantField_25 = expression_type;
+
+ LinkedNodeBuilder.block({
+ List<LinkedNodeBuilder> block_statements,
+ }) : _kind = idl.LinkedNodeKind.block,
+ _variantField_2 = block_statements;
+
LinkedNodeBuilder.blockFunctionBody({
LinkedNodeBuilder blockFunctionBody_block,
}) : _kind = idl.LinkedNodeKind.blockFunctionBody,
_variantField_6 = blockFunctionBody_block;
+ LinkedNodeBuilder.booleanLiteral({
+ bool booleanLiteral_value,
+ }) : _kind = idl.LinkedNodeKind.booleanLiteral,
+ _variantField_27 = booleanLiteral_value;
+
LinkedNodeBuilder.breakStatement({
LinkedNodeBuilder breakStatement_label,
}) : _kind = idl.LinkedNodeKind.breakStatement,
_variantField_6 = breakStatement_label;
+ LinkedNodeBuilder.cascadeExpression({
+ List<LinkedNodeBuilder> cascadeExpression_sections,
+ LinkedNodeBuilder cascadeExpression_target,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.cascadeExpression,
+ _variantField_2 = cascadeExpression_sections,
+ _variantField_6 = cascadeExpression_target,
+ _variantField_25 = expression_type;
+
LinkedNodeBuilder.catchClause({
LinkedNodeBuilder catchClause_body,
LinkedNodeBuilder catchClause_exceptionParameter,
@@ -8594,11 +8043,85 @@
_variantField_8 = catchClause_exceptionType,
_variantField_9 = catchClause_stackTraceParameter;
+ LinkedNodeBuilder.classDeclaration({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder classDeclaration_extendsClause,
+ LinkedNodeBuilder classDeclaration_withClause,
+ LinkedNodeBuilder classDeclaration_nativeClause,
+ bool classDeclaration_isDartObject,
+ LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+ List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+ LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ bool simplyBoundable_isSimplyBounded,
+ }) : _kind = idl.LinkedNodeKind.classDeclaration,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = classDeclaration_extendsClause,
+ _variantField_7 = classDeclaration_withClause,
+ _variantField_8 = classDeclaration_nativeClause,
+ _variantField_27 = classDeclaration_isDartObject,
+ _variantField_12 = classOrMixinDeclaration_implementsClause,
+ _variantField_5 = classOrMixinDeclaration_members,
+ _variantField_13 = classOrMixinDeclaration_typeParameters,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name,
+ _variantField_31 = simplyBoundable_isSimplyBounded;
+
+ LinkedNodeBuilder.classTypeAlias({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder classTypeAlias_typeParameters,
+ LinkedNodeBuilder classTypeAlias_superclass,
+ LinkedNodeBuilder classTypeAlias_withClause,
+ LinkedNodeBuilder classTypeAlias_implementsClause,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ bool simplyBoundable_isSimplyBounded,
+ }) : _kind = idl.LinkedNodeKind.classTypeAlias,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = classTypeAlias_typeParameters,
+ _variantField_7 = classTypeAlias_superclass,
+ _variantField_8 = classTypeAlias_withClause,
+ _variantField_9 = classTypeAlias_implementsClause,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name,
+ _variantField_31 = simplyBoundable_isSimplyBounded;
+
+ LinkedNodeBuilder.comment({
+ List<LinkedNodeBuilder> comment_references,
+ List<String> comment_tokens,
+ idl.LinkedNodeCommentType comment_type,
+ }) : _kind = idl.LinkedNodeKind.comment,
+ _variantField_2 = comment_references,
+ _variantField_35 = comment_tokens,
+ _variantField_29 = comment_type;
+
LinkedNodeBuilder.commentReference({
LinkedNodeBuilder commentReference_identifier,
}) : _kind = idl.LinkedNodeKind.commentReference,
_variantField_6 = commentReference_identifier;
+ LinkedNodeBuilder.compilationUnit({
+ List<LinkedNodeBuilder> compilationUnit_declarations,
+ LinkedNodeBuilder compilationUnit_scriptTag,
+ int codeLength,
+ int codeOffset,
+ List<LinkedNodeBuilder> compilationUnit_directives,
+ }) : _kind = idl.LinkedNodeKind.compilationUnit,
+ _variantField_2 = compilationUnit_declarations,
+ _variantField_6 = compilationUnit_scriptTag,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_3 = compilationUnit_directives;
+
LinkedNodeBuilder.conditionalExpression({
LinkedNodeBuilder conditionalExpression_condition,
LinkedNodeBuilder conditionalExpression_elseExpression,
@@ -8619,6 +8142,31 @@
_variantField_7 = configuration_value,
_variantField_8 = configuration_uri;
+ LinkedNodeBuilder.constructorDeclaration({
+ List<LinkedNodeBuilder> constructorDeclaration_initializers,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder constructorDeclaration_body,
+ LinkedNodeBuilder constructorDeclaration_name,
+ LinkedNodeBuilder constructorDeclaration_parameters,
+ LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
+ int codeLength,
+ int codeOffset,
+ int constructorDeclaration_periodOffset,
+ LinkedNodeBuilder constructorDeclaration_returnType,
+ }) : _kind = idl.LinkedNodeKind.constructorDeclaration,
+ _variantField_2 = constructorDeclaration_initializers,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = constructorDeclaration_body,
+ _variantField_7 = constructorDeclaration_name,
+ _variantField_8 = constructorDeclaration_parameters,
+ _variantField_9 = constructorDeclaration_redirectedConstructor,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_19 = constructorDeclaration_periodOffset,
+ _variantField_10 = constructorDeclaration_returnType;
+
LinkedNodeBuilder.constructorFieldInitializer({
LinkedNodeBuilder constructorFieldInitializer_expression,
LinkedNodeBuilder constructorFieldInitializer_fieldName,
@@ -8642,6 +8190,17 @@
}) : _kind = idl.LinkedNodeKind.continueStatement,
_variantField_6 = continueStatement_label;
+ LinkedNodeBuilder.declaredIdentifier({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder declaredIdentifier_identifier,
+ LinkedNodeBuilder declaredIdentifier_type,
+ }) : _kind = idl.LinkedNodeKind.declaredIdentifier,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = declaredIdentifier_identifier,
+ _variantField_7 = declaredIdentifier_type;
+
LinkedNodeBuilder.defaultFormalParameter({
LinkedNodeBuilder defaultFormalParameter_defaultValue,
LinkedNodeBuilder defaultFormalParameter_parameter,
@@ -8651,8 +8210,8 @@
}) : _kind = idl.LinkedNodeKind.defaultFormalParameter,
_variantField_6 = defaultFormalParameter_defaultValue,
_variantField_7 = defaultFormalParameter_parameter,
- _variantField_34 = codeLength,
- _variantField_33 = codeOffset,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
_variantField_26 = defaultFormalParameter_kind;
LinkedNodeBuilder.doStatement({
@@ -8662,6 +8221,71 @@
_variantField_6 = doStatement_body,
_variantField_7 = doStatement_condition;
+ LinkedNodeBuilder.dottedName({
+ List<LinkedNodeBuilder> dottedName_components,
+ }) : _kind = idl.LinkedNodeKind.dottedName,
+ _variantField_2 = dottedName_components;
+
+ LinkedNodeBuilder.doubleLiteral({
+ double doubleLiteral_value,
+ }) : _kind = idl.LinkedNodeKind.doubleLiteral,
+ _variantField_21 = doubleLiteral_value;
+
+ LinkedNodeBuilder.emptyFunctionBody({
+ int emptyFunctionBody_fake,
+ }) : _kind = idl.LinkedNodeKind.emptyFunctionBody,
+ _variantField_15 = emptyFunctionBody_fake;
+
+ LinkedNodeBuilder.emptyStatement({
+ int emptyStatement_fake,
+ }) : _kind = idl.LinkedNodeKind.emptyStatement,
+ _variantField_15 = emptyStatement_fake;
+
+ LinkedNodeBuilder.enumConstantDeclaration({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder enumConstantDeclaration_name,
+ }) : _kind = idl.LinkedNodeKind.enumConstantDeclaration,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = enumConstantDeclaration_name;
+
+ LinkedNodeBuilder.enumDeclaration({
+ List<LinkedNodeBuilder> enumDeclaration_constants,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ }) : _kind = idl.LinkedNodeKind.enumDeclaration,
+ _variantField_2 = enumDeclaration_constants,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name;
+
+ LinkedNodeBuilder.exportDirective({
+ List<LinkedNodeBuilder> namespaceDirective_combinators,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ int directive_keywordOffset,
+ List<LinkedNodeBuilder> namespaceDirective_configurations,
+ int uriBasedDirective_uriElement,
+ LinkedNodeBuilder uriBasedDirective_uri,
+ String namespaceDirective_selectedUri,
+ String uriBasedDirective_uriContent,
+ }) : _kind = idl.LinkedNodeKind.exportDirective,
+ _variantField_2 = namespaceDirective_combinators,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_17 = directive_keywordOffset,
+ _variantField_3 = namespaceDirective_configurations,
+ _variantField_19 = uriBasedDirective_uriElement,
+ _variantField_14 = uriBasedDirective_uri,
+ _variantField_20 = namespaceDirective_selectedUri,
+ _variantField_22 = uriBasedDirective_uriContent;
+
LinkedNodeBuilder.expressionFunctionBody({
LinkedNodeBuilder expressionFunctionBody_expression,
}) : _kind = idl.LinkedNodeKind.expressionFunctionBody,
@@ -8677,6 +8301,38 @@
}) : _kind = idl.LinkedNodeKind.extendsClause,
_variantField_6 = extendsClause_superclass;
+ LinkedNodeBuilder.fieldDeclaration({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder fieldDeclaration_fields,
+ }) : _kind = idl.LinkedNodeKind.fieldDeclaration,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = fieldDeclaration_fields;
+
+ LinkedNodeBuilder.fieldFormalParameter({
+ LinkedNodeTypeBuilder actualType,
+ List<LinkedNodeBuilder> normalFormalParameter_metadata,
+ LinkedNodeBuilder fieldFormalParameter_type,
+ LinkedNodeBuilder fieldFormalParameter_typeParameters,
+ LinkedNodeBuilder fieldFormalParameter_formalParameters,
+ bool inheritsCovariant,
+ LinkedNodeBuilder normalFormalParameter_identifier,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder normalFormalParameter_comment,
+ }) : _kind = idl.LinkedNodeKind.fieldFormalParameter,
+ _variantField_24 = actualType,
+ _variantField_4 = normalFormalParameter_metadata,
+ _variantField_6 = fieldFormalParameter_type,
+ _variantField_7 = fieldFormalParameter_typeParameters,
+ _variantField_8 = fieldFormalParameter_formalParameters,
+ _variantField_27 = inheritsCovariant,
+ _variantField_9 = normalFormalParameter_identifier,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_14 = normalFormalParameter_comment;
+
LinkedNodeBuilder.forEachPartsWithDeclaration({
LinkedNodeBuilder forEachParts_iterable,
LinkedNodeBuilder forEachPartsWithDeclaration_loopVariable,
@@ -8698,13 +8354,6 @@
_variantField_6 = forMixin_forLoopParts,
_variantField_7 = forElement_body;
- LinkedNodeBuilder.forStatement({
- LinkedNodeBuilder forMixin_forLoopParts,
- LinkedNodeBuilder forStatement_body,
- }) : _kind = idl.LinkedNodeKind.forStatement,
- _variantField_6 = forMixin_forLoopParts,
- _variantField_7 = forStatement_body;
-
LinkedNodeBuilder.forPartsWithDeclarations({
LinkedNodeBuilder forParts_condition,
LinkedNodeBuilder forPartsWithDeclarations_variables,
@@ -8723,11 +8372,155 @@
_variantField_7 = forPartsWithExpression_initialization,
_variantField_5 = forParts_updaters;
+ LinkedNodeBuilder.forStatement({
+ LinkedNodeBuilder forMixin_forLoopParts,
+ LinkedNodeBuilder forStatement_body,
+ }) : _kind = idl.LinkedNodeKind.forStatement,
+ _variantField_6 = forMixin_forLoopParts,
+ _variantField_7 = forStatement_body;
+
+ LinkedNodeBuilder.formalParameterList({
+ List<LinkedNodeBuilder> formalParameterList_parameters,
+ }) : _kind = idl.LinkedNodeKind.formalParameterList,
+ _variantField_2 = formalParameterList_parameters;
+
+ LinkedNodeBuilder.functionDeclaration({
+ LinkedNodeTypeBuilder actualReturnType,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder functionDeclaration_functionExpression,
+ LinkedNodeBuilder functionDeclaration_returnType,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ }) : _kind = idl.LinkedNodeKind.functionDeclaration,
+ _variantField_24 = actualReturnType,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = functionDeclaration_functionExpression,
+ _variantField_7 = functionDeclaration_returnType,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name;
+
LinkedNodeBuilder.functionDeclarationStatement({
LinkedNodeBuilder functionDeclarationStatement_functionDeclaration,
}) : _kind = idl.LinkedNodeKind.functionDeclarationStatement,
_variantField_6 = functionDeclarationStatement_functionDeclaration;
+ LinkedNodeBuilder.functionExpression({
+ LinkedNodeTypeBuilder actualReturnType,
+ LinkedNodeBuilder functionExpression_body,
+ LinkedNodeBuilder functionExpression_formalParameters,
+ LinkedNodeBuilder functionExpression_typeParameters,
+ }) : _kind = idl.LinkedNodeKind.functionExpression,
+ _variantField_24 = actualReturnType,
+ _variantField_6 = functionExpression_body,
+ _variantField_7 = functionExpression_formalParameters,
+ _variantField_8 = functionExpression_typeParameters;
+
+ LinkedNodeBuilder.functionExpressionInvocation({
+ LinkedNodeTypeBuilder invocationExpression_invokeType,
+ LinkedNodeBuilder functionExpressionInvocation_function,
+ LinkedNodeBuilder invocationExpression_typeArguments,
+ LinkedNodeTypeBuilder expression_type,
+ LinkedNodeBuilder invocationExpression_arguments,
+ }) : _kind = idl.LinkedNodeKind.functionExpressionInvocation,
+ _variantField_24 = invocationExpression_invokeType,
+ _variantField_6 = functionExpressionInvocation_function,
+ _variantField_12 = invocationExpression_typeArguments,
+ _variantField_25 = expression_type,
+ _variantField_14 = invocationExpression_arguments;
+
+ LinkedNodeBuilder.functionTypeAlias({
+ LinkedNodeTypeBuilder actualReturnType,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder functionTypeAlias_formalParameters,
+ LinkedNodeBuilder functionTypeAlias_returnType,
+ LinkedNodeBuilder functionTypeAlias_typeParameters,
+ bool typeAlias_hasSelfReference,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ bool simplyBoundable_isSimplyBounded,
+ }) : _kind = idl.LinkedNodeKind.functionTypeAlias,
+ _variantField_24 = actualReturnType,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = functionTypeAlias_formalParameters,
+ _variantField_7 = functionTypeAlias_returnType,
+ _variantField_8 = functionTypeAlias_typeParameters,
+ _variantField_27 = typeAlias_hasSelfReference,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name,
+ _variantField_31 = simplyBoundable_isSimplyBounded;
+
+ LinkedNodeBuilder.functionTypedFormalParameter({
+ LinkedNodeTypeBuilder actualType,
+ List<LinkedNodeBuilder> normalFormalParameter_metadata,
+ LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
+ LinkedNodeBuilder functionTypedFormalParameter_returnType,
+ LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
+ bool inheritsCovariant,
+ LinkedNodeBuilder normalFormalParameter_identifier,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder normalFormalParameter_comment,
+ }) : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
+ _variantField_24 = actualType,
+ _variantField_4 = normalFormalParameter_metadata,
+ _variantField_6 = functionTypedFormalParameter_formalParameters,
+ _variantField_7 = functionTypedFormalParameter_returnType,
+ _variantField_8 = functionTypedFormalParameter_typeParameters,
+ _variantField_27 = inheritsCovariant,
+ _variantField_9 = normalFormalParameter_identifier,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_14 = normalFormalParameter_comment;
+
+ LinkedNodeBuilder.genericFunctionType({
+ LinkedNodeTypeBuilder actualReturnType,
+ LinkedNodeBuilder genericFunctionType_typeParameters,
+ LinkedNodeBuilder genericFunctionType_returnType,
+ int genericFunctionType_id,
+ LinkedNodeBuilder genericFunctionType_formalParameters,
+ LinkedNodeTypeBuilder genericFunctionType_type,
+ }) : _kind = idl.LinkedNodeKind.genericFunctionType,
+ _variantField_24 = actualReturnType,
+ _variantField_6 = genericFunctionType_typeParameters,
+ _variantField_7 = genericFunctionType_returnType,
+ _variantField_17 = genericFunctionType_id,
+ _variantField_8 = genericFunctionType_formalParameters,
+ _variantField_25 = genericFunctionType_type;
+
+ LinkedNodeBuilder.genericTypeAlias({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder genericTypeAlias_typeParameters,
+ LinkedNodeBuilder genericTypeAlias_functionType,
+ bool typeAlias_hasSelfReference,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ bool simplyBoundable_isSimplyBounded,
+ }) : _kind = idl.LinkedNodeKind.genericTypeAlias,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = genericTypeAlias_typeParameters,
+ _variantField_7 = genericTypeAlias_functionType,
+ _variantField_27 = typeAlias_hasSelfReference,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name,
+ _variantField_31 = simplyBoundable_isSimplyBounded;
+
+ LinkedNodeBuilder.hideCombinator({
+ List<String> names,
+ }) : _kind = idl.LinkedNodeKind.hideCombinator,
+ _variantField_36 = names;
+
LinkedNodeBuilder.ifElement({
LinkedNodeBuilder ifMixin_condition,
LinkedNodeBuilder ifElement_thenElement,
@@ -8746,6 +8539,36 @@
_variantField_7 = ifStatement_elseStatement,
_variantField_8 = ifStatement_thenStatement;
+ LinkedNodeBuilder.implementsClause({
+ List<LinkedNodeBuilder> implementsClause_interfaces,
+ }) : _kind = idl.LinkedNodeKind.implementsClause,
+ _variantField_2 = implementsClause_interfaces;
+
+ LinkedNodeBuilder.importDirective({
+ List<LinkedNodeBuilder> namespaceDirective_combinators,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ int directive_keywordOffset,
+ int importDirective_prefixOffset,
+ List<LinkedNodeBuilder> namespaceDirective_configurations,
+ int uriBasedDirective_uriElement,
+ String importDirective_prefix,
+ LinkedNodeBuilder uriBasedDirective_uri,
+ String namespaceDirective_selectedUri,
+ String uriBasedDirective_uriContent,
+ }) : _kind = idl.LinkedNodeKind.importDirective,
+ _variantField_2 = namespaceDirective_combinators,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_17 = directive_keywordOffset,
+ _variantField_15 = importDirective_prefixOffset,
+ _variantField_3 = namespaceDirective_configurations,
+ _variantField_19 = uriBasedDirective_uriElement,
+ _variantField_1 = importDirective_prefix,
+ _variantField_14 = uriBasedDirective_uri,
+ _variantField_20 = namespaceDirective_selectedUri,
+ _variantField_22 = uriBasedDirective_uriContent;
+
LinkedNodeBuilder.indexExpression({
LinkedNodeBuilder indexExpression_index,
LinkedNodeBuilder indexExpression_target,
@@ -8759,11 +8582,32 @@
_variantField_15 = indexExpression_element,
_variantField_25 = expression_type;
+ LinkedNodeBuilder.instanceCreationExpression({
+ List<LinkedNodeBuilder> instanceCreationExpression_arguments,
+ LinkedNodeBuilder instanceCreationExpression_constructorName,
+ LinkedNodeBuilder instanceCreationExpression_typeArguments,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.instanceCreationExpression,
+ _variantField_2 = instanceCreationExpression_arguments,
+ _variantField_7 = instanceCreationExpression_constructorName,
+ _variantField_8 = instanceCreationExpression_typeArguments,
+ _variantField_25 = expression_type;
+
+ LinkedNodeBuilder.integerLiteral({
+ int integerLiteral_value,
+ }) : _kind = idl.LinkedNodeKind.integerLiteral,
+ _variantField_16 = integerLiteral_value;
+
LinkedNodeBuilder.interpolationExpression({
LinkedNodeBuilder interpolationExpression_expression,
}) : _kind = idl.LinkedNodeKind.interpolationExpression,
_variantField_6 = interpolationExpression_expression;
+ LinkedNodeBuilder.interpolationString({
+ String interpolationString_value,
+ }) : _kind = idl.LinkedNodeKind.interpolationString,
+ _variantField_30 = interpolationString_value;
+
LinkedNodeBuilder.isExpression({
LinkedNodeBuilder isExpression_expression,
LinkedNodeBuilder isExpression_type,
@@ -8776,6 +8620,38 @@
}) : _kind = idl.LinkedNodeKind.label,
_variantField_6 = label_label;
+ LinkedNodeBuilder.labeledStatement({
+ List<LinkedNodeBuilder> labeledStatement_labels,
+ LinkedNodeBuilder labeledStatement_statement,
+ }) : _kind = idl.LinkedNodeKind.labeledStatement,
+ _variantField_2 = labeledStatement_labels,
+ _variantField_6 = labeledStatement_statement;
+
+ LinkedNodeBuilder.libraryDirective({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder libraryDirective_name,
+ int directive_keywordOffset,
+ }) : _kind = idl.LinkedNodeKind.libraryDirective,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = libraryDirective_name,
+ _variantField_17 = directive_keywordOffset;
+
+ LinkedNodeBuilder.libraryIdentifier({
+ List<LinkedNodeBuilder> libraryIdentifier_components,
+ }) : _kind = idl.LinkedNodeKind.libraryIdentifier,
+ _variantField_2 = libraryIdentifier_components;
+
+ LinkedNodeBuilder.listLiteral({
+ List<LinkedNodeBuilder> typedLiteral_typeArguments,
+ List<LinkedNodeBuilder> listLiteral_elements,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.listLiteral,
+ _variantField_2 = typedLiteral_typeArguments,
+ _variantField_3 = listLiteral_elements,
+ _variantField_25 = expression_type;
+
LinkedNodeBuilder.mapLiteralEntry({
LinkedNodeBuilder mapLiteralEntry_key,
LinkedNodeBuilder mapLiteralEntry_value,
@@ -8783,6 +8659,69 @@
_variantField_6 = mapLiteralEntry_key,
_variantField_7 = mapLiteralEntry_value;
+ LinkedNodeBuilder.methodDeclaration({
+ LinkedNodeTypeBuilder actualReturnType,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder methodDeclaration_body,
+ LinkedNodeBuilder methodDeclaration_formalParameters,
+ LinkedNodeBuilder methodDeclaration_returnType,
+ LinkedNodeBuilder methodDeclaration_typeParameters,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder methodDeclaration_name,
+ }) : _kind = idl.LinkedNodeKind.methodDeclaration,
+ _variantField_24 = actualReturnType,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = methodDeclaration_body,
+ _variantField_7 = methodDeclaration_formalParameters,
+ _variantField_8 = methodDeclaration_returnType,
+ _variantField_9 = methodDeclaration_typeParameters,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = methodDeclaration_name;
+
+ LinkedNodeBuilder.methodInvocation({
+ LinkedNodeTypeBuilder invocationExpression_invokeType,
+ LinkedNodeBuilder methodInvocation_methodName,
+ LinkedNodeBuilder methodInvocation_target,
+ LinkedNodeBuilder invocationExpression_typeArguments,
+ LinkedNodeTypeBuilder expression_type,
+ LinkedNodeBuilder invocationExpression_arguments,
+ }) : _kind = idl.LinkedNodeKind.methodInvocation,
+ _variantField_24 = invocationExpression_invokeType,
+ _variantField_6 = methodInvocation_methodName,
+ _variantField_7 = methodInvocation_target,
+ _variantField_12 = invocationExpression_typeArguments,
+ _variantField_25 = expression_type,
+ _variantField_14 = invocationExpression_arguments;
+
+ LinkedNodeBuilder.mixinDeclaration({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder mixinDeclaration_onClause,
+ LinkedNodeBuilder classOrMixinDeclaration_implementsClause,
+ List<LinkedNodeBuilder> classOrMixinDeclaration_members,
+ LinkedNodeBuilder classOrMixinDeclaration_typeParameters,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder namedCompilationUnitMember_name,
+ List<String> mixinDeclaration_superInvokedNames,
+ bool simplyBoundable_isSimplyBounded,
+ }) : _kind = idl.LinkedNodeKind.mixinDeclaration,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = mixinDeclaration_onClause,
+ _variantField_12 = classOrMixinDeclaration_implementsClause,
+ _variantField_5 = classOrMixinDeclaration_members,
+ _variantField_13 = classOrMixinDeclaration_typeParameters,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_10 = namedCompilationUnitMember_name,
+ _variantField_36 = mixinDeclaration_superInvokedNames,
+ _variantField_31 = simplyBoundable_isSimplyBounded;
+
LinkedNodeBuilder.namedExpression({
LinkedNodeBuilder namedExpression_expression,
LinkedNodeBuilder namedExpression_name,
@@ -8800,6 +8739,18 @@
}) : _kind = idl.LinkedNodeKind.nativeFunctionBody,
_variantField_6 = nativeFunctionBody_stringLiteral;
+ LinkedNodeBuilder.nullLiteral({
+ int nullLiteral_fake,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.nullLiteral,
+ _variantField_15 = nullLiteral_fake,
+ _variantField_25 = expression_type;
+
+ LinkedNodeBuilder.onClause({
+ List<LinkedNodeBuilder> onClause_superclassConstraints,
+ }) : _kind = idl.LinkedNodeKind.onClause,
+ _variantField_2 = onClause_superclassConstraints;
+
LinkedNodeBuilder.parenthesizedExpression({
LinkedNodeBuilder parenthesizedExpression_expression,
LinkedNodeTypeBuilder expression_type,
@@ -8807,6 +8758,34 @@
_variantField_6 = parenthesizedExpression_expression,
_variantField_25 = expression_type;
+ LinkedNodeBuilder.partDirective({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ int directive_keywordOffset,
+ int uriBasedDirective_uriElement,
+ LinkedNodeBuilder uriBasedDirective_uri,
+ String uriBasedDirective_uriContent,
+ }) : _kind = idl.LinkedNodeKind.partDirective,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_17 = directive_keywordOffset,
+ _variantField_19 = uriBasedDirective_uriElement,
+ _variantField_14 = uriBasedDirective_uri,
+ _variantField_22 = uriBasedDirective_uriContent;
+
+ LinkedNodeBuilder.partOfDirective({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder partOfDirective_libraryName,
+ LinkedNodeBuilder partOfDirective_uri,
+ int directive_keywordOffset,
+ }) : _kind = idl.LinkedNodeKind.partOfDirective,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = partOfDirective_libraryName,
+ _variantField_7 = partOfDirective_uri,
+ _variantField_17 = directive_keywordOffset;
+
LinkedNodeBuilder.postfixExpression({
LinkedNodeBuilder postfixExpression_operand,
LinkedNodeTypeBuilder postfixExpression_elementType,
@@ -8820,15 +8799,6 @@
_variantField_28 = postfixExpression_operator,
_variantField_25 = expression_type;
- LinkedNodeBuilder.prefixedIdentifier({
- LinkedNodeBuilder prefixedIdentifier_identifier,
- LinkedNodeBuilder prefixedIdentifier_prefix,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.prefixedIdentifier,
- _variantField_6 = prefixedIdentifier_identifier,
- _variantField_7 = prefixedIdentifier_prefix,
- _variantField_25 = expression_type;
-
LinkedNodeBuilder.prefixExpression({
LinkedNodeBuilder prefixExpression_operand,
LinkedNodeTypeBuilder prefixExpression_elementType,
@@ -8842,6 +8812,15 @@
_variantField_28 = prefixExpression_operator,
_variantField_25 = expression_type;
+ LinkedNodeBuilder.prefixedIdentifier({
+ LinkedNodeBuilder prefixedIdentifier_identifier,
+ LinkedNodeBuilder prefixedIdentifier_prefix,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.prefixedIdentifier,
+ _variantField_6 = prefixedIdentifier_identifier,
+ _variantField_7 = prefixedIdentifier_prefix,
+ _variantField_25 = expression_type;
+
LinkedNodeBuilder.propertyAccess({
LinkedNodeBuilder propertyAccess_propertyName,
LinkedNodeBuilder propertyAccess_target,
@@ -8864,17 +8843,80 @@
_variantField_23 = redirectingConstructorInvocation_elementType,
_variantField_15 = redirectingConstructorInvocation_element;
+ LinkedNodeBuilder.rethrowExpression({
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.rethrowExpression,
+ _variantField_25 = expression_type;
+
LinkedNodeBuilder.returnStatement({
LinkedNodeBuilder returnStatement_expression,
}) : _kind = idl.LinkedNodeKind.returnStatement,
_variantField_6 = returnStatement_expression;
+ LinkedNodeBuilder.setOrMapLiteral({
+ List<LinkedNodeBuilder> typedLiteral_typeArguments,
+ List<LinkedNodeBuilder> setOrMapLiteral_elements,
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.setOrMapLiteral,
+ _variantField_2 = typedLiteral_typeArguments,
+ _variantField_3 = setOrMapLiteral_elements,
+ _variantField_25 = expression_type;
+
+ LinkedNodeBuilder.showCombinator({
+ List<String> names,
+ }) : _kind = idl.LinkedNodeKind.showCombinator,
+ _variantField_36 = names;
+
+ LinkedNodeBuilder.simpleFormalParameter({
+ LinkedNodeTypeBuilder actualType,
+ List<LinkedNodeBuilder> normalFormalParameter_metadata,
+ LinkedNodeBuilder simpleFormalParameter_type,
+ bool inheritsCovariant,
+ LinkedNodeBuilder normalFormalParameter_identifier,
+ int codeLength,
+ int codeOffset,
+ LinkedNodeBuilder normalFormalParameter_comment,
+ TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+ }) : _kind = idl.LinkedNodeKind.simpleFormalParameter,
+ _variantField_24 = actualType,
+ _variantField_4 = normalFormalParameter_metadata,
+ _variantField_6 = simpleFormalParameter_type,
+ _variantField_27 = inheritsCovariant,
+ _variantField_9 = normalFormalParameter_identifier,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_14 = normalFormalParameter_comment,
+ _variantField_34 = topLevelTypeInferenceError;
+
+ LinkedNodeBuilder.simpleIdentifier({
+ LinkedNodeTypeBuilder simpleIdentifier_elementType,
+ int simpleIdentifier_element,
+ LinkedNodeTypeBuilder expression_type,
+ int simpleIdentifier_offset,
+ String simpleIdentifier_name,
+ }) : _kind = idl.LinkedNodeKind.simpleIdentifier,
+ _variantField_23 = simpleIdentifier_elementType,
+ _variantField_15 = simpleIdentifier_element,
+ _variantField_25 = expression_type,
+ _variantField_16 = simpleIdentifier_offset,
+ _variantField_20 = simpleIdentifier_name;
+
+ LinkedNodeBuilder.simpleStringLiteral({
+ String simpleStringLiteral_value,
+ }) : _kind = idl.LinkedNodeKind.simpleStringLiteral,
+ _variantField_20 = simpleStringLiteral_value;
+
LinkedNodeBuilder.spreadElement({
LinkedNodeBuilder spreadElement_expression,
idl.UnlinkedTokenType spreadElement_spreadOperator,
}) : _kind = idl.LinkedNodeKind.spreadElement,
_variantField_6 = spreadElement_expression,
- _variantField_38 = spreadElement_spreadOperator;
+ _variantField_37 = spreadElement_spreadOperator;
+
+ LinkedNodeBuilder.stringInterpolation({
+ List<LinkedNodeBuilder> stringInterpolation_elements,
+ }) : _kind = idl.LinkedNodeKind.stringInterpolation,
+ _variantField_2 = stringInterpolation_elements;
LinkedNodeBuilder.superConstructorInvocation({
LinkedNodeBuilder superConstructorInvocation_arguments,
@@ -8887,6 +8929,46 @@
_variantField_23 = superConstructorInvocation_elementType,
_variantField_15 = superConstructorInvocation_element;
+ LinkedNodeBuilder.superExpression({
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.superExpression,
+ _variantField_25 = expression_type;
+
+ LinkedNodeBuilder.switchCase({
+ List<LinkedNodeBuilder> switchMember_statements,
+ LinkedNodeBuilder switchCase_expression,
+ List<LinkedNodeBuilder> switchMember_labels,
+ }) : _kind = idl.LinkedNodeKind.switchCase,
+ _variantField_4 = switchMember_statements,
+ _variantField_6 = switchCase_expression,
+ _variantField_3 = switchMember_labels;
+
+ LinkedNodeBuilder.switchDefault({
+ List<LinkedNodeBuilder> switchMember_statements,
+ List<LinkedNodeBuilder> switchMember_labels,
+ }) : _kind = idl.LinkedNodeKind.switchDefault,
+ _variantField_4 = switchMember_statements,
+ _variantField_3 = switchMember_labels;
+
+ LinkedNodeBuilder.switchStatement({
+ List<LinkedNodeBuilder> switchStatement_members,
+ LinkedNodeBuilder switchStatement_expression,
+ }) : _kind = idl.LinkedNodeKind.switchStatement,
+ _variantField_2 = switchStatement_members,
+ _variantField_7 = switchStatement_expression;
+
+ LinkedNodeBuilder.symbolLiteral({
+ LinkedNodeTypeBuilder expression_type,
+ List<String> names,
+ }) : _kind = idl.LinkedNodeKind.symbolLiteral,
+ _variantField_25 = expression_type,
+ _variantField_36 = names;
+
+ LinkedNodeBuilder.thisExpression({
+ LinkedNodeTypeBuilder expression_type,
+ }) : _kind = idl.LinkedNodeKind.thisExpression,
+ _variantField_25 = expression_type;
+
LinkedNodeBuilder.throwExpression({
LinkedNodeBuilder throwExpression_expression,
LinkedNodeTypeBuilder expression_type,
@@ -8894,6 +8976,92 @@
_variantField_6 = throwExpression_expression,
_variantField_25 = expression_type;
+ LinkedNodeBuilder.topLevelVariableDeclaration({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder topLevelVariableDeclaration_variableList,
+ }) : _kind = idl.LinkedNodeKind.topLevelVariableDeclaration,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = topLevelVariableDeclaration_variableList;
+
+ LinkedNodeBuilder.tryStatement({
+ List<LinkedNodeBuilder> tryStatement_catchClauses,
+ LinkedNodeBuilder tryStatement_body,
+ LinkedNodeBuilder tryStatement_finallyBlock,
+ }) : _kind = idl.LinkedNodeKind.tryStatement,
+ _variantField_2 = tryStatement_catchClauses,
+ _variantField_6 = tryStatement_body,
+ _variantField_7 = tryStatement_finallyBlock;
+
+ LinkedNodeBuilder.typeArgumentList({
+ List<LinkedNodeBuilder> typeArgumentList_arguments,
+ }) : _kind = idl.LinkedNodeKind.typeArgumentList,
+ _variantField_2 = typeArgumentList_arguments;
+
+ LinkedNodeBuilder.typeName({
+ List<LinkedNodeBuilder> typeName_typeArguments,
+ LinkedNodeBuilder typeName_name,
+ LinkedNodeTypeBuilder typeName_type,
+ }) : _kind = idl.LinkedNodeKind.typeName,
+ _variantField_2 = typeName_typeArguments,
+ _variantField_6 = typeName_name,
+ _variantField_23 = typeName_type;
+
+ LinkedNodeBuilder.typeParameter({
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder typeParameter_bound,
+ LinkedNodeBuilder typeParameter_name,
+ LinkedNodeTypeBuilder typeParameter_defaultType,
+ int codeLength,
+ int codeOffset,
+ }) : _kind = idl.LinkedNodeKind.typeParameter,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = typeParameter_bound,
+ _variantField_7 = typeParameter_name,
+ _variantField_23 = typeParameter_defaultType,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset;
+
+ LinkedNodeBuilder.typeParameterList({
+ List<LinkedNodeBuilder> typeParameterList_typeParameters,
+ }) : _kind = idl.LinkedNodeKind.typeParameterList,
+ _variantField_2 = typeParameterList_typeParameters;
+
+ LinkedNodeBuilder.variableDeclaration({
+ LinkedNodeTypeBuilder actualType,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder variableDeclaration_initializer,
+ LinkedNodeBuilder variableDeclaration_name,
+ bool inheritsCovariant,
+ int codeLength,
+ int codeOffset,
+ TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
+ }) : _kind = idl.LinkedNodeKind.variableDeclaration,
+ _variantField_24 = actualType,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = variableDeclaration_initializer,
+ _variantField_7 = variableDeclaration_name,
+ _variantField_27 = inheritsCovariant,
+ _variantField_33 = codeLength,
+ _variantField_32 = codeOffset,
+ _variantField_34 = topLevelTypeInferenceError;
+
+ LinkedNodeBuilder.variableDeclarationList({
+ List<LinkedNodeBuilder> variableDeclarationList_variables,
+ LinkedNodeBuilder annotatedNode_comment,
+ List<LinkedNodeBuilder> annotatedNode_metadata,
+ LinkedNodeBuilder variableDeclarationList_type,
+ }) : _kind = idl.LinkedNodeKind.variableDeclarationList,
+ _variantField_2 = variableDeclarationList_variables,
+ _variantField_11 = annotatedNode_comment,
+ _variantField_4 = annotatedNode_metadata,
+ _variantField_6 = variableDeclarationList_type;
+
LinkedNodeBuilder.variableDeclarationStatement({
LinkedNodeBuilder variableDeclarationStatement_variables,
}) : _kind = idl.LinkedNodeKind.variableDeclarationStatement,
@@ -8906,210 +9074,1973 @@
_variantField_6 = whileStatement_body,
_variantField_7 = whileStatement_condition;
+ LinkedNodeBuilder.withClause({
+ List<LinkedNodeBuilder> withClause_mixinTypes,
+ }) : _kind = idl.LinkedNodeKind.withClause,
+ _variantField_2 = withClause_mixinTypes;
+
LinkedNodeBuilder.yieldStatement({
LinkedNodeBuilder yieldStatement_expression,
}) : _kind = idl.LinkedNodeKind.yieldStatement,
_variantField_6 = yieldStatement_expression;
- LinkedNodeBuilder.simpleIdentifier({
- LinkedNodeTypeBuilder simpleIdentifier_elementType,
- int simpleIdentifier_element,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.simpleIdentifier,
- _variantField_23 = simpleIdentifier_elementType,
- _variantField_15 = simpleIdentifier_element,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.emptyFunctionBody({
- int emptyFunctionBody_fake,
- }) : _kind = idl.LinkedNodeKind.emptyFunctionBody,
- _variantField_15 = emptyFunctionBody_fake;
-
- LinkedNodeBuilder.emptyStatement({
- int emptyStatement_fake,
- }) : _kind = idl.LinkedNodeKind.emptyStatement,
- _variantField_15 = emptyStatement_fake;
-
- LinkedNodeBuilder.nullLiteral({
- int nullLiteral_fake,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.nullLiteral,
- _variantField_15 = nullLiteral_fake,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.booleanLiteral({
- bool booleanLiteral_value,
- }) : _kind = idl.LinkedNodeKind.booleanLiteral,
- _variantField_27 = booleanLiteral_value;
-
- LinkedNodeBuilder.hideCombinator({
- List<String> names,
- }) : _kind = idl.LinkedNodeKind.hideCombinator,
- _variantField_36 = names;
-
- LinkedNodeBuilder.showCombinator({
- List<String> names,
- }) : _kind = idl.LinkedNodeKind.showCombinator,
- _variantField_36 = names;
-
- LinkedNodeBuilder.symbolLiteral({
- List<String> names,
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.symbolLiteral,
- _variantField_36 = names,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.doubleLiteral({
- double doubleLiteral_value,
- }) : _kind = idl.LinkedNodeKind.doubleLiteral,
- _variantField_21 = doubleLiteral_value;
-
- LinkedNodeBuilder.rethrowExpression({
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.rethrowExpression,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.superExpression({
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.superExpression,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.thisExpression({
- LinkedNodeTypeBuilder expression_type,
- }) : _kind = idl.LinkedNodeKind.thisExpression,
- _variantField_25 = expression_type;
-
- LinkedNodeBuilder.integerLiteral({
- int integerLiteral_value,
- }) : _kind = idl.LinkedNodeKind.integerLiteral,
- _variantField_16 = integerLiteral_value;
-
- LinkedNodeBuilder.interpolationString({
- String interpolationString_value,
- }) : _kind = idl.LinkedNodeKind.interpolationString,
- _variantField_30 = interpolationString_value;
-
- LinkedNodeBuilder.simpleStringLiteral({
- String simpleStringLiteral_value,
- }) : _kind = idl.LinkedNodeKind.simpleStringLiteral,
- _variantField_20 = simpleStringLiteral_value;
-
/// Flush [informative] data recursively.
void flushInformative() {
- _variantField_24?.flushInformative();
- _variantField_2?.forEach((b) => b.flushInformative());
- _variantField_11?.flushInformative();
- _variantField_4?.forEach((b) => b.flushInformative());
- _variantField_6?.flushInformative();
- _variantField_7?.flushInformative();
- _variantField_23?.flushInformative();
- _variantField_8?.flushInformative();
- _variantField_9?.flushInformative();
- _variantField_12?.flushInformative();
- _variantField_5?.forEach((b) => b.flushInformative());
- _variantField_13?.flushInformative();
- _variantField_3?.forEach((b) => b.flushInformative());
- _variantField_10?.flushInformative();
- _variantField_25?.flushInformative();
- _variantField_14?.flushInformative();
- _variantField_35?.flushInformative();
- _variantField_32?.flushInformative();
+ if (kind == idl.LinkedNodeKind.adjacentStrings) {
+ adjacentStrings_strings?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.annotation) {
+ annotation_arguments?.flushInformative();
+ annotation_constructorName?.flushInformative();
+ annotation_elementType?.flushInformative();
+ annotation_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.argumentList) {
+ argumentList_arguments?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.asExpression) {
+ asExpression_expression?.flushInformative();
+ asExpression_type?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+ assertInitializer_condition?.flushInformative();
+ assertInitializer_message?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.assertStatement) {
+ assertStatement_condition?.flushInformative();
+ assertStatement_message?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+ assignmentExpression_leftHandSide?.flushInformative();
+ assignmentExpression_rightHandSide?.flushInformative();
+ assignmentExpression_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+ awaitExpression_expression?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+ binaryExpression_invokeType?.flushInformative();
+ binaryExpression_leftOperand?.flushInformative();
+ binaryExpression_rightOperand?.flushInformative();
+ binaryExpression_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.block) {
+ block_statements?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+ blockFunctionBody_block?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+ } else if (kind == idl.LinkedNodeKind.breakStatement) {
+ breakStatement_label?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+ cascadeExpression_sections?.forEach((b) => b.flushInformative());
+ cascadeExpression_target?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.catchClause) {
+ catchClause_body?.flushInformative();
+ catchClause_exceptionParameter?.flushInformative();
+ catchClause_exceptionType?.flushInformative();
+ catchClause_stackTraceParameter?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ classDeclaration_extendsClause?.flushInformative();
+ classDeclaration_withClause?.flushInformative();
+ classDeclaration_nativeClause?.flushInformative();
+ classOrMixinDeclaration_implementsClause?.flushInformative();
+ classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+ classOrMixinDeclaration_typeParameters?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ classTypeAlias_typeParameters?.flushInformative();
+ classTypeAlias_superclass?.flushInformative();
+ classTypeAlias_withClause?.flushInformative();
+ classTypeAlias_implementsClause?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.comment) {
+ comment_references?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.commentReference) {
+ commentReference_identifier?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+ compilationUnit_declarations?.forEach((b) => b.flushInformative());
+ compilationUnit_scriptTag?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ compilationUnit_directives?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+ conditionalExpression_condition?.flushInformative();
+ conditionalExpression_elseExpression?.flushInformative();
+ conditionalExpression_thenExpression?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.configuration) {
+ configuration_name?.flushInformative();
+ configuration_value?.flushInformative();
+ configuration_uri?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+ constructorDeclaration_initializers?.forEach((b) => b.flushInformative());
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ constructorDeclaration_body?.flushInformative();
+ constructorDeclaration_name?.flushInformative();
+ constructorDeclaration_parameters?.flushInformative();
+ constructorDeclaration_redirectedConstructor?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ constructorDeclaration_periodOffset = null;
+ constructorDeclaration_returnType?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+ constructorFieldInitializer_expression?.flushInformative();
+ constructorFieldInitializer_fieldName?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.constructorName) {
+ constructorName_name?.flushInformative();
+ constructorName_type?.flushInformative();
+ constructorName_elementType?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.continueStatement) {
+ continueStatement_label?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ declaredIdentifier_identifier?.flushInformative();
+ declaredIdentifier_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+ defaultFormalParameter_defaultValue?.flushInformative();
+ defaultFormalParameter_parameter?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ } else if (kind == idl.LinkedNodeKind.doStatement) {
+ doStatement_body?.flushInformative();
+ doStatement_condition?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.dottedName) {
+ dottedName_components?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+ } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+ } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+ } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ enumConstantDeclaration_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+ enumDeclaration_constants?.forEach((b) => b.flushInformative());
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.exportDirective) {
+ namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ directive_keywordOffset = null;
+ namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+ uriBasedDirective_uri?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+ expressionFunctionBody_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+ expressionStatement_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.extendsClause) {
+ extendsClause_superclass?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ fieldDeclaration_fields?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+ actualType?.flushInformative();
+ normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+ fieldFormalParameter_type?.flushInformative();
+ fieldFormalParameter_typeParameters?.flushInformative();
+ fieldFormalParameter_formalParameters?.flushInformative();
+ normalFormalParameter_identifier?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ normalFormalParameter_comment = null;
+ } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+ forEachParts_iterable?.flushInformative();
+ forEachPartsWithDeclaration_loopVariable?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+ forEachParts_iterable?.flushInformative();
+ forEachPartsWithIdentifier_identifier?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.forElement) {
+ forMixin_forLoopParts?.flushInformative();
+ forElement_body?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+ forParts_condition?.flushInformative();
+ forPartsWithDeclarations_variables?.flushInformative();
+ forParts_updaters?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+ forParts_condition?.flushInformative();
+ forPartsWithExpression_initialization?.flushInformative();
+ forParts_updaters?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.forStatement) {
+ forMixin_forLoopParts?.flushInformative();
+ forStatement_body?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+ formalParameterList_parameters?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+ actualReturnType?.flushInformative();
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ functionDeclaration_functionExpression?.flushInformative();
+ functionDeclaration_returnType?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+ functionDeclarationStatement_functionDeclaration?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.functionExpression) {
+ actualReturnType?.flushInformative();
+ functionExpression_body?.flushInformative();
+ functionExpression_formalParameters?.flushInformative();
+ functionExpression_typeParameters?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+ invocationExpression_invokeType?.flushInformative();
+ functionExpressionInvocation_function?.flushInformative();
+ invocationExpression_typeArguments?.flushInformative();
+ expression_type?.flushInformative();
+ invocationExpression_arguments?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+ actualReturnType?.flushInformative();
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ functionTypeAlias_formalParameters?.flushInformative();
+ functionTypeAlias_returnType?.flushInformative();
+ functionTypeAlias_typeParameters?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+ actualType?.flushInformative();
+ normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+ functionTypedFormalParameter_formalParameters?.flushInformative();
+ functionTypedFormalParameter_returnType?.flushInformative();
+ functionTypedFormalParameter_typeParameters?.flushInformative();
+ normalFormalParameter_identifier?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ normalFormalParameter_comment = null;
+ } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+ actualReturnType?.flushInformative();
+ genericFunctionType_typeParameters?.flushInformative();
+ genericFunctionType_returnType?.flushInformative();
+ genericFunctionType_formalParameters?.flushInformative();
+ genericFunctionType_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ genericTypeAlias_typeParameters?.flushInformative();
+ genericTypeAlias_functionType?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+ } else if (kind == idl.LinkedNodeKind.ifElement) {
+ ifMixin_condition?.flushInformative();
+ ifElement_thenElement?.flushInformative();
+ ifElement_elseElement?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.ifStatement) {
+ ifMixin_condition?.flushInformative();
+ ifStatement_elseStatement?.flushInformative();
+ ifStatement_thenStatement?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.implementsClause) {
+ implementsClause_interfaces?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.importDirective) {
+ namespaceDirective_combinators?.forEach((b) => b.flushInformative());
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ directive_keywordOffset = null;
+ namespaceDirective_configurations?.forEach((b) => b.flushInformative());
+ uriBasedDirective_uri?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.indexExpression) {
+ indexExpression_index?.flushInformative();
+ indexExpression_target?.flushInformative();
+ indexExpression_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+ instanceCreationExpression_arguments
+ ?.forEach((b) => b.flushInformative());
+ instanceCreationExpression_constructorName?.flushInformative();
+ instanceCreationExpression_typeArguments?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+ } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+ interpolationExpression_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.interpolationString) {
+ } else if (kind == idl.LinkedNodeKind.isExpression) {
+ isExpression_expression?.flushInformative();
+ isExpression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.label) {
+ label_label?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+ labeledStatement_labels?.forEach((b) => b.flushInformative());
+ labeledStatement_statement?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ libraryDirective_name?.flushInformative();
+ directive_keywordOffset = null;
+ } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+ libraryIdentifier_components?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.listLiteral) {
+ typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+ listLiteral_elements?.forEach((b) => b.flushInformative());
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+ mapLiteralEntry_key?.flushInformative();
+ mapLiteralEntry_value?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+ actualReturnType?.flushInformative();
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ methodDeclaration_body?.flushInformative();
+ methodDeclaration_formalParameters?.flushInformative();
+ methodDeclaration_returnType?.flushInformative();
+ methodDeclaration_typeParameters?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ methodDeclaration_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+ invocationExpression_invokeType?.flushInformative();
+ methodInvocation_methodName?.flushInformative();
+ methodInvocation_target?.flushInformative();
+ invocationExpression_typeArguments?.flushInformative();
+ expression_type?.flushInformative();
+ invocationExpression_arguments?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ mixinDeclaration_onClause?.flushInformative();
+ classOrMixinDeclaration_implementsClause?.flushInformative();
+ classOrMixinDeclaration_members?.forEach((b) => b.flushInformative());
+ classOrMixinDeclaration_typeParameters?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ namedCompilationUnitMember_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.namedExpression) {
+ namedExpression_expression?.flushInformative();
+ namedExpression_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.nativeClause) {
+ nativeClause_name?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+ nativeFunctionBody_stringLiteral?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.onClause) {
+ onClause_superclassConstraints?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+ parenthesizedExpression_expression?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.partDirective) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ directive_keywordOffset = null;
+ uriBasedDirective_uri?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ partOfDirective_libraryName?.flushInformative();
+ partOfDirective_uri?.flushInformative();
+ directive_keywordOffset = null;
+ } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+ postfixExpression_operand?.flushInformative();
+ postfixExpression_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+ prefixExpression_operand?.flushInformative();
+ prefixExpression_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+ prefixedIdentifier_identifier?.flushInformative();
+ prefixedIdentifier_prefix?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+ propertyAccess_propertyName?.flushInformative();
+ propertyAccess_target?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+ redirectingConstructorInvocation_arguments?.flushInformative();
+ redirectingConstructorInvocation_constructorName?.flushInformative();
+ redirectingConstructorInvocation_elementType?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.returnStatement) {
+ returnStatement_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+ typedLiteral_typeArguments?.forEach((b) => b.flushInformative());
+ setOrMapLiteral_elements?.forEach((b) => b.flushInformative());
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.showCombinator) {
+ } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+ actualType?.flushInformative();
+ normalFormalParameter_metadata?.forEach((b) => b.flushInformative());
+ simpleFormalParameter_type?.flushInformative();
+ normalFormalParameter_identifier?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ normalFormalParameter_comment = null;
+ topLevelTypeInferenceError?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+ simpleIdentifier_elementType?.flushInformative();
+ expression_type?.flushInformative();
+ simpleIdentifier_offset = null;
+ } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+ } else if (kind == idl.LinkedNodeKind.spreadElement) {
+ spreadElement_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+ stringInterpolation_elements?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+ superConstructorInvocation_arguments?.flushInformative();
+ superConstructorInvocation_constructorName?.flushInformative();
+ superConstructorInvocation_elementType?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.superExpression) {
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.switchCase) {
+ switchMember_statements?.forEach((b) => b.flushInformative());
+ switchCase_expression?.flushInformative();
+ switchMember_labels?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.switchDefault) {
+ switchMember_statements?.forEach((b) => b.flushInformative());
+ switchMember_labels?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.switchStatement) {
+ switchStatement_members?.forEach((b) => b.flushInformative());
+ switchStatement_expression?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.thisExpression) {
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.throwExpression) {
+ throwExpression_expression?.flushInformative();
+ expression_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ topLevelVariableDeclaration_variableList?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.tryStatement) {
+ tryStatement_catchClauses?.forEach((b) => b.flushInformative());
+ tryStatement_body?.flushInformative();
+ tryStatement_finallyBlock?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+ typeArgumentList_arguments?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.typeName) {
+ typeName_typeArguments?.forEach((b) => b.flushInformative());
+ typeName_name?.flushInformative();
+ typeName_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.typeParameter) {
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ typeParameter_bound?.flushInformative();
+ typeParameter_name?.flushInformative();
+ typeParameter_defaultType?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+ typeParameterList_typeParameters?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+ actualType?.flushInformative();
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ variableDeclaration_initializer?.flushInformative();
+ variableDeclaration_name?.flushInformative();
+ codeLength = null;
+ codeOffset = null;
+ topLevelTypeInferenceError?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+ variableDeclarationList_variables?.forEach((b) => b.flushInformative());
+ annotatedNode_comment = null;
+ annotatedNode_metadata?.forEach((b) => b.flushInformative());
+ variableDeclarationList_type?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+ variableDeclarationStatement_variables?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.whileStatement) {
+ whileStatement_body?.flushInformative();
+ whileStatement_condition?.flushInformative();
+ } else if (kind == idl.LinkedNodeKind.withClause) {
+ withClause_mixinTypes?.forEach((b) => b.flushInformative());
+ } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+ yieldStatement_expression?.flushInformative();
+ }
}
/// Accumulate non-[informative] data into [signature].
void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addInt(this._kind == null ? 0 : this._kind.index);
- signature.addString(this._variantField_1 ?? '');
- if (this._variantField_2 == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._variantField_2.length);
- for (var x in this._variantField_2) {
- x?.collectApiSignature(signature);
+ if (kind == idl.LinkedNodeKind.adjacentStrings) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.adjacentStrings_strings == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.adjacentStrings_strings.length);
+ for (var x in this.adjacentStrings_strings) {
+ x?.collectApiSignature(signature);
+ }
}
- }
- if (this._variantField_3 == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._variantField_3.length);
- for (var x in this._variantField_3) {
- x?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.annotation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.annotation_arguments != null);
+ this.annotation_arguments?.collectApiSignature(signature);
+ signature.addBool(this.annotation_constructorName != null);
+ this.annotation_constructorName?.collectApiSignature(signature);
+ signature.addBool(this.annotation_name != null);
+ this.annotation_name?.collectApiSignature(signature);
+ signature.addInt(this.annotation_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.annotation_elementType != null);
+ this.annotation_elementType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.argumentList) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.argumentList_arguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.argumentList_arguments.length);
+ for (var x in this.argumentList_arguments) {
+ x?.collectApiSignature(signature);
+ }
}
- }
- if (this._variantField_4 == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._variantField_4.length);
- for (var x in this._variantField_4) {
- x?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.asExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.asExpression_expression != null);
+ this.asExpression_expression?.collectApiSignature(signature);
+ signature.addBool(this.asExpression_type != null);
+ this.asExpression_type?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.assertInitializer) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.assertInitializer_condition != null);
+ this.assertInitializer_condition?.collectApiSignature(signature);
+ signature.addBool(this.assertInitializer_message != null);
+ this.assertInitializer_message?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.assertStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.assertStatement_condition != null);
+ this.assertStatement_condition?.collectApiSignature(signature);
+ signature.addBool(this.assertStatement_message != null);
+ this.assertStatement_message?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.assignmentExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.assignmentExpression_leftHandSide != null);
+ this.assignmentExpression_leftHandSide?.collectApiSignature(signature);
+ signature.addBool(this.assignmentExpression_rightHandSide != null);
+ this.assignmentExpression_rightHandSide?.collectApiSignature(signature);
+ signature.addInt(this.assignmentExpression_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.assignmentExpression_elementType != null);
+ this.assignmentExpression_elementType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ signature.addInt(this.assignmentExpression_operator == null
+ ? 0
+ : this.assignmentExpression_operator.index);
+ } else if (kind == idl.LinkedNodeKind.awaitExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.awaitExpression_expression != null);
+ this.awaitExpression_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.binaryExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.binaryExpression_leftOperand != null);
+ this.binaryExpression_leftOperand?.collectApiSignature(signature);
+ signature.addBool(this.binaryExpression_rightOperand != null);
+ this.binaryExpression_rightOperand?.collectApiSignature(signature);
+ signature.addInt(this.binaryExpression_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.binaryExpression_elementType != null);
+ this.binaryExpression_elementType?.collectApiSignature(signature);
+ signature.addBool(this.binaryExpression_invokeType != null);
+ this.binaryExpression_invokeType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ signature.addInt(this.binaryExpression_operator == null
+ ? 0
+ : this.binaryExpression_operator.index);
+ } else if (kind == idl.LinkedNodeKind.block) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.block_statements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.block_statements.length);
+ for (var x in this.block_statements) {
+ x?.collectApiSignature(signature);
+ }
}
- }
- if (this._variantField_5 == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._variantField_5.length);
- for (var x in this._variantField_5) {
- x?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.blockFunctionBody_block != null);
+ this.blockFunctionBody_block?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.booleanLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.booleanLiteral_value == true);
+ } else if (kind == idl.LinkedNodeKind.breakStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.breakStatement_label != null);
+ this.breakStatement_label?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.cascadeExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.cascadeExpression_sections == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.cascadeExpression_sections.length);
+ for (var x in this.cascadeExpression_sections) {
+ x?.collectApiSignature(signature);
+ }
}
- }
- signature.addBool(this._variantField_6 != null);
- this._variantField_6?.collectApiSignature(signature);
- signature.addBool(this._variantField_7 != null);
- this._variantField_7?.collectApiSignature(signature);
- signature.addBool(this._variantField_8 != null);
- this._variantField_8?.collectApiSignature(signature);
- signature.addBool(this._variantField_9 != null);
- this._variantField_9?.collectApiSignature(signature);
- signature.addBool(this._variantField_10 != null);
- this._variantField_10?.collectApiSignature(signature);
- signature.addBool(this._variantField_11 != null);
- this._variantField_11?.collectApiSignature(signature);
- signature.addBool(this._variantField_12 != null);
- this._variantField_12?.collectApiSignature(signature);
- signature.addBool(this._variantField_13 != null);
- this._variantField_13?.collectApiSignature(signature);
- signature.addBool(this._variantField_14 != null);
- this._variantField_14?.collectApiSignature(signature);
- signature.addInt(this._variantField_15 ?? 0);
- signature.addInt(this._variantField_16 ?? 0);
- signature.addInt(this._variantField_17 ?? 0);
- signature.addInt(this._flags ?? 0);
- signature.addInt(this._variantField_19 ?? 0);
- signature.addString(this._variantField_20 ?? '');
- signature.addDouble(this._variantField_21 ?? 0.0);
- signature.addString(this._variantField_22 ?? '');
- signature.addBool(this._variantField_23 != null);
- this._variantField_23?.collectApiSignature(signature);
- signature.addBool(this._variantField_24 != null);
- this._variantField_24?.collectApiSignature(signature);
- signature.addBool(this._variantField_25 != null);
- this._variantField_25?.collectApiSignature(signature);
- signature.addInt(
- this._variantField_26 == null ? 0 : this._variantField_26.index);
- signature.addBool(this._variantField_27 == true);
- signature.addInt(
- this._variantField_28 == null ? 0 : this._variantField_28.index);
- signature.addInt(
- this._variantField_29 == null ? 0 : this._variantField_29.index);
- signature.addString(this._variantField_30 ?? '');
- signature.addBool(this._variantField_31 == true);
- signature.addBool(this._variantField_32 != null);
- this._variantField_32?.collectApiSignature(signature);
- signature.addInt(this._variantField_33 ?? 0);
- signature.addInt(this._variantField_34 ?? 0);
- signature.addBool(this._variantField_35 != null);
- this._variantField_35?.collectApiSignature(signature);
- if (this._variantField_36 == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._variantField_36.length);
- for (var x in this._variantField_36) {
- signature.addString(x);
+ signature.addBool(this.cascadeExpression_target != null);
+ this.cascadeExpression_target?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.catchClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.catchClause_body != null);
+ this.catchClause_body?.collectApiSignature(signature);
+ signature.addBool(this.catchClause_exceptionParameter != null);
+ this.catchClause_exceptionParameter?.collectApiSignature(signature);
+ signature.addBool(this.catchClause_exceptionType != null);
+ this.catchClause_exceptionType?.collectApiSignature(signature);
+ signature.addBool(this.catchClause_stackTraceParameter != null);
+ this.catchClause_stackTraceParameter?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.classDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
}
+ if (this.classOrMixinDeclaration_members == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.classOrMixinDeclaration_members.length);
+ for (var x in this.classOrMixinDeclaration_members) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.classDeclaration_extendsClause != null);
+ this.classDeclaration_extendsClause?.collectApiSignature(signature);
+ signature.addBool(this.classDeclaration_withClause != null);
+ this.classDeclaration_withClause?.collectApiSignature(signature);
+ signature.addBool(this.classDeclaration_nativeClause != null);
+ this.classDeclaration_nativeClause?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+ this
+ .classOrMixinDeclaration_implementsClause
+ ?.collectApiSignature(signature);
+ signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+ this
+ .classOrMixinDeclaration_typeParameters
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.classDeclaration_isDartObject == true);
+ signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+ } else if (kind == idl.LinkedNodeKind.classTypeAlias) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.classTypeAlias_typeParameters != null);
+ this.classTypeAlias_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.classTypeAlias_superclass != null);
+ this.classTypeAlias_superclass?.collectApiSignature(signature);
+ signature.addBool(this.classTypeAlias_withClause != null);
+ this.classTypeAlias_withClause?.collectApiSignature(signature);
+ signature.addBool(this.classTypeAlias_implementsClause != null);
+ this.classTypeAlias_implementsClause?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+ } else if (kind == idl.LinkedNodeKind.comment) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.comment_references == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.comment_references.length);
+ for (var x in this.comment_references) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.comment_type == null ? 0 : this.comment_type.index);
+ if (this.comment_tokens == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.comment_tokens.length);
+ for (var x in this.comment_tokens) {
+ signature.addString(x);
+ }
+ }
+ } else if (kind == idl.LinkedNodeKind.commentReference) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.commentReference_identifier != null);
+ this.commentReference_identifier?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.compilationUnit) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.compilationUnit_declarations == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.compilationUnit_declarations.length);
+ for (var x in this.compilationUnit_declarations) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.compilationUnit_directives == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.compilationUnit_directives.length);
+ for (var x in this.compilationUnit_directives) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.compilationUnit_scriptTag != null);
+ this.compilationUnit_scriptTag?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.conditionalExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.conditionalExpression_condition != null);
+ this.conditionalExpression_condition?.collectApiSignature(signature);
+ signature.addBool(this.conditionalExpression_elseExpression != null);
+ this.conditionalExpression_elseExpression?.collectApiSignature(signature);
+ signature.addBool(this.conditionalExpression_thenExpression != null);
+ this.conditionalExpression_thenExpression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.configuration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.configuration_name != null);
+ this.configuration_name?.collectApiSignature(signature);
+ signature.addBool(this.configuration_value != null);
+ this.configuration_value?.collectApiSignature(signature);
+ signature.addBool(this.configuration_uri != null);
+ this.configuration_uri?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.constructorDeclaration_initializers == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.constructorDeclaration_initializers.length);
+ for (var x in this.constructorDeclaration_initializers) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.constructorDeclaration_body != null);
+ this.constructorDeclaration_body?.collectApiSignature(signature);
+ signature.addBool(this.constructorDeclaration_name != null);
+ this.constructorDeclaration_name?.collectApiSignature(signature);
+ signature.addBool(this.constructorDeclaration_parameters != null);
+ this.constructorDeclaration_parameters?.collectApiSignature(signature);
+ signature
+ .addBool(this.constructorDeclaration_redirectedConstructor != null);
+ this
+ .constructorDeclaration_redirectedConstructor
+ ?.collectApiSignature(signature);
+ signature.addBool(this.constructorDeclaration_returnType != null);
+ this.constructorDeclaration_returnType?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.constructorFieldInitializer_expression != null);
+ this
+ .constructorFieldInitializer_expression
+ ?.collectApiSignature(signature);
+ signature.addBool(this.constructorFieldInitializer_fieldName != null);
+ this
+ .constructorFieldInitializer_fieldName
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.constructorName) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.constructorName_name != null);
+ this.constructorName_name?.collectApiSignature(signature);
+ signature.addBool(this.constructorName_type != null);
+ this.constructorName_type?.collectApiSignature(signature);
+ signature.addInt(this.constructorName_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.constructorName_elementType != null);
+ this.constructorName_elementType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.continueStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.continueStatement_label != null);
+ this.continueStatement_label?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.declaredIdentifier_identifier != null);
+ this.declaredIdentifier_identifier?.collectApiSignature(signature);
+ signature.addBool(this.declaredIdentifier_type != null);
+ this.declaredIdentifier_type?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.defaultFormalParameter_defaultValue != null);
+ this.defaultFormalParameter_defaultValue?.collectApiSignature(signature);
+ signature.addBool(this.defaultFormalParameter_parameter != null);
+ this.defaultFormalParameter_parameter?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.defaultFormalParameter_kind == null
+ ? 0
+ : this.defaultFormalParameter_kind.index);
+ } else if (kind == idl.LinkedNodeKind.doStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.doStatement_body != null);
+ this.doStatement_body?.collectApiSignature(signature);
+ signature.addBool(this.doStatement_condition != null);
+ this.doStatement_condition?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.dottedName) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.dottedName_components == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.dottedName_components.length);
+ for (var x in this.dottedName_components) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.doubleLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addDouble(this.doubleLiteral_value ?? 0.0);
+ } else if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.emptyFunctionBody_fake ?? 0);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.emptyStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.emptyStatement_fake ?? 0);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.enumConstantDeclaration_name != null);
+ this.enumConstantDeclaration_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.enumDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.enumDeclaration_constants == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.enumDeclaration_constants.length);
+ for (var x in this.enumDeclaration_constants) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.exportDirective) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.namespaceDirective_combinators == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.namespaceDirective_combinators.length);
+ for (var x in this.namespaceDirective_combinators) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.namespaceDirective_configurations == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.namespaceDirective_configurations.length);
+ for (var x in this.namespaceDirective_configurations) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.uriBasedDirective_uri != null);
+ this.uriBasedDirective_uri?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+ signature.addString(this.namespaceDirective_selectedUri ?? '');
+ signature.addString(this.uriBasedDirective_uriContent ?? '');
+ } else if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.expressionFunctionBody_expression != null);
+ this.expressionFunctionBody_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.expressionStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.expressionStatement_expression != null);
+ this.expressionStatement_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.extendsClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.extendsClause_superclass != null);
+ this.extendsClause_superclass?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.fieldDeclaration_fields != null);
+ this.fieldDeclaration_fields?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.normalFormalParameter_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.normalFormalParameter_metadata.length);
+ for (var x in this.normalFormalParameter_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.fieldFormalParameter_type != null);
+ this.fieldFormalParameter_type?.collectApiSignature(signature);
+ signature.addBool(this.fieldFormalParameter_typeParameters != null);
+ this.fieldFormalParameter_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.fieldFormalParameter_formalParameters != null);
+ this
+ .fieldFormalParameter_formalParameters
+ ?.collectApiSignature(signature);
+ signature.addBool(this.normalFormalParameter_identifier != null);
+ this.normalFormalParameter_identifier?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualType != null);
+ this.actualType?.collectApiSignature(signature);
+ signature.addBool(this.inheritsCovariant == true);
+ } else if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.forEachParts_iterable != null);
+ this.forEachParts_iterable?.collectApiSignature(signature);
+ signature.addBool(this.forEachPartsWithDeclaration_loopVariable != null);
+ this
+ .forEachPartsWithDeclaration_loopVariable
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.forEachParts_iterable != null);
+ this.forEachParts_iterable?.collectApiSignature(signature);
+ signature.addBool(this.forEachPartsWithIdentifier_identifier != null);
+ this
+ .forEachPartsWithIdentifier_identifier
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.forElement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.forMixin_forLoopParts != null);
+ this.forMixin_forLoopParts?.collectApiSignature(signature);
+ signature.addBool(this.forElement_body != null);
+ this.forElement_body?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.forParts_updaters == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.forParts_updaters.length);
+ for (var x in this.forParts_updaters) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.forParts_condition != null);
+ this.forParts_condition?.collectApiSignature(signature);
+ signature.addBool(this.forPartsWithDeclarations_variables != null);
+ this.forPartsWithDeclarations_variables?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.forParts_updaters == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.forParts_updaters.length);
+ for (var x in this.forParts_updaters) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.forParts_condition != null);
+ this.forParts_condition?.collectApiSignature(signature);
+ signature.addBool(this.forPartsWithExpression_initialization != null);
+ this
+ .forPartsWithExpression_initialization
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.forStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.forMixin_forLoopParts != null);
+ this.forMixin_forLoopParts?.collectApiSignature(signature);
+ signature.addBool(this.forStatement_body != null);
+ this.forStatement_body?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.formalParameterList) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.formalParameterList_parameters == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.formalParameterList_parameters.length);
+ for (var x in this.formalParameterList_parameters) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.functionDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.functionDeclaration_functionExpression != null);
+ this
+ .functionDeclaration_functionExpression
+ ?.collectApiSignature(signature);
+ signature.addBool(this.functionDeclaration_returnType != null);
+ this.functionDeclaration_returnType?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualReturnType != null);
+ this.actualReturnType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(
+ this.functionDeclarationStatement_functionDeclaration != null);
+ this
+ .functionDeclarationStatement_functionDeclaration
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.functionExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.functionExpression_body != null);
+ this.functionExpression_body?.collectApiSignature(signature);
+ signature.addBool(this.functionExpression_formalParameters != null);
+ this.functionExpression_formalParameters?.collectApiSignature(signature);
+ signature.addBool(this.functionExpression_typeParameters != null);
+ this.functionExpression_typeParameters?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualReturnType != null);
+ this.actualReturnType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.functionExpressionInvocation_function != null);
+ this
+ .functionExpressionInvocation_function
+ ?.collectApiSignature(signature);
+ signature.addBool(this.invocationExpression_typeArguments != null);
+ this.invocationExpression_typeArguments?.collectApiSignature(signature);
+ signature.addBool(this.invocationExpression_arguments != null);
+ this.invocationExpression_arguments?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.invocationExpression_invokeType != null);
+ this.invocationExpression_invokeType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.functionTypeAlias_formalParameters != null);
+ this.functionTypeAlias_formalParameters?.collectApiSignature(signature);
+ signature.addBool(this.functionTypeAlias_returnType != null);
+ this.functionTypeAlias_returnType?.collectApiSignature(signature);
+ signature.addBool(this.functionTypeAlias_typeParameters != null);
+ this.functionTypeAlias_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualReturnType != null);
+ this.actualReturnType?.collectApiSignature(signature);
+ signature.addBool(this.typeAlias_hasSelfReference == true);
+ signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+ } else if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.normalFormalParameter_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.normalFormalParameter_metadata.length);
+ for (var x in this.normalFormalParameter_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature
+ .addBool(this.functionTypedFormalParameter_formalParameters != null);
+ this
+ .functionTypedFormalParameter_formalParameters
+ ?.collectApiSignature(signature);
+ signature.addBool(this.functionTypedFormalParameter_returnType != null);
+ this
+ .functionTypedFormalParameter_returnType
+ ?.collectApiSignature(signature);
+ signature
+ .addBool(this.functionTypedFormalParameter_typeParameters != null);
+ this
+ .functionTypedFormalParameter_typeParameters
+ ?.collectApiSignature(signature);
+ signature.addBool(this.normalFormalParameter_identifier != null);
+ this.normalFormalParameter_identifier?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualType != null);
+ this.actualType?.collectApiSignature(signature);
+ signature.addBool(this.inheritsCovariant == true);
+ } else if (kind == idl.LinkedNodeKind.genericFunctionType) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.genericFunctionType_typeParameters != null);
+ this.genericFunctionType_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.genericFunctionType_returnType != null);
+ this.genericFunctionType_returnType?.collectApiSignature(signature);
+ signature.addBool(this.genericFunctionType_formalParameters != null);
+ this.genericFunctionType_formalParameters?.collectApiSignature(signature);
+ signature.addInt(this.genericFunctionType_id ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualReturnType != null);
+ this.actualReturnType?.collectApiSignature(signature);
+ signature.addBool(this.genericFunctionType_type != null);
+ this.genericFunctionType_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.genericTypeAlias_typeParameters != null);
+ this.genericTypeAlias_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.genericTypeAlias_functionType != null);
+ this.genericTypeAlias_functionType?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.typeAlias_hasSelfReference == true);
+ signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+ } else if (kind == idl.LinkedNodeKind.hideCombinator) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ if (this.names == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.names.length);
+ for (var x in this.names) {
+ signature.addString(x);
+ }
+ }
+ } else if (kind == idl.LinkedNodeKind.ifElement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.ifMixin_condition != null);
+ this.ifMixin_condition?.collectApiSignature(signature);
+ signature.addBool(this.ifElement_thenElement != null);
+ this.ifElement_thenElement?.collectApiSignature(signature);
+ signature.addBool(this.ifElement_elseElement != null);
+ this.ifElement_elseElement?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.ifStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.ifMixin_condition != null);
+ this.ifMixin_condition?.collectApiSignature(signature);
+ signature.addBool(this.ifStatement_elseStatement != null);
+ this.ifStatement_elseStatement?.collectApiSignature(signature);
+ signature.addBool(this.ifStatement_thenStatement != null);
+ this.ifStatement_thenStatement?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.implementsClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.implementsClause_interfaces == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.implementsClause_interfaces.length);
+ for (var x in this.implementsClause_interfaces) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.importDirective) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addString(this.importDirective_prefix ?? '');
+ if (this.namespaceDirective_combinators == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.namespaceDirective_combinators.length);
+ for (var x in this.namespaceDirective_combinators) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.namespaceDirective_configurations == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.namespaceDirective_configurations.length);
+ for (var x in this.namespaceDirective_configurations) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.uriBasedDirective_uri != null);
+ this.uriBasedDirective_uri?.collectApiSignature(signature);
+ signature.addInt(this.importDirective_prefixOffset ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+ signature.addString(this.namespaceDirective_selectedUri ?? '');
+ signature.addString(this.uriBasedDirective_uriContent ?? '');
+ } else if (kind == idl.LinkedNodeKind.indexExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.indexExpression_index != null);
+ this.indexExpression_index?.collectApiSignature(signature);
+ signature.addBool(this.indexExpression_target != null);
+ this.indexExpression_target?.collectApiSignature(signature);
+ signature.addInt(this.indexExpression_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.indexExpression_elementType != null);
+ this.indexExpression_elementType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.instanceCreationExpression_arguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.instanceCreationExpression_arguments.length);
+ for (var x in this.instanceCreationExpression_arguments) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature
+ .addBool(this.instanceCreationExpression_constructorName != null);
+ this
+ .instanceCreationExpression_constructorName
+ ?.collectApiSignature(signature);
+ signature.addBool(this.instanceCreationExpression_typeArguments != null);
+ this
+ .instanceCreationExpression_typeArguments
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.integerLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.integerLiteral_value ?? 0);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.interpolationExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.interpolationExpression_expression != null);
+ this.interpolationExpression_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.interpolationString) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addString(this.interpolationString_value ?? '');
+ } else if (kind == idl.LinkedNodeKind.isExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.isExpression_expression != null);
+ this.isExpression_expression?.collectApiSignature(signature);
+ signature.addBool(this.isExpression_type != null);
+ this.isExpression_type?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.label) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.label_label != null);
+ this.label_label?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.labeledStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.labeledStatement_labels == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.labeledStatement_labels.length);
+ for (var x in this.labeledStatement_labels) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.labeledStatement_statement != null);
+ this.labeledStatement_statement?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.libraryDirective) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.libraryDirective_name != null);
+ this.libraryDirective_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.libraryIdentifier_components == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.libraryIdentifier_components.length);
+ for (var x in this.libraryIdentifier_components) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.listLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.typedLiteral_typeArguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.typedLiteral_typeArguments.length);
+ for (var x in this.typedLiteral_typeArguments) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.listLiteral_elements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.listLiteral_elements.length);
+ for (var x in this.listLiteral_elements) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.mapLiteralEntry_key != null);
+ this.mapLiteralEntry_key?.collectApiSignature(signature);
+ signature.addBool(this.mapLiteralEntry_value != null);
+ this.mapLiteralEntry_value?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.methodDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.methodDeclaration_body != null);
+ this.methodDeclaration_body?.collectApiSignature(signature);
+ signature.addBool(this.methodDeclaration_formalParameters != null);
+ this.methodDeclaration_formalParameters?.collectApiSignature(signature);
+ signature.addBool(this.methodDeclaration_returnType != null);
+ this.methodDeclaration_returnType?.collectApiSignature(signature);
+ signature.addBool(this.methodDeclaration_typeParameters != null);
+ this.methodDeclaration_typeParameters?.collectApiSignature(signature);
+ signature.addBool(this.methodDeclaration_name != null);
+ this.methodDeclaration_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualReturnType != null);
+ this.actualReturnType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.methodInvocation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.methodInvocation_methodName != null);
+ this.methodInvocation_methodName?.collectApiSignature(signature);
+ signature.addBool(this.methodInvocation_target != null);
+ this.methodInvocation_target?.collectApiSignature(signature);
+ signature.addBool(this.invocationExpression_typeArguments != null);
+ this.invocationExpression_typeArguments?.collectApiSignature(signature);
+ signature.addBool(this.invocationExpression_arguments != null);
+ this.invocationExpression_arguments?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.invocationExpression_invokeType != null);
+ this.invocationExpression_invokeType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.classOrMixinDeclaration_members == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.classOrMixinDeclaration_members.length);
+ for (var x in this.classOrMixinDeclaration_members) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.mixinDeclaration_onClause != null);
+ this.mixinDeclaration_onClause?.collectApiSignature(signature);
+ signature.addBool(this.namedCompilationUnitMember_name != null);
+ this.namedCompilationUnitMember_name?.collectApiSignature(signature);
+ signature.addBool(this.classOrMixinDeclaration_implementsClause != null);
+ this
+ .classOrMixinDeclaration_implementsClause
+ ?.collectApiSignature(signature);
+ signature.addBool(this.classOrMixinDeclaration_typeParameters != null);
+ this
+ .classOrMixinDeclaration_typeParameters
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.simplyBoundable_isSimplyBounded == true);
+ if (this.mixinDeclaration_superInvokedNames == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.mixinDeclaration_superInvokedNames.length);
+ for (var x in this.mixinDeclaration_superInvokedNames) {
+ signature.addString(x);
+ }
+ }
+ } else if (kind == idl.LinkedNodeKind.namedExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.namedExpression_expression != null);
+ this.namedExpression_expression?.collectApiSignature(signature);
+ signature.addBool(this.namedExpression_name != null);
+ this.namedExpression_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.nativeClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.nativeClause_name != null);
+ this.nativeClause_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.nativeFunctionBody_stringLiteral != null);
+ this.nativeFunctionBody_stringLiteral?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.nullLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.nullLiteral_fake ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.onClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.onClause_superclassConstraints == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.onClause_superclassConstraints.length);
+ for (var x in this.onClause_superclassConstraints) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.parenthesizedExpression_expression != null);
+ this.parenthesizedExpression_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.partDirective) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.uriBasedDirective_uri != null);
+ this.uriBasedDirective_uri?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.uriBasedDirective_uriElement ?? 0);
+ signature.addString(this.uriBasedDirective_uriContent ?? '');
+ } else if (kind == idl.LinkedNodeKind.partOfDirective) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.partOfDirective_libraryName != null);
+ this.partOfDirective_libraryName?.collectApiSignature(signature);
+ signature.addBool(this.partOfDirective_uri != null);
+ this.partOfDirective_uri?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.postfixExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.postfixExpression_operand != null);
+ this.postfixExpression_operand?.collectApiSignature(signature);
+ signature.addInt(this.postfixExpression_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.postfixExpression_elementType != null);
+ this.postfixExpression_elementType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ signature.addInt(this.postfixExpression_operator == null
+ ? 0
+ : this.postfixExpression_operator.index);
+ } else if (kind == idl.LinkedNodeKind.prefixExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.prefixExpression_operand != null);
+ this.prefixExpression_operand?.collectApiSignature(signature);
+ signature.addInt(this.prefixExpression_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.prefixExpression_elementType != null);
+ this.prefixExpression_elementType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ signature.addInt(this.prefixExpression_operator == null
+ ? 0
+ : this.prefixExpression_operator.index);
+ } else if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.prefixedIdentifier_identifier != null);
+ this.prefixedIdentifier_identifier?.collectApiSignature(signature);
+ signature.addBool(this.prefixedIdentifier_prefix != null);
+ this.prefixedIdentifier_prefix?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.propertyAccess) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.propertyAccess_propertyName != null);
+ this.propertyAccess_propertyName?.collectApiSignature(signature);
+ signature.addBool(this.propertyAccess_target != null);
+ this.propertyAccess_target?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ signature.addInt(this.propertyAccess_operator == null
+ ? 0
+ : this.propertyAccess_operator.index);
+ } else if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature
+ .addBool(this.redirectingConstructorInvocation_arguments != null);
+ this
+ .redirectingConstructorInvocation_arguments
+ ?.collectApiSignature(signature);
+ signature.addBool(
+ this.redirectingConstructorInvocation_constructorName != null);
+ this
+ .redirectingConstructorInvocation_constructorName
+ ?.collectApiSignature(signature);
+ signature.addInt(this.redirectingConstructorInvocation_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature
+ .addBool(this.redirectingConstructorInvocation_elementType != null);
+ this
+ .redirectingConstructorInvocation_elementType
+ ?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.rethrowExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.returnStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.returnStatement_expression != null);
+ this.returnStatement_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.typedLiteral_typeArguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.typedLiteral_typeArguments.length);
+ for (var x in this.typedLiteral_typeArguments) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.setOrMapLiteral_elements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.setOrMapLiteral_elements.length);
+ for (var x in this.setOrMapLiteral_elements) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.showCombinator) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ if (this.names == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.names.length);
+ for (var x in this.names) {
+ signature.addString(x);
+ }
+ }
+ } else if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.normalFormalParameter_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.normalFormalParameter_metadata.length);
+ for (var x in this.normalFormalParameter_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.simpleFormalParameter_type != null);
+ this.simpleFormalParameter_type?.collectApiSignature(signature);
+ signature.addBool(this.normalFormalParameter_identifier != null);
+ this.normalFormalParameter_identifier?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualType != null);
+ this.actualType?.collectApiSignature(signature);
+ signature.addBool(this.inheritsCovariant == true);
+ signature.addBool(this.topLevelTypeInferenceError != null);
+ this.topLevelTypeInferenceError?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.simpleIdentifier_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addString(this.simpleIdentifier_name ?? '');
+ signature.addBool(this.simpleIdentifier_elementType != null);
+ this.simpleIdentifier_elementType?.collectApiSignature(signature);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addString(this.simpleStringLiteral_value ?? '');
+ } else if (kind == idl.LinkedNodeKind.spreadElement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.spreadElement_expression != null);
+ this.spreadElement_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addInt(this.spreadElement_spreadOperator == null
+ ? 0
+ : this.spreadElement_spreadOperator.index);
+ } else if (kind == idl.LinkedNodeKind.stringInterpolation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.stringInterpolation_elements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.stringInterpolation_elements.length);
+ for (var x in this.stringInterpolation_elements) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.superConstructorInvocation_arguments != null);
+ this.superConstructorInvocation_arguments?.collectApiSignature(signature);
+ signature
+ .addBool(this.superConstructorInvocation_constructorName != null);
+ this
+ .superConstructorInvocation_constructorName
+ ?.collectApiSignature(signature);
+ signature.addInt(this.superConstructorInvocation_element ?? 0);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.superConstructorInvocation_elementType != null);
+ this
+ .superConstructorInvocation_elementType
+ ?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.superExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.switchCase) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.switchMember_labels == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.switchMember_labels.length);
+ for (var x in this.switchMember_labels) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.switchMember_statements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.switchMember_statements.length);
+ for (var x in this.switchMember_statements) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.switchCase_expression != null);
+ this.switchCase_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.switchDefault) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.switchMember_labels == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.switchMember_labels.length);
+ for (var x in this.switchMember_labels) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.switchMember_statements == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.switchMember_statements.length);
+ for (var x in this.switchMember_statements) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.switchStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.switchStatement_members == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.switchStatement_members.length);
+ for (var x in this.switchStatement_members) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.switchStatement_expression != null);
+ this.switchStatement_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.symbolLiteral) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ if (this.names == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.names.length);
+ for (var x in this.names) {
+ signature.addString(x);
+ }
+ }
+ } else if (kind == idl.LinkedNodeKind.thisExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.throwExpression) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.throwExpression_expression != null);
+ this.throwExpression_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.expression_type != null);
+ this.expression_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.topLevelVariableDeclaration_variableList != null);
+ this
+ .topLevelVariableDeclaration_variableList
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.tryStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.tryStatement_catchClauses == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.tryStatement_catchClauses.length);
+ for (var x in this.tryStatement_catchClauses) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.tryStatement_body != null);
+ this.tryStatement_body?.collectApiSignature(signature);
+ signature.addBool(this.tryStatement_finallyBlock != null);
+ this.tryStatement_finallyBlock?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.typeArgumentList) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.typeArgumentList_arguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.typeArgumentList_arguments.length);
+ for (var x in this.typeArgumentList_arguments) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.typeName) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.typeName_typeArguments == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.typeName_typeArguments.length);
+ for (var x in this.typeName_typeArguments) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.typeName_name != null);
+ this.typeName_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.typeName_type != null);
+ this.typeName_type?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.typeParameter) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.typeParameter_bound != null);
+ this.typeParameter_bound?.collectApiSignature(signature);
+ signature.addBool(this.typeParameter_name != null);
+ this.typeParameter_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.typeParameter_defaultType != null);
+ this.typeParameter_defaultType?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.typeParameterList) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.typeParameterList_typeParameters == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.typeParameterList_typeParameters.length);
+ for (var x in this.typeParameterList_typeParameters) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.variableDeclaration) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.variableDeclaration_initializer != null);
+ this.variableDeclaration_initializer?.collectApiSignature(signature);
+ signature.addBool(this.variableDeclaration_name != null);
+ this.variableDeclaration_name?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ signature.addBool(this.actualType != null);
+ this.actualType?.collectApiSignature(signature);
+ signature.addBool(this.inheritsCovariant == true);
+ signature.addBool(this.topLevelTypeInferenceError != null);
+ this.topLevelTypeInferenceError?.collectApiSignature(signature);
+ } else if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.variableDeclarationList_variables == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.variableDeclarationList_variables.length);
+ for (var x in this.variableDeclarationList_variables) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this.annotatedNode_metadata == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.annotatedNode_metadata.length);
+ for (var x in this.annotatedNode_metadata) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addBool(this.variableDeclarationList_type != null);
+ this.variableDeclarationList_type?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.variableDeclarationStatement_variables != null);
+ this
+ .variableDeclarationStatement_variables
+ ?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.whileStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.whileStatement_body != null);
+ this.whileStatement_body?.collectApiSignature(signature);
+ signature.addBool(this.whileStatement_condition != null);
+ this.whileStatement_condition?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.withClause) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ if (this.withClause_mixinTypes == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this.withClause_mixinTypes.length);
+ for (var x in this.withClause_mixinTypes) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ signature.addInt(this.flags ?? 0);
+ } else if (kind == idl.LinkedNodeKind.yieldStatement) {
+ signature.addInt(this.kind == null ? 0 : this.kind.index);
+ signature.addBool(this.yieldStatement_expression != null);
+ this.yieldStatement_expression?.collectApiSignature(signature);
+ signature.addInt(this.flags ?? 0);
}
- signature.addString(this._name ?? '');
- signature.addInt(
- this._variantField_38 == null ? 0 : this._variantField_38.index);
}
fb.Offset finish(fb.Builder fbBuilder) {
@@ -9125,18 +11056,17 @@
fb.Offset offset_variantField_12;
fb.Offset offset_variantField_5;
fb.Offset offset_variantField_13;
- fb.Offset offset_variantField_36;
+ fb.Offset offset_variantField_35;
fb.Offset offset_variantField_3;
fb.Offset offset_variantField_10;
fb.Offset offset_variantField_25;
fb.Offset offset_variantField_1;
fb.Offset offset_variantField_30;
fb.Offset offset_variantField_14;
- fb.Offset offset_name;
+ fb.Offset offset_variantField_36;
fb.Offset offset_variantField_20;
- fb.Offset offset_variantField_35;
+ fb.Offset offset_variantField_34;
fb.Offset offset_variantField_22;
- fb.Offset offset_variantField_32;
if (_variantField_24 != null) {
offset_variantField_24 = _variantField_24.finish(fbBuilder);
}
@@ -9176,9 +11106,9 @@
if (_variantField_13 != null) {
offset_variantField_13 = _variantField_13.finish(fbBuilder);
}
- if (!(_variantField_36 == null || _variantField_36.isEmpty)) {
- offset_variantField_36 = fbBuilder.writeList(
- _variantField_36.map((b) => fbBuilder.writeString(b)).toList());
+ if (!(_variantField_35 == null || _variantField_35.isEmpty)) {
+ offset_variantField_35 = fbBuilder.writeList(
+ _variantField_35.map((b) => fbBuilder.writeString(b)).toList());
}
if (!(_variantField_3 == null || _variantField_3.isEmpty)) {
offset_variantField_3 = fbBuilder
@@ -9199,21 +11129,19 @@
if (_variantField_14 != null) {
offset_variantField_14 = _variantField_14.finish(fbBuilder);
}
- if (_name != null) {
- offset_name = fbBuilder.writeString(_name);
+ if (!(_variantField_36 == null || _variantField_36.isEmpty)) {
+ offset_variantField_36 = fbBuilder.writeList(
+ _variantField_36.map((b) => fbBuilder.writeString(b)).toList());
}
if (_variantField_20 != null) {
offset_variantField_20 = fbBuilder.writeString(_variantField_20);
}
- if (_variantField_35 != null) {
- offset_variantField_35 = _variantField_35.finish(fbBuilder);
+ if (_variantField_34 != null) {
+ offset_variantField_34 = _variantField_34.finish(fbBuilder);
}
if (_variantField_22 != null) {
offset_variantField_22 = fbBuilder.writeString(_variantField_22);
}
- if (_variantField_32 != null) {
- offset_variantField_32 = _variantField_32.finish(fbBuilder);
- }
fbBuilder.startTable();
if (offset_variantField_24 != null) {
fbBuilder.addOffset(24, offset_variantField_24);
@@ -9264,14 +11192,14 @@
if (offset_variantField_13 != null) {
fbBuilder.addOffset(13, offset_variantField_13);
}
- if (_variantField_34 != null && _variantField_34 != 0) {
- fbBuilder.addUint32(34, _variantField_34);
- }
if (_variantField_33 != null && _variantField_33 != 0) {
fbBuilder.addUint32(33, _variantField_33);
}
- if (offset_variantField_36 != null) {
- fbBuilder.addOffset(36, offset_variantField_36);
+ if (_variantField_32 != null && _variantField_32 != 0) {
+ fbBuilder.addUint32(32, _variantField_32);
+ }
+ if (offset_variantField_35 != null) {
+ fbBuilder.addOffset(35, offset_variantField_35);
}
if (_variantField_29 != null &&
_variantField_29 != idl.LinkedNodeCommentType.block) {
@@ -9280,6 +11208,9 @@
if (offset_variantField_3 != null) {
fbBuilder.addOffset(3, offset_variantField_3);
}
+ if (_variantField_19 != null && _variantField_19 != 0) {
+ fbBuilder.addUint32(19, _variantField_19);
+ }
if (offset_variantField_10 != null) {
fbBuilder.addOffset(10, offset_variantField_10);
}
@@ -9312,8 +11243,8 @@
if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
fbBuilder.addUint8(0, _kind.index);
}
- if (offset_name != null) {
- fbBuilder.addOffset(37, offset_name);
+ if (offset_variantField_36 != null) {
+ fbBuilder.addOffset(36, offset_variantField_36);
}
if (offset_variantField_20 != null) {
fbBuilder.addOffset(20, offset_variantField_20);
@@ -9321,22 +11252,16 @@
if (_variantField_31 == true) {
fbBuilder.addBool(31, true);
}
- if (_variantField_38 != null &&
- _variantField_38 != idl.UnlinkedTokenType.NOTHING) {
- fbBuilder.addUint8(38, _variantField_38.index);
+ if (_variantField_37 != null &&
+ _variantField_37 != idl.UnlinkedTokenType.NOTHING) {
+ fbBuilder.addUint8(37, _variantField_37.index);
}
- if (offset_variantField_35 != null) {
- fbBuilder.addOffset(35, offset_variantField_35);
+ if (offset_variantField_34 != null) {
+ fbBuilder.addOffset(34, offset_variantField_34);
}
if (offset_variantField_22 != null) {
fbBuilder.addOffset(22, offset_variantField_22);
}
- if (_variantField_19 != null && _variantField_19 != 0) {
- fbBuilder.addUint32(19, _variantField_19);
- }
- if (offset_variantField_32 != null) {
- fbBuilder.addOffset(32, offset_variantField_32);
- }
return fbBuilder.endTable();
}
}
@@ -9373,11 +11298,12 @@
idl.LinkedNode _variantField_12;
List<idl.LinkedNode> _variantField_5;
idl.LinkedNode _variantField_13;
- int _variantField_34;
int _variantField_33;
- List<String> _variantField_36;
+ int _variantField_32;
+ List<String> _variantField_35;
idl.LinkedNodeCommentType _variantField_29;
List<idl.LinkedNode> _variantField_3;
+ int _variantField_19;
idl.LinkedNode _variantField_10;
idl.LinkedNodeFormalParameterKind _variantField_26;
double _variantField_21;
@@ -9388,14 +11314,12 @@
String _variantField_30;
idl.LinkedNode _variantField_14;
idl.LinkedNodeKind _kind;
- String _name;
+ List<String> _variantField_36;
String _variantField_20;
bool _variantField_31;
- idl.UnlinkedTokenType _variantField_38;
- idl.TopLevelInferenceError _variantField_35;
+ idl.UnlinkedTokenType _variantField_37;
+ idl.TopLevelInferenceError _variantField_34;
String _variantField_22;
- int _variantField_19;
- idl.LinkedNodeVariablesDeclaration _variantField_32;
@override
idl.LinkedNodeType get actualReturnType {
@@ -9935,6 +11859,14 @@
}
@override
+ idl.LinkedNode get enumConstantDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.enumConstantDeclaration);
+ _variantField_6 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 6, null);
+ return _variantField_6;
+ }
+
+ @override
idl.LinkedNode get expressionFunctionBody_expression {
assert(kind == idl.LinkedNodeKind.expressionFunctionBody);
_variantField_6 ??=
@@ -10443,6 +12375,14 @@
}
@override
+ idl.LinkedNode get constructorDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ _variantField_7 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+ return _variantField_7;
+ }
+
+ @override
idl.LinkedNode get constructorFieldInitializer_fieldName {
assert(kind == idl.LinkedNodeKind.constructorFieldInitializer);
_variantField_7 ??=
@@ -10707,6 +12647,22 @@
}
@override
+ idl.LinkedNode get typeParameter_name {
+ assert(kind == idl.LinkedNodeKind.typeParameter);
+ _variantField_7 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+ return _variantField_7;
+ }
+
+ @override
+ idl.LinkedNode get variableDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.variableDeclaration);
+ _variantField_7 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 7, null);
+ return _variantField_7;
+ }
+
+ @override
idl.LinkedNode get whileStatement_condition {
assert(kind == idl.LinkedNodeKind.whileStatement);
_variantField_7 ??=
@@ -10723,6 +12679,18 @@
}
@override
+ int get directive_keywordOffset {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.libraryDirective ||
+ kind == idl.LinkedNodeKind.partDirective ||
+ kind == idl.LinkedNodeKind.partOfDirective);
+ _variantField_17 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 17, 0);
+ return _variantField_17;
+ }
+
+ @override
int get genericFunctionType_id {
assert(kind == idl.LinkedNodeKind.genericFunctionType);
_variantField_17 ??=
@@ -11175,6 +13143,16 @@
}
@override
+ idl.LinkedNode get normalFormalParameter_identifier {
+ assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+ kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+ kind == idl.LinkedNodeKind.simpleFormalParameter);
+ _variantField_9 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 9, null);
+ return _variantField_9;
+ }
+
+ @override
idl.LinkedNode get classOrMixinDeclaration_implementsClause {
assert(kind == idl.LinkedNodeKind.classDeclaration ||
kind == idl.LinkedNodeKind.mixinDeclaration);
@@ -11239,9 +13217,9 @@
kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.typeParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_34 ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 34, 0);
- return _variantField_34;
+ _variantField_33 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
+ return _variantField_33;
}
@override
@@ -11262,35 +13240,17 @@
kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.typeParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_33 ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 33, 0);
- return _variantField_33;
+ _variantField_32 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 32, 0);
+ return _variantField_32;
}
@override
List<String> get comment_tokens {
assert(kind == idl.LinkedNodeKind.comment);
- _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 36, const <String>[]);
- return _variantField_36;
- }
-
- @override
- List<String> get mixinDeclaration_superInvokedNames {
- assert(kind == idl.LinkedNodeKind.mixinDeclaration);
- _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 36, const <String>[]);
- return _variantField_36;
- }
-
- @override
- List<String> get names {
- assert(kind == idl.LinkedNodeKind.hideCombinator ||
- kind == idl.LinkedNodeKind.showCombinator ||
- kind == idl.LinkedNodeKind.symbolLiteral);
- _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
- .vTableGet(_bc, _bcOffset, 36, const <String>[]);
- return _variantField_36;
+ _variantField_35 ??= const fb.ListReader<String>(const fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 35, const <String>[]);
+ return _variantField_35;
}
@override
@@ -11349,6 +13309,24 @@
}
@override
+ int get constructorDeclaration_periodOffset {
+ assert(kind == idl.LinkedNodeKind.constructorDeclaration);
+ _variantField_19 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+ return _variantField_19;
+ }
+
+ @override
+ int get uriBasedDirective_uriElement {
+ assert(kind == idl.LinkedNodeKind.exportDirective ||
+ kind == idl.LinkedNodeKind.importDirective ||
+ kind == idl.LinkedNodeKind.partDirective);
+ _variantField_19 ??=
+ const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
+ return _variantField_19;
+ }
+
+ @override
idl.LinkedNode get constructorDeclaration_returnType {
assert(kind == idl.LinkedNodeKind.constructorDeclaration);
_variantField_10 ??=
@@ -11357,6 +13335,28 @@
}
@override
+ idl.LinkedNode get methodDeclaration_name {
+ assert(kind == idl.LinkedNodeKind.methodDeclaration);
+ _variantField_10 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 10, null);
+ return _variantField_10;
+ }
+
+ @override
+ idl.LinkedNode get namedCompilationUnitMember_name {
+ assert(kind == idl.LinkedNodeKind.classDeclaration ||
+ kind == idl.LinkedNodeKind.classTypeAlias ||
+ kind == idl.LinkedNodeKind.enumDeclaration ||
+ kind == idl.LinkedNodeKind.functionDeclaration ||
+ kind == idl.LinkedNodeKind.functionTypeAlias ||
+ kind == idl.LinkedNodeKind.genericTypeAlias ||
+ kind == idl.LinkedNodeKind.mixinDeclaration);
+ _variantField_10 ??=
+ const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 10, null);
+ return _variantField_10;
+ }
+
+ @override
idl.LinkedNodeFormalParameterKind get defaultFormalParameter_kind {
assert(kind == idl.LinkedNodeKind.defaultFormalParameter);
_variantField_26 ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
@@ -11437,25 +13437,8 @@
}
@override
- int get nameOffset {
- assert(kind == idl.LinkedNodeKind.classDeclaration ||
- kind == idl.LinkedNodeKind.classTypeAlias ||
- kind == idl.LinkedNodeKind.constructorDeclaration ||
- kind == idl.LinkedNodeKind.enumConstantDeclaration ||
- kind == idl.LinkedNodeKind.enumDeclaration ||
- kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.fieldFormalParameter ||
- kind == idl.LinkedNodeKind.functionDeclaration ||
- kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
- kind == idl.LinkedNodeKind.functionTypeAlias ||
- kind == idl.LinkedNodeKind.genericTypeAlias ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.methodDeclaration ||
- kind == idl.LinkedNodeKind.mixinDeclaration ||
- kind == idl.LinkedNodeKind.partDirective ||
- kind == idl.LinkedNodeKind.simpleFormalParameter ||
- kind == idl.LinkedNodeKind.typeParameter ||
- kind == idl.LinkedNodeKind.variableDeclaration);
+ int get simpleIdentifier_offset {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
_variantField_16 ??=
const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
return _variantField_16;
@@ -11506,9 +13489,21 @@
}
@override
- String get name {
- _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 37, '');
- return _name;
+ List<String> get mixinDeclaration_superInvokedNames {
+ assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+ _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 36, const <String>[]);
+ return _variantField_36;
+ }
+
+ @override
+ List<String> get names {
+ assert(kind == idl.LinkedNodeKind.hideCombinator ||
+ kind == idl.LinkedNodeKind.showCombinator ||
+ kind == idl.LinkedNodeKind.symbolLiteral);
+ _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
+ .vTableGet(_bc, _bcOffset, 36, const <String>[]);
+ return _variantField_36;
}
@override
@@ -11521,6 +13516,14 @@
}
@override
+ String get simpleIdentifier_name {
+ assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+ _variantField_20 ??=
+ const fb.StringReader().vTableGet(_bc, _bcOffset, 20, '');
+ return _variantField_20;
+ }
+
+ @override
String get simpleStringLiteral_value {
assert(kind == idl.LinkedNodeKind.simpleStringLiteral);
_variantField_20 ??=
@@ -11543,18 +13546,18 @@
@override
idl.UnlinkedTokenType get spreadElement_spreadOperator {
assert(kind == idl.LinkedNodeKind.spreadElement);
- _variantField_38 ??= const _UnlinkedTokenTypeReader()
- .vTableGet(_bc, _bcOffset, 38, idl.UnlinkedTokenType.NOTHING);
- return _variantField_38;
+ _variantField_37 ??= const _UnlinkedTokenTypeReader()
+ .vTableGet(_bc, _bcOffset, 37, idl.UnlinkedTokenType.NOTHING);
+ return _variantField_37;
}
@override
idl.TopLevelInferenceError get topLevelTypeInferenceError {
assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_35 ??= const _TopLevelInferenceErrorReader()
- .vTableGet(_bc, _bcOffset, 35, null);
- return _variantField_35;
+ _variantField_34 ??= const _TopLevelInferenceErrorReader()
+ .vTableGet(_bc, _bcOffset, 34, null);
+ return _variantField_34;
}
@override
@@ -11566,24 +13569,6 @@
const fb.StringReader().vTableGet(_bc, _bcOffset, 22, '');
return _variantField_22;
}
-
- @override
- int get uriBasedDirective_uriElement {
- assert(kind == idl.LinkedNodeKind.exportDirective ||
- kind == idl.LinkedNodeKind.importDirective ||
- kind == idl.LinkedNodeKind.partDirective);
- _variantField_19 ??=
- const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 19, 0);
- return _variantField_19;
- }
-
- @override
- idl.LinkedNodeVariablesDeclaration get variableDeclaration_declaration {
- assert(kind == idl.LinkedNodeKind.variableDeclaration);
- _variantField_32 ??= const _LinkedNodeVariablesDeclarationReader()
- .vTableGet(_bc, _bcOffset, 32, null);
- return _variantField_32;
- }
}
abstract class _LinkedNodeMixin implements idl.LinkedNode {
@@ -11593,759 +13578,11 @@
if (flags != 0) _result["flags"] = flags;
if (kind != idl.LinkedNodeKind.adjacentStrings)
_result["kind"] = kind.toString().split('.')[1];
- if (name != '') _result["name"] = name;
- if (kind == idl.LinkedNodeKind.functionDeclaration) {
- if (actualReturnType != null)
- _result["actualReturnType"] = actualReturnType.toJson();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (functionDeclaration_functionExpression != null)
- _result["functionDeclaration_functionExpression"] =
- functionDeclaration_functionExpression.toJson();
- if (functionDeclaration_returnType != null)
- _result["functionDeclaration_returnType"] =
- functionDeclaration_returnType.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.functionExpression) {
- if (actualReturnType != null)
- _result["actualReturnType"] = actualReturnType.toJson();
- if (functionExpression_body != null)
- _result["functionExpression_body"] = functionExpression_body.toJson();
- if (functionExpression_formalParameters != null)
- _result["functionExpression_formalParameters"] =
- functionExpression_formalParameters.toJson();
- if (functionExpression_typeParameters != null)
- _result["functionExpression_typeParameters"] =
- functionExpression_typeParameters.toJson();
- }
- if (kind == idl.LinkedNodeKind.functionTypeAlias) {
- if (actualReturnType != null)
- _result["actualReturnType"] = actualReturnType.toJson();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (functionTypeAlias_formalParameters != null)
- _result["functionTypeAlias_formalParameters"] =
- functionTypeAlias_formalParameters.toJson();
- if (functionTypeAlias_returnType != null)
- _result["functionTypeAlias_returnType"] =
- functionTypeAlias_returnType.toJson();
- if (functionTypeAlias_typeParameters != null)
- _result["functionTypeAlias_typeParameters"] =
- functionTypeAlias_typeParameters.toJson();
- if (typeAlias_hasSelfReference != false)
- _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (simplyBoundable_isSimplyBounded != false)
- _result["simplyBoundable_isSimplyBounded"] =
- simplyBoundable_isSimplyBounded;
- }
- if (kind == idl.LinkedNodeKind.genericFunctionType) {
- if (actualReturnType != null)
- _result["actualReturnType"] = actualReturnType.toJson();
- if (genericFunctionType_typeParameters != null)
- _result["genericFunctionType_typeParameters"] =
- genericFunctionType_typeParameters.toJson();
- if (genericFunctionType_returnType != null)
- _result["genericFunctionType_returnType"] =
- genericFunctionType_returnType.toJson();
- if (genericFunctionType_id != 0)
- _result["genericFunctionType_id"] = genericFunctionType_id;
- if (genericFunctionType_formalParameters != null)
- _result["genericFunctionType_formalParameters"] =
- genericFunctionType_formalParameters.toJson();
- if (genericFunctionType_type != null)
- _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.methodDeclaration) {
- if (actualReturnType != null)
- _result["actualReturnType"] = actualReturnType.toJson();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (methodDeclaration_body != null)
- _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
- if (methodDeclaration_formalParameters != null)
- _result["methodDeclaration_formalParameters"] =
- methodDeclaration_formalParameters.toJson();
- if (methodDeclaration_returnType != null)
- _result["methodDeclaration_returnType"] =
- methodDeclaration_returnType.toJson();
- if (methodDeclaration_typeParameters != null)
- _result["methodDeclaration_typeParameters"] =
- methodDeclaration_typeParameters.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
- if (actualType != null) _result["actualType"] = actualType.toJson();
- if (normalFormalParameter_metadata.isNotEmpty)
- _result["normalFormalParameter_metadata"] =
- normalFormalParameter_metadata
- .map((_value) => _value.toJson())
- .toList();
- if (fieldFormalParameter_type != null)
- _result["fieldFormalParameter_type"] =
- fieldFormalParameter_type.toJson();
- if (fieldFormalParameter_typeParameters != null)
- _result["fieldFormalParameter_typeParameters"] =
- fieldFormalParameter_typeParameters.toJson();
- if (fieldFormalParameter_formalParameters != null)
- _result["fieldFormalParameter_formalParameters"] =
- fieldFormalParameter_formalParameters.toJson();
- if (inheritsCovariant != false)
- _result["inheritsCovariant"] = inheritsCovariant;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (normalFormalParameter_comment != null)
- _result["normalFormalParameter_comment"] =
- normalFormalParameter_comment.toJson();
- }
- if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
- if (actualType != null) _result["actualType"] = actualType.toJson();
- if (normalFormalParameter_metadata.isNotEmpty)
- _result["normalFormalParameter_metadata"] =
- normalFormalParameter_metadata
- .map((_value) => _value.toJson())
- .toList();
- if (functionTypedFormalParameter_formalParameters != null)
- _result["functionTypedFormalParameter_formalParameters"] =
- functionTypedFormalParameter_formalParameters.toJson();
- if (functionTypedFormalParameter_returnType != null)
- _result["functionTypedFormalParameter_returnType"] =
- functionTypedFormalParameter_returnType.toJson();
- if (functionTypedFormalParameter_typeParameters != null)
- _result["functionTypedFormalParameter_typeParameters"] =
- functionTypedFormalParameter_typeParameters.toJson();
- if (inheritsCovariant != false)
- _result["inheritsCovariant"] = inheritsCovariant;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (normalFormalParameter_comment != null)
- _result["normalFormalParameter_comment"] =
- normalFormalParameter_comment.toJson();
- }
- if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
- if (actualType != null) _result["actualType"] = actualType.toJson();
- if (normalFormalParameter_metadata.isNotEmpty)
- _result["normalFormalParameter_metadata"] =
- normalFormalParameter_metadata
- .map((_value) => _value.toJson())
- .toList();
- if (simpleFormalParameter_type != null)
- _result["simpleFormalParameter_type"] =
- simpleFormalParameter_type.toJson();
- if (inheritsCovariant != false)
- _result["inheritsCovariant"] = inheritsCovariant;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (normalFormalParameter_comment != null)
- _result["normalFormalParameter_comment"] =
- normalFormalParameter_comment.toJson();
- if (topLevelTypeInferenceError != null)
- _result["topLevelTypeInferenceError"] =
- topLevelTypeInferenceError.toJson();
- }
- if (kind == idl.LinkedNodeKind.variableDeclaration) {
- if (actualType != null) _result["actualType"] = actualType.toJson();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (variableDeclaration_initializer != null)
- _result["variableDeclaration_initializer"] =
- variableDeclaration_initializer.toJson();
- if (inheritsCovariant != false)
- _result["inheritsCovariant"] = inheritsCovariant;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (topLevelTypeInferenceError != null)
- _result["topLevelTypeInferenceError"] =
- topLevelTypeInferenceError.toJson();
- if (variableDeclaration_declaration != null)
- _result["variableDeclaration_declaration"] =
- variableDeclaration_declaration.toJson();
- }
- if (kind == idl.LinkedNodeKind.binaryExpression) {
- if (binaryExpression_invokeType != null)
- _result["binaryExpression_invokeType"] =
- binaryExpression_invokeType.toJson();
- if (binaryExpression_leftOperand != null)
- _result["binaryExpression_leftOperand"] =
- binaryExpression_leftOperand.toJson();
- if (binaryExpression_rightOperand != null)
- _result["binaryExpression_rightOperand"] =
- binaryExpression_rightOperand.toJson();
- if (binaryExpression_elementType != null)
- _result["binaryExpression_elementType"] =
- binaryExpression_elementType.toJson();
- if (binaryExpression_element != 0)
- _result["binaryExpression_element"] = binaryExpression_element;
- if (binaryExpression_operator != idl.UnlinkedTokenType.NOTHING)
- _result["binaryExpression_operator"] =
- binaryExpression_operator.toString().split('.')[1];
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
- if (invocationExpression_invokeType != null)
- _result["invocationExpression_invokeType"] =
- invocationExpression_invokeType.toJson();
- if (functionExpressionInvocation_function != null)
- _result["functionExpressionInvocation_function"] =
- functionExpressionInvocation_function.toJson();
- if (invocationExpression_typeArguments != null)
- _result["invocationExpression_typeArguments"] =
- invocationExpression_typeArguments.toJson();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- if (invocationExpression_arguments != null)
- _result["invocationExpression_arguments"] =
- invocationExpression_arguments.toJson();
- }
- if (kind == idl.LinkedNodeKind.methodInvocation) {
- if (invocationExpression_invokeType != null)
- _result["invocationExpression_invokeType"] =
- invocationExpression_invokeType.toJson();
- if (methodInvocation_methodName != null)
- _result["methodInvocation_methodName"] =
- methodInvocation_methodName.toJson();
- if (methodInvocation_target != null)
- _result["methodInvocation_target"] = methodInvocation_target.toJson();
- if (invocationExpression_typeArguments != null)
- _result["invocationExpression_typeArguments"] =
- invocationExpression_typeArguments.toJson();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- if (invocationExpression_arguments != null)
- _result["invocationExpression_arguments"] =
- invocationExpression_arguments.toJson();
- }
if (kind == idl.LinkedNodeKind.adjacentStrings) {
if (adjacentStrings_strings.isNotEmpty)
_result["adjacentStrings_strings"] =
adjacentStrings_strings.map((_value) => _value.toJson()).toList();
}
- if (kind == idl.LinkedNodeKind.argumentList) {
- if (argumentList_arguments.isNotEmpty)
- _result["argumentList_arguments"] =
- argumentList_arguments.map((_value) => _value.toJson()).toList();
- }
- if (kind == idl.LinkedNodeKind.block) {
- if (block_statements.isNotEmpty)
- _result["block_statements"] =
- block_statements.map((_value) => _value.toJson()).toList();
- }
- if (kind == idl.LinkedNodeKind.cascadeExpression) {
- if (cascadeExpression_sections.isNotEmpty)
- _result["cascadeExpression_sections"] = cascadeExpression_sections
- .map((_value) => _value.toJson())
- .toList();
- if (cascadeExpression_target != null)
- _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.comment) {
- if (comment_references.isNotEmpty)
- _result["comment_references"] =
- comment_references.map((_value) => _value.toJson()).toList();
- if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
- if (comment_type != idl.LinkedNodeCommentType.block)
- _result["comment_type"] = comment_type.toString().split('.')[1];
- }
- if (kind == idl.LinkedNodeKind.compilationUnit) {
- if (compilationUnit_declarations.isNotEmpty)
- _result["compilationUnit_declarations"] = compilationUnit_declarations
- .map((_value) => _value.toJson())
- .toList();
- if (compilationUnit_scriptTag != null)
- _result["compilationUnit_scriptTag"] =
- compilationUnit_scriptTag.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (compilationUnit_directives.isNotEmpty)
- _result["compilationUnit_directives"] = compilationUnit_directives
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.constructorDeclaration) {
- if (constructorDeclaration_initializers.isNotEmpty)
- _result["constructorDeclaration_initializers"] =
- constructorDeclaration_initializers
- .map((_value) => _value.toJson())
- .toList();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (constructorDeclaration_body != null)
- _result["constructorDeclaration_body"] =
- constructorDeclaration_body.toJson();
- if (constructorDeclaration_parameters != null)
- _result["constructorDeclaration_parameters"] =
- constructorDeclaration_parameters.toJson();
- if (constructorDeclaration_redirectedConstructor != null)
- _result["constructorDeclaration_redirectedConstructor"] =
- constructorDeclaration_redirectedConstructor.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (constructorDeclaration_returnType != null)
- _result["constructorDeclaration_returnType"] =
- constructorDeclaration_returnType.toJson();
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.dottedName) {
- if (dottedName_components.isNotEmpty)
- _result["dottedName_components"] =
- dottedName_components.map((_value) => _value.toJson()).toList();
- }
- if (kind == idl.LinkedNodeKind.enumDeclaration) {
- if (enumDeclaration_constants.isNotEmpty)
- _result["enumDeclaration_constants"] =
- enumDeclaration_constants.map((_value) => _value.toJson()).toList();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.formalParameterList) {
- if (formalParameterList_parameters.isNotEmpty)
- _result["formalParameterList_parameters"] =
- formalParameterList_parameters
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.implementsClause) {
- if (implementsClause_interfaces.isNotEmpty)
- _result["implementsClause_interfaces"] = implementsClause_interfaces
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
- if (instanceCreationExpression_arguments.isNotEmpty)
- _result["instanceCreationExpression_arguments"] =
- instanceCreationExpression_arguments
- .map((_value) => _value.toJson())
- .toList();
- if (instanceCreationExpression_constructorName != null)
- _result["instanceCreationExpression_constructorName"] =
- instanceCreationExpression_constructorName.toJson();
- if (instanceCreationExpression_typeArguments != null)
- _result["instanceCreationExpression_typeArguments"] =
- instanceCreationExpression_typeArguments.toJson();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.labeledStatement) {
- if (labeledStatement_labels.isNotEmpty)
- _result["labeledStatement_labels"] =
- labeledStatement_labels.map((_value) => _value.toJson()).toList();
- if (labeledStatement_statement != null)
- _result["labeledStatement_statement"] =
- labeledStatement_statement.toJson();
- }
- if (kind == idl.LinkedNodeKind.libraryIdentifier) {
- if (libraryIdentifier_components.isNotEmpty)
- _result["libraryIdentifier_components"] = libraryIdentifier_components
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.exportDirective) {
- if (namespaceDirective_combinators.isNotEmpty)
- _result["namespaceDirective_combinators"] =
- namespaceDirective_combinators
- .map((_value) => _value.toJson())
- .toList();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (namespaceDirective_configurations.isNotEmpty)
- _result["namespaceDirective_configurations"] =
- namespaceDirective_configurations
- .map((_value) => _value.toJson())
- .toList();
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (uriBasedDirective_uri != null)
- _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
- if (namespaceDirective_selectedUri != '')
- _result["namespaceDirective_selectedUri"] =
- namespaceDirective_selectedUri;
- if (uriBasedDirective_uriContent != '')
- _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
- if (uriBasedDirective_uriElement != 0)
- _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
- }
- if (kind == idl.LinkedNodeKind.importDirective) {
- if (namespaceDirective_combinators.isNotEmpty)
- _result["namespaceDirective_combinators"] =
- namespaceDirective_combinators
- .map((_value) => _value.toJson())
- .toList();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (importDirective_prefixOffset != 0)
- _result["importDirective_prefixOffset"] = importDirective_prefixOffset;
- if (namespaceDirective_configurations.isNotEmpty)
- _result["namespaceDirective_configurations"] =
- namespaceDirective_configurations
- .map((_value) => _value.toJson())
- .toList();
- if (importDirective_prefix != '')
- _result["importDirective_prefix"] = importDirective_prefix;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (uriBasedDirective_uri != null)
- _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
- if (namespaceDirective_selectedUri != '')
- _result["namespaceDirective_selectedUri"] =
- namespaceDirective_selectedUri;
- if (uriBasedDirective_uriContent != '')
- _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
- if (uriBasedDirective_uriElement != 0)
- _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
- }
- if (kind == idl.LinkedNodeKind.onClause) {
- if (onClause_superclassConstraints.isNotEmpty)
- _result["onClause_superclassConstraints"] =
- onClause_superclassConstraints
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.stringInterpolation) {
- if (stringInterpolation_elements.isNotEmpty)
- _result["stringInterpolation_elements"] = stringInterpolation_elements
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.switchStatement) {
- if (switchStatement_members.isNotEmpty)
- _result["switchStatement_members"] =
- switchStatement_members.map((_value) => _value.toJson()).toList();
- if (switchStatement_expression != null)
- _result["switchStatement_expression"] =
- switchStatement_expression.toJson();
- }
- if (kind == idl.LinkedNodeKind.tryStatement) {
- if (tryStatement_catchClauses.isNotEmpty)
- _result["tryStatement_catchClauses"] =
- tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
- if (tryStatement_body != null)
- _result["tryStatement_body"] = tryStatement_body.toJson();
- if (tryStatement_finallyBlock != null)
- _result["tryStatement_finallyBlock"] =
- tryStatement_finallyBlock.toJson();
- }
- if (kind == idl.LinkedNodeKind.typeArgumentList) {
- if (typeArgumentList_arguments.isNotEmpty)
- _result["typeArgumentList_arguments"] = typeArgumentList_arguments
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.listLiteral) {
- if (typedLiteral_typeArguments.isNotEmpty)
- _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
- .map((_value) => _value.toJson())
- .toList();
- if (listLiteral_elements.isNotEmpty)
- _result["listLiteral_elements"] =
- listLiteral_elements.map((_value) => _value.toJson()).toList();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
- if (typedLiteral_typeArguments.isNotEmpty)
- _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
- .map((_value) => _value.toJson())
- .toList();
- if (setOrMapLiteral_elements.isNotEmpty)
- _result["setOrMapLiteral_elements"] =
- setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.typeName) {
- if (typeName_typeArguments.isNotEmpty)
- _result["typeName_typeArguments"] =
- typeName_typeArguments.map((_value) => _value.toJson()).toList();
- if (typeName_name != null)
- _result["typeName_name"] = typeName_name.toJson();
- if (typeName_type != null)
- _result["typeName_type"] = typeName_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.typeParameterList) {
- if (typeParameterList_typeParameters.isNotEmpty)
- _result["typeParameterList_typeParameters"] =
- typeParameterList_typeParameters
- .map((_value) => _value.toJson())
- .toList();
- }
- if (kind == idl.LinkedNodeKind.variableDeclarationList) {
- if (variableDeclarationList_variables.isNotEmpty)
- _result["variableDeclarationList_variables"] =
- variableDeclarationList_variables
- .map((_value) => _value.toJson())
- .toList();
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (variableDeclarationList_type != null)
- _result["variableDeclarationList_type"] =
- variableDeclarationList_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.withClause) {
- if (withClause_mixinTypes.isNotEmpty)
- _result["withClause_mixinTypes"] =
- withClause_mixinTypes.map((_value) => _value.toJson()).toList();
- }
- if (kind == idl.LinkedNodeKind.classDeclaration) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (classDeclaration_extendsClause != null)
- _result["classDeclaration_extendsClause"] =
- classDeclaration_extendsClause.toJson();
- if (classDeclaration_withClause != null)
- _result["classDeclaration_withClause"] =
- classDeclaration_withClause.toJson();
- if (classDeclaration_nativeClause != null)
- _result["classDeclaration_nativeClause"] =
- classDeclaration_nativeClause.toJson();
- if (classDeclaration_isDartObject != false)
- _result["classDeclaration_isDartObject"] =
- classDeclaration_isDartObject;
- if (classOrMixinDeclaration_implementsClause != null)
- _result["classOrMixinDeclaration_implementsClause"] =
- classOrMixinDeclaration_implementsClause.toJson();
- if (classOrMixinDeclaration_members.isNotEmpty)
- _result["classOrMixinDeclaration_members"] =
- classOrMixinDeclaration_members
- .map((_value) => _value.toJson())
- .toList();
- if (classOrMixinDeclaration_typeParameters != null)
- _result["classOrMixinDeclaration_typeParameters"] =
- classOrMixinDeclaration_typeParameters.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (simplyBoundable_isSimplyBounded != false)
- _result["simplyBoundable_isSimplyBounded"] =
- simplyBoundable_isSimplyBounded;
- }
- if (kind == idl.LinkedNodeKind.classTypeAlias) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (classTypeAlias_typeParameters != null)
- _result["classTypeAlias_typeParameters"] =
- classTypeAlias_typeParameters.toJson();
- if (classTypeAlias_superclass != null)
- _result["classTypeAlias_superclass"] =
- classTypeAlias_superclass.toJson();
- if (classTypeAlias_withClause != null)
- _result["classTypeAlias_withClause"] =
- classTypeAlias_withClause.toJson();
- if (classTypeAlias_implementsClause != null)
- _result["classTypeAlias_implementsClause"] =
- classTypeAlias_implementsClause.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (simplyBoundable_isSimplyBounded != false)
- _result["simplyBoundable_isSimplyBounded"] =
- simplyBoundable_isSimplyBounded;
- }
- if (kind == idl.LinkedNodeKind.declaredIdentifier) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (declaredIdentifier_identifier != null)
- _result["declaredIdentifier_identifier"] =
- declaredIdentifier_identifier.toJson();
- if (declaredIdentifier_type != null)
- _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.fieldDeclaration) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (fieldDeclaration_fields != null)
- _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
- }
- if (kind == idl.LinkedNodeKind.genericTypeAlias) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (genericTypeAlias_typeParameters != null)
- _result["genericTypeAlias_typeParameters"] =
- genericTypeAlias_typeParameters.toJson();
- if (genericTypeAlias_functionType != null)
- _result["genericTypeAlias_functionType"] =
- genericTypeAlias_functionType.toJson();
- if (typeAlias_hasSelfReference != false)
- _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (simplyBoundable_isSimplyBounded != false)
- _result["simplyBoundable_isSimplyBounded"] =
- simplyBoundable_isSimplyBounded;
- }
- if (kind == idl.LinkedNodeKind.libraryDirective) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (libraryDirective_name != null)
- _result["libraryDirective_name"] = libraryDirective_name.toJson();
- }
- if (kind == idl.LinkedNodeKind.mixinDeclaration) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (mixinDeclaration_onClause != null)
- _result["mixinDeclaration_onClause"] =
- mixinDeclaration_onClause.toJson();
- if (classOrMixinDeclaration_implementsClause != null)
- _result["classOrMixinDeclaration_implementsClause"] =
- classOrMixinDeclaration_implementsClause.toJson();
- if (classOrMixinDeclaration_members.isNotEmpty)
- _result["classOrMixinDeclaration_members"] =
- classOrMixinDeclaration_members
- .map((_value) => _value.toJson())
- .toList();
- if (classOrMixinDeclaration_typeParameters != null)
- _result["classOrMixinDeclaration_typeParameters"] =
- classOrMixinDeclaration_typeParameters.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (mixinDeclaration_superInvokedNames.isNotEmpty)
- _result["mixinDeclaration_superInvokedNames"] =
- mixinDeclaration_superInvokedNames;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (simplyBoundable_isSimplyBounded != false)
- _result["simplyBoundable_isSimplyBounded"] =
- simplyBoundable_isSimplyBounded;
- }
- if (kind == idl.LinkedNodeKind.partDirective) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- if (uriBasedDirective_uri != null)
- _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
- if (uriBasedDirective_uriContent != '')
- _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
- if (uriBasedDirective_uriElement != 0)
- _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
- }
- if (kind == idl.LinkedNodeKind.partOfDirective) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (partOfDirective_libraryName != null)
- _result["partOfDirective_libraryName"] =
- partOfDirective_libraryName.toJson();
- if (partOfDirective_uri != null)
- _result["partOfDirective_uri"] = partOfDirective_uri.toJson();
- }
- if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (topLevelVariableDeclaration_variableList != null)
- _result["topLevelVariableDeclaration_variableList"] =
- topLevelVariableDeclaration_variableList.toJson();
- }
- if (kind == idl.LinkedNodeKind.typeParameter) {
- if (annotatedNode_comment != null)
- _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
- if (annotatedNode_metadata.isNotEmpty)
- _result["annotatedNode_metadata"] =
- annotatedNode_metadata.map((_value) => _value.toJson()).toList();
- if (typeParameter_bound != null)
- _result["typeParameter_bound"] = typeParameter_bound.toJson();
- if (typeParameter_defaultType != null)
- _result["typeParameter_defaultType"] =
- typeParameter_defaultType.toJson();
- if (codeLength != 0) _result["codeLength"] = codeLength;
- if (codeOffset != 0) _result["codeOffset"] = codeOffset;
- if (nameOffset != 0) _result["nameOffset"] = nameOffset;
- }
- if (kind == idl.LinkedNodeKind.switchCase) {
- if (switchMember_statements.isNotEmpty)
- _result["switchMember_statements"] =
- switchMember_statements.map((_value) => _value.toJson()).toList();
- if (switchCase_expression != null)
- _result["switchCase_expression"] = switchCase_expression.toJson();
- if (switchMember_labels.isNotEmpty)
- _result["switchMember_labels"] =
- switchMember_labels.map((_value) => _value.toJson()).toList();
- }
- if (kind == idl.LinkedNodeKind.switchDefault) {
- if (switchMember_statements.isNotEmpty)
- _result["switchMember_statements"] =
- switchMember_statements.map((_value) => _value.toJson()).toList();
- if (switchMember_labels.isNotEmpty)
- _result["switchMember_labels"] =
- switchMember_labels.map((_value) => _value.toJson()).toList();
- }
if (kind == idl.LinkedNodeKind.annotation) {
if (annotation_arguments != null)
_result["annotation_arguments"] = annotation_arguments.toJson();
@@ -12359,6 +13596,11 @@
if (annotation_name != null)
_result["annotation_name"] = annotation_name.toJson();
}
+ if (kind == idl.LinkedNodeKind.argumentList) {
+ if (argumentList_arguments.isNotEmpty)
+ _result["argumentList_arguments"] =
+ argumentList_arguments.map((_value) => _value.toJson()).toList();
+ }
if (kind == idl.LinkedNodeKind.asExpression) {
if (asExpression_expression != null)
_result["asExpression_expression"] = asExpression_expression.toJson();
@@ -12407,14 +13649,54 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
+ if (kind == idl.LinkedNodeKind.binaryExpression) {
+ if (binaryExpression_invokeType != null)
+ _result["binaryExpression_invokeType"] =
+ binaryExpression_invokeType.toJson();
+ if (binaryExpression_leftOperand != null)
+ _result["binaryExpression_leftOperand"] =
+ binaryExpression_leftOperand.toJson();
+ if (binaryExpression_rightOperand != null)
+ _result["binaryExpression_rightOperand"] =
+ binaryExpression_rightOperand.toJson();
+ if (binaryExpression_elementType != null)
+ _result["binaryExpression_elementType"] =
+ binaryExpression_elementType.toJson();
+ if (binaryExpression_element != 0)
+ _result["binaryExpression_element"] = binaryExpression_element;
+ if (binaryExpression_operator != idl.UnlinkedTokenType.NOTHING)
+ _result["binaryExpression_operator"] =
+ binaryExpression_operator.toString().split('.')[1];
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.block) {
+ if (block_statements.isNotEmpty)
+ _result["block_statements"] =
+ block_statements.map((_value) => _value.toJson()).toList();
+ }
if (kind == idl.LinkedNodeKind.blockFunctionBody) {
if (blockFunctionBody_block != null)
_result["blockFunctionBody_block"] = blockFunctionBody_block.toJson();
}
+ if (kind == idl.LinkedNodeKind.booleanLiteral) {
+ if (booleanLiteral_value != false)
+ _result["booleanLiteral_value"] = booleanLiteral_value;
+ }
if (kind == idl.LinkedNodeKind.breakStatement) {
if (breakStatement_label != null)
_result["breakStatement_label"] = breakStatement_label.toJson();
}
+ if (kind == idl.LinkedNodeKind.cascadeExpression) {
+ if (cascadeExpression_sections.isNotEmpty)
+ _result["cascadeExpression_sections"] = cascadeExpression_sections
+ .map((_value) => _value.toJson())
+ .toList();
+ if (cascadeExpression_target != null)
+ _result["cascadeExpression_target"] = cascadeExpression_target.toJson();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.catchClause) {
if (catchClause_body != null)
_result["catchClause_body"] = catchClause_body.toJson();
@@ -12428,11 +13710,99 @@
_result["catchClause_stackTraceParameter"] =
catchClause_stackTraceParameter.toJson();
}
+ if (kind == idl.LinkedNodeKind.classDeclaration) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (classDeclaration_extendsClause != null)
+ _result["classDeclaration_extendsClause"] =
+ classDeclaration_extendsClause.toJson();
+ if (classDeclaration_withClause != null)
+ _result["classDeclaration_withClause"] =
+ classDeclaration_withClause.toJson();
+ if (classDeclaration_nativeClause != null)
+ _result["classDeclaration_nativeClause"] =
+ classDeclaration_nativeClause.toJson();
+ if (classDeclaration_isDartObject != false)
+ _result["classDeclaration_isDartObject"] =
+ classDeclaration_isDartObject;
+ if (classOrMixinDeclaration_implementsClause != null)
+ _result["classOrMixinDeclaration_implementsClause"] =
+ classOrMixinDeclaration_implementsClause.toJson();
+ if (classOrMixinDeclaration_members.isNotEmpty)
+ _result["classOrMixinDeclaration_members"] =
+ classOrMixinDeclaration_members
+ .map((_value) => _value.toJson())
+ .toList();
+ if (classOrMixinDeclaration_typeParameters != null)
+ _result["classOrMixinDeclaration_typeParameters"] =
+ classOrMixinDeclaration_typeParameters.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ if (simplyBoundable_isSimplyBounded != false)
+ _result["simplyBoundable_isSimplyBounded"] =
+ simplyBoundable_isSimplyBounded;
+ }
+ if (kind == idl.LinkedNodeKind.classTypeAlias) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (classTypeAlias_typeParameters != null)
+ _result["classTypeAlias_typeParameters"] =
+ classTypeAlias_typeParameters.toJson();
+ if (classTypeAlias_superclass != null)
+ _result["classTypeAlias_superclass"] =
+ classTypeAlias_superclass.toJson();
+ if (classTypeAlias_withClause != null)
+ _result["classTypeAlias_withClause"] =
+ classTypeAlias_withClause.toJson();
+ if (classTypeAlias_implementsClause != null)
+ _result["classTypeAlias_implementsClause"] =
+ classTypeAlias_implementsClause.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ if (simplyBoundable_isSimplyBounded != false)
+ _result["simplyBoundable_isSimplyBounded"] =
+ simplyBoundable_isSimplyBounded;
+ }
+ if (kind == idl.LinkedNodeKind.comment) {
+ if (comment_references.isNotEmpty)
+ _result["comment_references"] =
+ comment_references.map((_value) => _value.toJson()).toList();
+ if (comment_tokens.isNotEmpty) _result["comment_tokens"] = comment_tokens;
+ if (comment_type != idl.LinkedNodeCommentType.block)
+ _result["comment_type"] = comment_type.toString().split('.')[1];
+ }
if (kind == idl.LinkedNodeKind.commentReference) {
if (commentReference_identifier != null)
_result["commentReference_identifier"] =
commentReference_identifier.toJson();
}
+ if (kind == idl.LinkedNodeKind.compilationUnit) {
+ if (compilationUnit_declarations.isNotEmpty)
+ _result["compilationUnit_declarations"] = compilationUnit_declarations
+ .map((_value) => _value.toJson())
+ .toList();
+ if (compilationUnit_scriptTag != null)
+ _result["compilationUnit_scriptTag"] =
+ compilationUnit_scriptTag.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (compilationUnit_directives.isNotEmpty)
+ _result["compilationUnit_directives"] = compilationUnit_directives
+ .map((_value) => _value.toJson())
+ .toList();
+ }
if (kind == idl.LinkedNodeKind.conditionalExpression) {
if (conditionalExpression_condition != null)
_result["conditionalExpression_condition"] =
@@ -12454,6 +13824,38 @@
if (configuration_uri != null)
_result["configuration_uri"] = configuration_uri.toJson();
}
+ if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+ if (constructorDeclaration_initializers.isNotEmpty)
+ _result["constructorDeclaration_initializers"] =
+ constructorDeclaration_initializers
+ .map((_value) => _value.toJson())
+ .toList();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (constructorDeclaration_body != null)
+ _result["constructorDeclaration_body"] =
+ constructorDeclaration_body.toJson();
+ if (constructorDeclaration_name != null)
+ _result["constructorDeclaration_name"] =
+ constructorDeclaration_name.toJson();
+ if (constructorDeclaration_parameters != null)
+ _result["constructorDeclaration_parameters"] =
+ constructorDeclaration_parameters.toJson();
+ if (constructorDeclaration_redirectedConstructor != null)
+ _result["constructorDeclaration_redirectedConstructor"] =
+ constructorDeclaration_redirectedConstructor.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (constructorDeclaration_periodOffset != 0)
+ _result["constructorDeclaration_periodOffset"] =
+ constructorDeclaration_periodOffset;
+ if (constructorDeclaration_returnType != null)
+ _result["constructorDeclaration_returnType"] =
+ constructorDeclaration_returnType.toJson();
+ }
if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
if (constructorFieldInitializer_expression != null)
_result["constructorFieldInitializer_expression"] =
@@ -12477,6 +13879,18 @@
if (continueStatement_label != null)
_result["continueStatement_label"] = continueStatement_label.toJson();
}
+ if (kind == idl.LinkedNodeKind.declaredIdentifier) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (declaredIdentifier_identifier != null)
+ _result["declaredIdentifier_identifier"] =
+ declaredIdentifier_identifier.toJson();
+ if (declaredIdentifier_type != null)
+ _result["declaredIdentifier_type"] = declaredIdentifier_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
if (defaultFormalParameter_defaultValue != null)
_result["defaultFormalParameter_defaultValue"] =
@@ -12497,6 +13911,78 @@
if (doStatement_condition != null)
_result["doStatement_condition"] = doStatement_condition.toJson();
}
+ if (kind == idl.LinkedNodeKind.dottedName) {
+ if (dottedName_components.isNotEmpty)
+ _result["dottedName_components"] =
+ dottedName_components.map((_value) => _value.toJson()).toList();
+ }
+ if (kind == idl.LinkedNodeKind.doubleLiteral) {
+ if (doubleLiteral_value != 0.0)
+ _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
+ ? doubleLiteral_value
+ : doubleLiteral_value.toString();
+ }
+ if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+ if (emptyFunctionBody_fake != 0)
+ _result["emptyFunctionBody_fake"] = emptyFunctionBody_fake;
+ }
+ if (kind == idl.LinkedNodeKind.emptyStatement) {
+ if (emptyStatement_fake != 0)
+ _result["emptyStatement_fake"] = emptyStatement_fake;
+ }
+ if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (enumConstantDeclaration_name != null)
+ _result["enumConstantDeclaration_name"] =
+ enumConstantDeclaration_name.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.enumDeclaration) {
+ if (enumDeclaration_constants.isNotEmpty)
+ _result["enumDeclaration_constants"] =
+ enumDeclaration_constants.map((_value) => _value.toJson()).toList();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.exportDirective) {
+ if (namespaceDirective_combinators.isNotEmpty)
+ _result["namespaceDirective_combinators"] =
+ namespaceDirective_combinators
+ .map((_value) => _value.toJson())
+ .toList();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (directive_keywordOffset != 0)
+ _result["directive_keywordOffset"] = directive_keywordOffset;
+ if (namespaceDirective_configurations.isNotEmpty)
+ _result["namespaceDirective_configurations"] =
+ namespaceDirective_configurations
+ .map((_value) => _value.toJson())
+ .toList();
+ if (uriBasedDirective_uriElement != 0)
+ _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+ if (uriBasedDirective_uri != null)
+ _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+ if (namespaceDirective_selectedUri != '')
+ _result["namespaceDirective_selectedUri"] =
+ namespaceDirective_selectedUri;
+ if (uriBasedDirective_uriContent != '')
+ _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+ }
if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
if (expressionFunctionBody_expression != null)
_result["expressionFunctionBody_expression"] =
@@ -12511,6 +13997,42 @@
if (extendsClause_superclass != null)
_result["extendsClause_superclass"] = extendsClause_superclass.toJson();
}
+ if (kind == idl.LinkedNodeKind.fieldDeclaration) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (fieldDeclaration_fields != null)
+ _result["fieldDeclaration_fields"] = fieldDeclaration_fields.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+ if (actualType != null) _result["actualType"] = actualType.toJson();
+ if (normalFormalParameter_metadata.isNotEmpty)
+ _result["normalFormalParameter_metadata"] =
+ normalFormalParameter_metadata
+ .map((_value) => _value.toJson())
+ .toList();
+ if (fieldFormalParameter_type != null)
+ _result["fieldFormalParameter_type"] =
+ fieldFormalParameter_type.toJson();
+ if (fieldFormalParameter_typeParameters != null)
+ _result["fieldFormalParameter_typeParameters"] =
+ fieldFormalParameter_typeParameters.toJson();
+ if (fieldFormalParameter_formalParameters != null)
+ _result["fieldFormalParameter_formalParameters"] =
+ fieldFormalParameter_formalParameters.toJson();
+ if (inheritsCovariant != false)
+ _result["inheritsCovariant"] = inheritsCovariant;
+ if (normalFormalParameter_identifier != null)
+ _result["normalFormalParameter_identifier"] =
+ normalFormalParameter_identifier.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (normalFormalParameter_comment != null)
+ _result["normalFormalParameter_comment"] =
+ normalFormalParameter_comment.toJson();
+ }
if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
if (forEachParts_iterable != null)
_result["forEachParts_iterable"] = forEachParts_iterable.toJson();
@@ -12531,12 +14053,6 @@
if (forElement_body != null)
_result["forElement_body"] = forElement_body.toJson();
}
- if (kind == idl.LinkedNodeKind.forStatement) {
- if (forMixin_forLoopParts != null)
- _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
- if (forStatement_body != null)
- _result["forStatement_body"] = forStatement_body.toJson();
- }
if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
if (forParts_condition != null)
_result["forParts_condition"] = forParts_condition.toJson();
@@ -12557,11 +14073,170 @@
_result["forParts_updaters"] =
forParts_updaters.map((_value) => _value.toJson()).toList();
}
+ if (kind == idl.LinkedNodeKind.forStatement) {
+ if (forMixin_forLoopParts != null)
+ _result["forMixin_forLoopParts"] = forMixin_forLoopParts.toJson();
+ if (forStatement_body != null)
+ _result["forStatement_body"] = forStatement_body.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.formalParameterList) {
+ if (formalParameterList_parameters.isNotEmpty)
+ _result["formalParameterList_parameters"] =
+ formalParameterList_parameters
+ .map((_value) => _value.toJson())
+ .toList();
+ }
+ if (kind == idl.LinkedNodeKind.functionDeclaration) {
+ if (actualReturnType != null)
+ _result["actualReturnType"] = actualReturnType.toJson();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (functionDeclaration_functionExpression != null)
+ _result["functionDeclaration_functionExpression"] =
+ functionDeclaration_functionExpression.toJson();
+ if (functionDeclaration_returnType != null)
+ _result["functionDeclaration_returnType"] =
+ functionDeclaration_returnType.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ }
if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
if (functionDeclarationStatement_functionDeclaration != null)
_result["functionDeclarationStatement_functionDeclaration"] =
functionDeclarationStatement_functionDeclaration.toJson();
}
+ if (kind == idl.LinkedNodeKind.functionExpression) {
+ if (actualReturnType != null)
+ _result["actualReturnType"] = actualReturnType.toJson();
+ if (functionExpression_body != null)
+ _result["functionExpression_body"] = functionExpression_body.toJson();
+ if (functionExpression_formalParameters != null)
+ _result["functionExpression_formalParameters"] =
+ functionExpression_formalParameters.toJson();
+ if (functionExpression_typeParameters != null)
+ _result["functionExpression_typeParameters"] =
+ functionExpression_typeParameters.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+ if (invocationExpression_invokeType != null)
+ _result["invocationExpression_invokeType"] =
+ invocationExpression_invokeType.toJson();
+ if (functionExpressionInvocation_function != null)
+ _result["functionExpressionInvocation_function"] =
+ functionExpressionInvocation_function.toJson();
+ if (invocationExpression_typeArguments != null)
+ _result["invocationExpression_typeArguments"] =
+ invocationExpression_typeArguments.toJson();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ if (invocationExpression_arguments != null)
+ _result["invocationExpression_arguments"] =
+ invocationExpression_arguments.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+ if (actualReturnType != null)
+ _result["actualReturnType"] = actualReturnType.toJson();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (functionTypeAlias_formalParameters != null)
+ _result["functionTypeAlias_formalParameters"] =
+ functionTypeAlias_formalParameters.toJson();
+ if (functionTypeAlias_returnType != null)
+ _result["functionTypeAlias_returnType"] =
+ functionTypeAlias_returnType.toJson();
+ if (functionTypeAlias_typeParameters != null)
+ _result["functionTypeAlias_typeParameters"] =
+ functionTypeAlias_typeParameters.toJson();
+ if (typeAlias_hasSelfReference != false)
+ _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ if (simplyBoundable_isSimplyBounded != false)
+ _result["simplyBoundable_isSimplyBounded"] =
+ simplyBoundable_isSimplyBounded;
+ }
+ if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+ if (actualType != null) _result["actualType"] = actualType.toJson();
+ if (normalFormalParameter_metadata.isNotEmpty)
+ _result["normalFormalParameter_metadata"] =
+ normalFormalParameter_metadata
+ .map((_value) => _value.toJson())
+ .toList();
+ if (functionTypedFormalParameter_formalParameters != null)
+ _result["functionTypedFormalParameter_formalParameters"] =
+ functionTypedFormalParameter_formalParameters.toJson();
+ if (functionTypedFormalParameter_returnType != null)
+ _result["functionTypedFormalParameter_returnType"] =
+ functionTypedFormalParameter_returnType.toJson();
+ if (functionTypedFormalParameter_typeParameters != null)
+ _result["functionTypedFormalParameter_typeParameters"] =
+ functionTypedFormalParameter_typeParameters.toJson();
+ if (inheritsCovariant != false)
+ _result["inheritsCovariant"] = inheritsCovariant;
+ if (normalFormalParameter_identifier != null)
+ _result["normalFormalParameter_identifier"] =
+ normalFormalParameter_identifier.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (normalFormalParameter_comment != null)
+ _result["normalFormalParameter_comment"] =
+ normalFormalParameter_comment.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.genericFunctionType) {
+ if (actualReturnType != null)
+ _result["actualReturnType"] = actualReturnType.toJson();
+ if (genericFunctionType_typeParameters != null)
+ _result["genericFunctionType_typeParameters"] =
+ genericFunctionType_typeParameters.toJson();
+ if (genericFunctionType_returnType != null)
+ _result["genericFunctionType_returnType"] =
+ genericFunctionType_returnType.toJson();
+ if (genericFunctionType_id != 0)
+ _result["genericFunctionType_id"] = genericFunctionType_id;
+ if (genericFunctionType_formalParameters != null)
+ _result["genericFunctionType_formalParameters"] =
+ genericFunctionType_formalParameters.toJson();
+ if (genericFunctionType_type != null)
+ _result["genericFunctionType_type"] = genericFunctionType_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.genericTypeAlias) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (genericTypeAlias_typeParameters != null)
+ _result["genericTypeAlias_typeParameters"] =
+ genericTypeAlias_typeParameters.toJson();
+ if (genericTypeAlias_functionType != null)
+ _result["genericTypeAlias_functionType"] =
+ genericTypeAlias_functionType.toJson();
+ if (typeAlias_hasSelfReference != false)
+ _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ if (simplyBoundable_isSimplyBounded != false)
+ _result["simplyBoundable_isSimplyBounded"] =
+ simplyBoundable_isSimplyBounded;
+ }
+ if (kind == idl.LinkedNodeKind.hideCombinator) {
+ if (names.isNotEmpty) _result["names"] = names;
+ }
if (kind == idl.LinkedNodeKind.ifElement) {
if (ifMixin_condition != null)
_result["ifMixin_condition"] = ifMixin_condition.toJson();
@@ -12580,6 +14255,44 @@
_result["ifStatement_thenStatement"] =
ifStatement_thenStatement.toJson();
}
+ if (kind == idl.LinkedNodeKind.implementsClause) {
+ if (implementsClause_interfaces.isNotEmpty)
+ _result["implementsClause_interfaces"] = implementsClause_interfaces
+ .map((_value) => _value.toJson())
+ .toList();
+ }
+ if (kind == idl.LinkedNodeKind.importDirective) {
+ if (namespaceDirective_combinators.isNotEmpty)
+ _result["namespaceDirective_combinators"] =
+ namespaceDirective_combinators
+ .map((_value) => _value.toJson())
+ .toList();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (directive_keywordOffset != 0)
+ _result["directive_keywordOffset"] = directive_keywordOffset;
+ if (importDirective_prefixOffset != 0)
+ _result["importDirective_prefixOffset"] = importDirective_prefixOffset;
+ if (namespaceDirective_configurations.isNotEmpty)
+ _result["namespaceDirective_configurations"] =
+ namespaceDirective_configurations
+ .map((_value) => _value.toJson())
+ .toList();
+ if (uriBasedDirective_uriElement != 0)
+ _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+ if (importDirective_prefix != '')
+ _result["importDirective_prefix"] = importDirective_prefix;
+ if (uriBasedDirective_uri != null)
+ _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+ if (namespaceDirective_selectedUri != '')
+ _result["namespaceDirective_selectedUri"] =
+ namespaceDirective_selectedUri;
+ if (uriBasedDirective_uriContent != '')
+ _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+ }
if (kind == idl.LinkedNodeKind.indexExpression) {
if (indexExpression_index != null)
_result["indexExpression_index"] = indexExpression_index.toJson();
@@ -12593,11 +14306,34 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
+ if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+ if (instanceCreationExpression_arguments.isNotEmpty)
+ _result["instanceCreationExpression_arguments"] =
+ instanceCreationExpression_arguments
+ .map((_value) => _value.toJson())
+ .toList();
+ if (instanceCreationExpression_constructorName != null)
+ _result["instanceCreationExpression_constructorName"] =
+ instanceCreationExpression_constructorName.toJson();
+ if (instanceCreationExpression_typeArguments != null)
+ _result["instanceCreationExpression_typeArguments"] =
+ instanceCreationExpression_typeArguments.toJson();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.integerLiteral) {
+ if (integerLiteral_value != 0)
+ _result["integerLiteral_value"] = integerLiteral_value;
+ }
if (kind == idl.LinkedNodeKind.interpolationExpression) {
if (interpolationExpression_expression != null)
_result["interpolationExpression_expression"] =
interpolationExpression_expression.toJson();
}
+ if (kind == idl.LinkedNodeKind.interpolationString) {
+ if (interpolationString_value != '')
+ _result["interpolationString_value"] = interpolationString_value;
+ }
if (kind == idl.LinkedNodeKind.isExpression) {
if (isExpression_expression != null)
_result["isExpression_expression"] = isExpression_expression.toJson();
@@ -12607,12 +14343,122 @@
if (kind == idl.LinkedNodeKind.label) {
if (label_label != null) _result["label_label"] = label_label.toJson();
}
+ if (kind == idl.LinkedNodeKind.labeledStatement) {
+ if (labeledStatement_labels.isNotEmpty)
+ _result["labeledStatement_labels"] =
+ labeledStatement_labels.map((_value) => _value.toJson()).toList();
+ if (labeledStatement_statement != null)
+ _result["labeledStatement_statement"] =
+ labeledStatement_statement.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.libraryDirective) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (libraryDirective_name != null)
+ _result["libraryDirective_name"] = libraryDirective_name.toJson();
+ if (directive_keywordOffset != 0)
+ _result["directive_keywordOffset"] = directive_keywordOffset;
+ }
+ if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+ if (libraryIdentifier_components.isNotEmpty)
+ _result["libraryIdentifier_components"] = libraryIdentifier_components
+ .map((_value) => _value.toJson())
+ .toList();
+ }
+ if (kind == idl.LinkedNodeKind.listLiteral) {
+ if (typedLiteral_typeArguments.isNotEmpty)
+ _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+ .map((_value) => _value.toJson())
+ .toList();
+ if (listLiteral_elements.isNotEmpty)
+ _result["listLiteral_elements"] =
+ listLiteral_elements.map((_value) => _value.toJson()).toList();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
if (mapLiteralEntry_key != null)
_result["mapLiteralEntry_key"] = mapLiteralEntry_key.toJson();
if (mapLiteralEntry_value != null)
_result["mapLiteralEntry_value"] = mapLiteralEntry_value.toJson();
}
+ if (kind == idl.LinkedNodeKind.methodDeclaration) {
+ if (actualReturnType != null)
+ _result["actualReturnType"] = actualReturnType.toJson();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (methodDeclaration_body != null)
+ _result["methodDeclaration_body"] = methodDeclaration_body.toJson();
+ if (methodDeclaration_formalParameters != null)
+ _result["methodDeclaration_formalParameters"] =
+ methodDeclaration_formalParameters.toJson();
+ if (methodDeclaration_returnType != null)
+ _result["methodDeclaration_returnType"] =
+ methodDeclaration_returnType.toJson();
+ if (methodDeclaration_typeParameters != null)
+ _result["methodDeclaration_typeParameters"] =
+ methodDeclaration_typeParameters.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (methodDeclaration_name != null)
+ _result["methodDeclaration_name"] = methodDeclaration_name.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.methodInvocation) {
+ if (invocationExpression_invokeType != null)
+ _result["invocationExpression_invokeType"] =
+ invocationExpression_invokeType.toJson();
+ if (methodInvocation_methodName != null)
+ _result["methodInvocation_methodName"] =
+ methodInvocation_methodName.toJson();
+ if (methodInvocation_target != null)
+ _result["methodInvocation_target"] = methodInvocation_target.toJson();
+ if (invocationExpression_typeArguments != null)
+ _result["invocationExpression_typeArguments"] =
+ invocationExpression_typeArguments.toJson();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ if (invocationExpression_arguments != null)
+ _result["invocationExpression_arguments"] =
+ invocationExpression_arguments.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.mixinDeclaration) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (mixinDeclaration_onClause != null)
+ _result["mixinDeclaration_onClause"] =
+ mixinDeclaration_onClause.toJson();
+ if (classOrMixinDeclaration_implementsClause != null)
+ _result["classOrMixinDeclaration_implementsClause"] =
+ classOrMixinDeclaration_implementsClause.toJson();
+ if (classOrMixinDeclaration_members.isNotEmpty)
+ _result["classOrMixinDeclaration_members"] =
+ classOrMixinDeclaration_members
+ .map((_value) => _value.toJson())
+ .toList();
+ if (classOrMixinDeclaration_typeParameters != null)
+ _result["classOrMixinDeclaration_typeParameters"] =
+ classOrMixinDeclaration_typeParameters.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (namedCompilationUnitMember_name != null)
+ _result["namedCompilationUnitMember_name"] =
+ namedCompilationUnitMember_name.toJson();
+ if (mixinDeclaration_superInvokedNames.isNotEmpty)
+ _result["mixinDeclaration_superInvokedNames"] =
+ mixinDeclaration_superInvokedNames;
+ if (simplyBoundable_isSimplyBounded != false)
+ _result["simplyBoundable_isSimplyBounded"] =
+ simplyBoundable_isSimplyBounded;
+ }
if (kind == idl.LinkedNodeKind.namedExpression) {
if (namedExpression_expression != null)
_result["namedExpression_expression"] =
@@ -12629,6 +14475,18 @@
_result["nativeFunctionBody_stringLiteral"] =
nativeFunctionBody_stringLiteral.toJson();
}
+ if (kind == idl.LinkedNodeKind.nullLiteral) {
+ if (nullLiteral_fake != 0) _result["nullLiteral_fake"] = nullLiteral_fake;
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.onClause) {
+ if (onClause_superclassConstraints.isNotEmpty)
+ _result["onClause_superclassConstraints"] =
+ onClause_superclassConstraints
+ .map((_value) => _value.toJson())
+ .toList();
+ }
if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
if (parenthesizedExpression_expression != null)
_result["parenthesizedExpression_expression"] =
@@ -12636,6 +14494,35 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
+ if (kind == idl.LinkedNodeKind.partDirective) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (directive_keywordOffset != 0)
+ _result["directive_keywordOffset"] = directive_keywordOffset;
+ if (uriBasedDirective_uriElement != 0)
+ _result["uriBasedDirective_uriElement"] = uriBasedDirective_uriElement;
+ if (uriBasedDirective_uri != null)
+ _result["uriBasedDirective_uri"] = uriBasedDirective_uri.toJson();
+ if (uriBasedDirective_uriContent != '')
+ _result["uriBasedDirective_uriContent"] = uriBasedDirective_uriContent;
+ }
+ if (kind == idl.LinkedNodeKind.partOfDirective) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (partOfDirective_libraryName != null)
+ _result["partOfDirective_libraryName"] =
+ partOfDirective_libraryName.toJson();
+ if (partOfDirective_uri != null)
+ _result["partOfDirective_uri"] = partOfDirective_uri.toJson();
+ if (directive_keywordOffset != 0)
+ _result["directive_keywordOffset"] = directive_keywordOffset;
+ }
if (kind == idl.LinkedNodeKind.postfixExpression) {
if (postfixExpression_operand != null)
_result["postfixExpression_operand"] =
@@ -12651,16 +14538,6 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
- if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
- if (prefixedIdentifier_identifier != null)
- _result["prefixedIdentifier_identifier"] =
- prefixedIdentifier_identifier.toJson();
- if (prefixedIdentifier_prefix != null)
- _result["prefixedIdentifier_prefix"] =
- prefixedIdentifier_prefix.toJson();
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
if (kind == idl.LinkedNodeKind.prefixExpression) {
if (prefixExpression_operand != null)
_result["prefixExpression_operand"] = prefixExpression_operand.toJson();
@@ -12675,6 +14552,16 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
+ if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+ if (prefixedIdentifier_identifier != null)
+ _result["prefixedIdentifier_identifier"] =
+ prefixedIdentifier_identifier.toJson();
+ if (prefixedIdentifier_prefix != null)
+ _result["prefixedIdentifier_prefix"] =
+ prefixedIdentifier_prefix.toJson();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.propertyAccess) {
if (propertyAccess_propertyName != null)
_result["propertyAccess_propertyName"] =
@@ -12701,11 +14588,70 @@
_result["redirectingConstructorInvocation_element"] =
redirectingConstructorInvocation_element;
}
+ if (kind == idl.LinkedNodeKind.rethrowExpression) {
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.returnStatement) {
if (returnStatement_expression != null)
_result["returnStatement_expression"] =
returnStatement_expression.toJson();
}
+ if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+ if (typedLiteral_typeArguments.isNotEmpty)
+ _result["typedLiteral_typeArguments"] = typedLiteral_typeArguments
+ .map((_value) => _value.toJson())
+ .toList();
+ if (setOrMapLiteral_elements.isNotEmpty)
+ _result["setOrMapLiteral_elements"] =
+ setOrMapLiteral_elements.map((_value) => _value.toJson()).toList();
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.showCombinator) {
+ if (names.isNotEmpty) _result["names"] = names;
+ }
+ if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+ if (actualType != null) _result["actualType"] = actualType.toJson();
+ if (normalFormalParameter_metadata.isNotEmpty)
+ _result["normalFormalParameter_metadata"] =
+ normalFormalParameter_metadata
+ .map((_value) => _value.toJson())
+ .toList();
+ if (simpleFormalParameter_type != null)
+ _result["simpleFormalParameter_type"] =
+ simpleFormalParameter_type.toJson();
+ if (inheritsCovariant != false)
+ _result["inheritsCovariant"] = inheritsCovariant;
+ if (normalFormalParameter_identifier != null)
+ _result["normalFormalParameter_identifier"] =
+ normalFormalParameter_identifier.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (normalFormalParameter_comment != null)
+ _result["normalFormalParameter_comment"] =
+ normalFormalParameter_comment.toJson();
+ if (topLevelTypeInferenceError != null)
+ _result["topLevelTypeInferenceError"] =
+ topLevelTypeInferenceError.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+ if (simpleIdentifier_elementType != null)
+ _result["simpleIdentifier_elementType"] =
+ simpleIdentifier_elementType.toJson();
+ if (simpleIdentifier_element != 0)
+ _result["simpleIdentifier_element"] = simpleIdentifier_element;
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ if (simpleIdentifier_offset != 0)
+ _result["simpleIdentifier_offset"] = simpleIdentifier_offset;
+ if (simpleIdentifier_name != '')
+ _result["simpleIdentifier_name"] = simpleIdentifier_name;
+ }
+ if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+ if (simpleStringLiteral_value != '')
+ _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
+ }
if (kind == idl.LinkedNodeKind.spreadElement) {
if (spreadElement_expression != null)
_result["spreadElement_expression"] = spreadElement_expression.toJson();
@@ -12713,6 +14659,12 @@
_result["spreadElement_spreadOperator"] =
spreadElement_spreadOperator.toString().split('.')[1];
}
+ if (kind == idl.LinkedNodeKind.stringInterpolation) {
+ if (stringInterpolation_elements.isNotEmpty)
+ _result["stringInterpolation_elements"] = stringInterpolation_elements
+ .map((_value) => _value.toJson())
+ .toList();
+ }
if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
if (superConstructorInvocation_arguments != null)
_result["superConstructorInvocation_arguments"] =
@@ -12727,6 +14679,45 @@
_result["superConstructorInvocation_element"] =
superConstructorInvocation_element;
}
+ if (kind == idl.LinkedNodeKind.superExpression) {
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.switchCase) {
+ if (switchMember_statements.isNotEmpty)
+ _result["switchMember_statements"] =
+ switchMember_statements.map((_value) => _value.toJson()).toList();
+ if (switchCase_expression != null)
+ _result["switchCase_expression"] = switchCase_expression.toJson();
+ if (switchMember_labels.isNotEmpty)
+ _result["switchMember_labels"] =
+ switchMember_labels.map((_value) => _value.toJson()).toList();
+ }
+ if (kind == idl.LinkedNodeKind.switchDefault) {
+ if (switchMember_statements.isNotEmpty)
+ _result["switchMember_statements"] =
+ switchMember_statements.map((_value) => _value.toJson()).toList();
+ if (switchMember_labels.isNotEmpty)
+ _result["switchMember_labels"] =
+ switchMember_labels.map((_value) => _value.toJson()).toList();
+ }
+ if (kind == idl.LinkedNodeKind.switchStatement) {
+ if (switchStatement_members.isNotEmpty)
+ _result["switchStatement_members"] =
+ switchStatement_members.map((_value) => _value.toJson()).toList();
+ if (switchStatement_expression != null)
+ _result["switchStatement_expression"] =
+ switchStatement_expression.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.symbolLiteral) {
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ if (names.isNotEmpty) _result["names"] = names;
+ }
+ if (kind == idl.LinkedNodeKind.thisExpression) {
+ if (expression_type != null)
+ _result["expression_type"] = expression_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.throwExpression) {
if (throwExpression_expression != null)
_result["throwExpression_expression"] =
@@ -12734,6 +14725,99 @@
if (expression_type != null)
_result["expression_type"] = expression_type.toJson();
}
+ if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (topLevelVariableDeclaration_variableList != null)
+ _result["topLevelVariableDeclaration_variableList"] =
+ topLevelVariableDeclaration_variableList.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.tryStatement) {
+ if (tryStatement_catchClauses.isNotEmpty)
+ _result["tryStatement_catchClauses"] =
+ tryStatement_catchClauses.map((_value) => _value.toJson()).toList();
+ if (tryStatement_body != null)
+ _result["tryStatement_body"] = tryStatement_body.toJson();
+ if (tryStatement_finallyBlock != null)
+ _result["tryStatement_finallyBlock"] =
+ tryStatement_finallyBlock.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.typeArgumentList) {
+ if (typeArgumentList_arguments.isNotEmpty)
+ _result["typeArgumentList_arguments"] = typeArgumentList_arguments
+ .map((_value) => _value.toJson())
+ .toList();
+ }
+ if (kind == idl.LinkedNodeKind.typeName) {
+ if (typeName_typeArguments.isNotEmpty)
+ _result["typeName_typeArguments"] =
+ typeName_typeArguments.map((_value) => _value.toJson()).toList();
+ if (typeName_name != null)
+ _result["typeName_name"] = typeName_name.toJson();
+ if (typeName_type != null)
+ _result["typeName_type"] = typeName_type.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.typeParameter) {
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (typeParameter_bound != null)
+ _result["typeParameter_bound"] = typeParameter_bound.toJson();
+ if (typeParameter_name != null)
+ _result["typeParameter_name"] = typeParameter_name.toJson();
+ if (typeParameter_defaultType != null)
+ _result["typeParameter_defaultType"] =
+ typeParameter_defaultType.toJson();
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ }
+ if (kind == idl.LinkedNodeKind.typeParameterList) {
+ if (typeParameterList_typeParameters.isNotEmpty)
+ _result["typeParameterList_typeParameters"] =
+ typeParameterList_typeParameters
+ .map((_value) => _value.toJson())
+ .toList();
+ }
+ if (kind == idl.LinkedNodeKind.variableDeclaration) {
+ if (actualType != null) _result["actualType"] = actualType.toJson();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (variableDeclaration_initializer != null)
+ _result["variableDeclaration_initializer"] =
+ variableDeclaration_initializer.toJson();
+ if (variableDeclaration_name != null)
+ _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+ if (inheritsCovariant != false)
+ _result["inheritsCovariant"] = inheritsCovariant;
+ if (codeLength != 0) _result["codeLength"] = codeLength;
+ if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+ if (topLevelTypeInferenceError != null)
+ _result["topLevelTypeInferenceError"] =
+ topLevelTypeInferenceError.toJson();
+ }
+ if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+ if (variableDeclarationList_variables.isNotEmpty)
+ _result["variableDeclarationList_variables"] =
+ variableDeclarationList_variables
+ .map((_value) => _value.toJson())
+ .toList();
+ if (annotatedNode_comment != null)
+ _result["annotatedNode_comment"] = annotatedNode_comment.toJson();
+ if (annotatedNode_metadata.isNotEmpty)
+ _result["annotatedNode_metadata"] =
+ annotatedNode_metadata.map((_value) => _value.toJson()).toList();
+ if (variableDeclarationList_type != null)
+ _result["variableDeclarationList_type"] =
+ variableDeclarationList_type.toJson();
+ }
if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
if (variableDeclarationStatement_variables != null)
_result["variableDeclarationStatement_variables"] =
@@ -12745,233 +14829,90 @@
if (whileStatement_condition != null)
_result["whileStatement_condition"] = whileStatement_condition.toJson();
}
+ if (kind == idl.LinkedNodeKind.withClause) {
+ if (withClause_mixinTypes.isNotEmpty)
+ _result["withClause_mixinTypes"] =
+ withClause_mixinTypes.map((_value) => _value.toJson()).toList();
+ }
if (kind == idl.LinkedNodeKind.yieldStatement) {
if (yieldStatement_expression != null)
_result["yieldStatement_expression"] =
yieldStatement_expression.toJson();
}
- if (kind == idl.LinkedNodeKind.simpleIdentifier) {
- if (simpleIdentifier_elementType != null)
- _result["simpleIdentifier_elementType"] =
- simpleIdentifier_elementType.toJson();
- if (simpleIdentifier_element != 0)
- _result["simpleIdentifier_element"] = simpleIdentifier_element;
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
- if (emptyFunctionBody_fake != 0)
- _result["emptyFunctionBody_fake"] = emptyFunctionBody_fake;
- }
- if (kind == idl.LinkedNodeKind.emptyStatement) {
- if (emptyStatement_fake != 0)
- _result["emptyStatement_fake"] = emptyStatement_fake;
- }
- if (kind == idl.LinkedNodeKind.nullLiteral) {
- if (nullLiteral_fake != 0) _result["nullLiteral_fake"] = nullLiteral_fake;
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.booleanLiteral) {
- if (booleanLiteral_value != false)
- _result["booleanLiteral_value"] = booleanLiteral_value;
- }
- if (kind == idl.LinkedNodeKind.hideCombinator) {
- if (names.isNotEmpty) _result["names"] = names;
- }
- if (kind == idl.LinkedNodeKind.showCombinator) {
- if (names.isNotEmpty) _result["names"] = names;
- }
- if (kind == idl.LinkedNodeKind.symbolLiteral) {
- if (names.isNotEmpty) _result["names"] = names;
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.doubleLiteral) {
- if (doubleLiteral_value != 0.0)
- _result["doubleLiteral_value"] = doubleLiteral_value.isFinite
- ? doubleLiteral_value
- : doubleLiteral_value.toString();
- }
- if (kind == idl.LinkedNodeKind.rethrowExpression) {
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.superExpression) {
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.thisExpression) {
- if (expression_type != null)
- _result["expression_type"] = expression_type.toJson();
- }
- if (kind == idl.LinkedNodeKind.integerLiteral) {
- if (integerLiteral_value != 0)
- _result["integerLiteral_value"] = integerLiteral_value;
- }
- if (kind == idl.LinkedNodeKind.interpolationString) {
- if (interpolationString_value != '')
- _result["interpolationString_value"] = interpolationString_value;
- }
- if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
- if (simpleStringLiteral_value != '')
- _result["simpleStringLiteral_value"] = simpleStringLiteral_value;
- }
return _result;
}
@override
Map<String, Object> toMap() {
- if (kind == idl.LinkedNodeKind.functionDeclaration) {
+ if (kind == idl.LinkedNodeKind.adjacentStrings) {
return {
- "actualReturnType": actualReturnType,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "functionDeclaration_functionExpression":
- functionDeclaration_functionExpression,
- "functionDeclaration_returnType": functionDeclaration_returnType,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "adjacentStrings_strings": adjacentStrings_strings,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.functionExpression) {
+ if (kind == idl.LinkedNodeKind.annotation) {
return {
- "actualReturnType": actualReturnType,
- "functionExpression_body": functionExpression_body,
- "functionExpression_formalParameters":
- functionExpression_formalParameters,
- "functionExpression_typeParameters": functionExpression_typeParameters,
+ "annotation_arguments": annotation_arguments,
+ "annotation_constructorName": annotation_constructorName,
+ "annotation_element": annotation_element,
+ "annotation_elementType": annotation_elementType,
+ "annotation_name": annotation_name,
"flags": flags,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+ if (kind == idl.LinkedNodeKind.argumentList) {
return {
- "actualReturnType": actualReturnType,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "functionTypeAlias_formalParameters":
- functionTypeAlias_formalParameters,
- "functionTypeAlias_returnType": functionTypeAlias_returnType,
- "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
- "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "argumentList_arguments": argumentList_arguments,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
- "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
};
}
- if (kind == idl.LinkedNodeKind.genericFunctionType) {
+ if (kind == idl.LinkedNodeKind.asExpression) {
return {
- "actualReturnType": actualReturnType,
- "genericFunctionType_typeParameters":
- genericFunctionType_typeParameters,
- "genericFunctionType_returnType": genericFunctionType_returnType,
- "genericFunctionType_id": genericFunctionType_id,
- "genericFunctionType_formalParameters":
- genericFunctionType_formalParameters,
- "genericFunctionType_type": genericFunctionType_type,
+ "asExpression_expression": asExpression_expression,
+ "asExpression_type": asExpression_type,
+ "expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.methodDeclaration) {
+ if (kind == idl.LinkedNodeKind.assertInitializer) {
return {
- "actualReturnType": actualReturnType,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "methodDeclaration_body": methodDeclaration_body,
- "methodDeclaration_formalParameters":
- methodDeclaration_formalParameters,
- "methodDeclaration_returnType": methodDeclaration_returnType,
- "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "assertInitializer_condition": assertInitializer_condition,
+ "assertInitializer_message": assertInitializer_message,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+ if (kind == idl.LinkedNodeKind.assertStatement) {
return {
- "actualType": actualType,
- "normalFormalParameter_metadata": normalFormalParameter_metadata,
- "fieldFormalParameter_type": fieldFormalParameter_type,
- "fieldFormalParameter_typeParameters":
- fieldFormalParameter_typeParameters,
- "fieldFormalParameter_formalParameters":
- fieldFormalParameter_formalParameters,
- "inheritsCovariant": inheritsCovariant,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "assertStatement_condition": assertStatement_condition,
+ "assertStatement_message": assertStatement_message,
"flags": flags,
- "nameOffset": nameOffset,
- "normalFormalParameter_comment": normalFormalParameter_comment,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+ if (kind == idl.LinkedNodeKind.assignmentExpression) {
return {
- "actualType": actualType,
- "normalFormalParameter_metadata": normalFormalParameter_metadata,
- "functionTypedFormalParameter_formalParameters":
- functionTypedFormalParameter_formalParameters,
- "functionTypedFormalParameter_returnType":
- functionTypedFormalParameter_returnType,
- "functionTypedFormalParameter_typeParameters":
- functionTypedFormalParameter_typeParameters,
- "inheritsCovariant": inheritsCovariant,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
+ "assignmentExpression_rightHandSide":
+ assignmentExpression_rightHandSide,
+ "assignmentExpression_elementType": assignmentExpression_elementType,
+ "assignmentExpression_element": assignmentExpression_element,
+ "assignmentExpression_operator": assignmentExpression_operator,
+ "expression_type": expression_type,
"flags": flags,
- "nameOffset": nameOffset,
- "normalFormalParameter_comment": normalFormalParameter_comment,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+ if (kind == idl.LinkedNodeKind.awaitExpression) {
return {
- "actualType": actualType,
- "normalFormalParameter_metadata": normalFormalParameter_metadata,
- "simpleFormalParameter_type": simpleFormalParameter_type,
- "inheritsCovariant": inheritsCovariant,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
+ "awaitExpression_expression": awaitExpression_expression,
+ "expression_type": expression_type,
"flags": flags,
- "nameOffset": nameOffset,
- "normalFormalParameter_comment": normalFormalParameter_comment,
"kind": kind,
- "name": name,
- "topLevelTypeInferenceError": topLevelTypeInferenceError,
- };
- }
- if (kind == idl.LinkedNodeKind.variableDeclaration) {
- return {
- "actualType": actualType,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "variableDeclaration_initializer": variableDeclaration_initializer,
- "inheritsCovariant": inheritsCovariant,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "flags": flags,
- "nameOffset": nameOffset,
- "kind": kind,
- "name": name,
- "topLevelTypeInferenceError": topLevelTypeInferenceError,
- "variableDeclaration_declaration": variableDeclaration_declaration,
};
}
if (kind == idl.LinkedNodeKind.binaryExpression) {
@@ -12985,51 +14926,6 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
- return {
- "invocationExpression_invokeType": invocationExpression_invokeType,
- "functionExpressionInvocation_function":
- functionExpressionInvocation_function,
- "invocationExpression_typeArguments":
- invocationExpression_typeArguments,
- "expression_type": expression_type,
- "flags": flags,
- "invocationExpression_arguments": invocationExpression_arguments,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.methodInvocation) {
- return {
- "invocationExpression_invokeType": invocationExpression_invokeType,
- "methodInvocation_methodName": methodInvocation_methodName,
- "methodInvocation_target": methodInvocation_target,
- "invocationExpression_typeArguments":
- invocationExpression_typeArguments,
- "expression_type": expression_type,
- "flags": flags,
- "invocationExpression_arguments": invocationExpression_arguments,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.adjacentStrings) {
- return {
- "adjacentStrings_strings": adjacentStrings_strings,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.argumentList) {
- return {
- "argumentList_arguments": argumentList_arguments,
- "flags": flags,
- "kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.block) {
@@ -13037,7 +14933,27 @@
"block_statements": block_statements,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.blockFunctionBody) {
+ return {
+ "blockFunctionBody_block": blockFunctionBody_block,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.booleanLiteral) {
+ return {
+ "booleanLiteral_value": booleanLiteral_value,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.breakStatement) {
+ return {
+ "breakStatement_label": breakStatement_label,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.cascadeExpression) {
@@ -13047,250 +14963,16 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
};
}
- if (kind == idl.LinkedNodeKind.comment) {
+ if (kind == idl.LinkedNodeKind.catchClause) {
return {
- "comment_references": comment_references,
- "comment_tokens": comment_tokens,
- "comment_type": comment_type,
+ "catchClause_body": catchClause_body,
+ "catchClause_exceptionParameter": catchClause_exceptionParameter,
+ "catchClause_exceptionType": catchClause_exceptionType,
+ "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
"flags": flags,
"kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.compilationUnit) {
- return {
- "compilationUnit_declarations": compilationUnit_declarations,
- "compilationUnit_scriptTag": compilationUnit_scriptTag,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "compilationUnit_directives": compilationUnit_directives,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.constructorDeclaration) {
- return {
- "constructorDeclaration_initializers":
- constructorDeclaration_initializers,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "constructorDeclaration_body": constructorDeclaration_body,
- "constructorDeclaration_parameters": constructorDeclaration_parameters,
- "constructorDeclaration_redirectedConstructor":
- constructorDeclaration_redirectedConstructor,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "constructorDeclaration_returnType": constructorDeclaration_returnType,
- "flags": flags,
- "nameOffset": nameOffset,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.dottedName) {
- return {
- "dottedName_components": dottedName_components,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.enumDeclaration) {
- return {
- "enumDeclaration_constants": enumDeclaration_constants,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "flags": flags,
- "nameOffset": nameOffset,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.formalParameterList) {
- return {
- "formalParameterList_parameters": formalParameterList_parameters,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.implementsClause) {
- return {
- "implementsClause_interfaces": implementsClause_interfaces,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
- return {
- "instanceCreationExpression_arguments":
- instanceCreationExpression_arguments,
- "instanceCreationExpression_constructorName":
- instanceCreationExpression_constructorName,
- "instanceCreationExpression_typeArguments":
- instanceCreationExpression_typeArguments,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.labeledStatement) {
- return {
- "labeledStatement_labels": labeledStatement_labels,
- "labeledStatement_statement": labeledStatement_statement,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.libraryIdentifier) {
- return {
- "libraryIdentifier_components": libraryIdentifier_components,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.exportDirective) {
- return {
- "namespaceDirective_combinators": namespaceDirective_combinators,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "namespaceDirective_configurations": namespaceDirective_configurations,
- "flags": flags,
- "nameOffset": nameOffset,
- "uriBasedDirective_uri": uriBasedDirective_uri,
- "kind": kind,
- "name": name,
- "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
- "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
- "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
- };
- }
- if (kind == idl.LinkedNodeKind.importDirective) {
- return {
- "namespaceDirective_combinators": namespaceDirective_combinators,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "importDirective_prefixOffset": importDirective_prefixOffset,
- "namespaceDirective_configurations": namespaceDirective_configurations,
- "flags": flags,
- "importDirective_prefix": importDirective_prefix,
- "nameOffset": nameOffset,
- "uriBasedDirective_uri": uriBasedDirective_uri,
- "kind": kind,
- "name": name,
- "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
- "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
- "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
- };
- }
- if (kind == idl.LinkedNodeKind.onClause) {
- return {
- "onClause_superclassConstraints": onClause_superclassConstraints,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.stringInterpolation) {
- return {
- "stringInterpolation_elements": stringInterpolation_elements,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.switchStatement) {
- return {
- "switchStatement_members": switchStatement_members,
- "switchStatement_expression": switchStatement_expression,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.tryStatement) {
- return {
- "tryStatement_catchClauses": tryStatement_catchClauses,
- "tryStatement_body": tryStatement_body,
- "tryStatement_finallyBlock": tryStatement_finallyBlock,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.typeArgumentList) {
- return {
- "typeArgumentList_arguments": typeArgumentList_arguments,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.listLiteral) {
- return {
- "typedLiteral_typeArguments": typedLiteral_typeArguments,
- "listLiteral_elements": listLiteral_elements,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
- return {
- "typedLiteral_typeArguments": typedLiteral_typeArguments,
- "setOrMapLiteral_elements": setOrMapLiteral_elements,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.typeName) {
- return {
- "typeName_typeArguments": typeName_typeArguments,
- "typeName_name": typeName_name,
- "typeName_type": typeName_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.typeParameterList) {
- return {
- "typeParameterList_typeParameters": typeParameterList_typeParameters,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.variableDeclarationList) {
- return {
- "variableDeclarationList_variables": variableDeclarationList_variables,
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "variableDeclarationList_type": variableDeclarationList_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.withClause) {
- return {
- "withClause_mixinTypes": withClause_mixinTypes,
- "flags": flags,
- "kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.classDeclaration) {
@@ -13308,10 +14990,9 @@
classOrMixinDeclaration_typeParameters,
"codeLength": codeLength,
"codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
"simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
};
}
@@ -13325,13 +15006,107 @@
"classTypeAlias_implementsClause": classTypeAlias_implementsClause,
"codeLength": codeLength,
"codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
"simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
};
}
+ if (kind == idl.LinkedNodeKind.comment) {
+ return {
+ "comment_references": comment_references,
+ "comment_tokens": comment_tokens,
+ "comment_type": comment_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.commentReference) {
+ return {
+ "commentReference_identifier": commentReference_identifier,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.compilationUnit) {
+ return {
+ "compilationUnit_declarations": compilationUnit_declarations,
+ "compilationUnit_scriptTag": compilationUnit_scriptTag,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "compilationUnit_directives": compilationUnit_directives,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.conditionalExpression) {
+ return {
+ "conditionalExpression_condition": conditionalExpression_condition,
+ "conditionalExpression_elseExpression":
+ conditionalExpression_elseExpression,
+ "conditionalExpression_thenExpression":
+ conditionalExpression_thenExpression,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.configuration) {
+ return {
+ "configuration_name": configuration_name,
+ "configuration_value": configuration_value,
+ "configuration_uri": configuration_uri,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.constructorDeclaration) {
+ return {
+ "constructorDeclaration_initializers":
+ constructorDeclaration_initializers,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "constructorDeclaration_body": constructorDeclaration_body,
+ "constructorDeclaration_name": constructorDeclaration_name,
+ "constructorDeclaration_parameters": constructorDeclaration_parameters,
+ "constructorDeclaration_redirectedConstructor":
+ constructorDeclaration_redirectedConstructor,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "constructorDeclaration_periodOffset":
+ constructorDeclaration_periodOffset,
+ "constructorDeclaration_returnType": constructorDeclaration_returnType,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
+ return {
+ "constructorFieldInitializer_expression":
+ constructorFieldInitializer_expression,
+ "constructorFieldInitializer_fieldName":
+ constructorFieldInitializer_fieldName,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.constructorName) {
+ return {
+ "constructorName_name": constructorName_name,
+ "constructorName_type": constructorName_type,
+ "constructorName_elementType": constructorName_elementType,
+ "constructorName_element": constructorName_element,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.continueStatement) {
+ return {
+ "continueStatement_label": continueStatement_label,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
if (kind == idl.LinkedNodeKind.declaredIdentifier) {
return {
"annotatedNode_comment": annotatedNode_comment,
@@ -13340,17 +15115,111 @@
"declaredIdentifier_type": declaredIdentifier_type,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
+ return {
+ "defaultFormalParameter_defaultValue":
+ defaultFormalParameter_defaultValue,
+ "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "defaultFormalParameter_kind": defaultFormalParameter_kind,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.doStatement) {
+ return {
+ "doStatement_body": doStatement_body,
+ "doStatement_condition": doStatement_condition,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.dottedName) {
+ return {
+ "dottedName_components": dottedName_components,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.doubleLiteral) {
+ return {
+ "doubleLiteral_value": doubleLiteral_value,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
+ return {
+ "emptyFunctionBody_fake": emptyFunctionBody_fake,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.emptyStatement) {
+ return {
+ "emptyStatement_fake": emptyStatement_fake,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.enumConstantDeclaration) {
return {
"annotatedNode_comment": annotatedNode_comment,
"annotatedNode_metadata": annotatedNode_metadata,
+ "enumConstantDeclaration_name": enumConstantDeclaration_name,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.enumDeclaration) {
+ return {
+ "enumDeclaration_constants": enumDeclaration_constants,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.exportDirective) {
+ return {
+ "namespaceDirective_combinators": namespaceDirective_combinators,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "directive_keywordOffset": directive_keywordOffset,
+ "namespaceDirective_configurations": namespaceDirective_configurations,
+ "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+ "flags": flags,
+ "uriBasedDirective_uri": uriBasedDirective_uri,
+ "kind": kind,
+ "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+ "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
+ return {
+ "expressionFunctionBody_expression": expressionFunctionBody_expression,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.expressionStatement) {
+ return {
+ "expressionStatement_expression": expressionStatement_expression,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.extendsClause) {
+ return {
+ "extendsClause_superclass": extendsClause_superclass,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.fieldDeclaration) {
@@ -13360,7 +15229,183 @@
"fieldDeclaration_fields": fieldDeclaration_fields,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.fieldFormalParameter) {
+ return {
+ "actualType": actualType,
+ "normalFormalParameter_metadata": normalFormalParameter_metadata,
+ "fieldFormalParameter_type": fieldFormalParameter_type,
+ "fieldFormalParameter_typeParameters":
+ fieldFormalParameter_typeParameters,
+ "fieldFormalParameter_formalParameters":
+ fieldFormalParameter_formalParameters,
+ "inheritsCovariant": inheritsCovariant,
+ "normalFormalParameter_identifier": normalFormalParameter_identifier,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "flags": flags,
+ "normalFormalParameter_comment": normalFormalParameter_comment,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
+ return {
+ "forEachParts_iterable": forEachParts_iterable,
+ "forEachPartsWithDeclaration_loopVariable":
+ forEachPartsWithDeclaration_loopVariable,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
+ return {
+ "forEachParts_iterable": forEachParts_iterable,
+ "forEachPartsWithIdentifier_identifier":
+ forEachPartsWithIdentifier_identifier,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forElement) {
+ return {
+ "forMixin_forLoopParts": forMixin_forLoopParts,
+ "forElement_body": forElement_body,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
+ return {
+ "forParts_condition": forParts_condition,
+ "forPartsWithDeclarations_variables":
+ forPartsWithDeclarations_variables,
+ "forParts_updaters": forParts_updaters,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
+ return {
+ "forParts_condition": forParts_condition,
+ "forPartsWithExpression_initialization":
+ forPartsWithExpression_initialization,
+ "forParts_updaters": forParts_updaters,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.forStatement) {
+ return {
+ "forMixin_forLoopParts": forMixin_forLoopParts,
+ "forStatement_body": forStatement_body,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.formalParameterList) {
+ return {
+ "formalParameterList_parameters": formalParameterList_parameters,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionDeclaration) {
+ return {
+ "actualReturnType": actualReturnType,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "functionDeclaration_functionExpression":
+ functionDeclaration_functionExpression,
+ "functionDeclaration_returnType": functionDeclaration_returnType,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
+ return {
+ "functionDeclarationStatement_functionDeclaration":
+ functionDeclarationStatement_functionDeclaration,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionExpression) {
+ return {
+ "actualReturnType": actualReturnType,
+ "functionExpression_body": functionExpression_body,
+ "functionExpression_formalParameters":
+ functionExpression_formalParameters,
+ "functionExpression_typeParameters": functionExpression_typeParameters,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionExpressionInvocation) {
+ return {
+ "invocationExpression_invokeType": invocationExpression_invokeType,
+ "functionExpressionInvocation_function":
+ functionExpressionInvocation_function,
+ "invocationExpression_typeArguments":
+ invocationExpression_typeArguments,
+ "expression_type": expression_type,
+ "flags": flags,
+ "invocationExpression_arguments": invocationExpression_arguments,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionTypeAlias) {
+ return {
+ "actualReturnType": actualReturnType,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "functionTypeAlias_formalParameters":
+ functionTypeAlias_formalParameters,
+ "functionTypeAlias_returnType": functionTypeAlias_returnType,
+ "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
+ "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+ "flags": flags,
+ "kind": kind,
+ "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.functionTypedFormalParameter) {
+ return {
+ "actualType": actualType,
+ "normalFormalParameter_metadata": normalFormalParameter_metadata,
+ "functionTypedFormalParameter_formalParameters":
+ functionTypedFormalParameter_formalParameters,
+ "functionTypedFormalParameter_returnType":
+ functionTypedFormalParameter_returnType,
+ "functionTypedFormalParameter_typeParameters":
+ functionTypedFormalParameter_typeParameters,
+ "inheritsCovariant": inheritsCovariant,
+ "normalFormalParameter_identifier": normalFormalParameter_identifier,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "flags": flags,
+ "normalFormalParameter_comment": normalFormalParameter_comment,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.genericFunctionType) {
+ return {
+ "actualReturnType": actualReturnType,
+ "genericFunctionType_typeParameters":
+ genericFunctionType_typeParameters,
+ "genericFunctionType_returnType": genericFunctionType_returnType,
+ "genericFunctionType_id": genericFunctionType_id,
+ "genericFunctionType_formalParameters":
+ genericFunctionType_formalParameters,
+ "genericFunctionType_type": genericFunctionType_type,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.genericTypeAlias) {
@@ -13372,21 +15417,192 @@
"typeAlias_hasSelfReference": typeAlias_hasSelfReference,
"codeLength": codeLength,
"codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
"flags": flags,
- "nameOffset": nameOffset,
"kind": kind,
- "name": name,
"simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
};
}
+ if (kind == idl.LinkedNodeKind.hideCombinator) {
+ return {
+ "flags": flags,
+ "kind": kind,
+ "names": names,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.ifElement) {
+ return {
+ "ifMixin_condition": ifMixin_condition,
+ "ifElement_thenElement": ifElement_thenElement,
+ "ifElement_elseElement": ifElement_elseElement,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.ifStatement) {
+ return {
+ "ifMixin_condition": ifMixin_condition,
+ "ifStatement_elseStatement": ifStatement_elseStatement,
+ "ifStatement_thenStatement": ifStatement_thenStatement,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.implementsClause) {
+ return {
+ "implementsClause_interfaces": implementsClause_interfaces,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.importDirective) {
+ return {
+ "namespaceDirective_combinators": namespaceDirective_combinators,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "directive_keywordOffset": directive_keywordOffset,
+ "importDirective_prefixOffset": importDirective_prefixOffset,
+ "namespaceDirective_configurations": namespaceDirective_configurations,
+ "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+ "flags": flags,
+ "importDirective_prefix": importDirective_prefix,
+ "uriBasedDirective_uri": uriBasedDirective_uri,
+ "kind": kind,
+ "namespaceDirective_selectedUri": namespaceDirective_selectedUri,
+ "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.indexExpression) {
+ return {
+ "indexExpression_index": indexExpression_index,
+ "indexExpression_target": indexExpression_target,
+ "indexExpression_elementType": indexExpression_elementType,
+ "indexExpression_element": indexExpression_element,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.instanceCreationExpression) {
+ return {
+ "instanceCreationExpression_arguments":
+ instanceCreationExpression_arguments,
+ "instanceCreationExpression_constructorName":
+ instanceCreationExpression_constructorName,
+ "instanceCreationExpression_typeArguments":
+ instanceCreationExpression_typeArguments,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.integerLiteral) {
+ return {
+ "flags": flags,
+ "integerLiteral_value": integerLiteral_value,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.interpolationExpression) {
+ return {
+ "interpolationExpression_expression":
+ interpolationExpression_expression,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.interpolationString) {
+ return {
+ "flags": flags,
+ "interpolationString_value": interpolationString_value,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.isExpression) {
+ return {
+ "isExpression_expression": isExpression_expression,
+ "isExpression_type": isExpression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.label) {
+ return {
+ "label_label": label_label,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.labeledStatement) {
+ return {
+ "labeledStatement_labels": labeledStatement_labels,
+ "labeledStatement_statement": labeledStatement_statement,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
if (kind == idl.LinkedNodeKind.libraryDirective) {
return {
"annotatedNode_comment": annotatedNode_comment,
"annotatedNode_metadata": annotatedNode_metadata,
"libraryDirective_name": libraryDirective_name,
+ "directive_keywordOffset": directive_keywordOffset,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.libraryIdentifier) {
+ return {
+ "libraryIdentifier_components": libraryIdentifier_components,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.listLiteral) {
+ return {
+ "typedLiteral_typeArguments": typedLiteral_typeArguments,
+ "listLiteral_elements": listLiteral_elements,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
+ return {
+ "mapLiteralEntry_key": mapLiteralEntry_key,
+ "mapLiteralEntry_value": mapLiteralEntry_value,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.methodDeclaration) {
+ return {
+ "actualReturnType": actualReturnType,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "methodDeclaration_body": methodDeclaration_body,
+ "methodDeclaration_formalParameters":
+ methodDeclaration_formalParameters,
+ "methodDeclaration_returnType": methodDeclaration_returnType,
+ "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "methodDeclaration_name": methodDeclaration_name,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.methodInvocation) {
+ return {
+ "invocationExpression_invokeType": invocationExpression_invokeType,
+ "methodInvocation_methodName": methodInvocation_methodName,
+ "methodInvocation_target": methodInvocation_target,
+ "invocationExpression_typeArguments":
+ invocationExpression_typeArguments,
+ "expression_type": expression_type,
+ "flags": flags,
+ "invocationExpression_arguments": invocationExpression_arguments,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.mixinDeclaration) {
@@ -13401,423 +15617,20 @@
classOrMixinDeclaration_typeParameters,
"codeLength": codeLength,
"codeOffset": codeOffset,
+ "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
+ "flags": flags,
+ "kind": kind,
"mixinDeclaration_superInvokedNames":
mixinDeclaration_superInvokedNames,
- "flags": flags,
- "nameOffset": nameOffset,
- "kind": kind,
- "name": name,
"simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
};
}
- if (kind == idl.LinkedNodeKind.partDirective) {
- return {
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "flags": flags,
- "nameOffset": nameOffset,
- "uriBasedDirective_uri": uriBasedDirective_uri,
- "kind": kind,
- "name": name,
- "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
- "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
- };
- }
- if (kind == idl.LinkedNodeKind.partOfDirective) {
- return {
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "partOfDirective_libraryName": partOfDirective_libraryName,
- "partOfDirective_uri": partOfDirective_uri,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
- return {
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "topLevelVariableDeclaration_variableList":
- topLevelVariableDeclaration_variableList,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.typeParameter) {
- return {
- "annotatedNode_comment": annotatedNode_comment,
- "annotatedNode_metadata": annotatedNode_metadata,
- "typeParameter_bound": typeParameter_bound,
- "typeParameter_defaultType": typeParameter_defaultType,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "flags": flags,
- "nameOffset": nameOffset,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.switchCase) {
- return {
- "switchMember_statements": switchMember_statements,
- "switchCase_expression": switchCase_expression,
- "switchMember_labels": switchMember_labels,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.switchDefault) {
- return {
- "switchMember_statements": switchMember_statements,
- "switchMember_labels": switchMember_labels,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.annotation) {
- return {
- "annotation_arguments": annotation_arguments,
- "annotation_constructorName": annotation_constructorName,
- "annotation_element": annotation_element,
- "annotation_elementType": annotation_elementType,
- "annotation_name": annotation_name,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.asExpression) {
- return {
- "asExpression_expression": asExpression_expression,
- "asExpression_type": asExpression_type,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.assertInitializer) {
- return {
- "assertInitializer_condition": assertInitializer_condition,
- "assertInitializer_message": assertInitializer_message,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.assertStatement) {
- return {
- "assertStatement_condition": assertStatement_condition,
- "assertStatement_message": assertStatement_message,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.assignmentExpression) {
- return {
- "assignmentExpression_leftHandSide": assignmentExpression_leftHandSide,
- "assignmentExpression_rightHandSide":
- assignmentExpression_rightHandSide,
- "assignmentExpression_elementType": assignmentExpression_elementType,
- "assignmentExpression_element": assignmentExpression_element,
- "assignmentExpression_operator": assignmentExpression_operator,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.awaitExpression) {
- return {
- "awaitExpression_expression": awaitExpression_expression,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.blockFunctionBody) {
- return {
- "blockFunctionBody_block": blockFunctionBody_block,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.breakStatement) {
- return {
- "breakStatement_label": breakStatement_label,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.catchClause) {
- return {
- "catchClause_body": catchClause_body,
- "catchClause_exceptionParameter": catchClause_exceptionParameter,
- "catchClause_exceptionType": catchClause_exceptionType,
- "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.commentReference) {
- return {
- "commentReference_identifier": commentReference_identifier,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.conditionalExpression) {
- return {
- "conditionalExpression_condition": conditionalExpression_condition,
- "conditionalExpression_elseExpression":
- conditionalExpression_elseExpression,
- "conditionalExpression_thenExpression":
- conditionalExpression_thenExpression,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.configuration) {
- return {
- "configuration_name": configuration_name,
- "configuration_value": configuration_value,
- "configuration_uri": configuration_uri,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.constructorFieldInitializer) {
- return {
- "constructorFieldInitializer_expression":
- constructorFieldInitializer_expression,
- "constructorFieldInitializer_fieldName":
- constructorFieldInitializer_fieldName,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.constructorName) {
- return {
- "constructorName_name": constructorName_name,
- "constructorName_type": constructorName_type,
- "constructorName_elementType": constructorName_elementType,
- "constructorName_element": constructorName_element,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.continueStatement) {
- return {
- "continueStatement_label": continueStatement_label,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.defaultFormalParameter) {
- return {
- "defaultFormalParameter_defaultValue":
- defaultFormalParameter_defaultValue,
- "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
- "codeLength": codeLength,
- "codeOffset": codeOffset,
- "defaultFormalParameter_kind": defaultFormalParameter_kind,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.doStatement) {
- return {
- "doStatement_body": doStatement_body,
- "doStatement_condition": doStatement_condition,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.expressionFunctionBody) {
- return {
- "expressionFunctionBody_expression": expressionFunctionBody_expression,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.expressionStatement) {
- return {
- "expressionStatement_expression": expressionStatement_expression,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.extendsClause) {
- return {
- "extendsClause_superclass": extendsClause_superclass,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forEachPartsWithDeclaration) {
- return {
- "forEachParts_iterable": forEachParts_iterable,
- "forEachPartsWithDeclaration_loopVariable":
- forEachPartsWithDeclaration_loopVariable,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forEachPartsWithIdentifier) {
- return {
- "forEachParts_iterable": forEachParts_iterable,
- "forEachPartsWithIdentifier_identifier":
- forEachPartsWithIdentifier_identifier,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forElement) {
- return {
- "forMixin_forLoopParts": forMixin_forLoopParts,
- "forElement_body": forElement_body,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forStatement) {
- return {
- "forMixin_forLoopParts": forMixin_forLoopParts,
- "forStatement_body": forStatement_body,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forPartsWithDeclarations) {
- return {
- "forParts_condition": forParts_condition,
- "forPartsWithDeclarations_variables":
- forPartsWithDeclarations_variables,
- "forParts_updaters": forParts_updaters,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.forPartsWithExpression) {
- return {
- "forParts_condition": forParts_condition,
- "forPartsWithExpression_initialization":
- forPartsWithExpression_initialization,
- "forParts_updaters": forParts_updaters,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.functionDeclarationStatement) {
- return {
- "functionDeclarationStatement_functionDeclaration":
- functionDeclarationStatement_functionDeclaration,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.ifElement) {
- return {
- "ifMixin_condition": ifMixin_condition,
- "ifElement_thenElement": ifElement_thenElement,
- "ifElement_elseElement": ifElement_elseElement,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.ifStatement) {
- return {
- "ifMixin_condition": ifMixin_condition,
- "ifStatement_elseStatement": ifStatement_elseStatement,
- "ifStatement_thenStatement": ifStatement_thenStatement,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.indexExpression) {
- return {
- "indexExpression_index": indexExpression_index,
- "indexExpression_target": indexExpression_target,
- "indexExpression_elementType": indexExpression_elementType,
- "indexExpression_element": indexExpression_element,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.interpolationExpression) {
- return {
- "interpolationExpression_expression":
- interpolationExpression_expression,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.isExpression) {
- return {
- "isExpression_expression": isExpression_expression,
- "isExpression_type": isExpression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.label) {
- return {
- "label_label": label_label,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.mapLiteralEntry) {
- return {
- "mapLiteralEntry_key": mapLiteralEntry_key,
- "mapLiteralEntry_value": mapLiteralEntry_value,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
if (kind == idl.LinkedNodeKind.namedExpression) {
return {
"namedExpression_expression": namedExpression_expression,
"namedExpression_name": namedExpression_name,
"flags": flags,
"kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.nativeClause) {
@@ -13825,7 +15638,6 @@
"nativeClause_name": nativeClause_name,
"flags": flags,
"kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.nativeFunctionBody) {
@@ -13833,7 +15645,21 @@
"nativeFunctionBody_stringLiteral": nativeFunctionBody_stringLiteral,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.nullLiteral) {
+ return {
+ "nullLiteral_fake": nullLiteral_fake,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.onClause) {
+ return {
+ "onClause_superclassConstraints": onClause_superclassConstraints,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.parenthesizedExpression) {
@@ -13843,7 +15669,29 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.partDirective) {
+ return {
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "directive_keywordOffset": directive_keywordOffset,
+ "uriBasedDirective_uriElement": uriBasedDirective_uriElement,
+ "flags": flags,
+ "uriBasedDirective_uri": uriBasedDirective_uri,
+ "kind": kind,
+ "uriBasedDirective_uriContent": uriBasedDirective_uriContent,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.partOfDirective) {
+ return {
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "partOfDirective_libraryName": partOfDirective_libraryName,
+ "partOfDirective_uri": partOfDirective_uri,
+ "directive_keywordOffset": directive_keywordOffset,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.postfixExpression) {
@@ -13855,17 +15703,6 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
- return {
- "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
- "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.prefixExpression) {
@@ -13877,7 +15714,15 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.prefixedIdentifier) {
+ return {
+ "prefixedIdentifier_identifier": prefixedIdentifier_identifier,
+ "prefixedIdentifier_prefix": prefixedIdentifier_prefix,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.propertyAccess) {
@@ -13888,7 +15733,6 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.redirectingConstructorInvocation) {
@@ -13903,7 +15747,13 @@
redirectingConstructorInvocation_element,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.rethrowExpression) {
+ return {
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.returnStatement) {
@@ -13911,7 +15761,55 @@
"returnStatement_expression": returnStatement_expression,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.setOrMapLiteral) {
+ return {
+ "typedLiteral_typeArguments": typedLiteral_typeArguments,
+ "setOrMapLiteral_elements": setOrMapLiteral_elements,
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.showCombinator) {
+ return {
+ "flags": flags,
+ "kind": kind,
+ "names": names,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.simpleFormalParameter) {
+ return {
+ "actualType": actualType,
+ "normalFormalParameter_metadata": normalFormalParameter_metadata,
+ "simpleFormalParameter_type": simpleFormalParameter_type,
+ "inheritsCovariant": inheritsCovariant,
+ "normalFormalParameter_identifier": normalFormalParameter_identifier,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "flags": flags,
+ "normalFormalParameter_comment": normalFormalParameter_comment,
+ "kind": kind,
+ "topLevelTypeInferenceError": topLevelTypeInferenceError,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.simpleIdentifier) {
+ return {
+ "simpleIdentifier_elementType": simpleIdentifier_elementType,
+ "simpleIdentifier_element": simpleIdentifier_element,
+ "expression_type": expression_type,
+ "flags": flags,
+ "simpleIdentifier_offset": simpleIdentifier_offset,
+ "kind": kind,
+ "simpleIdentifier_name": simpleIdentifier_name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
+ return {
+ "flags": flags,
+ "kind": kind,
+ "simpleStringLiteral_value": simpleStringLiteral_value,
};
}
if (kind == idl.LinkedNodeKind.spreadElement) {
@@ -13919,10 +15817,16 @@
"spreadElement_expression": spreadElement_expression,
"flags": flags,
"kind": kind,
- "name": name,
"spreadElement_spreadOperator": spreadElement_spreadOperator,
};
}
+ if (kind == idl.LinkedNodeKind.stringInterpolation) {
+ return {
+ "stringInterpolation_elements": stringInterpolation_elements,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
if (kind == idl.LinkedNodeKind.superConstructorInvocation) {
return {
"superConstructorInvocation_arguments":
@@ -13935,7 +15839,53 @@
superConstructorInvocation_element,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.superExpression) {
+ return {
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.switchCase) {
+ return {
+ "switchMember_statements": switchMember_statements,
+ "switchCase_expression": switchCase_expression,
+ "switchMember_labels": switchMember_labels,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.switchDefault) {
+ return {
+ "switchMember_statements": switchMember_statements,
+ "switchMember_labels": switchMember_labels,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.switchStatement) {
+ return {
+ "switchStatement_members": switchStatement_members,
+ "switchStatement_expression": switchStatement_expression,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.symbolLiteral) {
+ return {
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
+ "names": names,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.thisExpression) {
+ return {
+ "expression_type": expression_type,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.throwExpression) {
@@ -13944,7 +15894,86 @@
"expression_type": expression_type,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.topLevelVariableDeclaration) {
+ return {
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "topLevelVariableDeclaration_variableList":
+ topLevelVariableDeclaration_variableList,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.tryStatement) {
+ return {
+ "tryStatement_catchClauses": tryStatement_catchClauses,
+ "tryStatement_body": tryStatement_body,
+ "tryStatement_finallyBlock": tryStatement_finallyBlock,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.typeArgumentList) {
+ return {
+ "typeArgumentList_arguments": typeArgumentList_arguments,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.typeName) {
+ return {
+ "typeName_typeArguments": typeName_typeArguments,
+ "typeName_name": typeName_name,
+ "typeName_type": typeName_type,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.typeParameter) {
+ return {
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "typeParameter_bound": typeParameter_bound,
+ "typeParameter_name": typeParameter_name,
+ "typeParameter_defaultType": typeParameter_defaultType,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.typeParameterList) {
+ return {
+ "typeParameterList_typeParameters": typeParameterList_typeParameters,
+ "flags": flags,
+ "kind": kind,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.variableDeclaration) {
+ return {
+ "actualType": actualType,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "variableDeclaration_initializer": variableDeclaration_initializer,
+ "variableDeclaration_name": variableDeclaration_name,
+ "inheritsCovariant": inheritsCovariant,
+ "codeLength": codeLength,
+ "codeOffset": codeOffset,
+ "flags": flags,
+ "kind": kind,
+ "topLevelTypeInferenceError": topLevelTypeInferenceError,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.variableDeclarationList) {
+ return {
+ "variableDeclarationList_variables": variableDeclarationList_variables,
+ "annotatedNode_comment": annotatedNode_comment,
+ "annotatedNode_metadata": annotatedNode_metadata,
+ "variableDeclarationList_type": variableDeclarationList_type,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.variableDeclarationStatement) {
@@ -13953,7 +15982,6 @@
variableDeclarationStatement_variables,
"flags": flags,
"kind": kind,
- "name": name,
};
}
if (kind == idl.LinkedNodeKind.whileStatement) {
@@ -13962,7 +15990,13 @@
"whileStatement_condition": whileStatement_condition,
"flags": flags,
"kind": kind,
- "name": name,
+ };
+ }
+ if (kind == idl.LinkedNodeKind.withClause) {
+ return {
+ "withClause_mixinTypes": withClause_mixinTypes,
+ "flags": flags,
+ "kind": kind,
};
}
if (kind == idl.LinkedNodeKind.yieldStatement) {
@@ -13970,131 +16004,6 @@
"yieldStatement_expression": yieldStatement_expression,
"flags": flags,
"kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.simpleIdentifier) {
- return {
- "simpleIdentifier_elementType": simpleIdentifier_elementType,
- "simpleIdentifier_element": simpleIdentifier_element,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.emptyFunctionBody) {
- return {
- "emptyFunctionBody_fake": emptyFunctionBody_fake,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.emptyStatement) {
- return {
- "emptyStatement_fake": emptyStatement_fake,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.nullLiteral) {
- return {
- "nullLiteral_fake": nullLiteral_fake,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.booleanLiteral) {
- return {
- "booleanLiteral_value": booleanLiteral_value,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.hideCombinator) {
- return {
- "names": names,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.showCombinator) {
- return {
- "names": names,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.symbolLiteral) {
- return {
- "names": names,
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.doubleLiteral) {
- return {
- "doubleLiteral_value": doubleLiteral_value,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.rethrowExpression) {
- return {
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.superExpression) {
- return {
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.thisExpression) {
- return {
- "expression_type": expression_type,
- "flags": flags,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.integerLiteral) {
- return {
- "flags": flags,
- "integerLiteral_value": integerLiteral_value,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.interpolationString) {
- return {
- "flags": flags,
- "interpolationString_value": interpolationString_value,
- "kind": kind,
- "name": name,
- };
- }
- if (kind == idl.LinkedNodeKind.simpleStringLiteral) {
- return {
- "flags": flags,
- "kind": kind,
- "name": name,
- "simpleStringLiteral_value": simpleStringLiteral_value,
};
}
throw StateError("Unexpected $kind");
@@ -15258,12 +17167,12 @@
with _LinkedNodeUnitMixin
implements idl.LinkedNodeUnit {
List<LinkedNodeBuilder> _genericFunctionTypes;
+ bool _isNNBD;
bool _isSynthetic;
List<int> _lineStarts;
LinkedNodeBuilder _node;
UnlinkedTokensBuilder _tokens;
String _uriStr;
- bool _isNNBD;
@override
List<LinkedNodeBuilder> get genericFunctionTypes =>
@@ -15280,6 +17189,13 @@
}
@override
+ bool get isNNBD => _isNNBD ??= false;
+
+ set isNNBD(bool value) {
+ this._isNNBD = value;
+ }
+
+ @override
bool get isSynthetic => _isSynthetic ??= false;
set isSynthetic(bool value) {
@@ -15316,28 +17232,21 @@
this._uriStr = value;
}
- @override
- bool get isNNBD => _isNNBD ??= false;
-
- set isNNBD(bool value) {
- this._isNNBD = value;
- }
-
LinkedNodeUnitBuilder(
{List<LinkedNodeBuilder> genericFunctionTypes,
+ bool isNNBD,
bool isSynthetic,
List<int> lineStarts,
LinkedNodeBuilder node,
UnlinkedTokensBuilder tokens,
- String uriStr,
- bool isNNBD})
+ String uriStr})
: _genericFunctionTypes = genericFunctionTypes,
+ _isNNBD = isNNBD,
_isSynthetic = isSynthetic,
_lineStarts = lineStarts,
_node = node,
_tokens = tokens,
- _uriStr = uriStr,
- _isNNBD = isNNBD;
+ _uriStr = uriStr;
/// Flush [informative] data recursively.
void flushInformative() {
@@ -15392,6 +17301,9 @@
if (offset_genericFunctionTypes != null) {
fbBuilder.addOffset(5, offset_genericFunctionTypes);
}
+ if (_isNNBD == true) {
+ fbBuilder.addBool(6, true);
+ }
if (_isSynthetic == true) {
fbBuilder.addBool(3, true);
}
@@ -15407,9 +17319,6 @@
if (offset_uriStr != null) {
fbBuilder.addOffset(0, offset_uriStr);
}
- if (_isNNBD == true) {
- fbBuilder.addBool(6, true);
- }
return fbBuilder.endTable();
}
}
@@ -15431,12 +17340,12 @@
_LinkedNodeUnitImpl(this._bc, this._bcOffset);
List<idl.LinkedNode> _genericFunctionTypes;
+ bool _isNNBD;
bool _isSynthetic;
List<int> _lineStarts;
idl.LinkedNode _node;
idl.UnlinkedTokens _tokens;
String _uriStr;
- bool _isNNBD;
@override
List<idl.LinkedNode> get genericFunctionTypes {
@@ -15447,6 +17356,12 @@
}
@override
+ bool get isNNBD {
+ _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
+ return _isNNBD;
+ }
+
+ @override
bool get isSynthetic {
_isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
return _isSynthetic;
@@ -15477,12 +17392,6 @@
_uriStr ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
return _uriStr;
}
-
- @override
- bool get isNNBD {
- _isNNBD ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
- return _isNNBD;
- }
}
abstract class _LinkedNodeUnitMixin implements idl.LinkedNodeUnit {
@@ -15492,201 +17401,24 @@
if (genericFunctionTypes.isNotEmpty)
_result["genericFunctionTypes"] =
genericFunctionTypes.map((_value) => _value.toJson()).toList();
+ if (isNNBD != false) _result["isNNBD"] = isNNBD;
if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
if (node != null) _result["node"] = node.toJson();
if (tokens != null) _result["tokens"] = tokens.toJson();
if (uriStr != '') _result["uriStr"] = uriStr;
- if (isNNBD != false) _result["isNNBD"] = isNNBD;
return _result;
}
@override
Map<String, Object> toMap() => {
"genericFunctionTypes": genericFunctionTypes,
+ "isNNBD": isNNBD,
"isSynthetic": isSynthetic,
"lineStarts": lineStarts,
"node": node,
"tokens": tokens,
"uriStr": uriStr,
- "isNNBD": isNNBD,
- };
-
- @override
- String toString() => convert.json.encode(toJson());
-}
-
-class LinkedNodeVariablesDeclarationBuilder extends Object
- with _LinkedNodeVariablesDeclarationMixin
- implements idl.LinkedNodeVariablesDeclaration {
- LinkedNodeBuilder _comment;
- bool _isConst;
- bool _isCovariant;
- bool _isFinal;
- bool _isStatic;
-
- @override
- LinkedNodeBuilder get comment => _comment;
-
- set comment(LinkedNodeBuilder value) {
- this._comment = value;
- }
-
- @override
- bool get isConst => _isConst ??= false;
-
- set isConst(bool value) {
- this._isConst = value;
- }
-
- @override
- bool get isCovariant => _isCovariant ??= false;
-
- set isCovariant(bool value) {
- this._isCovariant = value;
- }
-
- @override
- bool get isFinal => _isFinal ??= false;
-
- set isFinal(bool value) {
- this._isFinal = value;
- }
-
- @override
- bool get isStatic => _isStatic ??= false;
-
- set isStatic(bool value) {
- this._isStatic = value;
- }
-
- LinkedNodeVariablesDeclarationBuilder(
- {LinkedNodeBuilder comment,
- bool isConst,
- bool isCovariant,
- bool isFinal,
- bool isStatic})
- : _comment = comment,
- _isConst = isConst,
- _isCovariant = isCovariant,
- _isFinal = isFinal,
- _isStatic = isStatic;
-
- /// Flush [informative] data recursively.
- void flushInformative() {
- _comment?.flushInformative();
- }
-
- /// Accumulate non-[informative] data into [signature].
- void collectApiSignature(api_sig.ApiSignature signature) {
- signature.addBool(this._comment != null);
- this._comment?.collectApiSignature(signature);
- signature.addBool(this._isConst == true);
- signature.addBool(this._isCovariant == true);
- signature.addBool(this._isFinal == true);
- signature.addBool(this._isStatic == true);
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_comment;
- if (_comment != null) {
- offset_comment = _comment.finish(fbBuilder);
- }
- fbBuilder.startTable();
- if (offset_comment != null) {
- fbBuilder.addOffset(0, offset_comment);
- }
- if (_isConst == true) {
- fbBuilder.addBool(1, true);
- }
- if (_isCovariant == true) {
- fbBuilder.addBool(2, true);
- }
- if (_isFinal == true) {
- fbBuilder.addBool(3, true);
- }
- if (_isStatic == true) {
- fbBuilder.addBool(4, true);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _LinkedNodeVariablesDeclarationReader
- extends fb.TableReader<_LinkedNodeVariablesDeclarationImpl> {
- const _LinkedNodeVariablesDeclarationReader();
-
- @override
- _LinkedNodeVariablesDeclarationImpl createObject(
- fb.BufferContext bc, int offset) =>
- new _LinkedNodeVariablesDeclarationImpl(bc, offset);
-}
-
-class _LinkedNodeVariablesDeclarationImpl extends Object
- with _LinkedNodeVariablesDeclarationMixin
- implements idl.LinkedNodeVariablesDeclaration {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _LinkedNodeVariablesDeclarationImpl(this._bc, this._bcOffset);
-
- idl.LinkedNode _comment;
- bool _isConst;
- bool _isCovariant;
- bool _isFinal;
- bool _isStatic;
-
- @override
- idl.LinkedNode get comment {
- _comment ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 0, null);
- return _comment;
- }
-
- @override
- bool get isConst {
- _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 1, false);
- return _isConst;
- }
-
- @override
- bool get isCovariant {
- _isCovariant ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
- return _isCovariant;
- }
-
- @override
- bool get isFinal {
- _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
- return _isFinal;
- }
-
- @override
- bool get isStatic {
- _isStatic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
- return _isStatic;
- }
-}
-
-abstract class _LinkedNodeVariablesDeclarationMixin
- implements idl.LinkedNodeVariablesDeclaration {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (comment != null) _result["comment"] = comment.toJson();
- if (isConst != false) _result["isConst"] = isConst;
- if (isCovariant != false) _result["isCovariant"] = isCovariant;
- if (isFinal != false) _result["isFinal"] = isFinal;
- if (isStatic != false) _result["isStatic"] = isStatic;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "comment": comment,
- "isConst": isConst,
- "isCovariant": isCovariant,
- "isFinal": isFinal,
- "isStatic": isStatic,
};
@override
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 6d9af7a..1230c79 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -1914,16 +1914,18 @@
variantField_13:LinkedNode (id: 13);
- variantField_34:uint (id: 34);
-
variantField_33:uint (id: 33);
- variantField_36:[string] (id: 36);
+ variantField_32:uint (id: 32);
+
+ variantField_35:[string] (id: 35);
variantField_29:LinkedNodeCommentType (id: 29);
variantField_3:[LinkedNode] (id: 3);
+ variantField_19:uint (id: 19);
+
variantField_10:LinkedNode (id: 10);
variantField_26:LinkedNodeFormalParameterKind (id: 26);
@@ -1944,21 +1946,17 @@
kind:LinkedNodeKind (id: 0);
- name:string (id: 37);
+ variantField_36:[string] (id: 36);
variantField_20:string (id: 20);
variantField_31:bool (id: 31);
- variantField_38:UnlinkedTokenType (id: 38);
+ variantField_37:UnlinkedTokenType (id: 37);
- variantField_35:TopLevelInferenceError (id: 35);
+ variantField_34:TopLevelInferenceError (id: 34);
variantField_22:string (id: 22);
-
- variantField_19:uint (id: 19);
-
- variantField_32:LinkedNodeVariablesDeclaration (id: 32);
}
/// Information about a group of libraries linked together, for example because
@@ -2044,6 +2042,8 @@
/// AST in declaration resolver.
genericFunctionTypes:[LinkedNode] (id: 5);
+ isNNBD:bool (id: 6);
+
isSynthetic:bool (id: 3);
/// Offsets of the first character of each line in the source code.
@@ -2054,22 +2054,6 @@
tokens:UnlinkedTokens (id: 1);
uriStr:string (id: 0);
-
- isNNBD:bool (id: 6);
-}
-
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-table LinkedNodeVariablesDeclaration {
- comment:LinkedNode (id: 0);
-
- isConst:bool (id: 1);
-
- isCovariant:bool (id: 2);
-
- isFinal:bool (id: 3);
-
- isStatic:bool (id: 4);
}
/// Information about the resolution of an [UnlinkedReference].
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 3e2a821..3a60a94 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -845,6 +845,7 @@
LinkedNodeKind.variableDeclaration,
LinkedNodeKind.variableDeclarationList,
])
+ @informative
LinkedNode get annotatedNode_comment;
@VariantId(4, variantList: [
@@ -1016,26 +1017,6 @@
@VariantId(8, variant: LinkedNodeKind.classTypeAlias)
LinkedNode get classTypeAlias_withClause;
- @VariantId(34, variantList: [
- LinkedNodeKind.classDeclaration,
- LinkedNodeKind.classTypeAlias,
- LinkedNodeKind.compilationUnit,
- LinkedNodeKind.constructorDeclaration,
- LinkedNodeKind.defaultFormalParameter,
- LinkedNodeKind.enumDeclaration,
- LinkedNodeKind.fieldFormalParameter,
- LinkedNodeKind.functionDeclaration,
- LinkedNodeKind.functionTypeAlias,
- LinkedNodeKind.functionTypedFormalParameter,
- LinkedNodeKind.genericTypeAlias,
- LinkedNodeKind.methodDeclaration,
- LinkedNodeKind.mixinDeclaration,
- LinkedNodeKind.simpleFormalParameter,
- LinkedNodeKind.typeParameter,
- LinkedNodeKind.variableDeclaration,
- ])
- int get codeLength;
-
@VariantId(33, variantList: [
LinkedNodeKind.classDeclaration,
LinkedNodeKind.classTypeAlias,
@@ -1054,12 +1035,34 @@
LinkedNodeKind.typeParameter,
LinkedNodeKind.variableDeclaration,
])
+ @informative
+ int get codeLength;
+
+ @VariantId(32, variantList: [
+ LinkedNodeKind.classDeclaration,
+ LinkedNodeKind.classTypeAlias,
+ LinkedNodeKind.compilationUnit,
+ LinkedNodeKind.constructorDeclaration,
+ LinkedNodeKind.defaultFormalParameter,
+ LinkedNodeKind.enumDeclaration,
+ LinkedNodeKind.fieldFormalParameter,
+ LinkedNodeKind.functionDeclaration,
+ LinkedNodeKind.functionTypeAlias,
+ LinkedNodeKind.functionTypedFormalParameter,
+ LinkedNodeKind.genericTypeAlias,
+ LinkedNodeKind.methodDeclaration,
+ LinkedNodeKind.mixinDeclaration,
+ LinkedNodeKind.simpleFormalParameter,
+ LinkedNodeKind.typeParameter,
+ LinkedNodeKind.variableDeclaration,
+ ])
+ @informative
int get codeOffset;
@VariantId(2, variant: LinkedNodeKind.comment)
List<LinkedNode> get comment_references;
- @VariantId(36, variant: LinkedNodeKind.comment)
+ @VariantId(35, variant: LinkedNodeKind.comment)
List<String> get comment_tokens;
@VariantId(29, variant: LinkedNodeKind.comment)
@@ -1101,9 +1104,16 @@
@VariantId(2, variant: LinkedNodeKind.constructorDeclaration)
List<LinkedNode> get constructorDeclaration_initializers;
+ @VariantId(7, variant: LinkedNodeKind.constructorDeclaration)
+ LinkedNode get constructorDeclaration_name;
+
@VariantId(8, variant: LinkedNodeKind.constructorDeclaration)
LinkedNode get constructorDeclaration_parameters;
+ @VariantId(19, variant: LinkedNodeKind.constructorDeclaration)
+ @informative
+ int get constructorDeclaration_periodOffset;
+
@VariantId(9, variant: LinkedNodeKind.constructorDeclaration)
LinkedNode get constructorDeclaration_redirectedConstructor;
@@ -1146,6 +1156,16 @@
@VariantId(7, variant: LinkedNodeKind.defaultFormalParameter)
LinkedNode get defaultFormalParameter_parameter;
+ @VariantId(17, variantList: [
+ LinkedNodeKind.exportDirective,
+ LinkedNodeKind.importDirective,
+ LinkedNodeKind.libraryDirective,
+ LinkedNodeKind.partDirective,
+ LinkedNodeKind.partOfDirective,
+ ])
+ @informative
+ int get directive_keywordOffset;
+
@VariantId(6, variant: LinkedNodeKind.doStatement)
LinkedNode get doStatement_body;
@@ -1164,6 +1184,9 @@
@VariantId(15, variant: LinkedNodeKind.emptyStatement)
int get emptyStatement_fake;
+ @VariantId(6, variant: LinkedNodeKind.enumConstantDeclaration)
+ LinkedNode get enumConstantDeclaration_name;
+
@VariantId(2, variant: LinkedNodeKind.enumDeclaration)
List<LinkedNode> get enumDeclaration_constants;
@@ -1446,6 +1469,9 @@
@VariantId(7, variant: LinkedNodeKind.methodDeclaration)
LinkedNode get methodDeclaration_formalParameters;
+ @VariantId(10, variant: LinkedNodeKind.methodDeclaration)
+ LinkedNode get methodDeclaration_name;
+
@VariantId(8, variant: LinkedNodeKind.methodDeclaration)
LinkedNode get methodDeclaration_returnType;
@@ -1464,8 +1490,16 @@
@VariantId(36, variant: LinkedNodeKind.mixinDeclaration)
List<String> get mixinDeclaration_superInvokedNames;
- @Id(37)
- String get name;
+ @VariantId(10, variantList: [
+ LinkedNodeKind.classDeclaration,
+ LinkedNodeKind.classTypeAlias,
+ LinkedNodeKind.enumDeclaration,
+ LinkedNodeKind.functionDeclaration,
+ LinkedNodeKind.functionTypeAlias,
+ LinkedNodeKind.genericTypeAlias,
+ LinkedNodeKind.mixinDeclaration,
+ ])
+ LinkedNode get namedCompilationUnitMember_name;
@VariantId(6, variant: LinkedNodeKind.namedExpression)
LinkedNode get namedExpression_expression;
@@ -1473,28 +1507,6 @@
@VariantId(7, variant: LinkedNodeKind.namedExpression)
LinkedNode get namedExpression_name;
- @VariantId(16, variantList: [
- LinkedNodeKind.classDeclaration,
- LinkedNodeKind.classTypeAlias,
- LinkedNodeKind.constructorDeclaration,
- LinkedNodeKind.enumConstantDeclaration,
- LinkedNodeKind.enumDeclaration,
- LinkedNodeKind.exportDirective,
- LinkedNodeKind.fieldFormalParameter,
- LinkedNodeKind.functionDeclaration,
- LinkedNodeKind.functionTypedFormalParameter,
- LinkedNodeKind.functionTypeAlias,
- LinkedNodeKind.genericTypeAlias,
- LinkedNodeKind.importDirective,
- LinkedNodeKind.methodDeclaration,
- LinkedNodeKind.mixinDeclaration,
- LinkedNodeKind.partDirective,
- LinkedNodeKind.simpleFormalParameter,
- LinkedNodeKind.typeParameter,
- LinkedNodeKind.variableDeclaration,
- ])
- int get nameOffset;
-
@VariantId(36, variantList: [
LinkedNodeKind.hideCombinator,
LinkedNodeKind.showCombinator,
@@ -1531,8 +1543,16 @@
LinkedNodeKind.functionTypedFormalParameter,
LinkedNodeKind.simpleFormalParameter,
])
+ @informative
LinkedNode get normalFormalParameter_comment;
+ @VariantId(9, variantList: [
+ LinkedNodeKind.fieldFormalParameter,
+ LinkedNodeKind.functionTypedFormalParameter,
+ LinkedNodeKind.simpleFormalParameter,
+ ])
+ LinkedNode get normalFormalParameter_identifier;
+
@VariantId(4, variantList: [
LinkedNodeKind.fieldFormalParameter,
LinkedNodeKind.functionTypedFormalParameter,
@@ -1621,6 +1641,13 @@
@VariantId(23, variant: LinkedNodeKind.simpleIdentifier)
LinkedNodeType get simpleIdentifier_elementType;
+ @VariantId(20, variant: LinkedNodeKind.simpleIdentifier)
+ String get simpleIdentifier_name;
+
+ @VariantId(16, variant: LinkedNodeKind.simpleIdentifier)
+ @informative
+ int get simpleIdentifier_offset;
+
@VariantId(20, variant: LinkedNodeKind.simpleStringLiteral)
String get simpleStringLiteral_value;
@@ -1636,7 +1663,7 @@
@VariantId(6, variant: LinkedNodeKind.spreadElement)
LinkedNode get spreadElement_expression;
- @VariantId(38, variant: LinkedNodeKind.spreadElement)
+ @VariantId(37, variant: LinkedNodeKind.spreadElement)
UnlinkedTokenType get spreadElement_spreadOperator;
@VariantId(2, variant: LinkedNodeKind.stringInterpolation)
@@ -1678,7 +1705,7 @@
@VariantId(6, variant: LinkedNodeKind.throwExpression)
LinkedNode get throwExpression_expression;
- @VariantId(35, variantList: [
+ @VariantId(34, variantList: [
LinkedNodeKind.simpleFormalParameter,
LinkedNodeKind.variableDeclaration,
])
@@ -1726,6 +1753,9 @@
@VariantId(23, variant: LinkedNodeKind.typeParameter)
LinkedNodeType get typeParameter_defaultType;
+ @VariantId(7, variant: LinkedNodeKind.typeParameter)
+ LinkedNode get typeParameter_name;
+
@VariantId(2, variant: LinkedNodeKind.typeParameterList)
List<LinkedNode> get typeParameterList_typeParameters;
@@ -1750,12 +1780,12 @@
])
int get uriBasedDirective_uriElement;
- @VariantId(32, variant: LinkedNodeKind.variableDeclaration)
- LinkedNodeVariablesDeclaration get variableDeclaration_declaration;
-
@VariantId(6, variant: LinkedNodeKind.variableDeclaration)
LinkedNode get variableDeclaration_initializer;
+ @VariantId(7, variant: LinkedNodeKind.variableDeclaration)
+ LinkedNode get variableDeclaration_name;
+
@VariantId(6, variant: LinkedNodeKind.variableDeclarationList)
LinkedNode get variableDeclarationList_type;
@@ -2035,6 +2065,9 @@
@Id(5)
List<LinkedNode> get genericFunctionTypes;
+ @Id(6)
+ bool get isNNBD;
+
@Id(3)
bool get isSynthetic;
@@ -2051,28 +2084,6 @@
@Id(0)
String get uriStr;
-
- @Id(6)
- bool get isNNBD;
-}
-
-/// Information about a top-level declaration, or a field declaration that
-/// contributes information to [LinkedNodeKind.variableDeclaration].
-abstract class LinkedNodeVariablesDeclaration extends base.SummaryClass {
- @Id(0)
- LinkedNode get comment;
-
- @Id(1)
- bool get isConst;
-
- @Id(2)
- bool get isCovariant;
-
- @Id(3)
- bool get isFinal;
-
- @Id(4)
- bool get isStatic;
}
/// Information about the resolution of an [UnlinkedReference].
diff --git a/pkg/analyzer/lib/src/summary/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index 7bbab6b..cf9c22f 100644
--- a/pkg/analyzer/lib/src/summary/summary_file_builder.dart
+++ b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
@@ -11,7 +11,6 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
@@ -148,15 +147,10 @@
}
void _link2() {
- var rootReference = summary2.Reference.root();
- var dartCoreRef = rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-
var elementFactory = summary2.LinkedElementFactory(
context,
null,
- rootReference,
+ summary2.Reference.root(),
);
var linkResult = summary2.link(elementFactory, inputLibraries);
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 9de3d22..21464da 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -33,6 +33,13 @@
/// Set to `true` when this reader is used to lazily read its unit.
bool isLazy = false;
+ /// Whether we are reading a directive.
+ ///
+ /// [StringLiteral]s in directives are not actual expressions, and don't need
+ /// a type. Moreover, when we are reading `dart:core` imports, the type
+ /// provider is not ready yet, so we cannot access type `String`.
+ bool _isReadingDirective = false;
+
AstBinaryReader(this._unitContext);
InterfaceType get _boolType => _unitContext.typeProvider.boolType;
@@ -82,7 +89,7 @@
typeParameters[i] = astFactory.typeParameter(
_readNode(data.annotatedNode_comment),
_readNodeList(data.annotatedNode_metadata),
- _declaredIdentifier(data),
+ _readNode(data.typeParameter_name),
data.typeParameter_bound != null ? _Tokens.EXTENDS : null,
null,
);
@@ -119,13 +126,6 @@
return _readType(data);
}
- SimpleIdentifier _declaredIdentifier(LinkedNode data) {
- return astFactory.simpleIdentifier(
- TokenFactory.tokenFromString(data.name)..offset = data.nameOffset,
- isDeclaration: true,
- );
- }
-
Element _elementOfComponents(
int rawElementIndex,
LinkedNodeType definingTypeNode,
@@ -151,9 +151,13 @@
}
AdjacentStrings _read_adjacentStrings(LinkedNode data) {
- return astFactory.adjacentStrings(
+ var node = astFactory.adjacentStrings(
_readNodeList(data.adjacentStrings_strings),
- )..staticType = _stringType;
+ );
+ if (!_isReadingDirective) {
+ node.staticType = _stringType;
+ }
+ return node;
}
Annotation _read_annotation(LinkedNode data) {
@@ -312,7 +316,7 @@
_readNodeListLazy(data.annotatedNode_metadata),
AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
_Tokens.CLASS,
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNode(data.classOrMixinDeclaration_typeParameters),
_readNodeLazy(data.classDeclaration_extendsClause),
_readNodeLazy(data.classDeclaration_withClause),
@@ -336,7 +340,7 @@
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
_Tokens.CLASS,
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNode(data.classTypeAlias_typeParameters),
_Tokens.EQ,
AstBinaryFlags.isAbstract(data.flags) ? _Tokens.ABSTRACT : null,
@@ -415,6 +419,7 @@
}
ConstructorDeclaration _read_constructorDeclaration(LinkedNode data) {
+ var name = _readNode(data.constructorDeclaration_name);
var node = astFactory.constructorDeclaration(
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
@@ -422,8 +427,10 @@
AstBinaryFlags.isConst(data.flags) ? _Tokens.CONST : null,
AstBinaryFlags.isFactory(data.flags) ? _Tokens.FACTORY : null,
_readNode(data.constructorDeclaration_returnType),
- data.name.isNotEmpty ? _Tokens.PERIOD : null,
- _declaredIdentifier(data),
+ name != null
+ ? Token(TokenType.PERIOD, data.constructorDeclaration_periodOffset)
+ : null,
+ name,
_readNodeLazy(data.constructorDeclaration_parameters),
_Tokens.choose(
AstBinaryFlags.hasSeparatorColon(data.flags),
@@ -537,7 +544,7 @@
var node = astFactory.enumConstantDeclaration(
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
- _declaredIdentifier(data),
+ _readNode(data.enumConstantDeclaration_name),
);
LazyEnumConstantDeclaration.setData(node, data);
return node;
@@ -548,7 +555,7 @@
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
_Tokens.ENUM,
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_Tokens.OPEN_CURLY_BRACKET,
_readNodeListLazy(data.enumDeclaration_constants),
_Tokens.CLOSE_CURLY_BRACKET,
@@ -559,6 +566,7 @@
ExportDirective _read_exportDirective(LinkedNode data) {
timerAstBinaryReaderDirective.start();
+ _isReadingDirective = true;
try {
var node = astFactory.exportDirective(
_readNode(data.annotatedNode_comment),
@@ -572,6 +580,7 @@
LazyDirective.setData(node, data);
return node;
} finally {
+ _isReadingDirective = false;
timerAstBinaryReaderDirective.stop();
}
}
@@ -626,7 +635,7 @@
FieldFormalParameter _read_fieldFormalParameter(LinkedNode data) {
var node = astFactory.fieldFormalParameter2(
- identifier: _declaredIdentifier(data),
+ identifier: _readNode(data.normalFormalParameter_identifier),
period: _Tokens.PERIOD,
thisKeyword: _Tokens.THIS,
covariantKeyword:
@@ -744,7 +753,7 @@
AstBinaryFlags.isSet(data.flags),
_Tokens.SET,
),
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNodeLazy(data.functionDeclaration_functionExpression),
);
LazyFunctionDeclaration.setData(node, data);
@@ -786,7 +795,7 @@
_readNodeListLazy(data.annotatedNode_metadata),
_Tokens.TYPEDEF,
_readNodeLazy(data.functionTypeAlias_returnType),
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNode(data.functionTypeAlias_typeParameters),
_readNodeLazy(data.functionTypeAlias_formalParameters),
_Tokens.SEMICOLON,
@@ -805,7 +814,7 @@
comment: _readNodeLazy(data.normalFormalParameter_comment),
covariantKeyword:
AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
- identifier: _declaredIdentifier(data),
+ identifier: _readNode(data.normalFormalParameter_identifier),
metadata: _readNodeListLazy(data.normalFormalParameter_metadata),
parameters: _readNodeLazy(
data.functionTypedFormalParameter_formalParameters,
@@ -831,7 +840,7 @@
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
_Tokens.TYPEDEF,
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNode(data.genericTypeAlias_typeParameters),
_Tokens.EQ,
_readNodeLazy(data.genericTypeAlias_functionType),
@@ -887,6 +896,7 @@
ImportDirective _read_importDirective(LinkedNode data) {
timerAstBinaryReaderDirective.start();
+ _isReadingDirective = true;
try {
SimpleIdentifier prefix;
if (data.importDirective_prefix.isNotEmpty) {
@@ -911,6 +921,7 @@
LazyDirective.setData(node, data);
return node;
} finally {
+ _isReadingDirective = false;
timerAstBinaryReaderDirective.stop();
}
}
@@ -1003,6 +1014,7 @@
LibraryDirective _read_libraryDirective(LinkedNode data) {
timerAstBinaryReaderDirective.start();
+ _isReadingDirective = true;
try {
var node = astFactory.libraryDirective(
_readNode(data.annotatedNode_comment),
@@ -1014,6 +1026,7 @@
LazyDirective.setData(node, data);
return node;
} finally {
+ _isReadingDirective = false;
timerAstBinaryReaderDirective.stop();
}
}
@@ -1062,7 +1075,7 @@
_Tokens.SET,
),
AstBinaryFlags.isOperator(data.flags) ? _Tokens.OPERATOR : null,
- _declaredIdentifier(data),
+ _readNode(data.methodDeclaration_name),
_readNode(data.methodDeclaration_typeParameters),
_readNodeLazy(data.methodDeclaration_formalParameters),
AstBinaryFlags.isAbstract(data.flags)
@@ -1095,7 +1108,7 @@
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
_Tokens.MIXIN,
- _declaredIdentifier(data),
+ _readNode(data.namedCompilationUnitMember_name),
_readNode(data.classOrMixinDeclaration_typeParameters),
_readNodeLazy(data.mixinDeclaration_onClause),
_readNodeLazy(data.classOrMixinDeclaration_implementsClause),
@@ -1156,6 +1169,7 @@
PartDirective _read_partDirective(LinkedNode data) {
timerAstBinaryReaderDirective.start();
+ _isReadingDirective = true;
try {
var node = astFactory.partDirective(
_readNode(data.annotatedNode_comment),
@@ -1167,12 +1181,14 @@
LazyDirective.setData(node, data);
return node;
} finally {
+ _isReadingDirective = false;
timerAstBinaryReaderDirective.stop();
}
}
PartOfDirective _read_partOfDirective(LinkedNode data) {
timerAstBinaryReaderDirective.start();
+ _isReadingDirective = true;
try {
var node = astFactory.partOfDirective(
_readNode(data.annotatedNode_comment),
@@ -1186,6 +1202,7 @@
LazyDirective.setData(node, data);
return node;
} finally {
+ _isReadingDirective = false;
timerAstBinaryReaderDirective.stop();
}
}
@@ -1289,7 +1306,7 @@
SimpleFormalParameter _read_simpleFormalParameter(LinkedNode data) {
SimpleFormalParameterImpl node = astFactory.simpleFormalParameter2(
- identifier: _declaredIdentifier(data),
+ identifier: _readNode(data.normalFormalParameter_identifier),
type: _readNode(data.simpleFormalParameter_type),
covariantKeyword:
AstBinaryFlags.isCovariant(data.flags) ? _Tokens.COVARIANT : null,
@@ -1313,7 +1330,8 @@
SimpleIdentifier _read_simpleIdentifier(LinkedNode data) {
return astFactory.simpleIdentifier(
- TokenFactory.tokenFromString(data.name),
+ TokenFactory.tokenFromString(data.simpleIdentifier_name)
+ ..offset = data.simpleIdentifier_offset,
isDeclaration: AstBinaryFlags.isDeclaration(data.flags),
)
..staticElement = _elementOfComponents(
@@ -1324,10 +1342,11 @@
}
SimpleStringLiteral _read_simpleStringLiteral(LinkedNode data) {
- // TODO(scheglov) restore staticType
- return AstTestFactory.string2(data.simpleStringLiteral_value)
-// ..staticType = _stringType
- ;
+ var node = AstTestFactory.string2(data.simpleStringLiteral_value);
+ if (!_isReadingDirective) {
+ node.staticType = _stringType;
+ }
+ return node;
}
SpreadElement _read_spreadElement(LinkedNode data) {
@@ -1466,7 +1485,7 @@
var node = astFactory.typeParameter(
_readNodeLazy(data.annotatedNode_comment),
_readNodeListLazy(data.annotatedNode_metadata),
- _declaredIdentifier(data),
+ _readNode(data.typeParameter_name),
_Tokens.EXTENDS,
_readNodeLazy(data.typeParameter_bound),
);
@@ -1484,7 +1503,7 @@
VariableDeclaration _read_variableDeclaration(LinkedNode data) {
var node = astFactory.variableDeclaration(
- _declaredIdentifier(data),
+ _readNode(data.variableDeclaration_name),
_Tokens.EQ,
_readNodeLazy(data.variableDeclaration_initializer),
);
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index ce98e5d..1b7c7d6 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -31,11 +31,6 @@
/// The list stored [GenericFunctionType]s, as visited in depth-first order.
final List<LinkedNodeBuilder> genericFunctionTypes = [];
- /// This field is set temporary while visiting [FieldDeclaration] or
- /// [TopLevelVariableDeclaration] to store data shared among all variables
- /// in these declarations.
- LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
-
/// Is `true` if the current [ClassDeclaration] has a const constructor,
/// so initializers of final fields should be written.
bool _hasConstConstructor = false;
@@ -315,6 +310,7 @@
LinkedNodeBuilder visitConstructorDeclaration(ConstructorDeclaration node) {
var builder = LinkedNodeBuilder.constructorDeclaration(
constructorDeclaration_initializers: _writeNodeList(node.initializers),
+ constructorDeclaration_name: node.name?.accept(this),
constructorDeclaration_parameters: node.parameters.accept(this),
constructorDeclaration_redirectedConstructor:
node.redirectedConstructor?.accept(this),
@@ -329,11 +325,7 @@
isFactory: node.factoryKeyword != null,
);
if (node.name != null) {
- builder
- ..name = node.name.name
- ..nameOffset = node.name.offset;
- } else {
- builder..nameOffset = node.returnType.offset;
+ builder..constructorDeclaration_periodOffset = node.period.offset;
}
_storeClassMember(builder, node);
_storeCodeOffsetLength(builder, node);
@@ -440,9 +432,8 @@
@override
LinkedNodeBuilder visitEnumConstantDeclaration(EnumConstantDeclaration node) {
var builder = LinkedNodeBuilder.enumConstantDeclaration(
- nameOffset: node.name.offset,
+ enumConstantDeclaration_name: node.name.accept(this),
);
- builder..name = node.name.name;
_storeDeclaration(builder, node);
return builder;
}
@@ -501,11 +492,6 @@
@override
LinkedNodeBuilder visitFieldDeclaration(FieldDeclaration node) {
- _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder(
- isCovariant: node.covariantKeyword != null,
- isStatic: node.isStatic,
- );
-
var builder = LinkedNodeBuilder.fieldDeclaration(
fieldDeclaration_fields: node.fields.accept(this),
);
@@ -515,9 +501,6 @@
);
_storeClassMember(builder, node);
- _variablesDeclaration.comment = builder.annotatedNode_comment;
- _variablesDeclaration = null;
-
return builder;
}
@@ -636,9 +619,9 @@
bodyToStore = null;
}
var builder = LinkedNodeBuilder.functionExpression(
- functionExpression_body: bodyToStore?.accept(this),
- functionExpression_formalParameters: node.parameters?.accept(this),
functionExpression_typeParameters: node.typeParameters?.accept(this),
+ functionExpression_formalParameters: node.parameters?.accept(this),
+ functionExpression_body: bodyToStore?.accept(this),
);
builder.flags = AstBinaryFlags.encode(
isAsync: node.body?.isAsynchronous ?? false,
@@ -699,10 +682,10 @@
genericFunctionTypes.add(null);
var builder = LinkedNodeBuilder.genericFunctionType(
- genericFunctionType_formalParameters: node.parameters.accept(this),
genericFunctionType_returnType: node.returnType?.accept(this),
- genericFunctionType_type: _writeType(node.type),
genericFunctionType_typeParameters: node.typeParameters?.accept(this),
+ genericFunctionType_formalParameters: node.parameters.accept(this),
+ genericFunctionType_type: _writeType(node.type),
);
builder.flags = AstBinaryFlags.encode(
hasQuestion: node.question != null,
@@ -917,13 +900,11 @@
@override
LinkedNodeBuilder visitMethodDeclaration(MethodDeclaration node) {
var builder = LinkedNodeBuilder.methodDeclaration(
- methodDeclaration_formalParameters: node.parameters?.accept(this),
methodDeclaration_returnType: node.returnType?.accept(this),
methodDeclaration_typeParameters: node.typeParameters?.accept(this),
+ methodDeclaration_formalParameters: node.parameters?.accept(this),
+ methodDeclaration_name: node.name.accept(this),
);
- builder
- ..name = node.name.name
- ..nameOffset = node.name.offset;
builder.flags = AstBinaryFlags.encode(
isAbstract: node.body is EmptyFunctionBody,
isAsync: node.body?.isAsynchronous ?? false,
@@ -1171,12 +1152,13 @@
var builder = LinkedNodeBuilder.simpleIdentifier(
simpleIdentifier_element: elementComponents.rawElement,
simpleIdentifier_elementType: elementComponents.definingType,
+ simpleIdentifier_name: node.name,
+ simpleIdentifier_offset: node.offset,
expression_type: _writeType(node.staticType),
);
builder.flags = AstBinaryFlags.encode(
isDeclaration: node is DeclaredSimpleIdentifier,
);
- builder.name = node.name;
return builder;
}
@@ -1280,16 +1262,11 @@
TopLevelVariableDeclaration node) {
timerAstBinaryWriterTopVar.start();
try {
- _variablesDeclaration = LinkedNodeVariablesDeclarationBuilder();
-
var builder = LinkedNodeBuilder.topLevelVariableDeclaration(
topLevelVariableDeclaration_variableList: node.variables?.accept(this),
);
_storeCompilationUnitMember(builder, node);
- _variablesDeclaration.comment = builder.annotatedNode_comment;
- _variablesDeclaration = null;
-
return builder;
} finally {
timerAstBinaryWriterTopVar.stop();
@@ -1331,10 +1308,8 @@
var builder = LinkedNodeBuilder.typeParameter(
typeParameter_bound: node.bound?.accept(this),
typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
+ typeParameter_name: node.name.accept(this),
);
- builder
- ..name = node.name.name
- ..nameOffset = node.name.offset;
_storeDeclaration(builder, node);
_storeCodeOffsetLength(builder, node);
return builder;
@@ -1366,15 +1341,12 @@
}
var builder = LinkedNodeBuilder.variableDeclaration(
+ variableDeclaration_name: node.name.accept(this),
variableDeclaration_initializer: initializer?.accept(this),
- variableDeclaration_declaration: _variablesDeclaration,
);
builder.flags = AstBinaryFlags.encode(
hasInitializer: node.initializer != null,
);
- builder
- ..name = node.name.name
- ..nameOffset = node.name.offset;
builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
_writeActualType(builder, node);
_storeInheritsCovariant(builder, node);
@@ -1383,11 +1355,6 @@
@override
LinkedNodeBuilder visitVariableDeclarationList(VariableDeclarationList node) {
- if (_variablesDeclaration != null) {
- _variablesDeclaration.isConst = node.isConst;
- _variablesDeclaration.isFinal = node.isFinal;
- }
-
var builder = LinkedNodeBuilder.variableDeclarationList(
variableDeclarationList_type: node.type?.accept(this),
variableDeclarationList_variables: _writeNodeList(node.variables),
@@ -1519,6 +1486,7 @@
void _storeDirective(LinkedNodeBuilder builder, Directive node) {
_storeAnnotatedNode(builder, node);
+ builder..directive_keywordOffset = node.keyword.offset;
}
void _storeExpression(LinkedNodeBuilder builder, Expression node) {
@@ -1577,9 +1545,7 @@
LinkedNodeBuilder builder, NamedCompilationUnitMember node) {
_storeCompilationUnitMember(builder, node);
_storeCodeOffsetLength(builder, node);
- builder
- ..name = node.name.name
- ..nameOffset = node.name.offset;
+ builder.namedCompilationUnitMember_name = node.name.accept(this);
}
void _storeNamespaceDirective(
@@ -1588,8 +1554,7 @@
builder
..namespaceDirective_combinators = _writeNodeList(node.combinators)
..namespaceDirective_configurations = _writeNodeList(node.configurations)
- ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node)
- ..nameOffset = node.offset;
+ ..namespaceDirective_selectedUri = LazyDirective.getSelectedUri(node);
}
void _storeNormalFormalParameter(
@@ -1604,9 +1569,8 @@
isRequired: node.requiredKeyword != null,
isVar: keyword?.type == Keyword.VAR,
)
- ..name = node.identifier?.name
- ..nameOffset = node.identifier?.offset ?? 0
- ..normalFormalParameter_metadata = _writeNodeList(node.metadata);
+ ..normalFormalParameter_metadata = _writeNodeList(node.metadata)
+ ..normalFormalParameter_identifier = node.identifier?.accept(this);
}
void _storeStatement(LinkedNodeBuilder builder, Statement node) {}
diff --git a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index c411c79..2845328 100644
--- a/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
@@ -65,6 +65,7 @@
var nameList = node.hiddenNames.map((i) => i.name).toList();
return Combinator.hide(nameList);
}
+ return null;
}).toList();
var exported = linker.builders[uri];
diff --git a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
index f531465..9fa79b02 100644
--- a/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/default_value_resolver.dart
@@ -27,19 +27,12 @@
void resolve() {
for (CompilationUnitElementImpl unit in _libraryElement.units) {
+ for (var classElement in unit.mixins) {
+ _class(classElement);
+ }
+
for (var classElement in unit.types) {
- _classElement = classElement;
-
- for (var element in classElement.constructors) {
- _constructor(element);
- }
-
- for (var element in classElement.methods) {
- _setScopeFromElement(element);
- _method(element);
- }
-
- _classElement = null;
+ _class(classElement);
}
for (var element in unit.functions) {
@@ -48,6 +41,21 @@
}
}
+ void _class(ClassElement classElement) {
+ _classElement = classElement;
+
+ for (var element in classElement.constructors) {
+ _constructor(element);
+ }
+
+ for (var element in classElement.methods) {
+ _setScopeFromElement(element);
+ _method(element);
+ }
+
+ _classElement = null;
+ }
+
void _constructor(ConstructorElementImpl element) {
if (element.isSynthetic) return;
diff --git a/pkg/analyzer/lib/src/summary2/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 13d6511..b8d1771 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -513,12 +513,12 @@
return node.getProperty(_key);
}
- static int getNameOffset(Directive node) {
+ static int getKeywordOffset(Directive node) {
var lazy = get(node);
if (lazy != null) {
- return lazy.data.nameOffset;
+ return lazy.data.directive_keywordOffset;
} else {
- return node.offset;
+ return node.keyword.offset;
}
}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e4f4f7b..7d9f6f5 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -5,7 +5,6 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
-import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -50,12 +49,9 @@
InheritanceManager2 inheritance; // TODO(scheglov) cache it
Linker(this.elementFactory) {
- var dynamicRef = rootReference.getChild('dart:core').getChild('dynamic');
- dynamicRef.element = DynamicElementImpl.instance;
- var neverRef = rootReference.getChild('dart:core').getChild('Never');
- neverRef.element = NeverElementImpl.instance;
-
- linkingBundleContext = LinkingBundleContext(dynamicRef);
+ linkingBundleContext = LinkingBundleContext(
+ elementFactory.dynamicRef,
+ );
bundleContext = LinkedBundleContext.forAst(
elementFactory,
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 94fef40a..9ce9558 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -23,12 +23,23 @@
CoreTypes _coreTypes;
LinkedElementFactory(
- this.analysisContext, this.analysisSession, this.rootReference);
+ this.analysisContext,
+ this.analysisSession,
+ this.rootReference,
+ ) {
+ var dartCoreRef = rootReference.getChild('dart:core');
+ dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
+ dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
+ }
CoreTypes get coreTypes {
return _coreTypes ??= CoreTypes(this);
}
+ Reference get dynamicRef {
+ return rootReference.getChild('dart:core').getChild('dynamic');
+ }
+
bool get hasDartCore {
return libraryMap.containsKey('dart:core');
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 320f151..4f1d87f 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -223,7 +223,7 @@
}
int getDirectiveOffset(AstNode node) {
- return LazyDirective.getNameOffset(node);
+ return LazyDirective.getKeywordOffset(node);
}
Comment getDocumentationComment(AstNode node) {
@@ -406,14 +406,6 @@
}
}
- InterfaceType getInterfaceType(LinkedNodeType linkedType) {
- var type = readType(linkedType);
- if (type is InterfaceType && !type.element.isEnum) {
- return type;
- }
- return null;
- }
-
Comment getLibraryDocumentationComment(CompilationUnit unit) {
for (var directive in unit.directives) {
if (directive is LibraryDirective) {
@@ -573,10 +565,6 @@
return LazyDirective.getSelectedUri(node);
}
- String getStringContent(LinkedNode node) {
- return node.simpleStringLiteral_value;
- }
-
TypeName getSuperclass(AstNode node) {
if (node is ClassDeclaration) {
LazyClassDeclaration.readExtendsClause(_astReader, node);
@@ -749,7 +737,9 @@
}
bool isExplicitlyCovariant(AstNode node) {
- if (node is EnumConstantDeclaration) {
+ if (node is DefaultFormalParameter) {
+ return isExplicitlyCovariant(node.parameter);
+ } else if (node is EnumConstantDeclaration) {
return false;
} else if (node is FormalParameter) {
return node.covariantKeyword != null;
@@ -784,10 +774,6 @@
throw UnimplementedError('${node.runtimeType}');
}
- bool isFunction(LinkedNode node) {
- return node.kind == LinkedNodeKind.functionDeclaration;
- }
-
bool isGenerator(AstNode node) {
if (node is ConstructorDeclaration) {
return false;
@@ -826,10 +812,6 @@
throw UnimplementedError('${node.runtimeType}');
}
- bool isMethod(LinkedNode node) {
- return node.kind == LinkedNodeKind.methodDeclaration;
- }
-
bool isSetter(AstNode node) {
if (node is FunctionDeclaration) {
return node.isSetter;
@@ -868,10 +850,6 @@
}
}
- AstNode readNode(LinkedNode linkedNode) {
- return _astReader.readNode(linkedNode);
- }
-
DartType readType(LinkedNodeType linkedType) {
if (linkedType == null) return null;
@@ -946,7 +924,9 @@
}
void setInheritsCovariant(AstNode node, bool value) {
- if (node is FormalParameter) {
+ if (node is DefaultFormalParameter) {
+ setInheritsCovariant(node.parameter, value);
+ } else if (node is FormalParameter) {
LazyAst.setInheritsCovariant(node, value);
} else if (node is VariableDeclaration) {
LazyAst.setInheritsCovariant(node, value);
@@ -1038,34 +1018,6 @@
throw StateError('Expected to find $indexInLibrary part directive.');
}
- static List<LinkedNode> getTypeParameters(LinkedNode node) {
- LinkedNode typeParameterList;
- var kind = node.kind;
- if (kind == LinkedNodeKind.classTypeAlias) {
- typeParameterList = node.classTypeAlias_typeParameters;
- } else if (kind == LinkedNodeKind.classDeclaration ||
- kind == LinkedNodeKind.mixinDeclaration) {
- typeParameterList = node.classOrMixinDeclaration_typeParameters;
- } else if (kind == LinkedNodeKind.constructorDeclaration) {
- return const [];
- } else if (kind == LinkedNodeKind.functionDeclaration) {
- return getTypeParameters(node.functionDeclaration_functionExpression);
- } else if (kind == LinkedNodeKind.functionExpression) {
- typeParameterList = node.functionExpression_typeParameters;
- } else if (kind == LinkedNodeKind.functionTypeAlias) {
- typeParameterList = node.functionTypeAlias_typeParameters;
- } else if (kind == LinkedNodeKind.genericFunctionType) {
- typeParameterList = node.genericFunctionType_typeParameters;
- } else if (kind == LinkedNodeKind.genericTypeAlias) {
- typeParameterList = node.genericTypeAlias_typeParameters;
- } else if (kind == LinkedNodeKind.methodDeclaration) {
- typeParameterList = node.methodDeclaration_typeParameters;
- } else {
- throw UnimplementedError('$kind');
- }
- return typeParameterList?.typeParameterList_typeParameters;
- }
-
static NullabilitySuffix _nullabilitySuffix(EntityRefNullabilitySuffix data) {
switch (data) {
case EntityRefNullabilitySuffix.starOrIrrelevant:
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index e54f0a3..e9efbb0 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -66,8 +66,15 @@
ClassElementImpl element = reference.element;
node.name.staticElement = element;
+
_createTypeParameterElements(node.typeParameters);
scope = new TypeParameterScope(scope, element);
+
+ node.typeParameters?.accept(this);
+ node.extendsClause?.accept(this);
+ node.implementsClause?.accept(this);
+ node.withClause?.accept(this);
+
scope = new ClassScope(scope, element);
LinkingNodeContext(node, scope);
@@ -79,10 +86,6 @@
}
}
- node.typeParameters?.accept(this);
- node.extendsClause?.accept(this);
- node.implementsClause?.accept(this);
- node.withClause?.accept(this);
node.members.accept(this);
nodesToBuildType.addDeclaration(node);
@@ -359,8 +362,8 @@
LinkingNodeContext(node, scope);
node.returnType?.accept(this);
- node.parameters?.accept(this);
node.typeParameters?.accept(this);
+ node.parameters?.accept(this);
nodesToBuildType.addDeclaration(node);
scope = outerScope;
@@ -377,14 +380,17 @@
MixinElementImpl element = reference.element;
node.name.staticElement = element;
+
_createTypeParameterElements(node.typeParameters);
scope = new TypeParameterScope(scope, element);
- scope = new ClassScope(scope, element);
- LinkingNodeContext(node, scope);
node.typeParameters?.accept(this);
node.onClause?.accept(this);
node.implementsClause?.accept(this);
+
+ scope = new ClassScope(scope, element);
+ LinkingNodeContext(node, scope);
+
node.members.accept(this);
nodesToBuildType.addDeclaration(node);
diff --git a/pkg/analyzer/lib/src/summary2/top_level_inference.dart b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
index eef737d..ac469fd 100644
--- a/pkg/analyzer/lib/src/summary2/top_level_inference.dart
+++ b/pkg/analyzer/lib/src/summary2/top_level_inference.dart
@@ -67,9 +67,11 @@
}
void _variableDeclarationList(VariableDeclarationList node) {
- if (node.isConst && node.type != null) {
+ var typeNode = node.type;
+ if (node.isConst && typeNode != null) {
for (var variable in node.variables) {
if (variable.initializer != null) {
+ InferenceContext.setType(variable.initializer, typeNode.type);
var astResolver = AstResolver(linker, _library, _scope);
astResolver.rewriteAst(variable.initializer);
astResolver.resolve(variable.initializer);
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index e451ec6..2ca6313 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -1118,7 +1118,7 @@
}
// Down cast or legal sideways cast, coercion needed.
- if (rules.isAssignableTo(from, to)) {
+ if (rules.isAssignableTo(from, to, featureSet: _featureSet)) {
return true;
}
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index ce217cf..7a1f121 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -87,6 +87,10 @@
return _node(search, (n) => n is ExpressionStatement);
}
+ FieldDeclaration fieldDeclaration(String search) {
+ return _node(search, (n) => n is FieldDeclaration);
+ }
+
FieldFormalParameter fieldFormalParameter(String search) {
return _node(search, (n) => n is FieldFormalParameter);
}
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index c422ade..7ee7052 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -179,6 +179,15 @@
expect(file.readAsBytesSync(), <int>[98, 98, 98]);
}
+ test_readAsBytesSync_existing_withOverlay_utf8() {
+ // Strings should be encoded as UTF8 when they're written, so when we read
+ // them back as bytes we should see the UTF8-encoded version of the string.
+ String overlayContent = '\u00e5'; // latin small letter a with ring above
+ File file =
+ _file(exists: true, withOverlay: true, overlayContent: overlayContent);
+ expect(file.readAsBytesSync(), <int>[0xc3, 0xa5]);
+ }
+
test_readAsBytesSync_notExisting_withoutOverlay() {
File file = _file(exists: false);
expect(() => file.readAsBytesSync(), throwsA(_isFileSystemException));
@@ -506,7 +515,7 @@
expect(child, isNotNull);
}
- test_getChildren() {
+ test_getChildren_existing() {
Folder folder = _folder(exists: true);
Folder child1 = _folder(
exists: true, path: provider.pathContext.join(folder.path, 'lib'));
@@ -523,6 +532,13 @@
unorderedEquals([child1.path, child2.path, child3.path]));
}
+ test_getChildren_nonExisting_withOverlay() {
+ File file = _file(exists: false, withOverlay: true);
+ List<Resource> children = file.parent.parent.getChildren();
+ expect(children, hasLength(1));
+ expect(children[0], _isFolder);
+ }
+
test_isOrContains_false() {
Folder folder = _folder(exists: true);
expect(folder.isOrContains(baseProvider.convertPath('/foo/baz')), isFalse);
@@ -662,20 +678,28 @@
expect(file.exists, isTrue);
}
- test_getFolder_existing() {
+ test_getFolder_existing_withoutOverlay() {
Folder folder = _folder(exists: true);
expect(folder, isNotNull);
expect(folder.path, defaultFolderPath);
expect(folder.exists, isTrue);
}
- test_getFolder_notExisting() {
+ test_getFolder_notExisting_withoutOverlay() {
Folder folder = _folder(exists: false);
expect(folder, isNotNull);
expect(folder.path, defaultFolderPath);
expect(folder.exists, isFalse);
}
+ test_getFolder_notExisting_withOverlay() {
+ File file = _file(exists: false, withOverlay: true);
+ Folder folder = file.parent;
+ expect(folder, isNotNull);
+ expect(folder.path, defaultFolderPath);
+ expect(folder.exists, isTrue);
+ }
+
test_getModificationTimes_withoutOverlay() async {
Source source = _file(exists: true).createSource();
List<int> times = await provider.getModificationTimes([source]);
@@ -688,36 +712,43 @@
expect(times, [42]);
}
- test_getResource_existingFile_withoutOverlay() {
+ test_getResource_file_existing_withoutOverlay() {
String path = _file(exists: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_existingFile_withOverlay() {
+ test_getResource_file_existing_withOverlay() {
String path = _file(exists: true, withOverlay: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_existingFolder() {
- String path = _folder(exists: true).path;
- Resource resource = provider.getResource(path);
- expect(resource, _isFolder);
- }
-
- test_getResource_notExisting_withoutOverlay() {
+ test_getResource_file_notExisting_withoutOverlay() {
String path = _file(exists: false).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
- test_getResource_notExisting_withOverlay() {
+ test_getResource_file_notExisting_withOverlay() {
String path = _file(exists: false, withOverlay: true).path;
Resource resource = provider.getResource(path);
expect(resource, _isFile);
}
+ test_getResource_folder_existing() {
+ String path = _folder(exists: true).path;
+ Resource resource = provider.getResource(path);
+ expect(resource, _isFolder);
+ }
+
+ test_getResource_folder_nonExisting_withOverlay() {
+ String filePath = _file(exists: false, withOverlay: true).path;
+ String folderPath = provider.pathContext.dirname(filePath);
+ Resource resource = provider.getResource(folderPath);
+ expect(resource, _isFolder);
+ }
+
test_getStateLocation_uniqueness() {
String idOne = 'one';
Folder folderOne = provider.getStateLocation(idOne);
@@ -763,7 +794,8 @@
{@required bool exists,
String content,
String path,
- bool withOverlay = false}) {
+ bool withOverlay = false,
+ String overlayContent = 'bbb'}) {
if (path == null) {
path = defaultFilePath;
} else {
@@ -773,7 +805,7 @@
baseProvider.newFile(path, content ?? 'a');
}
if (withOverlay) {
- provider.setOverlay(path, content: 'bbb', modificationStamp: 42);
+ provider.setOverlay(path, content: overlayContent, modificationStamp: 42);
}
return provider.getFile(path);
}
diff --git a/pkg/analyzer/test/generated/analysis_context_factory.dart b/pkg/analyzer/test/generated/analysis_context_factory.dart
index b70df9d..b7ae647 100644
--- a/pkg/analyzer/test/generated/analysis_context_factory.dart
+++ b/pkg/analyzer/test/generated/analysis_context_factory.dart
@@ -245,7 +245,7 @@
// Stream
ClassElementImpl streamElement =
ElementFactory.classElement2("Stream", ["T"]);
- streamElement.abstract = true;
+ streamElement.isAbstract = true;
streamElement.constructors = <ConstructorElement>[
ElementFactory.constructorElement2(streamElement, null)
];
@@ -365,7 +365,7 @@
TopLevelVariableElement piElement = ElementFactory.topLevelVariableElement3(
"PI", true, false, provider.doubleType);
ClassElementImpl randomElement = ElementFactory.classElement2("Random");
- randomElement.abstract = true;
+ randomElement.isAbstract = true;
ConstructorElementImpl randomConstructor =
ElementFactory.constructorElement2(randomElement, null);
randomConstructor.factory = true;
diff --git a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 4a01b55..f92a108 100644
--- a/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
@@ -16,12 +16,14 @@
@reflectiveTest
class CheckedModeCompileTimeErrorCodeTest extends DriverResolutionTest {
test_assertion_throws() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(int x, int y) : assert(x < y);
}
var v = const A(3, 2);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 61, 13),
+ ]);
}
test_fieldFormalParameterAssignableToField_extends() async {
@@ -46,13 +48,15 @@
test_fieldFormalParameterAssignableToField_fieldType_unresolved_null() async {
// Null always passes runtime type checks, even when the type is
// unresolved.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final Unresolved x;
const A(String this.x);
}
var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
+ ]);
}
test_fieldFormalParameterAssignableToField_implements() async {
@@ -151,7 +155,7 @@
test_fieldFormalParameterAssignableToField_typedef() async {
// foo has the runtime type dynamic -> dynamic, so it is not assignable
// to A.f.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
typedef String Int2String(int x);
class A {
final Int2String f;
@@ -159,7 +163,9 @@
}
foo(x) => 1;
var v = const A(foo);
-''', [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 116, 3),
+ ]);
}
test_fieldFormalParameterAssignableToField_typeSubstitution() async {
@@ -175,15 +181,18 @@
}
test_fieldFormalParameterNotAssignableToField() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final int x;
const A(this.x);
}
var v = const A('foo');
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 62,
+ 5),
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
]);
}
@@ -191,7 +200,7 @@
// According to checked-mode type checking rules, a value of type A is not
// assignable to a field of type B, because B extends A (the subtyping
// relationship is in the wrong direction).
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A();
}
@@ -204,37 +213,47 @@
}
const A u = const A();
var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 143,
+ 1),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_fieldType() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final int x;
const A(this.x);
}
var v = const A('foo');
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 62,
+ 5),
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 62, 5),
]);
}
test_fieldFormalParameterNotAssignableToField_fieldType_unresolved() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final Unresolved x;
const A(String this.x);
}
var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 18, 10),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_implements() async {
// According to checked-mode type checking rules, a value of type A is not
// assignable to a field of type B, because B implements A (the subtyping
// relationship is in the wrong direction).
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A();
}
@@ -245,61 +264,84 @@
}
const A u = const A();
var v = const C(u);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 132,
+ 1),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_list() async {
// <num>[1, 2, 3] has type List<num>, which is not a subtype of List<int>.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(List<int> x);
}
const dynamic w = const <num>[1, 2, 3];
var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 92,
+ 1),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_map_keyMismatch() async {
// <num, int>{1: 2} has type Map<num, int>, which is not a subtype of
// Map<int, int>.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(Map<int, int> x);
}
const dynamic w = const <num, int>{1: 2};
var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 98,
+ 1),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_map_valueMismatch() async {
// <int, num>{1: 2} has type Map<int, num>, which is not a subtype of
// Map<int, int>.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(Map<int, int> x);
}
const dynamic w = const <int, num>{1: 2};
var x = const A(w);
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 98,
+ 1),
+ ]);
}
test_fieldFormalParameterNotAssignableToField_optional() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final int x;
const A([this.x = 'foo']);
}
var v = const A();
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticTypeWarningCode.INVALID_ASSIGNMENT
+ error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 45, 5),
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 64,
+ 9),
]);
}
test_fieldFormalParameterNotAssignableToField_typedef() async {
// foo has the runtime type String -> int, so it should not be assignable
// to A.f (A.f requires it to be int -> String).
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
typedef String Int2String(int x);
class A {
final Int2String f;
@@ -308,35 +350,47 @@
int foo(String x) => 1;
var v = const A(foo);
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 127, 3),
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 127,
+ 3),
]);
}
test_fieldInitializerNotAssignable() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
final int x;
const A() : x = '';
}
''', [
- CheckedModeCompileTimeErrorCode.CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
- StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE
+ error(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 43, 2),
+ error(
+ CheckedModeCompileTimeErrorCode
+ .CONST_FIELD_INITIALIZER_NOT_ASSIGNABLE,
+ 43,
+ 2),
]);
}
test_fieldTypeMismatch() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(x) : y = x;
final int y;
}
var v = const A('foo');
-''', [CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH]);
+''', [
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+ 57,
+ 14),
+ ]);
}
test_fieldTypeMismatch_generic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
r'''
class C<T> {
final T x = y;
@@ -346,24 +400,30 @@
var v = const C<String>();
''',
[
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
- StaticTypeWarningCode.INVALID_ASSIGNMENT
+ error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+ error(
+ CheckedModeCompileTimeErrorCode
+ .CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
+ 70,
+ 17),
],
);
}
test_fieldTypeMismatch_unresolved() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(x) : y = x;
final Unresolved y;
}
var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
+ ]);
}
test_fieldTypeOk_generic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
r'''
class C<T> {
final T x = y;
@@ -372,7 +432,9 @@
const int y = 1;
var v = const C<int>();
''',
- [StaticTypeWarningCode.INVALID_ASSIGNMENT],
+ [
+ error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 27, 1),
+ ],
);
}
@@ -389,40 +451,50 @@
test_fieldTypeOk_unresolved_null() async {
// Null always passes runtime type checks, even when the type is
// unresolved.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(x) : y = x;
final Unresolved y;
}
var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 40, 10),
+ ]);
}
test_listElementTypeNotAssignable() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <String> [42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 24, 2),
+ ]);
}
test_listLiteral_inferredElementType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const Object x = [1];
const List<String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+ error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 41, 1),
+ ]);
}
test_mapLiteral_inferredKeyType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const Object x = {1: 1};
const Map<String, dynamic> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+ error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+ ]);
}
test_mapLiteral_inferredValueType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const Object x = {1: 1};
const Map<dynamic, String> y = x;
-''', [CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH]);
+''', [
+ error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 52, 1),
+ ]);
}
test_parameterAssignable_null() async {
@@ -445,59 +517,71 @@
test_parameterAssignable_undefined_null() async {
// Null always passes runtime type checks, even when the type is
// unresolved.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(Unresolved x);
}
var v = const A(null);
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
+ ]);
}
test_parameterNotAssignable() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(int x);
}
var v = const A('foo');
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 46,
+ 5),
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 46, 5),
]);
}
test_parameterNotAssignable_typeSubstitution() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<T> {
const A(T x);
}
var v = const A<int>('foo');
''', [
- CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
- StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 52, 5),
+ error(
+ CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
+ 52,
+ 5),
]);
}
test_parameterNotAssignable_undefined() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A(Unresolved x);
}
var v = const A('foo');
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 20, 10),
+ ]);
}
test_redirectingConstructor_paramTypeMismatch() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
const A.a1(x) : this.a2(x);
const A.a2(String x);
}
var v = const A.a1(0);
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 74, 13),
+ ]);
}
test_superConstructor_paramTypeMismatch() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class C {
final double d;
const C(this.d);
@@ -506,7 +590,9 @@
const D(d) : super(d);
}
const f = const D('0.0');
-''', [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+''', [
+ error(CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION, 106, 14),
+ ]);
}
test_topLevelVarAssignable_null() async {
@@ -518,23 +604,27 @@
test_topLevelVarAssignable_undefined_null() async {
// Null always passes runtime type checks, even when the type is
// unresolved.
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const Unresolved x = null;
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
+ ]);
}
test_topLevelVarNotAssignable() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const int x = 'foo';
''', [
- CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
- StaticTypeWarningCode.INVALID_ASSIGNMENT
+ error(CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH, 10, 1),
+ error(StaticTypeWarningCode.INVALID_ASSIGNMENT, 14, 5),
]);
}
test_topLevelVarNotAssignable_undefined() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const Unresolved x = 'foo';
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+ error(StaticWarningCode.UNDEFINED_CLASS, 6, 10),
+ ]);
}
}
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index e11ba55..e1db296 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code.dart
@@ -2726,7 +2726,6 @@
}
''', [
error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
]);
}
@@ -5134,12 +5133,17 @@
}
test_typeAliasCannotReferenceItself_typeVariableBounds() async {
+ var errors = [
+ error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+ ];
+ if (!AnalysisDriver.useSummary2) {
+ errors.add(
+ error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
+ );
+ }
await assertErrorsInCode('''
typedef A<T extends A<int>>();
-''', [
- error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
- error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
- ]);
+''', errors);
}
test_typeArgumentNotMatchingBounds_const() async {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 57e5769..7346b25 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -79,21 +79,21 @@
class CompileTimeErrorCodeTest_WithUIAsCode extends DriverResolutionTest {
test_defaultValueInFunctionTypeAlias_new_named() async {
// This test used to fail with UI as code enabled. Test the fix here.
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
typedef F = int Function({Map<String, String> m: const {}});
''', [
- ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
+ error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 47, 1),
]);
}
test_defaultValueInFunctionTypeAlias_new_named_ambiguous() async {
// Test that the strong checker does not crash when given an ambiguous
// set or map literal.
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
typedef F = int Function({Object m: const {1, 2: 3}});
''', [
- ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
- CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH,
+ error(ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE, 34, 1),
+ error(CompileTimeErrorCode.AMBIGUOUS_SET_OR_MAP_LITERAL_BOTH, 36, 15),
]);
}
}
@@ -101,236 +101,298 @@
@reflectiveTest
class ControlFlowCollectionsTest extends DriverResolutionTest {
test_awaitForIn_declaredVariableWrongType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
import 'dart:async';
f() async {
Stream<String> stream;
await for (int i in stream) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 75, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 80, 6),
+ ]);
}
test_awaitForIn_existingVariableWrongType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
import 'dart:async';
f() async {
Stream<String> stream;
int i;
await for (i in stream) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 64, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 85, 6),
+ ]);
}
test_awaitForIn_notStream() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
f() async {
await for (var i in true) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 29, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 34, 4),
+ ]);
}
test_duplicateDefinition_for_initializers() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
for (int i = 0, i = 0; i < 5;) {}
}
-''', [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+''', [
+ error(CompileTimeErrorCode.DUPLICATE_DEFINITION, 24, 1),
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 24, 1),
+ ]);
}
test_expectedOneListTypeArgument() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
main() {
<int, int>[];
-}''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+}''', [
+ error(StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS, 11, 10),
+ ]);
}
test_expectedOneSetTypeArgument() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
main() {
<int, int, int>{2, 3};
-}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]);
+}''', [
+ error(StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS, 11, 15),
+ ]);
}
test_expectedTwoMapTypeArguments_three_ambiguous() async {
// TODO(brianwilkerson) We probably need a new error code for "expected
// either one or two type arguments" to handle the ambiguous case.
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
main() {
<int, int, int>{};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+ error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+ ]);
}
test_expectedTwoMapTypeArguments_three_map() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
main() {
<int, int, int>{1:2};
-}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+}''', [
+ error(StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS, 11, 15),
+ ]);
}
test_forIn_declaredVariableWrongType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
f() {
for (int i in <String>[]) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 22, 10),
+ ]);
}
test_forIn_existingVariableWrongType() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
f() {
int i;
for (i in <String>[]) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 27, 10),
+ ]);
}
test_forIn_notIterable() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
f() {
for (var i in true) {}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE, 22, 4),
+ ]);
}
test_forIn_typeBoundBad() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
class Foo<T extends Iterable<int>> {
void method(T iterable) {
for (String i in iterable) {}
}
}
-''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 81, 1),
+ error(StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE, 86, 8),
+ ]);
}
test_forInWithConstVariable_forEach_identifier() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
const x = 0;
for (x in [0, 1, 2]) {}
}
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 14, 1),
+ error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 28, 1),
+ ]);
}
test_forInWithConstVariable_forEach_loopVariable() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
for (const x in [0, 1, 2]) {}
}
-''', [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+''', [
+ error(CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, 13, 7),
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 19, 1),
+ ]);
}
test_generalizedVoid_useOfInForeachIterableError() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
void main() {
void x;
for (var v in x) {}
}
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 35, 1),
+ error(StaticWarningCode.USE_OF_VOID_RESULT, 40, 1),
+ ]);
}
test_generalizedVoid_useOfVoidInForeachVariableError() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
void main() {
void x;
var y;
for (y in x) {}
}
-''', [StaticWarningCode.USE_OF_VOID_RESULT]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 30, 1),
+ error(StaticWarningCode.USE_OF_VOID_RESULT, 45, 1),
+ ]);
}
test_invalidTypeArgumentInConstList() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<E> {
m() {
return const <E>[];
}
}
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
+''', [
+ error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST, 39, 1),
+ ]);
}
test_invalidTypeArgumentInConstMap_key() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<E> {
m() {
return const <E, String>{};
}
}
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+ error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 39, 1),
+ ]);
}
test_invalidTypeArgumentInConstMap_value() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<E> {
m() {
return const <String, E>{};
}
}
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+''', [
+ error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP, 47, 1),
+ ]);
}
test_invalidTypeArgumentInConstSet_class() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<E> {
m() {
return const <E>{};
}
}
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+ error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+ ]);
}
test_listElementTypeNotAssignable_const() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <String>[42];
-''', [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+ ]);
}
test_mapValueTypeNotAssignable_const() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <String, String>{'a' : 2};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 1),
+ ]);
}
test_nonBoolCondition_for_declaration() async {
// https://github.com/dart-lang/sdk/issues/24713
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
for (int i = 0; 3;) {}
}
-''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 17, 1),
+ error(StaticTypeWarningCode.NON_BOOL_CONDITION, 24, 1),
+ ]);
}
test_nonBoolCondition_for_expression() async {
// https://github.com/dart-lang/sdk/issues/24713
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
int i;
for (i = 0; 3;) {}
-}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+}''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 12, 1),
+ error(StaticTypeWarningCode.NON_BOOL_CONDITION, 29, 1),
+ ]);
}
test_nonConstMapAsExpressionStatement_begin() async {
// TODO(danrubel) Fasta is not recovering well.
// Ideally we would produce a single diagnostic:
// CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
{'a' : 0, 'b' : 1}.length;
}
''', [
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER
+ error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+ error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 26, 1),
]);
}
@@ -338,43 +400,47 @@
// TODO(danrubel) Fasta is not recovering well.
// Ideally we would produce a single diagnostic:
// CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
f() {
{'a' : 0, 'b' : 1};
}
''', [
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.UNEXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.MISSING_IDENTIFIER
+ error(ParserErrorCode.EXPECTED_TOKEN, 9, 3),
+ error(ParserErrorCode.EXPECTED_TOKEN, 13, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 13, 1),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 13, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 15, 1),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 16, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 16, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 16, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 18, 3),
+ error(ParserErrorCode.UNEXPECTED_TOKEN, 22, 1),
+ error(ParserErrorCode.MISSING_IDENTIFIER, 22, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 22, 1),
+ error(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
]);
}
test_setElementTypeNotAssignable_const() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
+ ]);
}
}
@reflectiveTest
class InvalidTypeArgumentInConstSetTest extends DriverResolutionTest {
test_class() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A<E> {
m() {
return const <E>{};
}
}
-''', [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+''', [
+ error(CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET, 39, 1),
+ ]);
}
}
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index fe23034..11fa1ce 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -1901,7 +1901,7 @@
}
test_infer_mixin_with_substitution_functionType_new_syntax() async {
- await assertNoErrorsInCode('''
+ await assertErrorsInCode('''
abstract class A<T> {}
class B {}
@@ -1909,7 +1909,13 @@
mixin M<T, U> on A<T Function(U)> {}
class C extends A<int Function(String)> with M {}
-''');
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 47,
+ 1,
+ ),
+ ]);
CompilationUnit unit = result.unit;
ClassElement classC =
resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 20e6f2d..26fff6d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -108,12 +108,6 @@
}
@override
- void beginClassOrMixinBody(Token token) {
- super.beginClassOrMixinBody(token);
- begin('ClassOrMixinBody');
- }
-
- @override
void beginClassDeclaration(
Token beginToken, Token abstractToken, Token name) {
super.beginClassDeclaration(beginToken, abstractToken, name);
@@ -121,6 +115,12 @@
}
@override
+ void beginClassOrMixinBody(Token token) {
+ super.beginClassOrMixinBody(token);
+ begin('ClassOrMixinBody');
+ }
+
+ @override
void beginClassOrNamedMixinApplication(Token token) {
super.beginClassOrNamedMixinApplication(token);
begin('ClassOrNamedMixinApplication');
@@ -201,6 +201,12 @@
}
@override
+ void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+ super.beginExtensionDeclaration(extensionKeyword, name);
+ begin('ExtensionDeclaration');
+ }
+
+ @override
void beginFactoryMethod(
Token lastConsumed, Token externalToken, Token constToken) {
super.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -232,18 +238,6 @@
}
@override
- void beginForStatement(Token token) {
- super.beginForStatement(token);
- begin('ForStatement');
- }
-
- @override
- void beginForStatementBody(Token token) {
- super.beginForStatementBody(token);
- begin('ForStatementBody');
- }
-
- @override
void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
Token covariantToken, Token varFinalOrConst) {
super.beginFormalParameter(
@@ -258,15 +252,15 @@
}
@override
- void beginIfControlFlow(Token ifToken) {
- super.beginIfControlFlow(ifToken);
- begin('IfControlFlow');
+ void beginForStatement(Token token) {
+ super.beginForStatement(token);
+ begin('ForStatement');
}
@override
- void beginLocalFunctionDeclaration(Token token) {
- super.beginLocalFunctionDeclaration(token);
- begin('LocalFunctionDeclaration');
+ void beginForStatementBody(Token token) {
+ super.beginForStatementBody(token);
+ begin('ForStatementBody');
}
@override
@@ -306,6 +300,12 @@
}
@override
+ void beginIfControlFlow(Token ifToken) {
+ super.beginIfControlFlow(ifToken);
+ begin('IfControlFlow');
+ }
+
+ @override
void beginIfStatement(Token token) {
super.beginIfStatement(token);
begin('IfStatement');
@@ -360,6 +360,12 @@
}
@override
+ void beginLocalFunctionDeclaration(Token token) {
+ super.beginLocalFunctionDeclaration(token);
+ begin('LocalFunctionDeclaration');
+ }
+
+ @override
void beginMember() {
expectIn('ClassOrMixinBody');
super.beginMember();
@@ -602,12 +608,6 @@
}
@override
- void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
- end('ClassOrMixinBody');
- super.endClassOrMixinBody(memberCount, beginToken, endToken);
- }
-
- @override
void endClassDeclaration(Token beginToken, Token endToken) {
end('ClassDeclaration');
end('ClassOrNamedMixinApplication');
@@ -615,6 +615,12 @@
}
@override
+ void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+ end('ClassOrMixinBody');
+ super.endClassOrMixinBody(memberCount, beginToken, endToken);
+ }
+
+ @override
void endCombinators(int count) {
end('Combinators');
super.endCombinators(count);
@@ -690,6 +696,12 @@
}
@override
+ void endExtensionDeclaration(Token onKeyword, Token token) {
+ super.endExtensionDeclaration(onKeyword, token);
+ end('ExtensionDeclaration');
+ }
+
+ @override
void endFactoryMethod(
Token beginToken, Token factoryKeyword, Token endToken) {
end('FactoryMethod');
@@ -718,12 +730,6 @@
}
@override
- void endForInControlFlow(Token token) {
- end('ForControlFlow');
- super.endForInControlFlow(token);
- }
-
- @override
void endForIn(Token endToken) {
end('ForStatement');
super.endForIn(endToken);
@@ -736,24 +742,18 @@
}
@override
+ void endForInControlFlow(Token token) {
+ end('ForControlFlow');
+ super.endForInControlFlow(token);
+ }
+
+ @override
void endForInExpression(Token token) {
end('ForInExpression');
super.endForInExpression(token);
}
@override
- void endForStatement(Token endToken) {
- end('ForStatement');
- super.endForStatement(endToken);
- }
-
- @override
- void endForStatementBody(Token token) {
- end('ForStatementBody');
- super.endForStatementBody(token);
- }
-
- @override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
end('FormalParameter');
@@ -769,9 +769,15 @@
}
@override
- void endLocalFunctionDeclaration(Token endToken) {
- end('LocalFunctionDeclaration');
- super.endLocalFunctionDeclaration(endToken);
+ void endForStatement(Token endToken) {
+ end('ForStatement');
+ super.endForStatement(endToken);
+ }
+
+ @override
+ void endForStatementBody(Token token) {
+ end('ForStatementBody');
+ super.endForStatementBody(token);
}
@override
@@ -878,6 +884,12 @@
}
@override
+ void endLocalFunctionDeclaration(Token endToken) {
+ end('LocalFunctionDeclaration');
+ super.endLocalFunctionDeclaration(endToken);
+ }
+
+ @override
void endMember() {
end('Member');
super.endMember();
@@ -1116,33 +1128,23 @@
}
@override
- void handleIdentifierList(int count) {
- expectInOneOf(['Hide', 'Show']);
- super.handleIdentifierList(count);
- }
-
- @override
void handleDottedName(int count, Token firstIdentifier) {
expectIn('ConditionalUri');
super.handleDottedName(count, firstIdentifier);
}
@override
- void handleRecoverClassHeader() {
- expectIn('ClassDeclaration');
- listener.handleRecoverClassHeader();
+ void handleIdentifierList(int count) {
+ expectInOneOf(['Hide', 'Show']);
+ super.handleIdentifierList(count);
}
@override
- void handleRecoverImport(Token semicolon) {
- expectIn('CompilationUnit');
- listener.handleRecoverImport(semicolon);
- }
-
- @override
- void handleRecoverMixinHeader() {
- expectIn('MixinDeclaration');
- listener.handleRecoverMixinHeader();
+ void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+ // This event normally happens within "Import",
+ // but happens within "CompilationUnit" during recovery.
+ expectInOneOf(const ['Import', 'CompilationUnit']);
+ listener.handleImportPrefix(deferredKeyword, asKeyword);
}
@override
@@ -1182,11 +1184,21 @@
}
@override
- void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
- // This event normally happens within "Import",
- // but happens within "CompilationUnit" during recovery.
- expectInOneOf(const ['Import', 'CompilationUnit']);
- listener.handleImportPrefix(deferredKeyword, asKeyword);
+ void handleRecoverClassHeader() {
+ expectIn('ClassDeclaration');
+ listener.handleRecoverClassHeader();
+ }
+
+ @override
+ void handleRecoverImport(Token semicolon) {
+ expectIn('CompilationUnit');
+ listener.handleRecoverImport(semicolon);
+ }
+
+ @override
+ void handleRecoverMixinHeader() {
+ expectIn('MixinDeclaration');
+ listener.handleRecoverMixinHeader();
}
@override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 6de285d..4f0c894 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -36,6 +36,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ClassMemberParserTest_Fasta);
+ defineReflectiveTests(ExtensionMethodsParserTest_Fasta);
defineReflectiveTests(CollectionLiteralParserTest);
defineReflectiveTests(ComplexParserTest_Fasta);
defineReflectiveTests(ErrorParserTest_Fasta);
@@ -1435,6 +1436,163 @@
}
}
+@reflectiveTest
+class ExtensionMethodsParserTest_Fasta extends FastaParserTestCase {
+ @override
+ CompilationUnit parseCompilationUnit(String content,
+ {List<ErrorCode> codes,
+ List<ExpectedError> errors,
+ FeatureSet featureSet}) {
+ return super.parseCompilationUnit(content,
+ codes: codes,
+ errors: errors,
+ featureSet: featureSet ??
+ FeatureSet.forTesting(
+ sdkVersion: '2.3.0',
+ additionalFeatures: [Feature.extension_methods],
+ ));
+ }
+
+ void test_complex_extends() {
+ var unit = parseCompilationUnit(
+ 'extension E extends A with B, C implements D { }',
+ errors: [
+ expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 22, 4),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 28, 1),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 32, 10),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'extends');
+ expect((extension.extendedType as NamedType).name.name, 'A');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_complex_implements() {
+ var unit = parseCompilationUnit('extension E implements C, D { }', errors: [
+ expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+ expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 24, 1),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'implements');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_complex_type() {
+ var unit = parseCompilationUnit('extension E on C<T> { }');
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'on');
+ var namedType = (extension.extendedType as NamedType);
+ expect(namedType.name.name, 'C');
+ expect(namedType.typeArguments.arguments, hasLength(1));
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_missing_on() {
+ var unit = parseCompilationUnit('extension E', errors: [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 11, 0),
+ expectedError(ParserErrorCode.MISSING_CLASS_BODY, 11, 0),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'on');
+ expect((extension.extendedType as NamedType).name.name, '');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_missing_on_withBlock() {
+ var unit = parseCompilationUnit('extension E {}', errors: [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+ expectedError(ParserErrorCode.EXPECTED_TYPE_NAME, 12, 1),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'on');
+ expect((extension.extendedType as NamedType).name.name, '');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_missing_on_withClassAndBlock() {
+ var unit = parseCompilationUnit('extension E C {}', errors: [
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'on');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_simple() {
+ var unit = parseCompilationUnit('extension E on C { }');
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'on');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ var namedType = (extension.extendedType as NamedType);
+ expect(namedType.name.name, 'C');
+ expect(namedType.typeArguments, isNull);
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_simple_extends() {
+ var unit = parseCompilationUnit('extension E extends C { }', errors: [
+ expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 7),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'extends');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_simple_implements() {
+ var unit = parseCompilationUnit('extension E implements C { }', errors: [
+ expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 10),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'implements');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ expect(extension.members, hasLength(0));
+ }
+
+ void test_simple_not_enabled() {
+ parseCompilationUnit('extension E on C { }',
+ errors: [
+ expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 0, 9),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 15, 1)
+ ],
+ featureSet: FeatureSet.forTesting(sdkVersion: '2.3.0'));
+ }
+
+ void test_simple_with() {
+ var unit = parseCompilationUnit('extension E with C { }', errors: [
+ expectedError(ParserErrorCode.EXPECTED_INSTEAD, 12, 4),
+ ]);
+ expect(unit.declarations, hasLength(1));
+ var extension = unit.declarations[0] as ExtensionDeclaration;
+ expect(extension.name.name, 'E');
+ expect(extension.onKeyword.lexeme, 'with');
+ expect((extension.extendedType as NamedType).name.name, 'C');
+ expect(extension.members, hasLength(0));
+ }
+}
+
/**
* Implementation of [AbstractParserTestCase] specialized for testing the
* Fasta parser.
@@ -2131,19 +2289,24 @@
*/
@reflectiveTest
class NNBDParserTest_Fasta extends FastaParserTestCase {
+ @override
+ CompilationUnit parseCompilationUnit(String content,
+ {List<ErrorCode> codes,
+ List<ExpectedError> errors,
+ FeatureSet featureSet}) =>
+ super.parseCompilationUnit(content,
+ codes: codes, errors: errors, featureSet: featureSet ?? nonNullable);
+
void test_assignment_complex() {
- parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }',
- featureSet: nonNullable);
+ parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x + bar(7); }');
}
void test_assignment_simple() {
- parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }',
- featureSet: nonNullable);
+ parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
}
void test_binary_expression_statement() {
- final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }',
- featureSet: nonNullable);
+ final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }');
FunctionDeclaration funct = unit.declarations[0];
BlockFunctionBody body = funct.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
@@ -2156,13 +2319,11 @@
}
void test_conditional() {
- parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }',
- featureSet: nonNullable);
+ parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
}
void test_conditional_complex() {
- parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }',
- featureSet: nonNullable);
+ parseCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
}
void test_conditional_error() {
@@ -2171,74 +2332,62 @@
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 19, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 40, 1),
expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
- ],
- featureSet: nonNullable);
+ ]);
}
void test_conditional_simple() {
- parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }',
- featureSet: nonNullable);
+ parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
}
void test_enableNonNullable_false() {
parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
- errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)]);
+ errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 20, 1)],
+ featureSet: preNonNullable);
}
void test_for() {
- parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
}
void test_for_conditional() {
- parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
}
void test_for_nullable() {
- parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
}
void test_foreach() {
- parseCompilationUnit('main() { for(int x in [7]) { } }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { for(int x in [7]) { } }');
}
void test_foreach_nullable() {
- parseCompilationUnit('main() { for(int? x in [7, null]) { } }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { for(int? x in [7, null]) { } }');
}
void test_gft_nullable() {
- parseCompilationUnit('main() { C? Function() x = 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { C? Function() x = 7; }');
}
void test_gft_nullable_1() {
- parseCompilationUnit('main() { C Function()? x = 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { C Function()? x = 7; }');
}
void test_gft_nullable_2() {
- parseCompilationUnit('main() { C? Function()? x = 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { C? Function()? x = 7; }');
}
void test_gft_nullable_3() {
- parseCompilationUnit('main() { C? Function()? Function()? x = 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { C? Function()? Function()? x = 7; }');
}
void test_gft_nullable_prefixed() {
- parseCompilationUnit('main() { C.a? Function()? x = 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('main() { C.a? Function()? x = 7; }');
}
void test_is_nullable() {
- CompilationUnit unit = parseCompilationUnit(
- 'main() { x is String? ? (x + y) : z; }',
- featureSet: nonNullable);
+ CompilationUnit unit =
+ parseCompilationUnit('main() { x is String? ? (x + y) : z; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
@@ -2253,9 +2402,8 @@
}
void test_is_nullable_parenthesis() {
- CompilationUnit unit = parseCompilationUnit(
- 'main() { (x is String?) ? (x + y) : z; }',
- featureSet: nonNullable);
+ CompilationUnit unit =
+ parseCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
ExpressionStatement statement = body.block.statements[0];
@@ -2274,9 +2422,7 @@
parseCompilationUnit('''
// @dart = 2.2
main() { (x is String?) ? (x + y) : z; }
-''',
- errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)],
- featureSet: nonNullable);
+''', errors: [expectedError(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 36, 1)]);
}
void test_late_as_identifier() {
@@ -2309,12 +2455,11 @@
main() {
f(new C());
}
-''', featureSet: nonNullable);
+''');
}
void test_nullCheck() {
- var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
- featureSet: nonNullable);
+ var unit = parseCompilationUnit('f(int? y) { var x = y!; }');
FunctionDeclaration function = unit.declarations[0];
BlockFunctionBody body = function.functionExpression.body;
VariableDeclarationStatement statement = body.block.statements[0];
@@ -2338,23 +2483,36 @@
expect(identifier.name, 'y');
}
+ void test_nullCheckAfterGetterAccess() {
+ parseCompilationUnit('f() { var x = g.x!.y + 7; }');
+ }
+
+ void test_nullCheckAfterMethodCall() {
+ parseCompilationUnit('f() { var x = g.m()!.y + 7; }');
+ }
+
+ void test_nullCheckBeforeGetterAccess() {
+ parseCompilationUnit('f() { var x = g!.x + 7; }');
+ }
+
+ void test_nullCheckBeforeMethodCall() {
+ parseCompilationUnit('f() { var x = g!.m() + 7; }');
+ }
+
void test_nullCheckFunctionResult() {
- parseCompilationUnit('f() { var x = g()! + 7; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = g()! + 7; }');
}
void test_nullCheckIndexedValue() {
- parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
}
void test_nullCheckIndexedValue2() {
- parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
}
void test_nullCheckInExpression() {
- parseCompilationUnit('f(int? y) { var x = y! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f(int? y) { var x = y! + 7; }');
}
void test_nullCheckInExpression_disabled() {
@@ -2367,28 +2525,23 @@
}
void test_nullCheckMethodResult() {
- parseCompilationUnit('f() { var x = g.m()! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = g.m()! + 7; }');
}
void test_nullCheckMethodResult2() {
- parseCompilationUnit('f() { var x = g?.m()! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = g?.m()! + 7; }');
}
void test_nullCheckMethodResult3() {
- parseCompilationUnit('f() { var x = super.m()! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = super.m()! + 7; }');
}
void test_nullCheckOnConstConstructor() {
- parseCompilationUnit('f() { var x = const Foo()!; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = const Foo()!; }');
}
void test_nullCheckOnConstructor() {
- parseCompilationUnit('f() { var x = new Foo()!; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = new Foo()!; }');
}
void test_nullCheckOnLiteral_disabled() {
@@ -2399,47 +2552,46 @@
void test_nullCheckOnLiteralDouble() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = 1.2!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = 1.2!; }');
}
void test_nullCheckOnLiteralInt() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = 0!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = 0!; }');
}
void test_nullCheckOnLiteralList() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = [1,2]!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = [1,2]!; }');
}
void test_nullCheckOnLiteralMap() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = {1:2}!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = {1:2}!; }');
}
void test_nullCheckOnLiteralSet() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = {1,2}!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = {1,2}!; }');
}
void test_nullCheckOnLiteralString() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = "seven"!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = "seven"!; }');
}
void test_nullCheckOnNull() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = null!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = null!; }');
}
void test_nullCheckOnSymbol() {
// Issues like this should be caught during later analysis
- parseCompilationUnit('f() { var x = #seven!; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = #seven!; }');
}
void test_nullCheckOnValue() {
- parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f(Point p) { var x = p.y! + 7; }');
}
void test_nullCheckOnValue_disabled() {
@@ -2449,27 +2601,24 @@
}
void test_nullCheckParenthesizedExpression() {
- parseCompilationUnit('f(int? y) { var x = (y)! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f(int? y) { var x = (y)! + 7; }');
}
void test_nullCheckPropertyAccess() {
- parseCompilationUnit('f() { var x = g.p! + 7; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = g.p! + 7; }');
}
void test_nullCheckPropertyAccess2() {
- parseCompilationUnit('f() { var x = g?.p! + 7; }', featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = g?.p! + 7; }');
}
void test_nullCheckPropertyAccess3() {
- parseCompilationUnit('f() { var x = super.p! + 7; }',
- featureSet: nonNullable);
+ parseCompilationUnit('f() { var x = super.p! + 7; }');
}
void test_postfix_null_assertion_and_unary_prefix_operator_precedence() {
// -x! is parsed as -(x!).
- var unit =
- parseCompilationUnit('void main() { -x!; }', featureSet: nonNullable);
+ var unit = parseCompilationUnit('void main() { -x!; }');
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
@@ -2481,8 +2630,7 @@
void test_postfix_null_assertion_of_postfix_expression() {
// x++! is parsed as (x++)!.
- var unit =
- parseCompilationUnit('void main() { x++!; }', featureSet: nonNullable);
+ var unit = parseCompilationUnit('void main() { x++!; }');
var function = unit.declarations[0] as FunctionDeclaration;
var body = function.functionExpression.body as BlockFunctionBody;
var statement = body.block.statements[0] as ExpressionStatement;
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 1f29027..26edc07 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1628,6 +1628,25 @@
expect(initializer.period, isNull);
}
+ void test_parseGetter_identifier_colon_issue_36961() {
+ createParser('get a:');
+ MethodDeclaration method = parser.parseClassMember('C');
+ expect(method, isNotNull);
+ listener.assertErrors([
+ expectedError(ParserErrorCode.MISSING_INITIALIZER, 5, 1),
+ expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 6, 0),
+ ]);
+ expect(method.body, isNotNull);
+ expect(method.documentationComment, isNull);
+ expect(method.externalKeyword, isNull);
+ expect(method.modifierKeyword, isNull);
+ expect(method.name, isNotNull);
+ expect(method.operatorKeyword, isNull);
+ expect(method.parameters, isNull);
+ expect(method.propertyKeyword, isNotNull);
+ expect(method.returnType, isNull);
+ }
+
void test_parseGetter_nonStatic() {
createParser('/// Doc\nT get a;');
MethodDeclaration method = parser.parseClassMember('C');
@@ -3234,7 +3253,7 @@
ClassMember member = parser.parseClassMember('C');
expectNotNullIfNoErrors(member);
listener.assertErrors(
- [expectedError(ParserErrorCode.EXTERNAL_AFTER_FACTORY, 8, 8)]);
+ [expectedError(ParserErrorCode.MODIFIER_OUT_OF_ORDER, 8, 8)]);
}
void test_externalAfterStatic() {
@@ -4394,7 +4413,7 @@
void test_missingClassBody() {
parseCompilationUnit("class A class B {}",
- errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 8, 5)]);
+ errors: [expectedError(ParserErrorCode.MISSING_CLASS_BODY, 6, 1)]);
}
void test_missingClosingParenthesis() {
@@ -5310,7 +5329,7 @@
parseStatement('switch (a) return;', expectedEndOffset: 11);
expect(statement, isNotNull);
listener.assertErrors(usingFastaParser
- ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6)]
+ ? [expectedError(ParserErrorCode.EXPECTED_BODY, 9, 1)]
: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 6),
expectedError(ParserErrorCode.EXPECTED_CASE_OR_DEFAULT, 11, 6),
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 7fa83ed..9cc2c26 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -170,7 +170,7 @@
@reflectiveTest
class ErrorResolverTest extends DriverResolutionTest {
test_breakLabelOnSwitchMember() async {
- assertErrorCodesInCode(r'''
+ assertErrorsInCode(r'''
class A {
void m(int i) {
switch (i) {
@@ -180,11 +180,13 @@
break l;
}
}
-}''', [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
+}''', [
+ error(ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER, 105, 1),
+ ]);
}
test_continueLabelOnSwitch() async {
- assertErrorCodesInCode(r'''
+ assertErrorsInCode(r'''
class A {
void m(int i) {
l: switch (i) {
@@ -192,7 +194,9 @@
continue l;
}
}
-}''', [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
+}''', [
+ error(ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH, 79, 1),
+ ]);
}
test_enclosingElement_invalidLocalFunction() async {
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 47bfbff..de35b72 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -993,7 +993,7 @@
await resolveTestFile();
var node = findNode.simple('myVar(42)');
- assertType(node, '(int) → String');
+ assertType(node, 'String Function(int)');
}
test_metadata_class() async {
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index e261136..36b6c24 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -138,7 +138,7 @@
}
""";
await resolveTestUnit(code);
- expectIdentifierType("p()", '() → dynamic');
+ expectIdentifierType("p()", 'dynamic Function()');
}
test_staticMethods_classTypeParameters() async {
@@ -151,7 +151,7 @@
}
''';
await resolveTestUnit(code);
- expectFunctionType('m);', '() → void');
+ expectFunctionType('m);', 'void Function()');
}
test_staticMethods_classTypeParameters_genericMethod() async {
@@ -170,29 +170,30 @@
// C - m
TypeParameterType typeS;
{
- FunctionTypeImpl type = expectFunctionType('m);', '<S>(S) → void',
+ FunctionTypeImpl type = expectFunctionType('m);', 'void Function<S>(S)',
elementTypeParams: '[S]',
typeFormals: '[S]',
- identifierType: '<S>(S) → void');
+ identifierType: 'void Function<S>(S)');
typeS = type.typeFormals[0].type;
type = type.instantiate([DynamicTypeImpl.instance]);
- expect(type.toString(), '(dynamic) → void');
+ expect(type.toString(), 'void Function(dynamic)');
expect(type.typeParameters.toString(), '[S]');
expect(type.typeArguments, [DynamicTypeImpl.instance]);
expect(type.typeFormals, isEmpty);
}
// C - m - f
{
- FunctionTypeImpl type = expectFunctionType('f);', '<U>(S, U) → void',
+ FunctionTypeImpl type = expectFunctionType(
+ 'f);', 'void Function<U>(S, U)',
elementTypeParams: '[U]',
typeParams: '[S]',
typeArgs: '[S]',
typeFormals: '[U]',
- identifierType: '<U>(S, U) → void');
+ identifierType: 'void Function<U>(S, U)');
type = type.instantiate([DynamicTypeImpl.instance]);
- expect(type.toString(), '(S, dynamic) → void');
+ expect(type.toString(), 'void Function(S, dynamic)');
expect(type.typeParameters.toString(), '[S, U]');
expect(type.typeArguments, [typeS, DynamicTypeImpl.instance]);
expect(type.typeFormals, isEmpty);
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 4d44cbd..1f4358e 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -2528,8 +2528,8 @@
Couldn't infer type parameter 'T'.
Tried to infer 'double' for 'T' which doesn't work:
- Parameter 'f' declared as '(T) → T'
- but argument is '(int) → double'.
+ Parameter 'f' declared as 'T Function(T)'
+ but argument is 'double Function(int)'.
Consider passing explicit type argument(s) to the generic.
@@ -2555,10 +2555,10 @@
Couldn't infer type parameter 'T'.
Tried to infer 'num' for 'T' which doesn't work:
- Parameter 'a' declared as '(T) → T'
- but argument is '(int) → double'.
- Parameter 'b' declared as '(T) → T'
- but argument is '(double) → int'.
+ Parameter 'a' declared as 'T Function(T)'
+ but argument is 'double Function(int)'.
+ Parameter 'b' declared as 'T Function(T)'
+ but argument is 'int Function(double)'.
Consider passing explicit type argument(s) to the generic.
@@ -2585,7 +2585,7 @@
.variables
.variables[0];
var call = h.initializer as MethodInvocation;
- expect(call.staticInvokeType.toString(), '(Null, Null) → Null');
+ expect(call.staticInvokeType.toString(), 'Null Function(Null, Null)');
}
test_inference_error_extendsFromReturn2() async {
@@ -2606,8 +2606,8 @@
Tried to infer 'String' for 'T' which doesn't work:
Type parameter 'T' declared to extend 'num'.
The type 'String' was inferred from:
- Return type declared as '(T) → T'
- used where '(String) → String' is required.
+ Return type declared as 'T Function(T)'
+ used where 'String Function(String)' is required.
Consider passing explicit type argument(s) to the generic.
@@ -2633,8 +2633,8 @@
Couldn't infer type parameter 'T'.
Tried to infer 'dynamic' for 'T' which doesn't work:
- Function type declared as '<T extends num>(T, T) → T'
- used where '(num, dynamic) → num' is required.
+ Function type declared as 'T Function<T extends num>(T, T)'
+ used where 'num Function(num, dynamic)' is required.
Consider passing explicit type argument(s) to the generic.
@@ -2656,8 +2656,8 @@
Couldn't infer type parameter 'T'.
Tried to infer 'num' for 'T' which doesn't work:
- Return type declared as '(T) → T'
- used where '(num) → int' is required.
+ Return type declared as 'T Function(T)'
+ used where 'int Function(num)' is required.
Consider passing explicit type argument(s) to the generic.
@@ -2700,7 +2700,8 @@
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
if (AnalysisDriver.useSummary2) {
- expect('$fType', '((T) → T, (T, T) → int, (T) → T) → void');
+ expect('$fType',
+ 'void Function(T Function(T), int Function(T, T), T Function(T))');
} else {
expect(fType.typeArguments[0].toString(), 'T');
}
@@ -2731,7 +2732,7 @@
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
if (AnalysisDriver.useSummary2) {
- expect('$fType', '(List<T>, (T, T) → int, List<T>) → void');
+ expect('$fType', 'void Function(List<T>, int Function(T, T), List<T>)');
} else {
expect(fType.typeArguments[0].toString(), 'T');
}
@@ -2762,7 +2763,7 @@
MethodInvocation invoke = stmt.expression;
FunctionType fType = invoke.staticInvokeType;
if (AnalysisDriver.useSummary2) {
- expect('$fType', '(T, (T, T) → int, T) → void');
+ expect('$fType', 'void Function(T, int Function(T, T), T)');
} else {
expect(fType.typeArguments[0].toString(), 'T');
}
@@ -2788,10 +2789,10 @@
.variables[0];
_isDynamic(h.declaredElement.type);
var fCall = h.initializer as MethodInvocation;
- expect(
- fCall.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+ expect(fCall.staticInvokeType.toString(),
+ 'dynamic Function(dynamic Function(dynamic))');
var g = fCall.argumentList.arguments[0];
- expect(g.staticType.toString(), '(dynamic) → dynamic');
+ expect(g.staticType.toString(), 'dynamic Function(dynamic)');
}
test_inferGenericInstantiation2() async {
@@ -2816,11 +2817,11 @@
.functionExpression
.body as ExpressionFunctionBody)
.expression as MethodInvocation;
- expect(
- fold.staticInvokeType.toString(), '(num, (num, dynamic) → num) → num');
+ expect(fold.staticInvokeType.toString(),
+ 'num Function(num, num Function(num, dynamic))');
var max = fold.argumentList.arguments[1];
- // TODO(jmesserly): arguably (num, num) → num is better here.
- expect(max.staticType.toString(), '(dynamic, dynamic) → dynamic');
+ // TODO(jmesserly): arguably num Function(num, num) is better here.
+ expect(max.staticType.toString(), 'dynamic Function(dynamic, dynamic)');
}
test_inferredFieldDeclaration_propagation() async {
@@ -3608,7 +3609,7 @@
expect(typeName.type.toString(), 'A<T2, U2>');
var constructorMember = redirected.staticElement;
- expect(constructorMember.toString(), 'A.named() → A<T2, U2>');
+ expect(constructorMember.toString(), 'A<T2, U2> A.named()');
expect(redirected.name.staticElement, constructorMember);
}
@@ -3645,7 +3646,7 @@
expect(typeName.type.toString(), 'A<T2, U2>');
expect(redirected.name, isNull);
- expect(redirected.staticElement.toString(), 'A() → A<T2, U2>');
+ expect(redirected.staticElement.toString(), 'A<T2, U2> A()');
}
test_redirectingConstructor_propagation() async {
@@ -3984,17 +3985,17 @@
test_genericFunction() async {
await resolveTestUnit(r'T f<T>(T x) => null;');
- expectFunctionType('f', '<T>(T) → T',
+ expectFunctionType('f', 'T Function<T>(T)',
elementTypeParams: '[T]', typeFormals: '[T]');
SimpleIdentifier f = findIdentifier('f');
FunctionElementImpl e = f.staticElement;
FunctionType ft = e.type.instantiate([typeProvider.stringType]);
- expect(ft.toString(), '(String) → String');
+ expect(ft.toString(), 'String Function(String)');
}
test_genericFunction_bounds() async {
await resolveTestUnit(r'T f<T extends num>(T x) => null;');
- expectFunctionType('f', '<T extends num>(T) → T',
+ expectFunctionType('f', 'T Function<T extends num>(T)',
elementTypeParams: '[T extends num]', typeFormals: '[T extends num]');
}
@@ -4005,9 +4006,9 @@
await resolveTestUnit(r'''
void g(T f<T>(T x)) {}
''');
- var type = expectFunctionType2('f', '<T>(T) → T');
+ var type = expectFunctionType2('f', 'T Function<T>(T)');
FunctionType ft = type.instantiate([typeProvider.stringType]);
- expect(ft.toString(), '(String) → String');
+ expect(ft.toString(), 'String Function(String)');
}
test_genericFunction_static() async {
@@ -4016,12 +4017,12 @@
static T f<T>(T x) => null;
}
''');
- expectFunctionType('f', '<T>(T) → T',
+ expectFunctionType('f', 'T Function<T>(T)',
elementTypeParams: '[T]', typeFormals: '[T]');
SimpleIdentifier f = findIdentifier('f');
MethodElementImpl e = f.staticElement;
FunctionType ft = e.type.instantiate([typeProvider.stringType]);
- expect(ft.toString(), '(String) → String');
+ expect(ft.toString(), 'String Function(String)');
}
test_genericFunction_typedef() async {
@@ -4102,16 +4103,16 @@
C<String> cOfString;
}
''');
- expectFunctionType('f', '<T>(E) → List<T>',
+ expectFunctionType('f', 'List<T> Function<T>(E)',
elementTypeParams: '[T]',
typeParams: '[E]',
typeArgs: '[E]',
typeFormals: '[T]');
SimpleIdentifier c = findIdentifier('cOfString');
FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
- expect(ft.toString(), '<T>(String) → List<T>');
+ expect(ft.toString(), 'List<T> Function<T>(String)');
ft = ft.instantiate([typeProvider.intType]);
- expect(ft.toString(), '(String) → List<int>');
+ expect(ft.toString(), 'List<int> Function(String)');
expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
}
@@ -4127,7 +4128,7 @@
''');
MethodInvocation f = findIdentifier('f<int>').parent;
FunctionType ft = f.staticInvokeType;
- expect(ft.toString(), '(String) → List<int>');
+ expect(ft.toString(), 'List<int> Function(String)');
expect('${ft.typeArguments}/${ft.typeParameters}', '[String, int]/[E, T]');
SimpleIdentifier x = findIdentifier('x');
@@ -4325,7 +4326,7 @@
C<String> cOfString;
}
''');
- expectFunctionType('f', '<T>((E) → T) → List<T>',
+ expectFunctionType('f', 'List<T> Function<T>(T Function(E))',
elementTypeParams: '[T]',
typeParams: '[E]',
typeArgs: '[E]',
@@ -4333,9 +4334,9 @@
SimpleIdentifier c = findIdentifier('cOfString');
FunctionType ft = (c.staticType as InterfaceType).getMethod('f').type;
- expect(ft.toString(), '<T>((String) → T) → List<T>');
+ expect(ft.toString(), 'List<T> Function<T>(T Function(String))');
ft = ft.instantiate([typeProvider.intType]);
- expect(ft.toString(), '((String) → int) → List<int>');
+ expect(ft.toString(), 'List<int> Function(int Function(String))');
}
test_genericMethod_functionTypedParameter_tearoff() async {
@@ -4347,7 +4348,7 @@
var paramTearOff = pf;
}
''');
- expectIdentifierType('paramTearOff', "<T>(T) → T");
+ expectIdentifierType('paramTearOff', "T Function<T>(T)");
}
test_genericMethod_implicitDynamic() async {
@@ -4363,13 +4364,17 @@
list.map((e) => e);
list.map((e) => 3);
}''');
- expectIdentifierType('map((e) => e);', '<T>((dynamic) → T) → T');
- expectIdentifierType('map((e) => 3);', '<T>((dynamic) → T) → T');
+ expectIdentifierType(
+ 'map((e) => e);', 'T Function<T>(T Function(dynamic))');
+ expectIdentifierType(
+ 'map((e) => 3);', 'T Function<T>(T Function(dynamic))');
MethodInvocation m1 = findIdentifier('map((e) => e);').parent;
- expect(m1.staticInvokeType.toString(), '((dynamic) → dynamic) → dynamic');
+ expect(m1.staticInvokeType.toString(),
+ 'dynamic Function(dynamic Function(dynamic))');
MethodInvocation m2 = findIdentifier('map((e) => 3);').parent;
- expect(m2.staticInvokeType.toString(), '((dynamic) → int) → int');
+ expect(
+ m2.staticInvokeType.toString(), 'int Function(int Function(dynamic))');
}
test_genericMethod_max_doubleDouble() async {
@@ -4450,11 +4455,11 @@
}
''');
MethodInvocation f = findIdentifier('f<int>(3);').parent;
- expect(f.staticInvokeType.toString(), '(int) → S');
+ expect(f.staticInvokeType.toString(), 'S Function(int)');
FunctionType ft = f.staticInvokeType;
expect('${ft.typeArguments}/${ft.typeParameters}', '[S, int]/[T, S]');
- expectIdentifierType('f;', '<Sâ‚€>(Sâ‚€) → S');
+ expectIdentifierType('f;', 'S Function<Sâ‚€>(Sâ‚€)');
}
@FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/30236')
@@ -4469,12 +4474,12 @@
}
''');
MethodInvocation f = findIdentifier('f<int>(3);').parent;
- expect(f.staticInvokeType.toString(), '(int) → S');
+ expect(f.staticInvokeType.toString(), 'S Function(int)');
FunctionType ft = f.staticInvokeType;
expect('${ft.typeArguments}/${ft.typeParameters}',
'[S, int]/[T, S extends T]');
- expectIdentifierType('f;', '<Sâ‚€ extends S>(Sâ‚€) → S');
+ expectIdentifierType('f;', 'S Function<Sâ‚€ extends S>(Sâ‚€)');
}
test_genericMethod_nestedFunctions() async {
@@ -4484,8 +4489,8 @@
return null;
}
''');
- expectIdentifierType('f', '<S>(S) → S');
- expectIdentifierType('g', '<S>(S) → <S>(S) → S');
+ expectIdentifierType('f', 'S Function<S>(S)');
+ expectIdentifierType('g', 'S Function<S>(S) Function<S>(S)');
}
test_genericMethod_override() async {
@@ -4497,12 +4502,12 @@
T f<T>(T x) => null; // from D
}
''');
- expectFunctionType('f<T>(T x) => null; // from D', '<T>(T) → T',
+ expectFunctionType('f<T>(T x) => null; // from D', 'T Function<T>(T)',
elementTypeParams: '[T]', typeFormals: '[T]');
SimpleIdentifier f = findIdentifier('f<T>(T x) => null; // from D');
MethodElementImpl e = f.staticElement;
FunctionType ft = e.type.instantiate([typeProvider.stringType]);
- expect(ft.toString(), '(String) → String');
+ expect(ft.toString(), 'String Function(String)');
}
test_genericMethod_override_bounds() async {
@@ -4658,13 +4663,13 @@
var paramTearOff = pf;
}
''');
- expectIdentifierType('methodTearOff', "<T>(int) → T");
- expectIdentifierType('staticTearOff', "<T>(T) → T");
- expectIdentifierType('staticFieldTearOff', "<T>(T) → T");
- expectIdentifierType('topFunTearOff', "<T>(T) → T");
- expectIdentifierType('topFieldTearOff', "<T>(T) → T");
- expectIdentifierType('localTearOff', "<T>(T) → T");
- expectIdentifierType('paramTearOff', "<T>(T) → T");
+ expectIdentifierType('methodTearOff', "T Function<T>(int)");
+ expectIdentifierType('staticTearOff', "T Function<T>(T)");
+ expectIdentifierType('staticFieldTearOff', "T Function<T>(T)");
+ expectIdentifierType('topFunTearOff', "T Function<T>(T)");
+ expectIdentifierType('topFieldTearOff', "T Function<T>(T)");
+ expectIdentifierType('localTearOff', "T Function<T>(T)");
+ expectIdentifierType('paramTearOff', "T Function<T>(T)");
}
@failingTest
@@ -4690,13 +4695,13 @@
var paramTearOffInst = pf<int>;
}
''');
- expectIdentifierType('methodTearOffInst', "(int) → int");
- expectIdentifierType('staticTearOffInst', "(int) → int");
- expectIdentifierType('staticFieldTearOffInst', "(int) → int");
- expectIdentifierType('topFunTearOffInst', "(int) → int");
- expectIdentifierType('topFieldTearOffInst', "(int) → int");
- expectIdentifierType('localTearOffInst', "(int) → int");
- expectIdentifierType('paramTearOffInst', "(int) → int");
+ expectIdentifierType('methodTearOffInst', "int Function(int)");
+ expectIdentifierType('staticTearOffInst', "int Function(int)");
+ expectIdentifierType('staticFieldTearOffInst', "int Function(int)");
+ expectIdentifierType('topFunTearOffInst', "int Function(int)");
+ expectIdentifierType('topFieldTearOffInst', "int Function(int)");
+ expectIdentifierType('localTearOffInst', "int Function(int)");
+ expectIdentifierType('paramTearOffInst', "int Function(int)");
}
test_genericMethod_then() async {
@@ -4754,7 +4759,7 @@
var fieldRead = C.h;
}
''');
- expectIdentifierType('fieldRead', "<T>(T) → T");
+ expectIdentifierType('fieldRead', "T Function<T>(T)");
}
test_implicitBounds() async {
@@ -4876,7 +4881,7 @@
''';
await resolveTestUnit(code, noErrors: false);
assertNoErrors(testSource);
- expectIdentifierType('c;', 'C<(dynamic) → dynamic>');
+ expectIdentifierType('c;', 'C<dynamic Function(dynamic)>');
}
test_instantiateToBounds_class_ok_implicitDynamic_multi() async {
@@ -4979,7 +4984,7 @@
''';
await resolveTestUnit(code);
assertNoErrors(testSource);
- expectStaticInvokeType('m(null', '(Null, Null) → void');
+ expectStaticInvokeType('m(null', 'void Function(Null, Null)');
}
test_instantiateToBounds_method_ok_referenceOther_before2() async {
@@ -4994,7 +4999,7 @@
''';
await resolveTestUnit(code);
assertNoErrors(testSource);
- expectStaticInvokeType('m();', '() → Map<T, List<T>>');
+ expectStaticInvokeType('m();', 'Map<T, List<T>> Function()');
}
test_instantiateToBounds_method_ok_simpleBounds() async {
@@ -5009,7 +5014,7 @@
''';
await resolveTestUnit(code);
assertNoErrors(testSource);
- expectStaticInvokeType('m(null)', '(Null) → void');
+ expectStaticInvokeType('m(null)', 'void Function(Null)');
}
test_instantiateToBounds_method_ok_simpleBounds2() async {
@@ -5024,7 +5029,7 @@
''';
await resolveTestUnit(code);
assertNoErrors(testSource);
- expectStaticInvokeType('m();', '() → T');
+ expectStaticInvokeType('m();', 'T Function()');
}
test_issue32396() async {
@@ -5430,10 +5435,10 @@
Future<void> _objectMethodOnFunctions_helper2(String code) async {
await resolveTestUnit(code);
expectIdentifierType('t0', "String");
- expectIdentifierType('t1', "() → String");
+ expectIdentifierType('t1', "String Function()");
expectIdentifierType('t2', "int");
expectIdentifierType('t3', "String");
- expectIdentifierType('t4', "() → String");
+ expectIdentifierType('t4', "String Function()");
expectIdentifierType('t5', "int");
}
}
diff --git a/pkg/analyzer/test/generated/type_system_test.dart b/pkg/analyzer/test/generated/type_system_test.dart
index 9084e64..16599ec 100644
--- a/pkg/analyzer/test/generated/type_system_test.dart
+++ b/pkg/analyzer/test/generated/type_system_test.dart
@@ -4,6 +4,7 @@
// Tests related to the [TypeSystem] class.
+import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart' show astFactory;
import 'package:analyzer/dart/ast/token.dart' show Keyword;
import 'package:analyzer/dart/element/element.dart';
@@ -32,6 +33,7 @@
defineReflectiveTests(ConstraintMatchingTest);
defineReflectiveTests(StrongAssignabilityTest);
defineReflectiveTests(StrongSubtypingTest);
+ defineReflectiveTests(NonNullableSubtypingTest);
defineReflectiveTests(StrongGenericFunctionInferenceTest);
defineReflectiveTests(StrongLeastUpperBoundTest);
defineReflectiveTests(StrongGreatestLowerBoundTest);
@@ -78,6 +80,7 @@
InterfaceType get intType => typeProvider.intType;
InterfaceType get iterableType => typeProvider.iterableType;
InterfaceType get listType => typeProvider.listType;
+ InterfaceType get nullType => typeProvider.nullType;
InterfaceType get numType => typeProvider.numType;
InterfaceType get objectType => typeProvider.objectType;
InterfaceType get stringType => typeProvider.stringType;
@@ -850,6 +853,94 @@
}
@reflectiveTest
+class NonNullableSubtypingTest extends StrongSubtypingTestBase {
+ @override
+ void setUp() {
+ typeProvider = AnalysisContextFactory.contextWithCoreAndOptions(
+ new AnalysisOptionsImpl()
+ ..contextFeatures = FeatureSet.forTesting(
+ additionalFeatures: [Feature.non_nullable]),
+ resourceProvider: new MemoryResourceProvider())
+ .typeProvider;
+
+ // TypeSystem should use the context type provider.
+ typeSystem = new Dart2TypeSystem(typeProvider);
+
+ LibraryElement coreLibrary = typeProvider.objectType.element.library;
+ LibraryElement asyncLibrary = typeProvider.streamType.element.library;
+
+ // Get a non-nullable type provider for convience during the test.
+ typeProvider = new NonNullableTypeProvider(coreLibrary, asyncLibrary);
+ }
+
+ void test_int_nullableTypes() {
+ List<DartType> equivalents = <DartType>[
+ intType,
+ _star(intType),
+ ];
+ List<DartType> supertypes = <DartType>[
+ _question(intType),
+ objectType,
+ _question(objectType),
+ ];
+ List<DartType> unrelated = <DartType>[doubleType, nullType];
+ _checkGroups(intType,
+ equivalents: equivalents, supertypes: supertypes, unrelated: unrelated);
+ }
+
+ void test_intQuestion_nullableTypes() {
+ List<DartType> equivalents = <DartType>[
+ _question(intType),
+ _star(intType),
+ ];
+ List<DartType> subtypes = <DartType>[
+ intType,
+ nullType,
+ ];
+ List<DartType> supertypes = <DartType>[
+ _question(numType),
+ _star(numType),
+ _question(objectType),
+ _star(objectType),
+ ];
+ List<DartType> unrelated = <DartType>[doubleType, numType, objectType];
+ _checkGroups(_question(intType),
+ equivalents: equivalents,
+ supertypes: supertypes,
+ unrelated: unrelated,
+ subtypes: subtypes);
+ }
+
+ void test_intStar_nullableTypes() {
+ List<DartType> equivalents = <DartType>[
+ intType,
+ _question(intType),
+ _star(intType),
+ ];
+ List<DartType> subtypes = <DartType>[nullType];
+ List<DartType> supertypes = <DartType>[
+ numType,
+ _question(numType),
+ _star(numType),
+ objectType,
+ _question(objectType),
+ ];
+ List<DartType> unrelated = <DartType>[doubleType];
+ _checkGroups(_star(intType),
+ equivalents: equivalents,
+ supertypes: supertypes,
+ unrelated: unrelated,
+ subtypes: subtypes);
+ }
+
+ DartType _question(DartType dartType) =>
+ (dartType as TypeImpl).withNullability(NullabilitySuffix.question);
+
+ DartType _star(DartType dartType) =>
+ (dartType as TypeImpl).withNullability(NullabilitySuffix.star);
+}
+
+@reflectiveTest
class StrongAssignabilityTest extends AbstractTypeSystemTest {
void test_isAssignableTo_bottom_isBottom() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
@@ -1852,29 +1943,7 @@
}
@reflectiveTest
-class StrongSubtypingTest {
- TypeProvider typeProvider;
- TypeSystem typeSystem;
-
- DartType get bottomType => typeProvider.bottomType;
- InterfaceType get doubleType => typeProvider.doubleType;
- DartType get dynamicType => typeProvider.dynamicType;
- InterfaceType get functionType => typeProvider.functionType;
- InterfaceType get futureOrType => typeProvider.futureOrType;
- InterfaceType get intType => typeProvider.intType;
- InterfaceType get listType => typeProvider.listType;
- InterfaceType get numType => typeProvider.numType;
- InterfaceType get objectType => typeProvider.objectType;
- InterfaceType get stringType => typeProvider.stringType;
- DartType get voidType => VoidTypeImpl.instance;
-
- void setUp() {
- typeProvider = AnalysisContextFactory.contextWithCore(
- resourceProvider: new MemoryResourceProvider())
- .typeProvider;
- typeSystem = new Dart2TypeSystem(typeProvider);
- }
-
+class StrongSubtypingTest extends StrongSubtypingTestBase {
void test_bottom_isBottom() {
DartType interfaceType = ElementFactory.classElement2('A', []).type;
List<DartType> equivalents = <DartType>[bottomType];
@@ -2184,6 +2253,31 @@
];
_checkGroups(voidType, equivalents: equivalents, subtypes: subtypes);
}
+}
+
+class StrongSubtypingTestBase {
+ TypeProvider typeProvider;
+ TypeSystem typeSystem;
+
+ DartType get bottomType => typeProvider.bottomType;
+ InterfaceType get doubleType => typeProvider.doubleType;
+ DartType get dynamicType => typeProvider.dynamicType;
+ InterfaceType get functionType => typeProvider.functionType;
+ InterfaceType get futureOrType => typeProvider.futureOrType;
+ InterfaceType get intType => typeProvider.intType;
+ InterfaceType get listType => typeProvider.listType;
+ DartType get nullType => typeProvider.nullType;
+ InterfaceType get numType => typeProvider.numType;
+ InterfaceType get objectType => typeProvider.objectType;
+ InterfaceType get stringType => typeProvider.stringType;
+ DartType get voidType => VoidTypeImpl.instance;
+
+ void setUp() {
+ typeProvider = AnalysisContextFactory.contextWithCore(
+ resourceProvider: new MemoryResourceProvider())
+ .typeProvider;
+ typeSystem = new Dart2TypeSystem(typeProvider);
+ }
void _checkEquivalent(DartType type1, DartType type2) {
_checkIsSubtypeOf(type1, type2);
@@ -2218,7 +2312,8 @@
}
void _checkIsNotSubtypeOf(DartType type1, DartType type2) {
- expect(typeSystem.isSubtypeOf(type1, type2), false);
+ expect(typeSystem.isSubtypeOf(type1, type2), false,
+ reason: '$type1 was not supposed to be a subtype of $type2');
}
void _checkIsStrictSubtypeOf(DartType type1, DartType type2) {
@@ -2227,7 +2322,8 @@
}
void _checkIsSubtypeOf(DartType type1, DartType type2) {
- expect(typeSystem.isSubtypeOf(type1, type2), true);
+ expect(typeSystem.isSubtypeOf(type1, type2), true,
+ reason: '$type1 is not a subtype of $type2');
}
void _checkLattice(
diff --git a/pkg/analyzer/test/snippets/README.md b/pkg/analyzer/test/snippets/README.md
new file mode 100644
index 0000000..aab390e
--- /dev/null
+++ b/pkg/analyzer/test/snippets/README.md
@@ -0,0 +1 @@
+The 'snippets' directory exists to enable the test in 'verify_docs_test.dart'.
\ No newline at end of file
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 73fc758..40d5bc6 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -637,7 +637,7 @@
SimpleIdentifier constructorName = annotation.constructorName;
expect(constructorName.staticElement, same(constructor));
- expect(constructorName.staticType.toString(), '(int, {b: int}) → A');
+ expect(constructorName.staticType.toString(), 'A Function(int, {b: int})');
var arguments = annotation.arguments.arguments;
var parameters = constructor.parameters;
@@ -764,7 +764,8 @@
expect(prefixed.prefix.staticType, aClass.type);
expect(prefixed.identifier.staticElement, same(constructor));
- expect(prefixed.identifier.staticType.toString(), '(int, {b: int}) → A');
+ expect(
+ prefixed.identifier.staticType.toString(), 'A Function(int, {b: int})');
expect(annotation.constructorName, isNull);
@@ -1080,7 +1081,7 @@
SimpleIdentifier forTarget = forInvocation.target;
expect(forTarget.staticElement, itemsElement);
- var closureTypeStr = '(int) → Null';
+ var closureTypeStr = 'Null Function(int)';
FunctionExpression closure = forInvocation.argumentList.arguments[0];
FunctionElementImpl closureElement = closure.declaredElement;
@@ -1121,7 +1122,7 @@
SimpleIdentifier forTarget = forInvocation.target;
expect(forTarget.staticElement, itemsElement);
- var closureTypeStr = '(int) → Null';
+ var closureTypeStr = 'Null Function(int)';
FunctionExpression closure = forInvocation.argumentList.arguments[0];
FunctionElementImpl closureElement = closure.declaredElement;
@@ -1166,7 +1167,7 @@
await resolveTestFile();
var closure = findNode.functionExpression('<T>() =>');
- assertType(closure, '<T>() → List<T>');
+ assertType(closure, 'List<T> Function<T>()');
FunctionElementImpl closureElement = closure.declaredElement;
expect(closureElement.enclosingElement, findElement.function('main'));
@@ -1546,7 +1547,7 @@
var invocation = findNode.methodInvocation('loadLibrary');
assertType(invocation, 'Future<dynamic>');
- assertInvokeType(invocation, '() → Future<dynamic>');
+ assertInvokeType(invocation, 'Future<dynamic> Function()');
SimpleIdentifier target = invocation.target;
assertElement(target, import.prefix);
@@ -1554,7 +1555,7 @@
var name = invocation.methodName;
assertElement(name, import.importedLibrary.loadLibraryFunction);
- assertType(name, '() → Future<dynamic>');
+ assertType(name, 'Future<dynamic> Function()');
}
@failingTest
@@ -1573,7 +1574,7 @@
var invocation = findNode.methodInvocation('loadLibrary');
assertType(invocation, 'Future<dynamic>');
- assertInvokeType(invocation, '() → Future<dynamic>');
+ assertInvokeType(invocation, 'Future<dynamic> Function()');
SimpleIdentifier target = invocation.target;
assertElement(target, import.prefix);
@@ -1581,7 +1582,7 @@
var name = invocation.methodName;
assertElement(name, import.importedLibrary.loadLibraryFunction);
- assertType(name, '() → Future<dynamic>');
+ assertType(name, 'Future<dynamic> Function()');
var bRef = invocation.argumentList.arguments[0];
assertElement(bRef, findElement.topGet('b'));
@@ -1604,7 +1605,7 @@
var import = findElement.import('package:test/a.dart');
var prefixed = findNode.prefixed('a.loadLibrary');
- assertType(prefixed, '() → Future<dynamic>');
+ assertType(prefixed, 'Future<dynamic> Function()');
var prefix = prefixed.prefix;
assertElement(prefix, import.prefix);
@@ -1612,7 +1613,7 @@
var identifier = prefixed.identifier;
assertElement(identifier, import.importedLibrary.loadLibraryFunction);
- assertType(identifier, '() → Future<dynamic>');
+ assertType(identifier, 'Future<dynamic> Function()');
}
test_deferredImport_variable() async {
@@ -1815,7 +1816,7 @@
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
- expect(invocation.staticInvokeType.toString(), '() → String');
+ expect(invocation.staticInvokeType.toString(), 'String Function()');
MethodElement methodElement = invocation.methodName.staticElement;
expect(methodElement.name, 'toString');
@@ -1945,7 +1946,7 @@
expect(p.declaredElement, same(pElement));
expect(p.identifier.staticElement, same(pElement));
- expect(p.identifier.staticType.toString(), '(int) → String');
+ expect(p.identifier.staticType.toString(), 'String Function(int)');
{
FunctionType type = p.identifier.staticType;
@@ -2044,7 +2045,7 @@
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
- expect(invocation.staticInvokeType.toString(), '(int) → void');
+ expect(invocation.staticInvokeType.toString(), 'void Function(int)');
// TODO(scheglov) Check for MethodElement
// expect(invocation.methodName.staticElement, same(mElement));
}
@@ -2080,7 +2081,7 @@
FunctionExpressionInvocation invocation = statement.expression;
expect(invocation.staticElement, isNull);
- expect(invocation.staticInvokeType.toString(), '(String) → int');
+ expect(invocation.staticInvokeType.toString(), 'int Function(String)');
expect(invocation.staticType, typeProvider.intType);
List<TypeAnnotation> typeArguments = invocation.typeArguments.arguments;
@@ -2107,7 +2108,7 @@
''');
await resolveTestFile();
var f = findNode.simple('f;');
- assertType(f, '<T>(T) → void');
+ assertType(f, 'void Function<T>(T)');
var fType = f.staticType as FunctionType;
var fTypeTypeParameter = fType.typeFormals[0];
var fTypeParameter = fType.normalParameterTypes[0] as TypeParameterType;
@@ -2710,7 +2711,7 @@
var invocation = findNode.methodInvocation('codeUnitAt');
assertType(invocation, 'int');
- assertInvokeType(invocation, '(int) → int');
+ assertInvokeType(invocation, 'int Function(int)');
assertElement(invocation.methodName, stringElement.getMethod('codeUnitAt'));
var aRef = invocation.target;
@@ -2734,7 +2735,7 @@
var invocation = findNode.methodInvocation('m();');
assertType(invocation, 'int');
- assertInvokeType(invocation, '() → int');
+ assertInvokeType(invocation, 'int Function()');
assertElement(invocation.methodName, findElement.method('m'));
}
@@ -2750,7 +2751,7 @@
var invocation = findNode.methodInvocation('id(');
assertType(invocation, 'bool');
- assertInvokeType(invocation, '(Object, Object) → bool');
+ assertInvokeType(invocation, 'bool Function(Object, Object)');
assertElement(invocation.methodName, findElement.topGet('id'));
var aRef = invocation.argumentList.arguments[0];
@@ -3042,7 +3043,7 @@
var aRef = findNode.simple('a + 1');
assertElement(aRef, findElement.method('a'));
- assertType(aRef, '() → int');
+ assertType(aRef, 'int Function()');
}
test_invalid_fieldInitializer_this() async {
@@ -3355,7 +3356,7 @@
var invocation = findNode.methodInvocation('m(a)');
assertElement(invocation.methodName, m);
- assertType(invocation.methodName, '() → void');
+ assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
@@ -3377,7 +3378,7 @@
var invocation = findNode.methodInvocation('f(p: a');
assertElement(invocation.methodName, f);
- assertType(invocation.methodName, '({p: dynamic}) → void');
+ assertType(invocation.methodName, 'void Function({p: dynamic})');
assertType(invocation, 'void');
NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3403,7 +3404,7 @@
var invocation = findNode.methodInvocation('f(p: a');
assertElement(invocation.methodName, f);
- assertType(invocation.methodName, '({p: dynamic}) → void');
+ assertType(invocation.methodName, 'void Function({p: dynamic})');
assertType(invocation, 'void');
NamedExpression arg0 = invocation.argumentList.arguments[0];
@@ -3450,7 +3451,7 @@
var invocation = findNode.methodInvocation('m(a)');
assertElement(invocation.methodName, m);
- assertType(invocation.methodName, '() → void');
+ assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
@@ -3496,7 +3497,7 @@
var invocation = findNode.methodInvocation('f(a)');
assertElement(invocation.methodName, f);
- assertType(invocation.methodName, '() → void');
+ assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
@@ -3518,7 +3519,7 @@
var invocation = findNode.methodInvocation('f(a)');
assertElement(invocation.methodName, f);
- assertType(invocation.methodName, '() → void');
+ assertType(invocation.methodName, 'void Function()');
assertType(invocation, 'void');
var aRef = invocation.argumentList.arguments[0];
@@ -4032,7 +4033,7 @@
var v = f(1, '2');
}
''');
- String fTypeString = '(int, String) → double';
+ String fTypeString = 'double Function(int, String)';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
@@ -4139,7 +4140,7 @@
}
expect(fElement, isNotNull);
- expect(fElement.type.toString(), '<T,U>(T, U) → T');
+ expect(fElement.type.toString(), 'T Function<T,U>(T, U)');
expect(fNode.name.staticElement, same(fElement));
expect(fNode.name.staticType, fElement.type);
@@ -4187,7 +4188,8 @@
expect(fInvocation.staticType, typeProvider.intType);
assertTypeNull(fInvocation.methodName);
- expect(fInvocation.staticInvokeType.toString(), '(int, String) → int');
+ expect(
+ fInvocation.staticInvokeType.toString(), 'int Function(int, String)');
}
test_local_function_generic_f_bounded() async {
@@ -4204,7 +4206,7 @@
FunctionElement fElement = fNode.declaredElement;
expect(fElement.type.toString(),
- '<T extends U,U,V extends U>(T, U, V) → void');
+ 'void Function<T extends U,U,V extends U>(T, U, V)');
var tElement = fElement.typeParameters[0];
var uElement = fElement.typeParameters[1];
var vElement = fElement.typeParameters[2];
@@ -4225,7 +4227,7 @@
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionElement fElement = fNode.declaredElement;
- expect(fElement.type.toString(), '<T>({x: T}) → void');
+ expect(fElement.type.toString(), 'void Function<T>({x: T})');
var tElement = fElement.typeParameters[0];
expect(fElement.type.typeFormals[0], same(tElement));
expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4245,7 +4247,7 @@
FunctionDeclaration fNode = fStatement.functionDeclaration;
FunctionElement fElement = fNode.declaredElement;
- expect(fElement.type.toString(), '<T>([T]) → void');
+ expect(fElement.type.toString(), 'void Function<T>([T])');
var tElement = fElement.typeParameters[0];
expect(fElement.type.typeFormals[0], same(tElement));
expect((fElement.type.parameters[0].type as TypeParameterType).element,
@@ -4259,7 +4261,7 @@
f(1, b: '2', c: true);
}
''');
- String fTypeString = '(int, {b: String, c: bool}) → double';
+ String fTypeString = 'double Function(int, {b: String, c: bool})';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
@@ -4336,7 +4338,7 @@
expect(fNode.returnType, isNull);
expect(fElement, isNotNull);
- expect(fElement.type.toString(), '() → Null');
+ expect(fElement.type.toString(), 'Null Function()');
expect(fNode.name.staticElement, same(fElement));
expect(fNode.name.staticType, fElement.type);
@@ -4351,7 +4353,7 @@
var v = f(1, '2', true);
}
''');
- String fTypeString = '(int, [String, bool]) → double';
+ String fTypeString = 'double Function(int, [String, bool])';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
@@ -4429,7 +4431,7 @@
''');
await resolveTestFile();
var callback = findNode.simple('callback');
- assertType(callback, '<T extends E>(D) → C');
+ assertType(callback, 'C Function<T extends E>(D)');
var cReference = findNode.simple('C callback');
var cElement = findElement.class_('C');
assertType(cReference, 'C');
@@ -4748,20 +4750,20 @@
''');
await resolveTestFile();
- var mainStatements = _getMainStatements(result);
- var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
- var fElement = fDeclaration.functionDeclaration.declaredElement;
- var tElement = fElement.typeParameters[0];
- var body = fDeclaration.functionDeclaration.functionExpression.body
- as BlockFunctionBody;
- var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
- var gType = gDeclaration.variables.type as TypeName;
+ var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+ var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
+
+ if (!AnalysisDriver.useSummary2) {
+ var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+ expect(gTypeTypeArgument.element, same(tElement));
+ }
+
var gTypeParameterType =
gTypeType.namedParameterTypes['u'] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
+
var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
@@ -4781,20 +4783,20 @@
''');
await resolveTestFile();
- var mainStatements = _getMainStatements(result);
- var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
- var fElement = fDeclaration.functionDeclaration.declaredElement;
- var tElement = fElement.typeParameters[0];
- var body = fDeclaration.functionDeclaration.functionExpression.body
- as BlockFunctionBody;
- var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
- var gType = gDeclaration.variables.type as TypeName;
+ var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+ var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
+
+ if (!AnalysisDriver.useSummary2) {
+ var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+ expect(gTypeTypeArgument.element, same(tElement));
+ }
+
var gTypeParameterType =
gTypeType.normalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
+
var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
@@ -4814,20 +4816,20 @@
''');
await resolveTestFile();
- var mainStatements = _getMainStatements(result);
- var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
- var fElement = fDeclaration.functionDeclaration.declaredElement;
- var tElement = fElement.typeParameters[0];
- var body = fDeclaration.functionDeclaration.functionExpression.body
- as BlockFunctionBody;
- var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
- var gType = gDeclaration.variables.type as TypeName;
+ var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+ var gType = findNode.typeName('Consumer<T>');
var gTypeType = gType.type as FunctionType;
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
+
+ if (!AnalysisDriver.useSummary2) {
+ var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+ expect(gTypeTypeArgument.element, same(tElement));
+ }
+
var gTypeParameterType =
gTypeType.optionalParameterTypes[0] as TypeParameterType;
expect(gTypeParameterType.element, same(tElement));
+
var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
@@ -4847,19 +4849,19 @@
''');
await resolveTestFile();
- var mainStatements = _getMainStatements(result);
- var fDeclaration = mainStatements[0] as FunctionDeclarationStatement;
- var fElement = fDeclaration.functionDeclaration.declaredElement;
- var tElement = fElement.typeParameters[0];
- var body = fDeclaration.functionDeclaration.functionExpression.body
- as BlockFunctionBody;
- var gDeclaration = body.block.statements[0] as VariableDeclarationStatement;
- var gType = gDeclaration.variables.type as TypeName;
+ var tElement = findNode.typeParameter('T>(T x)').declaredElement;
+
+ var gType = findNode.typeName('Producer<T>');
var gTypeType = gType.type as FunctionType;
- var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
- expect(gTypeTypeArgument.element, same(tElement));
+
+ if (!AnalysisDriver.useSummary2) {
+ var gTypeTypeArgument = gTypeType.typeArguments[0] as TypeParameterType;
+ expect(gTypeTypeArgument.element, same(tElement));
+ }
+
var gTypeReturnType = gTypeType.returnType as TypeParameterType;
expect(gTypeReturnType.element, same(tElement));
+
var gArgumentType = gType.typeArguments.arguments[0] as TypeName;
var tReference = gArgumentType.name;
assertElement(tReference, tElement);
@@ -4883,7 +4885,7 @@
FunctionDeclaration main = result.unit.declarations[0];
expect(main.declaredElement, isNotNull);
expect(main.name.staticElement, isNotNull);
- expect(main.name.staticType.toString(), '() → void');
+ expect(main.name.staticType.toString(), 'void Function()');
BlockFunctionBody body = main.functionExpression.body;
NodeList<Statement> statements = body.block.statements;
@@ -5243,7 +5245,7 @@
c.f(1, b: '2', c: true);
}
''');
- String fTypeString = '(int, {b: String, c: bool}) → double';
+ String fTypeString = 'double Function(int, {b: String, c: bool})';
await resolveTestFile();
ClassDeclaration classDeclaration = result.unit.declarations[0];
@@ -5323,11 +5325,11 @@
MethodInvocation invocation = statement.expression;
expect(invocation.staticType, typeProvider.doubleType);
- expect(invocation.staticInvokeType.toString(), '(int) → double');
+ expect(invocation.staticInvokeType.toString(), 'double Function(int)');
SimpleIdentifier methodName = invocation.methodName;
expect(methodName.staticElement, same(callElement));
- expect(methodName.staticType.toString(), '(int) → double');
+ expect(methodName.staticType.toString(), 'double Function(int)');
}
test_methodInvocation_explicitCall_functionTarget() async {
@@ -5350,11 +5352,11 @@
MethodInvocation invocation = statement.expression;
expect(invocation.staticType, typeProvider.doubleType);
- expect(invocation.staticInvokeType.toString(), '(int) → double');
+ expect(invocation.staticInvokeType.toString(), 'double Function(int)');
SimpleIdentifier target = invocation.target;
expect(target.staticElement, same(parameter));
- expect(target.staticType.toString(), '(int) → double');
+ expect(target.staticType.toString(), 'double Function(int)');
SimpleIdentifier methodName = invocation.methodName;
expect(methodName.staticElement, isNull);
@@ -5385,7 +5387,7 @@
MethodInvocation invocation = statement.expression;
expect(invocation.methodName.staticElement, same(fooElement));
- var invokeTypeStr = '(int) → void';
+ var invokeTypeStr = 'void Function(int)';
expect(invocation.staticType.toString(), 'void');
expect(invocation.staticInvokeType.toString(), invokeTypeStr);
}
@@ -5406,7 +5408,7 @@
var invocation = findNode.methodInvocation('m(1)');
List<Expression> arguments = invocation.argumentList.arguments;
- var invokeTypeStr = '(int) → void';
+ var invokeTypeStr = 'void Function(int)';
assertType(invocation, 'void');
assertInvokeType(invocation, invokeTypeStr);
@@ -5433,12 +5435,12 @@
var invocation = findNode.methodInvocation('m(1, 2.3)');
List<Expression> arguments = invocation.argumentList.arguments;
- var invokeTypeStr = '(int, double) → Map<int, double>';
+ var invokeTypeStr = 'Map<int, double> Function(int, double)';
assertType(invocation, 'Map<int, double>');
assertInvokeType(invocation, invokeTypeStr);
assertMember(invocation.methodName, 'C<int>', mElement);
- assertType(invocation.methodName, '<U>(int, U) → Map<int, U>');
+ assertType(invocation.methodName, 'Map<int, U> Function<U>(int, U)');
if (AnalysisDriver.useSummary2) {
_assertArgumentToParameter2(arguments[0], 'int');
@@ -5562,7 +5564,8 @@
ExpressionStatement statement = fooStatements[0];
MethodInvocation invocation = statement.expression;
expect(invocation.methodName.staticElement, same(fElement));
- expect(invocation.staticInvokeType.toString(), '(int, {b: int}) → String');
+ expect(invocation.staticInvokeType.toString(),
+ 'String Function(int, {b: int})');
expect(invocation.staticType, typeProvider.stringType);
List<Expression> arguments = invocation.argumentList.arguments;
@@ -5622,7 +5625,7 @@
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
expect(invocation.methodName.staticElement, same(fElement));
- expect(invocation.staticInvokeType.toString(), '(int) → String');
+ expect(invocation.staticInvokeType.toString(), 'String Function(int)');
expect(invocation.staticType, typeProvider.stringType);
List<Expression> arguments = invocation.argumentList.arguments;
@@ -5686,7 +5689,7 @@
expect(target.staticElement, same(cElement));
expect(target.staticType, same(cElement.type));
- var invokeTypeStr = '(int) → void';
+ var invokeTypeStr = 'void Function(int)';
expect(invocation.staticType.toString(), 'void');
expect(invocation.staticInvokeType.toString(), invokeTypeStr);
expect(invocation.staticInvokeType.element, same(mElement));
@@ -5708,7 +5711,7 @@
expect(invocation.target, isNull);
- var invokeTypeStr = '(int) → void';
+ var invokeTypeStr = 'void Function(int)';
expect(invocation.staticType.toString(), 'void');
expect(invocation.staticInvokeType.toString(), invokeTypeStr);
expect(invocation.staticInvokeType.element, same(mElement));
@@ -5738,7 +5741,7 @@
BlockFunctionBody barBody = barNode.body;
ExpressionStatement fooStatement = barBody.block.statements[0];
MethodInvocation fooInvocation = fooStatement.expression;
- expect(fooInvocation.staticInvokeType.toString(), '(C<T>) → T');
+ expect(fooInvocation.staticInvokeType.toString(), 'T Function(C<T>)');
expect(fooInvocation.staticType.toString(), 'T');
expect(fooInvocation.staticType.element, same(tElement));
}
@@ -5750,7 +5753,7 @@
}
double f(int a, String b) {}
''');
- String fTypeString = '(int, String) → double';
+ String fTypeString = 'double Function(int, String)';
await resolveTestFile();
List<Statement> mainStatements = _getMainStatements(result);
@@ -5791,7 +5794,7 @@
// f<bool, String>(true, 'str');
{
- String fTypeString = '(bool, String) → void';
+ String fTypeString = 'void Function(bool, String)';
ExpressionStatement statement = mainStatements[0];
MethodInvocation invocation = statement.expression;
@@ -5827,7 +5830,7 @@
// f(1, 2.3);
{
- String fTypeString = '(int, double) → void';
+ String fTypeString = 'void Function(int, double)';
ExpressionStatement statement = mainStatements[1];
MethodInvocation invocation = statement.expression;
List<Expression> arguments = invocation.argumentList.arguments;
@@ -5876,7 +5879,6 @@
}
}
- @failingTest
test_optionalConst_prefixed() async {
newFile('/test/lib/a.dart', content: r'''
class C {
@@ -6131,7 +6133,7 @@
assertTypeName(intRef, intElement, 'int');
var functionRef = findNode.genericFunctionType('Function(double)');
- assertType(functionRef, '(double) → int');
+ assertType(functionRef, 'int Function(double)');
var doubleRef = findNode.typeName('double) g');
assertTypeName(doubleRef, doubleElement, 'double');
@@ -6180,7 +6182,7 @@
await resolveTestFile();
var gRef = findNode.simple('g()++');
- assertType(gRef, '() → int');
+ assertType(gRef, 'int Function()');
assertElement(gRef, findElement.parameter('g'));
}
@@ -6397,7 +6399,7 @@
PrefixedIdentifier prefixed = statement.expression;
expect(prefixed.prefix.staticElement, same(parameter));
- expect(prefixed.prefix.staticType.toString(), '(int) → double');
+ expect(prefixed.prefix.staticType.toString(), 'double Function(int)');
SimpleIdentifier methodName = prefixed.identifier;
expect(methodName.staticElement, isNull);
@@ -6760,7 +6762,7 @@
FunctionDeclaration main = result.unit.declarations[0];
expect(main.declaredElement, isNotNull);
expect(main.name.staticElement, isNotNull);
- expect(main.name.staticType.toString(), '() → void');
+ expect(main.name.staticType.toString(), 'void Function()');
BlockFunctionBody body = main.functionExpression.body;
NodeList<Statement> statements = body.block.statements;
@@ -7280,7 +7282,7 @@
{
ConstructorDeclaration node = cNode.members[0];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(int) → C');
+ expect(node.declaredElement.type.toString(), 'C Function(int)');
expect(node.returnType.staticElement, same(cElement));
expect(node.returnType.staticType, typeType);
expect(node.name, isNull);
@@ -7290,18 +7292,18 @@
{
ConstructorDeclaration node = cNode.members[1];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(int) → C');
+ expect(node.declaredElement.type.toString(), 'C Function(int)');
expect(node.returnType.staticElement, same(cElement));
expect(node.returnType.staticType, typeType);
expect(node.name.staticElement, same(node.declaredElement));
- expect(node.name.staticType.toString(), '(int) → C');
+ expect(node.name.staticType.toString(), 'C Function(int)');
}
// publicMethod()
{
MethodDeclaration node = cNode.members[2];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(double) → int');
+ expect(node.declaredElement.type.toString(), 'int Function(double)');
// method return type
TypeName returnType = node.returnType;
@@ -7333,7 +7335,7 @@
{
MethodDeclaration node = cNode.members[3];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '() → int');
+ expect(node.declaredElement.type.toString(), 'int Function()');
// getter return type
TypeName returnType = node.returnType;
@@ -7351,7 +7353,7 @@
{
MethodDeclaration node = cNode.members[4];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(double) → void');
+ expect(node.declaredElement.type.toString(), 'void Function(double)');
// setter return type
TypeName returnType = node.returnType;
@@ -7400,7 +7402,7 @@
{
FunctionDeclaration node = result.unit.declarations[0];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(double) → int');
+ expect(node.declaredElement.type.toString(), 'int Function(double)');
// function return type
TypeName returnType = node.returnType;
@@ -7433,7 +7435,7 @@
{
FunctionDeclaration node = result.unit.declarations[1];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '() → int');
+ expect(node.declaredElement.type.toString(), 'int Function()');
// getter return type
TypeName returnType = node.returnType;
@@ -7451,7 +7453,7 @@
{
FunctionDeclaration node = result.unit.declarations[2];
expect(node.declaredElement, isNotNull);
- expect(node.declaredElement.type.toString(), '(double) → void');
+ expect(node.declaredElement.type.toString(), 'void Function(double)');
// setter return type
TypeName returnType = node.returnType;
@@ -7669,7 +7671,7 @@
f(1, b: '2', c: true);
}
''');
- String fTypeString = '(int, {b: String, c: bool}) → double';
+ String fTypeString = 'double Function(int, {b: String, c: bool})';
await resolveTestFile();
FunctionDeclaration fDeclaration = result.unit.declarations[0];
@@ -7969,26 +7971,18 @@
''');
await resolveTestFile();
- CompilationUnit unit = result.unit;
- CompilationUnitElement unitElement = unit.declaredElement;
- var typeProvider = unitElement.context.typeProvider;
- FunctionTypeAlias alias = unit.declarations[0];
+ FunctionTypeAlias alias = findNode.functionTypeAlias('F<T>');
GenericTypeAliasElement aliasElement = alias.declaredElement;
- FunctionType aliasType = aliasElement.type;
- ClassDeclaration cNode = unit.declarations[1];
-
- FieldDeclaration fDeclaration = cNode.members[0];
- FunctionType instantiatedAliasType =
- aliasType.instantiate([typeProvider.intType]);
+ FieldDeclaration fDeclaration = findNode.fieldDeclaration('F<int> f');
TypeName typeName = fDeclaration.fields.type;
- expect(typeName.type, instantiatedAliasType);
+ expect('${typeName.type}', 'int Function(bool)');
SimpleIdentifier typeIdentifier = typeName.name;
expect(typeIdentifier.staticElement, same(aliasElement));
- expect(typeIdentifier.staticType, instantiatedAliasType);
+ expect('${typeIdentifier.staticType}', 'int Function(bool)');
List<TypeAnnotation> typeArguments = typeName.typeArguments.arguments;
expect(typeArguments, hasLength(1));
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 964254e..dcc2fad 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -15,7 +15,6 @@
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/status.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/dart/constant/evaluation.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
@@ -1754,7 +1753,7 @@
expect(result.errors, hasLength(0));
var f = result.unit.declarations[0] as FunctionDeclaration;
- expect(f.name.staticType.toString(), '() → int');
+ expect(f.name.staticType.toString(), 'int Function()');
expect(f.returnType.type.toString(), 'int');
// The same result is also received through the stream.
@@ -2228,102 +2227,6 @@
expect(await driver.getSourceKind(path), SourceKind.PART);
}
- test_getTopLevelNameDeclarations() async {
- var a = convertPath('/test/lib/a.dart');
- var b = convertPath('/test/lib/b.dart');
- var c = convertPath('/test/lib/c.dart');
- var d = convertPath('/test/lib/d.dart');
-
- newFile(a, content: 'class A {}');
- newFile(b, content: 'export "a.dart"; class B {}');
- newFile(c, content: 'import "d.dart"; class C {}');
- newFile(d, content: 'class D {}');
-
- driver.addFile(a);
- driver.addFile(b);
- driver.addFile(c);
- // Don't add d.dart, it is referenced implicitly.
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('A'), [a, b], [false, true]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('C'), [c], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('D'), [d], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('X'), [], []);
- }
-
- test_getTopLevelNameDeclarations_discover() async {
- var t = convertPath('/test/lib/test.dart');
- var a1 = convertPath('/aaa/lib/a1.dart');
- var a2 = convertPath('/aaa/lib/src/a2.dart');
- var b = convertPath('/bbb/lib/b.dart');
- var c = convertPath('/ccc/lib/c.dart');
-
- newFile(t, content: 'class T {}');
- newFile(a1, content: 'class A1 {}');
- newFile(a2, content: 'class A2 {}');
- newFile(b, content: 'class B {}');
- newFile(c, content: 'class C {}');
-
- driver.addFile(t);
- // Don't add a1.dart, a2.dart, or b.dart - they should be discovered.
- // And c.dart is not in .packages, so should not be discovered.
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('T'), [t], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('A1'), [a1], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('A2'), [a2], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('B'), [b], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('C'), [], []);
- }
-
- test_getTopLevelNameDeclarations_parts() async {
- var a = convertPath('/test/lib/a.dart');
- var b = convertPath('/test/lib/b.dart');
- var c = convertPath('/test/lib/c.dart');
-
- newFile(a, content: r'''
-library lib;
-part 'b.dart';
-part 'c.dart';
-class A {}
-''');
- newFile(b, content: 'part of lib; class B {}');
- newFile(c, content: 'part of lib; class C {}');
-
- driver.addFile(a);
- driver.addFile(b);
- driver.addFile(c);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('A'), [a], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('B'), [a], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('C'), [a], [false]);
-
- _assertTopLevelDeclarations(
- await driver.getTopLevelNameDeclarations('X'), [], []);
- }
-
test_getUnitElement() async {
String content = r'''
foo(int p) {}
@@ -3392,7 +3295,7 @@
expect(result.errors, hasLength(0));
var f = result.unit.declarations[0] as FunctionDeclaration;
- expect(f.name.staticType.toString(), '() → int');
+ expect(f.name.staticType.toString(), 'int Function()');
expect(f.returnType.type.toString(), 'int');
}
@@ -3513,20 +3416,6 @@
}
}
- void _assertTopLevelDeclarations(
- List<TopLevelDeclarationInSource> declarations,
- List<String> expectedFiles,
- List<bool> expectedIsExported) {
- expect(expectedFiles, hasLength(expectedIsExported.length));
- for (int i = 0; i < expectedFiles.length; i++) {
- expect(declarations,
- contains(predicate((TopLevelDeclarationInSource declaration) {
- return declaration.source.fullName == expectedFiles[i] &&
- declaration.isExported == expectedIsExported[i];
- })));
- }
- }
-
void _expectCircularityError(EvaluationResultImpl evaluationResult) {
expect(evaluationResult, isNotNull);
expect(evaluationResult.value, isNull);
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 f69ba70..24ec015 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -10,7 +10,6 @@
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/analysis/top_level_declaration.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart'
show AnalysisOptions, AnalysisOptionsImpl;
@@ -104,249 +103,6 @@
unorderedEquals(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']));
}
- test_exportedTopLevelDeclarations_cycle() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- String c = convertPath('/aaa/lib/c.dart');
- newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
- newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
- newFile(c, content: r'''
-export 'a.dart';
-class C {}
-''');
- _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C']);
-
- // We asked for 'a', and it was computed.
- // But 'b' and 'c' are not computed, because we detect that there is
- // cycle with 'a', so we cannot get all exported declarations of 'a'.
- _assertHasComputedExportedDeclarations([a]);
- }
-
- test_exportedTopLevelDeclarations_cycle_anotherOutsideCycle() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- String c = convertPath('/aaa/lib/c.dart');
- String d = convertPath('/aaa/lib/d.dart');
- newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
- newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
- newFile(c, content: r'''
-export 'b.dart';
-export 'd.dart';
-class C {}
-''');
- newFile(d, content: r'''
-class D {}
-''');
- _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D']);
-
- // To compute 'a' we compute 'b'.
- // But 'c' is not computed, because of the cycle [b, c].
- // However 'd' is not a part of a cycle, so it is computed too.
- _assertHasComputedExportedDeclarations([a, b, d]);
- }
-
- test_exportedTopLevelDeclarations_cycle_onSequence() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- String c = convertPath('/aaa/lib/c.dart');
- String d = convertPath('/aaa/lib/d.dart');
- String e = convertPath('/aaa/lib/e.dart');
- newFile(a, content: r'''
-export 'b.dart';
-class A {}
-''');
- newFile(b, content: r'''
-export 'c.dart';
-class B {}
-''');
- newFile(c, content: r'''
-export 'd.dart';
-class C {}
-''');
- newFile(d, content: r'''
-export 'e.dart';
-class D {}
-''');
- newFile(e, content: r'''
-export 'c.dart';
-class E {}
-''');
- // We compute 'a'.
- // To compute it we also compute 'b' and 'c'.
- // But 'd' and 'e' are not computed, because of the cycle [c, d, e].
- _assertExportedTopLevelDeclarations(a, ['A', 'B', 'C', 'D', 'E']);
- _assertHasComputedExportedDeclarations([a, b, c]);
-
- // We compute 'd', and try to compute 'e', because 'd' needs 'e'; 'e' can
- // be computed because 'c' is ready, so the cycle [c, d, e] is broken.
- _assertExportedTopLevelDeclarations(d, ['C', 'D', 'E']);
- _assertHasComputedExportedDeclarations([a, b, c, d, e]);
- }
-
- test_exportedTopLevelDeclarations_export() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class A {}
-''');
- newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
- _assertExportedTopLevelDeclarations(b, ['A', 'B']);
- _assertHasComputedExportedDeclarations([a, b]);
- }
-
- test_exportedTopLevelDeclarations_export2_show() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- String c = convertPath('/aaa/lib/c.dart');
- newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
- newFile(b, content: r'''
-export 'a.dart' show A1, A2;
-class B1 {}
-class B2 {}
-''');
- newFile(c, content: r'''
-export 'b.dart' show A2, A3, B1;
-class C {}
-''');
- _assertExportedTopLevelDeclarations(c, ['A2', 'B1', 'C']);
- _assertHasComputedExportedDeclarations([a, b, c]);
- }
-
- test_exportedTopLevelDeclarations_export_flushOnChange() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class A {}
-''');
- newFile(b, content: r'''
-export 'a.dart';
-class B {}
-''');
-
- // Initial exported declarations.
- _assertExportedTopLevelDeclarations(b, ['A', 'B']);
-
- // Update a.dart, so a.dart and b.dart exported declarations are flushed.
- newFile(a, content: 'class A {} class A2 {}');
- fileSystemState.getFileForPath(a).refresh();
- _assertExportedTopLevelDeclarations(b, ['A', 'A2', 'B']);
- }
-
- test_exportedTopLevelDeclarations_export_hide() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class A1 {}
-class A2 {}
-class A3 {}
-''');
- newFile(b, content: r'''
-export 'a.dart' hide A2;
-class B {}
-''');
- _assertExportedTopLevelDeclarations(b, ['A1', 'A3', 'B']);
- }
-
- test_exportedTopLevelDeclarations_export_preferLocal() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class V {}
-''');
- newFile(b, content: r'''
-export 'a.dart';
-int V;
-''');
- FileState file = fileSystemState.getFileForPath(b);
- Map<String, TopLevelDeclaration> declarations =
- file.exportedTopLevelDeclarations;
- expect(declarations.keys, unorderedEquals(['V']));
- expect(declarations['V'].kind, TopLevelDeclarationKind.variable);
- }
-
- test_exportedTopLevelDeclarations_export_show() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class A1 {}
-class A2 {}
-''');
- newFile(b, content: r'''
-export 'a.dart' show A2;
-class B {}
-''');
- _assertExportedTopLevelDeclarations(b, ['A2', 'B']);
- }
-
- test_exportedTopLevelDeclarations_export_show2() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- String c = convertPath('/aaa/lib/c.dart');
- String d = convertPath('/aaa/lib/d.dart');
- newFile(a, content: r'''
-export 'b.dart' show Foo;
-export 'c.dart' show Bar;
-''');
- newFile(b, content: r'''
-export 'd.dart';
-''');
- newFile(c, content: r'''
-export 'd.dart';
-''');
- newFile(d, content: r'''
-class Foo {}
-class Bar {}
-''');
- _assertExportedTopLevelDeclarations(a, ['Foo', 'Bar']);
- }
-
- test_exportedTopLevelDeclarations_import() {
- String a = convertPath('/aaa/lib/a.dart');
- String b = convertPath('/aaa/lib/b.dart');
- newFile(a, content: r'''
-class A {}
-''');
- newFile(b, content: r'''
-import 'a.dart';
-class B {}
-''');
- _assertExportedTopLevelDeclarations(b, ['B']);
- }
-
- test_exportedTopLevelDeclarations_parts() {
- String a = convertPath('/aaa/lib/a.dart');
- String a2 = convertPath('/aaa/lib/a2.dart');
- newFile(a, content: r'''
-library lib;
-part 'a2.dart';
-class A1 {}
-''');
- newFile(a2, content: r'''
-part of lib;
-class A2 {}
-''');
- _assertExportedTopLevelDeclarations(a, ['A1', 'A2']);
- }
-
test_getFileForPath_doesNotExist() {
String path = convertPath('/aaa/lib/a.dart');
FileState file = fileSystemState.getFileForPath(path);
@@ -811,52 +567,6 @@
expect(file.referencedNames, unorderedEquals(['A', 'B', 'C', 'D']));
}
- test_topLevelDeclarations() {
- String path = convertPath('/aaa/lib/a.dart');
- newFile(path, content: r'''
-class C {}
-typedef F();
-enum E {E1, E2}
-mixin M {}
-void f() {}
-var V1;
-get V2 => null;
-set V3(_) {}
-get V4 => null;
-set V4(_) {}
-
-class _C {}
-typedef _F();
-enum _E {E1, E2}
-mixin _M {}
-void _f() {}
-var _V1;
-get _V2 => null;
-set _V3(_) {}
-''');
- FileState file = fileSystemState.getFileForPath(path);
-
- Map<String, TopLevelDeclaration> declarations = file.topLevelDeclarations;
-
- void assertHas(String name, TopLevelDeclarationKind kind) {
- expect(declarations[name]?.kind, kind);
- }
-
- expect(
- declarations.keys,
- unorderedEquals(['C', 'F', 'E', 'M', 'f', 'V1', 'V2', 'V3', 'V4']),
- );
- assertHas('C', TopLevelDeclarationKind.type);
- assertHas('F', TopLevelDeclarationKind.type);
- assertHas('E', TopLevelDeclarationKind.type);
- assertHas('M', TopLevelDeclarationKind.type);
- assertHas('f', TopLevelDeclarationKind.function);
- assertHas('V1', TopLevelDeclarationKind.variable);
- assertHas('V2', TopLevelDeclarationKind.variable);
- assertHas('V3', TopLevelDeclarationKind.variable);
- assertHas('V4', TopLevelDeclarationKind.variable);
- }
-
test_transitiveSignature() {
String pa = convertPath('/aaa/lib/a.dart');
String pb = convertPath('/aaa/lib/b.dart');
@@ -917,24 +627,11 @@
expect(bSignature, isNot(aSignature));
}
- void _assertExportedTopLevelDeclarations(String path, List<String> expected) {
- FileState file = fileSystemState.getFileForPath(path);
- Map<String, TopLevelDeclaration> declarations =
- file.exportedTopLevelDeclarations;
- expect(declarations.keys, unorderedEquals(expected));
- }
-
void _assertFilesWithoutLibraryCycle(List<FileState> expected) {
var actual = fileSystemState.test.filesWithoutLibraryCycle;
expect(_excludeSdk(actual), unorderedEquals(expected));
}
- void _assertHasComputedExportedDeclarations(List<String> expectedPathList) {
- FileSystemStateTestView test = fileSystemState.test;
- expect(test.librariesWithComputedExportedDeclarations.map((f) => f.path),
- unorderedEquals(expectedPathList));
- }
-
void _assertIsUnresolvedFile(FileState file) {
expect(file.path, isNull);
expect(file.uri, isNull);
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 5771180..00cf65e 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -1713,6 +1713,48 @@
AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
}
+ void test_visitExtensionDeclaration_empty() {
+ _assertSource(
+ 'extension E on C {}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E', extendedType: AstTestFactory.typeName4('C')));
+ }
+
+ void test_visitExtensionDeclaration_multipleMember() {
+ _assertSource(
+ 'extension E on C {var a; var b;}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ extendedType: AstTestFactory.typeName4('C'),
+ members: [
+ AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+ [AstTestFactory.variableDeclaration('a')]),
+ AstTestFactory.fieldDeclaration2(
+ false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+ ]));
+ }
+
+ void test_visitExtensionDeclaration_parameters() {
+ _assertSource(
+ 'extension E<T> on C {}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ typeParameters: AstTestFactory.typeParameterList(['T']),
+ extendedType: AstTestFactory.typeName4('C')));
+ }
+
+ void test_visitExtensionDeclaration_singleMember() {
+ _assertSource(
+ 'extension E on C {var a;}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ extendedType: AstTestFactory.typeName4('C'),
+ members: [
+ AstTestFactory.fieldDeclaration2(
+ false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+ ]));
+ }
+
void test_visitFieldDeclaration_instance() {
_assertSource(
"var a;",
@@ -2351,6 +2393,16 @@
"f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
}
+ void test_visitFunctionTypedFormalParameter_nullable() {
+ _assertSource(
+ "T f()?",
+ astFactory.functionTypedFormalParameter2(
+ returnType: AstTestFactory.typeName4("T"),
+ identifier: AstTestFactory.identifier3('f'),
+ parameters: AstTestFactory.formalParameterList([]),
+ question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+ }
+
void test_visitFunctionTypedFormalParameter_type() {
_assertSource(
"T f()",
@@ -4427,6 +4479,48 @@
AstTestFactory.extendsClause(AstTestFactory.typeName4("C")));
}
+ void test_visitExtensionDeclaration_empty() {
+ _assertSource(
+ 'extension E on C {}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E', extendedType: AstTestFactory.typeName4('C')));
+ }
+
+ void test_visitExtensionDeclaration_multipleMember() {
+ _assertSource(
+ 'extension E on C {var a; var b;}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ extendedType: AstTestFactory.typeName4('C'),
+ members: [
+ AstTestFactory.fieldDeclaration2(false, Keyword.VAR,
+ [AstTestFactory.variableDeclaration('a')]),
+ AstTestFactory.fieldDeclaration2(
+ false, Keyword.VAR, [AstTestFactory.variableDeclaration('b')])
+ ]));
+ }
+
+ void test_visitExtensionDeclaration_parameters() {
+ _assertSource(
+ 'extension E<T> on C {}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ typeParameters: AstTestFactory.typeParameterList(['T']),
+ extendedType: AstTestFactory.typeName4('C')));
+ }
+
+ void test_visitExtensionDeclaration_singleMember() {
+ _assertSource(
+ 'extension E on C {var a;}',
+ AstTestFactory.extensionDeclaration(
+ name: 'E',
+ extendedType: AstTestFactory.typeName4('C'),
+ members: [
+ AstTestFactory.fieldDeclaration2(
+ false, Keyword.VAR, [AstTestFactory.variableDeclaration('a')])
+ ]));
+ }
+
void test_visitFieldDeclaration_instance() {
_assertSource(
"var a;",
@@ -5065,6 +5159,16 @@
"f()", AstTestFactory.functionTypedFormalParameter(null, "f"));
}
+ void test_visitFunctionTypedFormalParameter_nullable() {
+ _assertSource(
+ "T f()?",
+ astFactory.functionTypedFormalParameter2(
+ returnType: AstTestFactory.typeName4("T"),
+ identifier: AstTestFactory.identifier3('f'),
+ parameters: AstTestFactory.formalParameterList([]),
+ question: TokenFactory.tokenFromType(TokenType.QUESTION)));
+ }
+
void test_visitFunctionTypedFormalParameter_type() {
_assertSource(
"T f()",
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index bc41dcb..792b693 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -238,7 +238,7 @@
ClassElementImpl classA = ElementFactory.classElement2("A");
String methodName = "m";
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
- method.abstract = true;
+ method.isAbstract = true;
classA.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA];
@@ -260,7 +260,7 @@
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
- method.abstract = true;
+ method.isAbstract = true;
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
@@ -298,11 +298,11 @@
// }
LibraryElementImpl library = _newLibrary();
ClassElementImpl classA = ElementFactory.classElement2("A");
- classA.abstract = true;
+ classA.isAbstract = true;
String methodName = "m";
MethodElementImpl inheritedMethod =
ElementFactory.methodElement(methodName, null);
- inheritedMethod.abstract = true;
+ inheritedMethod.isAbstract = true;
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -485,7 +485,7 @@
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
- method.abstract = true;
+ method.isAbstract = true;
classB.methods = <MethodElement>[method];
(library.definingCompilationUnit as CompilationUnitElementImpl).types =
<ClassElement>[classA, classB];
@@ -524,11 +524,11 @@
// }
LibraryElementImpl library = _newLibrary();
ClassElementImpl classA = ElementFactory.classElement2("A");
- classA.abstract = true;
+ classA.isAbstract = true;
String methodName = "m";
MethodElementImpl inheritedMethod =
ElementFactory.methodElement(methodName, null);
- inheritedMethod.abstract = true;
+ inheritedMethod.isAbstract = true;
classA.methods = <MethodElement>[inheritedMethod];
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -558,7 +558,7 @@
ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
MethodElementImpl abstractMethod =
ElementFactory.methodElement(methodName, null);
- abstractMethod.abstract = true;
+ abstractMethod.isAbstract = true;
classB.methods = <MethodElement>[abstractMethod];
ClassElementImpl classC = ElementFactory.classElement("C", classB.type);
MethodElementImpl method = ElementFactory.methodElement(methodName, null);
@@ -1834,14 +1834,14 @@
var s = ElementFactory.genericTypeAliasElement("s");
t.function.returnType = s.type;
s.function.returnType = t.type;
- expect(t.type.toString(), '() \u2192 () \u2192 ...');
+ expect(t.type.toString(), '... Function() Function()');
}
void test_toString_recursive_via_interface_type() {
var f = ElementFactory.genericTypeAliasElement('f');
ClassElementImpl c = ElementFactory.classElement2('C', ['T']);
f.function.returnType = c.type.instantiate([f.type]);
- expect(f.type.toString(), '() \u2192 C<...>');
+ expect(f.type.toString(), 'C<...> Function()');
}
void test_typeParameters_genericLocalFunction_genericMethod_genericClass() {
@@ -3844,6 +3844,88 @@
expect(type.resolveToBound(null), same(classS.type));
}
+ void test_resolveToBound_bound_nullableInner() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_nullableInnerOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_nullableInnerStarOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(
+ type.resolveToBound(null),
+ equals((classS.type as TypeImpl)
+ .withNullability(NullabilitySuffix.question)));
+ }
+
+ void test_resolveToBound_bound_nullableOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound = classS.type;
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.question);
+ expect(
+ type.resolveToBound(null),
+ equals((classS.type as TypeImpl)
+ .withNullability(NullabilitySuffix.question)));
+ }
+
+ void test_resolveToBound_bound_starInner() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_starInnerNullableOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound =
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.question);
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.star);
+ expect(type.resolveToBound(null), same(element.bound));
+ }
+
+ void test_resolveToBound_bound_starOuter() {
+ ClassElementImpl classS = ElementFactory.classElement2("A");
+ TypeParameterElementImpl element =
+ new TypeParameterElementImpl.forNode(AstTestFactory.identifier3("E"));
+ element.bound = classS.type;
+ TypeParameterTypeImpl type = new TypeParameterTypeImpl(element)
+ .withNullability(NullabilitySuffix.star);
+ expect(
+ type.resolveToBound(null),
+ same(
+ (classS.type as TypeImpl).withNullability(NullabilitySuffix.star)));
+ }
+
void test_resolveToBound_nestedBound() {
ClassElementImpl classS = ElementFactory.classElement2("A");
TypeParameterElementImpl elementE =
diff --git a/pkg/analyzer/test/src/dart/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index a0c2fd3..d5bb2f7 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -46,7 +46,7 @@
void basicChecks(FunctionType f,
{element,
- displayName: '() → dynamic',
+ displayName: 'dynamic Function()',
returnType,
namedParameterTypes: isEmpty,
normalParameterNames: isEmpty,
@@ -148,7 +148,7 @@
var e = new MockGenericTypeAliasElement('F');
basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
basicChecks(e.function.type,
- element: same(e.function), displayName: '() → dynamic');
+ element: same(e.function), displayName: 'dynamic Function()');
}
test_forTypedef_innerAndOuterTypeParameter() {
@@ -172,7 +172,7 @@
typeFormals: [same(t)]);
basicChecks(e.function.type,
element: same(e.function),
- displayName: '<U>(U) → T',
+ displayName: 'T Function<U>(U)',
returnType: same(t.type),
typeArguments: [same(t.type)],
typeParameters: [same(t)],
@@ -223,7 +223,7 @@
returnType: same(t.type));
basicChecks(e.function.type,
element: same(e.function),
- displayName: '<T>() → T',
+ displayName: 'T Function<T>()',
returnType: same(t.type),
typeFormals: [same(t)]);
}
@@ -240,7 +240,7 @@
parameters: [same(p)]);
basicChecks(e.function.type,
element: same(e.function),
- displayName: '(dynamic) → dynamic',
+ displayName: 'dynamic Function(dynamic)',
normalParameterNames: ['p'],
normalParameterTypes: [same(dynamicType)],
parameters: [same(p)]);
@@ -260,7 +260,7 @@
if (bug_33302_fixed) {
expect(fReturn.displayName, 'List<G>');
} else {
- expect(fReturn.displayName, 'List<() → List<...>>');
+ expect(fReturn.displayName, 'List<List<...> Function()>');
}
var fReturnArg = (fReturn as InterfaceType).typeArguments[0];
expect(fReturnArg.element, same(g.function));
@@ -271,9 +271,10 @@
basicChecks(f.function.type,
element: same(f.function), displayName: isNotNull, returnType: fReturn);
if (bug_33302_fixed) {
- expect(f.function.type.displayName, '() → List<G>');
+ expect(f.function.type.displayName, 'List<G> Function()');
} else {
- expect(f.function.type.displayName, '() → List<() → List<...>>');
+ expect(
+ f.function.type.displayName, 'List<List<...> Function()> Function()');
}
basicChecks(g.type,
element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -282,7 +283,7 @@
if (bug_33302_fixed) {
expect(gReturn.displayName, 'List<F>');
} else {
- expect(gReturn.displayName, 'List<() → List<...>>');
+ expect(gReturn.displayName, 'List<List<...> Function()>');
}
var gReturnArg = (gReturn as InterfaceType).typeArguments[0];
expect(gReturnArg.element, same(f.function));
@@ -293,9 +294,10 @@
basicChecks(g.function.type,
element: same(g.function), displayName: isNotNull, returnType: gReturn);
if (bug_33302_fixed) {
- expect(g.function.type.displayName, '() → F');
+ expect(g.function.type.displayName, 'F Function()');
} else {
- expect(g.function.type.displayName, '() → List<() → List<...>>');
+ expect(
+ g.function.type.displayName, 'List<List<...> Function()> Function()');
}
}
@@ -326,9 +328,9 @@
normalParameterNames: ['g'],
returnType: same(voidType));
if (bug_33302_fixed) {
- expect(f.function.type.displayName, '(G) → void');
+ expect(f.function.type.displayName, 'void Function(G)');
} else {
- expect(f.function.type.displayName, '((...) → void) → void');
+ expect(f.function.type.displayName, 'void Function(void Function(...))');
}
basicChecks(g.type,
element: same(g),
@@ -350,9 +352,9 @@
normalParameterNames: ['f'],
returnType: same(voidType));
if (bug_33302_fixed) {
- expect(g.function.type.displayName, '(F) → void');
+ expect(g.function.type.displayName, 'void Function(F)');
} else {
- expect(g.function.type.displayName, '((...) → void) → void');
+ expect(g.function.type.displayName, 'void Function(void Function(...))');
}
}
@@ -372,9 +374,9 @@
basicChecks(f.function.type,
element: same(f.function), displayName: isNotNull, returnType: fReturn);
if (bug_33302_fixed) {
- expect(f.function.type.displayName, '() → G');
+ expect(f.function.type.displayName, 'G Function()');
} else {
- expect(f.function.type.displayName, '() → () → ...');
+ expect(f.function.type.displayName, '... Function() Function()');
}
basicChecks(g.type,
element: same(g), displayName: 'G', name: 'G', returnType: isNotNull);
@@ -385,9 +387,9 @@
basicChecks(g.function.type,
element: same(g.function), displayName: isNotNull, returnType: gReturn);
if (bug_33302_fixed) {
- expect(g.function.type.displayName, '() → F');
+ expect(g.function.type.displayName, 'F Function()');
} else {
- expect(g.function.type.displayName, '() → () → ...');
+ expect(g.function.type.displayName, '... Function() Function()');
}
}
@@ -397,7 +399,7 @@
element: same(e), displayName: 'F', name: 'F', returnType: objectType);
basicChecks(e.function.type,
element: same(e.function),
- displayName: '() → Object',
+ displayName: 'Object Function()',
returnType: objectType);
}
@@ -405,7 +407,7 @@
var e = new MockGenericTypeAliasElement.withNullReturn('F');
basicChecks(e.type, element: same(e), displayName: 'F', name: 'F');
basicChecks(e.function.type,
- element: same(e.function), displayName: '() → dynamic');
+ element: same(e.function), displayName: 'dynamic Function()');
}
test_forTypedef_typeParameter() {
@@ -421,7 +423,7 @@
typeFormals: [same(t)]);
basicChecks(e.function.type,
element: same(e.function),
- displayName: '() → T',
+ displayName: 'T Function()',
returnType: same(t.type),
typeArguments: [same(t.type)],
typeParameters: [same(t)]);
@@ -440,7 +442,7 @@
FunctionType instantiated = f.instantiate([objectType]);
basicChecks(instantiated,
element: isNull,
- displayName: '(Object) → Object',
+ displayName: 'Object Function(Object)',
returnType: same(objectType),
normalParameterNames: ['x'],
normalParameterTypes: [same(objectType)],
@@ -467,7 +469,7 @@
FunctionType instantiated = f.instantiate([objectType]);
basicChecks(instantiated,
element: isNull,
- displayName: '(int) → Object',
+ displayName: 'Object Function(int)',
returnType: same(objectType),
normalParameterNames: ['x'],
normalParameterTypes: [same(intType)],
@@ -480,7 +482,7 @@
FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
basicChecks(f,
element: isNull,
- displayName: '({x: Object}) → dynamic',
+ displayName: 'dynamic Function({x: Object})',
namedParameterTypes: {'x': same(objectType)},
parameters: hasLength(1));
expect(f.parameters[0].isNamed, isTrue);
@@ -493,7 +495,7 @@
FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
basicChecks(f,
element: isNull,
- displayName: '(Object) → dynamic',
+ displayName: 'dynamic Function(Object)',
normalParameterNames: ['x'],
normalParameterTypes: [same(objectType)],
parameters: hasLength(1));
@@ -508,7 +510,7 @@
FunctionType f = new FunctionTypeImpl.synthetic(dynamicType, [], [p]);
basicChecks(f,
element: isNull,
- displayName: '([Object]) → dynamic',
+ displayName: 'dynamic Function([Object])',
optionalParameterNames: ['x'],
optionalParameterTypes: [same(objectType)],
parameters: hasLength(1));
@@ -521,7 +523,7 @@
FunctionType f = new FunctionTypeImpl.synthetic(objectType, [], []);
basicChecks(f,
element: isNull,
- displayName: '() → Object',
+ displayName: 'Object Function()',
returnType: same(objectType));
}
@@ -537,7 +539,7 @@
var uSubstituted = substituted.typeFormals[0];
basicChecks(substituted,
element: isNull,
- displayName: '<U extends Object>(Object, U) → Map<Object, U>',
+ displayName: 'Map<Object, U> Function<U extends Object>(Object, U)',
returnType: mapOf(objectType, uSubstituted.type),
typeFormals: [uSubstituted],
normalParameterNames: ['x', 'y'],
@@ -562,7 +564,7 @@
FunctionType substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: isNull,
- displayName: '<U extends Object>(int) → int',
+ displayName: 'int Function<U extends Object>(int)',
returnType: same(f.returnType),
typeFormals: hasLength(1),
normalParameterNames: ['x'],
@@ -582,7 +584,7 @@
FunctionType substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: isNull,
- displayName: '<U>(Object, U) → int',
+ displayName: 'int Function<U>(Object, U)',
returnType: same(f.returnType),
typeFormals: same(f.typeFormals),
normalParameterNames: ['x', 'y'],
@@ -599,7 +601,7 @@
FunctionType substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: isNull,
- displayName: '<U>(U) → Object',
+ displayName: 'Object Function<U>(U)',
returnType: same(objectType),
typeFormals: same(f.typeFormals),
normalParameterNames: ['x'],
@@ -622,7 +624,7 @@
FunctionType f = new FunctionTypeImpl.synthetic(t.type, [t], []);
basicChecks(f,
element: isNull,
- displayName: '<T>() → T',
+ displayName: 'T Function<T>()',
returnType: same(t.type),
typeFormals: [same(t)]);
}
@@ -648,7 +650,7 @@
var instantiated = f.instantiate([t.type]);
basicChecks(instantiated,
element: same(e),
- displayName: '(T) → dynamic',
+ displayName: 'dynamic Function(T)',
typeArguments: hasLength(1),
typeParameters: [same(t)],
normalParameterNames: ['x'],
@@ -671,7 +673,7 @@
var instantiated = f.instantiate([objectType]);
basicChecks(instantiated,
element: same(e),
- displayName: '(Object) → dynamic',
+ displayName: 'dynamic Function(Object)',
typeArguments: hasLength(1),
typeParameters: [same(t)],
normalParameterNames: ['x'],
@@ -690,7 +692,7 @@
var instantiated = f.instantiate([objectType]);
basicChecks(instantiated,
element: same(e),
- displayName: '() → Object',
+ displayName: 'Object Function()',
typeArguments: hasLength(1),
typeParameters: [same(t)],
returnType: same(objectType));
@@ -703,7 +705,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '({x: dynamic}) → dynamic',
+ displayName: 'dynamic Function({x: dynamic})',
namedParameterTypes: {'x': same(dynamicType)},
parameters: [same(p)]);
}
@@ -715,7 +717,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '({x: Object}) → dynamic',
+ displayName: 'dynamic Function({x: Object})',
namedParameterTypes: {'x': same(objectType)},
parameters: [same(p)]);
}
@@ -735,7 +737,7 @@
element: same(e),
typeArguments: [same(t.type)],
typeParameters: [same(t)],
- displayName: '() → T',
+ displayName: 'T Function()',
returnType: same(t.type));
}
@@ -745,7 +747,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '(dynamic) → dynamic',
+ displayName: 'dynamic Function(dynamic)',
normalParameterNames: ['x'],
normalParameterTypes: [same(dynamicType)],
parameters: [same(p)]);
@@ -757,7 +759,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '(Object) → dynamic',
+ displayName: 'dynamic Function(Object)',
normalParameterNames: ['x'],
normalParameterTypes: [same(objectType)],
parameters: [same(p)]);
@@ -770,7 +772,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '([dynamic]) → dynamic',
+ displayName: 'dynamic Function([dynamic])',
optionalParameterNames: ['x'],
optionalParameterTypes: [same(dynamicType)],
parameters: [same(p)]);
@@ -783,7 +785,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '([Object]) → dynamic',
+ displayName: 'dynamic Function([Object])',
optionalParameterNames: ['x'],
optionalParameterTypes: [same(objectType)],
parameters: [same(p)]);
@@ -795,7 +797,7 @@
basicChecks(f,
element: same(e),
returnType: same(objectType),
- displayName: '() → Object');
+ displayName: 'Object Function()');
}
test_unnamedConstructor_returnType_null() {
@@ -804,7 +806,7 @@
basicChecks(f,
element: same(e),
returnType: same(dynamicType),
- displayName: '() → dynamic');
+ displayName: 'dynamic Function()');
}
test_unnamedConstructor_staticMethod_ignores_enclosing_type_params() {
@@ -854,10 +856,10 @@
typeArguments: [same(objectType)]);
if (bug_33300_fixed) {
expect(substituted.displayName,
- '<S extends T,T extends Object,V extends T>() → Map<S, V>');
+ 'Map<S, V> Function<S extends T,T extends Object,V extends T>()');
} else {
expect(substituted.displayName,
- '<S extends T extends Object,T extends Object,V extends T>() → Map<S, V>');
+ 'Map<S, V> Function<S extends T extends Object,T extends Object,V extends T>()');
}
var s2 = substituted.typeFormals[0];
var t2 = substituted.typeFormals[1];
@@ -908,12 +910,10 @@
typeArguments: [same(objectType)]);
if (bug_33300_fixed) {
expect(substituted.displayName,
- '<S extends T,T extends Object,V extends T>(S, V) → void');
+ 'void Function<S extends T,T extends Object,V extends T>(S, V)');
} else {
- expect(
- substituted.displayName,
- '<S extends T extends Object,T extends Object,V extends T>(S, V) '
- '→ void');
+ expect(substituted.displayName,
+ 'void Function<S extends T extends Object,T extends Object,V extends T>(S, V)');
}
var s2 = substituted.typeFormals[0];
var t2 = substituted.typeFormals[1];
@@ -944,7 +944,7 @@
var substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: same(e),
- displayName: '<U extends Object>() → U',
+ displayName: 'U Function<U extends Object>()',
typeArguments: [same(objectType)],
typeParameters: [same(t)],
returnType: isNotNull,
@@ -961,7 +961,9 @@
FunctionType f = new FunctionTypeImpl(e);
var substituted = f.substitute2([t.type], [t.type]);
basicChecks(substituted,
- element: same(e), displayName: '() → T', returnType: same(t.type));
+ element: same(e),
+ displayName: 'T Function()',
+ returnType: same(t.type));
// TODO(paulberry): test substitute length mismatch
}
@@ -974,7 +976,7 @@
var substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: same(e),
- displayName: '(Object) → dynamic',
+ displayName: 'dynamic Function(Object)',
normalParameterNames: ['x'],
normalParameterTypes: [same(objectType)],
parameters: hasLength(1),
@@ -993,7 +995,7 @@
var substituted = f.substitute2([objectType], [t.type]);
basicChecks(substituted,
element: same(e),
- displayName: '() → Object',
+ displayName: 'Object Function()',
returnType: same(objectType),
typeArguments: [same(objectType)],
typeParameters: [same(t)]);
@@ -1005,7 +1007,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '<T>() → dynamic',
+ displayName: 'dynamic Function<T>()',
typeFormals: [same(t)]);
// TODO(paulberry): test pruning of bounds
}
@@ -1019,7 +1021,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '<U extends T>() → U',
+ displayName: 'U Function<U extends T>()',
typeArguments: [same(t.type)],
typeParameters: [same(t)],
returnType: same(u.type),
@@ -1038,7 +1040,7 @@
FunctionType f = new FunctionTypeImpl(e);
basicChecks(f,
element: same(e),
- displayName: '() → T',
+ displayName: 'T Function()',
returnType: same(t.type),
typeArguments: [same(t.type)],
typeParameters: [same(t)]);
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
index 07b9de2..6286672 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
@@ -47,7 +47,7 @@
_assertGetInherited(
className: 'X',
name: 'foo',
- expected: 'B.foo: () → void',
+ expected: 'B.foo: void Function()',
);
}
@@ -70,7 +70,7 @@
_assertGetInherited(
className: 'X',
name: 'foo',
- expected: 'J.foo: () → void',
+ expected: 'J.foo: void Function()',
);
}
@@ -93,7 +93,7 @@
_assertGetInherited(
className: 'X',
name: 'foo',
- expected: 'M.foo: () → void',
+ expected: 'M.foo: void Function()',
);
}
@@ -116,7 +116,7 @@
_assertGetInherited(
className: 'X',
name: 'foo',
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -131,7 +131,7 @@
await resolveTestFile();
_assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
''');
}
@@ -158,7 +158,7 @@
await resolveTestFile();
_assertInheritedConcreteMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
''');
}
@@ -181,7 +181,7 @@
await resolveTestFile();
_assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -214,7 +214,7 @@
await resolveTestFile();
_assertInheritedConcreteMap('C', r'''
-A.foo: (int) → void
+A.foo: void Function(int)
''');
}
@@ -242,7 +242,7 @@
await resolveTestFile();
_assertInheritedConcreteMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -261,8 +261,8 @@
await resolveTestFile();
_assertInheritedConcreteMap('C', r'''
-A.foo: () → void
-B.bar: () → void
+A.foo: void Function()
+B.bar: void Function()
''');
}
@@ -277,7 +277,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
''');
}
@@ -292,7 +292,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
''');
}
@@ -307,7 +307,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
+A.foo: int Function()
''');
}
@@ -326,7 +326,7 @@
await resolveTestFile();
_assertInheritedMap('X', r'''
-B.foo: () → void
+B.foo: void Function()
''');
}
@@ -341,8 +341,8 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
''');
}
@@ -357,8 +357,8 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
''');
}
@@ -373,8 +373,8 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → int
-A.foo=: (int) → void
+A.foo: int Function()
+A.foo=: void Function(int)
''');
}
@@ -398,7 +398,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -413,7 +413,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -428,7 +428,7 @@
await resolveTestFile();
_assertInheritedMap('B', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -449,7 +449,7 @@
await resolveTestFile();
_assertInheritedMap('X', r'''
-A.foo: () → void
+A.foo: void Function()
''');
}
@@ -470,7 +470,7 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-J.bar: () → void
+J.bar: void Function()
''');
}
@@ -489,8 +489,8 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-I.foo: () → int
-J.bar: () → double
+I.foo: int Function()
+J.bar: double Function()
''');
}
@@ -509,7 +509,7 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-J.foo: () → int
+J.foo: int Function()
''');
}
@@ -528,7 +528,7 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-J.foo: () → void
+J.foo: void Function()
''');
}
@@ -548,11 +548,11 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
''');
_assertInheritedMap('B', r'''
-I.foo=: (num) → void
+I.foo=: void Function(num)
''');
}
@@ -580,11 +580,11 @@
await resolveTestFile();
_assertInheritedMap('D', r'''
-I3.foo: () → C
+I3.foo: C Function()
''');
_assertInheritedMap('E', r'''
-I3.foo: () → C
+I3.foo: C Function()
''');
}
@@ -612,7 +612,7 @@
await resolveTestFile();
_assertInheritedMap('D', r'''
-I1.foo: (A) → void
+I1.foo: void Function(A)
''');
}
@@ -640,11 +640,11 @@
await resolveTestFile();
_assertInheritedMap('D', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
''');
_assertInheritedMap('E', r'''
-I1.foo=: (A) → void
+I1.foo=: void Function(A)
''');
}
@@ -664,11 +664,11 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
''');
_assertInheritedMap('B', r'''
-I2.foo: ([int]) → int
+I2.foo: int Function([int])
''');
}
@@ -692,11 +692,11 @@
await resolveTestFile();
_assertInheritedMap('A', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
''');
_assertInheritedMap('B', r'''
-I3.foo: ([int, int]) → int
+I3.foo: int Function([int, int])
''');
}
@@ -717,7 +717,7 @@
_assertGetMember(
className: 'C',
name: 'f',
- expected: 'I2.f: (Object) → void',
+ expected: 'I2.f: void Function(Object)',
);
}
@@ -733,7 +733,7 @@
className: 'A',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -766,7 +766,7 @@
className: 'X',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -786,7 +786,7 @@
className: 'X',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -806,7 +806,7 @@
className: 'X',
name: 'toString',
concrete: true,
- expected: 'A.toString: () → String',
+ expected: 'A.toString: String Function()',
);
}
@@ -824,7 +824,7 @@
className: 'X',
name: 'foo',
concrete: true,
- expected: 'M.foo: () → void',
+ expected: 'M.foo: void Function()',
);
}
@@ -844,14 +844,14 @@
className: 'B',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
_assertGetMember(
className: 'C',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -886,14 +886,14 @@
className: 'B',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
_assertGetMember(
className: 'C',
name: 'foo',
concrete: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -938,7 +938,7 @@
className: 'C',
name: 'foo',
concrete: true,
- expected: 'C.foo: ([int]) → void',
+ expected: 'C.foo: void Function([int])',
);
}
@@ -967,7 +967,7 @@
_assertGetMember(
className: 'X',
name: 'foo',
- expected: 'M2.foo: () → void',
+ expected: 'M2.foo: void Function()',
);
}
@@ -992,7 +992,7 @@
_assertGetMember(
className: 'X',
name: 'foo',
- expected: 'B.foo: () → void',
+ expected: 'B.foo: void Function()',
);
}
@@ -1015,7 +1015,7 @@
_assertGetMember(
className: 'X',
name: 'foo',
- expected: 'X.foo: () → void',
+ expected: 'X.foo: void Function()',
);
}
@@ -1069,7 +1069,7 @@
className: 'M',
name: 'foo',
forSuper: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -1089,7 +1089,7 @@
className: 'X',
name: 'foo',
forSuper: true,
- expected: 'M.foo: () → void',
+ expected: 'M.foo: void Function()',
);
}
@@ -1109,7 +1109,7 @@
className: 'B',
name: 'foo',
forSuper: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
@@ -1145,7 +1145,7 @@
className: 'B',
name: 'foo',
forSuper: true,
- expected: 'A.foo: () → void',
+ expected: 'A.foo: void Function()',
);
}
diff --git a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
index d3bf71a..0069fd1 100644
--- a/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
+++ b/pkg/analyzer/test/src/dart/element/type_algebra_test.dart
@@ -92,7 +92,7 @@
{t: intType},
{t: BottomTypeImpl.instance},
).substituteType(type);
- assertElementTypeString(result, '(Never) → int');
+ assertElementTypeString(result, 'int Function(Never)');
}
}
@@ -138,11 +138,11 @@
var type = findElement.genericTypeAlias('F').function.type;
var t = findElement.typeParameter('T');
- assertElementTypeString(type, '<U extends T>(U) → T');
+ assertElementTypeString(type, 'T Function<U extends T>(U)');
_assertSubstitution(
type,
{t: intType},
- '<U extends int>(U) → int',
+ 'int Function<U extends int>(U)',
);
}
@@ -155,16 +155,16 @@
var type = findElement.genericTypeAlias('F').function.type;
var t = findElement.typeParameter('T');
var u = findElement.typeParameter('U');
- assertElementTypeString(type, '(U, bool) → T');
+ assertElementTypeString(type, 'T Function(U, bool)');
_assertSubstitution(
type,
{t: intType},
- '(U, bool) → int',
+ 'int Function(U, bool)',
);
_assertSubstitution(
type,
{t: intType, u: doubleType},
- '(double, bool) → int',
+ 'int Function(double, bool)',
);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
index 37aa571..d1b41ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/class_alias_test.dart
@@ -26,7 +26,7 @@
''');
await resolveTestFile();
assertNoTestErrors();
- assertConstructors(findElement.class_('X'), ['X() → X']);
+ assertConstructors(findElement.class_('X'), ['X X()']);
}
test_element() async {
@@ -83,8 +83,8 @@
await resolveTestFile();
assertNoTestErrors();
- assertConstructors(findElement.class_('C1'), ['C1(int i) → C1']);
- assertConstructors(findElement.class_('C2'), ['C2(int i) → C2']);
+ assertConstructors(findElement.class_('C1'), ['C1 C1(int i)']);
+ assertConstructors(findElement.class_('C2'), ['C2 C2(int i)']);
}
test_implicitConstructors_optionalParameters() async {
@@ -105,9 +105,9 @@
assertConstructors(
findElement.class_('C'),
[
- 'C.c1(int a) → C',
- 'C.c2(int a, [int b, int c]) → C',
- 'C.c3(int a, {int b, int c}) → C'
+ 'C C.c1(int a)',
+ 'C C.c2(int a, [int b, int c])',
+ 'C C.c3(int a, {int b, int c})'
],
);
}
@@ -125,6 +125,6 @@
await resolveTestFile();
assertNoTestErrors();
- assertConstructors(findElement.class_('B'), ['B(E x, E y) → B<E>']);
+ assertConstructors(findElement.class_('B'), ['B<E> B(E x, E y)']);
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
index 7bfebe1..503a83f 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_expression_invocation_test.dart
@@ -51,7 +51,7 @@
var invocation = findNode.functionExpressionInvocation('(0)');
assertType(invocation, 'bool');
- assertInvokeType(invocation, '(int) → bool');
+ assertInvokeType(invocation, 'bool Function(int)');
assertTypeArgumentTypes(invocation, ['int']);
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
index 59062c6..ae124eb 100644
--- a/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/generic_function_type_test.dart
@@ -46,4 +46,101 @@
int Function(int a) y;
''');
}
+
+ /// Test that when multiple [GenericFunctionType]s are used in a
+ /// [FunctionDeclaration], all of them are resolved correctly.
+ test_typeAnnotation_function() async {
+ await assertNoErrorsInCode('''
+void Function() f<T extends bool Function()>(int Function() a) {
+ return null;
+}
+
+double Function() x;
+''');
+ assertType(
+ findNode.genericFunctionType('void Function()'),
+ 'void Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('bool Function()'),
+ 'bool Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('int Function()'),
+ 'int Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('double Function()'),
+ 'double Function()',
+ );
+ }
+
+ /// Test that when multiple [GenericFunctionType]s are used in a
+ /// [FunctionDeclaration], the one in the return type is consumed before the
+ /// one in the parameter type. This is necessary because matching of
+ /// [GenericFunctionType] nodes to their elements is based on the sequential
+ /// identifier of a node in the unit.
+ test_typeAnnotation_function_returnType_parameterType() async {
+ await assertNoErrorsInCode(r'''
+void Function(E a) f<E>(void Function() b) {
+ return (_) {};
+}
+''');
+ }
+
+ /// Test that when multiple [GenericFunctionType]s are used in a
+ /// [GenericFunctionType], all of them are resolved correctly.
+ test_typeAnnotation_genericFunctionType() async {
+ await assertNoErrorsInCode('''
+void f(
+ void Function() a,
+ bool Function() Function(int Function()) b,
+) {}
+''');
+ }
+
+ /// Test that when multiple [GenericFunctionType]s are used in a
+ /// [FunctionDeclaration], all of them are resolved correctly.
+ test_typeAnnotation_method() async {
+ await assertNoErrorsInCode('''
+class C {
+ void Function() m<T extends bool Function()>(int Function() a) {
+ return null;
+ }
+}
+
+double Function() x;
+''');
+ assertType(
+ findNode.genericFunctionType('void Function()'),
+ 'void Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('bool Function()'),
+ 'bool Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('int Function()'),
+ 'int Function()',
+ );
+ assertType(
+ findNode.genericFunctionType('double Function()'),
+ 'double Function()',
+ );
+ }
+
+ /// Test that when multiple [GenericFunctionType]s are used in a
+ /// [MethodDeclaration], the one in the return type is consumed before the
+ /// one in the parameter type. This is necessary because matching of
+ /// [GenericFunctionType] nodes to their elements is based on the sequential
+ /// identifier of a node in the unit.
+ test_typeAnnotation_method_returnType_parameterType() async {
+ await assertNoErrorsInCode(r'''
+class C {
+ void Function(E a) f<E>(void Function() b) {
+ return (_) {};
+ }
+}
+''');
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 0f402b5..c31ff84 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -38,7 +38,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '(int) → void',
+ 'void Function(int)',
);
assertSuperExpression(invocation.target);
}
@@ -63,7 +63,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '(int) → void',
+ 'void Function(int)',
);
assertSuperExpression(invocation.target);
}
@@ -88,7 +88,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '() → int',
+ 'int Function()',
);
assertSuperExpression(invocation.target);
}
@@ -116,7 +116,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'M'),
- '(int) → void',
+ 'void Function(int)',
);
assertSuperExpression(invocation.target);
}
@@ -140,7 +140,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '() → int',
+ 'int Function()',
);
assertSuperExpression(invocation.target);
}
@@ -168,7 +168,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '(int) → void',
+ 'void Function(int)',
);
assertSuperExpression(invocation.target);
}
@@ -195,7 +195,7 @@
]);
var invocation = findNode.methodInvocation('foo(0)');
- assertInvokeType(invocation, '(int) → void');
+ assertInvokeType(invocation, 'void Function(int)');
assertType(invocation, 'void');
}
@@ -221,7 +221,7 @@
]);
var invocation = findNode.methodInvocation('foo(0)');
- assertInvokeType(invocation, '(int) → void');
+ assertInvokeType(invocation, 'void Function(int)');
assertType(invocation, 'void');
}
@@ -311,7 +311,7 @@
_assertInvalidInvocation(
'c.foo();',
findElement.getter('foo'),
- expectedMethodNameType: '() → dynamic',
+ expectedMethodNameType: 'dynamic Function()',
);
}
@@ -332,7 +332,7 @@
_assertInvalidInvocation(
'foo();',
findElement.getter('foo'),
- expectedMethodNameType: '() → dynamic',
+ expectedMethodNameType: 'dynamic Function()',
);
}
@@ -351,7 +351,7 @@
_assertInvalidInvocation(
'foo();',
findElement.getter('foo'),
- expectedMethodNameType: '() → dynamic',
+ expectedMethodNameType: 'dynamic Function()',
);
}
@@ -383,8 +383,8 @@
assertMethodInvocation(
findNode.methodInvocation('foo(0)'),
findElement.getter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → T',
+ 'double Function(int)',
+ expectedMethodNameType: 'T Function()',
);
}
@@ -405,7 +405,7 @@
_assertInvalidInvocation(
'foo()',
findElement.getter('foo'),
- expectedMethodNameType: '() → int',
+ expectedMethodNameType: 'int Function()',
);
}
@@ -426,7 +426,7 @@
_assertInvalidInvocation(
'foo()',
findElement.getter('foo'),
- expectedMethodNameType: '() → int',
+ expectedMethodNameType: 'int Function()',
);
}
@@ -449,7 +449,7 @@
_assertInvalidInvocation(
'foo()',
findElement.getter('foo'),
- expectedMethodNameType: '() → int',
+ expectedMethodNameType: 'int Function()',
);
}
@@ -476,7 +476,7 @@
assertMethodInvocation(
invocation,
import.topFunction('foo'),
- '() → void',
+ 'void Function()',
);
assertImportPrefix(invocation.target, import.prefix);
}
@@ -500,7 +500,7 @@
assertMethodInvocation(
invocation,
import.importedLibrary.loadLibraryFunction,
- '() → Future<dynamic>',
+ 'Future<dynamic> Function()',
);
assertImportPrefix(invocation.target, import.prefix);
}
@@ -867,7 +867,7 @@
'c.foo()',
findElement.getter('foo'),
expectedNameType: 'void',
- expectedMethodNameType: '() → void',
+ expectedMethodNameType: 'void Function()',
);
}
@@ -904,7 +904,7 @@
assertMethodInvocation(
findNode.methodInvocation('foo()()'),
findElement.topFunction('foo'),
- '() → void',
+ 'void Function()',
);
}
@@ -924,7 +924,7 @@
'foo()',
findElement.topGet('foo'),
expectedNameType: 'void',
- expectedMethodNameType: '() → void',
+ expectedMethodNameType: 'void Function()',
);
}
@@ -943,7 +943,7 @@
assertMethodInvocation(
findNode.methodInvocation('toString()'),
null,
- '() → String',
+ 'String Function()',
);
}
@@ -962,7 +962,7 @@
assertMethodInvocation(
findNode.methodInvocation('toString()'),
null,
- '() → String',
+ 'String Function()',
);
}
@@ -981,7 +981,7 @@
assertMethodInvocation(
findNode.methodInvocation('toString()'),
null,
- '() → String',
+ 'String Function()',
);
}
@@ -1000,7 +1000,7 @@
assertMethodInvocation(
findNode.methodInvocation('foo<int>()'),
findElement.topFunction('foo'),
- '() → void',
+ 'void Function()',
);
assertTypeName(findNode.typeName('int>'), intElement, 'int');
}
@@ -1020,7 +1020,7 @@
assertMethodInvocation(
findNode.methodInvocation('foo<int>()'),
findElement.topFunction('foo'),
- '() → Map<num, dynamic>',
+ 'Map<num, dynamic> Function()',
expectedTypeArguments: ['num', 'dynamic'],
);
assertTypeName(findNode.typeName('int>'), intElement, 'int');
@@ -1043,8 +1043,8 @@
assertMethodInvocation(
invocation,
findElement.getter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
assertClassRef(invocation.target, findElement.class_('C'));
}
@@ -1066,7 +1066,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → void',
+ 'void Function(int)',
);
assertClassRef(invocation.target, findElement.class_('C'));
}
@@ -1088,7 +1088,7 @@
assertMethodInvocation(
invocation,
import.importedLibrary.loadLibraryFunction,
- '() → Future<dynamic>',
+ 'Future<dynamic> Function()',
);
assertImportPrefix(invocation.target, import.prefix);
}
@@ -1108,10 +1108,10 @@
assertMethodInvocation(
invocation,
null,
- '(int) → void',
+ 'void Function(int)',
);
assertElement(invocation.target, findElement.topFunction('foo'));
- assertType(invocation.target, '(int) → void');
+ assertType(invocation.target, 'void Function(int)');
}
test_hasReceiver_importPrefix_topFunction() async {
@@ -1135,7 +1135,7 @@
assertMethodInvocation(
invocation,
import.topFunction('foo'),
- '(int, int) → int',
+ 'int Function(int, int)',
expectedTypeArguments: ['int'],
);
assertImportPrefix(invocation.target, import.prefix);
@@ -1162,8 +1162,8 @@
assertMethodInvocation(
invocation,
import.topGetter('foo'),
- '(int, int) → int',
- expectedMethodNameType: '() → <T>(T, T) → T',
+ 'int Function(int, int)',
+ expectedMethodNameType: 'T Function<T>(T, T) Function()',
expectedTypeArguments: ['int'],
);
assertImportPrefix(invocation.target, import.prefix);
@@ -1212,8 +1212,8 @@
assertMethodInvocation(
invocation,
findElement.getter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
}
@@ -1234,8 +1234,8 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → void',
- expectedMethodNameType: '(int) → void',
+ 'void Function(int)',
+ expectedMethodNameType: 'void Function(int)',
);
assertTypeArgumentTypes(invocation, []);
}
@@ -1259,8 +1259,8 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → int',
- expectedMethodNameType: '(int) → int',
+ 'int Function(int)',
+ expectedMethodNameType: 'int Function(int)',
expectedTypeArguments: ['int'],
);
assertTypeArgumentTypes(invocation, ['int']);
@@ -1293,7 +1293,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'I2'),
- '(Object) → void',
+ 'void Function(Object)',
);
}
@@ -1318,7 +1318,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1345,8 +1345,8 @@
assertMethodInvocation(
invocation,
import.class_('C').getGetter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
PrefixedIdentifier target = invocation.target;
@@ -1377,7 +1377,7 @@
assertMethodInvocation(
invocation,
import.class_('C').getMethod('foo'),
- '(int) → void',
+ 'void Function(int)',
);
PrefixedIdentifier target = invocation.target;
@@ -1404,8 +1404,8 @@
assertMethodInvocation(
invocation,
findElement.getter('foo', of: 'A'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
assertSuperExpression(invocation.target);
}
@@ -1429,7 +1429,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo', of: 'A'),
- '(int) → void',
+ 'void Function(int)',
);
assertSuperExpression(invocation.target);
}
@@ -1449,7 +1449,7 @@
assertMethodInvocation(
invocation,
findElement.topFunction('foo'),
- '({a: int, b: bool}) → void',
+ 'void Function({a: int, b: bool})',
);
assertNamedParameterRef('b: false', 'b');
assertNamedParameterRef('a: 0', 'a');
@@ -1474,8 +1474,8 @@
assertMethodInvocation(
invocation,
findElement.getter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
}
@@ -1496,8 +1496,8 @@
assertMethodInvocation(
invocation,
findElement.getter('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
}
@@ -1531,7 +1531,7 @@
assertMethodInvocation(
invocation,
findElement.localFunction('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1550,7 +1550,7 @@
assertMethodInvocation(
invocation,
findElement.localVar('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1571,7 +1571,7 @@
assertMethodInvocation(
invocation,
findElement.parameter('c'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1591,7 +1591,7 @@
assertMethodInvocation(
invocation,
findElement.localVar('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1614,7 +1614,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1635,7 +1635,7 @@
assertMethodInvocation(
invocation,
findElement.method('foo'),
- '(int) → void',
+ 'void Function(int)',
);
}
@@ -1654,8 +1654,8 @@
assertMethodInvocation(
invocation,
findElement.topFunction('foo'),
- '(int) → void',
- expectedMethodNameType: '(int) → void',
+ 'void Function(int)',
+ expectedMethodNameType: 'void Function(int)',
);
}
@@ -1674,8 +1674,8 @@
assertMethodInvocation(
invocation,
findElement.topGet('foo'),
- '(int) → double',
- expectedMethodNameType: '() → (int) → double',
+ 'double Function(int)',
+ expectedMethodNameType: 'double Function(int) Function()',
);
}
@@ -1694,8 +1694,8 @@
assertMethodInvocation(
invocation,
findElement.topGet('foo'),
- '(int) → void',
- expectedMethodNameType: '() → (int) → void',
+ 'void Function(int)',
+ expectedMethodNameType: 'void Function(int) Function()',
);
}
@@ -1726,7 +1726,7 @@
assertMethodInvocation(
invocation,
typeProvider.objectType.getMethod('toString'),
- '() → String',
+ 'String Function()',
);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index a88f8a3..671bdef5 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -1689,7 +1689,7 @@
M<T> f<T>() => null;
''');
var fInvocation = findNode.methodInvocation('f()');
- expect(fInvocation.staticInvokeType.toString(), '() → M<int>');
+ expect(fInvocation.staticInvokeType.toString(), 'M<int> Function()');
}
test_onClause() async {
@@ -1776,7 +1776,7 @@
var invocation = findNode.methodInvocation('foo(42)');
assertElement(invocation, findElement.method('foo'));
- assertInvokeType(invocation, '(int) → void');
+ assertInvokeType(invocation, 'void Function(int)');
assertType(invocation, 'void');
}
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 0011f32..7be6ca3 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
@@ -195,6 +195,30 @@
assertType(findNode.typeName('T? b'), 'T?');
}
+ test_member_potentiallyNullable_called() async {
+ addTestFile(r'''
+m<T extends Function>() {
+ List<T?> x;
+ x.first();
+}
+''');
+ await resolveTestFile();
+ // Do not assert no test errors. Deliberately invokes nullable type.
+ assertType(findNode.methodInvocation('first').methodName, 'Function?');
+ }
+
+ test_null_assertion_operator_changes_null_to_never() async {
+ addTestFile('''
+main() {
+ Null x = null;
+ x!;
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+ assertType(findNode.postfix('x!'), 'Never');
+ }
+
test_null_assertion_operator_removes_nullability() async {
addTestFile('''
main() {
@@ -218,7 +242,7 @@
await resolveTestFile();
assertNoTestErrors();
- assertType(findNode.typeName('F? a'), '(bool, String?) → int??');
+ assertType(findNode.typeName('F? a'), 'int? Function(bool, String?)?');
}
@failingTest
@@ -235,7 +259,7 @@
assertType(
findNode.typeName('F<String>'),
- '(bool!, String!, String?) → int??',
+ 'int? Function(bool!, String!, String?)?',
);
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index 813eec5..5a47b69 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -114,6 +114,46 @@
);
}
+ test_prefixed_unnamed_generic() async {
+ newFile('/test/lib/a.dart', content: r'''
+class C<T> {
+ const C();
+}
+''');
+ await assertNoErrorsInCode(r'''
+import 'a.dart' as p;
+
+const x = p.C<int>();
+''');
+ _fillLibraries();
+
+ var element_C = libraryA.getType('C');
+ var element_p = findElement.prefix('p');
+
+ var creation = findNode.instanceCreation('p.C<int>()');
+ assertType(creation, 'C<int>');
+
+ var constructorName = creation.constructorName;
+
+ var typeName = constructorName.type;
+ assertType(typeName, 'C<int>');
+
+ var pC = typeName.name as PrefixedIdentifier;
+ assertElement(pC, element_C);
+ // TODO(scheglov) enforce
+// assertTypeNull(pC);
+
+ var ref_p = pC.prefix;
+ assertElement(ref_p, element_p);
+ assertTypeNull(ref_p);
+
+ var ref_C = pC.identifier;
+ assertElement(ref_C, element_C);
+ assertTypeNull(ref_C);
+
+ assertType(typeName.typeArguments.arguments[0], 'int');
+ }
+
void _fillLibraries([LibraryElement library]) {
library ??= result.unit.declaredElement.library;
var uriStr = library.source.uri.toString();
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index fadcc32..56deafe 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -198,7 +198,7 @@
var getter = findElement.topGet(name);
assertElement(ref, getter);
- var type = getter.returnType.toString();
+ var type = typeString(getter.returnType);
assertType(ref, type);
}
@@ -206,7 +206,7 @@
var setter = findElement.topSet(name);
assertElement(ref, setter);
- var type = setter.parameters[0].type.toString();
+ var type = typeString(setter.parameters[0].type);
assertType(ref, type);
}
@@ -263,8 +263,8 @@
}
void assertInvokeType(InvocationExpression node, String expected) {
- DartType actual = node.staticInvokeType;
- expect(actual?.toString(), expected);
+ TypeImpl actual = node.staticInvokeType;
+ expect(typeString(actual), expected);
}
void assertInvokeTypeDynamic(InvocationExpression node) {
@@ -275,7 +275,7 @@
void assertMember(
Expression node, String expectedDefiningType, Element expectedBase) {
Member actual = getNodeElement(node);
- expect(actual.definingType.toString(), expectedDefiningType);
+ expect(typeString(actual.definingType), expectedDefiningType);
expect(actual.baseElement, same(expectedBase));
}
@@ -373,15 +373,14 @@
} else {
fail('Unsupported node: (${node.runtimeType}) $node');
}
- expect(actual?.toString(withNullability: typeToStringWithNullability),
- expected);
+ expect(typeString(actual), expected);
}
void assertTypeArgumentTypes(
InvocationExpression node,
List<String> expected,
) {
- var actual = node.typeArgumentTypes.map((t) => '$t').toList();
+ var actual = node.typeArgumentTypes.map((t) => typeString(t)).toList();
expect(actual, expected);
}
@@ -460,6 +459,11 @@
findElement = new FindElement(result.unit);
}
+ /// Return a textual representation of the [type] that is appropriate for
+ /// tests.
+ String typeString(DartType type) => (type as TypeImpl)
+ ?.toString(withNullability: typeToStringWithNullability);
+
Element _unwrapHandle(Element element) {
if (element is ElementHandle && element is! Member) {
return element.actualElement;
@@ -468,8 +472,8 @@
}
static String _extractReturnType(String invokeType) {
- int arrowIndex = invokeType.indexOf('→');
- expect(arrowIndex, isNonNegative);
- return invokeType.substring(arrowIndex + 1).trim();
+ int functionIndex = invokeType.indexOf(' Function');
+ expect(functionIndex, isNonNegative);
+ return invokeType.substring(0, functionIndex);
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
new file mode 100644
index 0000000..0b07098
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/collection_elements_test.dart
@@ -0,0 +1,335 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ForElementWithNnbdTest);
+ defineReflectiveTests(IfElementWithNnbdTest);
+ defineReflectiveTests(SpreadElementWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class ForElementWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_list_awaitForIn_dynamic_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int>[await for (var e in a()) e];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+ }
+
+ @failingTest
+ test_list_awaitForIn_int_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int>[await for (int e in a()) e];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+ }
+
+ @failingTest
+ test_list_for_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>[for (int i = 0; a(); i++) i];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_list_forIn_dynamic_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>[for (var e in a()) e];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+ }
+
+ @failingTest
+ test_list_forIn_int_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>[for (int e in a()) e];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+
+ @failingTest
+ test_map_awaitForIn_dynamic_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int, int>{await for (var e in a()) e : e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+ }
+
+ @failingTest
+ test_map_awaitForIn_int_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int, int>{await for (int e in a()) e : e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+ }
+
+ @failingTest
+ test_map_for_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int, int>{for (int i = 0; a(); i++) i : i};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_map_forIn_dynamic_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int, int>{for (var e in a()) e : e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+ }
+
+ @failingTest
+ test_map_forIn_int_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int, int>{for (int e in a()) e : e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+
+ @failingTest
+ test_set_awaitForIn_dynamic_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int>{await for (var e in a()) e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+ }
+
+ @failingTest
+ test_set_awaitForIn_int_downward() async {
+ addTestFile('''
+void f() async {
+ var b = <int>{await for (int e in a()) e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+ }
+
+ @failingTest
+ test_set_for_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>{for (int i = 0; a(); i++) i};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_set_forIn_dynamic_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>{for (var e in a()) e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+ }
+
+ @failingTest
+ test_set_forIn_int_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>{for (int e in a()) e};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+}
+
+@reflectiveTest
+class IfElementWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_list_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>[if (a()) 1];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_map_downward() async {
+ addTestFile('''
+void f() {
+ var b = <String, int>{if (a()) 'a' : 1};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_set_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>{if (a()) 1};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+}
+
+@reflectiveTest
+class SpreadElementWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_list_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>[...a()];
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+
+ @failingTest
+ test_map_downward() async {
+ addTestFile('''
+void f() {
+ var b = <String, int>{...a()};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Map<String, int> Function()');
+ }
+
+ @failingTest
+ test_set_downward() async {
+ addTestFile('''
+void f() {
+ var b = <int>{...a()};
+ print(b);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
new file mode 100644
index 0000000..72ebc03
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/conditional_expression_test.dart
@@ -0,0 +1,54 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConditionalExpressionTest);
+ defineReflectiveTests(ConditionalExpressionWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class ConditionalExpressionTest extends DriverResolutionTest {
+ test_upward() async {
+ addTestFile('''
+void f(bool a, int b, int c) {
+ var d = a ? b : c;
+ print(d);
+}
+''');
+ await resolveTestFile();
+ assertType(findNode.simple('d)'), 'int');
+ }
+}
+
+@reflectiveTest
+class ConditionalExpressionWithNnbdTest extends ConditionalExpressionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f(int b, int c) {
+ var d = a() ? b : c;
+ print(d);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('d)'), 'bool Function()');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
index 7f26d21..bf31077 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/logical_boolean_expressions_test.dart
@@ -19,7 +19,7 @@
@reflectiveTest
class LogicalAndTest extends DriverResolutionTest {
- test_simple() async {
+ test_upward() async {
addTestFile('''
void f(bool a, bool b) {
var c = a && b;
@@ -40,11 +40,26 @@
@override
bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f(b) {
+ var c = a() && b();
+ print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+ }
}
@reflectiveTest
class LogicalOrTest extends DriverResolutionTest {
- test_simple() async {
+ test_upward() async {
addTestFile('''
void f(bool a, bool b) {
var c = a || b;
@@ -65,4 +80,19 @@
@override
bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f(b) {
+ var c = a() || b();
+ print(c);
+}
+T a<T>() => throw '';
+T b<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ assertInvokeType(findNode.methodInvocation('b('), 'bool Function()');
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
index 2f8bf00..60335c4 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/prefix_expressions_test.dart
@@ -17,7 +17,7 @@
@reflectiveTest
class NotTest extends DriverResolutionTest {
- test_simple() async {
+ test_upward() async {
addTestFile('''
void f(bool a) {
var b = !a;
@@ -38,4 +38,17 @@
@override
bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f(b) {
+ var c = !a();
+ print(c);
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
new file mode 100644
index 0000000..6137756
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/statements_test.dart
@@ -0,0 +1,185 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(AssertWithNnbdTest);
+ defineReflectiveTests(DoWithNnbdTest);
+ defineReflectiveTests(ForWithNnbdTest);
+ defineReflectiveTests(IfWithNnbdTest);
+ defineReflectiveTests(WhileWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class AssertWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f() {
+ assert(a());
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+}
+
+@reflectiveTest
+class DoWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f() {
+ do {} while(a())
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+}
+
+@reflectiveTest
+class ForWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_awaitForIn_dynamic_downward() async {
+ addTestFile('''
+void f() async {
+ await for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Stream<dynamic> Function()');
+ }
+
+ @failingTest
+ test_awaitForIn_int_downward() async {
+ addTestFile('''
+void f() async {
+ await for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'Stream<int> Function()');
+ }
+
+ @failingTest
+ test_for_downward() async {
+ addTestFile('''
+void f() {
+ for (int i = 0; a(); i++) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+
+ @failingTest
+ test_forIn_dynamic_downward() async {
+ addTestFile('''
+void f() {
+ for (var e in a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<dynamic> Function()');
+ }
+
+ @failingTest
+ test_forIn_int_downward() async {
+ addTestFile('''
+void f() {
+ for (int e in a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(
+ findNode.methodInvocation('a('), 'Iterable<int> Function()');
+ }
+}
+
+@reflectiveTest
+class IfWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f() {
+ if (a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+}
+
+@reflectiveTest
+class WhileWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f() {
+ while (a()) {}
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'bool Function()');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
index 8d7aae0..0369a65 100644
--- a/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/test_all.dart
@@ -4,22 +4,30 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'collection_elements_test.dart' as collection_elements;
+import 'conditional_expression_test.dart' as conditional_expression;
import 'equality_expressions_test.dart' as equality_expressions;
import 'list_literal_test.dart' as list_literal;
import 'logical_boolean_expressions_test.dart' as logical_boolean_expressions;
import 'map_literal_test.dart' as map_literal;
import 'prefix_expressions_test.dart' as prefix_expressions;
import 'set_literal_test.dart' as set_literal;
+import 'statements_test.dart' as statements;
+import 'throw_test.dart' as throw_expression;
import 'type_test_expressions_test.dart' as type_test_expressions;
main() {
defineReflectiveSuite(() {
+ collection_elements.main();
+ conditional_expression.main();
equality_expressions.main();
list_literal.main();
logical_boolean_expressions.main();
map_literal.main();
prefix_expressions.main();
set_literal.main();
+ statements.main();
+ throw_expression.main();
type_test_expressions.main();
}, name: 'type inference');
}
diff --git a/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
new file mode 100644
index 0000000..8cdfe3a
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/type_inference/throw_test.dart
@@ -0,0 +1,38 @@
+// 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ThrowWithNnbdTest);
+ });
+}
+
+@reflectiveTest
+class ThrowWithNnbdTest extends DriverResolutionTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..contextFeatures = new FeatureSet.forTesting(
+ sdkVersion: '2.3.0', additionalFeatures: [Feature.non_nullable]);
+
+ @override
+ bool get typeToStringWithNullability => true;
+
+ @failingTest
+ test_downward() async {
+ addTestFile('''
+void f() {
+ throw a();
+}
+T a<T>() => throw '';
+''');
+ await resolveTestFile();
+ assertInvokeType(findNode.methodInvocation('a('), 'dynamic Function()');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 28b285e..06192b0 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -2,7 +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/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
@@ -10,6 +12,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ArgumentTypeNotAssignableTest);
+ defineReflectiveTests(ArgumentTypeNotAssignableTest_NNBD);
});
}
@@ -41,3 +44,45 @@
]);
}
}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableTest_NNBD extends ArgumentTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions =>
+ AnalysisOptionsImpl()..enabledExperiments = [EnableString.non_nullable];
+
+ test_downcast() async {
+ await assertErrorsInCode(r'''
+m() {
+ num y = 1;
+ n(y);
+}
+n(int x) {}
+''', [
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 23, 1),
+ ]);
+ }
+
+ @failingTest
+ test_downcast_nullableNonNullable() async {
+ await assertErrorsInCode(r'''
+m() {
+ int? y;
+ n(y);
+}
+n(int x) {}
+''', [
+ error(StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 24, 1),
+ ]);
+ }
+
+ test_dynamicCast() async {
+ await assertNoErrorsInCode(r'''
+m() {
+ dynamic i;
+ n(i);
+}
+n(int i) {}
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
index 28ab163..f773a8c 100644
--- a/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/async_keyword_used_as_identifier_test.dart
@@ -16,278 +16,6 @@
@reflectiveTest
class AsyncKeywordUsedAsIdentifierTest extends DriverResolutionTest {
- test_async_annotation() async {
- await assertErrorsInCode('''
-const int async = 0;
-f() async {
- g(@async x) {}
- g(0);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
- ]);
- }
-
- test_async_argumentLabel() async {
- await assertErrorsInCode('''
-f(c) async {
- c.g(async: 0);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
- ]);
- }
-
- test_async_async() async {
- await assertErrorsInCode('''
-f() async {
- var async = 1;
- print(async);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
- ]);
- }
-
- test_async_asyncStar() async {
- await assertErrorsInCode('''
-f() async* {
- var async = 1;
- print(async);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 19, 5),
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
- ]);
- }
-
- test_async_break() async {
- await assertErrorsInCode('''
-f() async {
- while (true) {
- break async;
- }
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 39, 5),
- error(CompileTimeErrorCode.LABEL_UNDEFINED, 39, 5),
- ]);
- }
-
- test_async_catchException() async {
- await assertErrorsInCode('''
-g() {}
-f() async {
- try {
- g();
- } catch (async) { }
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 47, 5),
- ]);
- }
-
- test_async_catchStacktrace() async {
- await assertErrorsInCode('''
-g() {}
-f() async {
- try {
- g();
- } catch (e, async) { }
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 50, 5),
- error(HintCode.UNUSED_CATCH_STACK, 50, 5),
- ]);
- }
-
- test_async_continue() async {
- await assertErrorsInCode('''
-f() async {
- while (true) {
- continue async;
- }
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 42, 5),
- error(CompileTimeErrorCode.LABEL_UNDEFINED, 42, 5),
- ]);
- }
-
- test_async_for() async {
- await assertErrorsInCode('''
-var async;
-f() async {
- for (async in []) {}
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 30, 5),
- ]);
- }
-
- test_async_formalParameter() async {
- await assertErrorsInCode('''
-f() async {
- g(int async) {}
- g(0);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 20, 5),
- ]);
- }
-
- test_async_getter() async {
- await assertErrorsInCode('''
-class C {
- int get async => 1;
-}
-f() async {
- return new C().async;
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 63, 5),
- ]);
- }
-
- test_async_invocation() async {
- await assertErrorsInCode('''
-class C {
- int async() => 1;
-}
-f() async {
- return new C().async();
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
- ]);
- }
-
- test_async_invocation_cascaded() async {
- await assertErrorsInCode('''
-class C {
- int async() => 1;
-}
-f() async {
- return new C()..async();
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 62, 5),
- ]);
- }
-
- test_async_label() async {
- await assertErrorsInCode('''
-f() async {
- async: g();
-}
-g() {}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 14, 5),
- error(HintCode.UNUSED_LABEL, 14, 6),
- ]);
- }
-
- test_async_localFunction() async {
- await assertErrorsInCode('''
-f() async {
- int async() => null;
- async();
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
- ]);
- }
-
- test_async_prefix() async {
- await assertErrorsInCode('''
-import 'dart:async' as async;
-f() async {
- return new async.Future.value(0);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 55, 5),
- ]);
- }
-
- test_async_setter() async {
- await assertErrorsInCode('''
-class C {
- void set async(int i) {}
-}
-f() async {
- new C().async = 1;
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 61, 5),
- ]);
- }
-
- test_async_setter_cascaded() async {
- await assertErrorsInCode('''
-class C {
- void set async(int i) {}
-}
-f() async {
- return new C()..async = 1;
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 69, 5),
- ]);
- }
-
- test_async_stringInterpolation() async {
- await assertErrorsInCode(r'''
-int async = 1;
-f() async {
- return "$async";
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 38, 5),
- ]);
- }
-
- test_async_suffix() async {
- newFile("/test/lib/lib1.dart", content: r'''
-library lib1;
-int async;
-''');
- await assertErrorsInCode('''
-import 'lib1.dart' as l;
-f() async {
- return l.async;
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 48, 5),
- ]);
- }
-
- test_async_switchLabel() async {
- await assertErrorsInCode('''
-f() async {
- switch (0) {
- async: case 0: break;
- }
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 31, 5),
- error(HintCode.UNUSED_LABEL, 31, 6),
- ]);
- }
-
- test_async_syncStar() async {
- await assertErrorsInCode('''
-f() sync* {
- var async = 1;
- print(async);
-}
-''', [
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 18, 5),
- error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 37, 5),
- ]);
- }
-
test_await_async() async {
await assertErrorsInCode('''
f() async {
diff --git a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
index 1769170..30e9267 100644
--- a/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -36,10 +36,7 @@
''');
}
- @failingTest
test_inferredType() async {
- // This test is failing because summary support is incomplete, which results
- // in the constructor having a type of 'List<C*>*'.
await assertErrorsInCode('''
class C {}
List<C> v = List(5);
@@ -48,16 +45,6 @@
]);
}
- test_starType() async {
- // TODO(brianwilkerson) This test is currently taking advantage of the fact
- // that the SDK is not opted in, which makes the use of `int` below a
- // reference to 'int*'. When it's possible to opt-out in a test this needs
- // to be updated to use an explicitly opted out type.
- await assertNoErrorsInCode('''
-List<int> v = List(5);
-''');
- }
-
test_typeParameter() async {
await assertErrorsInCode('''
class C<T> {
diff --git a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
index cee830f..3a1725e 100644
--- a/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_entry_not_in_map_test.dart
@@ -16,14 +16,18 @@
@reflectiveTest
class MapEntryNotInMapTest extends DriverResolutionTest {
test_set() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var c = <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+''', [
+ error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 14, 3),
+ ]);
}
test_set_const() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var c = const <int>{1:2};
-''', [CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP]);
+''', [
+ error(CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP, 20, 3),
+ ]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index 9fea9f5..949841c 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -19,7 +19,7 @@
@reflectiveTest
class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
const dynamic b = 0;
@@ -27,76 +27,96 @@
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+ ]);
}
test_const_ifElement_thenElseFalse_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
const dynamic b = 'b';
var v = const <int, bool>{if (1 < 0) a: true else b: false};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 94, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+ ]);
}
test_const_ifElement_thenFalse_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <int, bool>{if (1 < 0) a: true};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+ ]);
}
test_const_ifElement_thenFalse_intString_value() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
var v = const <int, bool>{if (1 < 0) 'a': true};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
+ ? [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
+ ]
: [
- StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
- CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 37, 3),
]);
}
test_const_ifElement_thenTrue_intInt_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
var v = const <int, bool>{if (true) a: true};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+ ]);
}
test_const_ifElement_thenTrue_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <int, bool>{if (true) a: true};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 59, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+ ]);
}
test_const_ifElement_thenTrue_notConst() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
final a = 0;
var v = const <int, bool>{if (1 < 2) a: true};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 50, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+ ]);
}
test_const_intInt_dynamic() async {
@@ -107,39 +127,47 @@
}
test_const_intString_dynamic() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const dynamic a = 'a';
var v = const <int, bool>{a : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 49, 1),
+ ]);
}
test_const_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+ ]);
}
test_const_spread_intInt() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
var v = const <int, String>{...{1: 'a'}};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 28, 11),
+ ]);
}
test_const_spread_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <int, String>{...{a: 'a'}};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]
+ ? [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
+ ]
: [
- StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
- CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 51, 11),
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 55, 1),
]);
}
@@ -160,9 +188,11 @@
}
test_nonConst_ifElement_thenFalse_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <int, bool>{if (1 < 0) 'a': true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 31, 3),
+ ]);
}
test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -194,9 +224,11 @@
}
test_nonConst_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <int, bool>{'a' : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 20, 3),
+ ]);
}
test_nonConst_spread_intInt() async {
@@ -212,9 +244,11 @@
}
test_nonConst_spread_intString() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <int, String>{...{'a': 'a'}};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 3),
+ ]);
}
test_nonConst_spread_intString_dynamic() async {
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index 30e7865..86a5746 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -2,7 +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/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../dart/resolution/driver_resolution.dart';
@@ -10,13 +12,14 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MapValueTypeNotAssignableTest);
+ defineReflectiveTests(MapValueTypeNotAssignableWithConstantsTest);
});
}
@reflectiveTest
class MapValueTypeNotAssignableTest extends DriverResolutionTest {
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
const dynamic b = 0;
@@ -24,76 +27,96 @@
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 68, 32),
+ ]);
}
test_const_ifElement_thenElseFalse_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
const dynamic b = 'b';
var v = const <bool, int>{if (1 < 0) true: a else false: b};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 101, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 70, 32),
+ ]);
}
test_const_ifElement_thenFalse_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <bool, int>{if (1 < 0) true: a};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 18),
+ ]);
}
test_const_ifElement_thenFalse_intString_value() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
var v = const <bool, int>{if (1 < 0) true: 'a'};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
+ ? [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
+ ]
: [
- StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
- CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 20),
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 43, 3),
]);
}
test_const_ifElement_thenTrue_intInt_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 0;
var v = const <bool, int>{if (true) true: a};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 47, 17),
+ ]);
}
test_const_ifElement_thenTrue_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <bool, int>{if (true) true: a};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 65, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 17),
+ ]);
}
test_const_ifElement_thenTrue_notConst() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
final a = 0;
var v = const <bool, int>{if (1 < 2) true: a};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ ? [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 56, 1),
+ ]
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 39, 18),
+ ]);
}
test_const_intInt_dynamic() async {
@@ -104,39 +127,47 @@
}
test_const_intString_dynamic() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
const dynamic a = 'a';
var v = const <bool, int>{true: a};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 55, 1),
+ ]);
}
test_const_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = const <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 32, 3),
+ ]);
}
test_const_spread_intInt() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
var v = const <bool, int>{...{true: 1}};
''',
analysisOptions.experimentStatus.constant_update_2018
? []
- : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
+ : [
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 26, 12),
+ ]);
}
test_const_spread_intString_dynamic() async {
- await assertErrorCodesInCode(
+ await assertErrorsInCode(
'''
const dynamic a = 'a';
var v = const <bool, int>{...{true: a}};
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]
+ ? [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
+ ]
: [
- StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
- CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT
+ error(CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT, 49, 12),
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 59, 1),
]);
}
@@ -157,9 +188,11 @@
}
test_nonConst_ifElement_thenFalse_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <bool, int>{if (1 < 0) true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 37, 3),
+ ]);
}
test_nonConst_ifElement_thenTrue_intInt_dynamic() async {
@@ -191,9 +224,11 @@
}
test_nonConst_intString_value() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <bool, int>{true: 'a'};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 26, 3),
+ ]);
}
test_nonConst_spread_intInt() async {
@@ -209,9 +244,11 @@
}
test_nonConst_spread_intString() async {
- await assertErrorCodesInCode('''
+ await assertErrorsInCode('''
var v = <bool, int>{...{true: 'a'}};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+''', [
+ error(StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 30, 3),
+ ]);
}
test_nonConst_spread_intString_dynamic() async {
@@ -221,3 +258,11 @@
''');
}
}
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithConstantsTest
+ extends MapValueTypeNotAssignableTest {
+ @override
+ AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+ ..enabledExperiments = [EnableString.constant_update_2018];
+}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
index dd0e60d..fa860a6 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_required_param_test.dart
@@ -248,12 +248,12 @@
test_functionInvocation() async {
await assertErrorsInCode(r'''
-void Function({required int a}) f() => null;
+void Function({required int a}) f() => throw '';
g() {
f()();
}
''', [
- error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 53, 5),
+ error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 57, 5),
]);
}
@@ -305,7 +305,7 @@
typedef String F({required String x});
class C {
- F m() => ({required String x}) => null;
+ F m() => ({required String x}) => throw '';
}
''', [
error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 20, 7),
diff --git a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
index 41042fb..56a4de8 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_return_test.dart
@@ -32,10 +32,12 @@
}
test_async() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'dart:async';
Future<int> f() async {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+ error(HintCode.MISSING_RETURN, 21, 11),
+ ]);
}
test_async_futureOrVoid() async {
@@ -66,35 +68,139 @@
}
test_factory() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
factory A() {}
}
-''', [HintCode.MISSING_RETURN]);
+''', [
+ error(HintCode.MISSING_RETURN, 12, 14),
+ ]);
}
test_function() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
int f() {}
-''', [HintCode.MISSING_RETURN]);
+''', [
+ error(HintCode.MISSING_RETURN, 0, 3),
+ ]);
+ }
+
+ test_functionExpression_declared() async {
+ await assertNoErrorsInCode(r'''
+main() {
+ f() {} // no hint
+}
+''');
+ }
+
+ test_functionExpression_expression() async {
+ await assertNoErrorsInCode(r'''
+main() {
+ int Function() f = () => null; // no hint
+}
+''');
+ }
+
+ test_functionExpression_futureOrDynamic() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:async';
+main() {
+ FutureOr<dynamic> Function() f = () { print(42); };
+}
+''');
+ }
+
+ test_functionExpression_futureOrInt() async {
+ await assertErrorsInCode(r'''
+import 'dart:async';
+main() {
+ FutureOr<int> Function() f = () { print(42); };
+}
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 57, 1),
+ error(HintCode.MISSING_RETURN, 61, 17),
+ ]);
+ }
+
+ test_functionExpression_inferred() async {
+ await assertErrorsInCode(r'''
+main() {
+ int Function() f = () { print(42); };
+}
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 26, 1),
+ error(HintCode.MISSING_RETURN, 30, 17),
+ ]);
+ }
+
+ test_functionExpression_inferred_dynamic() async {
+ await assertNoErrorsInCode(r'''
+main() {
+ Function() f = () { print(42); }; // no hint
+}
+''');
+ }
+
+ test_functionExpressionAsync_inferred() async {
+ await assertErrorsInCode(r'''
+main() {
+ Future<int> Function() f = () async { print(42); };
+}
+''', [
+ error(HintCode.UNUSED_LOCAL_VARIABLE, 34, 1),
+ error(HintCode.MISSING_RETURN, 38, 23),
+ ]);
+ }
+
+ test_functionExpressionAsync_inferred_dynamic() async {
+ await assertNoErrorsInCode(r'''
+main() {
+ Future Function() f = () async { print(42); }; // no hint
+}
+''');
}
test_method() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
class A {
int m() {}
-}''', [HintCode.MISSING_RETURN]);
+}
+''', [
+ error(HintCode.MISSING_RETURN, 12, 3),
+ ]);
+ }
+
+ test_method_futureOrDynamic() async {
+ await assertNoErrorsInCode(r'''
+import 'dart:async';
+class A {
+ FutureOr<dynamic> m() {}
+}
+''');
+ }
+
+ test_method_futureOrInt() async {
+ await assertErrorsInCode(r'''
+import 'dart:async';
+class A {
+ FutureOr<int> m() {}
+}
+''', [
+ error(HintCode.MISSING_RETURN, 33, 13),
+ ]);
}
test_method_inferred() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
abstract class A {
int m();
}
class B extends A {
m() {}
}
-''', [HintCode.MISSING_RETURN]);
+''', [
+ error(HintCode.MISSING_RETURN, 54, 6),
+ ]);
}
test_noReturnType() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
index e907d2c..8ada226 100644
--- a/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_be_immutable_test.dart
@@ -22,34 +22,40 @@
}
test_directAnnotation() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@immutable
class A {
int x;
}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+ ]);
}
test_directMixinAnnotation() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@immutable
mixin A {
int x;
}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 50, 1),
+ ]);
}
test_extendsClassWithAnnotation() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@immutable
class A {}
class B extends A {
int x;
}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 61, 1),
+ ]);
}
test_finalField() async {
@@ -64,7 +70,7 @@
}
test_fromMixinWithAnnotation() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@immutable
class A {}
@@ -72,11 +78,13 @@
int x;
}
class C extends A with B {}
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+ ]);
}
test_mixinApplication() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
@immutable
class A {}
@@ -84,11 +92,13 @@
int x;
}
class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+ ]);
}
test_mixinApplicationBase() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
int x;
@@ -96,7 +106,9 @@
class B {}
@immutable
class C = A with B;
-''', [HintCode.MUST_BE_IMMUTABLE]);
+''', [
+ error(HintCode.MUST_BE_IMMUTABLE, 82, 1),
+ ]);
}
test_staticField() async {
diff --git a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 7230ed0..32d9967 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -38,7 +38,7 @@
}
test_fromExtendingClass() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@mustCallSuper
@@ -49,7 +49,9 @@
void a()
{}
}
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+ error(HintCode.MUST_CALL_SUPER, 115, 1),
+ ]);
}
test_fromExtendingClass_abstractImplementation() async {
@@ -81,7 +83,7 @@
}
test_fromMixin() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class Mixin {
@mustCallSuper
@@ -91,11 +93,13 @@
@override
void a() {}
}
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+ error(HintCode.MUST_CALL_SUPER, 120, 1),
+ ]);
}
test_indirectlyInherited() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@mustCallSuper
@@ -111,11 +115,13 @@
@override
void a() {}
}
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+ error(HintCode.MUST_CALL_SUPER, 181, 1),
+ ]);
}
test_indirectlyInheritedFromMixin() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class Mixin {
@mustCallSuper
@@ -126,11 +132,13 @@
@override
void b() {}
}
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+ error(HintCode.MUST_CALL_SUPER, 156, 1),
+ ]);
}
test_indirectlyInheritedFromMixinConstraint() async {
- await assertErrorCodesInCode(r'''
+ await assertErrorsInCode(r'''
import 'package:meta/meta.dart';
class A {
@mustCallSuper
@@ -140,7 +148,9 @@
@override
void a() {}
}
-''', [HintCode.MUST_CALL_SUPER]);
+''', [
+ error(HintCode.MUST_CALL_SUPER, 110, 1),
+ ]);
}
test_overriddenWithFuture() async {
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
index 511316a..b32c756 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -19,15 +19,17 @@
@reflectiveTest
class NonBoolConditionTest extends DriverResolutionTest {
test_ifElement() async {
- assertErrorCodesInCode(
+ assertErrorsInCode(
'''
const c = [if (3) 1];
''',
analysisOptions.experimentStatus.constant_update_2018
- ? [StaticTypeWarningCode.NON_BOOL_CONDITION]
+ ? [
+ error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
+ ]
: [
- StaticTypeWarningCode.NON_BOOL_CONDITION,
- CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT
+ error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 11, 8),
+ error(StaticTypeWarningCode.NON_BOOL_CONDITION, 15, 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
index b63e481..2dc0373 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_as_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
..enabledExperiments = [EnableString.constant_update_2018];
test_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const dynamic a = 2;
const c = (a as int) + 2;
''');
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
index 1b16612..29f4773 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_bool_operator_test.dart
@@ -22,7 +22,7 @@
..enabledExperiments = [EnableString.constant_update_2018];
test_and_const_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const c = true & false;
''');
}
@@ -46,7 +46,7 @@
}
test_or_const_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const c = true | false;
''');
}
@@ -70,7 +70,7 @@
}
test_xor_const_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const c = true ^ false;
''');
}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
index 3d6b6ca..f8093af 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_eq_eq_operator_test.dart
@@ -22,7 +22,7 @@
..enabledExperiments = [EnableString.constant_update_2018];
test_left_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
class A {
const A();
}
@@ -42,7 +42,7 @@
}
test_right_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
class A {
const A();
}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
index 5e5f140..38d71f0 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_gt_gt_gt_operator_test.dart
@@ -24,7 +24,7 @@
test_const_equals() {
// TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
// UNDEFINED_OPERATOR when triple_shift is enabled by default.
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const a = 42 >>> 3;
''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
}
@@ -41,7 +41,7 @@
}
test_declaration_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
class A {
A operator >>>(A a) => this;
}
@@ -59,7 +59,7 @@
test_nonConst_equals() {
// TODO(brianwilkerson) Add '>>>' to MockSdk and remove the code
// UNDEFINED_OPERATOR when constant update is enabled by default.
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
var a = 42 >>> 3;
''', errorCodes: [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
index 70778cf..9b19e3c 100644
--- a/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/sdk_version_is_expression_in_const_context_test.dart
@@ -23,7 +23,7 @@
..enabledExperiments = [EnableString.constant_update_2018];
test_equals() {
- verifyVersion('2.2.2', '''
+ verifyVersion('2.3.2', '''
const dynamic a = 2;
const c = a is int;
''');
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index fff3f23..bf27038 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -165,6 +165,8 @@
import 'unused_shown_name_test.dart' as unused_shown_name;
import 'use_of_void_result_test.dart' as use_of_void_result;
import 'variable_type_mismatch_test.dart' as variable_type_mismatch;
+import 'wrong_type_parameter_variance_in_superinterface_test.dart'
+ as wrong_type_parameter_variance_in_superinterface;
main() {
defineReflectiveSuite(() {
@@ -287,5 +289,6 @@
unused_shown_name.main();
use_of_void_result.main();
variable_type_mismatch.main();
+ wrong_type_parameter_variance_in_superinterface.main();
}, name: 'diagnostics');
}
diff --git a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
index d008f0a..08ffb33 100644
--- a/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -48,6 +48,24 @@
''');
}
+ test_assert_nonNullable() async {
+ await assertNoErrorsInCode(r'''
+m() {
+ bool x = true;
+ assert(x);
+}
+''');
+ }
+
+ test_assert_nullable() async {
+ await assertErrorCodesInCode(r'''
+m() {
+ bool? x;
+ assert(x);
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+ }
+
test_await_nonNullable() async {
await assertNoErrorsInCode(r'''
m() async {
@@ -201,6 +219,15 @@
''');
}
+ test_member_dynamic_nullable() async {
+ await assertNoErrorsInCode(r'''
+m() {
+ dynamic x;
+ x.foo;
+}
+''');
+ }
+
test_member_hashCode_nullable() async {
await assertNoErrorsInCode(r'''
m() {
@@ -255,6 +282,24 @@
''');
}
+ test_member_potentiallyNullable() async {
+ await assertErrorCodesInCode(r'''
+m<T extends int?>() {
+ T x;
+ x.isEven;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+ }
+
+ test_member_potentiallyNullable_called() async {
+ await assertErrorCodesInCode(r'''
+m<T extends Function>() {
+ List<T?> x;
+ x.first();
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+ }
+
test_member_questionDot_nullable() async {
await assertNoErrorsInCode(r'''
m() {
@@ -286,7 +331,7 @@
await assertNoErrorsInCode(r'''
m() {
int x;
- x.noSuchMethod(null);
+ x.noSuchMethod(throw '');
}
''');
}
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
new file mode 100644
index 0000000..5815369
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/wrong_type_parameter_variance_in_superinterface_test.dart
@@ -0,0 +1,334 @@
+// 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:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(WrongTypeParameterVarianceInSuperinterfaceTest);
+ });
+}
+
+@reflectiveTest
+class WrongTypeParameterVarianceInSuperinterfaceTest
+ extends DriverResolutionTest {
+ test_class_extends_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_class_extends_function_parameterType_parameterType() async {
+ await assertNoErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''');
+ }
+
+ test_class_extends_function_parameterType_returnType() async {
+ await assertErrorsInCode(r'''
+typedef F1<X> = X Function();
+typedef F2<X> = void Function(F1<X>);
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 90,
+ 1,
+ ),
+ ]);
+ }
+
+ test_class_extends_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends A<F<X>> {}
+''');
+ }
+
+ test_class_extends_function_returnType_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F1<X> = void Function(X);
+typedef F2<X> = F1<X> Function();
+class A<X> {}
+class B<X> extends A<F2<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 90,
+ 1,
+ ),
+ ]);
+ }
+
+ test_class_extends_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<X> {}
+''');
+ }
+
+ test_class_implements_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_class_implements_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> implements A<F<X>> {}
+''');
+ }
+
+ test_class_implements_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> implements A<X> {}
+''');
+ }
+
+ test_class_with_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_class_with_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+class B<X> extends Object with A<F<X>> {}
+''');
+ }
+
+ test_class_with_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+class B<X> extends Object with A<X> {}
+''');
+ }
+
+ test_classTypeAlias_extends_function_invariant() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = X Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 63,
+ 1,
+ ),
+ ]);
+ }
+
+ test_classTypeAlias_extends_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 66,
+ 1,
+ ),
+ ]);
+ }
+
+ test_classTypeAlias_extends_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = A<F<X>> with M;
+''');
+ }
+
+ test_classTypeAlias_extends_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = A<X> with M;
+''');
+ }
+
+ test_classTypeAlias_implements_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 66,
+ 1,
+ ),
+ ]);
+ }
+
+ test_classTypeAlias_implements_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<F<X>>;
+''');
+ }
+
+ test_classTypeAlias_implements_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin M {}
+class B<X> = Object with M implements A<X>;
+''');
+ }
+
+ test_classTypeAlias_with_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_classTypeAlias_with_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+mixin M<X> {}
+class B<X> = Object with M<F<X>>;
+''');
+ }
+
+ test_classTypeAlias_with_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+mixin M<X> {}
+class B<X> = Object with M<X>;
+''');
+ }
+
+ test_mixin_implements_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_mixin_implements_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> implements A<F<X>> {}
+''');
+ }
+
+ test_mixin_implements_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> implements A<X> {}
+''');
+ }
+
+ test_mixin_on_function_parameterType() async {
+ await assertErrorsInCode(r'''
+typedef F<X> = void Function(X);
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 55,
+ 1,
+ ),
+ ]);
+ }
+
+ test_mixin_on_function_returnType() async {
+ await assertNoErrorsInCode(r'''
+typedef F<X> = X Function();
+class A<X> {}
+mixin B<X> on A<F<X>> {}
+''');
+ }
+
+ test_mixin_on_withoutFunction() async {
+ await assertNoErrorsInCode(r'''
+class A<X> {}
+mixin B<X> on A<X> {}
+''');
+ }
+
+ test_typeParameter_bound() async {
+ try {
+ await assertErrorsInCode(r'''
+class A<X> {}
+class B<X> extends A<void Function<Y extends X>()> {}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_TYPE_PARAMETER_VARIANCE_IN_SUPERINTERFACE,
+ 22,
+ 1,
+ ),
+ ]);
+ } catch (_) {
+ // TODO(scheglov) This code crashes with summary1.
+// NoSuchMethodError: The getter 'bound' was called on null.
+// Receiver: null
+// Tried calling: bound
+// #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
+// #1 ErrorVerifier._checkForTypeParameterSupertypeOfItsBound (error_verifier.dart:5438:30)
+ if (AnalysisDriver.useSummary2) rethrow;
+ }
+ }
+}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
index f8a05c4..914e1f6 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/switch_statement_test.dart
@@ -22,7 +22,7 @@
'switch',
[
ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ParserErrorCode.EXPECTED_TOKEN
],
"switch (_s_) {}",
@@ -32,7 +32,7 @@
'switch (',
[
ParserErrorCode.MISSING_IDENTIFIER,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"switch (_s_) {}",
@@ -47,11 +47,11 @@
new TestDescriptor(
'expression',
'switch (a',
- [ParserErrorCode.EXPECTED_TOKEN, ScannerErrorCode.EXPECTED_TOKEN],
+ [ParserErrorCode.EXPECTED_BODY, ScannerErrorCode.EXPECTED_TOKEN],
"switch (a) {}",
failing: ['block']),
new TestDescriptor('rightParen', 'switch (a)',
- [ParserErrorCode.EXPECTED_TOKEN], "switch (a) {}",
+ [ParserErrorCode.EXPECTED_BODY], "switch (a) {}",
failing: ['block']),
new TestDescriptor('leftBrace', 'switch (a) {',
[ScannerErrorCode.EXPECTED_TOKEN], "switch (a) {}",
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
index ca80f4c..1e2f8a5 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/try_statement_test.dart
@@ -22,7 +22,7 @@
'keyword',
'try',
[
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ParserErrorCode.MISSING_CATCH_OR_FINALLY
],
"try {} finally {}",
@@ -38,7 +38,7 @@
'try {} on',
[
ParserErrorCode.EXPECTED_TYPE_NAME,
- ParserErrorCode.EXPECTED_TOKEN
+ ParserErrorCode.EXPECTED_BODY
],
"try {} on _s_ {}",
failing: [
@@ -48,7 +48,7 @@
'localFunctionVoid'
]),
new TestDescriptor('on_identifier', 'try {} on A',
- [ParserErrorCode.EXPECTED_TOKEN], "try {} on A {}",
+ [ParserErrorCode.EXPECTED_BODY], "try {} on A {}",
failing: ['block']),
//
// Single catch clause.
@@ -56,7 +56,7 @@
new TestDescriptor(
'catch',
'try {} catch',
- [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+ [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
"try {} catch (e) {}",
failing: ['block']),
new TestDescriptor(
@@ -65,7 +65,7 @@
[
ScannerErrorCode.EXPECTED_TOKEN,
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN
+ ParserErrorCode.EXPECTED_BODY
],
"try {} catch (e) {}",
failing: ['block', 'labeled', 'localFunctionNonVoid']),
@@ -74,7 +74,7 @@
'try {} catch (e',
[
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} catch (e) {}",
@@ -84,7 +84,7 @@
'try {} catch (e, ',
[
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} catch (e, _s_) {}",
@@ -96,13 +96,13 @@
// TODO(danrubel): Update parser to generate CATCH_SYNTAX
// because in this situation there are not any extra parameters.
ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} catch (e, s) {}",
failing: ['eof', 'block']),
new TestDescriptor('catch_rightParen', 'try {} catch (e, s)',
- [ParserErrorCode.EXPECTED_TOKEN], "try {} catch (e, s) {}",
+ [ParserErrorCode.EXPECTED_BODY], "try {} catch (e, s) {}",
failing: ['block']),
//
// Single catch clause after an on clause.
@@ -110,7 +110,7 @@
new TestDescriptor(
'on_catch',
'try {} on A catch',
- [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_TOKEN],
+ [ParserErrorCode.CATCH_SYNTAX, ParserErrorCode.EXPECTED_BODY],
"try {} on A catch (e) {}",
failing: ['block']),
new TestDescriptor(
@@ -118,7 +118,7 @@
'try {} on A catch (',
[
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} on A catch (e) {}",
@@ -128,7 +128,7 @@
'try {} on A catch (e',
[
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} on A catch (e) {}",
@@ -138,7 +138,7 @@
'try {} on A catch (e, ',
[
ParserErrorCode.CATCH_SYNTAX,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} on A catch (e, _s_) {}",
@@ -150,19 +150,19 @@
// TODO(danrubel): Update parser to generate CATCH_SYNTAX
// because in this situation there are not any extra parameters.
ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.EXPECTED_BODY,
ScannerErrorCode.EXPECTED_TOKEN
],
"try {} on A catch (e, s) {}",
failing: ['eof', 'block']),
new TestDescriptor('on_catch_rightParen', 'try {} on A catch (e, s)',
- [ParserErrorCode.EXPECTED_TOKEN], "try {} on A catch (e, s) {}",
+ [ParserErrorCode.EXPECTED_BODY], "try {} on A catch (e, s) {}",
failing: ['block']),
//
// Only a finally clause.
//
new TestDescriptor('finally_noCatch_noBlock', 'try {} finally',
- [ParserErrorCode.EXPECTED_TOKEN], "try {} finally {}",
+ [ParserErrorCode.EXPECTED_BODY], "try {} finally {}",
failing: ['block']),
//
// A catch and finally clause.
@@ -170,7 +170,7 @@
new TestDescriptor(
'finally_catch_noBlock',
'try {} catch (e) {} finally',
- [ParserErrorCode.EXPECTED_TOKEN],
+ [ParserErrorCode.EXPECTED_BODY],
"try {} catch (e) {} finally {}",
failing: ['block']),
],
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 6834f37..38bd97b 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -226,6 +226,51 @@
@reflectiveTest
class ChangeFileTest extends _Base {
+ disabled_test_updated_library_parted() async {
+ // TODO(scheglov) Figure out why this fails on Windows.
+ var a = convertPath('/home/test/lib/a.dart');
+ var b = convertPath('/home/test/lib/b.dart');
+
+ newFile(a, content: r'''
+class A {}
+''');
+ newFile(b, content: r'''
+part 'a.dart';
+class B {}
+''');
+ tracker.addContext(testAnalysisContext);
+
+ await _doAllTrackerWork();
+ _assertHasNoLibrary('package:test/a.dart');
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration.class_('A', [
+ _ExpectedDeclaration.constructor(''),
+ ]),
+ _ExpectedDeclaration.class_('B', [
+ _ExpectedDeclaration.constructor(''),
+ ]),
+ ]);
+
+ newFile(a, content: r'''
+class A2 {}
+''');
+ tracker.changeFile(a);
+ await _doAllTrackerWork();
+ _assertHasLibrary('package:test/a.dart', declarations: [
+ _ExpectedDeclaration.class_('A2', [
+ _ExpectedDeclaration.constructor(''),
+ ]),
+ ]);
+ _assertHasLibrary('package:test/b.dart', declarations: [
+ _ExpectedDeclaration.class_('A2', [
+ _ExpectedDeclaration.constructor(''),
+ ]),
+ _ExpectedDeclaration.class_('B', [
+ _ExpectedDeclaration.constructor(''),
+ ]),
+ ]);
+ }
+
test_added_exported() async {
var a = convertPath('/home/test/lib/a.dart');
var b = convertPath('/home/test/lib/b.dart');
@@ -855,51 +900,6 @@
]);
}
- disabled_test_updated_library_parted() async {
- // TODO(scheglov) Figure out why this fails on Windows.
- var a = convertPath('/home/test/lib/a.dart');
- var b = convertPath('/home/test/lib/b.dart');
-
- newFile(a, content: r'''
-class A {}
-''');
- newFile(b, content: r'''
-part 'a.dart';
-class B {}
-''');
- tracker.addContext(testAnalysisContext);
-
- await _doAllTrackerWork();
- _assertHasNoLibrary('package:test/a.dart');
- _assertHasLibrary('package:test/b.dart', declarations: [
- _ExpectedDeclaration.class_('A', [
- _ExpectedDeclaration.constructor(''),
- ]),
- _ExpectedDeclaration.class_('B', [
- _ExpectedDeclaration.constructor(''),
- ]),
- ]);
-
- newFile(a, content: r'''
-class A2 {}
-''');
- tracker.changeFile(a);
- await _doAllTrackerWork();
- _assertHasLibrary('package:test/a.dart', declarations: [
- _ExpectedDeclaration.class_('A2', [
- _ExpectedDeclaration.constructor(''),
- ]),
- ]);
- _assertHasLibrary('package:test/b.dart', declarations: [
- _ExpectedDeclaration.class_('A2', [
- _ExpectedDeclaration.constructor(''),
- ]),
- _ExpectedDeclaration.class_('B', [
- _ExpectedDeclaration.constructor(''),
- ]),
- ]);
- }
-
test_updated_library_to_part() async {
var a = convertPath('/home/test/lib/a.dart');
@@ -1607,6 +1607,101 @@
_assertNoDeclaration(library, 'A');
}
+ test_FUNCTION_TYPE_ALIAS_old() async {
+ newFile('/home/test/lib/test.dart', content: r'''
+typedef void A();
+
+@deprecated
+typedef void B();
+
+/// aaa
+///
+/// bbb bbb
+typedef void C();
+
+typedef int D(int p1, [double p2, String p3]);
+
+typedef void E(int p1, double p2, {String p3});
+
+typedef void F<T extends num, U>();
+''');
+
+ tracker.addContext(testAnalysisContext);
+ await _doAllTrackerWork();
+
+ var library = _getLibrary('package:test/test.dart');
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'A'),
+ 'A',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ parameters: '()',
+ parameterNames: [],
+ parameterTypes: [],
+ relevanceTags: ['package:test/test.dart::A'],
+ requiredParameterCount: 0,
+ returnType: 'void',
+ );
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'B'),
+ 'B',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ isDeprecated: true,
+ parameters: '()',
+ parameterNames: [],
+ parameterTypes: [],
+ relevanceTags: ['package:test/test.dart::B'],
+ requiredParameterCount: 0,
+ returnType: 'void',
+ );
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'C'),
+ 'C',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ docSummary: 'aaa',
+ docComplete: 'aaa\n\nbbb bbb',
+ parameters: '()',
+ parameterNames: [],
+ parameterTypes: [],
+ relevanceTags: ['package:test/test.dart::C'],
+ requiredParameterCount: 0,
+ returnType: 'void',
+ );
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'D'),
+ 'D',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ parameters: '(int p1, [double p2, String p3])',
+ parameterNames: ['p1', 'p2', 'p3'],
+ parameterTypes: ['int', 'double', 'String'],
+ relevanceTags: ['package:test/test.dart::D'],
+ requiredParameterCount: 1,
+ returnType: 'int',
+ );
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'E'),
+ 'E',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ parameters: '(int p1, double p2, {String p3})',
+ parameterNames: ['p1', 'p2', 'p3'],
+ parameterTypes: ['int', 'double', 'String'],
+ relevanceTags: ['package:test/test.dart::E'],
+ requiredParameterCount: 2,
+ returnType: 'void',
+ );
+ _assertDeclaration(
+ _getDeclaration(library.declarations, 'F'),
+ 'F',
+ DeclarationKind.FUNCTION_TYPE_ALIAS,
+ parameters: '()',
+ parameterNames: [],
+ parameterTypes: [],
+ requiredParameterCount: 0,
+ relevanceTags: ['package:test/test.dart::F'],
+ returnType: 'void',
+ typeParameters: '<T extends num, U>',
+ );
+ }
+
test_GETTER() async {
newFile('/home/test/lib/test.dart', content: r'''
int get a => 0;
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 0e738780..3a24bb1 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -225,7 +225,7 @@
ClassElementForLink_Class B = library.getContainedName('B');
expect(B.fields, hasLength(1));
FieldElementForLink f = B.fields[0];
- expect(f.type.toString(), '(num) → int');
+ expect(f.type.toString(), 'int Function(num)');
}
void test_getContainedName_nonStaticField() {
@@ -267,7 +267,7 @@
''');
LibraryElementForLink library = linker.getLibrary(testDartUri);
expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
- '() → Null');
+ 'Null Function()');
}
void test_inferredType_closure_fromBundle_identifierSequence() {
@@ -287,7 +287,7 @@
''');
LibraryElementForLink library = linker.getLibrary(testDartUri);
expect(_getVariable(library.getContainedName('y')).inferredType.toString(),
- '(D) → E');
+ 'E Function(D)');
}
void test_inferredType_implicitFunctionTypeIndices() {
@@ -327,7 +327,7 @@
ClassElementForLink_Class cls = library.getContainedName('C');
expect(cls.fields, hasLength(1));
var field = cls.fields[0];
- expect(field.type.toString(), '(Never) → int');
+ expect(field.type.toString(), 'int Function(Never)');
}
void test_inferredType_instanceField_dynamic() {
@@ -379,7 +379,7 @@
var method = cls.methods[0];
expect(method.parameters, hasLength(1));
var pType = method.parameters[0].type;
- expect(pType.toString(), '<T,U>(T, U) → Map<T, List<U>>');
+ expect(pType.toString(), 'Map<T, List<U>> Function<T,U>(T, U)');
}
void test_inferredType_methodReturnType_dynamic() {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 041f812..800bdd1 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -51,11 +51,6 @@
);
}
- var rootReference = Reference.root();
- var dartCoreRef = rootReference.getChild('dart:core');
- dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
- dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-
var elementFactory = LinkedElementFactory(
RestrictedAnalysisContext(
SynchronousSession(
@@ -65,7 +60,7 @@
sourceFactory,
),
_AnalysisSessionForLinking(),
- rootReference,
+ Reference.root(),
);
var sdkLinkResult = link(elementFactory, inputLibraries);
@@ -90,16 +85,10 @@
sourceFactory,
);
- var rootReference = Reference.root();
- rootReference.getChild('dart:core').getChild('dynamic').element =
- DynamicElementImpl.instance;
- rootReference.getChild('dart:core').getChild('Never').element =
- NeverElementImpl.instance;
-
var elementFactory = LinkedElementFactory(
analysisContext,
_AnalysisSessionForLinking(),
- rootReference,
+ Reference.root(),
);
elementFactory.addBundle(
LinkedBundleContext(elementFactory, sdkBundle),
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index b602cc7..b67a6f2 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1202,6 +1202,22 @@
''');
}
+ test_class_method_namedAsSupertype() async {
+ var library = await checkLibrary(r'''
+class A {}
+class B extends A {
+ void A() {}
+}
+''');
+ checkElementText(library, r'''
+class A {
+}
+class B extends A {
+ void A() {}
+}
+''');
+ }
+
test_class_method_params() async {
var library = await checkLibrary('class C { f(x, y) {} }');
checkElementText(library, r'''
@@ -2521,6 +2537,66 @@
''');
}
+ test_const_inference_downward_list() async {
+ var library = await checkLibrary('''
+class P<T> {
+ const P();
+}
+
+class P1<T> extends P<T> {
+ const P1();
+}
+
+class P2<T> extends P<T> {
+ const P2();
+}
+
+const List<P> values = [
+ P1(),
+ P2<int>(),
+];
+''');
+ if (isAstBasedSummary) {
+ checkElementText(
+ library,
+ '''
+class P<T> {
+ const P();
+}
+class P1<T> extends P<T> {
+ const P1();
+}
+class P2<T> extends P<T> {
+ const P2();
+}
+const List<P<dynamic>> values = /*typeArgs=P<dynamic>*/[/*typeArgs=dynamic*/
+ P1/*location: test.dart;P1*/(),
+ P2/*location: test.dart;P2*/<
+ int/*location: dart:core;int*/>()];
+''',
+ withTypes: true);
+ } else {
+ checkElementText(
+ library,
+ '''
+class P<T> {
+ const P();
+}
+class P1<T> extends P<T> {
+ const P1();
+}
+class P2<T> extends P<T> {
+ const P2();
+}
+const List<P<dynamic>> values = const /*typeArgs=dynamic*/[const /*typeArgs=dynamic*/
+ P1/*location: test.dart;P1*/(), const
+ P2/*location: test.dart;P2*/<
+ int/*location: dart:core;int*/>()];
+''',
+ withTypes: true);
+ }
+ }
+
test_const_invalid_field_const() async {
var library = await checkLibrary(r'''
class C {
@@ -8666,6 +8742,22 @@
''');
}
+ test_mixin_method_namedAsConstraint() async {
+ var library = await checkLibrary(r'''
+class A {}
+mixin B on A {
+ void A() {}
+}
+''');
+ checkElementText(library, r'''
+class A {
+}
+mixin B on A {
+ void A() {}
+}
+''');
+ }
+
test_nameConflict_exportedAndLocal() async {
addLibrarySource('/a.dart', 'class C {}');
addLibrarySource('/c.dart', '''
@@ -8955,11 +9047,41 @@
withOffsets: true);
}
- test_parameter_covariant() async {
- var library = await checkLibrary('class C { void m(covariant C c) {} }');
+ test_parameter_covariant_explicit_named() async {
+ var library = await checkLibrary('''
+class A {
+ void m({covariant A a}) {}
+}
+''');
checkElementText(library, r'''
-class C {
- void m(covariant C c) {}
+class A {
+ void m({covariant A a}) {}
+}
+''');
+ }
+
+ test_parameter_covariant_explicit_positional() async {
+ var library = await checkLibrary('''
+class A {
+ void m([covariant A a]) {}
+}
+''');
+ checkElementText(library, r'''
+class A {
+ void m([covariant A a]) {}
+}
+''');
+ }
+
+ test_parameter_covariant_explicit_required() async {
+ var library = await checkLibrary('''
+class A {
+ void m(covariant A a) {}
+}
+''');
+ checkElementText(library, r'''
+class A {
+ void m(covariant A a) {}
}
''');
}
@@ -8983,6 +9105,25 @@
''');
}
+ test_parameter_covariant_inherited_named() async {
+ var library = await checkLibrary('''
+class A {
+ void m({covariant A a}) {}
+}
+class B extends A {
+ void m({B a}) {}
+}
+''');
+ checkElementText(library, r'''
+class A {
+ void m({covariant A a}) {}
+}
+class B extends A {
+ void m({covariant B a}) {}
+}
+''');
+ }
+
test_parameter_parameters() async {
var library = await checkLibrary('class C { f(g(x, y)) {} }');
checkElementText(library, r'''
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index d881108..e93a4af 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -240,6 +240,14 @@
declaredNames.remove('CONST_AND_COVARIANT');
declaredNames.remove('CONST_AND_VAR');
declaredNames.remove('COVARIANT_AFTER_FINAL');
+ declaredNames.remove('COVARIANT_AFTER_VAR');
+ declaredNames.remove('EXTERNAL_AFTER_CONST');
+ declaredNames.remove('EXTERNAL_AFTER_FACTORY');
+ declaredNames.remove('EXTERNAL_AFTER_STATIC');
+ declaredNames.remove('MISSING_CLASS_BODY');
+ declaredNames.remove('STATIC_AFTER_CONST');
+ declaredNames.remove('STATIC_AFTER_FINAL');
+ declaredNames.remove('STATIC_AFTER_VAR');
}
// Assert that all remaining declared names are in errorCodeValues
diff --git a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
index c2960c3..2ec431a6 100644
--- a/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
+++ b/pkg/analyzer/test/src/task/strong/dart2_inference_test.dart
@@ -51,15 +51,15 @@
return invocation.staticInvokeType.toString();
}
- expect(getType('f()); // 1'), '() → bool');
+ expect(getType('f()); // 1'), 'bool Function()');
- expect(getType('f(), '), '() → bool');
- expect(getType('f()); // 2'), '() → dynamic');
+ expect(getType('f(), '), 'bool Function()');
+ expect(getType('f()); // 2'), 'dynamic Function()');
- expect(getType('f()), // 3'), '() → bool');
+ expect(getType('f()), // 3'), 'bool Function()');
- expect(getType('f(), '), '() → bool');
- expect(getType('f()); // 4'), '() → dynamic');
+ expect(getType('f(), '), 'bool Function()');
+ expect(getType('f()); // 4'), 'dynamic Function()');
}
test_bool_logical() async {
@@ -80,7 +80,7 @@
void assertType(String prefix) {
var invocation = _findMethodInvocation(unit, code, prefix);
- expect(invocation.staticInvokeType.toString(), '() → bool');
+ expect(invocation.staticInvokeType.toString(), 'bool Function()');
}
assertType('f() || f(); // 1');
@@ -111,7 +111,7 @@
void assertType(String prefix) {
var invocation = _findMethodInvocation(unit, code, prefix);
- expect(invocation.staticInvokeType.toString(), '() → bool');
+ expect(invocation.staticInvokeType.toString(), 'bool Function()');
}
assertType('f()) {} // 1');
@@ -132,7 +132,7 @@
var unit = analysisResult.unit;
Expression closure = _findExpression(unit, code, '() => 42');
- expect(closure.staticType.toString(), '() → List<int>');
+ expect(closure.staticType.toString(), 'List<int> Function()');
}
test_closure_downwardReturnType_block() async {
@@ -149,7 +149,7 @@
var unit = analysisResult.unit;
Expression closure = _findExpression(unit, code, '() { // mark');
- expect(closure.staticType.toString(), '() → List<int>');
+ expect(closure.staticType.toString(), 'List<int> Function()');
}
test_compoundAssignment_index() async {
diff --git a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index d3502e5..a3a31c2 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -60,10 +60,10 @@
expect(futureInt.type.toString(), 'Future<int>');
var f = mainUnit.topLevelVariables[1];
expect(f.name, 'f');
- expect(f.type.toString(), '() → Future<int>');
+ expect(f.type.toString(), 'Future<int> Function()');
var g = mainUnit.topLevelVariables[2];
expect(g.name, 'g');
- expect(g.type.toString(), '() → Future<int>');
+ expect(g.type.toString(), 'Future<int> Function()');
}
test_asyncClosureReturnType_future() async {
@@ -72,7 +72,7 @@
''');
var f = mainUnit.topLevelVariables[0];
expect(f.name, 'f');
- expect(f.type.toString(), '() → Future<int>');
+ expect(f.type.toString(), 'Future<int> Function()');
}
test_asyncClosureReturnType_futureOr() async {
@@ -87,10 +87,10 @@
expect(futureOrInt.type.toString(), 'FutureOr<int>');
var f = mainUnit.topLevelVariables[1];
expect(f.name, 'f');
- expect(f.type.toString(), '() → FutureOr<int>');
+ expect(f.type.toString(), 'FutureOr<int> Function()');
var g = mainUnit.topLevelVariables[2];
expect(g.name, 'g');
- expect(g.type.toString(), '() → Future<int>');
+ expect(g.type.toString(), 'Future<int> Function()');
}
test_blockBodiedLambdas_async_allReturnsAreFutures() async {
@@ -113,7 +113,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Future<num>');
+ expect(f.type.toString(), 'Future<num> Function()');
}
test_blockBodiedLambdas_async_allReturnsAreValues() async {
@@ -136,7 +136,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Future<num>');
+ expect(f.type.toString(), 'Future<num> Function()');
}
test_blockBodiedLambdas_async_mixOfValuesAndFutures() async {
@@ -159,7 +159,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Future<num>');
+ expect(f.type.toString(), 'Future<num> Function()');
}
test_blockBodiedLambdas_asyncStar() async {
@@ -179,7 +179,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Stream<num>');
+ expect(f.type.toString(), 'Stream<num> Function()');
}
test_blockBodiedLambdas_basic() async {
@@ -204,7 +204,7 @@
}
''');
var g = findLocalVariable(unit, 'g');
- expect(g.type.toString(), '() → String');
+ expect(g.type.toString(), 'String Function()');
}
test_blockBodiedLambdas_downwardsIncompatibleWithUpwardsInference_topLevel() async {
@@ -213,7 +213,7 @@
var g = f;
''');
var g = unit.topLevelVariables[0];
- expect(g.type.toString(), '() → String');
+ expect(g.type.toString(), 'String Function()');
}
test_blockBodiedLambdas_inferBottom_async() async {
@@ -230,7 +230,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Future<Null>');
+ expect(f.type.toString(), 'Future<Null> Function()');
}
test_blockBodiedLambdas_inferBottom_asyncStar() async {
@@ -247,7 +247,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Stream<Null>');
+ expect(f.type.toString(), 'Stream<Null> Function()');
}
test_blockBodiedLambdas_inferBottom_sync() async {
@@ -272,7 +272,7 @@
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '(Object) → Null');
+ expect(f.type.toString(), 'Null Function(Object)');
}
test_blockBodiedLambdas_inferBottom_syncStar() async {
@@ -288,7 +288,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Iterable<Null>');
+ expect(f.type.toString(), 'Iterable<Null> Function()');
}
test_blockBodiedLambdas_LUB() async {
@@ -322,7 +322,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → (int) → double');
+ expect(f.type.toString(), 'double Function(int) Function()');
}
test_blockBodiedLambdas_noReturn() async {
@@ -355,7 +355,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Iterable<num>');
+ expect(f.type.toString(), 'Iterable<num> Function()');
}
test_bottom() async {
@@ -368,9 +368,9 @@
var v = mainUnit.topLevelVariables[0];
expect(v.type.toString(), 'dynamic');
if (AnalysisDriver.useSummary2) {
- expect(v.initializer.type.toString(), '() → dynamic');
+ expect(v.initializer.type.toString(), 'dynamic Function()');
} else {
- expect(v.initializer.type.toString(), '() → Null');
+ expect(v.initializer.type.toString(), 'Null Function()');
}
}
@@ -381,8 +381,8 @@
var v = /*info:INFERRED_TYPE_CLOSURE*/() => null;
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), '() → Null');
- expect(v.initializer.type.toString(), '() → () → Null');
+ expect(v.type.toString(), 'Null Function()');
+ expect(v.initializer.type.toString(), 'Null Function() Function()');
}
test_circularReference_viaClosures() async {
@@ -407,8 +407,8 @@
var y = mainUnit.topLevelVariables[1];
expect(x.name, 'x');
expect(y.name, 'y');
- expect(x.initializer.returnType.toString(), '() → dynamic');
- expect(y.initializer.returnType.toString(), '() → dynamic');
+ expect(x.initializer.returnType.toString(), 'dynamic Function()');
+ expect(y.initializer.returnType.toString(), 'dynamic Function()');
}
test_conflictsCanHappen() async {
@@ -1985,7 +1985,7 @@
typedef void F<V>(V v);
''');
var f = mainUnit.getType('C').methods[0];
- expect(f.type.toString(), '<U>(U) → (U) → void');
+ expect(f.type.toString(), 'void Function(U) Function<U>(U)');
}
test_genericMethods_inferGenericFunctionParameterType2() async {
@@ -1999,7 +1999,7 @@
typedef List<V> G<V>();
''');
var f = mainUnit.getType('C').methods[0];
- expect(f.type.toString(), '<U>(() → List<U>) → void');
+ expect(f.type.toString(), 'void Function<U>(List<U> Function())');
}
test_genericMethods_inferGenericFunctionReturnType() async {
@@ -2013,7 +2013,7 @@
typedef V F<V>();
''');
var f = mainUnit.getType('C').methods[0];
- expect(f.type.toString(), '<U>(U) → () → U');
+ expect(f.type.toString(), 'U Function() Function<U>(U)');
}
test_genericMethods_inferGenericInstantiation() async {
@@ -2192,7 +2192,7 @@
}
''');
var v = findLocalVariable(unit, 'v');
- expect(v.type.toString(), '(num) → List<int>');
+ expect(v.type.toString(), 'List<int> Function(num)');
}
test_genericMethods_usesGreatestLowerBound_topLevel() async {
@@ -2205,7 +2205,7 @@
var v = generic(/*info:INFERRED_TYPE_CLOSURE*/(F f) => null, /*info:INFERRED_TYPE_CLOSURE*/(G g) => null);
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), '(num) → List<int>');
+ expect(v.type.toString(), 'List<int> Function(num)');
}
test_infer_assignToIndex() async {
@@ -2495,7 +2495,7 @@
var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), 'List<() → Object>');
+ expect(v.type.toString(), 'List<Object Function()>');
}
test_inferedType_usesSyntheticFunctionType_functionTypedParam() async {
@@ -2505,7 +2505,7 @@
var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), 'List<((String) → int) → Object>');
+ expect(v.type.toString(), 'List<Object Function(int Function(String))>');
}
test_inferedType_usesSyntheticFunctionType_namedParam() async {
@@ -2515,7 +2515,7 @@
var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), 'List<({x: int}) → Object>');
+ expect(v.type.toString(), 'List<Object Function({x: int})>');
}
test_inferedType_usesSyntheticFunctionType_positionalParam() async {
@@ -2525,7 +2525,7 @@
var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), 'List<([int]) → Object>');
+ expect(v.type.toString(), 'List<Object Function([int])>');
}
test_inferedType_usesSyntheticFunctionType_requiredParam() async {
@@ -2535,7 +2535,7 @@
var v = /*info:INFERRED_TYPE_LITERAL*/[f, g];
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), 'List<(int) → Object>');
+ expect(v.type.toString(), 'List<Object Function(int)>');
}
test_inferFromComplexExpressionsIfOuterMostValueIsPrecise() async {
@@ -2783,20 +2783,25 @@
f9 /*info:INFERRED_TYPE_CLOSURE*/() => f5();
}
''');
- expect(findLocalFunction(unit, 'f0').type.toString(), '() → int');
- expect(findLocalFunction(unit, 'f1').type.toString(), '() → Future<int>');
+ expect(findLocalFunction(unit, 'f0').type.toString(), 'int Function()');
+ expect(findLocalFunction(unit, 'f1').type.toString(),
+ 'Future<int> Function()');
- expect(findLocalFunction(unit, 'f2').type.toString(), '() → int');
- expect(findLocalFunction(unit, 'f3').type.toString(), '() → Future<int>');
- expect(findLocalFunction(unit, 'f4').type.toString(), '() → Iterable<int>');
- expect(findLocalFunction(unit, 'f5').type.toString(), '() → Stream<int>');
+ expect(findLocalFunction(unit, 'f2').type.toString(), 'int Function()');
+ expect(findLocalFunction(unit, 'f3').type.toString(),
+ 'Future<int> Function()');
+ expect(findLocalFunction(unit, 'f4').type.toString(),
+ 'Iterable<int> Function()');
+ expect(findLocalFunction(unit, 'f5').type.toString(),
+ 'Stream<int> Function()');
- expect(findLocalFunction(unit, 'f6').type.toString(), '() → num');
+ expect(findLocalFunction(unit, 'f6').type.toString(), 'num Function()');
// Recursive cases: these infer in declaration order.
- expect(findLocalFunction(unit, 'f7').type.toString(), '() → dynamic');
- expect(findLocalFunction(unit, 'f8').type.toString(), '() → dynamic');
- expect(findLocalFunction(unit, 'f9').type.toString(), '() → Stream<int>');
+ expect(findLocalFunction(unit, 'f7').type.toString(), 'dynamic Function()');
+ expect(findLocalFunction(unit, 'f8').type.toString(), 'dynamic Function()');
+ expect(findLocalFunction(unit, 'f9').type.toString(),
+ 'Stream<int> Function()');
}
test_inferParameterType_setter_fromField() async {
@@ -2809,7 +2814,7 @@
}
''');
var f = mainUnit.getType('C').accessors[0];
- expect(f.type.toString(), '(int) → void');
+ expect(f.type.toString(), 'void Function(int)');
}
test_inferParameterType_setter_fromSetter() async {
@@ -2822,7 +2827,7 @@
}
''');
var f = mainUnit.getType('C').accessors[0];
- expect(f.type.toString(), '(int) → void');
+ expect(f.type.toString(), 'void Function(int)');
}
test_inferred_nonstatic_field_depends_on_static_field_complex() async {
@@ -2873,7 +2878,7 @@
}
''');
var f = findLocalVariable(unit, 'f');
- expect(f.type.toString(), '() → Null');
+ expect(f.type.toString(), 'Null Function()');
}
test_inferredType_cascade() async {
@@ -2984,7 +2989,7 @@
''');
var x = mainUnit.topLevelVariables[0];
expect(x.name, 'x');
- expect(x.type.toString(), '() → bool');
+ expect(x.type.toString(), 'bool Function()');
}
test_inferredType_extractMethodTearOff_viaInterface() async {
@@ -2998,7 +3003,7 @@
''');
var x = mainUnit.topLevelVariables[0];
expect(x.name, 'x');
- expect(x.type.toString(), '() → bool');
+ expect(x.type.toString(), 'bool Function()');
}
test_inferredType_fromTopLevelExecutableTearoff() async {
@@ -3006,7 +3011,7 @@
var v = print;
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), '(Object) → void');
+ expect(v.type.toString(), 'void Function(Object)');
}
test_inferredType_invokeMethod() async {
@@ -3060,7 +3065,7 @@
final x = <String, F>{};
''');
var x = mainUnit.topLevelVariables[0];
- expect(x.type.toString(), 'Map<String, () → void>');
+ expect(x.type.toString(), 'Map<String, void Function()>');
}
test_inferredType_isTypedef_parameterized() async {
@@ -3069,7 +3074,7 @@
final x = <String, F<int>>{};
''');
var x = mainUnit.topLevelVariables[0];
- expect(x.type.toString(), 'Map<String, () → int>');
+ expect(x.type.toString(), 'Map<String, int Function()>');
}
test_inferredType_viaClosure_multipleLevelsOfNesting() async {
@@ -3080,7 +3085,7 @@
}
''');
var f = mainUnit.getType('C').fields[0];
- expect(f.type.toString(), '(bool) → (int) → Map<int, bool>');
+ expect(f.type.toString(), 'Map<int, bool> Function(int) Function(bool)');
}
test_inferredType_viaClosure_typeDependsOnArgs() async {
@@ -3090,7 +3095,7 @@
}
''');
var f = mainUnit.getType('C').fields[0];
- expect(f.type.toString(), '(bool) → bool');
+ expect(f.type.toString(), 'bool Function(bool)');
}
test_inferredType_viaClosure_typeIndependentOfArgs_field() async {
@@ -3100,7 +3105,7 @@
}
''');
var f = mainUnit.getType('C').fields[0];
- expect(f.type.toString(), '(bool) → int');
+ expect(f.type.toString(), 'int Function(bool)');
}
test_inferredType_viaClosure_typeIndependentOfArgs_topLevel() async {
@@ -3108,7 +3113,7 @@
final f = /*info:INFERRED_TYPE_CLOSURE*/(bool b) => 1;
''');
var f = mainUnit.topLevelVariables[0];
- expect(f.type.toString(), '(bool) → int');
+ expect(f.type.toString(), 'int Function(bool)');
}
test_inferReturnOfStatementLambda() async {
@@ -4071,7 +4076,7 @@
}
''');
var v = mainUnit.topLevelVariables[0];
- expect(v.type.toString(), '(String) → int');
+ expect(v.type.toString(), 'int Function(String)');
}
test_unsafeBlockClosureInference_closureCall() async {
@@ -4271,7 +4276,7 @@
}
''');
var v = findLocalVariable(unit, 'v');
- expect(v.type.toString(), 'List<() → int>');
+ expect(v.type.toString(), 'List<int Function()>');
}
test_unsafeBlockClosureInference_inList_untyped() async {
@@ -4284,7 +4289,7 @@
}
''');
var v = findLocalVariable(unit, 'v');
- expect(v.type.toString(), 'List<() → int>');
+ expect(v.type.toString(), 'List<int Function()>');
}
test_unsafeBlockClosureInference_inMap_dynamic() async {
@@ -4305,7 +4310,7 @@
}
''');
var v = findLocalVariable(unit, 'v');
- expect(v.type.toString(), 'Map<int, () → int>');
+ expect(v.type.toString(), 'Map<int, int Function()>');
}
test_unsafeBlockClosureInference_inMap_untyped() async {
@@ -4318,7 +4323,7 @@
}
''');
var v = findLocalVariable(unit, 'v');
- expect(v.type.toString(), 'Map<int, () → int>');
+ expect(v.type.toString(), 'Map<int, int Function()>');
}
test_unsafeBlockClosureInference_methodCall_explicitDynamicParam() async {
diff --git a/pkg/analyzer/test/test_all.dart b/pkg/analyzer/test/test_all.dart
index a27c273..f68ff2b 100644
--- a/pkg/analyzer/test/test_all.dart
+++ b/pkg/analyzer/test/test_all.dart
@@ -13,6 +13,7 @@
import 'parse_compilation_unit_test.dart' as parse_compilation_unit;
import 'source/test_all.dart' as source;
import 'src/test_all.dart' as src;
+import 'verify_docs_test.dart' as verify_docs;
import 'verify_tests_test.dart' as verify_tests;
main() {
@@ -26,6 +27,7 @@
parse_compilation_unit.main();
source.main();
src.main();
+ verify_docs.main();
verify_tests.main();
}, name: 'analyzer');
}
diff --git a/pkg/analyzer/test/verify_docs_test.dart b/pkg/analyzer/test/verify_docs_test.dart
new file mode 100644
index 0000000..90fbc51
--- /dev/null
+++ b/pkg/analyzer/test/verify_docs_test.dart
@@ -0,0 +1,153 @@
+// 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 'dart:convert';
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:front_end/src/testing/package_root.dart' as package_root;
+import 'package:test/test.dart';
+
+main() async {
+ SnippetTester tester = SnippetTester();
+ await tester.verify();
+ if (tester.output.isNotEmpty) {
+ fail(tester.output.toString());
+ }
+}
+
+class SnippetTester {
+ OverlayResourceProvider provider;
+ Folder docFolder;
+ String snippetDirPath;
+ String snippetPath;
+
+ StringBuffer output = StringBuffer();
+
+ SnippetTester() {
+ provider = OverlayResourceProvider(PhysicalResourceProvider.INSTANCE);
+ String packageRoot =
+ provider.pathContext.normalize(package_root.packageRoot);
+ String analyzerPath = provider.pathContext.join(packageRoot, 'analyzer');
+ String docPath = provider.pathContext.join(analyzerPath, 'doc');
+ docFolder = provider.getFolder(docPath);
+ snippetDirPath =
+ provider.pathContext.join(analyzerPath, 'test', 'snippets');
+ snippetPath = provider.pathContext.join(snippetDirPath, 'snippet.dart');
+ }
+
+ void verify() async {
+ await verifyFolder(docFolder);
+ }
+
+ void verifyFile(File file) async {
+ String content = file.readAsStringSync();
+ List<String> lines = const LineSplitter().convert(content);
+ List<String> codeLines = [];
+ bool inCode = false;
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ if (line == '```dart') {
+ if (inCode) {
+ // TODO(brianwilkerson) Report this.
+ }
+ inCode = true;
+ } else if (line == '```') {
+ if (!inCode) {
+ // TODO(brianwilkerson) Report this.
+ }
+ await verifySnippet(file, codeLines.join('\n'));
+ codeLines.clear();
+ inCode = false;
+ } else if (inCode) {
+ codeLines.add(line);
+ }
+ }
+ }
+
+ void verifyFolder(Folder folder) async {
+ for (Resource child in folder.getChildren()) {
+ if (child is File) {
+ if (child.shortName.endsWith('.md')) {
+ await verifyFile(child);
+ }
+ } else if (child is Folder) {
+ await verifyFolder(child);
+ }
+ }
+ }
+
+ void verifySnippet(File file, String snippet) async {
+ // TODO(brianwilkerson) When the files outside of 'src' contain only public
+ // API, write code to compute the list of imports so that new public API
+ // will automatically be allowed.
+ String imports = '''
+import 'dart:math' as math;
+
+import 'package:analyzer/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/analysis_context_collection.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/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+
+''';
+ provider.setOverlay(snippetPath,
+ content: '''
+$imports
+$snippet
+''',
+ modificationStamp: 1);
+ try {
+ AnalysisContextCollection collection = new AnalysisContextCollection(
+ includedPaths: <String>[snippetDirPath], resourceProvider: provider);
+ List<AnalysisContext> contexts = collection.contexts;
+ if (contexts.length != 1) {
+ fail('The snippets directory contains multiple analysis contexts.');
+ }
+ ErrorsResult results =
+ await contexts[0].currentSession.getErrors(snippetPath);
+ Iterable<AnalysisError> errors = results.errors.where((error) {
+ ErrorCode errorCode = error.errorCode;
+ return errorCode != HintCode.UNUSED_IMPORT &&
+ errorCode != HintCode.UNUSED_LOCAL_VARIABLE;
+ });
+ if (errors.isNotEmpty) {
+ String filePath =
+ provider.pathContext.relative(file.path, from: docFolder.path);
+ if (output.isNotEmpty) {
+ output.writeln();
+ }
+ output.writeln('Errors in snippet in "$filePath":');
+ output.writeln();
+ output.writeln(snippet);
+ output.writeln();
+ int importsLength = imports.length + 1; // account for the '\n'.
+ for (var error in errors) {
+ writeError(error, importsLength);
+ }
+ }
+ } finally {
+ provider.removeOverlay(snippetPath);
+ }
+ }
+
+ void writeError(AnalysisError error, int prefixLength) {
+ output.write(error.errorCode);
+ output.write(' (');
+ output.write(error.offset - prefixLength);
+ output.write(', ');
+ output.write(error.length);
+ output.write(') ');
+ output.writeln(error.message);
+ }
+}
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index 798e369..d27a4d8 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -54,16 +54,591 @@
typedef String _StringToString(String s);
-class _CodeGenerator {
+class _BaseGenerator {
static const String _throwDeprecated =
"throw new UnimplementedError('attempt to access deprecated field')";
+ /// Semantic model of the "IDL" input file.
+ final idlModel.Idl _idl;
+
/// Buffer in which generated code is accumulated.
- final StringBuffer _outBuffer = new StringBuffer();
+ final StringBuffer _outBuffer;
/// Current indentation level.
String _indentation = '';
+ _BaseGenerator(this._idl, this._outBuffer);
+
+ /// Generate a Dart expression representing the default value for a field
+ /// having the given [type], or `null` if there is no default value.
+ ///
+ /// If [builder] is `true`, the returned type should be appropriate for use in
+ /// a builder class.
+ String defaultValue(idlModel.FieldType type, bool builder) {
+ if (type.isList) {
+ if (builder) {
+ idlModel.FieldType elementType =
+ new idlModel.FieldType(type.typeName, false);
+ return '<${encodedType(elementType)}>[]';
+ } else {
+ return 'const <${idlPrefix(type.typeName)}>[]';
+ }
+ } else if (_idl.enums.containsKey(type.typeName)) {
+ return '${idlPrefix(type.typeName)}.'
+ '${_idl.enums[type.typeName].values[0].name}';
+ } else if (type.typeName == 'double') {
+ return '0.0';
+ } else if (type.typeName == 'int') {
+ return '0';
+ } else if (type.typeName == 'String') {
+ return "''";
+ } else if (type.typeName == 'bool') {
+ return 'false';
+ } else {
+ return null;
+ }
+ }
+
+ /// Generate a string representing the Dart type which should be used to
+ /// represent [type] while building a serialized data structure.
+ String encodedType(idlModel.FieldType type) {
+ String typeStr;
+ if (_idl.classes.containsKey(type.typeName)) {
+ typeStr = '${type.typeName}Builder';
+ } else {
+ typeStr = idlPrefix(type.typeName);
+ }
+ if (type.isList) {
+ return 'List<$typeStr>';
+ } else {
+ return typeStr;
+ }
+ }
+
+ /// Add the prefix `idl.` to a type name, unless that type name is the name of
+ /// a built-in type.
+ String idlPrefix(String s) {
+ switch (s) {
+ case 'bool':
+ case 'double':
+ case 'int':
+ case 'String':
+ return s;
+ default:
+ return 'idl.$s';
+ }
+ }
+
+ /// Execute [callback] with two spaces added to [_indentation].
+ void indent(void callback()) {
+ String oldIndentation = _indentation;
+ try {
+ _indentation += ' ';
+ callback();
+ } finally {
+ _indentation = oldIndentation;
+ }
+ }
+
+ /// Add the string [s] to the output as a single line, indenting as
+ /// appropriate.
+ void out([String s = '']) {
+ if (s == '') {
+ _outBuffer.writeln('');
+ } else {
+ _outBuffer.writeln('$_indentation$s');
+ }
+ }
+
+ void outDoc(String documentation) {
+ if (documentation != null) {
+ documentation.split('\n').forEach(out);
+ }
+ }
+
+ /// Enclose [s] in quotes, escaping as necessary.
+ String quoted(String s) {
+ return json.encode(s);
+ }
+
+ List<String> _computeVariants(idlModel.ClassDeclaration cls) {
+ var allVariants = Set<String>();
+ for (var field in cls.fields) {
+ var logicalFields = field.logicalProperties?.values;
+ if (logicalFields != null) {
+ for (var logicalField in logicalFields) {
+ allVariants.addAll(logicalField.variants);
+ }
+ }
+ }
+ return allVariants.toList()..sort();
+ }
+
+ String _variantAssertStatement(
+ idlModel.ClassDeclaration class_,
+ idlModel.LogicalProperty property,
+ ) {
+ var assertCondition = property.variants
+ ?.map((key) => '${class_.variantField} == idl.$key')
+ ?.join(' || ');
+ return 'assert($assertCondition);';
+ }
+}
+
+class _BuilderGenerator extends _BaseGenerator {
+ final idlModel.ClassDeclaration cls;
+ List<String> constructorParams = <String>[];
+
+ _BuilderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ : super(idl, outBuffer);
+
+ String get builderName => name + 'Builder';
+
+ String get name => cls.name;
+
+ void generate() {
+ String mixinName = '_${name}Mixin';
+ var implementsClause =
+ cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
+ out('class $builderName extends Object with $mixinName$implementsClause {');
+ indent(() {
+ _generateFields();
+ _generateGettersSetters();
+ _generateConstructors();
+ _generateFlushInformative();
+ _generateCollectApiSignature();
+ _generateToBuffer();
+ _generateFinish();
+ });
+ out('}');
+ }
+
+ void _generateCollectApiSignature() {
+ out();
+ out('/// Accumulate non-[informative] data into [signature].');
+ out('void collectApiSignature(api_sig.ApiSignature signature) {');
+
+ void writeField(String name, idlModel.FieldType type, bool isInformative) {
+ if (isInformative) {
+ return;
+ }
+ String ref = 'this.$name';
+ if (type.isList) {
+ out('if ($ref == null) {');
+ indent(() {
+ out('signature.addInt(0);');
+ });
+ out('} else {');
+ indent(() {
+ out('signature.addInt($ref.length);');
+ out('for (var x in $ref) {');
+ indent(() {
+ _generateSignatureCall(type.typeName, 'x', false);
+ });
+ out('}');
+ });
+ out('}');
+ } else {
+ _generateSignatureCall(type.typeName, ref, true);
+ }
+ }
+
+ indent(() {
+ List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
+ ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
+ a.id.compareTo(b.id));
+ if (cls.variantField != null) {
+ var firstVariant = true;
+ for (var variant in _computeVariants(cls)) {
+ if (firstVariant) {
+ firstVariant = false;
+ } else {
+ out('else');
+ }
+ out('if (${cls.variantField} == idl.$variant) {');
+ indent(() {
+ for (var field in sortedFields) {
+ var logicalProperties = field.logicalProperties;
+ if (logicalProperties != null) {
+ for (var logicalName in logicalProperties.keys) {
+ var logicalProperty = logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
+ writeField(
+ logicalName,
+ field.type,
+ logicalProperty.isInformative,
+ );
+ }
+ }
+ } else {
+ writeField(field.name, field.type, field.isInformative);
+ }
+ }
+ });
+ out('}');
+ }
+ } else {
+ for (idlModel.FieldDeclaration field in sortedFields) {
+ writeField('_${field.name}', field.type, field.isInformative);
+ }
+ }
+ });
+ out('}');
+ }
+
+ void _generateConstructors() {
+ out();
+ if (cls.variantField != null) {
+ for (var variant in _computeVariants(cls)) {
+ var constructorName = variant.split('.')[1];
+ out('$builderName.$constructorName({');
+
+ for (var field in cls.fields) {
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
+ out('${encodedType(field.type)} $logicalName,');
+ }
+ }
+ }
+ }
+
+ out('}) : ');
+
+ out('_${cls.variantField} = idl.$variant');
+
+ var separator = ',';
+ for (var field in cls.fields) {
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
+ out('$separator _${field.name} = $logicalName');
+ separator = ', ';
+ }
+ }
+ }
+ }
+
+ out(';');
+ out();
+ }
+ } else {
+ out('$builderName({${constructorParams.join(', ')}})');
+ List<idlModel.FieldDeclaration> fields = cls.fields.toList();
+ for (int i = 0; i < fields.length; i++) {
+ idlModel.FieldDeclaration field = fields[i];
+ String prefix = i == 0 ? ' : ' : ' ';
+ String suffix = i == fields.length - 1 ? ';' : ',';
+ out('${prefix}_${field.name} = ${field.name}$suffix');
+ }
+ }
+ }
+
+ void _generateFields() {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ String fieldName = field.name;
+ idlModel.FieldType type = field.type;
+ String typeStr = encodedType(type);
+ out('$typeStr _$fieldName;');
+ }
+ }
+
+ void _generateFinish() {
+ out();
+ out('fb.Offset finish(fb.Builder fbBuilder) {');
+ indent(() {
+ // Write objects and remember Offset(s).
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ idlModel.FieldType fieldType = field.type;
+ String offsetName = 'offset_' + field.name;
+ if (fieldType.isList ||
+ fieldType.typeName == 'String' ||
+ _idl.classes.containsKey(fieldType.typeName)) {
+ out('fb.Offset $offsetName;');
+ }
+ }
+
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ idlModel.FieldType fieldType = field.type;
+ String valueName = '_' + field.name;
+ String offsetName = 'offset_' + field.name;
+ String condition;
+ String writeCode;
+ if (fieldType.isList) {
+ condition = ' || $valueName.isEmpty';
+ if (_idl.classes.containsKey(fieldType.typeName)) {
+ String itemCode = 'b.finish(fbBuilder)';
+ String listCode = '$valueName.map((b) => $itemCode).toList()';
+ writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+ } else if (_idl.enums.containsKey(fieldType.typeName)) {
+ String itemCode = 'b.index';
+ String listCode = '$valueName.map((b) => $itemCode).toList()';
+ writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
+ } else if (fieldType.typeName == 'bool') {
+ writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
+ } else if (fieldType.typeName == 'int') {
+ writeCode = '$offsetName = fbBuilder.writeListUint32($valueName);';
+ } else if (fieldType.typeName == 'double') {
+ writeCode = '$offsetName = fbBuilder.writeListFloat64($valueName);';
+ } else {
+ assert(fieldType.typeName == 'String');
+ String itemCode = 'fbBuilder.writeString(b)';
+ String listCode = '$valueName.map((b) => $itemCode).toList()';
+ writeCode = '$offsetName = fbBuilder.writeList($listCode);';
+ }
+ } else if (fieldType.typeName == 'String') {
+ writeCode = '$offsetName = fbBuilder.writeString($valueName);';
+ } else if (_idl.classes.containsKey(fieldType.typeName)) {
+ writeCode = '$offsetName = $valueName.finish(fbBuilder);';
+ }
+ if (writeCode != null) {
+ if (condition == null) {
+ out('if ($valueName != null) {');
+ } else {
+ out('if (!($valueName == null$condition)) {');
+ }
+ indent(() {
+ out(writeCode);
+ });
+ out('}');
+ }
+ }
+
+ // Write the table.
+ out('fbBuilder.startTable();');
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ int index = field.id;
+ idlModel.FieldType fieldType = field.type;
+ String valueName = '_' + field.name;
+ String condition = '$valueName != null';
+ String writeCode;
+ if (fieldType.isList ||
+ fieldType.typeName == 'String' ||
+ _idl.classes.containsKey(fieldType.typeName)) {
+ String offsetName = 'offset_' + field.name;
+ condition = '$offsetName != null';
+ writeCode = 'fbBuilder.addOffset($index, $offsetName);';
+ } else if (fieldType.typeName == 'bool') {
+ condition = '$valueName == true';
+ writeCode = 'fbBuilder.addBool($index, true);';
+ } else if (fieldType.typeName == 'double') {
+ condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+ writeCode = 'fbBuilder.addFloat64($index, $valueName);';
+ } else if (fieldType.typeName == 'int') {
+ condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+ writeCode = 'fbBuilder.addUint32($index, $valueName);';
+ } else if (_idl.enums.containsKey(fieldType.typeName)) {
+ condition += ' && $valueName != ${defaultValue(fieldType, true)}';
+ writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
+ }
+ if (writeCode == null) {
+ throw new UnimplementedError('Writing type ${fieldType.typeName}');
+ }
+ out('if ($condition) {');
+ indent(() {
+ out(writeCode);
+ });
+ out('}');
+ }
+ out('return fbBuilder.endTable();');
+ });
+ out('}');
+ }
+
+ void _generateFlushInformative() {
+ out();
+ out('/// Flush [informative] data recursively.');
+ out('void flushInformative() {');
+
+ void writeField(String name, idlModel.FieldType type, bool isInformative) {
+ if (isInformative) {
+ out('$name = null;');
+ } else if (_idl.classes.containsKey(type.typeName)) {
+ if (type.isList) {
+ out('$name?.forEach((b) => b.flushInformative());');
+ } else {
+ out('$name?.flushInformative();');
+ }
+ }
+ }
+
+ indent(() {
+ if (cls.variantField != null) {
+ var firstVariant = true;
+ for (var variant in _computeVariants(cls)) {
+ if (firstVariant) {
+ firstVariant = false;
+ } else {
+ out('else');
+ }
+ out('if (${cls.variantField} == idl.$variant) {');
+ indent(() {
+ for (var field in cls.fields) {
+ var logicalProperties = field.logicalProperties;
+ if (logicalProperties != null) {
+ for (var logicalName in logicalProperties.keys) {
+ var logicalProperty = logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
+ writeField(
+ logicalName,
+ field.type,
+ logicalProperty.isInformative,
+ );
+ }
+ }
+ } else {
+ writeField(field.name, field.type, field.isInformative);
+ }
+ }
+ });
+ out('}');
+ }
+ } else {
+ for (idlModel.FieldDeclaration field in cls.fields) {
+ writeField('_${field.name}', field.type, field.isInformative);
+ }
+ }
+ });
+ out('}');
+ }
+
+ void _generateGettersSetters() {
+ for (idlModel.FieldDeclaration field in cls.allFields) {
+ String fieldName = field.name;
+ idlModel.FieldType fieldType = field.type;
+ String typeStr = encodedType(fieldType);
+ String def = defaultValue(fieldType, true);
+ String defSuffix = def == null ? '' : ' ??= $def';
+ out();
+ if (field.isDeprecated) {
+ out('@override');
+ out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
+ } else {
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
+ out('@override');
+ out('$typeStr get $logicalName {');
+ indent(() {
+ out(_variantAssertStatement(cls, logicalProperty));
+ out('return _${field.name}$defSuffix;');
+ });
+ out('}');
+ out();
+ }
+ } else {
+ out('@override');
+ out('$typeStr get $fieldName => _$fieldName$defSuffix;');
+ }
+ out();
+
+ constructorParams.add('$typeStr $fieldName');
+
+ outDoc(field.documentation);
+
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
+ out('set $logicalName($typeStr value) {');
+ indent(() {
+ out(_variantAssertStatement(cls, logicalProperty));
+ _generateNonNegativeInt(fieldType);
+ out('_variantField_${field.id} = value;');
+ });
+ out('}');
+ out();
+ }
+ } else {
+ out('set $fieldName($typeStr value) {');
+ indent(() {
+ _generateNonNegativeInt(fieldType);
+ out('this._$fieldName = value;');
+ });
+ out('}');
+ }
+ }
+ }
+ }
+
+ void _generateNonNegativeInt(idlModel.FieldType fieldType) {
+ if (fieldType.typeName == 'int') {
+ if (!fieldType.isList) {
+ out('assert(value == null || value >= 0);');
+ } else {
+ out('assert(value == null || value.every((e) => e >= 0));');
+ }
+ }
+ }
+
+ /// Generate a call to the appropriate method of [ApiSignature] for the type
+ /// [typeName], using the data named by [ref]. If [couldBeNull] is `true`,
+ /// generate code to handle the possibility that [ref] is `null` (substituting
+ /// in the appropriate default value).
+ void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
+ if (_idl.enums.containsKey(typeName)) {
+ if (couldBeNull) {
+ out('signature.addInt($ref == null ? 0 : $ref.index);');
+ } else {
+ out('signature.addInt($ref.index);');
+ }
+ } else if (_idl.classes.containsKey(typeName)) {
+ if (couldBeNull) {
+ out('signature.addBool($ref != null);');
+ }
+ out('$ref?.collectApiSignature(signature);');
+ } else {
+ switch (typeName) {
+ case 'String':
+ if (couldBeNull) {
+ ref += " ?? ''";
+ }
+ out("signature.addString($ref);");
+ break;
+ case 'int':
+ if (couldBeNull) {
+ ref += ' ?? 0';
+ }
+ out('signature.addInt($ref);');
+ break;
+ case 'bool':
+ if (couldBeNull) {
+ ref += ' == true';
+ }
+ out('signature.addBool($ref);');
+ break;
+ case 'double':
+ if (couldBeNull) {
+ ref += ' ?? 0.0';
+ }
+ out('signature.addDouble($ref);');
+ break;
+ default:
+ throw "Don't know how to generate signature call for $typeName";
+ }
+ }
+ }
+
+ void _generateToBuffer() {
+ if (cls.isTopLevel) {
+ out();
+ out('List<int> toBuffer() {');
+ indent(() {
+ out('fb.Builder fbBuilder = new fb.Builder();');
+ String fileId =
+ cls.fileIdentifier == null ? '' : ', ${quoted(cls.fileIdentifier)}';
+ out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
+ });
+ out('}');
+ }
+ }
+}
+
+class _CodeGenerator {
+ /// Buffer in which generated code is accumulated.
+ final StringBuffer _outBuffer = new StringBuffer();
+
/// Semantic model of the "IDL" input file.
idlModel.Idl _idl;
@@ -133,63 +708,6 @@
});
}
- /// Generate a string representing the Dart type which should be used to
- /// represent [type] when deserialized.
- String dartType(idlModel.FieldType type) {
- String baseType = idlPrefix(type.typeName);
- if (type.isList) {
- return 'List<$baseType>';
- } else {
- return baseType;
- }
- }
-
- /// Generate a Dart expression representing the default value for a field
- /// having the given [type], or `null` if there is no default value.
- ///
- /// If [builder] is `true`, the returned type should be appropriate for use in
- /// a builder class.
- String defaultValue(idlModel.FieldType type, bool builder) {
- if (type.isList) {
- if (builder) {
- idlModel.FieldType elementType =
- new idlModel.FieldType(type.typeName, false);
- return '<${encodedType(elementType)}>[]';
- } else {
- return 'const <${idlPrefix(type.typeName)}>[]';
- }
- } else if (_idl.enums.containsKey(type.typeName)) {
- return '${idlPrefix(type.typeName)}.'
- '${_idl.enums[type.typeName].values[0].name}';
- } else if (type.typeName == 'double') {
- return '0.0';
- } else if (type.typeName == 'int') {
- return '0';
- } else if (type.typeName == 'String') {
- return "''";
- } else if (type.typeName == 'bool') {
- return 'false';
- } else {
- return null;
- }
- }
-
- /// Generate a string representing the Dart type which should be used to
- /// represent [type] while building a serialized data structure.
- String encodedType(idlModel.FieldType type) {
- String typeStr;
- if (_idl.classes.containsKey(type.typeName)) {
- typeStr = '${type.typeName}Builder';
- } else {
- typeStr = idlPrefix(type.typeName);
- }
- if (type.isList) {
- return 'List<$typeStr>';
- } else {
- return typeStr;
- }
- }
-
/// Process the AST in [idlParsed] and store the resulting semantic model in
/// [_idl]. Also perform some error checking.
void extractIdl(CompilationUnit idlParsed) {
@@ -283,91 +801,10 @@
}
}
- /// Generate a string representing the FlatBuffer schema type which should be
- /// used to represent [type].
- String fbsType(idlModel.FieldType type) {
- String typeStr;
- switch (type.typeName) {
- case 'bool':
- typeStr = 'bool';
- break;
- case 'double':
- typeStr = 'double';
- break;
- case 'int':
- typeStr = 'uint';
- break;
- case 'String':
- typeStr = 'string';
- break;
- default:
- typeStr = type.typeName;
- break;
- }
- if (type.isList) {
- // FlatBuffers don't natively support a packed list of booleans, so we
- // treat it as a list of unsigned bytes, which is a compatible data
- // structure.
- if (typeStr == 'bool') {
- typeStr = 'ubyte';
- }
- return '[$typeStr]';
- } else {
- return typeStr;
- }
- }
-
/// Entry point to the code generator when generating the "format.fbs" file.
void generateFlatBufferSchema() {
outputHeader();
- for (idlModel.EnumDeclaration enm in _idl.enums.values) {
- out();
- outDoc(enm.documentation);
- out('enum ${enm.name} : byte {');
- indent(() {
- for (int i = 0; i < enm.values.length; i++) {
- idlModel.EnumValueDeclaration value = enm.values[i];
- if (i != 0) {
- out();
- }
- String suffix = i < enm.values.length - 1 ? ',' : '';
- outDoc(value.documentation);
- out('${value.name}$suffix');
- }
- });
- out('}');
- }
- for (idlModel.ClassDeclaration cls in _idl.classes.values) {
- out();
- outDoc(cls.documentation);
- out('table ${cls.name} {');
- indent(() {
- for (int i = 0; i < cls.allFields.length; i++) {
- idlModel.FieldDeclaration field = cls.allFields[i];
- if (i != 0) {
- out();
- }
- outDoc(field.documentation);
- List<String> attributes = <String>['id: ${field.id}'];
- if (field.isDeprecated) {
- attributes.add('deprecated');
- }
- String attrText = attributes.join(', ');
- out('${field.name}:${fbsType(field.type)} ($attrText);');
- }
- });
- out('}');
- }
- out();
- // Standard flatbuffers only support one root type. We support multiple
- // root types. For now work around this by forcing PackageBundle to be the
- // root type. TODO(paulberry): come up with a better solution.
- idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
- out('root_type ${rootType.name};');
- if (rootType.fileIdentifier != null) {
- out();
- out('file_identifier ${quoted(rootType.fileIdentifier)};');
- }
+ _FlatBufferSchemaGenerator(_idl, _outBuffer).generate();
}
/// Entry point to the code generator when generating the "format.dart" file.
@@ -382,69 +819,33 @@
out();
out("import 'idl.dart' as idl;");
out();
- for (idlModel.EnumDeclaration enm in _idl.enums.values) {
- _generateEnumReader(enm);
+ for (idlModel.EnumDeclaration enum_ in _idl.enums.values) {
+ _EnumReaderGenerator(_idl, _outBuffer, enum_).generate();
out();
}
for (idlModel.ClassDeclaration cls in _idl.classes.values) {
if (!cls.isDeprecated) {
- _generateBuilder(cls);
+ _BuilderGenerator(_idl, _outBuffer, cls).generate();
out();
}
if (cls.isTopLevel) {
- _generateReadFunction(cls);
+ _ReaderGenerator(_idl, _outBuffer, cls).generateReaderFunction();
out();
}
if (!cls.isDeprecated) {
- _generateReader(cls);
+ _ReaderGenerator(_idl, _outBuffer, cls).generateReader();
out();
- _generateImpl(cls);
+ _ImplGenerator(_idl, _outBuffer, cls).generate();
out();
- _generateMixin(cls);
+ _MixinGenerator(_idl, _outBuffer, cls).generate();
out();
}
}
}
- /// Add the prefix `idl.` to a type name, unless that type name is the name of
- /// a built-in type.
- String idlPrefix(String s) {
- switch (s) {
- case 'bool':
- case 'double':
- case 'int':
- case 'String':
- return s;
- default:
- return 'idl.$s';
- }
- }
-
- /// Execute [callback] with two spaces added to [_indentation].
- void indent(void callback()) {
- String oldIndentation = _indentation;
- try {
- _indentation += ' ';
- callback();
- } finally {
- _indentation = oldIndentation;
- }
- }
-
- /// Add the string [s] to the output as a single line, indenting as
- /// appropriate.
+ /// Add the string [s] to the output as a single line.
void out([String s = '']) {
- if (s == '') {
- _outBuffer.writeln('');
- } else {
- _outBuffer.writeln('$_indentation$s');
- }
- }
-
- void outDoc(String documentation) {
- if (documentation != null) {
- documentation.split('\n').forEach(out);
- }
+ _outBuffer.writeln(s);
}
void outputHeader() {
@@ -459,11 +860,6 @@
out();
}
- /// Enclose [s] in quotes, escaping as necessary.
- String quoted(String s) {
- return json.encode(s);
- }
-
void _addFieldForGetter(
idlModel.ClassDeclaration cls,
MethodDeclaration getter,
@@ -572,21 +968,21 @@
var fieldType = new idlModel.FieldType(type.name, isList);
String name = getter.name;
- Map<String, List<String>> variantMap;
+ Map<String, idlModel.LogicalProperty> logicalProperties;
if (variants != null) {
var fieldsWithSameId =
cls.allFields.where((field) => field.id == id).toList();
if (fieldsWithSameId.isNotEmpty) {
- var existingField = fieldsWithSameId.first;
- if (existingField.variantMap == null) {
+ var existingField = fieldsWithSameId.single;
+ if (existingField.logicalProperties == null) {
throw Exception('$desc: id $id is already used as a non-variant '
'field: ${existingField.name}');
}
- var map = existingField.variantMap;
+ var map = existingField.logicalProperties;
for (var variant in variants) {
for (var logicalName in map.keys) {
- if (map[logicalName].contains(variant)) {
+ if (map[logicalName].variants.contains(variant)) {
throw Exception('$desc: id $id is already used for $logicalName');
}
}
@@ -598,11 +994,27 @@
);
}
- map.putIfAbsent(getter.name, () => <String>[]).addAll(variants);
+ if (map[getter.name] != null) {
+ throw Exception(
+ '$desc: logical property ${getter.name} is already used',
+ );
+ }
+
+ map[getter.name] = idlModel.LogicalProperty(
+ isDeprecated: isDeprecated,
+ isInformative: isInformative,
+ variants: variants,
+ );
return;
} else {
name = 'variantField_$id';
- variantMap = <String, List<String>>{getter.name: variants};
+ logicalProperties = <String, idlModel.LogicalProperty>{
+ getter.name: idlModel.LogicalProperty(
+ isDeprecated: isDeprecated,
+ isInformative: isInformative,
+ variants: variants,
+ ),
+ };
}
}
@@ -614,318 +1026,46 @@
id: id,
isDeprecated: isDeprecated,
isInformative: isInformative,
- variantMap: variantMap,
+ logicalProperties: logicalProperties,
),
);
}
- Iterable<String> _computeVariants(idlModel.ClassDeclaration cls) {
- return cls.fields
- .map((f) => f.variantMap?.values ?? [])
- .expand((v) => v)
- .expand((v) => v)
- .toSet();
+ /// Return the documentation text of the given [node], or `null` if the [node]
+ /// does not have a comment. Each line is `\n` separated.
+ String _getNodeDoc(AnnotatedNode node) {
+ Comment comment = node.documentationComment;
+ if (comment != null && comment.isDocumentation) {
+ if (comment.tokens.length == 1 &&
+ comment.tokens.first.lexeme.startsWith('/*')) {
+ Token token = comment.tokens.first;
+ return token.lexeme.split('\n').map((String line) {
+ line = line.trimLeft();
+ if (line.startsWith('*')) line = ' ' + line;
+ return line;
+ }).join('\n');
+ } else if (comment.tokens
+ .every((token) => token.lexeme.startsWith('///'))) {
+ return comment.tokens
+ .map((token) => token.lexeme.trimLeft())
+ .join('\n');
+ }
+ }
+ return null;
}
+}
- void _generateBuilder(idlModel.ClassDeclaration cls) {
- String name = cls.name;
- String builderName = name + 'Builder';
- String mixinName = '_${name}Mixin';
- List<String> constructorParams = <String>[];
- var implementsClause =
- cls.isDeprecated ? '' : ' implements ${idlPrefix(name)}';
- out('class $builderName extends Object with $mixinName$implementsClause {');
- indent(() {
- // Generate fields.
- for (idlModel.FieldDeclaration field in cls.fields) {
- String fieldName = field.name;
- idlModel.FieldType type = field.type;
- String typeStr = encodedType(type);
- out('$typeStr _$fieldName;');
- }
+class _EnumReaderGenerator extends _BaseGenerator {
+ final idlModel.EnumDeclaration enum_;
- // Generate getters and setters.
- for (idlModel.FieldDeclaration field in cls.allFields) {
- String fieldName = field.name;
- idlModel.FieldType fieldType = field.type;
- String typeStr = encodedType(fieldType);
- String def = defaultValue(fieldType, true);
- String defSuffix = def == null ? '' : ' ??= $def';
- out();
- if (field.isDeprecated) {
- out('@override');
- out('Null get $fieldName => $_throwDeprecated;');
- } else {
- if (field.variantMap != null) {
- for (var logicalName in field.variantMap.keys) {
- var variants = field.variantMap[logicalName];
- out('@override');
- out('$typeStr get $logicalName {');
- indent(() {
- out(_variantAssertStatement(cls, variants));
- out('return _${field.name}$defSuffix;');
- });
- out('}');
- out();
- }
- } else {
- out('@override');
- out('$typeStr get $fieldName => _$fieldName$defSuffix;');
- }
- out();
+ _EnumReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.enum_)
+ : super(idl, outBuffer);
- constructorParams.add('$typeStr $fieldName');
-
- outDoc(field.documentation);
-
- if (field.variantMap != null) {
- for (var logicalName in field.variantMap.keys) {
- var variants = field.variantMap[logicalName];
- out('set $logicalName($typeStr value) {');
- indent(() {
- out(_variantAssertStatement(cls, variants));
- _generateNonNegativeInt(fieldType);
- out('_variantField_${field.id} = value;');
- });
- out('}');
- out();
- }
- } else {
- out('set $fieldName($typeStr value) {');
- indent(() {
- _generateNonNegativeInt(fieldType);
- out('this._$fieldName = value;');
- });
- out('}');
- }
- }
- }
- // Generate constructor.
- out();
- if (cls.variantField != null) {
- for (var variant in _computeVariants(cls)) {
- var constructorName = variant.split('.')[1];
- out('$builderName.$constructorName({');
-
- for (var field in cls.fields) {
- if (field.variantMap != null) {
- for (var property in field.variantMap.keys) {
- if (field.variantMap[property].contains(variant)) {
- out('${encodedType(field.type)} $property,');
- }
- }
- }
- }
-
- out('}) : ');
-
- out('_${cls.variantField} = idl.$variant');
-
- var separator = ',';
- for (var field in cls.fields) {
- if (field.variantMap != null) {
- for (var property in field.variantMap.keys) {
- if (field.variantMap[property].contains(variant)) {
- out('$separator _${field.name} = $property');
- separator = ', ';
- }
- }
- }
- }
-
- out(';');
- out();
- }
- } else {
- out('$builderName({${constructorParams.join(', ')}})');
- List<idlModel.FieldDeclaration> fields = cls.fields.toList();
- for (int i = 0; i < fields.length; i++) {
- idlModel.FieldDeclaration field = fields[i];
- String prefix = i == 0 ? ' : ' : ' ';
- String suffix = i == fields.length - 1 ? ';' : ',';
- out('${prefix}_${field.name} = ${field.name}$suffix');
- }
- }
-
- // Generate flushInformative().
- {
- out();
- out('/// Flush [informative] data recursively.');
- out('void flushInformative() {');
- indent(() {
- for (idlModel.FieldDeclaration field in cls.fields) {
- idlModel.FieldType fieldType = field.type;
- String valueName = '_' + field.name;
- if (field.isInformative) {
- out('$valueName = null;');
- } else if (_idl.classes.containsKey(fieldType.typeName)) {
- if (fieldType.isList) {
- out('$valueName?.forEach((b) => b.flushInformative());');
- } else {
- out('$valueName?.flushInformative();');
- }
- }
- }
- });
- out('}');
- }
- // Generate collectApiSignature().
- {
- out();
- out('/// Accumulate non-[informative] data into [signature].');
- out('void collectApiSignature(api_sig.ApiSignature signature) {');
- indent(() {
- List<idlModel.FieldDeclaration> sortedFields = cls.fields.toList()
- ..sort((idlModel.FieldDeclaration a, idlModel.FieldDeclaration b) =>
- a.id.compareTo(b.id));
- for (idlModel.FieldDeclaration field in sortedFields) {
- if (field.isInformative) {
- continue;
- }
- String ref = 'this._${field.name}';
- if (field.type.isList) {
- out('if ($ref == null) {');
- indent(() {
- out('signature.addInt(0);');
- });
- out('} else {');
- indent(() {
- out('signature.addInt($ref.length);');
- out('for (var x in $ref) {');
- indent(() {
- _generateSignatureCall(field.type.typeName, 'x', false);
- });
- out('}');
- });
- out('}');
- } else {
- _generateSignatureCall(field.type.typeName, ref, true);
- }
- }
- });
- out('}');
- }
- // Generate finish.
- if (cls.isTopLevel) {
- out();
- out('List<int> toBuffer() {');
- indent(() {
- out('fb.Builder fbBuilder = new fb.Builder();');
- String fileId = cls.fileIdentifier == null
- ? ''
- : ', ${quoted(cls.fileIdentifier)}';
- out('return fbBuilder.finish(finish(fbBuilder)$fileId);');
- });
- out('}');
- }
- out();
- out('fb.Offset finish(fb.Builder fbBuilder) {');
- indent(() {
- // Write objects and remember Offset(s).
- for (idlModel.FieldDeclaration field in cls.fields) {
- idlModel.FieldType fieldType = field.type;
- String offsetName = 'offset_' + field.name;
- if (fieldType.isList ||
- fieldType.typeName == 'String' ||
- _idl.classes.containsKey(fieldType.typeName)) {
- out('fb.Offset $offsetName;');
- }
- }
- for (idlModel.FieldDeclaration field in cls.fields) {
- idlModel.FieldType fieldType = field.type;
- String valueName = '_' + field.name;
- String offsetName = 'offset_' + field.name;
- String condition;
- String writeCode;
- if (fieldType.isList) {
- condition = ' || $valueName.isEmpty';
- if (_idl.classes.containsKey(fieldType.typeName)) {
- String itemCode = 'b.finish(fbBuilder)';
- String listCode = '$valueName.map((b) => $itemCode).toList()';
- writeCode = '$offsetName = fbBuilder.writeList($listCode);';
- } else if (_idl.enums.containsKey(fieldType.typeName)) {
- String itemCode = 'b.index';
- String listCode = '$valueName.map((b) => $itemCode).toList()';
- writeCode = '$offsetName = fbBuilder.writeListUint8($listCode);';
- } else if (fieldType.typeName == 'bool') {
- writeCode = '$offsetName = fbBuilder.writeListBool($valueName);';
- } else if (fieldType.typeName == 'int') {
- writeCode =
- '$offsetName = fbBuilder.writeListUint32($valueName);';
- } else if (fieldType.typeName == 'double') {
- writeCode =
- '$offsetName = fbBuilder.writeListFloat64($valueName);';
- } else {
- assert(fieldType.typeName == 'String');
- String itemCode = 'fbBuilder.writeString(b)';
- String listCode = '$valueName.map((b) => $itemCode).toList()';
- writeCode = '$offsetName = fbBuilder.writeList($listCode);';
- }
- } else if (fieldType.typeName == 'String') {
- writeCode = '$offsetName = fbBuilder.writeString($valueName);';
- } else if (_idl.classes.containsKey(fieldType.typeName)) {
- writeCode = '$offsetName = $valueName.finish(fbBuilder);';
- }
- if (writeCode != null) {
- if (condition == null) {
- out('if ($valueName != null) {');
- } else {
- out('if (!($valueName == null$condition)) {');
- }
- indent(() {
- out(writeCode);
- });
- out('}');
- }
- }
- // Write the table.
- out('fbBuilder.startTable();');
- for (idlModel.FieldDeclaration field in cls.fields) {
- int index = field.id;
- idlModel.FieldType fieldType = field.type;
- String valueName = '_' + field.name;
- String condition = '$valueName != null';
- String writeCode;
- if (fieldType.isList ||
- fieldType.typeName == 'String' ||
- _idl.classes.containsKey(fieldType.typeName)) {
- String offsetName = 'offset_' + field.name;
- condition = '$offsetName != null';
- writeCode = 'fbBuilder.addOffset($index, $offsetName);';
- } else if (fieldType.typeName == 'bool') {
- condition = '$valueName == true';
- writeCode = 'fbBuilder.addBool($index, true);';
- } else if (fieldType.typeName == 'double') {
- condition += ' && $valueName != ${defaultValue(fieldType, true)}';
- writeCode = 'fbBuilder.addFloat64($index, $valueName);';
- } else if (fieldType.typeName == 'int') {
- condition += ' && $valueName != ${defaultValue(fieldType, true)}';
- writeCode = 'fbBuilder.addUint32($index, $valueName);';
- } else if (_idl.enums.containsKey(fieldType.typeName)) {
- condition += ' && $valueName != ${defaultValue(fieldType, true)}';
- writeCode = 'fbBuilder.addUint8($index, $valueName.index);';
- }
- if (writeCode == null) {
- throw new UnimplementedError('Writing type ${fieldType.typeName}');
- }
- out('if ($condition) {');
- indent(() {
- out(writeCode);
- });
- out('}');
- }
- out('return fbBuilder.endTable();');
- });
- out('}');
- });
- out('}');
- }
-
- void _generateEnumReader(idlModel.EnumDeclaration enm) {
- String name = enm.name;
+ void generate() {
+ String name = enum_.name;
String readerName = '_${name}Reader';
String count = '${idlPrefix(name)}.values.length';
- String def = '${idlPrefix(name)}.${enm.values[0].name}';
+ String def = '${idlPrefix(name)}.${enum_.values[0].name}';
out('class $readerName extends fb.Reader<${idlPrefix(name)}> {');
indent(() {
out('const $readerName() : super();');
@@ -943,8 +1083,105 @@
});
out('}');
}
+}
- void _generateImpl(idlModel.ClassDeclaration cls) {
+class _FlatBufferSchemaGenerator extends _BaseGenerator {
+ _FlatBufferSchemaGenerator(idlModel.Idl idl, StringBuffer outBuffer)
+ : super(idl, outBuffer);
+
+ void generate() {
+ for (idlModel.EnumDeclaration enm in _idl.enums.values) {
+ out();
+ outDoc(enm.documentation);
+ out('enum ${enm.name} : byte {');
+ indent(() {
+ for (int i = 0; i < enm.values.length; i++) {
+ idlModel.EnumValueDeclaration value = enm.values[i];
+ if (i != 0) {
+ out();
+ }
+ String suffix = i < enm.values.length - 1 ? ',' : '';
+ outDoc(value.documentation);
+ out('${value.name}$suffix');
+ }
+ });
+ out('}');
+ }
+ for (idlModel.ClassDeclaration cls in _idl.classes.values) {
+ out();
+ outDoc(cls.documentation);
+ out('table ${cls.name} {');
+ indent(() {
+ for (int i = 0; i < cls.allFields.length; i++) {
+ idlModel.FieldDeclaration field = cls.allFields[i];
+ if (i != 0) {
+ out();
+ }
+ outDoc(field.documentation);
+ List<String> attributes = <String>['id: ${field.id}'];
+ if (field.isDeprecated) {
+ attributes.add('deprecated');
+ }
+ String attrText = attributes.join(', ');
+ out('${field.name}:${_fbsType(field.type)} ($attrText);');
+ }
+ });
+ out('}');
+ }
+ out();
+ // Standard flatbuffers only support one root type. We support multiple
+ // root types. For now work around this by forcing PackageBundle to be the
+ // root type. TODO(paulberry): come up with a better solution.
+ idlModel.ClassDeclaration rootType = _idl.classes['PackageBundle'];
+ out('root_type ${rootType.name};');
+ if (rootType.fileIdentifier != null) {
+ out();
+ out('file_identifier ${quoted(rootType.fileIdentifier)};');
+ }
+ }
+
+ /// Generate a string representing the FlatBuffer schema type which should be
+ /// used to represent [type].
+ String _fbsType(idlModel.FieldType type) {
+ String typeStr;
+ switch (type.typeName) {
+ case 'bool':
+ typeStr = 'bool';
+ break;
+ case 'double':
+ typeStr = 'double';
+ break;
+ case 'int':
+ typeStr = 'uint';
+ break;
+ case 'String':
+ typeStr = 'string';
+ break;
+ default:
+ typeStr = type.typeName;
+ break;
+ }
+ if (type.isList) {
+ // FlatBuffers don't natively support a packed list of booleans, so we
+ // treat it as a list of unsigned bytes, which is a compatible data
+ // structure.
+ if (typeStr == 'bool') {
+ typeStr = 'ubyte';
+ }
+ return '[$typeStr]';
+ } else {
+ return typeStr;
+ }
+ }
+}
+
+class _ImplGenerator extends _BaseGenerator {
+ final idlModel.ClassDeclaration cls;
+
+ _ImplGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ : super(idl, outBuffer);
+
+ void generate() {
String name = cls.name;
String implName = '_${name}Impl';
String mixinName = '_${name}Mixin';
@@ -958,7 +1195,7 @@
out();
// Write cache fields.
for (idlModel.FieldDeclaration field in cls.fields) {
- String returnType = dartType(field.type);
+ String returnType = _dartType(field.type);
String fieldName = field.name;
out('$returnType _$fieldName;');
}
@@ -1005,18 +1242,18 @@
assert(readCode != null);
// Write the getter implementation.
out();
- String returnType = dartType(type);
+ String returnType = _dartType(type);
if (field.isDeprecated) {
out('@override');
- out('Null get $fieldName => $_throwDeprecated;');
+ out('Null get $fieldName => ${_BaseGenerator._throwDeprecated};');
} else {
- if (field.variantMap != null) {
- for (var logicalName in field.variantMap.keys) {
- var variants = field.variantMap[logicalName];
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
out('@override');
out('$returnType get $logicalName {');
indent(() {
- out(_variantAssertStatement(cls, variants));
+ out(_variantAssertStatement(cls, logicalProperty));
String readExpr =
'$readCode.vTableGet(_bc, _bcOffset, $index, $def)';
out('_$fieldName ??= $readExpr;');
@@ -1042,7 +1279,25 @@
out('}');
}
- void _generateMixin(idlModel.ClassDeclaration cls) {
+ /// Generate a string representing the Dart type which should be used to
+ /// represent [type] when deserialized.
+ String _dartType(idlModel.FieldType type) {
+ String baseType = idlPrefix(type.typeName);
+ if (type.isList) {
+ return 'List<$baseType>';
+ } else {
+ return baseType;
+ }
+ }
+}
+
+class _MixinGenerator extends _BaseGenerator {
+ final idlModel.ClassDeclaration cls;
+
+ _MixinGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ : super(idl, outBuffer);
+
+ void generate() {
String name = cls.name;
String mixinName = '_${name}Mixin';
out('abstract class $mixinName implements ${idlPrefix(name)} {');
@@ -1088,7 +1343,7 @@
if (cls.variantField != null) {
indent(() {
for (idlModel.FieldDeclaration field in cls.fields) {
- if (field.variantMap == null) {
+ if (field.logicalProperties == null) {
var condition = jsonCondition(field.type, field.name);
var storeField = jsonStore(field.type, field.name);
out('if ($condition) $storeField;');
@@ -1098,9 +1353,11 @@
out('if (${cls.variantField} == idl.$variant) {');
indent(() {
for (idlModel.FieldDeclaration field in cls.fields) {
- if (field.variantMap != null) {
- for (var logicalName in field.variantMap.keys) {
- if (field.variantMap[logicalName].contains(variant)) {
+ var logicalProperties = field.logicalProperties;
+ if (logicalProperties != null) {
+ for (var logicalName in logicalProperties.keys) {
+ var logicalProperty = logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
var condition = jsonCondition(field.type, logicalName);
var storeField = jsonStore(field.type, logicalName);
out('if ($condition) $storeField;');
@@ -1136,9 +1393,10 @@
indent(() {
out('return {');
for (idlModel.FieldDeclaration field in cls.fields) {
- if (field.variantMap != null) {
- for (var logicalName in field.variantMap.keys) {
- if (field.variantMap[logicalName].contains(variant)) {
+ if (field.logicalProperties != null) {
+ for (var logicalName in field.logicalProperties.keys) {
+ var logicalProperty = field.logicalProperties[logicalName];
+ if (logicalProperty.variants.contains(variant)) {
out('${quoted(logicalName)}: $logicalName,');
}
}
@@ -1170,18 +1428,15 @@
});
out('}');
}
+}
- void _generateNonNegativeInt(idlModel.FieldType fieldType) {
- if (fieldType.typeName == 'int') {
- if (!fieldType.isList) {
- out('assert(value == null || value >= 0);');
- } else {
- out('assert(value == null || value.every((e) => e >= 0));');
- }
- }
- }
+class _ReaderGenerator extends _BaseGenerator {
+ final idlModel.ClassDeclaration cls;
- void _generateReader(idlModel.ClassDeclaration cls) {
+ _ReaderGenerator(idlModel.Idl idl, StringBuffer outBuffer, this.cls)
+ : super(idl, outBuffer);
+
+ void generateReader() {
String name = cls.name;
String readerName = '_${name}Reader';
String implName = '_${name}Impl';
@@ -1195,7 +1450,7 @@
out('}');
}
- void _generateReadFunction(idlModel.ClassDeclaration cls) {
+ void generateReaderFunction() {
String name = cls.name;
out('${idlPrefix(name)} read$name(List<int> buffer) {');
indent(() {
@@ -1204,85 +1459,4 @@
});
out('}');
}
-
- /// Generate a call to the appropriate method of [ApiSignature] for the type
- /// [typeName], using the data named by [ref]. If [couldBeNull] is `true`,
- /// generate code to handle the possibility that [ref] is `null` (substituting
- /// in the appropriate default value).
- void _generateSignatureCall(String typeName, String ref, bool couldBeNull) {
- if (_idl.enums.containsKey(typeName)) {
- if (couldBeNull) {
- out('signature.addInt($ref == null ? 0 : $ref.index);');
- } else {
- out('signature.addInt($ref.index);');
- }
- } else if (_idl.classes.containsKey(typeName)) {
- if (couldBeNull) {
- out('signature.addBool($ref != null);');
- }
- out('$ref?.collectApiSignature(signature);');
- } else {
- switch (typeName) {
- case 'String':
- if (couldBeNull) {
- ref += " ?? ''";
- }
- out("signature.addString($ref);");
- break;
- case 'int':
- if (couldBeNull) {
- ref += ' ?? 0';
- }
- out('signature.addInt($ref);');
- break;
- case 'bool':
- if (couldBeNull) {
- ref += ' == true';
- }
- out('signature.addBool($ref);');
- break;
- case 'double':
- if (couldBeNull) {
- ref += ' ?? 0.0';
- }
- out('signature.addDouble($ref);');
- break;
- default:
- throw "Don't know how to generate signature call for $typeName";
- }
- }
- }
-
- /// Return the documentation text of the given [node], or `null` if the [node]
- /// does not have a comment. Each line is `\n` separated.
- String _getNodeDoc(AnnotatedNode node) {
- Comment comment = node.documentationComment;
- if (comment != null && comment.isDocumentation) {
- if (comment.tokens.length == 1 &&
- comment.tokens.first.lexeme.startsWith('/*')) {
- Token token = comment.tokens.first;
- return token.lexeme.split('\n').map((String line) {
- line = line.trimLeft();
- if (line.startsWith('*')) line = ' ' + line;
- return line;
- }).join('\n');
- } else if (comment.tokens
- .every((token) => token.lexeme.startsWith('///'))) {
- return comment.tokens
- .map((token) => token.lexeme.trimLeft())
- .join('\n');
- }
- }
- return null;
- }
-
- String _variantAssertStatement(
- idlModel.ClassDeclaration class_,
- List<String> variants,
- ) {
- var assertCondition = variants
- ?.map((key) => '${class_.variantField} == idl.$key')
- ?.join(' || ');
- return 'assert($assertCondition);';
- }
}
diff --git a/pkg/analyzer/tool/summary/idl_model.dart b/pkg/analyzer/tool/summary/idl_model.dart
index 597e669..5354155 100644
--- a/pkg/analyzer/tool/summary/idl_model.dart
+++ b/pkg/analyzer/tool/summary/idl_model.dart
@@ -115,9 +115,9 @@
final bool isInformative;
/**
- * Maps logical property names to variants in which this field is available.
+ * Maps logical property names to logical property.
*/
- final Map<String, List<String>> variantMap;
+ final Map<String, LogicalProperty> logicalProperties;
FieldDeclaration({
@required String documentation,
@@ -126,7 +126,7 @@
@required this.id,
@required this.isDeprecated,
@required this.isInformative,
- @required this.variantMap,
+ @required this.logicalProperties,
}) : super(documentation, name);
}
@@ -179,3 +179,29 @@
*/
final Map<String, EnumDeclaration> enums = <String, EnumDeclaration>{};
}
+
+/**
+ * Information about a logical property mapped to a single data fields.
+ */
+class LogicalProperty {
+ /**
+ * Indicates whether the property is deprecated.
+ */
+ final bool isDeprecated;
+
+ /**
+ * Indicates whether the property is informative.
+ */
+ final bool isInformative;
+
+ /**
+ * Names of variants in which this property is available.
+ */
+ final List<String> variants;
+
+ LogicalProperty({
+ @required this.isDeprecated,
+ @required this.isInformative,
+ @required this.variants,
+ });
+}
diff --git a/pkg/analyzer_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 5bb4368..10ef17b 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/analysis/declared_variables.dart';
import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/dart/analysis/byte_store.dart';
@@ -15,7 +16,10 @@
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/sdk/sdk.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
@@ -28,6 +32,10 @@
import 'package:analyzer/src/summary/summarize_ast.dart';
import 'package:analyzer/src/summary/summarize_elements.dart';
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
+import 'package:analyzer/src/summary2/link.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_bundle_context.dart' as summary2;
+import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
+import 'package:analyzer/src/summary2/reference.dart' as summary2;
import 'package:analyzer_cli/src/context_cache.dart';
import 'package:analyzer_cli/src/driver.dart';
import 'package:analyzer_cli/src/error_formatter.dart';
@@ -175,16 +183,23 @@
final ContextCache contextCache;
SummaryDataStore summaryDataStore;
- AnalysisOptions analysisOptions;
+ AnalysisOptionsImpl analysisOptions;
Map<Uri, File> uriToFileMap;
final List<Source> explicitSources = <Source>[];
final List<PackageBundle> unlinkedBundles = <PackageBundle>[];
+ SourceFactory sourceFactory;
+ DeclaredVariables declaredVariables;
AnalysisDriver analysisDriver;
PackageBundleAssembler assembler;
final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
+ final bool buildSummary2 = true;
+ final bool consumeSummary2 = false;
+ final Map<String, ParsedUnitResult> inputParsedUnitResults = {};
+ summary2.LinkedElementFactory elementFactory;
+
// May be null.
final DependencyTracker dependencyTracker;
@@ -275,6 +290,10 @@
_computeLinkedLibraries(unlinkedUris);
}
+ if (buildSummary2) {
+ _computeLinkedLibraries2();
+ }
+
// Write the whole package bundle.
PackageBundleBuilder bundle = assembler.assemble();
if (options.buildSummaryOutput != null) {
@@ -351,6 +370,58 @@
});
}
+ /**
+ * Use [elementFactory] filled with input summaries, and link prepared
+ * [inputParsedUnitResults] to produce linked libraries in [assembler].
+ */
+ void _computeLinkedLibraries2() {
+ logger.run('Link output summary2', () {
+ var inputLibraries = <summary2.LinkInputLibrary>[];
+
+ for (var librarySource in explicitSources) {
+ var path = librarySource.fullName;
+
+ var parseResult = inputParsedUnitResults[path];
+ if (parseResult == null) {
+ throw ArgumentError('No parsed unit for $path');
+ }
+
+ var unit = parseResult.unit;
+ var isPart = unit.directives.any((d) => d is PartOfDirective);
+ if (isPart) {
+ continue;
+ }
+
+ var inputUnits = <summary2.LinkInputUnit>[];
+ inputUnits.add(
+ summary2.LinkInputUnit(librarySource, false, unit),
+ );
+
+ for (var directive in unit.directives) {
+ if (directive is PartDirective) {
+ var partUri = directive.uri.stringValue;
+ var partSource = sourceFactory.resolveUri(librarySource, partUri);
+ var partPath = partSource.fullName;
+ var partParseResult = inputParsedUnitResults[partPath];
+ if (partParseResult == null) {
+ throw ArgumentError('No parsed unit for part $partPath in $path');
+ }
+ inputUnits.add(
+ summary2.LinkInputUnit(partSource, false, partParseResult.unit),
+ );
+ }
+ }
+
+ inputLibraries.add(
+ summary2.LinkInputLibrary(librarySource, inputUnits),
+ );
+ }
+
+ var linkResult = summary2.link(elementFactory, inputLibraries);
+ assembler.setBundle2(linkResult.bundle);
+ });
+ }
+
Future<ErrorSeverity> _computeMaxSeverity() async {
ErrorSeverity maxSeverity = ErrorSeverity.NONE;
if (!options.buildSuppressExitCode) {
@@ -429,7 +500,7 @@
summaryDataStore.addBundle(null, sdkBundle);
});
- var sourceFactory = new SourceFactory(<UriResolver>[
+ sourceFactory = new SourceFactory(<UriResolver>[
new DartUriResolver(sdk),
new TrackingInSummaryUriResolver(
new InSummaryUriResolver(resourceProvider, summaryDataStore),
@@ -449,14 +520,38 @@
new FileContentOverlay(),
null,
sourceFactory,
- analysisOptions as AnalysisOptionsImpl,
+ analysisOptions,
externalSummaries: summaryDataStore);
- analysisDriver.declaredVariables =
- new DeclaredVariables.fromMap(options.definedVariables);
+
+ declaredVariables = new DeclaredVariables.fromMap(options.definedVariables);
+ analysisDriver.declaredVariables = declaredVariables;
+
+ if (buildSummary2) {
+ _createLinkedElementFactory();
+ }
scheduler.start();
}
+ void _createLinkedElementFactory() {
+ var analysisContext = RestrictedAnalysisContext(
+ SynchronousSession(analysisOptions, declaredVariables),
+ sourceFactory,
+ );
+
+ elementFactory = summary2.LinkedElementFactory(
+ analysisContext,
+ null,
+ summary2.Reference.root(),
+ );
+
+ for (var bundle in summaryDataStore.bundles) {
+ elementFactory.addBundle(
+ summary2.LinkedBundleContext(elementFactory, bundle.bundle2),
+ );
+ }
+ }
+
/**
* Convert [sourceEntities] (a list of file specifications of the form
* "$uri|$path") to a map from URI to path. If an error occurs, report the
@@ -495,13 +590,14 @@
}
// Parse the source and serialize its AST.
Uri uri = Uri.parse(absoluteUri);
- Source source = analysisDriver.sourceFactory.forUri2(uri);
+ Source source = sourceFactory.forUri2(uri);
if (!source.exists()) {
// TODO(paulberry): we should report a warning/error because DDC
// compilations are unlikely to work.
return;
}
var result = await analysisDriver.parseFile(source.fullName);
+ inputParsedUnitResults[result.path] = result;
UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit);
uriToUnit[absoluteUri] = unlinkedUnit;
assembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -513,6 +609,11 @@
*/
Future<void> _printErrors({String outputPath}) async {
await logger.runAsync('Compute and print analysis errors', () async {
+ var wasUseSummary2 = AnalysisDriver.useSummary2;
+ if (consumeSummary2) {
+ AnalysisDriver.useSummary2 = true;
+ }
+
StringBuffer buffer = new StringBuffer();
var severityProcessor = (AnalysisError error) =>
determineProcessedSeverity(error, options, analysisOptions);
@@ -537,6 +638,8 @@
} else {
new io.File(outputPath).writeAsStringSync(buffer.toString());
}
+
+ AnalysisDriver.useSummary2 = wasUseSummary2;
});
}
}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 2449bb7..4050a75 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -393,6 +393,34 @@
return parameterElement?.type is FunctionType;
}
+ /**
+ * Given that the [node] contains the [offset], return the [FormalParameter]
+ * that encloses the [offset], or `null`.
+ */
+ static FormalParameter findFormalParameter(
+ FormalParameterList node,
+ int offset,
+ ) {
+ assert(node.offset < offset && offset < node.end);
+ var parameters = node.parameters;
+ for (var i = 0; i < parameters.length; i++) {
+ var parameter = parameters[i];
+ if (i == 0 && offset < parameter.offset) {
+ return parameter;
+ }
+ if (parameter.offset <= offset) {
+ if (i < parameters.length - 1) {
+ if (offset < parameters[i + 1].offset) {
+ return parameter;
+ }
+ } else if (offset <= node.rightParenthesis.offset) {
+ return parameter;
+ }
+ }
+ }
+ return null;
+ }
+
static int _computeArgIndex(AstNode containingNode, Object entity) {
var argList = containingNode;
if (argList is NamedExpression) {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 6e035ce..2b0dc59 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -82,6 +82,17 @@
bool includeVarNameSuggestions = false;
/**
+ * Indicates whether the completion location is in a field declaration.
+ */
+ bool inFieldDeclaration = false;
+
+ /**
+ * Indicates whether the completion location is in a top-level variable
+ * declaration.
+ */
+ bool inTopLevelVariableDeclaration = false;
+
+ /**
* Indicates whether the completion location is in the body of a static method.
*/
bool inStaticMethodBody = false;
@@ -150,6 +161,11 @@
}
}
+ optype.inFieldDeclaration =
+ targetNode.thisOrAncestorOfType<FieldDeclaration>() != null;
+ optype.inTopLevelVariableDeclaration =
+ targetNode.thisOrAncestorOfType<TopLevelVariableDeclaration>() != null;
+
// If a value should be suggested, suggest also constructors.
if (optype.includeReturnValueSuggestions) {
// Careful: in angular plugin, `target.unit` may be null!
@@ -648,28 +664,27 @@
}
}
}
+
+ // Find the containing parameter.
+ var parameter = CompletionTarget.findFormalParameter(node, offset);
+ if (parameter == null) return;
+
// Handle default normal parameter just as a normal parameter.
- if (entity is DefaultFormalParameter) {
- entity = entity.parameter;
+ if (parameter is DefaultFormalParameter) {
+ parameter = (parameter as DefaultFormalParameter).parameter;
}
+
// "(^ this.field)"
- if (entity is FieldFormalParameter) {
- if (offset < entity.thisKeyword.offset) {
+ if (parameter is FieldFormalParameter) {
+ if (offset < parameter.thisKeyword.offset) {
optype.includeTypeNameSuggestions = true;
}
+ return;
}
+
// "(Type name)"
- if (entity is SimpleFormalParameter) {
- // "(Type^)" is parsed as a parameter with the _name_ "Type".
- if (entity.type == null) {
- optype.includeTypeNameSuggestions = true;
- }
- // If inside of "Type" in "(Type^ name)", then include types.
- if (entity.type != null &&
- entity.type.offset <= offset &&
- offset <= entity.type.end) {
- optype.includeTypeNameSuggestions = true;
- }
+ if (parameter is SimpleFormalParameter) {
+ visitSimpleFormalParameter(parameter);
}
}
@@ -974,6 +989,45 @@
}
@override
+ void visitSimpleFormalParameter(SimpleFormalParameter node) {
+ var type = node.type;
+ var name = node.identifier;
+
+ // "(Type^)" is parsed as a parameter with the _name_ "Type".
+ if (type == null &&
+ name != null &&
+ name.offset <= offset &&
+ offset <= name.end) {
+ optype.includeTypeNameSuggestions = true;
+ return;
+ }
+
+ // If "(^ Type)", then include types.
+ if (type == null && offset < name.offset) {
+ optype.includeTypeNameSuggestions = true;
+ return;
+ }
+
+ // If "(Type ^)", then include parameter names.
+ if (type == null && name.end < offset && offset <= name.token.next.offset) {
+ optype.includeVarNameSuggestions = true;
+ return;
+ }
+
+ // If inside of "Type" in "(Type^ name)", then include types.
+ if (type != null && type.offset <= offset && offset <= type.end) {
+ optype.includeTypeNameSuggestions = true;
+ return;
+ }
+
+ // If "(Type name^)", then include parameter names.
+ if (type != null && name.offset <= offset && offset <= name.end) {
+ optype.includeVarNameSuggestions = true;
+ return;
+ }
+ }
+
+ @override
void visitSimpleIdentifier(SimpleIdentifier node) {
// This should never happen; the containingNode will always be some node
// higher up in the parse tree, and the SimpleIdentifier will be the
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 8f42f89..83a16cf 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -37,7 +37,7 @@
'',
'b: ',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: ({a: int, b: String}) → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function({a: int, b: String})',
expectedParameter: 'b: String',
);
}
@@ -55,7 +55,7 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: (int) → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function(int)',
expectedParameter: 'a: int',
);
}
@@ -83,7 +83,7 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: (int, int) → Foo<int>',
+ expectedExecutable: 'Foo.<init>: Foo<int> Function(int, int)',
expectedParameter: 'a: int',
);
}
@@ -102,7 +102,7 @@
')',
'(false)',
argIndex: 1,
- expectedExecutable: 'Foo.<init>: (bool, bool) → Foo<bool>',
+ expectedExecutable: 'Foo.<init>: Foo<bool> Function(bool, bool)',
expectedParameter: 'b: bool',
);
}
@@ -121,7 +121,8 @@
'',
'b: ',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: ({a: int, b: String, c: double}) → Foo',
+ expectedExecutable:
+ 'Foo.<init>: Foo Function({a: int, b: String, c: double})',
expectedParameter: 'b: String',
);
}
@@ -140,7 +141,7 @@
'',
'b: ',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: ({a: int}) → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function({a: int})',
);
}
@@ -158,7 +159,7 @@
')',
'(0)',
argIndex: 1,
- expectedExecutable: 'Foo.named: (int, String, double) → Foo',
+ expectedExecutable: 'Foo.named: Foo Function(int, String, double)',
expectedParameter: 'b: String',
);
}
@@ -177,7 +178,7 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: (int) → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function(int)',
expectedParameter: 'a: int',
);
}
@@ -196,8 +197,8 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: ((String) → int) → Foo',
- expectedParameter: 'f: (String) → int',
+ expectedExecutable: 'Foo.<init>: Foo Function(int Function(String))',
+ expectedParameter: 'f: int Function(String)',
isFunctionalArgument: true,
);
}
@@ -214,7 +215,7 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'Foo.<init>: () → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function()',
);
}
@@ -230,7 +231,7 @@
')',
'(a)',
argIndex: 1,
- expectedExecutable: 'Foo.<init>: () → Foo',
+ expectedExecutable: 'Foo.<init>: Foo Function()',
);
}
@@ -246,7 +247,7 @@
'',
'b: ',
argIndex: 0,
- expectedExecutable: 'foo: ({a: int, b: String, c: double}) → int',
+ expectedExecutable: 'foo: int Function({a: int, b: String, c: double})',
expectedParameter: 'b: String',
);
}
@@ -263,8 +264,8 @@
'',
'f: ',
argIndex: 0,
- expectedExecutable: 'foo: ({f: (String) → int}) → int',
- expectedParameter: 'f: (String) → int',
+ expectedExecutable: 'foo: int Function({f: int Function(String)})',
+ expectedParameter: 'f: int Function(String)',
isFunctionalArgument: true,
);
}
@@ -281,7 +282,7 @@
'',
'b: ',
argIndex: 0,
- expectedExecutable: 'foo: ({a: int}) → int',
+ expectedExecutable: 'foo: int Function({a: int})',
);
}
@@ -297,7 +298,7 @@
')',
'(0)',
argIndex: 1,
- expectedExecutable: 'foo: (int, String) → int',
+ expectedExecutable: 'foo: int Function(int, String)',
expectedParameter: 'b: String',
);
}
@@ -314,8 +315,8 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'foo: ((String) → int) → int',
- expectedParameter: 'f: (String) → int',
+ expectedExecutable: 'foo: int Function(int Function(String))',
+ expectedParameter: 'f: int Function(String)',
isFunctionalArgument: true,
);
}
@@ -334,8 +335,8 @@
')',
'()',
argIndex: 0,
- expectedExecutable: 'C.foo: ((String) → int) → int',
- expectedParameter: 'f: (String) → int',
+ expectedExecutable: 'C.foo: int Function(int Function(String))',
+ expectedParameter: 'f: int Function(String)',
isFunctionalArgument: true,
);
}
@@ -352,7 +353,7 @@
'n',
'(n)',
argIndex: 0,
- expectedExecutable: 'foo: (int, String) → int',
+ expectedExecutable: 'foo: int Function(int, String)',
expectedParameter: 'a: int',
);
}
@@ -369,7 +370,7 @@
')',
'((n))',
argIndex: 0,
- expectedExecutable: 'foo: (int, String) → int',
+ expectedExecutable: 'foo: int Function(int, String)',
expectedParameter: 'a: int',
);
}
@@ -386,7 +387,7 @@
'n',
'(n)',
argIndex: 0,
- expectedExecutable: 'foo: (int, String) → int',
+ expectedExecutable: 'foo: int Function(int, String)',
expectedParameter: 'a: int',
);
}
@@ -664,6 +665,13 @@
assertTarget('new C();', '{var f; {var x;} new C();}');
}
+ test_MapLiteral_empty() async {
+ // MapLiteral VariableDeclaration
+ await createTarget('foo = {^');
+ // fasta scanner inserts synthetic closing '}'
+ assertTarget('}', '{}');
+ }
+
test_MapLiteral_expression() async {
super.setUp();
final experimentStatus =
@@ -683,13 +691,6 @@
}
}
- test_MapLiteral_empty() async {
- // MapLiteral VariableDeclaration
- await createTarget('foo = {^');
- // fasta scanner inserts synthetic closing '}'
- assertTarget('}', '{}');
- }
-
test_MapLiteralEntry() async {
// SimpleIdentifier MapLiteralEntry MapLiteral VariableDeclaration
await createTarget('foo = {7:T^};');
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index caf7f39..186cfa7 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
@@ -2131,23 +2131,35 @@
await assertOpType(functionBody: true);
}
-//
test_SimpleFormalParameter_closure() async {
// SimpleIdentifier SimpleFormalParameter FormalParameterList
addTestSource('mth() { PNGS.sort((String a, Str^) => a.compareTo(b)); }');
await assertOpType(typeNames: true, functionBody: true);
}
- test_SimpleFormalParameter_name1() async {
- // SimpleIdentifier SimpleFormalParameter FormalParameterList
- addTestSource('m(String na^) {}');
- await assertOpType(typeNames: false);
+ test_SimpleFormalParameter_name_typed() async {
+ addTestSource('f(String ^, int b) {}');
+ await assertOpType(typeNames: false, varNames: true);
}
- test_SimpleFormalParameter_name2() async {
- // SimpleIdentifier SimpleFormalParameter FormalParameterList
- addTestSource('m(int first, String na^) {}');
- await assertOpType(typeNames: false);
+ test_SimpleFormalParameter_name_typed_hasName() async {
+ addTestSource('f(String n^, int b) {}');
+ await assertOpType(typeNames: false, varNames: true);
+ }
+
+ test_SimpleFormalParameter_name_typed_last() async {
+ addTestSource('f(String ^) {}');
+ await assertOpType(typeNames: false, varNames: true);
+ }
+
+ test_SimpleFormalParameter_name_typed_last_hasName() async {
+ addTestSource('f(String n^) {}');
+ await assertOpType(typeNames: false, varNames: true);
+ }
+
+ test_SimpleFormalParameter_type_named() async {
+ addTestSource('f(^ name) {}');
+ await assertOpType(typeNames: true, varNames: false);
}
test_SimpleFormalParameter_type_optionalNamed() async {
@@ -2186,6 +2198,11 @@
await assertOpType(typeNames: true);
}
+ test_SimpleFormalParameter_untyped() async {
+ addTestSource('main(final ^) {}');
+ await assertOpType(typeNames: true, varNames: false);
+ }
+
test_SwitchCase_before() async {
// SwitchCase SwitchStatement Block
addTestSource('main() {switch(k) {^case 1:}}');
diff --git a/pkg/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index 444937c..d9a48b1 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -5,6 +5,7 @@
library dart2js.backend_strategy;
import 'common.dart';
+import 'common/codegen.dart';
import 'common/tasks.dart';
import 'deferred_load.dart' show OutputUnitData;
import 'enqueue.dart';
@@ -12,7 +13,9 @@
import 'inferrer/types.dart';
import 'io/source_information.dart';
import 'js_backend/inferred_data.dart';
+import 'js_backend/interceptor_data.dart';
import 'js_backend/native_data.dart';
+import 'serialization/serialization.dart';
import 'ssa/ssa.dart';
import 'universe/codegen_world_builder.dart';
import 'universe/world_builder.dart';
@@ -35,10 +38,12 @@
CodegenWorldBuilder createCodegenWorldBuilder(
NativeBasicData nativeBasicData,
JClosedWorld closedWorld,
- SelectorConstraintsStrategy selectorConstraintsStrategy);
+ SelectorConstraintsStrategy selectorConstraintsStrategy,
+ OneShotInterceptorData oneShotInterceptorData);
/// Creates the [WorkItemBuilder] used by the codegen enqueuer.
- WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld);
+ WorkItemBuilder createCodegenWorkItemBuilder(
+ JClosedWorld closedWorld, CodegenResults codegenResults);
/// Creates the [SsaBuilder] used for the element model.
SsaBuilder createSsaBuilder(
@@ -53,4 +58,15 @@
/// Creates the [TypesInferrer] used by this strategy.
TypesInferrer createTypesInferrer(
JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder);
+
+ /// Calls [f] for every member that needs to be serialized for modular code
+ /// generation and returns an [EntityWriter] for encoding these members in
+ /// the serialized data.
+ ///
+ /// The needed members include members computed on demand during non-modular
+ /// code generation, such as constructor bodies and and generator bodies.
+ EntityWriter forEachCodegenMember(void Function(MemberEntity member) f);
+
+ /// Prepare [source] to deserialize modular code generation data.
+ void prepareCodegenReader(DataSource source);
}
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index 343d58b..beb4c95 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -261,6 +261,9 @@
/// the closure class.
FunctionEntity get callMethod => null;
+ /// The signature method for [callMethod] if needed.
+ FunctionEntity get signatureMethod => null;
+
/// List of locals that this closure class has created corresponding field
/// entities for.
@deprecated
diff --git a/pkg/compiler/lib/src/commandline_options.dart b/pkg/compiler/lib/src/commandline_options.dart
index 576cfc4..801a18f 100644
--- a/pkg/compiler/lib/src/commandline_options.dart
+++ b/pkg/compiler/lib/src/commandline_options.dart
@@ -84,6 +84,10 @@
static const String dillDependencies = '--dill-dependencies';
static const String readData = '--read-data';
static const String writeData = '--write-data';
+ static const String readCodegen = '--read-codegen';
+ static const String writeCodegen = '--write-codegen';
+ static const String codegenShard = '--codegen-shard';
+ static const String codegenShards = '--codegen-shards';
static const String cfeOnly = '--cfe-only';
static const String debugGlobalInference = '--debug-global-inference';
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 852152d..f7c4050 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -6,18 +6,22 @@
import 'package:js_ast/src/precedence.dart' as js show PRIMARY;
+import '../common.dart';
import '../common_elements.dart';
import '../constants/values.dart';
import '../deferred_load.dart';
import '../elements/entities.dart';
import '../elements/types.dart' show DartType, InterfaceType;
import '../inferrer/abstract_value_domain.dart';
+import '../inferrer/types.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
+import '../js_backend/backend.dart';
import '../js_backend/namer.dart';
import '../js_emitter/code_emitter_task.dart' show Emitter;
import '../native/behavior.dart';
import '../serialization/serialization.dart';
+import '../ssa/ssa.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
@@ -57,6 +61,8 @@
Iterable<NativeBehavior> get nativeBehaviors => const [];
Iterable<FunctionEntity> get nativeMethods => const [];
+
+ Iterable<Selector> get oneShotInterceptors => const [];
}
class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@@ -70,6 +76,7 @@
Set<GenericInstantiation> _genericInstantiations;
List<NativeBehavior> _nativeBehaviors;
Set<FunctionEntity> _nativeMethods;
+ Set<Selector> _oneShotInterceptors;
_CodegenImpact();
@@ -85,7 +92,8 @@
this._asyncMarkers,
this._genericInstantiations,
this._nativeBehaviors,
- this._nativeMethods)
+ this._nativeMethods,
+ this._oneShotInterceptors)
: super.internal(dynamicUses, staticUses, typeUses, constantUses);
factory _CodegenImpact.readFromDataSource(DataSource source) {
@@ -126,6 +134,9 @@
emptyAsNull: true);
Set<FunctionEntity> nativeMethods =
source.readMembers<FunctionEntity>(emptyAsNull: true)?.toSet();
+ Set<Selector> oneShotInterceptors = source
+ .readList(() => Selector.readFromDataSource(source), emptyAsNull: true)
+ ?.toSet();
source.end(tag);
return new _CodegenImpact.internal(
dynamicUses,
@@ -139,7 +150,8 @@
asyncMarkers,
genericInstantiations,
nativeBehaviors,
- nativeMethods);
+ nativeMethods,
+ oneShotInterceptors);
}
@override
@@ -172,6 +184,9 @@
(NativeBehavior behavior) => behavior.writeToDataSink(sink),
allowNull: true);
sink.writeMembers(_nativeMethods, allowNull: true);
+ sink.writeList(_oneShotInterceptors,
+ (Selector selector) => selector.writeToDataSink(sink),
+ allowNull: true);
sink.end(tag);
}
@@ -267,6 +282,16 @@
return _nativeMethods ?? const [];
}
+ void registerOneShotInterceptor(Selector selector) {
+ _oneShotInterceptors ??= {};
+ _oneShotInterceptors.add(selector);
+ }
+
+ @override
+ Iterable<Selector> get oneShotInterceptors {
+ return _oneShotInterceptors ?? const [];
+ }
+
@override
String toString() {
StringBuffer sb = new StringBuffer();
@@ -290,6 +315,7 @@
add('genericInstantiations', genericInstantiations);
add('nativeBehaviors', nativeBehaviors);
add('nativeMethods', nativeMethods);
+ add('oneShotInterceptors', oneShotInterceptors);
return sb.toString();
}
@@ -348,6 +374,10 @@
_worldImpact.registerSpecializedGetInterceptor(classes);
}
+ void registerOneShotInterceptor(Selector selector) {
+ _worldImpact.registerOneShotInterceptor(selector);
+ }
+
void registerUseInterceptor() {
_worldImpact.registerUseInterceptor();
}
@@ -388,6 +418,58 @@
}
}
+/// Interface for reading the code generation results for all [MemberEntity]s.
+abstract class CodegenResults {
+ GlobalTypeInferenceResults get globalTypeInferenceResults;
+ CodegenInputs get codegenInputs;
+ CodegenResult getCodegenResults(MemberEntity member);
+}
+
+/// Code generation results computed on-demand.
+///
+/// This is used in the non-modular codegen enqueuer driving code generation.
+class OnDemandCodegenResults extends CodegenResults {
+ @override
+ final GlobalTypeInferenceResults globalTypeInferenceResults;
+ @override
+ final CodegenInputs codegenInputs;
+ final SsaFunctionCompiler _functionCompiler;
+
+ OnDemandCodegenResults(this.globalTypeInferenceResults, this.codegenInputs,
+ this._functionCompiler);
+
+ @override
+ CodegenResult getCodegenResults(MemberEntity member) {
+ return _functionCompiler.compile(member);
+ }
+}
+
+/// Deserialized code generation results.
+///
+/// This is used for modular code generation.
+class DeserializedCodegenResults extends CodegenResults {
+ @override
+ final GlobalTypeInferenceResults globalTypeInferenceResults;
+ @override
+ final CodegenInputs codegenInputs;
+
+ final Map<MemberEntity, CodegenResult> _map;
+
+ DeserializedCodegenResults(
+ this.globalTypeInferenceResults, this.codegenInputs, this._map);
+
+ @override
+ CodegenResult getCodegenResults(MemberEntity member) {
+ CodegenResult result = _map[member];
+ if (result == null) {
+ failedAt(member,
+ "No codegen results from $member (${identityHashCode(member)}).");
+ }
+ return result;
+ }
+}
+
+/// The code generation result for a single [MemberEntity].
class CodegenResult {
static const String tag = 'codegen-result';
@@ -481,8 +563,8 @@
case ModularNameKind.nameForGetInterceptor:
name.value = namer.nameForGetInterceptor(name.set);
break;
- case ModularNameKind.nameForGetOneShotInterceptor:
- name.value = namer.nameForGetOneShotInterceptor(name.data, name.set);
+ case ModularNameKind.nameForOneShotInterceptor:
+ name.value = namer.nameForOneShotInterceptor(name.data, name.set);
break;
case ModularNameKind.asName:
name.value = namer.asName(name.data);
@@ -556,7 +638,7 @@
globalPropertyNameForType,
globalPropertyNameForMember,
nameForGetInterceptor,
- nameForGetOneShotInterceptor,
+ nameForOneShotInterceptor,
asName,
}
@@ -611,7 +693,7 @@
case ModularNameKind.nameForGetInterceptor:
set = source.readClasses().toSet();
break;
- case ModularNameKind.nameForGetOneShotInterceptor:
+ case ModularNameKind.nameForOneShotInterceptor:
data = Selector.readFromDataSource(source);
set = source.readClasses().toSet();
break;
@@ -663,7 +745,7 @@
case ModularNameKind.nameForGetInterceptor:
sink.writeClasses(set);
break;
- case ModularNameKind.nameForGetOneShotInterceptor:
+ case ModularNameKind.nameForOneShotInterceptor:
Selector selector = data;
selector.writeToDataSink(sink);
sink.writeClasses(set);
@@ -1014,7 +1096,10 @@
}
void _writeInfo(js.Node node) {
- SourceInformation.writeToDataSink(sink, node.sourceInformation);
+ sink.writeCached<SourceInformation>(node.sourceInformation,
+ (SourceInformation sourceInformation) {
+ SourceInformation.writeToDataSink(sink, sourceInformation);
+ });
}
@override
@@ -2009,7 +2094,9 @@
break;
}
SourceInformation sourceInformation =
- SourceInformation.readFromDataSource(source);
+ source.readCached<SourceInformation>(() {
+ return SourceInformation.readFromDataSource(source);
+ });
if (sourceInformation != null) {
node = node.withSourceInformation(sourceInformation);
}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index a0b1e01..85057ab 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -11,6 +11,7 @@
import '../compiler_new.dart' as api;
import 'backend_strategy.dart';
+import 'common/codegen.dart';
import 'common/names.dart' show Selectors, Uris;
import 'common/tasks.dart' show CompilerTask, GenericTask, Measurer;
import 'common/work.dart' show WorkItem;
@@ -171,7 +172,8 @@
enqueuer,
dumpInfoTask = new DumpInfoTask(this),
selfTask,
- serializationTask = new SerializationTask(this, measurer),
+ serializationTask = new SerializationTask(
+ options, reporter, provider, outputProvider, measurer),
];
tasks.addAll(backend.tasks);
@@ -227,13 +229,14 @@
reporter.log('Compiling $uri (${options.buildId})');
if (options.readDataUri != null) {
- GlobalTypeInferenceResults results =
- await serializationTask.deserialize();
+ GlobalTypeInferenceResults globalTypeInferenceResults =
+ await serializationTask.deserializeGlobalTypeInference(
+ environment, abstractValueStrategy);
if (options.debugGlobalInference) {
- performGlobalTypeInference(results.closedWorld);
+ performGlobalTypeInference(globalTypeInferenceResults.closedWorld);
return;
}
- emitJavaScriptCode(results);
+ await generateJavaScriptCode(globalTypeInferenceResults);
} else {
KernelResult result = await kernelLoader.load(uri);
reporter.log("Kernel load complete");
@@ -263,6 +266,31 @@
}
}
+ void generateJavaScriptCode(
+ GlobalTypeInferenceResults globalTypeInferenceResults) async {
+ JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+ backendStrategy.registerJClosedWorld(closedWorld);
+ if (options.showInternalProgress) reporter.log('Compiling...');
+ phase = PHASE_COMPILING;
+ CodegenInputs codegenInputs =
+ backend.onCodegenStart(globalTypeInferenceResults);
+
+ if (options.readCodegenUri != null) {
+ CodegenResults codegenResults =
+ await serializationTask.deserializeCodegen(
+ backendStrategy, globalTypeInferenceResults, codegenInputs);
+ runCodegenEnqueuer(codegenResults);
+ } else {
+ CodegenResults codegenResults = new OnDemandCodegenResults(
+ globalTypeInferenceResults, codegenInputs, backend.functionCompiler);
+ if (options.writeCodegenUri != null) {
+ serializationTask.serializeCodegen(backendStrategy, codegenResults);
+ } else {
+ runCodegenEnqueuer(codegenResults);
+ }
+ }
+ }
+
/// Clear the internal compiler state to prevent memory leaks when invoking
/// the compiler multiple times (e.g. in batch mode).
// TODO(ahe): implement a better mechanism where we can store
@@ -355,16 +383,13 @@
mainFunction, closedWorld, inferredDataBuilder);
}
- void emitJavaScriptCode(GlobalTypeInferenceResults globalInferenceResults) {
+ void runCodegenEnqueuer(CodegenResults codegenResults) {
+ GlobalTypeInferenceResults globalInferenceResults =
+ codegenResults.globalTypeInferenceResults;
JClosedWorld closedWorld = globalInferenceResults.closedWorld;
- backendStrategy.registerJClosedWorld(closedWorld);
- if (options.showInternalProgress) reporter.log('Compiling...');
- phase = PHASE_COMPILING;
-
- CodegenInputs codegen = backend.onCodegenStart(globalInferenceResults);
- backend.onCodegenEnqueuerStart(globalInferenceResults, codegen);
+ CodegenInputs codegenInputs = codegenResults.codegenInputs;
Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(
- closedWorld, globalInferenceResults, codegen);
+ closedWorld, globalInferenceResults, codegenInputs, codegenResults);
_codegenWorldBuilder = codegenEnqueuer.worldBuilder;
FunctionEntity mainFunction = closedWorld.elementEnvironment.mainFunction;
@@ -376,14 +401,14 @@
codegenWorldForTesting = codegenWorld;
}
int programSize = backend.assembleProgram(closedWorld,
- globalInferenceResults.inferredData, codegen, codegenWorld);
+ globalInferenceResults.inferredData, codegenInputs, codegenWorld);
if (options.dumpInfo) {
dumpInfoTask.reportSize(programSize);
dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
}
- backend.onCodegenEnd(codegen);
+ backend.onCodegenEnd(codegenInputs);
checkQueue(codegenEnqueuer);
}
@@ -398,7 +423,8 @@
GlobalTypeInferenceResults globalInferenceResults =
performGlobalTypeInference(closedWorld);
if (options.writeDataUri != null) {
- serializationTask.serialize(globalInferenceResults);
+ serializationTask
+ .serializeGlobalTypeInference(globalInferenceResults);
return;
}
if (options.testMode) {
@@ -416,7 +442,7 @@
worldData);
}
if (stopAfterTypeInference) return;
- emitJavaScriptCode(globalInferenceResults);
+ generateJavaScriptCode(globalInferenceResults);
}
});
}
diff --git a/pkg/compiler/lib/src/constants/values.dart b/pkg/compiler/lib/src/constants/values.dart
index c10956f..67b4c3f 100644
--- a/pkg/compiler/lib/src/constants/values.dart
+++ b/pkg/compiler/lib/src/constants/values.dart
@@ -27,7 +27,8 @@
TYPE,
INTERCEPTOR,
JS_NAME,
- ABSTRACT_VALUE,
+ DUMMY_INTERCEPTOR,
+ UNREACHABLE,
INSTANTIATION,
DEFERRED_GLOBAL,
NON_CONSTANT,
@@ -50,8 +51,10 @@
R visitType(covariant TypeConstantValue constant, covariant A arg);
R visitInterceptor(
covariant InterceptorConstantValue constant, covariant A arg);
- R visitAbstractValue(
- covariant AbstractValueConstantValue constant, covariant A arg);
+ R visitDummyInterceptor(
+ covariant DummyInterceptorConstantValue constant, covariant A arg);
+ R visitUnreachable(
+ covariant UnreachableConstantValue constant, covariant A arg);
R visitJsName(covariant JsNameConstantValue constant, covariant A arg);
R visitDeferredGlobal(
covariant DeferredGlobalConstantValue constant, covariant A arg);
@@ -850,19 +853,19 @@
String toStructuredText() => 'JsNameConstant(${name})';
}
-/// An abstract value as a constant value. This is only used during code
-/// generation.
-class AbstractValueConstantValue extends ConstantValue {
+/// A constant used as the dummy interceptor value for intercepted calls with
+/// a known non-interceptor target.
+class DummyInterceptorConstantValue extends ConstantValue {
final AbstractValue abstractValue;
- AbstractValueConstantValue(this.abstractValue);
+ DummyInterceptorConstantValue(this.abstractValue);
@override
bool get isDummy => true;
@override
bool operator ==(other) {
- return other is AbstractValueConstantValue &&
+ return other is DummyInterceptorConstantValue &&
abstractValue == other.abstractValue;
}
@@ -874,20 +877,49 @@
@override
accept(ConstantValueVisitor visitor, arg) {
- return visitor.visitAbstractValue(this, arg);
+ return visitor.visitDummyInterceptor(this, arg);
}
@override
DartType getType(CommonElements types) => types.dynamicType;
@override
- ConstantValueKind get kind => ConstantValueKind.ABSTRACT_VALUE;
+ ConstantValueKind get kind => ConstantValueKind.DUMMY_INTERCEPTOR;
@override
- String toDartText() => 'abstract_value($abstractValue)';
+ String toDartText() => 'dummy_interceptor($abstractValue)';
@override
- String toStructuredText() => 'AbstractValueConstant($abstractValue)';
+ String toStructuredText() => 'DummyInterceptorConstant($abstractValue)';
+}
+
+// A constant with an empty type used in [HInstruction]s of an expression
+// in an unreachable context.
+class UnreachableConstantValue extends ConstantValue {
+ const UnreachableConstantValue();
+
+ @override
+ bool get isDummy => true;
+
+ @override
+ List<ConstantValue> getDependencies() => const <ConstantValue>[];
+
+ @override
+ accept(ConstantValueVisitor visitor, arg) {
+ return visitor.visitUnreachable(this, arg);
+ }
+
+ @override
+ DartType getType(CommonElements types) => types.dynamicType;
+
+ @override
+ ConstantValueKind get kind => ConstantValueKind.UNREACHABLE;
+
+ @override
+ String toDartText() => 'unreachable()';
+
+ @override
+ String toStructuredText() => 'UnreachableConstant()';
}
class ConstructedConstantValue extends ObjectConstantValue {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index ebdc6a0..7348d20 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -110,6 +110,10 @@
Uri sourceMapOut;
Uri readDataUri;
Uri writeDataUri;
+ Uri readCodegenUri;
+ Uri writeCodegenUri;
+ int codegenShard;
+ int codegenShards;
List<String> bazelPaths;
Uri packageConfig = null;
Uri packageRoot = null;
@@ -129,7 +133,8 @@
int optimizationLevel = null;
Uri platformBinaries;
Map<String, String> environment = new Map<String, String>();
- CompilationStrategy compilationStrategy = CompilationStrategy.direct;
+ ReadStrategy readStrategy = ReadStrategy.fromDart;
+ WriteStrategy writeStrategy = WriteStrategy.toJs;
void passThrough(String argument) => options.add(argument);
void ignoreOption(String argument) {}
@@ -246,13 +251,12 @@
}
void setReadData(String argument) {
- if (compilationStrategy == CompilationStrategy.toData) {
- fail("Cannot read and write serialized simultaneously.");
- }
if (argument != Flags.readData) {
readDataUri = nativeToUri(extractPath(argument, isDirectory: false));
}
- compilationStrategy = CompilationStrategy.fromData;
+ if (readStrategy != ReadStrategy.fromCodegen) {
+ readStrategy = ReadStrategy.fromData;
+ }
}
void setDillDependencies(String argument) {
@@ -263,17 +267,58 @@
}
void setCfeOnly(String argument) {
- compilationStrategy = CompilationStrategy.toKernel;
+ if (writeStrategy == WriteStrategy.toData) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and write serialized data simultaneously.");
+ }
+ if (writeStrategy == WriteStrategy.toCodegen) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and write serialized codegen simultaneously.");
+ }
+ writeStrategy = WriteStrategy.toKernel;
+ }
+
+ void setReadCodegen(String argument) {
+ if (argument != Flags.readCodegen) {
+ readCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+ }
+ readStrategy = ReadStrategy.fromCodegen;
}
void setWriteData(String argument) {
- if (compilationStrategy == CompilationStrategy.fromData) {
- fail("Cannot read and write serialized simultaneously.");
+ if (writeStrategy == WriteStrategy.toKernel) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and write serialized data simultaneously.");
+ }
+ if (writeStrategy == WriteStrategy.toCodegen) {
+ fail("Cannot write serialized data and codegen simultaneously.");
}
if (argument != Flags.writeData) {
writeDataUri = nativeToUri(extractPath(argument, isDirectory: false));
}
- compilationStrategy = CompilationStrategy.toData;
+ writeStrategy = WriteStrategy.toData;
+ }
+
+ void setWriteCodegen(String argument) {
+ if (writeStrategy == WriteStrategy.toKernel) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and write serialized codegen simultaneously.");
+ }
+ if (writeStrategy == WriteStrategy.toData) {
+ fail("Cannot write serialized data and codegen data simultaneously.");
+ }
+ if (argument != Flags.writeCodegen) {
+ writeCodegenUri = nativeToUri(extractPath(argument, isDirectory: false));
+ }
+ writeStrategy = WriteStrategy.toCodegen;
+ }
+
+ void setCodegenShard(String argument) {
+ codegenShard = int.parse(extractParameter(argument));
+ }
+
+ void setCodegenShards(String argument) {
+ codegenShards = int.parse(extractParameter(argument));
}
void setDumpInfo(String argument) {
@@ -349,6 +394,12 @@
new OptionHandler('${Flags.dillDependencies}=.+', setDillDependencies),
new OptionHandler('${Flags.readData}|${Flags.readData}=.+', setReadData),
new OptionHandler('${Flags.writeData}|${Flags.writeData}=.+', setWriteData),
+ new OptionHandler(
+ '${Flags.readCodegen}|${Flags.readCodegen}=.+', setReadCodegen),
+ new OptionHandler(
+ '${Flags.writeCodegen}|${Flags.writeCodegen}=.+', setWriteCodegen),
+ new OptionHandler('${Flags.codegenShard}=.+', setCodegenShard),
+ new OptionHandler('${Flags.codegenShards}=.+', setCodegenShards),
new OptionHandler(Flags.cfeOnly, setCfeOnly),
new OptionHandler(Flags.debugGlobalInference, passThrough),
new OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
@@ -511,28 +562,86 @@
String scriptName = arguments[0];
- switch (compilationStrategy) {
- case CompilationStrategy.direct:
+ switch (writeStrategy) {
+ case WriteStrategy.toJs:
out ??= currentDirectory.resolve('out.js');
break;
- case CompilationStrategy.toKernel:
+ case WriteStrategy.toKernel:
out ??= currentDirectory.resolve('out.dill');
options.add(Flags.cfeOnly);
+ if (readStrategy == ReadStrategy.fromData) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and read serialized data simultaneously.");
+ } else if (readStrategy == ReadStrategy.fromCodegen) {
+ fail("Cannot use ${Flags.cfeOnly} "
+ "and read serialized codegen simultaneously.");
+ }
break;
- case CompilationStrategy.toData:
+ case WriteStrategy.toData:
out ??= currentDirectory.resolve('out.dill');
writeDataUri ??= currentDirectory.resolve('$out.data');
options.add('${Flags.writeData}=${writeDataUri}');
+ if (readStrategy == ReadStrategy.fromData) {
+ fail("Cannot read and write serialized data simultaneously.");
+ } else if (readStrategy == ReadStrategy.fromCodegen) {
+ fail("Cannot read serialized codegen and "
+ "write serialized data simultaneously.");
+ }
break;
- case CompilationStrategy.fromData:
- out ??= currentDirectory.resolve('out.js');
+ case WriteStrategy.toCodegen:
+ // TODO(johnniwinther): Avoid the need for an [out] value in this case or
+ // use [out] to pass [writeCodegenUri].
+ out ??= currentDirectory.resolve('out');
+ writeCodegenUri ??= currentDirectory.resolve('$out.code');
+ options.add('${Flags.writeCodegen}=${writeCodegenUri}');
+ if (readStrategy == ReadStrategy.fromCodegen) {
+ fail("Cannot read and write serialized codegen simultaneously.");
+ }
+ if (readStrategy != ReadStrategy.fromData) {
+ fail("Can only write serialized codegen from serialized data.");
+ }
+ if (codegenShards == null) {
+ fail("Cannot write serialized codegen without setting "
+ "${Flags.codegenShards}.");
+ } else if (codegenShards <= 0) {
+ fail("${Flags.codegenShards} must be a positive integer.");
+ }
+ if (codegenShard == null) {
+ fail("Cannot write serialized codegen without setting "
+ "${Flags.codegenShard}.");
+ } else if (codegenShard < 0 || codegenShard >= codegenShards) {
+ fail("${Flags.codegenShard} must be between 0 and "
+ "${Flags.codegenShards}.");
+ }
+ options.add('${Flags.codegenShard}=$codegenShard');
+ options.add('${Flags.codegenShards}=$codegenShards');
+ break;
+ }
+ switch (readStrategy) {
+ case ReadStrategy.fromDart:
+ break;
+ case ReadStrategy.fromData:
readDataUri ??= currentDirectory.resolve('$scriptName.data');
options.add('${Flags.readData}=${readDataUri}');
break;
+ case ReadStrategy.fromCodegen:
+ readDataUri ??= currentDirectory.resolve('$scriptName.data');
+ options.add('${Flags.readData}=${readDataUri}');
+ readCodegenUri ??= currentDirectory.resolve('$scriptName.code');
+ options.add('${Flags.readCodegen}=${readCodegenUri}');
+ if (codegenShards == null) {
+ fail("Cannot write serialized codegen without setting "
+ "${Flags.codegenShards}.");
+ } else if (codegenShards <= 0) {
+ fail("${Flags.codegenShards} must be a positive integer.");
+ }
+ options.add('${Flags.codegenShards}=$codegenShards');
}
options.add('--out=$out');
- sourceMapOut = Uri.parse('$out.map');
- options.add('--source-map=${sourceMapOut}');
+ if (writeStrategy == WriteStrategy.toJs) {
+ sourceMapOut = Uri.parse('$out.map');
+ options.add('--source-map=${sourceMapOut}');
+ }
RandomAccessFileOutputProvider outputProvider =
new RandomAccessFileOutputProvider(out, sourceMapOut,
@@ -544,86 +653,98 @@
}
writeString(
Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
- switch (compilationStrategy) {
- case CompilationStrategy.direct:
- int dartCharactersRead = inputProvider.dartCharactersRead;
- int jsCharactersWritten =
- outputProvider.totalCharactersWrittenJavaScript;
- int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
- print('Compiled '
- '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
- '${_formatCharacterCount(jsCharactersWritten)} characters '
- 'JavaScript in '
- '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
- diagnosticHandler
- .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
- 'JavaScript in '
- '${relativize(currentDirectory, out, Platform.isWindows)}');
- if (outputSpecified || diagnosticHandler.verbose) {
- String input = uriPathToNative(scriptName);
- String output = relativize(currentDirectory, out, Platform.isWindows);
- print('Dart file ($input) compiled to JavaScript: $output');
- if (diagnosticHandler.verbose) {
- var files = outputProvider.allOutputFiles;
- int jsCount = files.where((f) => f.endsWith('.js')).length;
- print('Emitted file $jsCount JavaScript files.');
- }
- }
+ String input = uriPathToNative(scriptName);
+ int inputSize;
+ String processName;
+ String inputName;
+
+ int outputSize;
+ int primaryOutputSize;
+ String outputName;
+
+ String summary;
+ switch (readStrategy) {
+ case ReadStrategy.fromDart:
+ inputName = 'characters Dart';
+ inputSize = inputProvider.dartCharactersRead;
+ summary = 'Dart file $input ';
break;
- case CompilationStrategy.toKernel:
- int dartCharactersRead = inputProvider.dartCharactersRead;
- int dataBytesWritten = outputProvider.totalDataWritten;
- print('Compiled '
- '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
- '${_formatCharacterCount(dataBytesWritten)} kernel bytes in '
- '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
- String input = uriPathToNative(scriptName);
- String dillOutput =
- relativize(currentDirectory, out, Platform.isWindows);
- print('Dart file ($input) compiled to ${dillOutput}.');
+ case ReadStrategy.fromData:
+ inputName = 'bytes data';
+ inputSize = inputProvider.dartCharactersRead;
+ String dataInput =
+ relativize(currentDirectory, readDataUri, Platform.isWindows);
+ summary = 'Data files $input and $dataInput ';
break;
- case CompilationStrategy.toData:
- int dartCharactersRead = inputProvider.dartCharactersRead;
- int dataBytesWritten = outputProvider.totalDataWritten;
- print('Serialized '
- '${_formatCharacterCount(dartCharactersRead)} characters Dart to '
- '${_formatCharacterCount(dataBytesWritten)} bytes data in '
- '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
- String input = uriPathToNative(scriptName);
- String dillOutput =
- relativize(currentDirectory, out, Platform.isWindows);
+ case ReadStrategy.fromCodegen:
+ inputName = 'bytes data';
+ inputSize = inputProvider.dartCharactersRead;
+ String dataInput =
+ relativize(currentDirectory, readDataUri, Platform.isWindows);
+ String codeInput =
+ relativize(currentDirectory, readCodegenUri, Platform.isWindows);
+ summary = 'Data files $input, $dataInput and '
+ '${codeInput}[0-${codegenShards - 1}] ';
+ break;
+ }
+
+ switch (writeStrategy) {
+ case WriteStrategy.toJs:
+ processName = 'Compiled';
+ outputName = 'characters JavaScript';
+ outputSize = outputProvider.totalCharactersWrittenJavaScript;
+ primaryOutputSize = outputProvider.totalCharactersWrittenPrimary;
+ String output = relativize(currentDirectory, out, Platform.isWindows);
+ summary += 'compiled to JavaScript: ${output}';
+ break;
+ case WriteStrategy.toKernel:
+ processName = 'Compiled';
+ outputName = 'kernel bytes';
+ outputSize = outputProvider.totalDataWritten;
+ String output = relativize(currentDirectory, out, Platform.isWindows);
+ summary += 'compiled to dill: ${output}.';
+ break;
+ case WriteStrategy.toData:
+ processName = 'Serialized';
+ outputName = 'bytes data';
+ outputSize = outputProvider.totalDataWritten;
+ String output = relativize(currentDirectory, out, Platform.isWindows);
String dataOutput =
relativize(currentDirectory, writeDataUri, Platform.isWindows);
- print('Dart file ($input) serialized to '
- '${dillOutput} and ${dataOutput}.');
+ summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
break;
- case CompilationStrategy.fromData:
- int dataCharactersRead = inputProvider.dartCharactersRead;
- int jsCharactersWritten =
- outputProvider.totalCharactersWrittenJavaScript;
- int jsCharactersPrimary = outputProvider.totalCharactersWrittenPrimary;
- print('Compiled '
- '${_formatCharacterCount(dataCharactersRead)} bytes data to '
- '${_formatCharacterCount(jsCharactersWritten)} characters '
- 'JavaScript in '
- '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+ case WriteStrategy.toCodegen:
+ processName = 'Serialized';
+ outputName = 'bytes data';
+ outputSize = outputProvider.totalDataWritten;
+ String codeOutput =
+ relativize(currentDirectory, writeCodegenUri, Platform.isWindows);
+ summary += 'serialized to codegen data: '
+ '${codeOutput}${codegenShard}.';
+ break;
+ }
- diagnosticHandler
- .info('${_formatCharacterCount(jsCharactersPrimary)} characters '
- 'JavaScript in '
- '${relativize(currentDirectory, out, Platform.isWindows)}');
- if (outputSpecified || diagnosticHandler.verbose) {
- String input = uriPathToNative(scriptName);
- String output = relativize(currentDirectory, out, Platform.isWindows);
- print('Dart file ($input) compiled to JavaScript: $output');
- if (diagnosticHandler.verbose) {
- var files = outputProvider.allOutputFiles;
- int jsCount = files.where((f) => f.endsWith('.js')).length;
- print('Emitted file $jsCount JavaScript files.');
- }
+ print('$processName '
+ '${_formatCharacterCount(inputSize)} $inputName to '
+ '${_formatCharacterCount(outputSize)} $outputName in '
+ '${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
+ if (primaryOutputSize != null) {
+ diagnosticHandler
+ .info('${_formatCharacterCount(primaryOutputSize)} $outputName '
+ 'in ${relativize(currentDirectory, out, Platform.isWindows)}');
+ }
+ if (writeStrategy == WriteStrategy.toJs) {
+ if (outputSpecified || diagnosticHandler.verbose) {
+ print(summary);
+ if (diagnosticHandler.verbose) {
+ var files = outputProvider.allOutputFiles;
+ int jsCount = files.where((f) => f.endsWith('.js')).length;
+ print('Emitted file $jsCount JavaScript files.');
}
- break;
+ }
+ } else {
+ print(summary);
}
return result;
@@ -1043,4 +1164,5 @@
});
}
-enum CompilationStrategy { direct, toKernel, toData, fromData }
+enum ReadStrategy { fromDart, fromData, fromCodegen }
+enum WriteStrategy { toKernel, toData, toCodegen, toJs }
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index 5c32df6..118d4ed 100644
--- a/pkg/compiler/lib/src/deferred_load.dart
+++ b/pkg/compiler/lib/src/deferred_load.dart
@@ -1218,6 +1218,23 @@
}
}
+/// Interface for updating an [OutputUnitData] object with data for late
+/// members, that is, members created on demand during code generation.
+class LateOutputUnitDataBuilder {
+ final OutputUnitData _outputUnitData;
+
+ LateOutputUnitDataBuilder(this._outputUnitData);
+
+ /// Registers [newEntity] to be emitted in the same output unit as
+ /// [existingEntity];
+ void registerColocatedMembers(
+ MemberEntity existingEntity, MemberEntity newEntity) {
+ assert(_outputUnitData._memberToUnit[newEntity] == null);
+ _outputUnitData._memberToUnit[newEntity] =
+ _outputUnitData.outputUnitForMember(existingEntity);
+ }
+}
+
/// Results of the deferred loading algorithm.
///
/// Provides information about the output unit associated with entities and
@@ -1393,24 +1410,28 @@
}
/// Returns the [OutputUnit] where [cls] belongs.
- OutputUnit outputUnitForClass(ClassEntity cls) {
+ // TODO(johnniwinther): Remove the need for [allowNull]. Dump-info currently
+ // needs it.
+ OutputUnit outputUnitForClass(ClassEntity cls, {bool allowNull: false}) {
if (!isProgramSplit) return mainOutputUnit;
OutputUnit unit = _classToUnit[cls];
+ assert(allowNull || unit != null, 'No output unit for class $cls');
return unit ?? mainOutputUnit;
}
+ OutputUnit outputUnitForClassForTesting(ClassEntity cls) => _classToUnit[cls];
+
/// Returns the [OutputUnit] where [member] belongs.
OutputUnit outputUnitForMember(MemberEntity member) {
if (!isProgramSplit) return mainOutputUnit;
OutputUnit unit = _memberToUnit[member];
- if (unit != null) return unit;
- if (member.isInstanceMember) {
- return outputUnitForClass(member.enclosingClass);
- }
-
- return mainOutputUnit;
+ assert(unit != null, 'No output unit for member $member');
+ return unit ?? mainOutputUnit;
}
+ OutputUnit outputUnitForMemberForTesting(MemberEntity member) =>
+ _memberToUnit[member];
+
/// Direct access to the output-unit to constants map used for testing.
Iterable<ConstantValue> get constantsForTesting => _constantToUnit.keys;
@@ -1420,6 +1441,9 @@
return _constantToUnit[constant];
}
+ OutputUnit outputUnitForConstantForTesting(ConstantValue constant) =>
+ _constantToUnit[constant];
+
/// Indicates whether [element] is deferred.
bool isDeferredClass(ClassEntity element) {
return outputUnitForClass(element) != mainOutputUnit;
@@ -1456,22 +1480,14 @@
/// Registers that a constant is used in the same deferred output unit as
/// [field].
- void registerConstantDeferredUse(
- DeferredGlobalConstantValue constant, OutputUnit unit) {
+ void registerConstantDeferredUse(DeferredGlobalConstantValue constant) {
if (!isProgramSplit) return;
+ OutputUnit unit = constant.unit;
assert(
_constantToUnit[constant] == null || _constantToUnit[constant] == unit);
_constantToUnit[constant] = unit;
}
- /// Registers [newEntity] to be emitted in the same output unit as
- /// [existingEntity];
- void registerColocatedMembers(
- MemberEntity existingEntity, MemberEntity newEntity) {
- assert(_memberToUnit[newEntity] == null);
- _memberToUnit[newEntity] = outputUnitForMember(existingEntity);
- }
-
/// Returns the unique name for the given deferred [import].
String getImportDeferName(Spannable node, ImportEntity import) {
String name = _importDeferName[import];
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index eec68ab..454d157 100644
--- a/pkg/compiler/lib/src/dump_info.dart
+++ b/pkg/compiler/lib/src/dump_info.dart
@@ -365,7 +365,7 @@
OutputUnitInfo _unitInfoForClass(ClassEntity entity) {
return _infoFromOutputUnit(
- closedWorld.outputUnitData.outputUnitForClass(entity));
+ closedWorld.outputUnitData.outputUnitForClass(entity, allowNull: true));
}
OutputUnitInfo _unitInfoForConstant(ConstantValue constant) {
diff --git a/pkg/compiler/lib/src/elements/indexed.dart b/pkg/compiler/lib/src/elements/indexed.dart
index e83b8a0..6a6afc4 100644
--- a/pkg/compiler/lib/src/elements/indexed.dart
+++ b/pkg/compiler/lib/src/elements/indexed.dart
@@ -56,6 +56,8 @@
/// Base implementation for an index based map of entities of type [E].
abstract class EntityMapBase<E extends _Indexed> {
+ bool _closed = false;
+
int _size = 0;
List<E> _list = <E>[];
@@ -67,6 +69,14 @@
/// Returns the number (null and non-null) entities in the map.
int get length => _list.length;
+
+ /// Closes the entity map, prohibiting further registration.
+ ///
+ /// This is used to ensure that no new entities are added while serializing
+ /// modular code generation data.
+ void close() {
+ _closed = true;
+ }
}
/// Index based map of entities of type [E].
@@ -76,6 +86,8 @@
/// The index of [entity] is set to match its index in the entity list in this
/// map.
E0 register<E0 extends E>(E0 entity) {
+ assert(
+ !_closed, "Trying to register $entity @ ${_list.length} when closed.");
assert(entity != null);
assert(entity._index == null);
entity._index = _list.length;
@@ -134,6 +146,8 @@
/// The index of [entity] is set to match its index in the entity and data
/// lists in this map.
E0 register<E0 extends E, D0 extends D>(E0 entity, D0 data) {
+ assert(
+ !_closed, "Trying to register $entity @ ${_list.length} when closed.");
assert(entity != null);
assert(entity._index == null);
assert(
@@ -199,6 +213,8 @@
/// environment lists in this map.
E0 register<E0 extends E, D0 extends D, V0 extends V>(
E0 entity, D0 data, V0 env) {
+ assert(
+ !_closed, "Trying to register $entity @ ${_list.length} when closed.");
assert(entity != null);
assert(entity._index == null);
assert(
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 5439e6e..81ca07d 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -6,6 +6,7 @@
import 'dart:collection' show Queue;
+import 'common/codegen.dart';
import 'common/tasks.dart' show CompilerTask;
import 'common/work.dart' show WorkItem;
import 'common.dart';
@@ -68,9 +69,10 @@
Enqueuer createCodegenEnqueuer(
JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults,
- CodegenInputs codegen) {
- Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(
- this, compiler, closedWorld, globalInferenceResults, codegen)
+ CodegenInputs codegenInputs,
+ CodegenResults codegenResults) {
+ Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(this, compiler,
+ closedWorld, globalInferenceResults, codegenInputs, codegenResults)
..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
if (retainDataForTesting) {
codegenEnqueuerForTesting = enqueuer;
diff --git a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
index a453382..0994564 100644
--- a/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
+++ b/pkg/compiler/lib/src/inferrer/typemasks/constants.dart
@@ -48,12 +48,18 @@
}
@override
- TypeMask visitAbstractValue(
- AbstractValueConstantValue constant, JClosedWorld closedWorld) {
+ TypeMask visitDummyInterceptor(
+ DummyInterceptorConstantValue constant, JClosedWorld closedWorld) {
return constant.abstractValue;
}
@override
+ TypeMask visitUnreachable(
+ UnreachableConstantValue constant, JClosedWorld closedWorld) {
+ return closedWorld.abstractValueDomain.emptyType;
+ }
+
+ @override
TypeMask visitJsName(JsNameConstantValue constant, JClosedWorld closedWorld) {
return closedWorld.abstractValueDomain.stringType;
}
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index a92ab7e..cb1c2a4 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -12,6 +12,7 @@
import '../js/js_debug.dart';
import '../js/js_source_mapping.dart';
import '../serialization/serialization.dart';
+import '../util/util.dart';
import 'code_output.dart' show BufferedCodeOutput;
import 'source_information.dart';
@@ -34,8 +35,10 @@
factory PositionSourceInformation.readFromDataSource(DataSource source) {
source.begin(tag);
- SourceLocation startPosition = SourceLocation.readFromDataSource(source);
- SourceLocation innerPosition = SourceLocation.readFromDataSource(source);
+ SourceLocation startPosition = source.readCached<SourceLocation>(
+ () => SourceLocation.readFromDataSource(source));
+ SourceLocation innerPosition = source.readCached<SourceLocation>(
+ () => SourceLocation.readFromDataSource(source));
List<FrameContext> inliningContext = source.readList(
() => FrameContext.readFromDataSource(source),
emptyAsNull: true);
@@ -46,8 +49,14 @@
void writeToDataSinkInternal(DataSink sink) {
sink.begin(tag);
- SourceLocation.writeToDataSink(sink, startPosition);
- SourceLocation.writeToDataSink(sink, innerPosition);
+ sink.writeCached(
+ startPosition,
+ (SourceLocation sourceLocation) =>
+ SourceLocation.writeToDataSink(sink, sourceLocation));
+ sink.writeCached(
+ innerPosition,
+ (SourceLocation sourceLocation) =>
+ SourceLocation.writeToDataSink(sink, sourceLocation));
sink.writeList(inliningContext,
(FrameContext context) => context.writeToDataSink(sink),
allowNull: true);
@@ -77,16 +86,17 @@
@override
int get hashCode {
- return 0x7FFFFFFF &
- (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
+ return Hashing.listHash(
+ inliningContext, Hashing.objectsHash(startPosition, innerPosition));
}
@override
bool operator ==(other) {
if (identical(this, other)) return true;
- if (other is! PositionSourceInformation) return false;
- return startPosition == other.startPosition &&
- innerPosition == other.innerPosition;
+ return other is PositionSourceInformation &&
+ startPosition == other.startPosition &&
+ innerPosition == other.innerPosition &&
+ equalElements(inliningContext, other.inliningContext);
}
/// Create a textual representation of the source information using [uriText]
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index bc8f6e7..0034fb5 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -84,8 +84,8 @@
factory FrameContext.readFromDataSource(DataSource source) {
source.begin(tag);
- SourceInformation callInformation =
- SourceInformation.readFromDataSource(source);
+ SourceInformation callInformation = source.readCached<SourceInformation>(
+ () => SourceInformation.readFromDataSource(source));
String inlinedMethodName = source.readString();
source.end(tag);
return new FrameContext(callInformation, inlinedMethodName);
@@ -93,7 +93,10 @@
void writeToDataSink(DataSink sink) {
sink.begin(tag);
- SourceInformation.writeToDataSink(sink, callInformation);
+ sink.writeCached<SourceInformation>(
+ callInformation,
+ (SourceInformation sourceInformation) =>
+ SourceInformation.writeToDataSink(sink, sourceInformation));
sink.writeString(inlinedMethodName);
sink.end(tag);
}
@@ -317,8 +320,8 @@
@override
bool operator ==(other) {
if (identical(this, other)) return true;
- if (other is! SourceLocation) return false;
- return sourceUri == other.sourceUri &&
+ return other is SourceLocation &&
+ sourceUri == other.sourceUri &&
offset == other.offset &&
sourceName == other.sourceName;
}
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index b3768c4..01cad9d 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -1385,8 +1385,9 @@
if (clause is js.Case) {
return new js.Case(
clause.expression, translateToBlock(clause.body));
- } else if (clause is js.Default) {
- return new js.Default(translateToBlock(clause.body));
+ } else {
+ return new js.Default(
+ translateToBlock((clause as js.Default).body));
}
}).toList();
addStatement(new js.Switch(key, cases));
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 79a1ada..d187523 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -30,11 +30,9 @@
import '../universe/class_hierarchy.dart'
show ClassHierarchyBuilder, ClassQueries;
import '../universe/codegen_world_builder.dart';
-import '../universe/selector.dart' show Selector;
import '../universe/world_builder.dart';
import '../universe/world_impact.dart'
show ImpactStrategy, ImpactUseCase, WorldImpact, WorldImpactVisitor;
-import '../util/util.dart';
import '../world.dart' show JClosedWorld;
import 'field_analysis.dart';
import 'annotations.dart';
@@ -84,11 +82,12 @@
final Map<FunctionEntity, int> _cachedDecisions =
new Map<FunctionEntity, int>();
+ final Set<FunctionEntity> _noInlineFunctions = new Set<FunctionEntity>();
final Set<FunctionEntity> _tryInlineFunctions = new Set<FunctionEntity>();
FunctionInlineCache(AnnotationsData annotationsData) {
annotationsData.forEachNoInline((FunctionEntity function) {
- markAsNonInlinable(function);
+ markAsNoInline(function);
});
annotationsData.forEachTryInline((FunctionEntity function) {
markAsTryInline(function);
@@ -174,7 +173,7 @@
case _mustNotInline:
throw failedAt(
element,
- "Can't mark a function as non-inlinable and inlinable at the "
+ "Can't mark $element as non-inlinable and inlinable at the "
"same time.");
case _unknown:
@@ -200,7 +199,7 @@
case _canInlineInLoopMustNotOutside:
throw failedAt(
element,
- "Can't mark a function as non-inlinable and inlinable at the "
+ "Can't mark $element as non-inlinable and inlinable at the "
"same time.");
case _unknown:
@@ -230,7 +229,7 @@
case _canInline:
throw failedAt(
element,
- "Can't mark a function as non-inlinable and inlinable at the "
+ "Can't mark $element as non-inlinable and inlinable at the "
"same time.");
case _mayInlineInLoopMustNotOutside:
@@ -247,7 +246,7 @@
case _canInline:
throw failedAt(
element,
- "Can't mark a function as non-inlinable and inlinable at the "
+ "Can't mark $element as non-inlinable and inlinable at the "
"same time.");
case _unknown:
@@ -272,6 +271,16 @@
}
}
+ void markAsNoInline(FunctionEntity element) {
+ assert(checkFunction(element), failedAt(element));
+ _noInlineFunctions.add(element);
+ }
+
+ bool markedAsNoInline(FunctionEntity element) {
+ assert(checkFunction(element), failedAt(element));
+ return _noInlineFunctions.contains(element);
+ }
+
void markAsTryInline(FunctionEntity element) {
assert(checkFunction(element), failedAt(element));
_tryInlineFunctions.add(element);
@@ -537,7 +546,14 @@
Compiler compiler,
JClosedWorld closedWorld,
GlobalTypeInferenceResults globalInferenceResults,
- CodegenInputs codegen) {
+ CodegenInputs codegen,
+ CodegenResults codegenResults) {
+ OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
+ closedWorld.interceptorData,
+ closedWorld.commonElements,
+ closedWorld.nativeData);
+ _onCodegenEnqueuerStart(
+ globalInferenceResults, codegen, oneShotInterceptorData);
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
CommonElements commonElements = closedWorld.commonElements;
BackendImpacts impacts = new BackendImpacts(commonElements);
@@ -549,8 +565,10 @@
compiler.backendStrategy.createCodegenWorldBuilder(
closedWorld.nativeData,
closedWorld,
- compiler.abstractValueStrategy.createSelectorStrategy()),
- compiler.backendStrategy.createCodegenWorkItemBuilder(closedWorld),
+ compiler.abstractValueStrategy.createSelectorStrategy(),
+ oneShotInterceptorData),
+ compiler.backendStrategy
+ .createCodegenWorkItemBuilder(closedWorld, codegenResults),
new CodegenEnqueuerListener(
elementEnvironment,
commonElements,
@@ -563,10 +581,14 @@
Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
- WorldImpact generateCode(WorkItem work, JClosedWorld closedWorld,
- EntityLookup entityLookup, ComponentLookup componentLookup) {
+ WorldImpact generateCode(
+ WorkItem work,
+ JClosedWorld closedWorld,
+ CodegenResults codegenResults,
+ EntityLookup entityLookup,
+ ComponentLookup componentLookup) {
MemberEntity member = work.element;
- CodegenResult result = functionCompiler.compile(member);
+ CodegenResult result = codegenResults.getCodegenResults(member);
if (compiler.options.testMode) {
bool useDataKinds = true;
List<Object> data = [];
@@ -594,7 +616,6 @@
_codegenImpactTransformer.transformCodegenImpact(result.impact);
compiler.dumpInfoTask.registerImpact(member, worldImpact);
result.applyModularState(_namer, emitterTask.emitter);
- //print('$member:$result');
return worldImpact;
}
@@ -613,9 +634,9 @@
/// Generates the output and returns the total size of the generated code.
int assembleProgram(JClosedWorld closedWorld, InferredData inferredData,
- CodegenInputs codegen, CodegenWorld codegenWorld) {
+ CodegenInputs codegenInputs, CodegenWorld codegenWorld) {
int programSize = emitterTask.assembleProgram(
- _namer, closedWorld, inferredData, codegen, codegenWorld);
+ _namer, closedWorld, inferredData, codegenInputs, codegenWorld);
closedWorld.noSuchMethodData.emitDiagnostic(reporter);
return programSize;
}
@@ -646,10 +667,6 @@
? const MinifiedFixedNames()
: const FixedNames();
- OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
- closedWorld.interceptorData,
- closedWorld.commonElements,
- closedWorld.nativeData);
Tracer tracer = new Tracer(closedWorld, compiler.outputProvider);
RuntimeTypesEncoder rtiEncoder = new RuntimeTypesEncoderImpl(
rtiTags,
@@ -668,7 +685,7 @@
rtiSubstitutions = runtimeTypesImpl;
}
- CodegenInputs codegen = new CodegenInputsImpl(oneShotInterceptorData,
+ CodegenInputs codegen = new CodegenInputsImpl(
rtiSubstitutions, rtiEncoder, tracer, rtiTags, fixedNames);
functionCompiler.initialize(globalTypeInferenceResults, codegen);
@@ -676,9 +693,10 @@
}
/// Called before the compiler starts running the codegen enqueuer.
- void onCodegenEnqueuerStart(
+ void _onCodegenEnqueuerStart(
GlobalTypeInferenceResults globalTypeInferenceResults,
- CodegenInputs codegen) {
+ CodegenInputs codegen,
+ OneShotInterceptorData oneShotInterceptorData) {
JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
RuntimeTypeTags rtiTags = codegen.rtiTags;
FixedNames fixedNames = codegen.fixedNames;
@@ -702,6 +720,7 @@
_codegenImpactTransformer = new CodegenImpactTransformer(
compiler.options,
+ closedWorld,
closedWorld.elementEnvironment,
closedWorld.commonElements,
impacts,
@@ -710,7 +729,7 @@
closedWorld.rtiNeed,
nativeCodegenEnqueuer,
_namer,
- codegen.oneShotInterceptorData,
+ oneShotInterceptorData,
rtiChecksBuilder,
emitterTask.nativeEmitter);
}
@@ -771,38 +790,11 @@
}
}
-class SuperMemberData {
- /// A set of member that are called from subclasses via `super`.
- final Set<MemberEntity> _aliasedSuperMembers = new Setlet<MemberEntity>();
-
- /// Record that [member] is called from a subclass via `super`.
- bool maybeRegisterAliasedSuperMember(MemberEntity member, Selector selector) {
- if (!canUseAliasedSuperMember(member, selector)) {
- // Invoking a super getter isn't supported, this would require changes to
- // compact field descriptors in the emitter.
- return false;
- }
- _aliasedSuperMembers.add(member);
- return true;
- }
-
- bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
- return !selector.isGetter;
- }
-
- /// Returns `true` if [member] is called from a subclass via `super`.
- bool isAliasedSuperMember(MemberEntity member) {
- return _aliasedSuperMembers.contains(member);
- }
-}
-
/// Interface for resources only used during code generation.
abstract class CodegenInputs {
CheckedModeHelpers get checkedModeHelpers;
- OneShotInterceptorData get oneShotInterceptorData;
RuntimeTypesSubstitutions get rtiSubstitutions;
RuntimeTypesEncoder get rtiEncoder;
- SuperMemberData get superMemberData;
Tracer get tracer;
RuntimeTypeTags get rtiTags;
FixedNames get fixedNames;
@@ -813,18 +805,12 @@
final CheckedModeHelpers checkedModeHelpers = new CheckedModeHelpers();
@override
- final OneShotInterceptorData oneShotInterceptorData;
-
- @override
final RuntimeTypesSubstitutions rtiSubstitutions;
@override
final RuntimeTypesEncoder rtiEncoder;
@override
- final SuperMemberData superMemberData = new SuperMemberData();
-
- @override
final Tracer tracer;
@override
@@ -833,6 +819,6 @@
@override
final FixedNames fixedNames;
- CodegenInputsImpl(this.oneShotInterceptorData, this.rtiSubstitutions,
- this.rtiEncoder, this.tracer, this.rtiTags, this.fixedNames);
+ CodegenInputsImpl(this.rtiSubstitutions, this.rtiEncoder, this.tracer,
+ this.rtiTags, this.fixedNames);
}
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 290c803..256d8f1 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -699,7 +699,7 @@
BackendImpact _noSuchMethodSupport;
BackendImpact get noSuchMethodSupport {
- return _noSuchMethodSupport ??= new BackendImpact(staticUses: [
+ return _noSuchMethodSupport ??= new BackendImpact(globalUses: [
_commonElements.createInvocationMirror,
_commonElements.createUnmangledInvocationMirror
], dynamicUses: [
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 96bc202..06ec784 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -144,12 +144,17 @@
}
@override
- jsAst.Expression visitAbstractValue(AbstractValueConstantValue constant,
+ jsAst.Expression visitDummyInterceptor(DummyInterceptorConstantValue constant,
[_]) {
return new jsAst.LiteralNumber('0');
}
@override
+ jsAst.Expression visitUnreachable(UnreachableConstantValue constant, [_]) {
+ return new jsAst.LiteralNumber('0');
+ }
+
+ @override
jsAst.Expression visitJsName(JsNameConstantValue constant, [_]) {
return constant.name;
}
diff --git a/pkg/compiler/lib/src/js_backend/impact_transformer.dart b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
index d4276ff..2084a1d 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -13,6 +13,7 @@
import '../common/resolution.dart' show ResolutionImpact;
import '../common_elements.dart' show ElementEnvironment;
import '../constants/expressions.dart';
+import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
import '../js_emitter/native_emitter.dart';
@@ -20,10 +21,11 @@
import '../native/behavior.dart';
import '../options.dart';
import '../universe/feature.dart';
-import '../universe/use.dart'
- show StaticUse, StaticUseKind, TypeUse, TypeUseKind;
+import '../universe/selector.dart';
+import '../universe/use.dart';
import '../universe/world_impact.dart' show TransformedWorldImpact, WorldImpact;
import '../util/util.dart';
+import '../world.dart';
import 'backend_impact.dart';
import 'backend_usage.dart';
import 'custom_elements_analysis.dart';
@@ -342,6 +344,7 @@
class CodegenImpactTransformer {
final CompilerOptions _options;
+ final JClosedWorld _closedWorld;
final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
final BackendImpacts _impacts;
@@ -356,6 +359,7 @@
CodegenImpactTransformer(
this._options,
+ this._closedWorld,
this._elementEnvironment,
this._commonElements,
this._impacts,
@@ -395,6 +399,17 @@
}
}
+ for (ConstantUse constantUse in impact.constantUses) {
+ switch (constantUse.value.kind) {
+ case ConstantValueKind.DEFERRED_GLOBAL:
+ _closedWorld.outputUnitData
+ .registerConstantDeferredUse(constantUse.value);
+ break;
+ default:
+ break;
+ }
+ }
+
for (Pair<DartType, DartType> check
in impact.typeVariableBoundsSubtypeChecks) {
_rtiChecksBuilder.registerTypeVariableBoundsSubtypeCheck(
@@ -402,12 +417,34 @@
}
for (StaticUse staticUse in impact.staticUses) {
- if (staticUse.kind == StaticUseKind.CALL_METHOD) {
- FunctionEntity callMethod = staticUse.element;
- if (_rtiNeed.methodNeedsSignature(callMethod)) {
- _impacts.computeSignature
- .registerImpact(transformed, _elementEnvironment);
- }
+ switch (staticUse.kind) {
+ case StaticUseKind.CALL_METHOD:
+ FunctionEntity callMethod = staticUse.element;
+ if (_rtiNeed.methodNeedsSignature(callMethod)) {
+ _impacts.computeSignature
+ .registerImpact(transformed, _elementEnvironment);
+ }
+ break;
+ case StaticUseKind.STATIC_TEAR_OFF:
+ case StaticUseKind.INSTANCE_FIELD_GET:
+ case StaticUseKind.INSTANCE_FIELD_SET:
+ case StaticUseKind.SUPER_INVOKE:
+ case StaticUseKind.STATIC_INVOKE:
+ case StaticUseKind.SUPER_FIELD_SET:
+ case StaticUseKind.SUPER_SETTER_SET:
+ case StaticUseKind.STATIC_SET:
+ case StaticUseKind.SUPER_TEAR_OFF:
+ case StaticUseKind.SUPER_GET:
+ case StaticUseKind.STATIC_GET:
+ case StaticUseKind.FIELD_INIT:
+ case StaticUseKind.FIELD_CONSTANT_INIT:
+ case StaticUseKind.CONSTRUCTOR_INVOKE:
+ case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+ case StaticUseKind.DIRECT_INVOKE:
+ case StaticUseKind.INLINING:
+ case StaticUseKind.CLOSURE:
+ case StaticUseKind.CLOSURE_CALL:
+ break;
}
}
@@ -455,6 +492,11 @@
_nativeEmitter.nativeMethods.add(function);
}
+ for (Selector selector in impact.oneShotInterceptors) {
+ _oneShotInterceptorData.registerOneShotInterceptor(
+ selector, _namer, _closedWorld);
+ }
+
// TODO(johnniwinther): Remove eager registration.
return transformed;
}
diff --git a/pkg/compiler/lib/src/js_backend/interceptor_data.dart b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
index b63dae7..db85765 100644
--- a/pkg/compiler/lib/src/js_backend/interceptor_data.dart
+++ b/pkg/compiler/lib/src/js_backend/interceptor_data.dart
@@ -12,6 +12,7 @@
import '../inferrer/abstract_value_domain.dart';
import '../js/js.dart' as jsAst;
import '../serialization/serialization.dart';
+import '../universe/class_set.dart';
import '../universe/selector.dart';
import '../world.dart' show JClosedWorld;
import 'namer.dart' show ModularNamer, suffixForGetInterceptor;
@@ -252,6 +253,7 @@
if (result == null) result = new Set<ClassEntity>();
result.add(subclass);
}
+ return IterationStep.CONTINUE;
});
}
return result;
@@ -388,11 +390,11 @@
String key = suffixForGetInterceptor(_commonElements, _nativeData, classes);
Map<String, OneShotInterceptor> interceptors =
_oneShotInterceptors[selector] ??= {};
- OneShotInterceptor interceptor = interceptors.putIfAbsent(
- key, () => new OneShotInterceptor(key, selector));
+ OneShotInterceptor interceptor =
+ interceptors[key] ??= new OneShotInterceptor(key, selector);
interceptor.classes.addAll(classes);
registerSpecializedGetInterceptor(classes, namer);
- return namer.nameForGetOneShotInterceptor(selector, classes);
+ return namer.nameForOneShotInterceptor(selector, classes);
}
void registerSpecializedGetInterceptor(
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index c59f8f4..709ee76 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -385,7 +385,7 @@
/// Property name used for the one-shot interceptor method for the given
/// [selector] and return-type specialization.
@override
- jsAst.Name nameForGetOneShotInterceptor(
+ jsAst.Name nameForOneShotInterceptor(
Selector selector, Iterable<ClassEntity> classes) {
String root = selector.isOperator
? operatorNameToIdentifier(selector.name)
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index ee53198..c4b1477 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -1323,7 +1323,7 @@
}
@override
- jsAst.Name nameForGetOneShotInterceptor(
+ jsAst.Name nameForOneShotInterceptor(
Selector selector, Iterable<ClassEntity> classes) {
// The one-shot name is a global name derived from the invocation name. To
// avoid instability we would like the names to be unique and not clash with
@@ -1884,8 +1884,13 @@
}
@override
- void visitAbstractValue(AbstractValueConstantValue constant, [_]) {
- add('dummy_receiver');
+ void visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
+ add('dummy_interceptor');
+ }
+
+ @override
+ void visitUnreachable(UnreachableConstantValue constant, [_]) {
+ add('unreachable');
}
@override
@@ -2012,10 +2017,18 @@
}
@override
- int visitAbstractValue(AbstractValueConstantValue constant, [_]) {
+ int visitDummyInterceptor(DummyInterceptorConstantValue constant, [_]) {
throw failedAt(
NO_LOCATION_SPANNABLE,
- 'AbstractValueConstantValue should never be named and '
+ 'DummyInterceptorConstantValue should never be named and '
+ 'never be subconstant');
+ }
+
+ @override
+ int visitUnreachable(UnreachableConstantValue constant, [_]) {
+ throw failedAt(
+ NO_LOCATION_SPANNABLE,
+ 'UnreachableConstantValue should never be named and '
'never be subconstant');
}
@@ -2352,7 +2365,7 @@
/// Property name used for the one-shot interceptor method for the given
/// [selector] and return-type specialization.
- jsAst.Name nameForGetOneShotInterceptor(
+ jsAst.Name nameForOneShotInterceptor(
Selector selector, Set<ClassEntity> classes);
/// Returns the runtime name for [element].
@@ -2736,12 +2749,10 @@
}
@override
- jsAst.Name nameForGetOneShotInterceptor(
+ jsAst.Name nameForOneShotInterceptor(
Selector selector, Set<ClassEntity> classes) {
- jsAst.Name name = new ModularName(
- ModularNameKind.nameForGetOneShotInterceptor,
- data: selector,
- set: classes);
+ jsAst.Name name = new ModularName(ModularNameKind.nameForOneShotInterceptor,
+ data: selector, set: classes);
_registry.registerModularName(name);
return name;
}
diff --git a/pkg/compiler/lib/src/js_backend/namer_names.dart b/pkg/compiler/lib/src/js_backend/namer_names.dart
index f74a30a..f405dc0 100644
--- a/pkg/compiler/lib/src/js_backend/namer_names.dart
+++ b/pkg/compiler/lib/src/js_backend/namer_names.dart
@@ -212,7 +212,7 @@
@override
String get name {
assert(isFinalized, "TokenName($key) has not been finalized.");
- return _name ?? key;
+ return _name;
}
@override
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 3dd3633..fa7a7d1 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -22,6 +22,7 @@
import '../options.dart';
import '../serialization/serialization.dart';
import '../universe/class_hierarchy.dart';
+import '../universe/class_set.dart';
import '../universe/codegen_world_builder.dart';
import '../universe/feature.dart';
import '../universe/selector.dart';
@@ -1525,6 +1526,7 @@
closedWorld.classHierarchy.forEachStrictSubtypeOf(cls,
(ClassEntity sub) {
potentiallyNeedTypeArguments(sub);
+ return IterationStep.CONTINUE;
});
} else if (entity is FunctionEntity) {
methodsNeedingTypeArguments.add(entity);
diff --git a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
index f0ed8a1..5393c9b 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -107,10 +107,10 @@
Namer namer,
JClosedWorld closedWorld,
InferredData inferredData,
- CodegenInputs codegen,
+ CodegenInputs codegenInputs,
CodegenWorld codegenWorld) {
return measure(() {
- _finalizeRti(codegen, codegenWorld);
+ _finalizeRti(codegenInputs, codegenWorld);
ProgramBuilder programBuilder = new ProgramBuilder(
_compiler.options,
_compiler.reporter,
@@ -123,10 +123,9 @@
closedWorld.nativeData,
closedWorld.rtiNeed,
closedWorld.interceptorData,
- codegen.superMemberData,
typeTestRegistry.rtiChecks,
- codegen.rtiEncoder,
- codegen.oneShotInterceptorData,
+ codegenInputs.rtiEncoder,
+ codegenWorld.oneShotInterceptorData,
_backend.customElementsCodegenAnalysis,
_backend.generatedCode,
namer,
diff --git a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
index fb1a792..f205845 100644
--- a/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
+++ b/pkg/compiler/lib/src/js_emitter/constant_ordering.dart
@@ -31,7 +31,7 @@
int compareValues(ConstantValue a, ConstantValue b) {
if (identical(a, b)) return 0;
- int r = _KindVisitor.kind(a).compareTo(_KindVisitor.kind(b));
+ int r = a.kind.index.compareTo(b.kind.index);
if (r != 0) return r;
return a.accept(this, b);
}
@@ -168,8 +168,14 @@
}
@override
- int visitAbstractValue(
- AbstractValueConstantValue a, AbstractValueConstantValue b) {
+ int visitDummyInterceptor(
+ DummyInterceptorConstantValue a, DummyInterceptorConstantValue b) {
+ // Never emitted.
+ return 0;
+ }
+
+ @override
+ int visitUnreachable(UnreachableConstantValue a, UnreachableConstantValue b) {
// Never emitted.
return 0;
}
@@ -197,66 +203,6 @@
}
}
-class _KindVisitor implements ConstantValueVisitor<int, Null> {
- const _KindVisitor();
-
- static const int FUNCTION = 1;
- static const int NULL = 2;
- static const int INT = 3;
- static const int DOUBLE = 4;
- static const int BOOL = 5;
- static const int STRING = 6;
- static const int LIST = 7;
- static const int SET = 8;
- static const int MAP = 9;
- static const int CONSTRUCTED = 10;
- static const int TYPE = 11;
- static const int INTERCEPTOR = 12;
- static const int ABSTRACT_VALUE = 13;
- static const int JS_NAME = 14;
- static const int DEFERRED_GLOBAL = 15;
- static const int NONCONSTANT = 16;
- static const int INSTANTIATION = 17;
-
- static int kind(ConstantValue constant) =>
- constant.accept(const _KindVisitor(), null);
-
- @override
- int visitFunction(FunctionConstantValue a, _) => FUNCTION;
- @override
- int visitNull(NullConstantValue a, _) => NULL;
- @override
- int visitNonConstant(NonConstantValue a, _) => NONCONSTANT;
- @override
- int visitInt(IntConstantValue a, _) => INT;
- @override
- int visitDouble(DoubleConstantValue a, _) => DOUBLE;
- @override
- int visitBool(BoolConstantValue a, _) => BOOL;
- @override
- int visitString(StringConstantValue a, _) => STRING;
- @override
- int visitList(ListConstantValue a, _) => LIST;
- @override
- int visitSet(SetConstantValue a, _) => SET;
- @override
- int visitMap(MapConstantValue a, _) => MAP;
- @override
- int visitConstructed(ConstructedConstantValue a, _) => CONSTRUCTED;
- @override
- int visitType(TypeConstantValue a, _) => TYPE;
- @override
- int visitInterceptor(InterceptorConstantValue a, _) => INTERCEPTOR;
- @override
- int visitAbstractValue(AbstractValueConstantValue a, _) => ABSTRACT_VALUE;
- @override
- int visitJsName(JsNameConstantValue a, _) => JS_NAME;
- @override
- int visitDeferredGlobal(DeferredGlobalConstantValue a, _) => DEFERRED_GLOBAL;
- @override
- int visitInstantiation(InstantiationConstantValue a, _) => INSTANTIATION;
-}
-
/// Visitor for distinguishing types by kind.
class _DartTypeKindVisitor extends DartTypeVisitor<int, Null> {
const _DartTypeKindVisitor();
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 10ebf1d..0cc2993 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -20,7 +20,6 @@
import '../../js/js.dart' as js;
import '../../js_backend/field_analysis.dart'
show FieldAnalysisData, JFieldAnalysis;
-import '../../js_backend/backend.dart' show SuperMemberData;
import '../../js_backend/backend_usage.dart';
import '../../js_backend/custom_elements_analysis.dart';
import '../../js_backend/inferred_data.dart';
@@ -68,7 +67,6 @@
final NativeData _nativeData;
final RuntimeTypesNeed _rtiNeed;
final InterceptorData _interceptorData;
- final SuperMemberData _superMemberData;
final RuntimeTypesChecks _rtiChecks;
final RuntimeTypesEncoder _rtiEncoder;
final OneShotInterceptorData _oneShotInterceptorData;
@@ -111,7 +109,6 @@
this._nativeData,
this._rtiNeed,
this._interceptorData,
- this._superMemberData,
this._rtiChecks,
this._rtiEncoder,
this._oneShotInterceptorData,
@@ -887,7 +884,7 @@
bool canBeApplied = _methodCanBeApplied(element);
- js.Name aliasName = _superMemberData.isAliasedSuperMember(element)
+ js.Name aliasName = _codegenWorld.isAliasedSuperMember(element)
? _namer.aliasedSuperMemberPropertyName(element)
: null;
@@ -1136,7 +1133,7 @@
Map<js.Name, OneShotInterceptor> interceptorMap = {};
for (OneShotInterceptor interceptor
in _oneShotInterceptorData.oneShotInterceptors) {
- js.Name name = _namer.nameForGetOneShotInterceptor(
+ js.Name name = _namer.nameForOneShotInterceptor(
interceptor.selector, interceptor.classes);
names.add(name);
assert(
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index bb595f5..9a39986 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -628,6 +628,7 @@
@override
JFunction callMethod;
+ @override
JSignatureMethod signatureMethod;
@override
final Local closureEntity;
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 5356e84..cde245a 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -19,6 +19,7 @@
import '../constants/evaluation.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
+import '../deferred_load.dart';
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import '../elements/indexed.dart';
@@ -127,6 +128,8 @@
Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
+ LateOutputUnitDataBuilder lateOutputUnitDataBuilder;
+
JsKernelToElementMap(
this.reporter,
Environment environment,
@@ -441,6 +444,31 @@
source.end(tag);
}
+ /// Prepares the entity maps for codegen serialization and returns the member
+ /// index limit for early members.
+ ///
+ /// This method creates all late members, such as constructor bodies and
+ /// generator bodies, and closes the entity maps for further registration.
+ int prepareForCodegenSerialization() {
+ int length = members.length;
+ for (int memberIndex = 0; memberIndex < length; memberIndex++) {
+ MemberEntity member = members.getEntity(memberIndex);
+ if (member == null) continue;
+ if (member is JGenerativeConstructor) {
+ getConstructorBody(members.getData(member).definition.node);
+ }
+ if (member is IndexedFunction && member.asyncMarker != AsyncMarker.SYNC) {
+ getGeneratorBody(member);
+ }
+ }
+ libraries.close();
+ classes.close();
+ members.close();
+ typedefs.close();
+ typeVariables.close();
+ return length;
+ }
+
/// Serializes this [JsToElementMap] to [sink].
void writeToDataSink(DataSink sink) {
sink.begin(tag);
@@ -1604,33 +1632,35 @@
@override
FunctionEntity getConstructorBody(ir.Constructor node) {
ConstructorEntity constructor = getConstructor(node);
- return _getConstructorBody(node, constructor);
+ return _getConstructorBody(constructor);
}
- FunctionEntity _getConstructorBody(
- ir.Constructor node, covariant IndexedConstructor constructor) {
+ JConstructorBody _getConstructorBody(IndexedConstructor constructor) {
JConstructorDataImpl data = members.getData(constructor);
if (data.constructorBody == null) {
/// The constructor calls the constructor body with all parameters.
// TODO(johnniwinther): Remove parameters that are not used in the
// constructor body.
ParameterStructure parameterStructure =
- _getParameterStructureFromFunctionNode(node.function);
+ _getParameterStructureFromFunctionNode(data.node.function);
JConstructorBody constructorBody =
createConstructorBody(constructor, parameterStructure);
members.register<IndexedFunction, FunctionData>(
constructorBody,
new ConstructorBodyDataImpl(
- node,
- node.function,
- new SpecialMemberDefinition(node, MemberKind.constructorBody),
+ data.node,
+ data.node.function,
+ new SpecialMemberDefinition(
+ data.node, MemberKind.constructorBody),
data.staticTypes));
IndexedClass cls = constructor.enclosingClass;
JClassEnvImpl classEnv = classes.getEnv(cls);
// TODO(johnniwinther): Avoid this by only including live members in the
// js-model.
classEnv.addConstructorBody(constructorBody);
+ lateOutputUnitDataBuilder.registerColocatedMembers(
+ constructor, constructorBody);
data.constructorBody = constructorBody;
}
return data.constructorBody;
@@ -2079,6 +2109,9 @@
(_injectedClassMembers[function.enclosingClass] ??= <IndexedMember>[])
.add(generatorBody);
}
+ lateOutputUnitDataBuilder.registerColocatedMembers(
+ generatorBody.function, generatorBody);
+ _generatorBodies[function] = generatorBody;
}
return generatorBody;
}
@@ -2616,3 +2649,81 @@
return _elementMap.libraries.getEntity(index);
}
}
+
+/// Enum used for serialization of 'late members', that is, members normally
+/// created on demand, like constructor bodies and generator bodies.
+enum LateMemberKind {
+ constructorBody,
+ generatorBody,
+}
+
+/// Entity reader that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The support encoding corresponds to the encoding generated by the
+/// [ClosedEntityWriter].
+class ClosedEntityReader extends EntityReader {
+ final JsKernelToElementMap _elementMap;
+
+ ClosedEntityReader(this._elementMap);
+
+ @override
+ IndexedMember readMemberFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ int index = source.readInt();
+ if (index == 0) {
+ return _readLateMemberFromDataSource(source, entityLookup);
+ } else {
+ return entityLookup.getMemberByIndex(index - 1);
+ }
+ }
+
+ IndexedMember _readLateMemberFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ LateMemberKind kind = source.readEnum(LateMemberKind.values);
+ switch (kind) {
+ case LateMemberKind.constructorBody:
+ IndexedConstructor constructor = source.readMember();
+ return _elementMap._getConstructorBody(constructor);
+ case LateMemberKind.generatorBody:
+ IndexedFunction function = source.readMember();
+ return _elementMap.getGeneratorBody(function);
+ }
+ throw new UnsupportedError("Unexpected late member kind: $kind.");
+ }
+}
+
+/// Entity writer that supports member entities normally created on-demand, like
+/// constructor bodies and generator bodies.
+///
+/// The generated encoding corresponds to the encoding read by the
+/// [ClosedEntityReader].
+class ClosedEntityWriter extends EntityWriter {
+ final int _earlyMemberIndexLimit;
+
+ final JsKernelToElementMap _elementMap;
+
+ ClosedEntityWriter(this._elementMap, this._earlyMemberIndexLimit);
+
+ @override
+ void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+ if (value.memberIndex >= _earlyMemberIndexLimit) {
+ sink.writeInt(0);
+ _writeLateMemberToDataSink(sink, value);
+ } else {
+ sink.writeInt(value.memberIndex + 1);
+ }
+ }
+
+ void _writeLateMemberToDataSink(DataSink sink, IndexedMember value) {
+ if (value is JConstructorBody) {
+ sink.writeEnum(LateMemberKind.constructorBody);
+ sink.writeMember(value.constructor);
+ } else if (value is JGeneratorBody) {
+ sink.writeEnum(LateMemberKind.generatorBody);
+ sink.writeMember(value.function);
+ } else {
+ throw new UnsupportedError("Unexpected late member $value.");
+ }
+ }
+}
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index ffe37e3..2a64023 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -8,7 +8,7 @@
import '../backend_strategy.dart';
import '../common.dart';
-import '../common/codegen.dart' show CodegenRegistry;
+import '../common/codegen.dart' show CodegenRegistry, CodegenResults;
import '../common/tasks.dart';
import '../common/work.dart';
import '../compiler.dart';
@@ -25,6 +25,7 @@
import '../js/js_source_mapping.dart';
import '../js_backend/backend.dart';
import '../js_backend/inferred_data.dart';
+import '../js_backend/interceptor_data.dart';
import '../js_backend/native_data.dart';
import '../js_backend/namer.dart' show ModularNamer;
import '../js_emitter/code_emitter_task.dart' show ModularEmitter;
@@ -80,8 +81,11 @@
closureDataBuilder,
_compiler.options,
_compiler.abstractValueStrategy);
- return closedWorldBuilder.convertClosedWorld(
+ JClosedWorld jClosedWorld = closedWorldBuilder.convertClosedWorld(
closedWorld, strategy.closureModels, outputUnitData);
+ _elementMap.lateOutputUnitDataBuilder =
+ new LateOutputUnitDataBuilder(jClosedWorld.outputUnitData);
+ return jClosedWorld;
}
@override
@@ -111,12 +115,14 @@
}
@override
- WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld) {
+ WorkItemBuilder createCodegenWorkItemBuilder(
+ JClosedWorld closedWorld, CodegenResults codegenResults) {
assert(_elementMap != null,
"JsBackendStrategy.elementMap has not been created yet.");
return new KernelCodegenWorkItemBuilder(
_compiler.backend,
closedWorld,
+ codegenResults,
new ClosedEntityLookup(_elementMap),
// TODO(johnniwinther): Avoid the need for a [ComponentLookup]. This
// is caused by some type masks holding a kernel node for using in
@@ -128,9 +134,10 @@
CodegenWorldBuilder createCodegenWorldBuilder(
NativeBasicData nativeBasicData,
JClosedWorld closedWorld,
- SelectorConstraintsStrategy selectorConstraintsStrategy) {
+ SelectorConstraintsStrategy selectorConstraintsStrategy,
+ OneShotInterceptorData oneShotInterceptorData) {
return new CodegenWorldBuilderImpl(
- closedWorld, selectorConstraintsStrategy);
+ closedWorld, selectorConstraintsStrategy, oneShotInterceptorData);
}
@override
@@ -143,40 +150,65 @@
JClosedWorld closedWorld, InferredDataBuilder inferredDataBuilder) {
return new TypeGraphInferrer(_compiler, closedWorld, inferredDataBuilder);
}
+
+ @override
+ void prepareCodegenReader(DataSource source) {
+ source.registerEntityReader(new ClosedEntityReader(_elementMap));
+ source.registerEntityLookup(new ClosedEntityLookup(_elementMap));
+ source.registerComponentLookup(
+ new ComponentLookup(_elementMap.programEnv.mainComponent));
+ }
+
+ @override
+ EntityWriter forEachCodegenMember(void Function(MemberEntity member) f) {
+ int earlyMemberIndexLimit = _elementMap.prepareForCodegenSerialization();
+ ClosedEntityWriter entityWriter =
+ new ClosedEntityWriter(_elementMap, earlyMemberIndexLimit);
+ for (int memberIndex = 0;
+ memberIndex < _elementMap.members.length;
+ memberIndex++) {
+ MemberEntity member = _elementMap.members.getEntity(memberIndex);
+ if (member == null || member.isAbstract) continue;
+ f(member);
+ }
+ return entityWriter;
+ }
}
class KernelCodegenWorkItemBuilder implements WorkItemBuilder {
final JavaScriptBackend _backend;
final JClosedWorld _closedWorld;
+ final CodegenResults _codegenResults;
final EntityLookup _entityLookup;
final ComponentLookup _componentLookup;
KernelCodegenWorkItemBuilder(this._backend, this._closedWorld,
- this._entityLookup, this._componentLookup);
+ this._codegenResults, this._entityLookup, this._componentLookup);
@override
WorkItem createWorkItem(MemberEntity entity) {
if (entity.isAbstract) return null;
- return new KernelCodegenWorkItem(
- _backend, _closedWorld, _entityLookup, _componentLookup, entity);
+ return new KernelCodegenWorkItem(_backend, _closedWorld, _codegenResults,
+ _entityLookup, _componentLookup, entity);
}
}
class KernelCodegenWorkItem extends WorkItem {
final JavaScriptBackend _backend;
final JClosedWorld _closedWorld;
+ final CodegenResults _codegenResults;
final EntityLookup _entityLookup;
final ComponentLookup _componentLookup;
@override
final MemberEntity element;
- KernelCodegenWorkItem(this._backend, this._closedWorld, this._entityLookup,
- this._componentLookup, this.element);
+ KernelCodegenWorkItem(this._backend, this._closedWorld, this._codegenResults,
+ this._entityLookup, this._componentLookup, this.element);
@override
WorldImpact run() {
return _backend.generateCode(
- this, _closedWorld, _entityLookup, _componentLookup);
+ this, _closedWorld, _codegenResults, _entityLookup, _componentLookup);
}
}
@@ -189,9 +221,8 @@
final JsToElementMap _elementMap;
final SourceInformationStrategy _sourceInformationStrategy;
- // TODO(johnniwinther,sra): Inlining decisions should not be based on the
- // order in which ssa graphs are built.
FunctionInlineCache _inlineCache;
+ InlineDataCache _inlineDataCache;
KernelSsaBuilder(this._task, this._options, this._reporter,
this._dumpInfoTask, this._elementMap, this._sourceInformationStrategy);
@@ -206,6 +237,9 @@
ModularNamer namer,
ModularEmitter emitter) {
_inlineCache ??= new FunctionInlineCache(closedWorld.annotationsData);
+ _inlineDataCache ??= new InlineDataCache(
+ enableUserAssertions: _options.enableUserAssertions,
+ omitImplicitCasts: _options.omitImplicitChecks);
return _task.measure(() {
KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
_options,
@@ -222,7 +256,8 @@
codegen.tracer,
codegen.rtiEncoder,
_sourceInformationStrategy,
- _inlineCache);
+ _inlineCache,
+ _inlineDataCache);
return builder.build();
});
}
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 6ed9e82..3515770 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -170,6 +170,8 @@
OutputUnitData outputUnitData =
new OutputUnitData.readFromDataSource(source);
+ elementMap.lateOutputUnitDataBuilder =
+ new LateOutputUnitDataBuilder(outputUnitData);
Map<MemberEntity, MemberAccess> memberAccess =
source.readMemberMap(() => new MemberAccess.readFromDataSource(source));
diff --git a/pkg/compiler/lib/src/js_model/js_world_builder.dart b/pkg/compiler/lib/src/js_model/js_world_builder.dart
index b3a59d2..f4d964c 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -108,6 +108,7 @@
.getClassHierarchyNode(closedWorld.commonElements.objectClass)
.forEachSubclass((ClassEntity cls) {
convertClassSet(closedWorld.classHierarchy.getClassSet(cls));
+ return IterationStep.CONTINUE;
}, ClassHierarchyNode.ALL);
Set<MemberEntity> liveInstanceMembers =
@@ -485,6 +486,9 @@
if (entity is KLocalFunction) {
var closureInfo = closureDataLookup.getClosureInfo(entity.node);
result[closureInfo.callMethod] = unit;
+ if (closureInfo.signatureMethod != null) {
+ result[closureInfo.signatureMethod] = unit;
+ }
}
});
return result;
@@ -846,7 +850,11 @@
@override
ConstantValue visitString(StringConstantValue constant, _) => constant;
@override
- ConstantValue visitAbstractValue(AbstractValueConstantValue constant, _) =>
+ ConstantValue visitDummyInterceptor(
+ DummyInterceptorConstantValue constant, _) =>
+ constant;
+ @override
+ ConstantValue visitUnreachable(UnreachableConstantValue constant, _) =>
constant;
@override
ConstantValue visitJsName(JsNameConstantValue constant, _) => constant;
diff --git a/pkg/compiler/lib/src/old_to_new_api.dart b/pkg/compiler/lib/src/old_to_new_api.dart
index 808e242..a5d7c45 100644
--- a/pkg/compiler/lib/src/old_to_new_api.dart
+++ b/pkg/compiler/lib/src/old_to_new_api.dart
@@ -23,6 +23,8 @@
@override
Future<Input> readFromUri(Uri uri, {InputKind inputKind: InputKind.UTF8}) {
+ // The switch handles all enum values, but not null.
+ // ignore: missing_return
return _inputProvider(uri).then((/*String|List<int>*/ data) {
switch (inputKind) {
case InputKind.UTF8:
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 2e4ac4b..acce37c 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -76,6 +76,16 @@
/// If this is set, the compilation stops after type inference.
Uri writeDataUri;
+ /// Location from which codegen data is read.
+ ///
+ /// If this is set, the compilation starts at codegen enqueueing.
+ Uri readCodegenUri;
+
+ /// Location to which codegen data is serialized.
+ ///
+ /// If this is set, the compilation stops after code generation.
+ Uri writeCodegenUri;
+
/// Whether to run only the CFE and emit the generated kernel file in
/// [outputUri].
bool cfeOnly = false;
@@ -325,6 +335,13 @@
/// If specified, a bundle of optimizations to enable (or disable).
int optimizationLevel = null;
+ /// The shard to serialize when using [writeCodegenUri].
+ int codegenShard;
+
+ /// The number of shards to serialize when using [writeCodegenUri] or to
+ /// deserialize when using [readCodegenUri].
+ int codegenShards;
+
// -------------------------------------------------
// Options for deprecated features
// -------------------------------------------------
@@ -407,6 +424,10 @@
_extractUriListOption(options, '${Flags.dillDependencies}')
..readDataUri = _extractUriOption(options, '${Flags.readData}=')
..writeDataUri = _extractUriOption(options, '${Flags.writeData}=')
+ ..readCodegenUri = _extractUriOption(options, '${Flags.readCodegen}=')
+ ..writeCodegenUri = _extractUriOption(options, '${Flags.writeCodegen}=')
+ ..codegenShard = _extractIntOption(options, '${Flags.codegenShard}=')
+ ..codegenShards = _extractIntOption(options, '${Flags.codegenShards}=')
..cfeOnly = _hasOption(options, Flags.cfeOnly)
..debugGlobalInference = _hasOption(options, Flags.debugGlobalInference);
}
@@ -533,10 +554,15 @@
}
Uri _extractUriOption(List<String> options, String prefix) {
- var option = _extractStringOption(options, prefix, null);
+ String option = _extractStringOption(options, prefix, null);
return (option == null) ? null : Uri.parse(option);
}
+int _extractIntOption(List<String> options, String prefix) {
+ String option = _extractStringOption(options, prefix, null);
+ return (option == null) ? null : int.parse(option);
+}
+
bool _hasOption(List<String> options, String option) {
return options.indexOf(option) >= 0;
}
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index ac9d487..a1af8e8 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -34,9 +34,12 @@
Map<Type, IndexedSink> _generalCaches = {};
+ EntityWriter _entityWriter = const EntityWriter();
CodegenWriter _codegenWriter;
- AbstractDataSink({this.useDataKinds: false}) {
+ final Map<String, int> tagFrequencyMap;
+
+ AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
_dartTypeWriter = new DartTypeWriter(this);
_dartTypeNodeWriter = new DartTypeNodeWriter(this);
_stringIndex = new IndexedSink<String>(this);
@@ -47,6 +50,10 @@
@override
void begin(String tag) {
+ if (tagFrequencyMap != null) {
+ tagFrequencyMap[tag] ??= 0;
+ tagFrequencyMap[tag]++;
+ }
if (useDataKinds) {
_tags ??= <String>[];
_tags.add(tag);
@@ -307,22 +314,26 @@
@override
void writeLibrary(IndexedLibrary value) {
- writeInt(value.libraryIndex);
+ _entityWriter.writeLibraryToDataSink(this, value);
}
@override
void writeClass(IndexedClass value) {
- writeInt(value.classIndex);
+ _entityWriter.writeClassToDataSink(this, value);
}
@override
void writeTypedef(IndexedTypedef value) {
- writeInt(value.typedefIndex);
+ _entityWriter.writeTypedefToDataSink(this, value);
}
@override
void writeMember(IndexedMember value) {
- writeInt(value.memberIndex);
+ _entityWriter.writeMemberToDataSink(this, value);
+ }
+
+ void writeTypeVariable(IndexedTypeVariable value) {
+ _entityWriter.writeTypeVariableToDataSink(this, value);
}
@override
@@ -450,10 +461,12 @@
writeConstant(constant.referenced);
writeOutputUnitReference(constant.unit);
break;
- case ConstantValueKind.ABSTRACT_VALUE:
- AbstractValueConstantValue constant = value;
+ case ConstantValueKind.DUMMY_INTERCEPTOR:
+ DummyInterceptorConstantValue constant = value;
writeAbstractValue(constant.abstractValue);
break;
+ case ConstantValueKind.UNREACHABLE:
+ break;
case ConstantValueKind.JS_NAME:
JsNameConstantValue constant = value;
writeJsNode(constant.name);
@@ -488,6 +501,12 @@
}
@override
+ void registerEntityWriter(EntityWriter writer) {
+ assert(writer != null);
+ _entityWriter = writer;
+ }
+
+ @override
void registerCodegenWriter(CodegenWriter writer) {
assert(writer != null);
assert(_codegenWriter == null);
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 87cb765..a2fa583 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -9,6 +9,7 @@
abstract class AbstractDataSource extends DataSourceMixin
implements DataSource {
final bool useDataKinds;
+ EntityReader _entityReader = const EntityReader();
ComponentLookup _componentLookup;
EntityLookup _entityLookup;
LocalLookup _localLookup;
@@ -66,6 +67,12 @@
_localLookup = localLookup;
}
+ @override
+ void registerEntityReader(EntityReader reader) {
+ assert(reader != null);
+ _entityReader = reader;
+ }
+
LocalLookup get localLookup {
assert(_localLookup != null);
return _localLookup;
@@ -79,6 +86,12 @@
}
@override
+ void deregisterCodegenReader(CodegenReader reader) {
+ assert(_codegenReader == reader);
+ _codegenReader = null;
+ }
+
+ @override
E readCached<E>(E f()) {
IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
return source.read(f);
@@ -86,38 +99,27 @@
@override
IndexedLibrary readLibrary() {
- return getIndexedLibrary(readInt());
+ return _entityReader.readLibraryFromDataSource(this, entityLookup);
}
@override
IndexedClass readClass() {
- return getIndexedClass(readInt());
+ return _entityReader.readClassFromDataSource(this, entityLookup);
}
@override
IndexedTypedef readTypedef() {
- return getIndexedTypedef(readInt());
+ return _entityReader.readTypedefFromDataSource(this, entityLookup);
}
@override
IndexedMember readMember() {
- return getIndexedMember(readInt());
+ return _entityReader.readMemberFromDataSource(this, entityLookup);
}
- IndexedLibrary getIndexedLibrary(int libraryIndex) =>
- entityLookup.getLibraryByIndex(libraryIndex);
-
- IndexedClass getIndexedClass(int classIndex) =>
- entityLookup.getClassByIndex(classIndex);
-
- IndexedTypedef getIndexedTypedef(int typedefIndex) =>
- entityLookup.getTypedefByIndex(typedefIndex);
-
- IndexedMember getIndexedMember(int memberIndex) =>
- entityLookup.getMemberByIndex(memberIndex);
-
- IndexedTypeVariable getIndexedTypeVariable(int typeVariableIndex) =>
- entityLookup.getTypeVariableByIndex(typeVariableIndex);
+ IndexedTypeVariable readTypeVariable() {
+ return _entityReader.readTypeVariableFromDataSource(this, entityLookup);
+ }
List<DartType> _readDartTypes(
List<FunctionTypeVariable> functionTypeVariables) {
@@ -164,7 +166,7 @@
case DartTypeKind.voidType:
return const VoidType();
case DartTypeKind.typeVariable:
- return new TypeVariableType(getIndexedTypeVariable(readInt()));
+ return new TypeVariableType(readTypeVariable());
case DartTypeKind.functionTypeVariable:
int index = readInt();
assert(0 <= index && index < functionTypeVariables.length);
@@ -200,11 +202,11 @@
typeVariables);
case DartTypeKind.interfaceType:
- IndexedClass cls = getIndexedClass(readInt());
+ IndexedClass cls = readClass();
List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
return new InterfaceType(cls, typeArguments);
case DartTypeKind.typedef:
- IndexedTypedef typedef = getIndexedTypedef(readInt());
+ IndexedTypedef typedef = readTypedef();
List<DartType> typeArguments = _readDartTypes(functionTypeVariables);
DartType unaliased = _readDartType(functionTypeVariables);
return new TypedefType(typedef, typeArguments, unaliased);
@@ -510,9 +512,11 @@
ConstantValue constant = readConstant();
OutputUnit unit = readOutputUnitReference();
return new DeferredGlobalConstantValue(constant, unit);
- case ConstantValueKind.ABSTRACT_VALUE:
+ case ConstantValueKind.DUMMY_INTERCEPTOR:
AbstractValue abstractValue = readAbstractValue();
- return new AbstractValueConstantValue(abstractValue);
+ return new DummyInterceptorConstantValue(abstractValue);
+ case ConstantValueKind.UNREACHABLE:
+ return const UnreachableConstantValue();
case ConstantValueKind.JS_NAME:
js.LiteralString name = readJsNode();
return new JsNameConstantValue(name);
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 3f771b4..6d46fb4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -12,9 +12,10 @@
BufferedSink _bufferedSink;
int _length = 0;
- BinarySink(this.sink, {bool useDataKinds: false})
+ BinarySink(this.sink,
+ {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
: _bufferedSink = new BufferedSink(sink),
- super(useDataKinds: useDataKinds);
+ super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 40cc83d..b73a8c9 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -130,7 +130,7 @@
List<FunctionTypeVariable> functionTypeVariables) {
_sink.writeEnum(DartTypeKind.typeVariable);
IndexedTypeVariable typeVariable = type.element;
- _sink.writeInt(typeVariable.typeVariableIndex);
+ _sink.writeTypeVariable(typeVariable);
}
@override
@@ -336,6 +336,7 @@
class IndexedSink<E> {
final AbstractDataSink _sink;
final Map<E, int> _cache = {};
+ Set<E> _current = {};
IndexedSink(this._sink);
@@ -346,10 +347,14 @@
void write(E value, void writeValue(E value)) {
int index = _cache[value];
if (index == null) {
+ if (!_current.add(value)) {
+ throw new ArgumentError("Cyclic dependency on cached value: $value");
+ }
index = _cache.length;
- _cache[value] = index;
_sink._writeIntInternal(index);
writeValue(value);
+ _cache[value] = index;
+ _current.remove(value);
} else {
_sink._writeIntInternal(index);
}
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 31376e3..82c8885 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,8 @@
class ObjectSink extends AbstractDataSink {
List<dynamic> _data;
- ObjectSink(this._data, {bool useDataKinds})
- : super(useDataKinds: useDataKinds);
+ ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
+ : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index d4f574c..92e6ad0 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -399,6 +399,10 @@
/// This feature is only available a [CodegenWriter] has been registered.
void writeJsNodeOrNull(js.Node value);
+ /// Register an [EntityWriter] with this data sink for non-default encoding
+ /// of entity references.
+ void registerEntityWriter(EntityWriter writer);
+
/// Register a [CodegenWriter] with this data sink to support serialization
/// of codegen only data.
void registerCodegenWriter(CodegenWriter writer);
@@ -426,13 +430,21 @@
/// deserialization of references to indexed entities.
void registerEntityLookup(EntityLookup entityLookup);
+ /// Registers an [EntityReader] with this data source for non-default encoding
+ /// of entity references.
+ void registerEntityReader(EntityReader reader);
+
/// Registers a [LocalLookup] object with this data source to support
/// deserialization of references to locals.
void registerLocalLookup(LocalLookup localLookup);
/// Registers a [CodegenReader] with this data source to support
/// deserialization of codegen only data.
- void registerCodegenReader(CodegenReader read);
+ void registerCodegenReader(CodegenReader reader);
+
+ /// Unregisters the [CodegenReader] from this data source to remove support
+ /// for deserialization of codegen only data.
+ void deregisterCodegenReader(CodegenReader reader);
/// Reads a reference to an [E] value from this data source. If the value has
/// not yet been deserialized, [f] is called to deserialize the value itself.
@@ -771,6 +783,61 @@
IndexedTypeVariable getTypeVariableByIndex(int index);
}
+/// Decoding strategy for entity references.
+class EntityReader {
+ const EntityReader();
+
+ IndexedLibrary readLibraryFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ return entityLookup.getLibraryByIndex(source.readInt());
+ }
+
+ IndexedClass readClassFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ return entityLookup.getClassByIndex(source.readInt());
+ }
+
+ IndexedTypedef readTypedefFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ return entityLookup.getTypedefByIndex(source.readInt());
+ }
+
+ IndexedMember readMemberFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ return entityLookup.getMemberByIndex(source.readInt());
+ }
+
+ IndexedTypeVariable readTypeVariableFromDataSource(
+ DataSource source, EntityLookup entityLookup) {
+ return entityLookup.getTypeVariableByIndex(source.readInt());
+ }
+}
+
+/// Encoding strategy for entity references.
+class EntityWriter {
+ const EntityWriter();
+
+ void writeLibraryToDataSink(DataSink sink, IndexedLibrary value) {
+ sink.writeInt(value.libraryIndex);
+ }
+
+ void writeClassToDataSink(DataSink sink, IndexedClass value) {
+ sink.writeInt(value.classIndex);
+ }
+
+ void writeTypedefToDataSink(DataSink sink, IndexedTypedef value) {
+ sink.writeInt(value.typedefIndex);
+ }
+
+ void writeMemberToDataSink(DataSink sink, IndexedMember value) {
+ sink.writeInt(value.memberIndex);
+ }
+
+ void writeTypeVariableToDataSink(DataSink sink, IndexedTypeVariable value) {
+ sink.writeInt(value.typeVariableIndex);
+ }
+}
+
/// Interface used for looking up locals by index during deserialization.
abstract class LocalLookup {
Local getLocalByIndex(MemberEntity memberContext, int index);
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 56ab4bd..61771d5 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -7,16 +7,20 @@
import 'package:kernel/binary/ast_from_binary.dart' as ir;
import 'package:kernel/binary/ast_to_binary.dart' as ir;
import '../../compiler_new.dart' as api;
+import '../backend_strategy.dart';
+import '../common/codegen.dart';
import '../common/tasks.dart';
-import '../compiler.dart';
import '../diagnostics/diagnostic_listener.dart';
+import '../elements/entities.dart';
import '../environment.dart';
import '../inferrer/abstract_value_domain.dart';
import '../inferrer/types.dart';
+import '../js_backend/backend.dart';
import '../js_backend/inferred_data.dart';
import '../js_model/js_world.dart';
import '../options.dart';
import '../util/sink_adapter.dart';
+import '../world.dart';
import 'serialization.dart';
void serializeGlobalTypeInferenceResults(
@@ -45,21 +49,26 @@
}
class SerializationTask extends CompilerTask {
- final Compiler compiler;
+ final CompilerOptions _options;
+ final DiagnosticReporter _reporter;
+ final api.CompilerInput _provider;
+ final api.CompilerOutput _outputProvider;
- SerializationTask(this.compiler, Measurer measurer) : super(measurer);
+ SerializationTask(this._options, this._reporter, this._provider,
+ this._outputProvider, Measurer measurer)
+ : super(measurer);
@override
String get name => 'Serialization';
- void serialize(GlobalTypeInferenceResults results) {
+ void serializeGlobalTypeInference(GlobalTypeInferenceResults results) {
measureSubtask('serialize dill', () {
// TODO(sigmund): remove entirely: we will do this immediately as soon as
// we get the component in the kernel/loader.dart task once we refactor
// how we apply our modular kernel transformation for super mixin calls.
- compiler.reporter.log('Writing dill to ${compiler.options.outputUri}');
+ _reporter.log('Writing dill to ${_options.outputUri}');
api.BinaryOutputSink dillOutput =
- compiler.outputProvider.createBinarySink(compiler.options.outputUri);
+ _outputProvider.createBinarySink(_options.outputUri);
JsClosedWorld closedWorld = results.closedWorld;
ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
BinaryOutputSinkAdapter irSink = new BinaryOutputSinkAdapter(dillOutput);
@@ -69,40 +78,99 @@
});
measureSubtask('serialize data', () {
- compiler.reporter.log('Writing data to ${compiler.options.writeDataUri}');
- api.BinaryOutputSink dataOutput = compiler.outputProvider
- .createBinarySink(compiler.options.writeDataUri);
+ _reporter.log('Writing data to ${_options.writeDataUri}');
+ api.BinaryOutputSink dataOutput =
+ _outputProvider.createBinarySink(_options.writeDataUri);
DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
serializeGlobalTypeInferenceResults(results, sink);
});
}
- Future<GlobalTypeInferenceResults> deserialize() async {
+ Future<GlobalTypeInferenceResults> deserializeGlobalTypeInference(
+ Environment environment,
+ AbstractValueStrategy abstractValueStrategy) async {
ir.Component component =
await measureIoSubtask('deserialize dill', () async {
- compiler.reporter.log('Reading dill from ${compiler.options.entryPoint}');
- api.Input<List<int>> dillInput = await compiler.provider.readFromUri(
- compiler.options.entryPoint,
- inputKind: api.InputKind.binary);
+ _reporter.log('Reading dill from ${_options.entryPoint}');
+ api.Input<List<int>> dillInput = await _provider
+ .readFromUri(_options.entryPoint, inputKind: api.InputKind.binary);
ir.Component component = new ir.Component();
new ir.BinaryBuilder(dillInput.data).readComponent(component);
return component;
});
return await measureIoSubtask('deserialize data', () async {
- compiler.reporter
- .log('Reading data from ${compiler.options.readDataUri}');
- api.Input<List<int>> dataInput = await compiler.provider.readFromUri(
- compiler.options.readDataUri,
- inputKind: api.InputKind.binary);
+ _reporter.log('Reading data from ${_options.readDataUri}');
+ api.Input<List<int>> dataInput = await _provider
+ .readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
DataSource source = new BinarySourceImpl(dataInput.data);
- return deserializeGlobalTypeInferenceResults(
- compiler.options,
- compiler.reporter,
- compiler.environment,
- compiler.abstractValueStrategy,
- component,
- source);
+ return deserializeGlobalTypeInferenceResults(_options, _reporter,
+ environment, abstractValueStrategy, component, source);
});
}
+
+ void serializeCodegen(
+ BackendStrategy backendStrategy, CodegenResults codegenResults) {
+ GlobalTypeInferenceResults globalTypeInferenceResults =
+ codegenResults.globalTypeInferenceResults;
+ JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+ int shard = _options.codegenShard;
+ int shards = _options.codegenShards;
+ Map<MemberEntity, CodegenResult> results = {};
+ int index = 0;
+ EntityWriter entityWriter =
+ backendStrategy.forEachCodegenMember((MemberEntity member) {
+ if (index % shards == shard) {
+ CodegenResult codegenResult = codegenResults.getCodegenResults(member);
+ results[member] = codegenResult;
+ }
+ index++;
+ });
+ measureSubtask('serialize codegen', () {
+ Uri uri = Uri.parse('${_options.writeCodegenUri}$shard');
+ api.BinaryOutputSink dataOutput = _outputProvider.createBinarySink(uri);
+ DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+ _reporter.log('Writing data to ${uri}');
+ sink.registerEntityWriter(entityWriter);
+ sink.registerCodegenWriter(new CodegenWriterImpl(closedWorld));
+ sink.writeMemberMap(
+ results, (CodegenResult result) => result.writeToDataSink(sink));
+ sink.close();
+ });
+ }
+
+ Future<CodegenResults> deserializeCodegen(
+ BackendStrategy backendStrategy,
+ GlobalTypeInferenceResults globalTypeInferenceResults,
+ CodegenInputs codegenInputs) async {
+ int shards = _options.codegenShards;
+ JClosedWorld closedWorld = globalTypeInferenceResults.closedWorld;
+ Map<MemberEntity, CodegenResult> results = {};
+ for (int shard = 0; shard < shards; shard++) {
+ Uri uri = Uri.parse('${_options.readCodegenUri}$shard');
+ await measureIoSubtask('deserialize codegen', () async {
+ _reporter.log('Reading data from ${uri}');
+ api.Input<List<int>> dataInput =
+ await _provider.readFromUri(uri, inputKind: api.InputKind.binary);
+ DataSource source = new BinarySourceImpl(dataInput.data);
+ backendStrategy.prepareCodegenReader(source);
+ Map<MemberEntity, CodegenResult> codegenResults =
+ source.readMemberMap(() {
+ List<ModularName> modularNames = [];
+ List<ModularExpression> modularExpressions = [];
+ CodegenReader reader = new CodegenReaderImpl(
+ closedWorld, modularNames, modularExpressions);
+ source.registerCodegenReader(reader);
+ CodegenResult result = CodegenResult.readFromDataSource(
+ source, modularNames, modularExpressions);
+ source.deregisterCodegenReader(reader);
+ return result;
+ });
+ _reporter.log('Read ${codegenResults.length} members from ${uri}');
+ results.addAll(codegenResults);
+ });
+ }
+ return new DeserializedCodegenResults(
+ globalTypeInferenceResults, codegenInputs, results);
+ }
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 67cc980..f0f64ff 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -12,6 +12,7 @@
import '../common_elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
+import '../deferred_load.dart';
import '../dump_info.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
@@ -151,6 +152,7 @@
StackFrame _currentFrame;
final FunctionInlineCache _inlineCache;
+ final InlineDataCache _inlineDataCache;
KernelSsaGraphBuilder(
this.options,
@@ -167,7 +169,8 @@
this._tracer,
this._rtiEncoder,
this._sourceInformationStrategy,
- this._inlineCache)
+ this._inlineCache,
+ this._inlineDataCache)
: this.targetElement = _effectiveTargetElementFor(_initialTargetElement),
this._closureDataLookup = closedWorld.closureDataLookup {
_enterFrame(targetElement, null);
@@ -620,17 +623,11 @@
return _elementMap.getDartType(type);
}
- /// Pops the most recent instruction from the stack and 'boolifies' it.
- ///
- /// Boolification is checking if the value is '=== true'.
+ /// Pops the most recent instruction from the stack and ensures that it is a
+ /// non-null bool.
HInstruction popBoolified() {
HInstruction value = pop();
- if (_typeBuilder.checkOrTrustTypes) {
- return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
- }
- HInstruction result = new HBoolify(value, _abstractValueDomain.boolType);
- add(result);
- return result;
+ return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
}
/// Extend current method parameters with parameters for the class type
@@ -1364,7 +1361,6 @@
}
JGeneratorBody body = _elementMap.getGeneratorBody(function);
- closedWorld.outputUnitData.registerColocatedMembers(function, body);
push(new HInvokeGeneratorBody(
body,
inputs,
@@ -1740,11 +1736,13 @@
_sourceInformationBuilder.buildGet(node);
if (!closedWorld.outputUnitData
.hasOnlyNonDeferredImportPathsToConstant(targetElement, value)) {
+ OutputUnit outputUnit =
+ closedWorld.outputUnitData.outputUnitForConstant(value);
+ ConstantValue deferredConstant =
+ new DeferredGlobalConstantValue(value, outputUnit);
+ registry.registerConstantUse(new ConstantUse.deferred(deferredConstant));
stack.add(graph.addDeferredConstant(
- value,
- closedWorld.outputUnitData.outputUnitForConstant(value),
- sourceInformation,
- closedWorld));
+ deferredConstant, sourceInformation, closedWorld));
} else {
stack.add(graph.addConstant(value, closedWorld,
sourceInformation: sourceInformation));
@@ -2403,8 +2401,8 @@
expressionInstruction,
localsHandler.substInContext(type),
node.isTypeError
- ? HTypeConversion.CHECKED_MODE_CHECK
- : HTypeConversion.CAST_TYPE_CHECK,
+ ? HTypeConversion.TYPE_CHECK
+ : HTypeConversion.CAST_CHECK,
sourceInformation: sourceInformation);
if (converted != expressionInstruction) {
add(converted);
@@ -3303,15 +3301,20 @@
push(new HStatic(field, _typeInferenceMap.getInferredTypeOf(field),
sourceInformation));
} else if (fieldData.isEffectivelyConstant) {
- var unit = closedWorld.outputUnitData.outputUnitForMember(field);
+ OutputUnit outputUnit =
+ closedWorld.outputUnitData.outputUnitForMember(field);
// TODO(sigmund): this is not equivalent to what the old FE does: if
// there is no prefix the old FE wouldn't treat this in any special
// way. Also, if the prefix points to a constant in the main output
// unit, the old FE would still generate a deferred wrapper here.
if (!closedWorld.outputUnitData
.hasOnlyNonDeferredImportPaths(targetElement, field)) {
+ ConstantValue deferredConstant = new DeferredGlobalConstantValue(
+ fieldData.initialValue, outputUnit);
+ registry
+ .registerConstantUse(new ConstantUse.deferred(deferredConstant));
stack.add(graph.addDeferredConstant(
- fieldData.initialValue, unit, sourceInformation, closedWorld));
+ deferredConstant, sourceInformation, closedWorld));
} else {
stack.add(graph.addConstant(fieldData.initialValue, closedWorld,
sourceInformation: sourceInformation));
@@ -3816,9 +3819,9 @@
"Expected 1-2 argument, actual: $arguments."));
HInstruction lengthInput = arguments.first;
if (lengthInput.isNumber(_abstractValueDomain).isPotentiallyFalse) {
- HTypeConversion conversion = new HTypeConversion(
+ HPrimitiveCheck conversion = new HPrimitiveCheck(
_commonElements.numType,
- HTypeConversion.ARGUMENT_TYPE_CHECK,
+ HPrimitiveCheck.ARGUMENT_TYPE_CHECK,
_abstractValueDomain.numType,
lengthInput,
sourceInformation);
@@ -5552,6 +5555,7 @@
// Bail out early if the inlining decision is in the cache and we can't
// inline (no need to check the hard constraints).
+ if (_inlineCache.markedAsNoInline(function)) return false;
bool cachedCanBeInlined =
_inlineCache.canInline(function, insideLoop: insideLoop);
if (cachedCanBeInlined == false) return false;
@@ -5612,26 +5616,22 @@
return true;
}
- bool doesNotContainCode() {
+ bool doesNotContainCode(InlineData inlineData) {
// A function with size 1 does not contain any code.
- return InlineWeeder.canBeInlined(_elementMap, function, 1,
- enableUserAssertions: options.enableUserAssertions);
+ return inlineData.canBeInlined(maxInliningNodes: 1);
}
- bool reductiveHeuristic() {
+ bool reductiveHeuristic(InlineData inlineData) {
// The call is on a path which is executed rarely, so inline only if it
// does not make the program larger.
if (_isCalledOnce(function)) {
- return InlineWeeder.canBeInlined(_elementMap, function, null,
- enableUserAssertions: options.enableUserAssertions);
+ return inlineData.canBeInlined();
}
- if (InlineReductiveWeeder.canBeInlined(
- _elementMap, function, providedArguments.length,
- enableUserAssertions: options.enableUserAssertions,
- omitImplicitCasts: options.omitImplicitChecks)) {
+ if (inlineData.canBeInlinedReductive(
+ argumentCount: providedArguments.length)) {
return true;
}
- return doesNotContainCode();
+ return doesNotContainCode(inlineData);
}
bool heuristicSayGoodToGo() {
@@ -5645,13 +5645,16 @@
bool hasOnlyNonDeferredImportPaths = closedWorld.outputUnitData
.hasOnlyNonDeferredImportPaths(_initialTargetElement, function);
+ InlineData inlineData =
+ _inlineDataCache.getInlineData(_elementMap, function);
+
if (!hasOnlyNonDeferredImportPaths) {
- return doesNotContainCode();
+ return doesNotContainCode(inlineData);
}
// Do not inline code that is rarely executed unless it reduces size.
if (_inExpressionOfThrow || _inLazyInitializerExpression) {
- return reductiveHeuristic();
+ return reductiveHeuristic(inlineData);
}
if (cachedCanBeInlined == true) {
@@ -5659,10 +5662,7 @@
// if we can inline this method regardless of size.
String reason;
assert(
- (reason = InlineWeeder.cannotBeInlinedReason(
- _elementMap, function, null,
- allowLoops: true,
- enableUserAssertions: options.enableUserAssertions)) ==
+ (reason = inlineData.cannotBeInlinedReason(allowLoops: true)) ==
null,
failedAt(function, "Cannot inline $function: $reason"));
return true;
@@ -5691,10 +5691,8 @@
allowLoops = true;
}
- bool canInline = InlineWeeder.canBeInlined(
- _elementMap, function, maxInliningNodes,
- allowLoops: allowLoops,
- enableUserAssertions: options.enableUserAssertions);
+ bool canInline = inlineData.canBeInlined(
+ maxInliningNodes: maxInliningNodes, allowLoops: allowLoops);
if (markedTryInline) {
if (canInline) {
_inlineCache.markAsInlinable(function, insideLoop: true);
@@ -5710,7 +5708,12 @@
if (canInline) {
_inlineCache.markAsInlinable(function, insideLoop: insideLoop);
} else {
- _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+ if (_isFunctionCalledOnce(function)) {
+ // TODO(34203): We can't update the decision due to imprecision in
+ // the calledOnce data, described in Issue 34203.
+ } else {
+ _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
+ }
}
}
return canInline;
@@ -6110,8 +6113,6 @@
/// Generates type tests for the parameters of the inlined function.
void _potentiallyCheckInlinedParameterTypes(FunctionEntity function) {
- if (!_typeBuilder.checkOrTrustTypes) return;
-
// TODO(sra): Incorporate properties of call site to help determine which
// type parameters and value parameters need to be checked.
bool trusted = false;
@@ -6217,517 +6218,10 @@
this.oldLocalsHandler,
this.inTryStatement,
this.allFunctionsCalledOnce);
-}
-
-class InlineWeeder extends ir.Visitor {
- // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
- static const INLINING_NODES_OUTSIDE_LOOP = 15;
- static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
- static const INLINING_NODES_INSIDE_LOOP = 34;
- static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
-
- static bool canBeInlined(
- JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
- {bool allowLoops: false, bool enableUserAssertions: null}) {
- return cannotBeInlinedReason(elementMap, function, maxInliningNodes,
- allowLoops: allowLoops,
- enableUserAssertions: enableUserAssertions) ==
- null;
- }
-
- static String cannotBeInlinedReason(
- JsToElementMap elementMap, FunctionEntity function, int maxInliningNodes,
- {bool allowLoops: false, bool enableUserAssertions: null}) {
- InlineWeeder visitor =
- new InlineWeeder(maxInliningNodes, allowLoops, enableUserAssertions);
- ir.FunctionNode node = getFunctionNode(elementMap, function);
- node.accept(visitor);
- if (function.isConstructor) {
- MemberDefinition definition = elementMap.getMemberDefinition(function);
- ir.Node node = definition.node;
- if (node is ir.Constructor) {
- node.initializers.forEach((n) => n.accept(visitor));
- }
- }
- return visitor.tooDifficultReason;
- }
-
- final int maxInliningNodes; // `null` for unbounded.
- final bool allowLoops;
- final bool enableUserAssertions;
-
- bool seenReturn = false;
- int nodeCount = 0;
- String tooDifficultReason;
- bool get tooDifficult => tooDifficultReason != null;
-
- InlineWeeder(
- this.maxInliningNodes, this.allowLoops, this.enableUserAssertions);
-
- bool registerNode() {
- if (maxInliningNodes == null) return true;
- if (nodeCount++ > maxInliningNodes) {
- tooDifficultReason ??= 'too many nodes';
- return false;
- }
- return true;
- }
@override
- defaultNode(ir.Node node) {
- if (tooDifficult) return;
- if (!registerNode()) return;
- if (seenReturn) {
- tooDifficultReason ??= 'code after return';
- return;
- }
- node.visitChildren(this);
- }
-
- @override
- visitReturnStatement(ir.ReturnStatement node) {
- if (!registerNode()) return;
- if (seenReturn) {
- tooDifficultReason ??= 'code after return';
- return;
- }
- node.visitChildren(this);
- seenReturn = true;
- }
-
- @override
- visitThrow(ir.Throw node) {
- if (!registerNode()) return;
- if (seenReturn) {
- tooDifficultReason ??= 'code after return';
- return;
- }
- node.visitChildren(this);
- }
-
- _handleLoop(ir.Node node) {
- // It's actually not difficult to inline a method with a loop, but our
- // measurements show that it's currently better to not inline a method that
- // contains a loop.
- if (!allowLoops) tooDifficultReason ??= 'loop';
- node.visitChildren(this);
- }
-
- @override
- visitForStatement(ir.ForStatement node) {
- _handleLoop(node);
- }
-
- @override
- visitForInStatement(ir.ForInStatement node) {
- _handleLoop(node);
- }
-
- @override
- visitWhileStatement(ir.WhileStatement node) {
- _handleLoop(node);
- }
-
- @override
- visitDoStatement(ir.DoStatement node) {
- _handleLoop(node);
- }
-
- @override
- visitTryCatch(ir.TryCatch node) {
- tooDifficultReason ??= 'try';
- }
-
- @override
- visitTryFinally(ir.TryFinally node) {
- tooDifficultReason ??= 'try';
- }
-
- @override
- visitFunctionExpression(ir.FunctionExpression node) {
- if (!registerNode()) return;
- tooDifficultReason ??= 'closure';
- }
-
- @override
- visitFunctionDeclaration(ir.FunctionDeclaration node) {
- if (!registerNode()) return;
- tooDifficultReason ??= 'closure';
- }
-
- @override
- visitFunctionNode(ir.FunctionNode node) {
- if (node.asyncMarker != ir.AsyncMarker.Sync) {
- tooDifficultReason ??= 'async/await';
- return;
- }
- node.visitChildren(this);
- }
-
- @override
- visitConditionalExpression(ir.ConditionalExpression node) {
- // Heuristic: In "parameter ? A : B" there is a high probability that
- // parameter is a constant. Assuming the parameter is constant, we can
- // compute a count that is bounded by the largest arm rather than the sum of
- // both arms.
- ir.Expression condition = node.condition;
- condition.accept(this);
- if (tooDifficult) return;
- int commonPrefixCount = nodeCount;
-
- node.then.accept(this);
- if (tooDifficult) return;
- int thenCount = nodeCount - commonPrefixCount;
-
- nodeCount = commonPrefixCount;
- node.otherwise.accept(this);
- if (tooDifficult) return;
- int elseCount = nodeCount - commonPrefixCount;
-
- nodeCount = commonPrefixCount + thenCount + elseCount;
- if (condition is ir.VariableGet &&
- condition.variable.parent is ir.FunctionNode) {
- nodeCount =
- commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
- }
- // This is last so that [tooDifficult] is always updated.
- if (!registerNode()) return;
- }
-
- @override
- visitAssertInitializer(ir.AssertInitializer node) {
- if (!enableUserAssertions) return;
- node.visitChildren(this);
- }
-
- @override
- visitAssertStatement(ir.AssertStatement node) {
- if (!enableUserAssertions) return;
- defaultNode(node);
- }
-}
-
-/// Determines if inlining a function is very likely to reduce code size.
-class InlineReductiveWeeder extends ir.Visitor {
- // We allow the body to be a single function call that does not have any more
- // inputs than the inlinee.
- //
- // We allow the body to be the return of an 'eligible' constant. A constant is
- // 'eligible' if it is not large (e.g. a long string).
- //
- // We skip 'e as{TypeError} T' when the checks are omitted.
- //
- //
- // TODO(sra): Consider slightly expansive simple constructors where all we
- // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
- //
- // TODO(25231): Make larger string constants eligible by sharing references.
-
- static bool canBeInlined(
- JsToElementMap elementMap, FunctionEntity function, int argumentCount,
- {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
- return cannotBeInlinedReason(elementMap, function, argumentCount,
- enableUserAssertions: enableUserAssertions,
- omitImplicitCasts: omitImplicitCasts) ==
- null;
- }
-
- static String cannotBeInlinedReason(
- JsToElementMap elementMap, FunctionEntity function, int argumentCount,
- {bool enableUserAssertions: null, bool omitImplicitCasts: null}) {
- assert(enableUserAssertions != null);
- assert(omitImplicitCasts != null);
- var visitor = new InlineReductiveWeeder(
- argumentCount, enableUserAssertions, omitImplicitCasts);
- ir.FunctionNode node = getFunctionNode(elementMap, function);
- if (function.isConstructor) {
- return visitor.tooDifficultReason ??= 'constructor';
- }
- node.accept(visitor);
- return visitor.tooDifficultReason;
- }
-
- final int argumentCount;
- final bool enableUserAssertions;
- final bool omitImplicitCasts;
- final int maxInliningNodes;
-
- bool seenReturn = false;
- int nodeCount = 0;
- int callCount = 0;
- String tooDifficultReason;
- bool get tooDifficult => tooDifficultReason != null;
-
- InlineReductiveWeeder(
- this.argumentCount, this.enableUserAssertions, this.omitImplicitCasts)
- :
- // Node budget that covers one call and the passed-in arguments.
- // The +1 also allows a top-level zero-argument to be inlined if it
- // returns a constant.
- maxInliningNodes = argumentCount + 1;
-
- bool registerNode() {
- if (++nodeCount > maxInliningNodes) {
- tooDifficultReason ??= 'too many nodes';
- return false;
- }
- return true;
- }
-
- bool registerCall() {
- if (++callCount > 1) {
- tooDifficultReason ??= 'too many calls';
- return false;
- }
- return true;
- }
-
- @override
- defaultNode(ir.Node node) {
- if (tooDifficult) return;
- if (seenReturn) {
- tooDifficultReason ??= 'code after return';
- return;
- }
- if (!registerNode()) return;
- node.visitChildren(this);
- }
-
- @override
- visitReturnStatement(ir.ReturnStatement node) {
- if (seenReturn) {
- tooDifficultReason ??= 'code after return';
- return;
- }
- node.visitChildren(this);
- seenReturn = true;
- }
-
- @override
- visitThrow(ir.Throw node) {
- tooDifficultReason ??= 'throw';
- }
-
- @override
- visitEmptyStatement(ir.EmptyStatement node) {}
-
- @override
- visitExpressionStatement(ir.ExpressionStatement node) {
- node.visitChildren(this);
- }
-
- @override
- visitBlock(ir.Block node) {
- node.visitChildren(this);
- }
-
- @override
- visitStringLiteral(ir.StringLiteral node) {
- registerNode();
- // Avoid copying long strings into call site.
- if (node.value.length > 14) tooDifficultReason ??= 'long string';
- }
-
- @override
- visitPropertyGet(ir.PropertyGet node) {
- if (!registerCall()) return;
- if (!registerNode()) return;
- node.receiver.accept(this);
- }
-
- @override
- visitDirectPropertyGet(ir.DirectPropertyGet node) {
- if (!registerCall()) return;
- if (!registerNode()) return;
- node.receiver.accept(this);
- }
-
- @override
- visitPropertySet(ir.PropertySet node) {
- if (!registerCall()) return;
- if (!registerNode()) return;
- node.receiver.accept(this);
- node.value.accept(this);
- }
-
- @override
- visitDirectPropertySet(ir.DirectPropertySet node) {
- if (!registerCall()) return;
- if (!registerNode()) return;
- node.receiver.accept(this);
- node.value.accept(this);
- }
-
- @override
- visitVariableGet(ir.VariableGet node) {
- registerNode();
- }
-
- @override
- visitThisExpression(ir.ThisExpression node) {
- registerNode();
- }
-
- @override
- visitStaticGet(ir.StaticGet node) {
- // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
- if (!registerCall()) return;
- registerNode();
- }
-
- @override
- visitConstructorInvocation(ir.ConstructorInvocation node) {
- if (node.isConst) {
- // A const constructor call compiles to a constant pool reference.
- registerNode();
- return;
- }
- if (!registerCall()) return;
- if (!registerNode()) return;
- _processArguments(node.arguments, node.target?.function);
- }
-
- @override
- visitStaticInvocation(ir.StaticInvocation node) {
- if (node.isConst) {
- tooDifficultReason ??= 'external const constructor';
- return;
- }
- if (!registerCall()) return;
- if (!registerNode()) return;
- _processArguments(node.arguments, node.target?.function);
- }
-
- @override
- visitMethodInvocation(ir.MethodInvocation node) {
- if (!registerCall()) return;
- if (!registerNode()) return;
- node.receiver.accept(this);
- _processArguments(node.arguments, null);
- }
-
- _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
- if (arguments.types.isNotEmpty) {
- tooDifficultReason ??= 'type arguments';
- return;
- }
- int count = arguments.positional.length + arguments.named.length;
- if (count > argumentCount) {
- tooDifficultReason ??= 'increasing arguments';
- return;
- }
-
- if (target != null) {
- // Disallow defaulted optional arguments since they will be passed
- // explicitly.
- if (target.positionalParameters.length + target.namedParameters.length >
- count) {
- tooDifficultReason ??= 'argument defaulting';
- return;
- }
- }
-
- for (var e in arguments.positional) {
- e.accept(this);
- if (tooDifficult) return;
- }
- for (var e in arguments.named) {
- e.value.accept(this);
- if (tooDifficult) return;
- }
- }
-
- @override
- visitAsExpression(ir.AsExpression node) {
- if (node.isTypeError && omitImplicitCasts) {
- node.operand.accept(this);
- return;
- }
- tooDifficultReason ??= 'cast';
- }
-
- @override
- visitVariableDeclaration(ir.VariableDeclaration node) {
- // A local variable is an alias for the initializer expression.
- if (node.initializer != null) {
- --nodeCount; // discount one reference to the variable.
- node.initializer.accept(this);
- return;
- }
- }
-
- @override
- visitForStatement(ir.ForStatement node) {
- tooDifficultReason ??= 'loop';
- }
-
- @override
- visitForInStatement(ir.ForInStatement node) {
- tooDifficultReason ??= 'loop';
- }
-
- @override
- visitWhileStatement(ir.WhileStatement node) {
- tooDifficultReason ??= 'loop';
- }
-
- @override
- visitDoStatement(ir.DoStatement node) {
- tooDifficultReason ??= 'loop';
- }
-
- @override
- visitTryCatch(ir.TryCatch node) {
- tooDifficultReason ??= 'try';
- }
-
- @override
- visitTryFinally(ir.TryFinally node) {
- tooDifficultReason ??= 'try';
- }
-
- @override
- visitIfStatement(ir.IfStatement node) {
- tooDifficultReason ??= 'if';
- }
-
- @override
- visitFunctionExpression(ir.FunctionExpression node) {
- tooDifficultReason ??= 'closure';
- }
-
- @override
- visitFunctionDeclaration(ir.FunctionDeclaration node) {
- tooDifficultReason ??= 'closure';
- }
-
- @override
- visitFunctionNode(ir.FunctionNode node) {
- if (node.asyncMarker != ir.AsyncMarker.Sync) {
- tooDifficultReason ??= 'async/await';
- return;
- }
- // TODO(sra): Cost of parameter checking?
- node.body.accept(this);
- }
-
- @override
- visitConditionalExpression(ir.ConditionalExpression node) {
- if (!registerNode()) return;
- node.visitChildren(this);
- }
-
- @override
- visitAssertInitializer(ir.AssertInitializer node) {
- if (!enableUserAssertions) return;
- node.visitChildren(this);
- }
-
- @override
- visitAssertStatement(ir.AssertStatement node) {
- if (!enableUserAssertions) return;
- defaultNode(node);
- }
+ String toString() => 'KernelInliningState($function,'
+ 'allFunctionsCalledOnce=$allFunctionsCalledOnce)';
}
/// Class in charge of building try, catch and/or finally blocks. This handles
@@ -7062,3 +6556,621 @@
@override
String toString() => 'StaticType($type,$relation)';
}
+
+class InlineData {
+ bool isConstructor = false;
+ bool codeAfterReturn = false;
+ bool hasLoop = false;
+ bool hasClosure = false;
+ bool hasTry = false;
+ bool hasAsyncAwait = false;
+ bool hasThrow = false;
+ bool hasLongString = false;
+ bool hasExternalConstantConstructorCall = false;
+ bool hasTypeArguments = false;
+ bool hasArgumentDefaulting = false;
+ bool hasCast = false;
+ bool hasIf = false;
+ List<int> argumentCounts = [];
+ int regularNodeCount = 0;
+ int callCount = 0;
+ int reductiveNodeCount = 0;
+
+ InlineData();
+
+ InlineData.internal(
+ {this.codeAfterReturn,
+ this.hasLoop,
+ this.hasClosure,
+ this.hasTry,
+ this.hasAsyncAwait,
+ this.hasThrow,
+ this.hasLongString,
+ this.regularNodeCount,
+ this.callCount});
+
+ bool canBeInlined({int maxInliningNodes, bool allowLoops: false}) {
+ return cannotBeInlinedReason(
+ maxInliningNodes: maxInliningNodes, allowLoops: allowLoops) ==
+ null;
+ }
+
+ String cannotBeInlinedReason({int maxInliningNodes, bool allowLoops: false}) {
+ if (hasLoop && !allowLoops) {
+ return 'loop';
+ } else if (hasTry) {
+ return 'try';
+ } else if (hasClosure) {
+ return 'closure';
+ } else if (codeAfterReturn) {
+ return 'code after return';
+ } else if (hasAsyncAwait) {
+ return 'async/await';
+ } else if (maxInliningNodes != null &&
+ regularNodeCount - 1 > maxInliningNodes) {
+ return 'too many nodes (${regularNodeCount - 1}>$maxInliningNodes)';
+ }
+ return null;
+ }
+
+ bool canBeInlinedReductive({int argumentCount}) {
+ return cannotBeInlinedReductiveReason(argumentCount: argumentCount) == null;
+ }
+
+ String cannotBeInlinedReductiveReason({int argumentCount}) {
+ if (hasTry) {
+ return 'try';
+ } else if (hasClosure) {
+ return 'closure';
+ } else if (codeAfterReturn) {
+ return 'code after return';
+ } else if (hasAsyncAwait) {
+ return 'async/await';
+ } else if (callCount > 1) {
+ return 'too many calls';
+ } else if (hasThrow) {
+ return 'throw';
+ } else if (hasLongString) {
+ return 'long string';
+ } else if (hasExternalConstantConstructorCall) {
+ return 'external const constructor';
+ } else if (hasTypeArguments) {
+ return 'type arguments';
+ } else if (hasArgumentDefaulting) {
+ return 'argument defaulting';
+ } else if (hasCast) {
+ return 'cast';
+ } else if (hasIf) {
+ return 'if';
+ } else if (isConstructor) {
+ return 'constructor';
+ }
+ for (int count in argumentCounts) {
+ if (count > argumentCount) {
+ return 'increasing arguments';
+ }
+ }
+ // Node budget that covers one call and the passed-in arguments.
+ // The +1 also allows a top-level zero-argument to be inlined if it
+ // returns a constant.
+ int maxInliningNodes = argumentCount + 1;
+ if (reductiveNodeCount > maxInliningNodes) {
+ return 'too many nodes (${reductiveNodeCount}>$maxInliningNodes)';
+ }
+
+ return null;
+ }
+
+ @override
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('InlineData(');
+ String comma = '';
+ if (isConstructor) {
+ sb.write('isConstructor');
+ comma = ',';
+ }
+ if (codeAfterReturn) {
+ sb.write(comma);
+ sb.write('codeAfterReturn');
+ comma = ',';
+ }
+ if (hasLoop) {
+ sb.write(comma);
+ sb.write('hasLoop');
+ comma = ',';
+ }
+ if (hasClosure) {
+ sb.write(comma);
+ sb.write('hasClosure');
+ comma = ',';
+ }
+ if (hasTry) {
+ sb.write(comma);
+ sb.write('hasTry');
+ comma = ',';
+ }
+ if (hasAsyncAwait) {
+ sb.write(comma);
+ sb.write('hasAsyncAwait');
+ comma = ',';
+ }
+ if (hasThrow) {
+ sb.write(comma);
+ sb.write('hasThrow');
+ comma = ',';
+ }
+ if (hasLongString) {
+ sb.write(comma);
+ sb.write('hasLongString');
+ comma = ',';
+ }
+ if (hasExternalConstantConstructorCall) {
+ sb.write(comma);
+ sb.write('hasExternalConstantConstructorCall');
+ comma = ',';
+ }
+ if (hasTypeArguments) {
+ sb.write(comma);
+ sb.write('hasTypeArguments');
+ comma = ',';
+ }
+ if (hasArgumentDefaulting) {
+ sb.write(comma);
+ sb.write('hasArgumentDefaulting');
+ comma = ',';
+ }
+ if (hasCast) {
+ sb.write(comma);
+ sb.write('hasCast');
+ comma = ',';
+ }
+ if (hasIf) {
+ sb.write(comma);
+ sb.write('hasIf');
+ comma = ',';
+ }
+ if (argumentCounts.isNotEmpty) {
+ sb.write(comma);
+ sb.write('argumentCounts={${argumentCounts.join(',')}}');
+ comma = ',';
+ }
+ sb.write(comma);
+ sb.write('regularNodeCount=$regularNodeCount,');
+ sb.write('callCount=$callCount,');
+ sb.write('reductiveNodeCount=$reductiveNodeCount');
+ sb.write(')');
+ return sb.toString();
+ }
+}
+
+class InlineDataCache {
+ final bool enableUserAssertions;
+ final bool omitImplicitCasts;
+
+ InlineDataCache(
+ {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+ Map<FunctionEntity, InlineData> _cache = {};
+
+ InlineData getInlineData(JsToElementMap elementMap, FunctionEntity function) {
+ return _cache[function] ??= InlineWeeder.computeInlineData(
+ elementMap, function,
+ enableUserAssertions: enableUserAssertions,
+ omitImplicitCasts: omitImplicitCasts);
+ }
+}
+
+class InlineWeeder extends ir.Visitor {
+ // Invariant: *INSIDE_LOOP* > *OUTSIDE_LOOP*
+ static const INLINING_NODES_OUTSIDE_LOOP = 15;
+ static const INLINING_NODES_OUTSIDE_LOOP_ARG_FACTOR = 3;
+ static const INLINING_NODES_INSIDE_LOOP = 34;
+ static const INLINING_NODES_INSIDE_LOOP_ARG_FACTOR = 4;
+
+ final bool enableUserAssertions;
+ final bool omitImplicitCasts;
+
+ final InlineData data = new InlineData();
+ bool seenReturn = false;
+
+ /// Whether node-count is collector to determine if a function can be
+ /// inlined.
+ bool countRegularNode = true;
+
+ /// Whether node-count is collected to determine if inlining a function is
+ /// very likely to reduce code size.
+ ///
+ /// For the reductive analysis:
+ /// We allow the body to be a single function call that does not have any more
+ /// inputs than the inlinee.
+ ///
+ /// We allow the body to be the return of an 'eligible' constant. A constant
+ /// is 'eligible' if it is not large (e.g. a long string).
+ ///
+ /// We skip 'e as{TypeError} T' when the checks are omitted.
+ //
+ // TODO(sra): Consider slightly expansive simple constructors where all we
+ // gain is a 'new' keyword, e.g. `new X.Foo(a)` vs `X.Foo$(a)`.
+ //
+ // TODO(25231): Make larger string constants eligible by sharing references.
+ bool countReductiveNode = true;
+
+ InlineWeeder(
+ {this.enableUserAssertions: false, this.omitImplicitCasts: false});
+
+ static InlineData computeInlineData(
+ JsToElementMap elementMap, FunctionEntity function,
+ {bool enableUserAssertions: false, bool omitImplicitCasts: false}) {
+ InlineWeeder visitor = new InlineWeeder(
+ enableUserAssertions: enableUserAssertions,
+ omitImplicitCasts: omitImplicitCasts);
+ ir.FunctionNode node = getFunctionNode(elementMap, function);
+ node.accept(visitor);
+ if (function.isConstructor) {
+ visitor.data.isConstructor = true;
+ MemberDefinition definition = elementMap.getMemberDefinition(function);
+ visitor.skipReductiveNodes(() {
+ ir.Node node = definition.node;
+ if (node is ir.Constructor) {
+ visitor.visitList(node.initializers);
+ }
+ });
+ }
+ return visitor.data;
+ }
+
+ void skipRegularNodes(void f()) {
+ bool oldCountRegularNode = countRegularNode;
+ countRegularNode = false;
+ f();
+ countRegularNode = oldCountRegularNode;
+ }
+
+ void skipReductiveNodes(void f()) {
+ bool oldCountReductiveNode = countReductiveNode;
+ countReductiveNode = false;
+ f();
+ countReductiveNode = oldCountReductiveNode;
+ }
+
+ void registerRegularNode() {
+ if (countRegularNode) {
+ data.regularNodeCount++;
+ if (seenReturn) {
+ data.codeAfterReturn = true;
+ }
+ }
+ }
+
+ void registerReductiveNode() {
+ if (countReductiveNode) {
+ data.reductiveNodeCount++;
+ if (seenReturn) {
+ data.codeAfterReturn = true;
+ }
+ }
+ }
+
+ void unregisterReductiveNode() {
+ if (countReductiveNode) {
+ data.reductiveNodeCount--;
+ }
+ }
+
+ void visit(ir.Node node) => node?.accept(this);
+
+ void visitList(List<ir.Node> nodes) {
+ for (ir.Node node in nodes) {
+ visit(node);
+ }
+ }
+
+ @override
+ defaultNode(ir.Node node) {
+ registerRegularNode();
+ registerReductiveNode();
+ node.visitChildren(this);
+ }
+
+ @override
+ visitReturnStatement(ir.ReturnStatement node) {
+ registerRegularNode();
+ node.visitChildren(this);
+ seenReturn = true;
+ }
+
+ @override
+ visitThrow(ir.Throw node) {
+ registerRegularNode();
+ data.hasThrow = true;
+ node.visitChildren(this);
+ }
+
+ _handleLoop(ir.Node node) {
+ // It's actually not difficult to inline a method with a loop, but our
+ // measurements show that it's currently better to not inline a method that
+ // contains a loop.
+ data.hasLoop = true;
+ node.visitChildren(this);
+ }
+
+ @override
+ visitForStatement(ir.ForStatement node) {
+ _handleLoop(node);
+ }
+
+ @override
+ visitForInStatement(ir.ForInStatement node) {
+ _handleLoop(node);
+ }
+
+ @override
+ visitWhileStatement(ir.WhileStatement node) {
+ _handleLoop(node);
+ }
+
+ @override
+ visitDoStatement(ir.DoStatement node) {
+ _handleLoop(node);
+ }
+
+ @override
+ visitTryCatch(ir.TryCatch node) {
+ data.hasTry = true;
+ }
+
+ @override
+ visitTryFinally(ir.TryFinally node) {
+ data.hasTry = true;
+ }
+
+ @override
+ visitFunctionExpression(ir.FunctionExpression node) {
+ registerRegularNode();
+ data.hasClosure = true;
+ }
+
+ @override
+ visitFunctionDeclaration(ir.FunctionDeclaration node) {
+ registerRegularNode();
+ data.hasClosure = true;
+ }
+
+ @override
+ visitFunctionNode(ir.FunctionNode node) {
+ if (node.asyncMarker != ir.AsyncMarker.Sync) {
+ data.hasAsyncAwait = true;
+ }
+ // TODO(sra): Cost of parameter checking?
+ skipReductiveNodes(() {
+ visitList(node.typeParameters);
+ visitList(node.positionalParameters);
+ visitList(node.namedParameters);
+ visit(node.returnType);
+ });
+ visit(node.body);
+ }
+
+ @override
+ visitConditionalExpression(ir.ConditionalExpression node) {
+ // Heuristic: In "parameter ? A : B" there is a high probability that
+ // parameter is a constant. Assuming the parameter is constant, we can
+ // compute a count that is bounded by the largest arm rather than the sum of
+ // both arms.
+ ir.Expression condition = node.condition;
+ visit(condition);
+ int commonPrefixCount = data.regularNodeCount;
+
+ visit(node.then);
+ int thenCount = data.regularNodeCount - commonPrefixCount;
+
+ data.regularNodeCount = commonPrefixCount;
+ visit(node.otherwise);
+ int elseCount = data.regularNodeCount - commonPrefixCount;
+
+ data.regularNodeCount = commonPrefixCount + thenCount + elseCount;
+ if (condition is ir.VariableGet &&
+ condition.variable.parent is ir.FunctionNode) {
+ data.regularNodeCount =
+ commonPrefixCount + (thenCount > elseCount ? thenCount : elseCount);
+ }
+ // This is last so that [tooDifficult] is always updated.
+ registerRegularNode();
+ registerReductiveNode();
+ skipRegularNodes(() => visit(node.staticType));
+ }
+
+ @override
+ visitAssertInitializer(ir.AssertInitializer node) {
+ if (!enableUserAssertions) return;
+ node.visitChildren(this);
+ }
+
+ @override
+ visitAssertStatement(ir.AssertStatement node) {
+ if (!enableUserAssertions) return;
+ defaultNode(node);
+ }
+
+ void registerCall() {
+ ++data.callCount;
+ }
+
+ @override
+ visitEmptyStatement(ir.EmptyStatement node) {
+ registerRegularNode();
+ }
+
+ @override
+ visitExpressionStatement(ir.ExpressionStatement node) {
+ registerRegularNode();
+ node.visitChildren(this);
+ }
+
+ @override
+ visitBlock(ir.Block node) {
+ registerRegularNode();
+ node.visitChildren(this);
+ }
+
+ @override
+ visitStringLiteral(ir.StringLiteral node) {
+ registerRegularNode();
+ registerReductiveNode();
+ // Avoid copying long strings into call site.
+ if (node.value.length > 14) {
+ data.hasLongString = true;
+ }
+ }
+
+ @override
+ visitPropertyGet(ir.PropertyGet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ }
+
+ @override
+ visitDirectPropertyGet(ir.DirectPropertyGet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ visit(node.receiver);
+ }
+
+ @override
+ visitPropertySet(ir.PropertySet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.name));
+ visit(node.receiver);
+ visit(node.value);
+ }
+
+ @override
+ visitDirectPropertySet(ir.DirectPropertySet node) {
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ visit(node.receiver);
+ visit(node.value);
+ }
+
+ @override
+ visitVariableGet(ir.VariableGet node) {
+ registerRegularNode();
+ registerReductiveNode();
+ skipReductiveNodes(() => visit(node.promotedType));
+ }
+
+ @override
+ visitThisExpression(ir.ThisExpression node) {
+ registerRegularNode();
+ registerReductiveNode();
+ }
+
+ @override
+ visitStaticGet(ir.StaticGet node) {
+ // Assume lazy-init static, loaded via a call: `$.$get$foo()`.
+ registerCall();
+ registerRegularNode();
+ registerReductiveNode();
+ }
+
+ @override
+ visitConstructorInvocation(ir.ConstructorInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ if (node.isConst) {
+ // A const constructor call compiles to a constant pool reference.
+ skipReductiveNodes(() => node.visitChildren(this));
+ } else {
+ registerCall();
+ _processArguments(node.arguments, node.target?.function);
+ }
+ }
+
+ @override
+ visitStaticInvocation(ir.StaticInvocation node) {
+ registerRegularNode();
+ if (node.isConst) {
+ data.hasExternalConstantConstructorCall = true;
+ skipReductiveNodes(() => node.visitChildren(this));
+ } else {
+ registerCall();
+ registerReductiveNode();
+ _processArguments(node.arguments, node.target?.function);
+ }
+ }
+
+ @override
+ visitMethodInvocation(ir.MethodInvocation node) {
+ registerRegularNode();
+ registerReductiveNode();
+ registerCall();
+ visit(node.receiver);
+ skipReductiveNodes(() => visit(node.name));
+ _processArguments(node.arguments, null);
+ }
+
+ _processArguments(ir.Arguments arguments, ir.FunctionNode target) {
+ registerRegularNode();
+ if (arguments.types.isNotEmpty) {
+ data.hasTypeArguments = true;
+ skipReductiveNodes(() => visitList(arguments.types));
+ }
+ int count = arguments.positional.length + arguments.named.length;
+ data.argumentCounts.add(count);
+
+ if (target != null) {
+ // Disallow defaulted optional arguments since they will be passed
+ // explicitly.
+ if (target.positionalParameters.length + target.namedParameters.length >
+ count) {
+ data.hasArgumentDefaulting = true;
+ }
+ }
+
+ visitList(arguments.positional);
+ for (ir.NamedExpression expression in arguments.named) {
+ registerRegularNode();
+ expression.value.accept(this);
+ }
+ }
+
+ @override
+ visitAsExpression(ir.AsExpression node) {
+ registerRegularNode();
+ visit(node.operand);
+ skipReductiveNodes(() => visit(node.type));
+ if (!(node.isTypeError && omitImplicitCasts)) {
+ data.hasCast = true;
+ }
+ }
+
+ @override
+ visitVariableDeclaration(ir.VariableDeclaration node) {
+ registerRegularNode();
+ skipReductiveNodes(() {
+ visitList(node.annotations);
+ visit(node.type);
+ });
+ visit(node.initializer);
+
+ // A local variable is an alias for the initializer expression.
+ if (node.initializer != null) {
+ unregisterReductiveNode(); // discount one reference to the variable.
+ }
+ }
+
+ @override
+ visitIfStatement(ir.IfStatement node) {
+ registerRegularNode();
+ node.visitChildren(this);
+ data.hasIf = true;
+ }
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 47d0de0..1b97f87 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -21,7 +21,7 @@
import '../io/source_information.dart';
import '../js/js.dart' as js;
import '../js_backend/interceptor_data.dart';
-import '../js_backend/backend.dart' show CodegenInputs, SuperMemberData;
+import '../js_backend/backend.dart' show CodegenInputs;
import '../js_backend/checked_mode_helpers.dart';
import '../js_backend/native_data.dart';
import '../js_backend/namer.dart' show ModularNamer;
@@ -112,11 +112,9 @@
_options,
emitter,
codegen.checkedModeHelpers,
- codegen.oneShotInterceptorData,
codegen.rtiSubstitutions,
codegen.rtiEncoder,
namer,
- codegen.superMemberData,
codegen.tracer,
closedWorld,
registry);
@@ -143,11 +141,9 @@
_options,
emitter,
codegen.checkedModeHelpers,
- codegen.oneShotInterceptorData,
codegen.rtiSubstitutions,
codegen.rtiEncoder,
namer,
- codegen.superMemberData,
codegen.tracer,
closedWorld,
registry);
@@ -182,11 +178,9 @@
final CompilerOptions _options;
final ModularEmitter _emitter;
final CheckedModeHelpers _checkedModeHelpers;
- final OneShotInterceptorData _oneShotInterceptorData;
final RuntimeTypesSubstitutions _rtiSubstitutions;
final RuntimeTypesEncoder _rtiEncoder;
final ModularNamer _namer;
- final SuperMemberData _superMemberData;
final Tracer _tracer;
final JClosedWorld _closedWorld;
final CodegenRegistry _registry;
@@ -238,11 +232,9 @@
this._options,
this._emitter,
this._checkedModeHelpers,
- this._oneShotInterceptorData,
this._rtiSubstitutions,
this._rtiEncoder,
this._namer,
- this._superMemberData,
this._tracer,
this._closedWorld,
this._registry,
@@ -389,8 +381,7 @@
runPhase(new SsaTypeKnownRemover());
runPhase(new SsaTrustedCheckRemover(_options));
runPhase(new SsaAssignmentChaining(_options, _closedWorld));
- runPhase(new SsaInstructionMerger(
- _abstractValueDomain, generateAtUseSite, _superMemberData));
+ runPhase(new SsaInstructionMerger(_abstractValueDomain, generateAtUseSite));
runPhase(new SsaConditionMerger(generateAtUseSite, controlFlowOperators));
runPhase(new SsaShareRegionConstants(_options));
@@ -628,6 +619,9 @@
js.Expression generateExpressionAssignment(String variableName,
js.Expression value, SourceInformation sourceInformation) {
+ // TODO(johnniwinther): Introduce a DeferredVariableUse to handle this
+ // in the SSA codegen or let the JS printer handle it fully and remove it
+ // here.
if (value is js.Binary) {
js.Binary binary = value;
String op = binary.op;
@@ -699,11 +693,14 @@
// emit an assignment, because the intTypeCheck just returns its
// argument.
bool needsAssignment = true;
- if (instruction is HTypeConversion) {
- HTypeConversion typeConversion = instruction;
- String inputName = variableNames.getName(typeConversion.checkedInput);
- if (variableNames.getName(instruction) == inputName) {
- needsAssignment = false;
+ if (instruction is HCheck) {
+ if (instruction is HTypeConversion ||
+ instruction is HPrimitiveCheck ||
+ instruction is HBoolConversion) {
+ String inputName = variableNames.getName(instruction.checkedInput);
+ if (variableNames.getName(instruction) == inputName) {
+ needsAssignment = false;
+ }
}
}
if (instruction is HLocalValue) {
@@ -1567,15 +1564,6 @@
visitGreaterEqual(HGreaterEqual node) => visitRelational(node, '>=');
@override
- visitBoolify(HBoolify node) {
- assert(node.inputs.length == 1);
- use(node.inputs[0]);
- push(new js.Binary(
- '===', pop(), newLiteralBool(true, node.sourceInformation))
- .withSourceInformation(node.sourceInformation));
- }
-
- @override
visitExit(HExit node) {
// Don't do anything.
}
@@ -1923,8 +1911,10 @@
js.Expression isolate =
_namer.readGlobalObjectForLibrary(_commonElements.interceptorsLibrary);
Selector selector = node.selector;
- js.Name methodName = _oneShotInterceptorData.registerOneShotInterceptor(
- selector, _namer, _closedWorld);
+ Set<ClassEntity> classes =
+ _interceptorData.getInterceptedClassesOn(selector.name, _closedWorld);
+ _registry.registerOneShotInterceptor(selector);
+ js.Name methodName = _namer.nameForOneShotInterceptor(selector, classes);
push(js
.propertyCall(isolate, methodName, arguments)
.withSourceInformation(node.sourceInformation));
@@ -2137,8 +2127,7 @@
MemberEntity superElement = node.element;
ClassEntity superClass = superElement.enclosingClass;
Selector selector = node.selector;
- bool useAliasedSuper = _superMemberData.maybeRegisterAliasedSuperMember(
- superElement, selector);
+ bool useAliasedSuper = canUseAliasedSuperMember(superElement, selector);
if (selector.isGetter) {
if (superElement.isField || superElement.isGetter) {
_registry.registerStaticUse(new StaticUse.superGet(superElement));
@@ -2153,8 +2142,7 @@
_registry.registerStaticUse(new StaticUse.superSetterSet(superElement));
}
} else {
- if (_superMemberData.maybeRegisterAliasedSuperMember(
- superElement, selector)) {
+ if (useAliasedSuper) {
_registry.registerStaticUse(new StaticUse.superInvoke(
superElement, new CallStructure.unnamed(node.inputs.length)));
} else {
@@ -2432,11 +2420,6 @@
use(input.inputs[0]);
} else if (input is HIdentity) {
emitIdentityComparison(input, sourceInformation, inverse: true);
- } else if (input is HBoolify) {
- use(input.inputs[0]);
- push(new js.Binary(
- "!==", pop(), newLiteralBool(true, input.sourceInformation))
- .withSourceInformation(sourceInformation));
} else if (canGenerateOptimizedComparison(input)) {
HRelational relational = input;
constant_system.BinaryOperation operation = relational.operation();
@@ -3124,55 +3107,9 @@
negative: negative);
}
- js.Expression generateReceiverOrArgumentTypeTest(HTypeConversion node) {
- DartType type = node.typeExpression;
- HInstruction input = node.checkedInput;
- AbstractValue checkedType = node.checkedType;
- // This path is no longer used for indexable primitive types.
- assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
- // Figure out if it is beneficial to use a null check. V8 generally prefers
- // 'typeof' checks, but for integers we cannot compile this test into a
- // single typeof check so the null check is cheaper.
- if (type == _commonElements.numType) {
- // input is !num
- checkNum(input, '!==', input.sourceInformation);
- return pop();
- } else if (type == _commonElements.boolType) {
- // input is !bool
- checkBool(input, '!==', input.sourceInformation);
- return pop();
- }
- throw failedAt(input, 'Unexpected check: $type.');
- }
-
@override
void visitTypeConversion(HTypeConversion node) {
- if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) {
- js.Expression test = generateReceiverOrArgumentTypeTest(node);
- js.Block oldContainer = currentContainer;
- js.Statement body = new js.Block.empty();
- currentContainer = body;
- if (node.isArgumentTypeCheck) {
- generateThrowWithHelper(
- _commonElements.throwIllegalArgumentException, node.checkedInput,
- sourceInformation: node.sourceInformation);
- } else if (node.isReceiverTypeCheck) {
- use(node.checkedInput);
- js.Name methodName =
- _namer.invocationName(node.receiverTypeCheckSelector);
- js.Expression call = js.propertyCall(pop(), methodName,
- []).withSourceInformation(node.sourceInformation);
- pushStatement(
- new js.Return(call).withSourceInformation(node.sourceInformation));
- }
- currentContainer = oldContainer;
- body = unwrapStatement(body);
- pushStatement(new js.If.noElse(test, body)
- .withSourceInformation(node.sourceInformation));
- return;
- }
-
- assert(node.isCheckedModeCheck || node.isCastTypeCheck);
+ assert(node.isTypeCheck || node.isCastCheck);
DartType type = node.typeExpression;
assert(!type.isTypedef);
assert(!type.isDynamic);
@@ -3185,14 +3122,9 @@
}
_registry.registerTypeUse(new TypeUse.isCheck(type));
- CheckedModeHelper helper;
- if (node.isBooleanConversionCheck) {
- helper = const CheckedModeHelper('boolConversionCheck');
- } else {
- helper = _checkedModeHelpers.getCheckedModeHelper(
- type, _closedWorld.commonElements,
- typeCast: node.isCastTypeCheck);
- }
+ CheckedModeHelper helper = _checkedModeHelpers.getCheckedModeHelper(
+ type, _closedWorld.commonElements,
+ typeCast: node.isCastCheck);
StaticUse staticUse = helper.getStaticUse(_closedWorld.commonElements);
_registry.registerStaticUse(staticUse);
@@ -3206,6 +3138,66 @@
}
@override
+ void visitPrimitiveCheck(HPrimitiveCheck node) {
+ js.Expression test = _generateReceiverOrArgumentTypeTest(node);
+ js.Block oldContainer = currentContainer;
+ js.Statement body = new js.Block.empty();
+ currentContainer = body;
+ if (node.isArgumentTypeCheck) {
+ generateThrowWithHelper(
+ _commonElements.throwIllegalArgumentException, node.checkedInput,
+ sourceInformation: node.sourceInformation);
+ } else if (node.isReceiverTypeCheck) {
+ use(node.checkedInput);
+ js.Name methodName =
+ _namer.invocationName(node.receiverTypeCheckSelector);
+ js.Expression call = js.propertyCall(
+ pop(), methodName, []).withSourceInformation(node.sourceInformation);
+ pushStatement(
+ new js.Return(call).withSourceInformation(node.sourceInformation));
+ }
+ currentContainer = oldContainer;
+ body = unwrapStatement(body);
+ pushStatement(new js.If.noElse(test, body)
+ .withSourceInformation(node.sourceInformation));
+ }
+
+ js.Expression _generateReceiverOrArgumentTypeTest(HPrimitiveCheck node) {
+ DartType type = node.typeExpression;
+ HInstruction input = node.checkedInput;
+ AbstractValue checkedType = node.checkedType;
+ // This path is no longer used for indexable primitive types.
+ assert(_abstractValueDomain.isJsIndexable(checkedType).isPotentiallyFalse);
+ // Figure out if it is beneficial to use a null check. V8 generally prefers
+ // 'typeof' checks, but for integers we cannot compile this test into a
+ // single typeof check so the null check is cheaper.
+ if (type == _commonElements.numType) {
+ // input is !num
+ checkNum(input, '!==', input.sourceInformation);
+ return pop();
+ }
+ if (type == _commonElements.boolType) {
+ // input is !bool
+ checkBool(input, '!==', input.sourceInformation);
+ return pop();
+ }
+ throw failedAt(input, 'Unexpected check: $type.');
+ }
+
+ @override
+ void visitBoolConversion(HBoolConversion node) {
+ _registry.registerTypeUse(new TypeUse.isCheck(_commonElements.boolType));
+ CheckedModeHelper helper = const CheckedModeHelper('boolConversionCheck');
+ StaticUse staticUse = helper.getStaticUse(_commonElements);
+ _registry.registerStaticUse(staticUse);
+ use(node.checkedInput);
+ List<js.Expression> arguments = [pop()];
+ push(
+ new js.Call(_emitter.staticFunctionAccess(staticUse.element), arguments)
+ .withSourceInformation(node.sourceInformation));
+ }
+
+ @override
void visitTypeKnown(HTypeKnown node) {
// [HTypeKnown] instructions are removed before generating code.
assert(false);
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index bc388f2..8ffd0ed 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -5,7 +5,6 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../inferrer/abstract_value_domain.dart';
-import '../js_backend/js_backend.dart' show SuperMemberData;
import '../js_backend/interceptor_data.dart';
import '../options.dart';
import '../universe/selector.dart' show Selector;
@@ -13,6 +12,15 @@
import 'codegen.dart' show CodegenPhase;
import 'nodes.dart';
+/// Returns `true` if the invocation of [selector] on [member] can use an
+/// aliased member.
+///
+/// Invoking a super getter isn't supported, this would require changes to
+/// compact field descriptors in the emitter.
+bool canUseAliasedSuperMember(MemberEntity member, Selector selector) {
+ return !selector.isGetter;
+}
+
/// Replaces some instructions with specialized versions to make codegen easier.
/// Caches codegen information on nodes.
class SsaInstructionSelection extends HBaseVisitor with CodegenPhase {
@@ -191,7 +199,7 @@
!_interceptorData.isInterceptedMixinSelector(
selector, mask, _closedWorld)) {
ConstantValue constant =
- new AbstractValueConstantValue(receiverArgument.instructionType);
+ new DummyInterceptorConstantValue(receiverArgument.instructionType);
HConstant dummy = graph.addConstant(constant, _closedWorld);
receiverArgument.usedBy.remove(node);
node.inputs[1] = dummy;
@@ -372,6 +380,8 @@
for (HInstruction user in instruction.usedBy) {
if (user is HTypeConversion) {
user.inputType = instruction.instructionType;
+ } else if (user is HPrimitiveCheck) {
+ user.inputType = instruction.instructionType;
}
}
instruction.block.rewrite(instruction, instruction.checkedInput);
@@ -379,7 +389,7 @@
}
}
-/// Remove [HTypeConversion] instructions from the graph in '--trust-primitives'
+/// Remove [HPrimitiveCheck] instructions from the graph in '--trust-primitives'
/// mode.
class SsaTrustedCheckRemover extends HBaseVisitor with CodegenPhase {
final CompilerOptions _options;
@@ -403,11 +413,15 @@
}
@override
- void visitTypeConversion(HTypeConversion instruction) {
- if (instruction.isReceiverTypeCheck || instruction.isArgumentTypeCheck) {
- instruction.block.rewrite(instruction, instruction.checkedInput);
- instruction.block.remove(instruction);
- }
+ void visitPrimitiveCheck(HPrimitiveCheck instruction) {
+ instruction.block.rewrite(instruction, instruction.checkedInput);
+ instruction.block.remove(instruction);
+ }
+
+ @override
+ void visitBoolConversion(HBoolConversion instruction) {
+ instruction.block.rewrite(instruction, instruction.checkedInput);
+ instruction.block.remove(instruction);
}
}
@@ -589,7 +603,6 @@
/// t2 = add(4, 3);
class SsaInstructionMerger extends HBaseVisitor with CodegenPhase {
final AbstractValueDomain _abstractValueDomain;
- final SuperMemberData _superMemberData;
/// List of [HInstruction] that the instruction merger expects in
/// order when visiting the inputs of an instruction.
@@ -606,8 +619,7 @@
generateAtUseSite.add(instruction);
}
- SsaInstructionMerger(
- this._abstractValueDomain, this.generateAtUseSite, this._superMemberData);
+ SsaInstructionMerger(this._abstractValueDomain, this.generateAtUseSite);
@override
void visitGraph(HGraph graph) {
@@ -693,7 +705,7 @@
// after first access if we use lazy initialization.
// In this case, we therefore don't allow the receiver (the first argument)
// to be generated at use site, and only analyze all other arguments.
- if (!_superMemberData.canUseAliasedSuperMember(superMethod, selector)) {
+ if (!canUseAliasedSuperMember(superMethod, selector)) {
analyzeInputs(instruction, 1);
} else {
super.visitInvokeSuper(instruction);
@@ -737,16 +749,15 @@
@override
void visitTypeConversion(HTypeConversion instruction) {
- if (!instruction.isArgumentTypeCheck && !instruction.isReceiverTypeCheck) {
- assert(instruction.isCheckedModeCheck || instruction.isCastTypeCheck);
- // Checked mode checks and cast checks compile to code that
- // only use their input once, so we can safely visit them
- // and try to merge the input.
- visitInstruction(instruction);
- }
+ // Type checks and cast checks compile to code that only use their input
+ // once, so we can safely visit them and try to merge the input.
+ visitInstruction(instruction);
}
@override
+ void visitPrimitiveCheck(HPrimitiveCheck instruction) {}
+
+ @override
void visitTypeKnown(HTypeKnown instruction) {
// [HTypeKnown] instructions are removed before code generation.
assert(false);
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index 0a99d31..cdfb2a9 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -214,30 +214,18 @@
_registerSpecializer(original, null, null, 'Round');
}
- void registerTypeConversion(
- HInstruction original, HTypeConversion converted) {
+ void registerPrimitiveCheck(HInstruction original, HPrimitiveCheck check) {
Features features = new Features();
- switch (converted.kind) {
- case HTypeConversion.CHECKED_MODE_CHECK:
- features['kind'] = 'checked';
- break;
- case HTypeConversion.ARGUMENT_TYPE_CHECK:
- features['kind'] = 'argument';
- break;
- case HTypeConversion.CAST_TYPE_CHECK:
- features['kind'] = 'cast';
- break;
- case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
- features['kind'] = 'boolean';
- break;
- case HTypeConversion.RECEIVER_TYPE_CHECK:
- features['kind'] = 'receiver';
- break;
+
+ if (check.isReceiverTypeCheck) {
+ features['kind'] = 'receiver';
+ } else if (check.isArgumentTypeCheck) {
+ features['kind'] = 'argument';
}
- if (converted.typeExpression != null) {
- features['type'] = '${converted.typeExpression}';
+ if (check.typeExpression != null) {
+ features['type'] = '${check.typeExpression}';
}
- entries.add(new OptimizationLogEntry('TypeConversion', features));
+ entries.add(new OptimizationLogEntry('PrimitiveCheck', features));
}
String getText() {
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index a893874..db7f6f6 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -8,7 +8,6 @@
import '../common.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
-import '../deferred_load.dart' show OutputUnit;
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/types.dart';
@@ -31,7 +30,6 @@
R visitBitNot(HBitNot node);
R visitBitOr(HBitOr node);
R visitBitXor(HBitXor node);
- R visitBoolify(HBoolify node);
R visitBoundsCheck(HBoundsCheck node);
R visitBreak(HBreak node);
R visitConstant(HConstant node);
@@ -97,6 +95,8 @@
R visitTruncatingDivide(HTruncatingDivide node);
R visitTry(HTry node);
R visitTypeConversion(HTypeConversion node);
+ R visitPrimitiveCheck(HPrimitiveCheck node);
+ R visitBoolConversion(HBoolConversion node);
R visitTypeKnown(HTypeKnown node);
R visitYield(HYield node);
@@ -284,11 +284,9 @@
return result;
}
- HConstant addDeferredConstant(ConstantValue constant, OutputUnit unit,
+ HConstant addDeferredConstant(DeferredGlobalConstantValue constant,
SourceInformation sourceInformation, JClosedWorld closedWorld) {
- ConstantValue wrapper = new DeferredGlobalConstantValue(constant, unit);
- closedWorld.outputUnitData.registerConstantDeferredUse(wrapper, unit);
- return addConstant(wrapper, closedWorld,
+ return addConstant(constant, closedWorld,
sourceInformation: sourceInformation);
}
@@ -326,10 +324,7 @@
HConstant addConstantUnreachable(JClosedWorld closedWorld) {
// A constant with an empty type used as the HInstruction of an expression
// in an unreachable context.
- return addConstant(
- new AbstractValueConstantValue(
- closedWorld.abstractValueDomain.emptyType),
- closedWorld);
+ return addConstant(const UnreachableConstantValue(), closedWorld);
}
void finalize(AbstractValueDomain domain) {
@@ -436,8 +431,6 @@
@override
visitBitXor(HBitXor node) => visitBinaryBitOp(node);
@override
- visitBoolify(HBoolify node) => visitInstruction(node);
- @override
visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
@override
visitBreak(HBreak node) => visitJump(node);
@@ -576,6 +569,10 @@
@override
visitTypeConversion(HTypeConversion node) => visitCheck(node);
@override
+ visitBoolConversion(HBoolConversion node) => visitCheck(node);
+ @override
+ visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
+ @override
visitTypeKnown(HTypeKnown node) => visitCheck(node);
@override
visitAwait(HAwait node) => visitInstruction(node);
@@ -1022,7 +1019,6 @@
// Type codes.
static const int UNDEFINED_TYPECODE = -1;
- static const int BOOLIFY_TYPECODE = 0;
static const int TYPE_GUARD_TYPECODE = 1;
static const int BOUNDS_CHECK_TYPECODE = 2;
static const int INTEGER_CHECK_TYPECODE = 3;
@@ -1065,6 +1061,8 @@
static const int REMAINDER_TYPECODE = 42;
static const int GET_LENGTH_TYPECODE = 43;
static const int ABS_TYPECODE = 44;
+ static const int BOOL_CONVERSION_TYPECODE = 45;
+ static const int PRIMITIVE_CHECK_TYPECODE = 46;
HInstruction(this.inputs, this.instructionType)
: id = idCounter++,
@@ -1371,11 +1369,7 @@
closedWorld.abstractValueDomain.dynamicType, this, sourceInformation);
}
assert(type.isInterfaceType);
- if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
- // Boolean conversion checks work on non-nullable booleans.
- return new HTypeConversion(type, kind,
- closedWorld.abstractValueDomain.boolType, this, sourceInformation);
- } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
+ if (kind == HTypeConversion.TYPE_CHECK && !type.treatAsRaw) {
throw 'creating compound check to $type (this = ${this})';
} else {
InterfaceType interfaceType = type;
@@ -1561,23 +1555,6 @@
: super(inputs, type);
}
-class HBoolify extends HInstruction {
- HBoolify(HInstruction value, AbstractValue type)
- : super(<HInstruction>[value], type) {
- setUseGvn();
- sourceInformation = value.sourceInformation;
- }
-
- @override
- accept(HVisitor visitor) => visitor.visitBoolify(this);
- @override
- int typeCode() => HInstruction.BOOLIFY_TYPECODE;
- @override
- bool typeEquals(other) => other is HBoolify;
- @override
- bool dataEquals(HInstruction other) => true;
-}
-
/// A [HCheck] instruction is an instruction that might do a dynamic
/// check at runtime on another instruction. To have proper instruction
/// dependencies in the graph, instructions that depend on the check
@@ -3514,58 +3491,33 @@
class HTypeConversion extends HCheck {
// Values for [kind].
- static const int CHECKED_MODE_CHECK = 0;
- static const int ARGUMENT_TYPE_CHECK = 1;
- static const int CAST_TYPE_CHECK = 2;
- static const int BOOLEAN_CONVERSION_CHECK = 3;
- static const int RECEIVER_TYPE_CHECK = 4;
+ static const int TYPE_CHECK = 0;
+ static const int CAST_CHECK = 1;
final DartType typeExpression;
final int kind;
- // [receiverTypeCheckSelector] is the selector used for a receiver type check
- // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
- // compiled to the following, for which we need the selector `$add`.
- //
- // if (typeof x != "number") x.$add();
- //
- final Selector receiverTypeCheckSelector;
AbstractValue checkedType; // Not final because we refine it.
AbstractValue
inputType; // Holds input type for codegen after HTypeKnown removal.
HTypeConversion(this.typeExpression, this.kind, AbstractValue type,
- HInstruction input, SourceInformation sourceInformation,
- {this.receiverTypeCheckSelector})
+ HInstruction input, SourceInformation sourceInformation)
: checkedType = type,
super(<HInstruction>[input], type) {
- assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
assert(typeExpression == null || !typeExpression.isTypedef);
- assert(!isControlFlow() || typeExpression != null);
- sourceElement = input.sourceElement;
+ this.sourceElement = input.sourceElement;
this.sourceInformation = sourceInformation;
}
HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
AbstractValue type, HInstruction input, HInstruction typeRepresentation)
: checkedType = type,
- receiverTypeCheckSelector = null,
super(<HInstruction>[input, typeRepresentation], type) {
assert(!typeExpression.isTypedef);
sourceElement = input.sourceElement;
}
- HTypeConversion.viaMethodOnType(this.typeExpression, this.kind,
- AbstractValue type, HInstruction reifiedType, HInstruction input)
- : checkedType = type,
- receiverTypeCheckSelector = null,
- super(<HInstruction>[reifiedType, input], type) {
- // This form is currently used only for function types.
- assert(typeExpression.isFunctionType);
- assert(kind == CHECKED_MODE_CHECK || kind == CAST_TYPE_CHECK);
- sourceElement = input.sourceElement;
- }
-
bool get hasTypeRepresentation {
return typeExpression != null &&
typeExpression.isInterfaceType &&
@@ -3580,23 +3532,13 @@
@override
HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
if (typeExpression == type) {
- // Don't omit a boolean conversion (which doesn't allow `null`) unless
- // this type conversion is already a boolean conversion.
- if (kind != BOOLEAN_CONVERSION_CHECK || isBooleanConversionCheck) {
- return this;
- }
+ return this;
}
return super.convertType(closedWorld, type, kind);
}
- bool get isCheckedModeCheck {
- return kind == CHECKED_MODE_CHECK || kind == BOOLEAN_CONVERSION_CHECK;
- }
-
- bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
- bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
- bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
- bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;
+ bool get isTypeCheck => kind == TYPE_CHECK;
+ bool get isCastCheck => kind == CAST_CHECK;
@override
accept(HVisitor visitor) => visitor.visitTypeConversion(this);
@@ -3604,7 +3546,7 @@
@override
bool isJsStatement() => isControlFlow();
@override
- bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;
+ bool isControlFlow() => false;
@override
int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
@@ -3617,8 +3559,7 @@
bool dataEquals(HTypeConversion other) {
return kind == other.kind &&
typeExpression == other.typeExpression &&
- checkedType == other.checkedType &&
- receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+ checkedType == other.checkedType;
}
bool isRedundant(JClosedWorld closedWorld) {
@@ -3666,6 +3607,130 @@
'checkedInput=$checkedInput)';
}
+/// Check for receiver or argument type when lowering operation to a primitive,
+/// e.g. lowering `+` to [HAdd].
+///
+/// After NNBD, `a + b` will require `a` and `b` are non-nullable and these
+/// checks will become explicit in the source (e.g. `a! + b!`). At that time,
+/// this check should be removed. If needed, the `!` check can be optimized
+/// give the same signals to the JavaScript VM.
+class HPrimitiveCheck extends HCheck {
+ // Values for [kind].
+ static const int ARGUMENT_TYPE_CHECK = 1;
+ static const int RECEIVER_TYPE_CHECK = 3;
+
+ final DartType typeExpression;
+ final int kind;
+
+ // [receiverTypeCheckSelector] is the selector used for a receiver type check
+ // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
+ // compiled to the following, for which we need the selector `$add`.
+ //
+ // if (typeof x != "number") x.$add();
+ //
+ final Selector receiverTypeCheckSelector;
+
+ AbstractValue checkedType; // Not final because we refine it.
+ AbstractValue
+ inputType; // Holds input type for codegen after HTypeKnown removal.
+
+ HPrimitiveCheck(this.typeExpression, this.kind, AbstractValue type,
+ HInstruction input, SourceInformation sourceInformation,
+ {this.receiverTypeCheckSelector})
+ : checkedType = type,
+ super(<HInstruction>[input], type) {
+ assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
+ this.sourceElement = input.sourceElement;
+ this.sourceInformation = sourceInformation;
+ }
+
+ @override
+ HInstruction convertType(JClosedWorld closedWorld, DartType type, int kind) {
+ if (typeExpression == type) {
+ return this;
+ }
+ return super.convertType(closedWorld, type, kind);
+ }
+
+ bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
+ bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
+
+ @override
+ accept(HVisitor visitor) => visitor.visitPrimitiveCheck(this);
+
+ @override
+ bool isJsStatement() => true;
+ @override
+ bool isControlFlow() => true;
+
+ @override
+ int typeCode() => HInstruction.PRIMITIVE_CHECK_TYPECODE;
+ @override
+ bool typeEquals(HInstruction other) => other is HPrimitiveCheck;
+ @override
+ bool isCodeMotionInvariant() => false;
+
+ @override
+ bool dataEquals(HPrimitiveCheck other) {
+ return kind == other.kind &&
+ checkedType == other.checkedType &&
+ receiverTypeCheckSelector == other.receiverTypeCheckSelector;
+ }
+
+ bool isRedundant(JClosedWorld closedWorld) {
+ AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+ // Type is refined from `dynamic`, so it might become non-redundant.
+ if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
+ return false;
+ }
+ AbstractValue inputType = checkedInput.instructionType;
+ return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
+ }
+
+ @override
+ String toString() => 'HPrimitiveCheck(checkedType=$checkedType, kind=$kind, '
+ 'checkedInput=$checkedInput)';
+}
+
+/// A check that the input to a condition (if, ?:, while, etc) is non-null. The
+/// front-end generates 'as bool' checks, but until the transition to NNBD is
+/// complete, this allows `null` to be passed to the condition.
+///
+// TODO(sra): Once NNDB is far enough along that the front-end can generate `as
+// bool!` checks and the backend checks them correctly, this instruction will
+// become unnecessary and should be removed.
+class HBoolConversion extends HCheck {
+ HBoolConversion(HInstruction input, AbstractValue type)
+ : super(<HInstruction>[input], type);
+
+ @override
+ bool isJsStatement() => false;
+
+ @override
+ bool isCodeMotionInvariant() => false;
+
+ @override
+ accept(HVisitor visitor) => visitor.visitBoolConversion(this);
+
+ @override
+ int typeCode() => HInstruction.BOOL_CONVERSION_TYPECODE;
+ @override
+ bool typeEquals(HInstruction other) => other is HBoolConversion;
+ @override
+ bool dataEquals(HBoolConversion other) => true;
+
+ bool isRedundant(JClosedWorld closedWorld) {
+ AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
+ AbstractValue inputType = checkedInput.instructionType;
+ return abstractValueDomain
+ .isIn(inputType, instructionType)
+ .isDefinitelyTrue;
+ }
+
+ @override
+ toString() => 'HBoolConversion($checkedInput)';
+}
+
/// The [HTypeKnown] instruction marks a value with a refined type.
class HTypeKnown extends HCheck {
AbstractValue knownType;
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 91a06794f..249121e 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -439,33 +439,6 @@
}
@override
- HInstruction visitBoolify(HBoolify node) {
- List<HInstruction> inputs = node.inputs;
- assert(inputs.length == 1);
- HInstruction input = inputs[0];
- if (input.isBoolean(_abstractValueDomain).isDefinitelyTrue) {
- return input;
- }
-
- // If the code is unreachable, remove the HBoolify. This can happen when
- // there is a throw expression in a short-circuit conditional. Removing the
- // unreachable HBoolify makes it easier to reconstruct the short-circuit
- // operation.
- if (_abstractValueDomain.isEmpty(input.instructionType).isDefinitelyTrue) {
- return input;
- }
-
- // All values that cannot be 'true' are boolified to false.
- AbstractValue mask = input.instructionType;
- if (_abstractValueDomain
- .containsType(mask, commonElements.jsBoolClass)
- .isPotentiallyFalse) {
- return _graph.addConstantBool(false, _closedWorld);
- }
- return node;
- }
-
- @override
HInstruction visitNot(HNot node) {
List<HInstruction> inputs = node.inputs;
assert(inputs.length == 1);
@@ -925,23 +898,8 @@
return node;
}
- bool allUsersAreBoolifies(HInstruction instruction) {
- List<HInstruction> users = instruction.usedBy;
- int length = users.length;
- for (int i = 0; i < length; i++) {
- if (users[i] is! HBoolify) return false;
- }
- return true;
- }
-
@override
HInstruction visitRelational(HRelational node) {
- if (allUsersAreBoolifies(node)) {
- // TODO(ngeoffray): Call a boolified selector.
- // This node stays the same, but the Boolify node will go away.
- }
- // Note that we still have to call [super] to make sure that we end up
- // in the remaining optimizations.
return super.visitRelational(node);
}
@@ -1161,6 +1119,18 @@
}
@override
+ HInstruction visitPrimitiveCheck(HPrimitiveCheck node) {
+ if (node.isRedundant(_closedWorld)) return node.checkedInput;
+ return node;
+ }
+
+ @override
+ HInstruction visitBoolConversion(HBoolConversion node) {
+ if (node.isRedundant(_closedWorld)) return node.checkedInput;
+ return node;
+ }
+
+ @override
HInstruction visitTypeKnown(HTypeKnown node) {
return node.isRedundant(_closedWorld) ? node.checkedInput : node;
}
@@ -1364,8 +1334,8 @@
node.needsCheck = true;
return node;
}
- HInstruction other = value.convertType(
- _closedWorld, type, HTypeConversion.CHECKED_MODE_CHECK);
+ HInstruction other =
+ value.convertType(_closedWorld, type, HTypeConversion.TYPE_CHECK);
if (other != value) {
node.block.addBefore(node, other);
value = other;
@@ -1955,8 +1925,7 @@
HInstruction get zapInstruction {
if (zapInstructionCache == null) {
// A constant with no type does not pollute types at phi nodes.
- ConstantValue constant =
- new AbstractValueConstantValue(_abstractValueDomain.emptyType);
+ ConstantValue constant = const UnreachableConstantValue();
zapInstructionCache = analyzer.graph.addConstant(constant, closedWorld);
}
return zapInstructionCache;
@@ -2929,10 +2898,6 @@
collectTargets(user, trueTargets, null);
}
}
- } else if (user is HBoolify) {
- // We collect targets for strictly boolean operations so HBoolify cannot
- // change the result.
- collectTargets(user, trueTargets, falseTargets);
}
}
}
diff --git a/pkg/compiler/lib/src/ssa/ssa_tracer.dart b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
index 9a5b4ca..db7b380 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -173,11 +173,6 @@
return "LateValue: ${temporaryId(node.inputs[0])}";
}
- @override
- String visitBoolify(HBoolify node) {
- return "Boolify: ${temporaryId(node.inputs[0])}";
- }
-
String handleInvokeBinary(HInvokeBinary node, String opcode) {
String left = temporaryId(node.left);
String right = temporaryId(node.right);
@@ -609,22 +604,32 @@
}
String _typeConversionKind(HTypeConversion node) {
- switch (node.kind) {
- case HTypeConversion.CHECKED_MODE_CHECK:
- return 'CHECKED_MODE';
- case HTypeConversion.ARGUMENT_TYPE_CHECK:
- return 'ARGUMENT';
- case HTypeConversion.CAST_TYPE_CHECK:
- return 'CAST';
- case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
- return 'BOOLEAN_CONVERSION';
- case HTypeConversion.RECEIVER_TYPE_CHECK:
- return 'RECEIVER';
- }
+ if (node.isTypeCheck) return 'TYPE_CHECK';
+ if (node.isCastCheck) return 'CAST_CHECK';
return '?';
}
@override
+ String visitPrimitiveCheck(HPrimitiveCheck node) {
+ String checkedInput = temporaryId(node.checkedInput);
+ assert(node.inputs.length == 1);
+ String kind = _primitiveCheckKind(node);
+ return "PrimitiveCheck: $kind $checkedInput to ${node.instructionType}";
+ }
+
+ String _primitiveCheckKind(HPrimitiveCheck node) {
+ if (node.isReceiverTypeCheck) return 'RECEIVER';
+ if (node.isArgumentTypeCheck) return 'ARGUMENT';
+ return '?';
+ }
+
+ @override
+ String visitBoolConversion(HBoolConversion node) {
+ String checkedInput = temporaryId(node.checkedInput);
+ return "BoolConversion: $checkedInput";
+ }
+
+ @override
String visitTypeKnown(HTypeKnown node) {
assert(node.inputs.length <= 2);
String result =
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index 710338c..0a5d8fe 100644
--- a/pkg/compiler/lib/src/ssa/type_builder.dart
+++ b/pkg/compiler/lib/src/ssa/type_builder.dart
@@ -85,6 +85,19 @@
return other;
}
+ /// Produces code that checks the runtime type is actually the type specified
+ /// by attempting a type conversion.
+ HInstruction _checkBoolConverion(HInstruction original) {
+ var checkInstruction =
+ HBoolConversion(original, _abstractValueDomain.boolType);
+ if (checkInstruction.isRedundant(_closedWorld)) {
+ return original;
+ }
+ DartType boolType = _closedWorld.commonElements.boolType;
+ builder.registry?.registerTypeUse(new TypeUse.isCheck(boolType));
+ return checkInstruction;
+ }
+
HInstruction trustTypeOfParameter(HInstruction original, DartType type) {
if (type == null) return original;
HInstruction trusted = _trustType(original, type);
@@ -103,8 +116,7 @@
if (builder.options.parameterCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, type);
} else if (builder.options.parameterCheckPolicy.isEmitted) {
- checkedOrTrusted =
- _checkType(original, type, HTypeConversion.CHECKED_MODE_CHECK);
+ checkedOrTrusted = _checkType(original, type, HTypeConversion.TYPE_CHECK);
}
if (checkedOrTrusted == original) return original;
builder.add(checkedOrTrusted);
@@ -116,7 +128,7 @@
/// trusts the written type.
HInstruction potentiallyCheckOrTrustTypeOfAssignment(
HInstruction original, DartType type,
- {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
+ {int kind: HTypeConversion.TYPE_CHECK}) {
if (type == null) return original;
HInstruction checkedOrTrusted = original;
if (builder.options.assignmentCheckPolicy.isTrusted) {
@@ -135,8 +147,7 @@
if (builder.options.conditionCheckPolicy.isTrusted) {
checkedOrTrusted = _trustType(original, boolType);
} else if (builder.options.conditionCheckPolicy.isEmitted) {
- checkedOrTrusted = _checkType(
- original, boolType, HTypeConversion.BOOLEAN_CONVERSION_CHECK);
+ checkedOrTrusted = _checkBoolConverion(original);
}
if (checkedOrTrusted == original) return original;
builder.add(checkedOrTrusted);
@@ -262,8 +273,6 @@
return result;
}
- bool get checkOrTrustTypes => true;
-
/// Build a [HTypeConversion] for converting [original] to type [type].
///
/// Invariant: [type] must be valid in the context.
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 7079eec..257ce71 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -222,24 +222,29 @@
HInstruction input = instruction.checkedInput;
AbstractValue inputType = input.instructionType;
AbstractValue checkedType = instruction.checkedType;
- if (instruction.isArgumentTypeCheck || instruction.isReceiverTypeCheck) {
- // We must make sure a type conversion for receiver or argument check
- // does not try to do an int check, because an int check is not enough.
- // We only do an int check if the input is integer or null.
- if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
- abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
- input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
- instruction.checkedType = abstractValueDomain.intType;
- } else if (abstractValueDomain
- .isIntegerOrNull(checkedType)
- .isDefinitelyTrue &&
- input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
- instruction.checkedType = abstractValueDomain.numType;
- }
- }
-
AbstractValue outputType =
abstractValueDomain.intersection(checkedType, inputType);
+ outputType = _numericFixup(outputType, inputType, checkedType);
+ if (inputType != outputType) {
+ // Replace dominated uses of input with uses of this HTypeConversion so
+ // the uses benefit from the stronger type.
+ //
+ // The dependency on the checked value also improves the generated
+ // JavaScript. Many checks are compiled to a function call expression that
+ // returns the checked result, so the check can be generated as a
+ // subexpression rather than a separate statement.
+ //
+ // Do not replace local accesses, since the local must be a HLocalValue,
+ // not a HTypeConversion.
+ if (!(input is HParameterValue && input.usedAsVariable())) {
+ input.replaceAllUsersDominatedBy(instruction.next, instruction);
+ }
+ }
+ return outputType;
+ }
+
+ AbstractValue _numericFixup(AbstractValue outputType, AbstractValue inputType,
+ AbstractValue checkedType) {
if (abstractValueDomain.isEmpty(outputType).isDefinitelyTrue) {
// Intersection of double and integer conflicts (is empty), but JS numbers
// can be both int and double at the same time. For example, the input
@@ -257,17 +262,38 @@
}
}
}
+ return outputType;
+ }
+
+ @override
+ AbstractValue visitPrimitiveCheck(HPrimitiveCheck instruction) {
+ HInstruction input = instruction.checkedInput;
+ AbstractValue inputType = input.instructionType;
+ AbstractValue checkedType = instruction.checkedType;
+
+ // We must make sure a receiver or argument check does not try to do an int
+ // check, because an int check is not enough. We only do an int check if
+ // the input is integer or null.
+ if (abstractValueDomain.isNumberOrNull(checkedType).isDefinitelyTrue &&
+ abstractValueDomain.isDoubleOrNull(checkedType).isDefinitelyFalse &&
+ input.isIntegerOrNull(abstractValueDomain).isDefinitelyTrue) {
+ instruction.checkedType = abstractValueDomain.intType;
+ } else if (abstractValueDomain
+ .isIntegerOrNull(checkedType)
+ .isDefinitelyTrue &&
+ input.isIntegerOrNull(abstractValueDomain).isPotentiallyFalse) {
+ instruction.checkedType = abstractValueDomain.numType;
+ }
+
+ AbstractValue outputType =
+ abstractValueDomain.intersection(checkedType, inputType);
+ outputType = _numericFixup(outputType, inputType, checkedType);
if (inputType != outputType) {
- // Replace dominated uses of input with uses of this HTypeConversion so
+ // Replace dominated uses of input with uses of this HPrimitiveCheck so
// the uses benefit from the stronger type.
//
- // The dependency on the checked value also improves the generated
- // JavaScript. Many checks are compiled to a function call expression that
- // returns the checked result, so the check can be generated as a
- // subexpression rather than a separate statement.
- //
- // Do not replace local accesses, since the local must be a HLocalValue,
- // not a HTypeConversion.
+ // Do not replace local variable accesses, since the local must be a
+ // HLocalValue, not another kind of instruction.
if (!(input is HParameterValue && input.usedAsVariable())) {
input.replaceAllUsersDominatedBy(instruction.next, instruction);
}
@@ -289,15 +315,17 @@
void convertInput(HInvokeDynamic instruction, HInstruction input,
AbstractValue type, int kind, DartType typeExpression) {
- Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
+ assert(kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK ||
+ kind == HPrimitiveCheck.ARGUMENT_TYPE_CHECK);
+ Selector selector = (kind == HPrimitiveCheck.RECEIVER_TYPE_CHECK)
? instruction.selector
: null;
- HTypeConversion converted = new HTypeConversion(
+ HPrimitiveCheck converted = new HPrimitiveCheck(
typeExpression, kind, type, input, instruction.sourceInformation,
receiverTypeCheckSelector: selector);
instruction.block.addBefore(instruction, converted);
input.replaceAllUsersDominatedBy(instruction, converted);
- _log?.registerTypeConversion(instruction, converted);
+ _log?.registerPrimitiveCheck(instruction, converted);
}
bool isCheckEnoughForNsmOrAe(HInstruction instruction, AbstractValue type) {
@@ -327,7 +355,7 @@
instruction,
receiver,
abstractValueDomain.excludeNull(receiver.instructionType),
- HTypeConversion.RECEIVER_TYPE_CHECK,
+ HPrimitiveCheck.RECEIVER_TYPE_CHECK,
commonElements.numType);
return true;
} else if (instruction.element == null) {
@@ -353,7 +381,7 @@
if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
instruction.element = target;
convertInput(instruction, receiver, type,
- HTypeConversion.RECEIVER_TYPE_CHECK, typeExpression);
+ HPrimitiveCheck.RECEIVER_TYPE_CHECK, typeExpression);
return true;
}
}
@@ -382,7 +410,7 @@
// still add a check because it allows to GVN these operations,
// but we should find a better way.
convertInput(instruction, right, type,
- HTypeConversion.ARGUMENT_TYPE_CHECK, commonElements.numType);
+ HPrimitiveCheck.ARGUMENT_TYPE_CHECK, commonElements.numType);
return true;
}
return false;
diff --git a/pkg/compiler/lib/src/universe/class_hierarchy.dart b/pkg/compiler/lib/src/universe/class_hierarchy.dart
index 776b4f1..49a899e 100644
--- a/pkg/compiler/lib/src/universe/class_hierarchy.dart
+++ b/pkg/compiler/lib/src/universe/class_hierarchy.dart
@@ -195,10 +195,12 @@
getClassHierarchyNode(_commonElements.objectClass);
node.forEachSubclass((ClassEntity cls) {
getClassHierarchyNode(cls).writeToDataSink(sink);
+ return null;
}, ClassHierarchyNode.ALL);
ClassSet set = getClassSet(_commonElements.objectClass);
set.forEachSubclass((ClassEntity cls) {
getClassSet(cls).writeToDataSink(sink);
+ return null;
}, ClassHierarchyNode.ALL);
sink.end(tag);
}
@@ -836,6 +838,7 @@
if (builder._isSubtypeOf(z, y)) {
classes.add(z);
}
+ return null;
}, ClassHierarchyNode.ALL, strict: strict);
}
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 9b26699..afe16e0 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -10,6 +10,7 @@
import '../constants/values.dart';
import '../elements/entities.dart';
import '../elements/types.dart';
+import '../js_backend/interceptor_data.dart' show OneShotInterceptorData;
import '../js_backend/native_data.dart' show NativeBasicData;
import '../js_model/elements.dart';
import '../util/enumset.dart';
@@ -87,11 +88,17 @@
/// an ordering that is less sensitive to perturbations in the source code.
Iterable<ConstantValue> getConstantsForEmission(
[Comparator<ConstantValue> preSortCompare]);
+
+ /// Returns `true` if [member] is called from a subclass via `super`.
+ bool isAliasedSuperMember(MemberEntity member);
+
+ OneShotInterceptorData get oneShotInterceptorData;
}
class CodegenWorldBuilderImpl extends WorldBuilderBase
implements CodegenWorldBuilder {
final JClosedWorld _closedWorld;
+ final OneShotInterceptorData _oneShotInterceptorData;
/// The set of all directly instantiated classes, that is, classes with a
/// generative constructor that has been called directly and not only through
@@ -154,7 +161,8 @@
final Set<DartType> _constTypeLiterals = new Set<DartType>();
final Set<DartType> _liveTypeArguments = new Set<DartType>();
- CodegenWorldBuilderImpl(this._closedWorld, this._selectorConstraintsStrategy);
+ CodegenWorldBuilderImpl(this._closedWorld, this._selectorConstraintsStrategy,
+ this._oneShotInterceptorData);
ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
@@ -582,7 +590,8 @@
invokedGetters: _invokedGetters,
invokedSetters: _invokedSetters,
staticTypeArgumentDependencies: staticTypeArgumentDependencies,
- dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies);
+ dynamicTypeArgumentDependencies: dynamicTypeArgumentDependencies,
+ oneShotInterceptorData: _oneShotInterceptorData);
}
}
@@ -624,6 +633,9 @@
final Map<Selector, Set<DartType>> _dynamicTypeArgumentDependencies;
+ @override
+ final OneShotInterceptorData oneShotInterceptorData;
+
CodegenWorldImpl(this._closedWorld, this._liveMemberUsage,
{this.constTypeLiterals,
this.directlyInstantiatedClasses,
@@ -637,7 +649,8 @@
Map<String, Map<Selector, SelectorConstraints>> invokedGetters,
Map<String, Map<Selector, SelectorConstraints>> invokedSetters,
Map<Entity, Set<DartType>> staticTypeArgumentDependencies,
- Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies})
+ Map<Selector, Set<DartType>> dynamicTypeArgumentDependencies,
+ this.oneShotInterceptorData})
: _compiledConstants = compiledConstants,
_invokedNames = invokedNames,
_invokedGetters = invokedGetters,
@@ -866,4 +879,12 @@
}
return result;
}
+
+ @override
+ bool isAliasedSuperMember(MemberEntity member) {
+ MemberUsage usage = _liveMemberUsage[member];
+ if (usage == null) return false;
+ return usage.invokes.contains(Access.superAccess) ||
+ usage.writes.contains(Access.superAccess);
+ }
}
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index d062fc5..5e124f3 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -901,9 +901,12 @@
/// Type constant used for registration of custom elements.
ConstantUse.customElements(TypeConstantValue value) : this._(value);
- /// Constant literal used on code.
+ /// Constant literal used in code.
ConstantUse.literal(ConstantValue value) : this._(value);
+ /// Deferred constant used in code.
+ ConstantUse.deferred(DeferredGlobalConstantValue value) : this._(value);
+
@override
bool operator ==(other) {
if (identical(this, other)) return true;
diff --git a/pkg/compiler/tool/modular_dart2js.dart b/pkg/compiler/tool/modular_dart2js.dart
new file mode 100644
index 0000000..f8e15e3
--- /dev/null
+++ b/pkg/compiler/tool/modular_dart2js.dart
@@ -0,0 +1,180 @@
+// 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 'dart:convert';
+import 'dart:io';
+import 'package:compiler/src/commandline_options.dart';
+
+main(List<String> args) async {
+ Stopwatch stopwatch = new Stopwatch();
+ String input;
+ String serializedInput;
+ String output = 'out.js';
+ List<String> arguments = [];
+ int start = 0;
+ int stop = 3;
+ int shards;
+ bool enableAssertions = false;
+ for (String arg in args) {
+ if (arg.startsWith('-')) {
+ if (arg.startsWith('--start=')) {
+ start = int.parse(arg.substring('--start='.length));
+ } else if (arg.startsWith('--stop=')) {
+ stop = int.parse(arg.substring('--stop='.length));
+ } else if (arg.startsWith('--shards=')) {
+ shards = int.parse(arg.substring('--shards='.length));
+ } else if (arg == '-ea' || arg == '--enable_asserts') {
+ enableAssertions = true;
+ } else if (arg.startsWith('--in=')) {
+ serializedInput = arg.substring('--in='.length);
+ } else if (arg.startsWith('-o')) {
+ output = arg.substring('-o'.length);
+ } else if (arg.startsWith('--out=')) {
+ output = arg.substring('--out='.length);
+ } else {
+ arguments.add(arg);
+ }
+ } else {
+ if (input != null) {
+ print("Multiple entrypoints provided: '${input}' and '${arg}'.");
+ exit(-1);
+ }
+ input = arg;
+ }
+ }
+
+ if (input == null) {
+ print("No entrypoint provided.");
+ exit(-1);
+ }
+
+ serializedInput ??= output;
+
+ String inputPrefix = serializedInput;
+ if (serializedInput.endsWith('.js')) {
+ inputPrefix = output.substring(0, output.length - '.js'.length);
+ }
+ String outputPrefix = output;
+ if (output.endsWith('.js')) {
+ outputPrefix = output.substring(0, output.length - '.js'.length);
+ }
+
+ List<String> baseOptions = ['--packages=${Platform.packageConfig}'];
+ if (enableAssertions) {
+ baseOptions.add('--enable_asserts');
+ }
+ baseOptions.add('package:compiler/src/dart2js.dart');
+ baseOptions.addAll(arguments);
+
+ String cfeOutput = '${inputPrefix}0.dill';
+ String dillOutput = '${inputPrefix}.dill';
+ String dataOutput = '${inputPrefix}.dill.data';
+ String codeOutput = '${outputPrefix}.code';
+ shards ??= 2;
+
+ stopwatch.start();
+ if (start <= 0 && stop >= 0) {
+ await subProcess(
+ baseOptions, [input, Flags.cfeOnly, '--out=$cfeOutput'], '0:\t');
+ }
+ if (start <= 1 && stop >= 1) {
+ await subProcess(
+ baseOptions,
+ [cfeOutput, '--out=$dillOutput', '${Flags.writeData}=${dataOutput}'],
+ '1:\t');
+ }
+ if (shards <= 1) {
+ await subProcess(
+ baseOptions,
+ [dillOutput, '${Flags.readData}=${dataOutput}', '--out=${output}'],
+ '3:\t');
+ } else {
+ if (start <= 2 && stop >= 2) {
+ List<List<String>> additionalArguments = [];
+ List<String> outputPrefixes = [];
+ for (int shard = 0; shard < shards; shard++) {
+ additionalArguments.add([
+ dillOutput,
+ '${Flags.readData}=${dataOutput}',
+ '${Flags.codegenShard}=$shard',
+ '${Flags.codegenShards}=$shards',
+ '${Flags.writeCodegen}=${codeOutput}'
+ ]);
+ outputPrefixes.add('2:${shard + 1}/$shards\t');
+ }
+
+ Stopwatch subwatch = new Stopwatch();
+ subwatch.start();
+ await Future.wait(new List<Future>.generate(shards, (int shard) {
+ return subProcess(
+ baseOptions, additionalArguments[shard], outputPrefixes[shard]);
+ }));
+ subwatch.stop();
+ print('2:\tTotal time: ${_formatMs(subwatch.elapsedMilliseconds)}');
+ }
+ if (start <= 3 && stop >= 3) {
+ await subProcess(
+ baseOptions,
+ [
+ dillOutput,
+ '${Flags.readData}=${dataOutput}',
+ '${Flags.readCodegen}=${codeOutput}',
+ '${Flags.codegenShards}=$shards',
+ '--out=${output}'
+ ],
+ '3:\t');
+ }
+ }
+ stopwatch.stop();
+ print('Total time: ${_formatMs(stopwatch.elapsedMilliseconds)}');
+}
+
+Future subProcess(List<String> baseOptions, List<String> additionalOptions,
+ String outputPrefix) async {
+ List<String> options = []..addAll(baseOptions)..addAll(additionalOptions);
+ print(
+ '${outputPrefix}Command: ${Platform.resolvedExecutable} ${options.join(' ')}');
+ Process process = await Process.start(Platform.resolvedExecutable, options,
+ runInShell: true);
+ _Prefixer stdoutPrefixer = new _Prefixer(outputPrefix, stdout);
+ _Prefixer stderrOutputter = new _Prefixer(outputPrefix, stderr);
+ process.stdout.transform(utf8.decoder).listen(stdoutPrefixer);
+ process.stderr.transform(utf8.decoder).listen(stderrOutputter);
+
+ int exitCode = await process.exitCode;
+ if (exitCode != 0) {
+ exit(exitCode);
+ }
+}
+
+class _Prefixer {
+ final String _prefix;
+ final Stdout _stdout;
+ bool _atNewLine = true;
+
+ _Prefixer(this._prefix, this._stdout);
+
+ void call(String text) {
+ int index = 0;
+ while (index < text.length) {
+ if (_atNewLine) {
+ _stdout.write(_prefix);
+ _atNewLine = false;
+ }
+ int pos = text.indexOf('\n', index);
+ if (pos != -1) {
+ _stdout.write(text.substring(index, pos + 1));
+ _atNewLine = true;
+ index = pos + 1;
+ } else {
+ _stdout.write(text.substring(index));
+ index = text.length;
+ }
+ }
+ }
+}
+
+String _formatMs(int ms) {
+ return (ms / 1000).toStringAsFixed(3) + 's';
+}
diff --git a/pkg/dev_compiler/analysis_options.yaml b/pkg/dev_compiler/analysis_options.yaml
index 43cfad3..29c4ac1 100644
--- a/pkg/dev_compiler/analysis_options.yaml
+++ b/pkg/dev_compiler/analysis_options.yaml
@@ -1,4 +1,6 @@
analyzer:
+ strong-mode:
+ implicit-casts: false
errors:
todo: ignore
exclude:
@@ -29,5 +31,6 @@
- recursive_getters
- type_init_formals
- unnecessary_null_in_if_null_operators
+ - unrelated_type_equality_checks
- use_rethrow_when_possible
- valid_regexps
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index f97e1c2..3ff97b0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -24,7 +24,6 @@
import 'package:analyzer/src/generated/resolver.dart'
show TypeProvider, NamespaceBuilder;
import 'package:analyzer/src/generated/type_system.dart' show Dart2TypeSystem;
-import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/task/strong/ast_properties.dart';
import 'package:path/path.dart' as path;
@@ -428,7 +427,7 @@
String jsLibraryName(LibraryElement library) {
var uri = library.source.uri;
if (uri.scheme == 'dart') {
- return uri.path;
+ return isSdkInternalRuntime(library) ? 'dart' : uri.path;
}
// TODO(vsm): This is not necessarily unique if '__' appears in a file name.
var encodedSeparator = '__';
@@ -467,6 +466,10 @@
}
@override
+ Iterable<String> jsPartDebuggerNames(LibraryElement library) =>
+ library.parts.map((part) => part.uri);
+
+ @override
String libraryToModule(LibraryElement library) {
var source = library.source;
// TODO(jmesserly): we need to split out HTML.
@@ -610,7 +613,7 @@
@override
visitExportDirective(ExportDirective node) {
- ExportElement element = node.element;
+ var element = node.element as ExportElement;
var currentLibrary = element.library;
var currentNames = currentLibrary.publicNamespace.definedNames;
@@ -696,7 +699,7 @@
// TODO(jmesserly): fuse this with notNull check.
// TODO(jmesserly): this does not correctly distinguish user casts from
// required-for-soundness casts.
- return runtimeCall('asInt(#)', jsFrom);
+ return runtimeCall('asInt(#)', [jsFrom]);
}
// A no-op in JavaScript.
@@ -1544,7 +1547,7 @@
param = covariantParams.lookup(param) as ParameterElement;
if (param == null) continue;
- if (param.kind == ParameterKind.NAMED) {
+ if (param.isNamed) {
foundNamedParams = true;
var name = propertyName(param.name);
@@ -1557,10 +1560,12 @@
var jsParam = _emitParameter(param);
jsParams.add(jsParam);
- if (param.kind == ParameterKind.POSITIONAL) {
+ if (param.isPositional) {
body.add(js.statement('if (# !== void 0) #;',
[jsParam, _emitCast(param.type, jsParam)]));
} else {
+ //TODO(nshahan) Cleanup this logic. Do we need this else branch?
+ // https://github.com/dart-lang/sdk/issues/37123
body.add(_emitCast(param.type, jsParam).toStatement());
}
}
@@ -1834,8 +1839,8 @@
ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
var className = _emitTopLevelName(classElem);
if (jsTypeRep.isPrimitive(classElem.type)) {
- body.add(
- runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+ body.add(runtimeStatement(
+ 'definePrimitiveHashCode(#.prototype)', [className]));
}
body.add(runtimeStatement(
'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2175,6 +2180,10 @@
emitSignature('Setter', instanceSetters);
emitSignature('StaticGetter', staticGetters);
emitSignature('StaticSetter', staticSetters);
+ body.add(runtimeStatement('setLibraryUri(#, #)', [
+ className,
+ js.escapedString(jsLibraryDebuggerName(classElem.library))
+ ]));
}
{
@@ -2275,7 +2284,7 @@
JS.Block _emitConstructorBody(ConstructorDeclaration node,
List<VariableDeclaration> fields, JS.Expression className) {
var body = <JS.Statement>[];
- ClassDeclaration cls = node.parent;
+ var cls = node.parent as ClassDeclaration;
// Generate optional/named argument value assignment. These can not have
// side effects, and may be used by the constructor's initializers, so it's
@@ -2574,7 +2583,7 @@
}
if (node.isGetter || node.isSetter) {
- PropertyAccessorElement element = node.declaredElement;
+ var element = node.declaredElement as PropertyAccessorElement;
var pairAccessor = node.isGetter
? element.correspondingSetter
: element.correspondingGetter;
@@ -2718,7 +2727,7 @@
// Simplify `=> { return e; }` to `=> e`
if (body is JS.Block) {
- JS.Block block = body;
+ var block = body as JS.Block;
if (block.statements.length == 1) {
JS.Statement s = block.statements[0];
if (s is JS.Return && s.value != null) body = s.value;
@@ -3044,7 +3053,7 @@
// If the type is a type literal expression in Dart code, wrap the raw
// runtime type in a "Type" instance.
if (!_isInForeignJS && _isTypeLiteral(node)) {
- typeName = runtimeCall('wrapType(#)', typeName);
+ typeName = runtimeCall('wrapType(#)', [typeName]);
}
return typeName;
@@ -3283,7 +3292,7 @@
if (_isExternal(member)) {
var nativeName = _extensionTypes.getNativePeers(c);
if (nativeName.isNotEmpty) {
- return runtimeCall('global.#', nativeName[0]);
+ return runtimeCall('global.#', [nativeName[0]]);
}
}
return _emitTopLevelName(c);
@@ -3321,7 +3330,8 @@
// Anonymous JS types do not have a corresponding concrete JS type so we
// have to use a helper to define them.
if (_isObjectLiteral(element)) {
- return runtimeCall('anonymousJSType(#)', js.escapedString(element.name));
+ return runtimeCall(
+ 'anonymousJSType(#)', [js.escapedString(element.name)]);
}
var jsName = _getJSNameWithoutGlobal(element);
if (jsName != null) {
@@ -3772,7 +3782,8 @@
// Handle Object methods that are supported by `null`.
if (_isObjectMethodCall(name, argumentList.arguments) &&
isNullable(target)) {
- assert(typeArgs == null); // Object methods don't take type args.
+ assert(typeArgs == null ||
+ typeArgs.isEmpty); // Object methods don't take type args.
return runtimeCall('#(#, #)', [name, jsTarget, args]);
}
@@ -4142,16 +4153,26 @@
if (conditionType is FunctionType &&
conditionType.parameters.isEmpty &&
conditionType.returnType == types.boolType) {
- jsCondition = runtimeCall('test(#())', jsCondition);
+ jsCondition = runtimeCall('test(#())', [jsCondition]);
} else if (conditionType != types.boolType) {
- jsCondition = runtimeCall('dassert(#)', jsCondition);
+ jsCondition = runtimeCall('dassert(#)', [jsCondition]);
} else if (isNullable(condition)) {
- jsCondition = runtimeCall('test(#)', jsCondition);
+ jsCondition = runtimeCall('test(#)', [jsCondition]);
}
- return js.statement(' if (!#) #.assertFailed(#);', [
+
+ var location = _getLocation(condition.offset);
+ return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
jsCondition,
runtimeModule,
- message != null ? [_visitExpression(message)] : []
+ if (message == null)
+ JS.LiteralNull()
+ else
+ _visitExpression(message),
+ js.escapedString(location.sourceUrl.toString()),
+ // Lines and columns are typically printed with 1 based indexing.
+ js.number(location.line + 1),
+ js.number(location.column + 1),
+ js.escapedString(condition.toSource()),
]);
}
@@ -4552,7 +4573,7 @@
if (expr == null) return null;
var jsExpr = _visitExpression(expr);
if (!isNullable(expr)) return jsExpr;
- return runtimeCall('notNull(#)', jsExpr);
+ return runtimeCall('notNull(#)', [jsExpr]);
}
JS.Expression _emitEqualityOperator(BinaryExpression node, Token op) {
@@ -5036,6 +5057,11 @@
var op = node.operator;
var expr = node.operand;
+ if (op.type == TokenType.BANG) {
+ // If the expression is non-nullable already, this is a no-op.
+ return isNullable(expr) ? notNull(expr) : _visitExpression(expr);
+ }
+
var dispatchType = getStaticType(expr);
if (jsTypeRep.unaryOperationIsPrimitive(dispatchType)) {
if (!isNullable(expr)) {
@@ -5362,12 +5388,13 @@
@override
JS.Expression visitThrowExpression(ThrowExpression node) {
- return runtimeCall('throw(#)', _visitExpression(node.expression));
+ return runtimeCall('throw(#)', [_visitExpression(node.expression)]);
}
@override
JS.Expression visitRethrowExpression(RethrowExpression node) {
- return runtimeCall('rethrow(#)', _emitSimpleIdentifier(_rethrowParameter));
+ return runtimeCall(
+ 'rethrow(#)', [_emitSimpleIdentifier(_rethrowParameter)]);
}
/// Visits a statement, and ensures the resulting AST handles block scope
@@ -5774,7 +5801,7 @@
var jsExpr = _visitExpression(e);
parts.add(e.staticType == types.stringType && !isNullable(e)
? jsExpr
- : runtimeCall('str(#)', jsExpr));
+ : runtimeCall('str(#)', [jsExpr]));
}
}
if (parts.isEmpty) return js.string('');
@@ -5843,8 +5870,7 @@
/// fucntion, call it, and yield the result of [yieldType].
/// TODO(nshahan) Move to share between compilers. Need to work out a common
/// emitLibraryName().
- JS.Expression detectYieldAndCall(
- JS.Statement body, InterfaceType yieldType) {
+ JS.Expression detectYieldAndCall(JS.Block body, InterfaceType yieldType) {
var finder = YieldFinder();
body.accept(finder);
if (finder.hasYield) {
@@ -5871,7 +5897,7 @@
// a function call that returns the list.
var functionBody = JS.Block([
items,
- node.accept<JS.Node>(this),
+ node.accept<JS.Node>(this) as JS.Statement,
JS.Return(_currentCollectionVariable)
]);
var functionCall = detectYieldAndCall(functionBody, arrayType);
@@ -5902,7 +5928,7 @@
]);
}
- return pushToCurrentCollection(node);
+ return pushToCurrentCollection(node as Expression);
}
/// Returns `true` if [node] is a UI-as-Code [CollectionElement].
@@ -6019,10 +6045,10 @@
}
if (node is AsExpression && CoercionReifier.isImplicit(node)) {
assert(node.staticType == types.boolType);
- return runtimeCall('dtest(#)', _visitExpression(node.expression));
+ return runtimeCall('dtest(#)', [_visitExpression(node.expression)]);
}
var result = _visitExpression(node);
- if (isNullable(node)) result = runtimeCall('test(#)', result);
+ if (isNullable(node)) result = runtimeCall('test(#)', [result]);
return result;
}
@@ -6291,9 +6317,9 @@
}
JS.Expression _throwUnsafe(String message) => runtimeCall(
- 'throw(Error(#))', js.escapedString("compile error: $message"));
+ 'throw(Error(#))', [js.escapedString("compile error: $message")]);
- JS.Node _unreachable(Object node) {
+ Null _unreachable(Object node) {
throw UnsupportedError('tried to generate an unreachable node: `$node`');
}
@@ -6489,7 +6515,7 @@
@override
JS.Statement visitForElement(ForElement node) {
var jsBody = _isUiAsCodeElement(node.body)
- ? node.body.accept(this)
+ ? node.body.accept(this) as JS.Statement
: _visitNestedCollectionElement(node.body);
return _forAdaptor(node.forLoopParts, node.awaitKeyword, jsBody);
}
@@ -6497,13 +6523,13 @@
@override
JS.Statement visitIfElement(IfElement node) {
var thenElement = _isUiAsCodeElement(node.thenElement)
- ? node.thenElement.accept(this)
+ ? node.thenElement.accept(this) as JS.Statement
: _visitNestedCollectionElement(node.thenElement);
JS.Statement elseElement;
if (node.elseElement != null) {
if (_isUiAsCodeElement(node.elseElement)) {
- elseElement = node.elseElement.accept<JS.Node>(this);
+ elseElement = node.elseElement.accept<JS.Node>(this) as JS.Statement;
} else {
elseElement = _visitNestedCollectionElement(node.elseElement);
}
@@ -6583,7 +6609,8 @@
/// Returns [expression] wrapped in an implict cast to [castType] or
/// [expression] as provided if [castType] is `null` signifying that
/// no cast is needed.
- JS.Expression wrapInImplicitCast(JS.Expression expression, castType) =>
+ JS.Expression wrapInImplicitCast(
+ JS.Expression expression, DartType castType) =>
castType == null ? expression : _emitCast(castType, expression);
/// Returns a statement spreading the elements of [expression] into
@@ -6673,6 +6700,9 @@
@override
visitForPartsWithExpression(ForPartsWithExpression node) =>
_unreachable(node);
+
+ @override
+ visitExtensionDeclaration(ExtensionDeclaration node) => _unreachable(node);
}
// TODO(jacobr): we would like to do something like the following
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index 8d55999..9e9cb02 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -81,10 +81,10 @@
var resourceProvider = options.resourceProvider;
var contextBuilder = options.createContextBuilder();
- var analysisOptions =
- contextBuilder.getAnalysisOptions(options.analysisRoot);
+ var analysisOptions = contextBuilder
+ .getAnalysisOptions(options.analysisRoot) as AnalysisOptionsImpl;
- (analysisOptions as AnalysisOptionsImpl).enabledExperiments =
+ analysisOptions.enabledExperiments =
experiments.entries.where((e) => e.value).map((e) => e.key).toList();
var dartSdk = contextBuilder.findSdk(null, analysisOptions);
@@ -336,7 +336,7 @@
var libraryFile = _fsState.getFileForUri(Uri.parse(libraryUri));
var analyzer = LibraryAnalyzer(
- analysisOptions,
+ analysisOptions as AnalysisOptionsImpl,
declaredVariables,
resynthesizer.sourceFactory,
(uri) => _isLibraryUri('$uri'),
diff --git a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
index 45f443f..e8fe0f0 100644
--- a/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/element_helpers.dart
@@ -124,7 +124,7 @@
if (node == null) return false;
var parent = node.parent;
while (parent is ParenthesizedExpression) {
- node = parent;
+ node = parent as Expression;
parent = node.parent;
}
return parent is InvocationExpression && identical(node, parent.function) ||
diff --git a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
index a88c582..94f1c2edb 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_metalet.dart
@@ -59,8 +59,7 @@
var block = toStatement();
var s = block.statements;
if (s.length == 1 && s.first is ExpressionStatement) {
- ExpressionStatement es = s.first;
- return es.expression;
+ return (s.first as ExpressionStatement).expression;
}
return _toInvokedFunction(block);
@@ -114,8 +113,7 @@
var block = toReturn();
var s = block.statements;
if (s.length == 1 && s.first is Return) {
- Return es = s.first;
- return _expression = es.value;
+ return _expression = (s.first as Return).value;
}
// Wrap it in an immediately called function to get in expression context.
return _expression = _toInvokedFunction(block);
@@ -280,7 +278,7 @@
}
assert(body.isNotEmpty);
- Binary newBody = Expression.binary([assign]..addAll(body), ',');
+ var newBody = Expression.binary([assign]..addAll(body), ',') as Binary;
newBody = _substitute(newBody, {result: left});
return MetaLet(vars, newBody.commaToExpressionList(),
statelessResult: statelessResult);
diff --git a/pkg/dev_compiler/lib/src/compiler/js_names.dart b/pkg/dev_compiler/lib/src/compiler/js_names.dart
index a5afca2..24d3dbd 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_names.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_names.dart
@@ -207,7 +207,7 @@
if (node is FunctionExpression) {
super.visitFunctionExpression(node);
} else {
- super.visitClassExpression(node);
+ super.visitClassExpression(node as ClassExpression);
}
_finishScopes();
scope = scope.parent;
diff --git a/pkg/dev_compiler/lib/src/compiler/js_utils.dart b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
index 74820eb..997702f 100644
--- a/pkg/dev_compiler/lib/src/compiler/js_utils.dart
+++ b/pkg/dev_compiler/lib/src/compiler/js_utils.dart
@@ -10,7 +10,7 @@
if (fn.body is Block && fn.body.statements.length == 1) {
var stat = fn.body.statements.single;
if (stat is Return && stat.value is Call) {
- Call call = stat.value;
+ var call = stat.value as Call;
var innerFun = call.target;
if (innerFun is ArrowFun &&
call.arguments.isEmpty &&
diff --git a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
index 05cc667..6a3182d 100644
--- a/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
+++ b/pkg/dev_compiler/lib/src/compiler/shared_compiler.dart
@@ -108,6 +108,10 @@
@protected
String jsLibraryDebuggerName(Library library);
+ /// Debugger friendly names for all parts in a Dart [library].
+ @protected
+ Iterable<String> jsPartDebuggerNames(Library library);
+
/// Gets the module import URI that contains [library].
@protected
String libraryToModule(Library library);
@@ -142,7 +146,7 @@
if (name == '[]=') {
_operatorSetResultStack.add(isLastParamMutated()
? JS.TemporaryId((formals.last as JS.Identifier).name)
- : formals.last);
+ : formals.last as JS.Identifier);
} else {
_operatorSetResultStack.add(null);
}
@@ -202,34 +206,21 @@
///
/// For example:
///
- /// runtimeCall('asInt(#)', expr)
+ /// runtimeCall('asInt(#)', [<expr>])
///
/// Generates a JS AST representing:
///
/// dart.asInt(<expr>)
///
@protected
- JS.Expression runtimeCall(String code, [args]) {
- if (args != null) {
- var newArgs = <Object>[runtimeModule];
- if (args is Iterable) {
- newArgs.addAll(args);
- } else {
- newArgs.add(args);
- }
- args = newArgs;
- } else {
- args = runtimeModule;
- }
- return js.call('#.$code', args);
- }
+ JS.Expression runtimeCall(String code, [List<Object> args]) =>
+ js.call('#.$code', <Object>[runtimeModule, ...?args]);
/// Calls [runtimeCall] and uses `toStatement()` to convert the resulting
/// expression into a statement.
@protected
- JS.Statement runtimeStatement(String code, [args]) {
- return runtimeCall(code, args).toStatement();
- }
+ JS.Statement runtimeStatement(String code, [List<Object> args]) =>
+ runtimeCall(code, args).toStatement();
/// Emits a private name JS Symbol for [name] scoped to the Dart [library].
///
@@ -342,7 +333,7 @@
/// constant instance of a user-defined class stored in [expr].
@protected
JS.Expression canonicalizeConstObject(JS.Expression expr) =>
- cacheConst(runtimeCall('const(#)', expr));
+ cacheConst(runtimeCall('const(#)', [expr]));
/// Emits preamble for the module containing [libraries], and returns the
/// list of module items for further items to be added.
@@ -486,19 +477,25 @@
void _emitDebuggerExtensionInfo(String name) {
var properties = <JS.Property>[];
+ var parts = <JS.Property>[];
_libraries.forEach((library, value) {
// TODO(jacobr): we could specify a short library name instead of the
// full library uri if we wanted to save space.
- properties.add(
- JS.Property(js.escapedString(jsLibraryDebuggerName(library)), value));
+ var libraryName = js.escapedString(jsLibraryDebuggerName(library));
+ properties.add(JS.Property(libraryName, value));
+ var partNames = jsPartDebuggerNames(library);
+ if (partNames.isNotEmpty) {
+ parts.add(JS.Property(libraryName, js.stringArray(partNames)));
+ }
});
var module = JS.ObjectInitializer(properties, multiline: true);
+ var partMap = JS.ObjectInitializer(parts, multiline: true);
// Track the module name for each library in the module.
// This data is only required for debugging.
moduleItems.add(js.statement(
- '#.trackLibraries(#, #, $sourceMapLocationID);',
- [runtimeModule, js.string(name), module]));
+ '#.trackLibraries(#, #, #, $sourceMapLocationID);',
+ [runtimeModule, js.string(name), module, partMap]));
}
/// Finishes the module created by [startModule], by combining the preable
diff --git a/pkg/dev_compiler/lib/src/js_ast/printer.dart b/pkg/dev_compiler/lib/src/js_ast/printer.dart
index 38b7fea..f4a9717 100644
--- a/pkg/dev_compiler/lib/src/js_ast/printer.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/printer.dart
@@ -133,7 +133,7 @@
String lastAddedString;
int get lastCharCode {
if (lastAddedString == null) return 0;
- assert(lastAddedString.length != "");
+ assert(lastAddedString.isNotEmpty);
return lastAddedString.codeUnitAt(lastAddedString.length - 1);
}
@@ -1284,7 +1284,7 @@
nameSpecifierListOut(List<NameSpecifier> names, bool export) {
if (names == null) return;
- if (names.length == 1 && names[0].name == '*') {
+ if (names.length == 1 && names[0].name.name == '*') {
nameSpecifierOut(names[0], export);
return;
}
@@ -1306,7 +1306,7 @@
if (from != null) {
out(' from');
spaceOut();
- visit(from);
+ out("'${from.valueWithoutQuotes}.js'");
}
}
diff --git a/pkg/dev_compiler/lib/src/js_ast/template.dart b/pkg/dev_compiler/lib/src/js_ast/template.dart
index b876e7c..6363cd6 100644
--- a/pkg/dev_compiler/lib/src/js_ast/template.dart
+++ b/pkg/dev_compiler/lib/src/js_ast/template.dart
@@ -361,7 +361,7 @@
@override
Instantiator<Statement> visitExpressionStatement(ExpressionStatement node) {
- Instantiator<Expression> makeExpression = visit(node.expression);
+ var makeExpression = visit(node.expression) as Instantiator<Expression>;
return (a) => makeExpression(a).toStatement();
}
@@ -385,8 +385,8 @@
Instantiator<Statement> visitIfConditionalCompilation(
If node, InterpolatedExpression condition) {
- Instantiator<Statement> makeThen = visit(node.then);
- Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+ var makeThen = visit(node.then) as Instantiator<Statement>;
+ var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
return (arguments) {
// Allow bools to be used for conditional compliation.
var nameOrPosition = condition.nameOrPosition;
@@ -400,49 +400,50 @@
}
Instantiator<Statement> visitIfNormal(If node) {
- Instantiator<Expression> makeCondition = visit(node.condition);
- Instantiator<Statement> makeThen = visit(node.then);
- Instantiator<Statement> makeOtherwise = visit(node.otherwise);
+ var makeCondition = visit(node.condition) as Instantiator<Expression>;
+ var makeThen = visit(node.then) as Instantiator<Statement>;
+ var makeOtherwise = visit(node.otherwise) as Instantiator<Statement>;
return (a) => If(makeCondition(a), makeThen(a), makeOtherwise(a));
}
@override
Instantiator<Statement> visitFor(For node) {
- Instantiator<Expression> makeInit = visitNullable(node.init);
- Instantiator<Expression> makeCondition = visitNullable(node.condition);
- Instantiator<Expression> makeUpdate = visitNullable(node.update);
- Instantiator<Statement> makeBody = visit(node.body);
+ var makeInit = visitNullable(node.init) as Instantiator<Expression>;
+ var makeCondition =
+ visitNullable(node.condition) as Instantiator<Expression>;
+ var makeUpdate = visitNullable(node.update) as Instantiator<Expression>;
+ var makeBody = visit(node.body) as Instantiator<Statement>;
return (a) => For(makeInit(a), makeCondition(a),
makeUpdate(a)?.toVoidExpression(), makeBody(a));
}
@override
Instantiator<ForIn> visitForIn(ForIn node) {
- Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
- Instantiator<Expression> makeObject = visit(node.object);
- Instantiator<Statement> makeBody = visit(node.body);
+ var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+ var makeObject = visit(node.object) as Instantiator<Expression>;
+ var makeBody = visit(node.body) as Instantiator<Statement>;
return (a) => ForIn(makeLeftHandSide(a), makeObject(a), makeBody(a));
}
@override
Instantiator<ForOf> visitForOf(ForOf node) {
- Instantiator<Expression> makeLeftHandSide = visit(node.leftHandSide);
- Instantiator<Expression> makeObject = visit(node.iterable);
- Instantiator<Statement> makeBody = visit(node.body);
+ var makeLeftHandSide = visit(node.leftHandSide) as Instantiator<Expression>;
+ var makeObject = visit(node.iterable) as Instantiator<Expression>;
+ var makeBody = visit(node.body) as Instantiator<Statement>;
return (a) => ForOf(makeLeftHandSide(a), makeObject(a), makeBody(a));
}
@override
Instantiator<While> visitWhile(While node) {
- Instantiator<Expression> makeCondition = visit(node.condition);
- Instantiator<Statement> makeBody = visit(node.body);
+ var makeCondition = visit(node.condition) as Instantiator<Expression>;
+ var makeBody = visit(node.body) as Instantiator<Statement>;
return (a) => While(makeCondition(a), makeBody(a));
}
@override
Instantiator<Do> visitDo(Do node) {
- Instantiator<Statement> makeBody = visit(node.body);
- Instantiator<Expression> makeCondition = visit(node.condition);
+ var makeBody = visit(node.body) as Instantiator<Statement>;
+ var makeCondition = visit(node.condition) as Instantiator<Expression>;
return (a) => Do(makeBody(a), makeCondition(a));
}
@@ -456,48 +457,49 @@
@override
Instantiator<Statement> visitReturn(Return node) {
if (node.value == null) return (args) => Return();
- Instantiator<Expression> makeExpression = visit(node.value);
+ var makeExpression = visit(node.value) as Instantiator<Expression>;
return (a) => makeExpression(a).toReturn();
}
@override
Instantiator<DartYield> visitDartYield(DartYield node) {
- Instantiator<Expression> makeExpression = visit(node.expression);
+ var makeExpression = visit(node.expression) as Instantiator<Expression>;
return (a) => DartYield(makeExpression(a), node.hasStar);
}
@override
Instantiator<Throw> visitThrow(Throw node) {
- Instantiator<Expression> makeExpression = visit(node.expression);
+ var makeExpression = visit(node.expression) as Instantiator<Expression>;
return (a) => Throw(makeExpression(a));
}
@override
Instantiator<Try> visitTry(Try node) {
- Instantiator<Block> makeBody = visit(node.body);
- Instantiator<Catch> makeCatch = visitNullable(node.catchPart);
- Instantiator<Block> makeFinally = visitNullable(node.finallyPart);
+ var makeBody = visit(node.body) as Instantiator<Block>;
+ var makeCatch = visitNullable(node.catchPart) as Instantiator<Catch>;
+ var makeFinally = visitNullable(node.finallyPart) as Instantiator<Block>;
return (a) => Try(makeBody(a), makeCatch(a), makeFinally(a));
}
@override
Instantiator<Catch> visitCatch(Catch node) {
- Instantiator<Identifier> makeDeclaration = visit(node.declaration);
- Instantiator<Block> makeBody = visit(node.body);
+ var makeDeclaration = visit(node.declaration) as Instantiator<Identifier>;
+ var makeBody = visit(node.body) as Instantiator<Block>;
return (a) => Catch(makeDeclaration(a), makeBody(a));
}
@override
Instantiator<Switch> visitSwitch(Switch node) {
- Instantiator<Expression> makeKey = visit(node.key);
+ var makeKey = visit(node.key) as Instantiator<Expression>;
var makeCases = node.cases.map(visitSwitchCase).toList();
return (a) => Switch(makeKey(a), makeCases.map((m) => m(a)).toList());
}
@override
Instantiator<SwitchCase> visitSwitchCase(SwitchCase node) {
- Instantiator<Expression> makeExpression = visitNullable(node.expression);
- Instantiator<Block> makeBody = visit(node.body);
+ var makeExpression =
+ visitNullable(node.expression) as Instantiator<Expression>;
+ var makeBody = visit(node.body) as Instantiator<Block>;
return (arguments) {
return SwitchCase(makeExpression(arguments), makeBody(arguments));
};
@@ -506,14 +508,14 @@
@override
Instantiator<FunctionDeclaration> visitFunctionDeclaration(
FunctionDeclaration node) {
- Instantiator<Identifier> makeName = visit(node.name);
- Instantiator<Fun> makeFunction = visit(node.function);
+ var makeName = visit(node.name) as Instantiator<Identifier>;
+ var makeFunction = visit(node.function) as Instantiator<Fun>;
return (a) => FunctionDeclaration(makeName(a), makeFunction(a));
}
@override
Instantiator<LabeledStatement> visitLabeledStatement(LabeledStatement node) {
- Instantiator<Statement> makeBody = visit(node.body);
+ var makeBody = visit(node.body) as Instantiator<Statement>;
return (a) => LabeledStatement(node.label, makeBody(a));
}
@@ -539,23 +541,24 @@
Instantiator makeValue = visitNullable(node.value);
return (arguments) {
return makeValue(arguments)
- .toAssignExpression(makeLeftHandSide(arguments), op);
+ .toAssignExpression(makeLeftHandSide(arguments), op) as Expression;
};
}
@override
Instantiator<VariableInitialization> visitVariableInitialization(
VariableInitialization node) {
- Instantiator<VariableBinding> makeDeclaration = visit(node.declaration);
- Instantiator<Expression> makeValue = visitNullable(node.value);
+ var makeDeclaration =
+ visit(node.declaration) as Instantiator<VariableBinding>;
+ var makeValue = visitNullable(node.value) as Instantiator<Expression>;
return (a) => VariableInitialization(makeDeclaration(a), makeValue(a));
}
@override
Instantiator<Conditional> visitConditional(Conditional cond) {
- Instantiator<Expression> makeCondition = visit(cond.condition);
- Instantiator<Expression> makeThen = visit(cond.then);
- Instantiator<Expression> makeOtherwise = visit(cond.otherwise);
+ var makeCondition = visit(cond.condition) as Instantiator<Expression>;
+ var makeThen = visit(cond.then) as Instantiator<Expression>;
+ var makeOtherwise = visit(cond.otherwise) as Instantiator<Expression>;
return (a) => Conditional(makeCondition(a), makeThen(a), makeOtherwise(a));
}
@@ -566,7 +569,7 @@
Instantiator<Call> visitCall(Call node) => handleCallOrNew(node, false);
Instantiator<Call> handleCallOrNew(Call node, bool isNew) {
- Instantiator<Expression> makeTarget = visit(node.target);
+ var makeTarget = visit(node.target) as Instantiator<Expression>;
var argumentMakers = node.arguments.map(visitSplayableExpression).toList();
// TODO(sra): Avoid copying call arguments if no interpolation or forced
@@ -580,22 +583,22 @@
@override
Instantiator<Binary> visitBinary(Binary node) {
- Instantiator<Expression> makeLeft = visit(node.left);
- Instantiator<Expression> makeRight = visit(node.right);
+ var makeLeft = visit(node.left) as Instantiator<Expression>;
+ var makeRight = visit(node.right) as Instantiator<Expression>;
String op = node.op;
return (a) => Binary(op, makeLeft(a), makeRight(a));
}
@override
Instantiator<Prefix> visitPrefix(Prefix node) {
- Instantiator<Expression> makeOperand = visit(node.argument);
+ var makeOperand = visit(node.argument) as Instantiator<Expression>;
String op = node.op;
return (a) => Prefix(op, makeOperand(a));
}
@override
Instantiator<Postfix> visitPostfix(Postfix node) {
- Instantiator<Expression> makeOperand = visit(node.argument);
+ var makeOperand = visit(node.argument) as Instantiator<Expression>;
String op = node.op;
return (a) => Postfix(op, makeOperand(a));
}
@@ -629,22 +632,22 @@
@override
Instantiator<PropertyAccess> visitAccess(PropertyAccess node) {
- Instantiator<Expression> makeReceiver = visit(node.receiver);
- Instantiator<Expression> makeSelector = visit(node.selector);
+ var makeReceiver = visit(node.receiver) as Instantiator<Expression>;
+ var makeSelector = visit(node.selector) as Instantiator<Expression>;
return (a) => PropertyAccess(makeReceiver(a), makeSelector(a));
}
@override
Instantiator<NamedFunction> visitNamedFunction(NamedFunction node) {
- Instantiator<Identifier> makeDeclaration = visit(node.name);
- Instantiator<Fun> makeFunction = visit(node.function);
+ var makeDeclaration = visit(node.name) as Instantiator<Identifier>;
+ var makeFunction = visit(node.function) as Instantiator<Fun>;
return (a) => NamedFunction(makeDeclaration(a), makeFunction(a));
}
@override
Instantiator<Fun> visitFun(Fun node) {
var paramMakers = node.params.map(visitSplayable).toList();
- Instantiator<Block> makeBody = visit(node.body);
+ var makeBody = visit(node.body) as Instantiator<Block>;
return (a) => Fun(splayNodes(paramMakers, a), makeBody(a),
isGenerator: node.isGenerator, asyncModifier: node.asyncModifier);
}
@@ -653,7 +656,7 @@
Instantiator<ArrowFun> visitArrowFun(ArrowFun node) {
var paramMakers = node.params.map(visitSplayable).toList();
Instantiator makeBody = visit(node.body);
- return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a));
+ return (a) => ArrowFun(splayNodes(paramMakers, a), makeBody(a) as Node);
}
@override
@@ -692,8 +695,8 @@
@override
Instantiator<Property> visitProperty(Property node) {
- Instantiator<Expression> makeName = visit(node.name);
- Instantiator<Expression> makeValue = visit(node.value);
+ var makeName = visit(node.name) as Instantiator<Expression>;
+ var makeValue = visit(node.value) as Instantiator<Expression>;
return (a) => Property(makeName(a), makeValue(a));
}
@@ -709,7 +712,7 @@
@override
Instantiator<TaggedTemplate> visitTaggedTemplate(TaggedTemplate node) {
- Instantiator<Expression> makeTag = visit(node.tag);
+ var makeTag = visit(node.tag) as Instantiator<Expression>;
var makeTemplate = visitTemplateString(node.template);
return (a) => TaggedTemplate(makeTag(a), makeTemplate(a));
}
@@ -723,8 +726,8 @@
@override
Instantiator<ClassExpression> visitClassExpression(ClassExpression node) {
var makeMethods = node.methods.map(visitSplayableExpression).toList();
- Instantiator<Identifier> makeName = visit(node.name);
- Instantiator<Expression> makeHeritage = visit(node.heritage);
+ var makeName = visit(node.name) as Instantiator<Identifier>;
+ var makeHeritage = visit(node.heritage) as Instantiator<Expression>;
return (a) => ClassExpression(
makeName(a), makeHeritage(a), splayNodes(makeMethods, a));
@@ -732,8 +735,8 @@
@override
Instantiator<Method> visitMethod(Method node) {
- Instantiator<Expression> makeName = visit(node.name);
- Instantiator<Fun> makeFunction = visit(node.function);
+ var makeName = visit(node.name) as Instantiator<Expression>;
+ var makeFunction = visit(node.function) as Instantiator<Fun>;
return (a) => Method(makeName(a), makeFunction(a),
isGetter: node.isGetter,
isSetter: node.isSetter,
@@ -747,13 +750,13 @@
@override
Instantiator<CommentExpression> visitCommentExpression(
CommentExpression node) {
- Instantiator<Expression> makeExpr = visit(node.expression);
+ var makeExpr = visit(node.expression) as Instantiator<Expression>;
return (a) => CommentExpression(node.comment, makeExpr(a));
}
@override
Instantiator<Await> visitAwait(Await node) {
- Instantiator<Expression> makeExpr = visit(node.expression);
+ var makeExpr = visit(node.expression) as Instantiator<Expression>;
return (a) => Await(makeExpr(a));
}
@@ -779,11 +782,12 @@
@override
Instantiator<DestructuredVariable> visitDestructuredVariable(
DestructuredVariable node) {
- Instantiator<Identifier> makeName = visitNullable(node.name);
- Instantiator<Expression> makeProperty = visitNullable(node.property);
- Instantiator<BindingPattern> makeStructure = visitNullable(node.structure);
- Instantiator<Expression> makeDefaultValue =
- visitNullable(node.defaultValue);
+ var makeName = visitNullable(node.name) as Instantiator<Identifier>;
+ var makeProperty = visitNullable(node.property) as Instantiator<Expression>;
+ var makeStructure =
+ visitNullable(node.structure) as Instantiator<BindingPattern>;
+ var makeDefaultValue =
+ visitNullable(node.defaultValue) as Instantiator<Expression>;
return (a) => DestructuredVariable(
name: makeName(a),
property: makeProperty(a),
diff --git a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
index 308e199..caa8b83 100644
--- a/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
+++ b/pkg/dev_compiler/lib/src/kernel/analyzer_to_kernel.dart
@@ -645,7 +645,9 @@
var f = type as a.FunctionType;
if (f.name != null && f.name != '') {
var ref = ensureNode
- ? visitFunctionTypeAliasElement(f.element).reference
+ ? visitFunctionTypeAliasElement(
+ f.element as a.FunctionTypeAliasElement)
+ .reference
: _reference(f.element);
return TypedefType.byReference(ref, f.typeArguments.map(visit).toList());
}
@@ -752,8 +754,8 @@
void Function(Expression) addAnnotation) {
if (metadata.isEmpty) return;
- for (a.ElementAnnotationImpl annotation in metadata) {
- var ast = annotation.annotationAst;
+ for (a.ElementAnnotation annotation in metadata) {
+ var ast = (annotation as a.ElementAnnotationImpl).annotationAst;
var arguments = ast.arguments;
if (arguments == null) {
var e = ast.element;
@@ -833,7 +835,8 @@
//
// This leads to mismatch in how we call this constructor. So we need to
// find the redirected one.
- for (var rc; (rc = constructor.redirectedConstructor) != null;) {
+ for (a.ConstructorElement rc;
+ (rc = constructor.redirectedConstructor) != null;) {
constructor = rc;
}
constructor = constructor is a.ConstructorMember
@@ -852,7 +855,9 @@
}
if (obj is a.DartObjectImpl && type is a.FunctionType) {
var e = obj.toFunctionValue();
- e = e is a.PropertyAccessorElement && e.isSynthetic ? e.variable : e;
+ e = e is a.PropertyAccessorElement && e.isSynthetic
+ ? e.variable as a.ExecutableElement
+ : e;
// TODO(jmesserly): support generic tear-off implicit instantiation.
return StaticGet.byReference(_reference(e));
}
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 8794109..7507c3a 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -11,6 +11,7 @@
import 'package:cli_util/cli_util.dart' show getSdkPath;
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/kernel.dart' hide MapEntry;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
import 'package:kernel/target/targets.dart';
import 'package:kernel/text/ast_to_text.dart' as kernel show Printer;
import 'package:kernel/binary/ast_to_binary.dart' as kernel show BinaryPrinter;
@@ -265,7 +266,7 @@
converter.dispose();
}
- var hierarchy;
+ ClassHierarchy hierarchy;
fe.DdcResult result;
if (useAnalyzer || !useIncrementalCompiler) {
result = await fe.compile(compilerState, inputs, diagnosticMessageHandler);
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index 7427bbc..13f7c0b 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:collection';
+import 'dart:convert';
import 'dart:math' show max, min;
import 'package:front_end/src/api_unstable/ddc.dart' show TypeSchemaEnvironment;
@@ -316,7 +317,9 @@
@override
String jsLibraryName(Library library) {
var uri = library.importUri;
- if (uri.scheme == 'dart') return uri.path;
+ if (uri.scheme == 'dart') {
+ return isSdkInternalRuntime(library) ? 'dart' : uri.path;
+ }
// TODO(vsm): This is not necessarily unique if '__' appears in a file name.
Iterable<String> segments;
@@ -335,13 +338,11 @@
}
@override
- String jsLibraryDebuggerName(Library library) {
- var uri = library.importUri;
- // For package: and dart: uris show the entire
- if (uri.scheme == 'dart' || uri.scheme == 'package') return uri.toString();
- // TODO(jmesserly): this is not unique typically.
- return uri.pathSegments.last;
- }
+ String jsLibraryDebuggerName(Library library) => '${library.importUri}';
+
+ @override
+ Iterable<String> jsPartDebuggerNames(Library library) =>
+ library.parts.map((part) => part.partUri);
@override
bool isSdkInternalRuntime(Library l) {
@@ -551,10 +552,11 @@
className ?? JS.Identifier(name)
]);
- var genericArgs = [typeConstructor];
- if (deferredBaseClass != null && deferredBaseClass.isNotEmpty) {
- genericArgs.add(js.call('(#) => { #; }', [jsFormals, deferredBaseClass]));
- }
+ var genericArgs = [
+ typeConstructor,
+ if (deferredBaseClass != null && deferredBaseClass.isNotEmpty)
+ js.call('(#) => { #; }', [jsFormals, deferredBaseClass]),
+ ];
var genericCall = runtimeCall('generic(#)', [genericArgs]);
@@ -723,12 +725,12 @@
_currentUri = ctor.enclosingClass.fileUri;
var jsParams = _emitParameters(ctor.function);
_currentUri = savedUri;
- var ctorBody = <JS.Statement>[];
- if (mixinCtor != null) ctorBody.add(mixinCtor);
var name = ctor.name.name;
- if (name != '' || hasUnnamedSuper) {
- ctorBody.add(_emitSuperConstructorCall(className, name, jsParams));
- }
+ var ctorBody = [
+ if (mixinCtor != null) mixinCtor,
+ if (name != '' || hasUnnamedSuper)
+ _emitSuperConstructorCall(className, name, jsParams),
+ ];
body.add(_addConstructorToClass(
c, className, name, JS.Fun(jsParams, JS.Block(ctorBody))));
}
@@ -1164,7 +1166,7 @@
var savedClass = _classEmittingSignatures;
_classEmittingSignatures = c;
- var interfaces = List.from(c.implementedTypes)
+ var interfaces = c.implementedTypes.toList()
..addAll(c.superclassConstraints());
if (interfaces.isNotEmpty) {
body.add(js.statement('#[#.implements] = () => [#];', [
@@ -1268,6 +1270,10 @@
emitSignature('Setter', instanceSetters);
emitSignature('StaticGetter', staticGetters);
emitSignature('StaticSetter', staticSetters);
+ body.add(runtimeStatement('setLibraryUri(#, #)', [
+ className,
+ js.escapedString(jsLibraryDebuggerName(c.enclosingLibrary))
+ ]));
var instanceFields = <JS.Property>[];
var staticFields = <JS.Property>[];
@@ -1288,8 +1294,10 @@
if (emitMetadata) {
var constructors = <JS.Property>[];
- var allConstructors = List<Member>.from(c.constructors)
- ..addAll(c.procedures.where((p) => p.isFactory));
+ var allConstructors = [
+ ...c.constructors,
+ ...c.procedures.where((p) => p.isFactory),
+ ];
for (var ctor in allConstructors) {
var memberName = _constructorName(ctor.name.name);
var type = _emitAnnotatedFunctionType(
@@ -1552,7 +1560,7 @@
if (expr == null) return null;
var jsExpr = _visitExpression(expr);
if (!isNullable(expr)) return jsExpr;
- return runtimeCall('notNull(#)', jsExpr);
+ return runtimeCall('notNull(#)', [jsExpr]);
}
/// If the class has only factory constructors, and it can be mixed in,
@@ -1996,8 +2004,8 @@
Class c, String jsPeerName, List<JS.Statement> body) {
var className = _emitTopLevelName(c);
if (_typeRep.isPrimitive(c.rawType)) {
- body.add(
- runtimeStatement('definePrimitiveHashCode(#.prototype)', className));
+ body.add(runtimeStatement(
+ 'definePrimitiveHashCode(#.prototype)', [className]));
}
body.add(runtimeStatement(
'registerExtension(#, #)', [js.string(jsPeerName), className]));
@@ -2437,22 +2445,22 @@
}
@override
- defaultDartType(type) => _emitInvalidNode(type);
+ JS.Expression defaultDartType(DartType type) => _emitInvalidNode(type);
@override
- visitInvalidType(type) => defaultDartType(type);
+ JS.Expression visitInvalidType(InvalidType type) => defaultDartType(type);
@override
- visitDynamicType(type) => runtimeCall('dynamic');
+ JS.Expression visitDynamicType(DynamicType type) => runtimeCall('dynamic');
@override
- visitVoidType(type) => runtimeCall('void');
+ JS.Expression visitVoidType(VoidType type) => runtimeCall('void');
@override
- visitBottomType(type) => runtimeCall('bottom');
+ JS.Expression visitBottomType(BottomType type) => runtimeCall('bottom');
@override
- visitInterfaceType(type) {
+ JS.Expression visitInterfaceType(InterfaceType type) {
var c = type.classNode;
_declareBeforeUse(c);
@@ -2471,7 +2479,7 @@
// have to use a helper to define them.
if (isJSAnonymousType(c)) {
return runtimeCall(
- 'anonymousJSType(#)', js.escapedString(getLocalClassName(c)));
+ 'anonymousJSType(#)', [js.escapedString(getLocalClassName(c))]);
}
var jsName = _getJSNameWithoutGlobal(c);
if (jsName != null) {
@@ -2510,7 +2518,7 @@
}
@override
- visitFunctionType(type, {Member member, bool lazy = false}) {
+ JS.Expression visitFunctionType(type, {Member member, bool lazy = false}) {
var requiredTypes =
type.positionalParameters.take(type.requiredParameterCount).toList();
var function = member?.function;
@@ -2665,14 +2673,15 @@
}
@override
- visitTypeParameterType(type) => _emitTypeParameter(type.parameter);
+ JS.Expression visitTypeParameterType(TypeParameterType type) =>
+ _emitTypeParameter(type.parameter);
- JS.Identifier _emitTypeParameter(TypeParameter t) {
- return JS.Identifier(getTypeParameterName(t));
- }
+ JS.Identifier _emitTypeParameter(TypeParameter t) =>
+ JS.Identifier(getTypeParameterName(t));
@override
- visitTypedefType(type) => visitFunctionType(type.unalias);
+ JS.Expression visitTypedefType(TypedefType type) =>
+ visitFunctionType(type.unalias as FunctionType);
JS.Fun _emitFunction(FunctionNode f, String name) {
// normal function (sync), vs (sync*, async, async*)
@@ -2698,11 +2707,11 @@
List<JS.Parameter> _emitParameters(FunctionNode f) {
var positional = f.positionalParameters;
- var result = List<JS.Parameter>.from(positional.map(_emitVariableDef));
+ var result = List<JS.Parameter>.of(positional.map(_emitVariableDef));
if (positional.isNotEmpty &&
f.requiredParameterCount == positional.length &&
positional.last.annotations.any(isJsRestAnnotation)) {
- result.last = JS.RestParameter(result.last);
+ result.last = JS.RestParameter(result.last as JS.Identifier);
}
if (f.namedParameters.isNotEmpty) result.add(namedArgumentTemp);
return result;
@@ -3023,9 +3032,10 @@
// (sync*/async/async*). Our code generator assumes it can emit names for
// named argument initialization, and sync* functions also emit locally
// modified parameters into the function's scope.
- var parameterNames = HashSet<String>()
- ..addAll(f.positionalParameters.map((p) => p.name))
- ..addAll(f.namedParameters.map((p) => p.name));
+ var parameterNames = {
+ for (var p in f.positionalParameters) p.name,
+ for (var p in f.namedParameters) p.name,
+ };
return jsBody.toScopedBlock(parameterNames);
}
@@ -3060,11 +3070,11 @@
if (node is AsExpression && node.isTypeError) {
assert(node.getStaticType(types) == types.boolType);
- return runtimeCall('dtest(#)', _visitExpression(node.operand));
+ return runtimeCall('dtest(#)', [_visitExpression(node.operand)]);
}
var result = _visitExpression(node);
- if (isNullable(node)) result = runtimeCall('test(#)', result);
+ if (isNullable(node)) result = runtimeCall('test(#)', [result]);
return result;
}
@@ -3133,10 +3143,11 @@
}
@override
- defaultStatement(Statement node) => _emitInvalidNode(node).toStatement();
+ JS.Statement defaultStatement(Statement node) =>
+ _emitInvalidNode(node).toStatement();
@override
- visitExpressionStatement(ExpressionStatement node) {
+ JS.Statement visitExpressionStatement(ExpressionStatement node) {
var expr = node.expression;
if (expr is StaticInvocation) {
if (isInlineJS(expr.target)) {
@@ -3150,7 +3161,7 @@
}
@override
- visitBlock(Block node) {
+ JS.Statement visitBlock(Block node) {
// If this is the block body of a function, don't mark it as a separate
// scope, because the function is the scope. This avoids generating an
// unncessary nested block.
@@ -3164,17 +3175,17 @@
}
@override
- visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
+ JS.Statement visitEmptyStatement(EmptyStatement node) => JS.EmptyStatement();
@override
- visitAssertBlock(AssertBlock node) {
+ JS.Statement visitAssertBlock(AssertBlock node) {
// AssertBlocks are introduced by the VM-specific async elimination
// transformation. We do not expect them to arise here.
throw UnsupportedError('compilation of an assert block');
}
@override
- visitAssertStatement(AssertStatement node) {
+ JS.Statement visitAssertStatement(AssertStatement node) {
if (!options.enableAsserts) return JS.EmptyStatement();
var condition = node.condition;
var conditionType = condition.getStaticType(types);
@@ -3184,16 +3195,30 @@
if (conditionType is FunctionType &&
conditionType.requiredParameterCount == 0 &&
conditionType.returnType == boolType) {
- jsCondition = runtimeCall('test(#())', jsCondition);
+ jsCondition = runtimeCall('test(#())', [jsCondition]);
} else if (conditionType != boolType) {
- jsCondition = runtimeCall('dassert(#)', jsCondition);
+ jsCondition = runtimeCall('dassert(#)', [jsCondition]);
} else if (isNullable(condition)) {
- jsCondition = runtimeCall('test(#)', jsCondition);
+ jsCondition = runtimeCall('test(#)', [jsCondition]);
}
- return js.statement(' if (!#) #.assertFailed(#);', [
+
+ var encodedConditionSource = node
+ .enclosingComponent.uriToSource[node.location.file].source
+ .sublist(node.conditionStartOffset, node.conditionEndOffset);
+ var conditionSource = utf8.decode(encodedConditionSource);
+ var location = _getLocation(node.conditionStartOffset);
+ return js.statement(' if (!#) #.assertFailed(#, #, #, #, #);', [
jsCondition,
runtimeModule,
- node.message != null ? [_visitExpression(node.message)] : []
+ if (node.message == null)
+ JS.LiteralNull()
+ else
+ _visitExpression(node.message),
+ js.escapedString(location.sourceUrl.toString()),
+ // Lines and columns are typically printed with 1 based indexing.
+ js.number(location.line + 1),
+ js.number(location.column + 1),
+ js.escapedString(conditionSource),
]);
}
@@ -3208,7 +3233,7 @@
}
@override
- visitLabeledStatement(LabeledStatement node) {
+ JS.Statement visitLabeledStatement(LabeledStatement node) {
List<LabeledStatement> saved;
var target = _effectiveTargets[node];
// If the effective target is known then this statement is either contained
@@ -3246,7 +3271,7 @@
}
@override
- visitBreakStatement(BreakStatement node) {
+ JS.Statement visitBreakStatement(BreakStatement node) {
// Switch statements with continue labels must explicitly break to their
// implicit label due to their being wrapped in a loop.
if (_inLabeledContinueSwitch &&
@@ -3433,7 +3458,7 @@
}
@override
- visitSwitchStatement(SwitchStatement node) {
+ JS.Statement visitSwitchStatement(SwitchStatement node) {
// Switches with labeled continues are generated as an infinite loop with
// an explicit variable for holding the switch's next case state and an
// explicit label. Any implicit breaks are made explicit (e.g., when break
@@ -3517,7 +3542,7 @@
}
@override
- visitContinueSwitchStatement(ContinueSwitchStatement node) {
+ JS.Statement visitContinueSwitchStatement(ContinueSwitchStatement node) {
var switchStmt = node.target.parent;
if (_inLabeledContinueSwitch &&
_switchLabelStates.containsKey(switchStmt)) {
@@ -3537,7 +3562,7 @@
}
@override
- visitIfStatement(IfStatement node) {
+ JS.Statement visitIfStatement(IfStatement node) {
return JS.If(_visitTest(node.condition), _visitScope(node.then),
_visitScope(node.otherwise));
}
@@ -3563,7 +3588,7 @@
}
@override
- visitTryCatch(TryCatch node) {
+ JS.Statement visitTryCatch(TryCatch node) {
return JS.Try(
_visitStatement(node.body).toBlock(), _visitCatch(node.catches), null);
}
@@ -3598,15 +3623,14 @@
runtimeModule,
_emitVariableRef(caughtError)
]),
+ if (stackTraceParameter != null)
+ js.statement('let # = #.stackTrace(#)', [
+ _emitVariableDef(stackTraceParameter),
+ runtimeModule,
+ _emitVariableRef(caughtError)
+ ]),
+ catchBody,
];
- if (stackTraceParameter != null) {
- catchStatements.add(js.statement('let # = #.stackTrace(#)', [
- _emitVariableDef(stackTraceParameter),
- runtimeModule,
- _emitVariableRef(caughtError)
- ]));
- }
- catchStatements.add(catchBody);
_rethrowParameter = savedRethrow;
return JS.Catch(_emitVariableDef(caughtError), JS.Block(catchStatements));
}
@@ -3645,7 +3669,7 @@
}
@override
- visitTryFinally(TryFinally node) {
+ JS.Statement visitTryFinally(TryFinally node) {
var body = _visitStatement(node.body);
var finallyBlock =
_superDisallowed(() => _visitStatement(node.finalizer).toBlock());
@@ -3660,7 +3684,7 @@
}
@override
- visitYieldStatement(YieldStatement node) {
+ JS.Statement visitYieldStatement(YieldStatement node) {
var jsExpr = _visitExpression(node.expression);
var star = node.isYieldStar;
if (_asyncStarController != null) {
@@ -3687,7 +3711,7 @@
}
@override
- visitVariableDeclaration(VariableDeclaration node) {
+ JS.Statement visitVariableDeclaration(VariableDeclaration node) {
// TODO(jmesserly): casts are sometimes required here.
// Kernel does not represent these explicitly.
var v = _emitVariableDef(node);
@@ -3696,7 +3720,7 @@
}
@override
- visitFunctionDeclaration(FunctionDeclaration node) {
+ JS.Statement visitFunctionDeclaration(FunctionDeclaration node) {
var func = node.function;
var fn = _emitFunction(func, node.variable.name);
@@ -3714,20 +3738,22 @@
}
@override
- defaultExpression(Expression node) => _emitInvalidNode(node);
+ JS.Expression defaultExpression(Expression node) => _emitInvalidNode(node);
@override
- defaultBasicLiteral(BasicLiteral node) => defaultExpression(node);
+ JS.Expression defaultBasicLiteral(BasicLiteral node) =>
+ defaultExpression(node);
@override
- visitInvalidExpression(InvalidExpression node) => defaultExpression(node);
+ JS.Expression visitInvalidExpression(InvalidExpression node) =>
+ defaultExpression(node);
@override
- visitConstantExpression(ConstantExpression node) =>
- node.constant.accept(this);
+ JS.Expression visitConstantExpression(ConstantExpression node) =>
+ node.constant.accept(this) as JS.Expression;
@override
- visitVariableGet(VariableGet node) {
+ JS.Expression visitVariableGet(VariableGet node) {
var v = node.variable;
var id = _emitVariableRef(v);
if (id.name == v.name) {
@@ -3767,28 +3793,29 @@
// TODO(jmesserly): resugar operators for kernel, such as ++x, x++, x+=.
@override
- visitVariableSet(VariableSet node) => _visitExpression(node.value)
- .toAssignExpression(_emitVariableRef(node.variable));
+ JS.Expression visitVariableSet(VariableSet node) =>
+ _visitExpression(node.value)
+ .toAssignExpression(_emitVariableRef(node.variable));
@override
- visitPropertyGet(PropertyGet node) {
+ JS.Expression visitPropertyGet(PropertyGet node) {
return _emitPropertyGet(
node.receiver, node.interfaceTarget, node.name.name);
}
@override
- visitPropertySet(PropertySet node) {
+ JS.Expression visitPropertySet(PropertySet node) {
return _emitPropertySet(
node.receiver, node.interfaceTarget, node.value, node.name.name);
}
@override
- visitDirectPropertyGet(DirectPropertyGet node) {
+ JS.Expression visitDirectPropertyGet(DirectPropertyGet node) {
return _emitPropertyGet(node.receiver, node.target);
}
@override
- visitDirectPropertySet(DirectPropertySet node) {
+ JS.Expression visitDirectPropertySet(DirectPropertySet node) {
return _emitPropertySet(node.receiver, node.target, node.value);
}
@@ -3853,7 +3880,7 @@
}
@override
- visitSuperPropertyGet(SuperPropertyGet node) {
+ JS.Expression visitSuperPropertyGet(SuperPropertyGet node) {
var target = node.interfaceTarget;
var jsTarget = _emitSuperTarget(target);
if (_reifyTearoff(target)) {
@@ -3863,14 +3890,14 @@
}
@override
- visitSuperPropertySet(SuperPropertySet node) {
+ JS.Expression visitSuperPropertySet(SuperPropertySet node) {
var target = node.interfaceTarget;
var jsTarget = _emitSuperTarget(target, setter: true);
return _visitExpression(node.value).toAssignExpression(jsTarget);
}
@override
- visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
+ JS.Expression visitStaticGet(StaticGet node) => _emitStaticGet(node.target);
JS.Expression _emitStaticGet(Member target) {
// TODO(vsm): Re-inline constants. See:
@@ -3886,19 +3913,19 @@
}
@override
- visitStaticSet(StaticSet node) {
+ JS.Expression visitStaticSet(StaticSet node) {
return _visitExpression(node.value)
.toAssignExpression(_emitStaticTarget(node.target));
}
@override
- visitMethodInvocation(MethodInvocation node) {
+ JS.Expression visitMethodInvocation(MethodInvocation node) {
return _emitMethodCall(
node.receiver, node.interfaceTarget, node.arguments, node);
}
@override
- visitDirectMethodInvocation(DirectMethodInvocation node) {
+ JS.Expression visitDirectMethodInvocation(DirectMethodInvocation node) {
return _emitMethodCall(node.receiver, node.target, node.arguments, node);
}
@@ -4006,7 +4033,7 @@
return null;
}
- _isDynamicOrFunction(DartType t) =>
+ bool _isDynamicOrFunction(DartType t) =>
t == coreTypes.functionClass.rawType || t == const DynamicType();
JS.Expression _emitUnaryOperator(
@@ -4362,7 +4389,7 @@
// TODO(jmesserly): optimize super operators for kernel
@override
- visitSuperMethodInvocation(SuperMethodInvocation node) {
+ JS.Expression visitSuperMethodInvocation(SuperMethodInvocation node) {
var target = node.interfaceTarget;
return JS.Call(_emitSuperTarget(target),
_emitArgumentList(node.arguments, target: target));
@@ -4396,13 +4423,12 @@
isGetter: !setter, isSetter: setter);
} else {
var function = member.function;
- var params = _emitTypeFormals(function.typeParameters);
- for (var param in function.positionalParameters) {
- params.add(JS.Identifier(param.name));
- }
- if (function.namedParameters.isNotEmpty) {
- params.add(namedArgumentTemp);
- }
+ var params = [
+ ..._emitTypeFormals(function.typeParameters),
+ for (var param in function.positionalParameters)
+ JS.Identifier(param.name),
+ if (function.namedParameters.isNotEmpty) namedArgumentTemp,
+ ];
var fn = js.fun(
'function(#) { return super[#](#); }', [params, jsName, params]);
@@ -4414,7 +4440,7 @@
}
@override
- visitStaticInvocation(StaticInvocation node) {
+ JS.Expression visitStaticInvocation(StaticInvocation node) {
var target = node.target;
if (isInlineJS(target)) return _emitInlineJSCode(node) as JS.Expression;
if (target.isFactory) return _emitFactoryInvocation(node);
@@ -4515,26 +4541,18 @@
List<JS.Expression> _emitArgumentList(Arguments node,
{bool types = true, Member target}) {
types = types && _reifyGenericFunction(target);
- var args = <JS.Expression>[];
- if (types) {
- for (var typeArg in node.types) {
- args.add(_emitType(typeArg));
- }
- }
- for (var arg in node.positional) {
- if (arg is StaticInvocation &&
- isJSSpreadInvocation(arg.target) &&
- arg.arguments.positional.length == 1) {
- args.add(JS.Spread(_visitExpression(arg.arguments.positional[0])));
- } else {
- args.add(_visitExpression(arg));
- }
- }
- if (node.named.isNotEmpty) {
- args.add(
- JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()));
- }
- return args;
+ return [
+ if (types) for (var typeArg in node.types) _emitType(typeArg),
+ for (var arg in node.positional)
+ if (arg is StaticInvocation &&
+ isJSSpreadInvocation(arg.target) &&
+ arg.arguments.positional.length == 1)
+ JS.Spread(_visitExpression(arg.arguments.positional[0]))
+ else
+ _visitExpression(arg),
+ if (node.named.isNotEmpty)
+ JS.ObjectInitializer(node.named.map(_emitNamedExpression).toList()),
+ ];
}
JS.Property _emitNamedExpression(NamedExpression arg) {
@@ -4649,7 +4667,7 @@
}
@override
- visitConstructorInvocation(ConstructorInvocation node) {
+ JS.Expression visitConstructorInvocation(ConstructorInvocation node) {
var ctor = node.target;
var args = node.arguments;
var result = JS.New(_emitConstructorName(node.constructedType, ctor),
@@ -4672,7 +4690,9 @@
if (isFromEnvironmentInvocation(coreTypes, node)) {
var value = _constants.evaluate(node);
- if (value is PrimitiveConstant) return value.accept(this);
+ if (value is PrimitiveConstant) {
+ return value.accept(this) as JS.Expression;
+ }
}
if (args.positional.isEmpty &&
@@ -4745,7 +4765,7 @@
}
@override
- visitNot(Not node) {
+ JS.Expression visitNot(Not node) {
var operand = node.operand;
if (operand is MethodInvocation && operand.name.name == '==') {
return _emitEqualityOperator(operand.receiver, operand.interfaceTarget,
@@ -4767,14 +4787,14 @@
}
@override
- visitLogicalExpression(LogicalExpression node) {
+ JS.Expression visitLogicalExpression(LogicalExpression node) {
// The operands of logical boolean operators are subject to boolean
// conversion.
return _visitTest(node);
}
@override
- visitConditionalExpression(ConditionalExpression node) {
+ JS.Expression visitConditionalExpression(ConditionalExpression node) {
return js.call('# ? # : #', [
_visitTest(node.condition),
_visitExpression(node.then),
@@ -4784,7 +4804,7 @@
}
@override
- visitStringConcatenation(StringConcatenation node) {
+ JS.Expression visitStringConcatenation(StringConcatenation node) {
var parts = <JS.Expression>[];
for (var e in node.expressions) {
var jsExpr = _visitExpression(e);
@@ -4793,14 +4813,14 @@
}
parts.add(e.getStaticType(types) == types.stringType && !isNullable(e)
? jsExpr
- : runtimeCall('str(#)', jsExpr));
+ : runtimeCall('str(#)', [jsExpr]));
}
if (parts.isEmpty) return js.string('');
return JS.Expression.binary(parts, '+');
}
@override
- visitListConcatenation(ListConcatenation node) {
+ JS.Expression visitListConcatenation(ListConcatenation node) {
// Only occurs inside unevaluated constants.
List<JS.Expression> entries = [];
_concatenate(Expression node) {
@@ -4822,7 +4842,7 @@
}
@override
- visitSetConcatenation(SetConcatenation node) {
+ JS.Expression visitSetConcatenation(SetConcatenation node) {
// Only occurs inside unevaluated constants.
List<JS.Expression> entries = [];
_concatenate(Expression node) {
@@ -4844,7 +4864,7 @@
}
@override
- visitMapConcatenation(MapConcatenation node) {
+ JS.Expression visitMapConcatenation(MapConcatenation node) {
// Only occurs inside unevaluated constants.
List<JS.Expression> entries = [];
_concatenate(Expression node) {
@@ -4872,13 +4892,13 @@
}
@override
- visitInstanceCreation(InstanceCreation node) {
+ JS.Expression visitInstanceCreation(InstanceCreation node) {
// Only occurs inside unevaluated constants.
throw new UnsupportedError("Instance creation");
}
@override
- visitIsExpression(IsExpression node) {
+ JS.Expression visitIsExpression(IsExpression node) {
return _emitIsExpression(node.operand, node.type);
}
@@ -4895,7 +4915,7 @@
}
@override
- visitAsExpression(AsExpression node) {
+ JS.Expression visitAsExpression(AsExpression node) {
Expression fromExpr = node.operand;
var to = node.type;
var jsFrom = _visitExpression(fromExpr);
@@ -4929,7 +4949,7 @@
// TODO(jmesserly): fuse this with notNull check.
// TODO(jmesserly): this does not correctly distinguish user casts from
// required-for-soundness casts.
- return runtimeCall('asInt(#)', jsFrom);
+ return runtimeCall('asInt(#)', [jsFrom]);
}
// A no-op in JavaScript.
@@ -4948,32 +4968,34 @@
}
@override
- visitSymbolLiteral(SymbolLiteral node) => emitDartSymbol(node.value);
+ JS.Expression visitSymbolLiteral(SymbolLiteral node) =>
+ emitDartSymbol(node.value);
@override
- visitTypeLiteral(TypeLiteral node) => _emitTypeLiteral(node.type);
+ JS.Expression visitTypeLiteral(TypeLiteral node) =>
+ _emitTypeLiteral(node.type);
- _emitTypeLiteral(DartType type) {
+ JS.Expression _emitTypeLiteral(DartType type) {
var typeRep = _emitType(type);
// If the type is a type literal expression in Dart code, wrap the raw
// runtime type in a "Type" instance.
- return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', typeRep);
+ return _isInForeignJS ? typeRep : runtimeCall('wrapType(#)', [typeRep]);
}
@override
- visitThisExpression(ThisExpression node) => JS.This();
+ JS.Expression visitThisExpression(ThisExpression node) => JS.This();
@override
- visitRethrow(Rethrow node) {
- return runtimeCall('rethrow(#)', _emitVariableRef(_rethrowParameter));
+ JS.Expression visitRethrow(Rethrow node) {
+ return runtimeCall('rethrow(#)', [_emitVariableRef(_rethrowParameter)]);
}
@override
- visitThrow(Throw node) =>
- runtimeCall('throw(#)', _visitExpression(node.expression));
+ JS.Expression visitThrow(Throw node) =>
+ runtimeCall('throw(#)', [_visitExpression(node.expression)]);
@override
- visitListLiteral(ListLiteral node) {
+ JS.Expression visitListLiteral(ListLiteral node) {
var elementType = node.typeArgument;
var elements = _visitExpressionList(node.expressions);
// TODO(markzipan): remove const check when we use front-end const eval
@@ -5005,7 +5027,7 @@
}
@override
- visitSetLiteral(SetLiteral node) {
+ JS.Expression visitSetLiteral(SetLiteral node) {
// TODO(markzipan): remove const check when we use front-end const eval
if (!node.isConst) {
var setType = visitInterfaceType(
@@ -5027,12 +5049,13 @@
}
@override
- visitMapLiteral(MapLiteral node) {
- var entries = <JS.Expression>[];
- for (var e in node.entries) {
- entries.add(_visitExpression(e.key));
- entries.add(_visitExpression(e.value));
- }
+ JS.Expression visitMapLiteral(MapLiteral node) {
+ var entries = [
+ for (var e in node.entries) ...[
+ _visitExpression(e.key),
+ _visitExpression(e.value),
+ ],
+ ];
// TODO(markzipan): remove const check when we use front-end const eval
if (!node.isConst) {
@@ -5053,11 +5076,11 @@
}
@override
- visitAwaitExpression(AwaitExpression node) =>
+ JS.Expression visitAwaitExpression(AwaitExpression node) =>
JS.Yield(_visitExpression(node.operand));
@override
- visitFunctionExpression(FunctionExpression node) {
+ JS.Expression visitFunctionExpression(FunctionExpression node) {
var fn = _emitArrowFunction(node);
if (!_reifyFunctionType(node.function)) return fn;
return _emitFunctionTagged(fn, node.getStaticType(types) as FunctionType);
@@ -5069,11 +5092,11 @@
// Simplify `=> { return e; }` to `=> e`
if (body is JS.Block) {
- JS.Block block = body;
+ var block = body as JS.Block;
if (block.statements.length == 1) {
JS.Statement s = block.statements[0];
if (s is JS.Block) {
- block = s;
+ block = s as JS.Block;
s = block.statements.length == 1 ? block.statements[0] : null;
}
if (s is JS.Return && s.value != null) body = s.value;
@@ -5086,22 +5109,24 @@
}
@override
- visitStringLiteral(StringLiteral node) => js.escapedString(node.value, '"');
+ JS.Expression visitStringLiteral(StringLiteral node) =>
+ js.escapedString(node.value, '"');
@override
- visitIntLiteral(IntLiteral node) => js.uint64(node.value);
+ JS.Expression visitIntLiteral(IntLiteral node) => js.uint64(node.value);
@override
- visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
+ JS.Expression visitDoubleLiteral(DoubleLiteral node) => js.number(node.value);
@override
- visitBoolLiteral(BoolLiteral node) => JS.LiteralBool(node.value);
+ JS.Expression visitBoolLiteral(BoolLiteral node) =>
+ JS.LiteralBool(node.value);
@override
- visitNullLiteral(NullLiteral node) => JS.LiteralNull();
+ JS.Expression visitNullLiteral(NullLiteral node) => JS.LiteralNull();
@override
- visitLet(Let node) {
+ JS.Expression visitLet(Let node) {
var v = node.variable;
var init = _visitExpression(v.initializer);
var body = _visitExpression(node.body);
@@ -5123,12 +5148,12 @@
}
@override
- visitBlockExpression(BlockExpression node) {
+ JS.Expression visitBlockExpression(BlockExpression node) {
var jsExpr = _visitExpression(node.value);
- List<JS.Statement> jsStmts = node.body.statements
- .map(_visitStatement)
- .toList()
- ..add(JS.Return(jsExpr));
+ var jsStmts = [
+ for (var s in node.body.statements) _visitStatement(s),
+ JS.Return(jsExpr),
+ ];
var jsBlock = JS.Block(jsStmts);
// BlockExpressions with async operations must be constructed
// with a generator instead of a lambda.
@@ -5146,7 +5171,7 @@
}
@override
- visitInstantiation(Instantiation node) {
+ JS.Expression visitInstantiation(Instantiation node) {
return runtimeCall('gbind(#, #)', [
_visitExpression(node.expression),
node.typeArguments.map(_emitType).toList()
@@ -5154,14 +5179,16 @@
}
@override
- visitLoadLibrary(LoadLibrary node) => runtimeCall('loadLibrary()');
+ JS.Expression visitLoadLibrary(LoadLibrary node) =>
+ runtimeCall('loadLibrary()');
// TODO(jmesserly): DDC loads all libraries eagerly.
// See
// https://github.com/dart-lang/sdk/issues/27776
// https://github.com/dart-lang/sdk/issues/27777
@override
- visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) => js.boolean(true);
+ JS.Expression visitCheckLibraryIsLoaded(CheckLibraryIsLoaded node) =>
+ js.boolean(true);
bool _reifyFunctionType(FunctionNode f) {
if (_currentLibrary.importUri.scheme != 'dart') return true;
@@ -5204,18 +5231,19 @@
/// Calls [findAnnotation] followed by [getNameFromAnnotation].
String getAnnotationName(NamedNode node, bool test(Expression value)) {
return _constants.getFieldValueFromAnnotation(
- findAnnotation(node, test), 'name');
+ findAnnotation(node, test), 'name') as String;
}
- JS.Expression visitConstant(Constant node) => node.accept(this);
+ JS.Expression visitConstant(Constant node) =>
+ node.accept(this) as JS.Expression;
@override
- visitNullConstant(NullConstant node) => JS.LiteralNull();
+ JS.Expression visitNullConstant(NullConstant node) => JS.LiteralNull();
@override
- visitBoolConstant(BoolConstant node) => js.boolean(node.value);
+ JS.Expression visitBoolConstant(BoolConstant node) => js.boolean(node.value);
@override
- visitIntConstant(IntConstant node) => js.number(node.value);
+ JS.Expression visitIntConstant(IntConstant node) => js.number(node.value);
@override
- visitDoubleConstant(DoubleConstant node) {
+ JS.Expression visitDoubleConstant(DoubleConstant node) {
var value = node.value;
// Emit the constant as an integer, if possible.
@@ -5233,41 +5261,41 @@
}
@override
- visitStringConstant(StringConstant node) => js.escapedString(node.value, '"');
+ JS.Expression visitStringConstant(StringConstant node) =>
+ js.escapedString(node.value, '"');
// DDC does not currently use the non-primivite constant nodes; rather these
// are emitted via their normal expression nodes.
@override
- defaultConstant(Constant node) => _emitInvalidNode(node);
+ JS.Expression defaultConstant(Constant node) => _emitInvalidNode(node);
@override
- visitSymbolConstant(node) => emitDartSymbol(node.name);
+ JS.Expression visitSymbolConstant(SymbolConstant node) =>
+ emitDartSymbol(node.name);
@override
- visitMapConstant(node) {
- var entries = <JS.Expression>[];
- for (var e in node.entries) {
- entries.add(visitConstant(e.key));
- entries.add(visitConstant(e.value));
- }
-
+ JS.Expression visitMapConstant(MapConstant node) {
+ var entries = [
+ for (var e in node.entries) ...[
+ visitConstant(e.key),
+ visitConstant(e.value),
+ ],
+ ];
return _emitConstMap(node.keyType, node.valueType, entries);
}
@override
- visitListConstant(node) => _emitConstList(
+ JS.Expression visitListConstant(ListConstant node) => _emitConstList(
node.typeArgument, node.entries.map(visitConstant).toList());
@override
- visitSetConstant(node) {
- return _emitConstSet(
- node.typeArgument, node.entries.map(visitConstant).toList());
- }
+ JS.Expression visitSetConstant(SetConstant node) => _emitConstSet(
+ node.typeArgument, node.entries.map(visitConstant).toList());
@override
- visitInstanceConstant(node) {
+ JS.Expression visitInstanceConstant(InstanceConstant node) {
entryToProperty(MapEntry<Reference, Constant> entry) {
- var constant = entry.value.accept(this);
+ var constant = entry.value.accept(this) as JS.Expression;
var member = entry.key.asField;
return JS.Property(
_emitMemberName(member.name.name, member: member), constant);
@@ -5275,30 +5303,33 @@
var type = visitInterfaceType(node.getType(types) as InterfaceType);
var prototype = js.call("#.prototype", [type]);
- var properties = [JS.Property(propertyName("__proto__"), prototype)]
- ..addAll(node.fieldValues.entries.map(entryToProperty));
+ var properties = [
+ JS.Property(propertyName("__proto__"), prototype),
+ for (var e in node.fieldValues.entries) entryToProperty(e),
+ ];
return canonicalizeConstObject(
JS.ObjectInitializer(properties, multiline: true));
}
@override
- visitTearOffConstant(node) => _emitStaticGet(node.procedure);
+ JS.Expression visitTearOffConstant(TearOffConstant node) =>
+ _emitStaticGet(node.procedure);
@override
- visitTypeLiteralConstant(node) => _emitTypeLiteral(node.type);
+ JS.Expression visitTypeLiteralConstant(TypeLiteralConstant node) =>
+ _emitTypeLiteral(node.type);
@override
- visitPartialInstantiationConstant(node) {
- return runtimeCall('gbind(#, #)', [
- visitConstant(node.tearOffConstant),
- node.types.map(_emitType).toList()
- ]);
- }
+ JS.Expression visitPartialInstantiationConstant(
+ PartialInstantiationConstant node) =>
+ runtimeCall('gbind(#, #)', [
+ visitConstant(node.tearOffConstant),
+ node.types.map(_emitType).toList()
+ ]);
@override
- visitUnevaluatedConstant(node) {
- return _visitExpression(node.expression);
- }
+ JS.Expression visitUnevaluatedConstant(UnevaluatedConstant node) =>
+ _visitExpression(node.expression);
}
bool _isInlineJSFunction(Statement body) {
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index 4fe583b..3066d8e 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -118,7 +118,7 @@
final CoreTypes coreTypes;
_ConstantVisitor(this.coreTypes);
- bool isConstant(Expression e) => e.accept(this);
+ bool isConstant(Expression e) => e.accept(this) as bool;
@override
defaultExpression(node) => false;
@@ -200,6 +200,23 @@
@override
NumberSemantics get numberSemantics => NumberSemantics.js;
+
+ @override
+ bool shouldInlineConstant(ConstantExpression initializer) {
+ Constant constant = initializer.constant;
+ if (constant is StringConstant) {
+ // Only inline small string constants, not large ones.
+ // (The upper bound value is arbitrary.)
+ return constant.value.length < 32;
+ } else if (constant is PrimitiveConstant) {
+ // Inline all other primitives.
+ return true;
+ } else {
+ // Don't inline other constants, because it would take too much code size.
+ // Better to refer to them by their field/variable name.
+ return false;
+ }
+ }
}
class _ErrorReporter extends SimpleErrorReporter {
diff --git a/pkg/dev_compiler/lib/src/kernel/native_types.dart b/pkg/dev_compiler/lib/src/kernel/native_types.dart
index 99a2140..d5450f6 100644
--- a/pkg/dev_compiler/lib/src/kernel/native_types.dart
+++ b/pkg/dev_compiler/lib/src/kernel/native_types.dart
@@ -142,7 +142,7 @@
/// field (which is also the constructor parameter).
String _getNativeAnnotationName(Expression annotation) {
if (!_isNativeAnnotation(annotation)) return null;
- return constants.getFieldValueFromAnnotation(annotation, 'name');
+ return constants.getFieldValueFromAnnotation(annotation, 'name') as String;
}
}
diff --git a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
index 185d3f0..481a4e8 100644
--- a/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
+++ b/pkg/dev_compiler/lib/src/kernel/nullable_inference.dart
@@ -230,7 +230,7 @@
@override
visitConstantExpression(ConstantExpression node) {
var c = node.constant;
- if (c is UnevaluatedConstant) return c.expression.accept(this);
+ if (c is UnevaluatedConstant) return c.expression.accept(this) as bool;
if (c is PrimitiveConstant) return c.value == null;
return false;
}
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 5738f30..e954139 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -67,8 +67,21 @@
uri.scheme == 'dart' &&
(uri.path == 'core' || uri.path == '_interceptors');
+ bool _allowedTestLibrary(Uri uri) {
+ String scriptName = uri.path;
+ return scriptName.contains('tests/compiler/dartdevc_native');
+ }
+
+ bool _allowedDartLibrary(Uri uri) => uri.scheme == 'dart';
+
@override
- bool enableNative(Uri uri) => uri.scheme == 'dart';
+ bool enableNative(Uri uri) =>
+ _allowedTestLibrary(uri) || _allowedDartLibrary(uri);
+
+ @override
+ bool allowPlatformPrivateLibraryAccess(Uri importer, Uri imported) =>
+ super.allowPlatformPrivateLibraryAccess(importer, imported) ||
+ _allowedTestLibrary(importer);
@override
bool get nativeExtensionExpectsString => false;
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index ea33a0b..7ca09fb 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -2,7 +2,7 @@
publish_to: none
environment:
- sdk: '>=2.1.0 <3.0.0'
+ sdk: '>=2.3.0 <3.0.0'
dependencies:
analyzer: any
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/.packages b/pkg/dev_compiler/test/modular/data/js_interop/.packages
new file mode 100644
index 0000000..68d6156
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/.packages
@@ -0,0 +1 @@
+js:../../../../../../pkg/js/lib
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/log.dart b/pkg/dev_compiler/test/modular/data/js_interop/log.dart
new file mode 100644
index 0000000..f69bf62
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/log.dart
@@ -0,0 +1,27 @@
+// 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.
+
+/// Calls to [console.log] and to [log] from other modules don't work if the
+/// js-interop annotations are not preserved. However, calls via [log2] and
+/// [log3] do work because the annotation is available when compiling this
+/// module.
+@JS()
+library log;
+
+import 'package:js/js.dart';
+
+@JS()
+class Console {
+ @JS()
+ external void log(arg);
+}
+
+@JS('console')
+external Console get console;
+
+@JS('console.log')
+external void log(String s);
+
+void log2(String s) => log(s);
+void log3(String s) => console.log(s);
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/main.dart b/pkg/dev_compiler/test/modular/data/js_interop/main.dart
new file mode 100644
index 0000000..f0d26c2
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/main.dart
@@ -0,0 +1,11 @@
+// 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 'log.dart';
+
+void main() {
+ log2('A');
+ log3('B');
+ log('C');
+ console.log('D');
+}
diff --git a/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml b/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml
new file mode 100644
index 0000000..021eddc
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/data/js_interop/modules.yaml
@@ -0,0 +1,8 @@
+# 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.
+#
+# Regression test: js-interop annotations need to be preserved in outline files.
+dependencies:
+ main: log
+ log: js
diff --git a/pkg/dev_compiler/test/modular/modular_test.dart b/pkg/dev_compiler/test/modular/modular_test.dart
new file mode 100644
index 0000000..8e96f72
--- /dev/null
+++ b/pkg/dev_compiler/test/modular/modular_test.dart
@@ -0,0 +1,320 @@
+// 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.
+
+/// Test the modular compilation pipeline of ddc.
+///
+/// This is a shell that runs multiple tests, one per folder under `data/`.
+import 'dart:io';
+
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/pipeline.dart';
+import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
+
+Uri sdkRoot = Platform.script.resolve("../../../../");
+Options _options;
+main(List<String> args) async {
+ _options = Options.parse(args);
+ var suiteFolder = Platform.script.resolve('data/');
+ var suiteName = relativize(suiteFolder, sdkRoot).path;
+ await runSuite(
+ suiteFolder,
+ suiteName.substring(0, suiteName.length - 1), // remove trailing /
+ _options,
+ new IOPipeline([
+ SourceToSummaryDillStep(),
+ DDKStep(),
+ RunD8(),
+ ], cacheSharedModules: true));
+}
+
+const dillId = const DataId("dill");
+const jsId = const DataId("js");
+const txtId = const DataId("txt");
+
+class SourceToSummaryDillStep implements IOModularStep {
+ @override
+ List<DataId> get resultData => const [dillId];
+
+ @override
+ bool get needsSources => true;
+
+ @override
+ List<DataId> get dependencyDataNeeded => const [dillId];
+
+ @override
+ List<DataId> get moduleDataNeeded => const [];
+
+ @override
+ bool get onlyOnMain => false;
+
+ @override
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: source-to-dill on $module");
+
+ // We use non file-URI schemes for representing source locations in a
+ // root-agnostic way. This allows us to refer to file across modules and
+ // across steps without exposing the underlying temporary folders that are
+ // created by the framework. In build systems like bazel this is especially
+ // important because each step may be run on a different machine.
+ //
+ // Files in packages are defined in terms of `package:` URIs, while
+ // non-package URIs are defined using the `dart-dev-app` scheme.
+ String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
+ String sourceToImportUri(Uri relativeUri) =>
+ _sourceToImportUri(module, rootScheme, relativeUri);
+
+ Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+ _createPackagesFile(module, root, transitiveDependencies);
+
+ List<String> sources;
+ List<String> extraArgs;
+ if (module.isSdk) {
+ sources = ['dart:core'];
+ extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+ assert(transitiveDependencies.isEmpty);
+ } else {
+ sources = module.sources.map(sourceToImportUri).toList();
+ extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+ }
+
+ List<String> args = [
+ sdkRoot.resolve("utils/bazel/kernel_worker.dart").toFilePath(),
+ '--summary-only',
+ '--target',
+ 'ddc',
+ '--multi-root',
+ '$root',
+ '--multi-root-scheme',
+ rootScheme,
+ ...extraArgs,
+ '--output',
+ '${toUri(module, dillId)}',
+ ...(transitiveDependencies
+ .expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
+ ...(sources.expand((String uri) => ['--source', uri])),
+ ...(flags.expand((String flag) => ['--enable-experiment', flag])),
+ ];
+
+ var result =
+ await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+ _checkExitCode(result, this, module);
+ }
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: source-to-dill on $module");
+ }
+}
+
+class DDKStep implements IOModularStep {
+ @override
+ List<DataId> get resultData => const [jsId];
+
+ @override
+ bool get needsSources => true;
+
+ @override
+ List<DataId> get dependencyDataNeeded => const [dillId];
+
+ @override
+ List<DataId> get moduleDataNeeded => const [dillId];
+
+ @override
+ bool get onlyOnMain => false;
+
+ @override
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: ddk on $module");
+ var sdkRoot = Platform.script.resolve("../../../../");
+
+ Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
+ _createPackagesFile(module, root, transitiveDependencies);
+
+ List<String> args;
+ if (module.isSdk) {
+ // TODO(sigmund): this produces an error because kernel_sdk doesn't have a
+ // way to provide a .packages file. Technically is not needed, but it
+ // would be nice to proceed without any error messages.
+ args = [
+ '--packages=${sdkRoot.toFilePath()}/.packages',
+ sdkRoot.resolve('pkg/dev_compiler/tool/kernel_sdk.dart').toFilePath(),
+ '--libraries',
+ 'sdk/lib/libraries.json',
+ '--output',
+ '${toUri(module, jsId)}.ignored_dill',
+ ];
+ var result = await _runProcess(
+ Platform.resolvedExecutable, args, root.toFilePath());
+ _checkExitCode(result, this, module);
+ await File.fromUri(root.resolve('es6/dart_sdk.js'))
+ .copy(root.resolveUri(toUri(module, jsId)).toFilePath());
+ } else {
+ Uri output = toUri(module, jsId);
+ Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
+ String sourceToImportUri(Uri relativeUri) =>
+ _sourceToImportUri(module, 'dev-dart-app', relativeUri);
+
+ args = [
+ '--packages=${sdkRoot.toFilePath()}/.packages',
+ sdkRoot.resolve('pkg/dev_compiler/bin/dartdevc.dart').toFilePath(),
+ '--kernel',
+ '--modules=es6',
+ '--no-summarize',
+ '--no-source-map',
+ '--multi-root-scheme',
+ 'dev-dart-app',
+ '--dart-sdk-summary',
+ '${toUri(sdkModule, dillId)}',
+ '--packages',
+ '.packages',
+ ...module.sources.map(sourceToImportUri),
+ for (String flag in flags) '--enable-experiment=$flag',
+ ...(transitiveDependencies
+ .where((m) => !m.isSdk)
+ .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+ '-o',
+ '$output',
+ ];
+ var result = await _runProcess(
+ Platform.resolvedExecutable, args, root.toFilePath());
+ _checkExitCode(result, this, module);
+ }
+ }
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: ddk on $module");
+ }
+}
+
+class RunD8 implements IOModularStep {
+ @override
+ List<DataId> get resultData => const [txtId];
+
+ @override
+ bool get needsSources => false;
+
+ @override
+ List<DataId> get dependencyDataNeeded => const [jsId];
+
+ @override
+ List<DataId> get moduleDataNeeded => const [jsId];
+
+ @override
+ bool get onlyOnMain => true;
+
+ @override
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: d8 on $module");
+ var sdkRoot = Platform.script.resolve("../../../../");
+
+ // Rename sdk.js to dart_sdk.js (the alternative, but more hermetic solution
+ // would be to rename the import on all other .js files, but seems
+ // overkill/unnecessary.
+ if (await File.fromUri(root.resolve('dart_sdk.js')).exists()) {
+ throw 'error: dart_sdk.js already exists.';
+ }
+
+ await File.fromUri(root.resolve('sdk.js'))
+ .copy(root.resolve('dart_sdk.js').toFilePath());
+ var runjs = '''
+ import { dart, _isolate_helper } from 'dart_sdk.js';
+ import { main } from 'main.js';
+ _isolate_helper.startRootIsolate(() => {}, []);
+ main.main();
+ ''';
+
+ var wrapper =
+ root.resolveUri(toUri(module, jsId)).toFilePath() + ".wrapper.js";
+ await File(wrapper).writeAsString(runjs);
+ List<String> d8Args = ['--module', wrapper];
+ var result = await _runProcess(
+ sdkRoot.resolve(_d8executable).toFilePath(), d8Args, root.toFilePath());
+
+ _checkExitCode(result, this, module);
+
+ await File.fromUri(root.resolveUri(toUri(module, txtId)))
+ .writeAsString(result.stdout as String);
+ }
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: d8 on $module");
+ }
+}
+
+void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
+ if (result.exitCode != 0 || _options.verbose) {
+ stdout.write(result.stdout);
+ stderr.write(result.stderr);
+ }
+ if (result.exitCode != 0) {
+ throw "${step.runtimeType} failed on $module:\n\n"
+ "stdout:\n${result.stdout}\n\n"
+ "stderr:\n${result.stderr}";
+ }
+}
+
+Future<ProcessResult> _runProcess(
+ String command, List<String> arguments, String workingDirectory) {
+ if (_options.verbose) {
+ print('command:\n$command ${arguments.join(' ')} from $workingDirectory');
+ }
+ return Process.run(command, arguments, workingDirectory: workingDirectory);
+}
+
+String get _d8executable {
+ if (Platform.isWindows) {
+ return 'third_party/d8/windows/d8.exe';
+ } else if (Platform.isLinux) {
+ return 'third_party/d8/linux/d8';
+ } else if (Platform.isMacOS) {
+ return 'third_party/d8/macos/d8';
+ }
+ throw new UnsupportedError('Unsupported platform.');
+}
+
+Future<void> _createPackagesFile(
+ Module module, Uri root, Set<Module> transitiveDependencies) async {
+ // We create a .packages file which defines the location of this module if
+ // it is a package. The CFE requires that if a `package:` URI of a
+ // dependency is used in an import, then we need that package entry in the
+ // .packages file. However, after it checks that the definition exists, the
+ // CFE will not actually use the resolved URI if a library for the import
+ // URI is already found in one of the provided .dill files of the
+ // dependencies. For that reason, and to ensure that a step only has access
+ // to the files provided in a module, we generate a .packages with invalid
+ // folders for other packages.
+ // TODO(sigmund): follow up with the CFE to see if we can remove the need
+ // for the .packages entry altogether if they won't need to read the
+ // sources.
+ var packagesContents = new StringBuffer();
+ if (module.isPackage) {
+ packagesContents.write('${module.name}:${module.packageBase}\n');
+ }
+ for (Module dependency in transitiveDependencies) {
+ if (dependency.isPackage) {
+ packagesContents.write('${dependency.name}:unused\n');
+ }
+ }
+
+ await File.fromUri(root.resolve('.packages'))
+ .writeAsString('$packagesContents');
+}
+
+String _sourceToImportUri(Module module, String rootScheme, Uri relativeUri) {
+ if (module.isPackage) {
+ var basePath = module.packageBase.path;
+ var packageRelativePath = basePath == "./"
+ ? relativeUri.path
+ : relativeUri.path.substring(basePath.length);
+ return 'package:${module.name}/$packageRelativePath';
+ } else {
+ return '$rootScheme:/$relativeUri';
+ }
+}
diff --git a/pkg/dev_compiler/test/sourcemap/ddc_common.dart b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
index 74f2764..f6f4838 100644
--- a/pkg/dev_compiler/test/sourcemap/ddc_common.dart
+++ b/pkg/dev_compiler/test/sourcemap/ddc_common.dart
@@ -167,7 +167,7 @@
var sdkFile = File(path.relative(sdkJsFile.path, from: sdkRoot.path));
String jsRootDart = "/root_dart/${sdkFile.uri}";
File.fromUri(outputFile.resolve("$outputFilename.html.js")).writeAsStringSync(
- jsContent.replaceFirst("from 'dart_sdk'", "from '$jsRootDart'"));
+ jsContent.replaceFirst("from 'dart_sdk.js'", "from '$jsRootDart'"));
File.fromUri(outputFile.resolve("$outputFilename.html.html"))
.writeAsStringSync(getWrapperHtmlContent(
jsRootDart, "/root_build/$outputFilename.html.js"));
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
index d14cc6d..3818d6f 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddc_suite.dart
@@ -70,7 +70,7 @@
var jsContent = File.fromUri(outputFile).readAsStringSync();
File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
- "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+ "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
if (debugging) {
createHtmlWrapper(
diff --git a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
index de9c620..511c10b 100644
--- a/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
+++ b/pkg/dev_compiler/test/sourcemap/sourcemaps_ddk_suite.dart
@@ -70,7 +70,8 @@
bool succeeded = false;
try {
var result = await compile(args, compilerState: context.compilerState);
- context.compilerState = result.compilerState;
+ context.compilerState =
+ result.compilerState as fe.InitializedCompilerState;
succeeded = result.success;
} catch (e, s) {
print('Unhandled exception:');
@@ -88,7 +89,7 @@
var jsContent = File.fromUri(outputFile).readAsStringSync();
File.fromUri(outputFile).writeAsStringSync(jsContent.replaceFirst(
- "from 'dart_sdk'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
+ "from 'dart_sdk.js'", "from '${uriPathForwardSlashed(jsSdkPath)}'"));
if (debugging) {
createHtmlWrapper(
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 0b3049e..6cd6de3 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -77,11 +77,21 @@
var summaries = options['summary'] as List;
var port = int.parse(options['port'] as String);
+ // By default (no `-d`), we use the `dartdevc` binary on the user's path to
+ // compute the SDK we use for execution. I.e., we assume that `dart` is
+ // under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related
+ // artifacts. In this mode, this script can run against any installed SDK.
+ // If you want to run against a freshly built SDK, that must be first on
+ // your path.
var dartBinary = Platform.resolvedExecutable;
- var dartPath = path.dirname(dartBinary);
- var dartSdk = path.dirname(dartPath);
+ var dartSdk = path.dirname(path.dirname(dartBinary));
+
+ // In debug mode (`-d`), we run from the `pkg/dev_compiler` sources. We
+ // determine the location via this actual script (i.e., `-d` assumes
+ // this script remains under to `tool` sub-directory).
var toolPath = Platform.script.normalizePath().toFilePath();
var ddcPath = path.dirname(path.dirname(toolPath));
+ var dartCheckoutPath = path.dirname(path.dirname(ddcPath));
ProcessResult runDdc(String command, List<String> args) {
if (debug) {
@@ -91,7 +101,7 @@
command = dartBinary;
} else {
// Use built snapshot.
- command = path.join(dartPath, command);
+ command = path.join(dartSdk, 'bin', command);
}
return Process.runSync(command, args);
}
@@ -236,6 +246,15 @@
nodeBinary, ['--inspect=localhost:$port', nodeFile],
environment: {'NODE_PATH': nodePath});
} else if (d8) {
+ // Fix SDK import. `d8` doesn't let us set paths, so we need a full path
+ // to the SDK.
+
+ var jsFile = File('$libRoot/$basename.js');
+ var jsContents = jsFile.readAsStringSync();
+ jsContents = jsContents.replaceFirst(
+ "from 'dart_sdk.js'", "from '$sdkJsPath/dart_sdk.js'");
+ jsFile.writeAsStringSync(jsContents);
+
var runjs = '''
import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
import { $basename } from '$basename.js';
@@ -248,10 +267,21 @@
console.error(e);
}
''';
- var d8File = '$libRoot/$basename.d8.js';
+ var d8File = path.join(libRoot, '$basename.d8.js');
new File(d8File).writeAsStringSync(runjs);
- var d8Binary = binary ?? 'd8';
+ var d8Binary = binary ?? path.join(dartCheckoutPath, _d8executable);
result = Process.runSync(d8Binary, ['--module', d8File]);
}
await echoResult(result);
}
+
+String get _d8executable {
+ if (Platform.isWindows) {
+ return path.join('third_party', 'd8', 'windows', 'd8.exe');
+ } else if (Platform.isLinux) {
+ return path.join('third_party', 'd8', 'linux', 'd8');
+ } else if (Platform.isMacOS) {
+ return path.join('third_party', 'd8', 'macos', 'd8');
+ }
+ throw new UnsupportedError('Unsupported platform.');
+}
diff --git a/pkg/dev_compiler/tool/ddw b/pkg/dev_compiler/tool/ddw
deleted file mode 100755
index c35b2ca..0000000
--- a/pkg/dev_compiler/tool/ddw
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/bin/bash
-#
-# Compiles code with DDC and runs the resulting code in node.js.
-#
-# The first script supplied should be the one with `main()`.
-#
-# Saves the output in the same directory as the sources for convenient
-# inspection, modification or rerunning the code.
-set -e
-
-function follow_links() {
- file="$1"
- while [ -h "$file" ]; do
- file="$(readlink "$file")"
- done
- echo "$file"
-}
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-SDK_DIR="$( cd "${PROG_NAME%/*}/../../.."; pwd -P)"
-
-if [[ `uname` == 'Darwin' ]];
-then
- OUT_DIR="$SDK_DIR"/xcodebuild
-else
- OUT_DIR="$SDK_DIR"/out
-fi
-
-if [ -z "$DART_CONFIGURATION" ];
-then
- DIRS=$( ls "$OUT_DIR" )
- # list of possible configurations in decreasing desirability
- CONFIGS=("ReleaseX64" "ReleaseIA32" "DebugX64" "DebugIA32"
- "ReleaseARM" "ReleaseARM64" "ReleaseARMV5TE"
- "DebugARM" "DebugARM64" "DebugARMV5TE")
- DART_CONFIGURATION="None"
- for CONFIG in ${CONFIGS[*]}
- do
- for DIR in $DIRS;
- do
- if [ "$CONFIG" = "$DIR" ];
- then
- # choose most desirable configuration that is available and break
- DART_CONFIGURATION="$DIR"
- break 2
- fi
- done
- done
- if [ "$DART_CONFIGURATION" = "None" ]
- then
- echo "No valid dart configuration found in $OUT_DIR"
- exit 1
- fi
-fi
-
-GEN_DIR="$OUT_DIR"/"$DART_CONFIGURATION"/gen/utils/dartdevc
-
-KERNEL=false
-if [ "$1" = "-k" ]; then
- KERNEL=true
- shift
-fi
-
-BASENAME=$( basename "${1%.*}")
-LIBROOT=$(cd $( dirname "${1%.*}") && pwd)
-
-if [ "$KERNEL" = true ]; then
-
- if [ ! -e $GEN_DIR/kernel/ddc_sdk.dill ]; then
- echo "DDC SDK must be built first, please run:"
- echo " pushd $SDKDIR"
- echo " ./tools/build.py -m release dartdevc_kernel_sdk"
- exit 1
- fi
-
- NODE_PATH=$GEN_DIR/kernel/common:$LIBROOT:$NODE_PATH
-
- dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --kernel --modules=node \
- --dart-sdk-summary=$GEN_DIR/kernel/ddc_sdk.dill \
- -o $LIBROOT/$BASENAME.js $*
-else
-
- if [ ! -e $GEN_DIR/ddc_sdk.sum ]; then
- echo "DDC SDK must be built first, please run:"
- echo " pushd $SDKDIR"
- echo " ./tools/build.py -m release dartdevc_sdk"
- exit 1
- fi
-
- NODE_PATH=$GEN_DIR/js/common:$LIBROOT:$NODE_PATH
-
- dart -c $SDK_DIR/pkg/dev_compiler/bin/dartdevc.dart --modules=node \
- --library-root=$LIBROOT --dart-sdk-summary=$GEN_DIR/ddc_sdk.sum \
- -o $LIBROOT/$BASENAME.js $*
-fi
-
-pushd $LIBROOT > /dev/null
-echo "
- // Fix the node.js search paths that Electron cleared out.
- const Module = require('module');
- const originalResolveFilename = Module._resolveFilename;
- Module._resolveFilename = function (request, parent, isMain) {
- let paths = parent.paths;
- const ddcPath = \"$GEN_DIR/js/common\";
- if (paths[0] != ddcPath) {
- paths.splice(0, 0, ddcPath, \"$LIBROOT\");
- }
- return originalResolveFilename(request, parent, isMain);
- };
- let sdk = require(\"dart_sdk\");
- let main = require(\"$BASENAME\").$BASENAME.main;
- sdk.dart.ignoreWhitelistedErrors(false);
- sdk._isolate_helper.startRootIsolate(main, []);" \
- > $LIBROOT/$BASENAME.run.js
-devtool $LIBROOT/$BASENAME.run.js
-popd > /dev/null
diff --git a/pkg/dev_compiler/tool/global_compile.dart b/pkg/dev_compiler/tool/global_compile.dart
deleted file mode 100644
index a1f96fd..0000000
--- a/pkg/dev_compiler/tool/global_compile.dart
+++ /dev/null
@@ -1,285 +0,0 @@
-#!/usr/bin/env dart
-// Copyright (c) 2016, 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:io';
-
-// ignore: deprecated_member_use
-import 'package:analyzer/analyzer.dart' show parseDirectives;
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
-import 'package:args/args.dart' show ArgParser;
-import 'package:path/path.dart' as path;
-
-const ENTRY = "main";
-
-void main(List<String> args) {
- // Parse flags.
- var parser = ArgParser()
- ..addOption('out',
- help: 'Output file (defaults to "out.js")',
- abbr: 'o',
- defaultsTo: 'out.js')
- ..addFlag('unsafe-force-compile',
- help: 'Generate code with undefined behavior', negatable: false)
- ..addFlag('emit-metadata',
- help: 'Preserve annotations in generated code', negatable: false)
- ..addOption('package-root',
- help: 'Directory containing packages',
- abbr: 'p',
- defaultsTo: 'packages/')
- ..addFlag('log', help: 'Show individual build commands')
- ..addOption('tmp',
- help:
- 'Directory for temporary artifacts (defaults to a system tmp directory)');
-
- var options = parser.parse(args);
- if (options.rest.length != 1) {
- throw 'Expected a single dart entrypoint.';
- }
- var entry = options.rest.first;
- var outfile = options['out'] as String;
- var packageRoot = options['package-root'] as String;
- var unsafe = options['unsafe-force-compile'] as bool;
- var log = options['log'] as bool;
- var tmp = options['tmp'] as String;
- var metadata = options['emit-metadata'] as bool;
-
- // Build an invocation to dartdevc
- var dartPath = Platform.resolvedExecutable;
- var ddcPath = path.dirname(path.dirname(Platform.script.toFilePath()));
- var template = [
- '$ddcPath/bin/dartdevc.dart',
- '--modules=legacy', // TODO(vsm): Change this to use common format.
- '--single-out-file',
- '--inline-source-map',
- '-p',
- packageRoot
- ];
- if (metadata) {
- template.add('--emit-metadata');
- }
- if (unsafe) {
- template.add('--unsafe-force-compile');
- }
-
- // Compute the transitive closure
- var total = Stopwatch()..start();
- var partial = Stopwatch()..start();
-
- // TODO(vsm): We're using the analyzer just to compute the import/export/part
- // dependence graph. This is expensive. Is there a lighterweight way to do
- // this?
- transitiveFiles(entry, Directory.current.path, packageRoot);
- orderModules();
- computeTransitiveDependences();
-
- var graphTime = partial.elapsedMilliseconds / 1000;
- print('Computed global build graph in $graphTime seconds');
-
- // Prepend Dart runtime files to the output
- var out = File(outfile);
- var dartLibrary =
- File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'))
- .readAsStringSync();
- out.writeAsStringSync(dartLibrary);
- var dartSdk = File(path.join(ddcPath, 'lib', 'js', 'legacy', 'dart_sdk.js'))
- .readAsStringSync();
- out.writeAsStringSync(dartSdk, mode: FileMode.append);
-
- // Linearize module concatenation for deterministic output
- var last = Future.value();
- for (var module in orderedModules) {
- linearizerMap[module] = last;
- var completer = Completer();
- completerMap[module] = completer;
- last = completer.future;
- }
-
- // Build modules asynchronously
- var tmpdir = (tmp == null)
- ? Directory.systemTemp
- .createTempSync(outfile.replaceAll(path.separator, '__'))
- : Directory(tmp)
- ..createSync();
- for (var module in orderedModules) {
- var file = tmpdir.path + path.separator + module + '.js';
- var command = template.toList()..addAll(['-o', file]);
- var dependences = transitiveDependenceMap[module];
- for (var dependence in dependences) {
- var summary = tmpdir.path + path.separator + dependence + '.sum';
- command.addAll(['-s', summary]);
- }
- var infiles = fileMap[module];
- command.addAll(infiles);
-
- var waitList = dependenceMap.containsKey(module)
- ? dependenceMap[module].map((dep) => readyMap[dep])
- : <Future>[];
- var future = Future.wait(waitList);
- readyMap[module] = future.then((_) {
- var ready = Process.run(dartPath, command);
- if (log) {
- print(command.join(' '));
- }
- return ready.then((result) {
- if (result.exitCode != 0) {
- print('ERROR: compiling $module');
- print(result.stdout);
- print(result.stderr);
- out.deleteSync();
- exit(1);
- }
- print('Compiled $module (${infiles.length} files)');
- print(result.stdout);
-
- // Schedule module append once the previous module is written
- var codefile = File(file);
- linearizerMap[module]
- .then((_) => codefile.readAsString())
- .then((code) =>
- out.writeAsString(code, mode: FileMode.append, flush: true))
- .then((_) => completerMap[module].complete());
- });
- });
- }
-
- last.then((_) {
- var time = total.elapsedMilliseconds / 1000;
- print('Successfully compiled ${inputSet.length} files in $time seconds');
-
- // Append the entry point invocation.
- var libraryName =
- path.withoutExtension(entry).replaceAll(path.separator, '__');
- out.writeAsStringSync('dart_library.start("$ENTRY", "$libraryName");\n',
- mode: FileMode.append);
- });
-}
-
-final inputSet = Set<String>();
-final dependenceMap = Map<String, Set<String>>();
-final transitiveDependenceMap = Map<String, Set<String>>();
-final fileMap = Map<String, Set<String>>();
-
-final readyMap = Map<String, Future>();
-final linearizerMap = Map<String, Future>();
-final completerMap = Map<String, Completer>();
-
-final orderedModules = List<String>();
-final visitedModules = Set<String>();
-
-void orderModules(
- [String module = ENTRY, List<String> stack, Set<String> visited]) {
- if (stack == null) {
- assert(visited == null);
- stack = List<String>();
- visited = Set<String>();
- }
- if (visited.contains(module)) return;
- visited.add(module);
- if (stack.contains(module)) {
- print(stack);
- throw 'Circular dependence on $module';
- }
- stack.add(module);
- var dependences = dependenceMap[module];
- if (dependences != null) {
- for (var dependence in dependences) {
- orderModules(dependence, stack, visited);
- }
- }
- orderedModules.add(module);
- assert(module == stack.last);
- stack.removeLast();
-}
-
-void computeTransitiveDependences() {
- for (var module in orderedModules) {
- var transitiveSet = Set<String>();
- if (dependenceMap.containsKey(module)) {
- transitiveSet.addAll(dependenceMap[module]);
- for (var dependence in dependenceMap[module]) {
- transitiveSet.addAll(transitiveDependenceMap[dependence]);
- }
- }
- transitiveDependenceMap[module] = transitiveSet;
- }
-}
-
-String getModule(String uri) {
- var sourceUri = Uri.parse(uri);
- if (sourceUri.scheme == 'dart') {
- return 'dart';
- } else if (sourceUri.scheme == 'package') {
- return path.split(sourceUri.path)[0];
- } else {
- return ENTRY;
- }
-}
-
-bool processFile(String file) {
- inputSet.add(file);
-
- var module = getModule(file);
- fileMap.putIfAbsent(module, () => Set<String>());
- return fileMap[module].add(file);
-}
-
-void processDependence(String from, String to) {
- var fromModule = getModule(from);
- var toModule = getModule(to);
- if (fromModule == toModule || toModule == 'dart') return;
- dependenceMap.putIfAbsent(fromModule, () => Set<String>());
- dependenceMap[fromModule].add(toModule);
-}
-
-String canonicalize(String uri, String root) {
- var sourceUri = Uri.parse(uri);
- if (sourceUri.scheme == '') {
- sourceUri = path.toUri(
- path.isAbsolute(uri) ? path.absolute(uri) : path.join(root, uri));
- return sourceUri.path;
- }
- return sourceUri.toString();
-}
-
-/// Simplified from ParseDartTask.resolveDirective.
-String _resolveDirective(UriBasedDirectiveImpl directive) {
- StringLiteral uriLiteral = directive.uri;
- String uriContent = uriLiteral.stringValue;
- if (uriContent != null) {
- uriContent = uriContent.trim();
- directive.uriContent = uriContent;
- }
- return directive.validate() == null ? uriContent : null;
-}
-
-String _loadFile(String uri, String packageRoot) {
- if (uri.startsWith('package:')) {
- uri = path.join(packageRoot, uri.substring(8));
- }
- return File(uri).readAsStringSync();
-}
-
-void transitiveFiles(String entryPoint, String root, String packageRoot) {
- entryPoint = canonicalize(entryPoint, root);
- if (entryPoint.startsWith('dart:')) return;
- if (processFile(entryPoint)) {
- // Process this
- var source = _loadFile(entryPoint, packageRoot);
- var entryDir = path.dirname(entryPoint);
- var unit = parseDirectives(source, name: entryPoint, suppressErrors: true);
- for (var d in unit.directives) {
- if (d is NamespaceDirectiveImpl) {
- var uri = _resolveDirective(d);
- processDependence(entryPoint, canonicalize(uri, entryDir));
- transitiveFiles(uri, entryDir, packageRoot);
- } else if (d is PartDirectiveImpl) {
- var uri = _resolveDirective(d);
- processFile(canonicalize(uri, entryDir));
- }
- }
- }
-}
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
index f9dd584..d0bbcd8 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/collection_patch.dart
@@ -303,8 +303,9 @@
}
}
-class ImmutableSet<E> extends _HashSet<E> {
- ImmutableSet.from(JSArray entries) {
+// Used for DDC const sets.
+class _ImmutableSet<E> extends _HashSet<E> {
+ _ImmutableSet.from(JSArray entries) {
var map = _map;
for (Object key in entries) {
if (key == null) {
@@ -323,7 +324,7 @@
bool remove(Object key) => throw _unsupported();
static Error _unsupported() =>
- UnsupportedError("Cannot modify unmodifiable map");
+ UnsupportedError("Cannot modify unmodifiable set");
}
class _IdentityHashSet<E> extends _InternalSet<E>
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index a8103b3..1c742e1 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -645,6 +645,7 @@
final List _arguments;
final Map<Symbol, dynamic> _namedArguments;
final List _existingArgumentNames;
+ final Invocation _invocation;
@patch
NoSuchMethodError(Object receiver, Symbol memberName,
@@ -654,7 +655,8 @@
_memberName = memberName,
_arguments = positionalArguments,
_namedArguments = namedArguments,
- _existingArgumentNames = existingArgumentNames;
+ _existingArgumentNames = existingArgumentNames,
+ _invocation = null;
@patch
NoSuchMethodError.withInvocation(Object receiver, Invocation invocation)
@@ -662,7 +664,8 @@
_memberName = invocation.memberName,
_arguments = invocation.positionalArguments,
_namedArguments = invocation.namedArguments,
- _existingArgumentNames = null;
+ _existingArgumentNames = null,
+ _invocation = invocation;
@patch
String toString() {
@@ -687,8 +690,12 @@
String memberName = _symbolToString(_memberName);
String receiverText = Error.safeToString(_receiver);
String actualParameters = '$sb';
+ var failureMessage = (_invocation is dart.InvocationImpl)
+ ? (_invocation as dart.InvocationImpl).failureMessage
+ : 'method not found';
if (_existingArgumentNames == null) {
- return "NoSuchMethodError: method not found: '$memberName'\n"
+ return "NoSuchMethodError: '$memberName'\n"
+ "$failureMessage\n"
"Receiver: ${receiverText}\n"
"Arguments: [$actualParameters]";
} else {
@@ -2316,6 +2323,7 @@
_rsh(uDigits, maxUsed, 1, uDigits);
if (ac) {
if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+ // a += y
if (aIsNegative) {
if ((aDigits[maxUsed] != 0) ||
(_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -2327,6 +2335,7 @@
} else {
_absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
}
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2339,6 +2348,7 @@
}
_rsh(aDigits, abcdUsed, 1, aDigits);
} else if ((bDigits[0] & 1) == 1) {
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2355,6 +2365,7 @@
_rsh(vDigits, maxUsed, 1, vDigits);
if (ac) {
if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+ // c += y
if (cIsNegative) {
if ((cDigits[maxUsed] != 0) ||
(_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2366,6 +2377,7 @@
} else {
_absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
}
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2378,6 +2390,7 @@
}
_rsh(cDigits, abcdUsed, 1, cDigits);
} else if ((dDigits[0] & 1) == 1) {
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2391,8 +2404,10 @@
_rsh(dDigits, abcdUsed, 1, dDigits);
}
if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+ // u -= v
_absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
if (ac) {
+ // a -= c
if (aIsNegative == cIsNegative) {
var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
if (a_cmp_c > 0) {
@@ -2405,6 +2420,7 @@
_absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
}
}
+ // b -= d
if (bIsNegative == dIsNegative) {
var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
if (b_cmp_d > 0) {
@@ -2417,8 +2433,10 @@
_absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
}
} else {
+ // v -= u
_absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
if (ac) {
+ // c -= a
if (cIsNegative == aIsNegative) {
var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
if (c_cmp_a > 0) {
@@ -2431,6 +2449,7 @@
_absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
}
}
+ // d -= b
if (dIsNegative == bIsNegative) {
var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
if (d_cmp_b > 0) {
@@ -2462,25 +2481,18 @@
}
if (dIsNegative) {
- if ((dDigits[maxUsed] != 0) ||
+ while ((dDigits[maxUsed] != 0) ||
(_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x, d still negative
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
- }
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
}
- } else if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x
+ _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+ dIsNegative = false;
+ } else {
+ while ((dDigits[maxUsed] != 0) ||
+ (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+ // d -= x
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
}
}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
index 02b8aca..704b856 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
@@ -188,6 +188,7 @@
final _staticGetterSig = JS('', 'Symbol("sigStaticGetter")');
final _staticSetterSig = JS('', 'Symbol("sigStaticSetter")');
final _genericTypeCtor = JS('', 'Symbol("genericType")');
+final _libraryUri = JS('', 'Symbol("libraryUri")');
getConstructors(value) => _getMembers(value, _constructorSig);
getMethods(value) => _getMembers(value, _methodSig);
@@ -205,6 +206,9 @@
getType(obj) =>
JS('', '# == null ? # : #.__proto__.constructor', obj, Object, obj);
+getLibraryUri(value) => JS('', '#[#]', value, _libraryUri);
+setLibraryUri(f, uri) => JS('', '#[#] = #', f, _libraryUri, uri);
+
bool isJsInterop(obj) {
if (obj == null) return false;
if (JS('!', 'typeof # === "function"', obj)) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
index 8c8e929..d4cec70 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/errors.dart
@@ -33,9 +33,13 @@
throw UnimplementedError(message);
}
-assertFailed(message) {
+// TODO(nshahan) Cleanup embeded strings and extract file location at runtime
+// from the stacktrace.
+assertFailed(String message,
+ [String fileUri, int line, int column, String conditionSource]) {
if (JS('!', 'dart.__trapRuntimeErrors')) JS('', 'debugger');
- throw AssertionErrorImpl(message);
+
+ throw AssertionErrorImpl(message, fileUri, line, column, conditionSource);
}
throwCyclicInitializationError([Object field]) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
index 7ab4a81..0c287ae 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/operations.dart
@@ -15,13 +15,15 @@
final bool isMethod;
final bool isGetter;
final bool isSetter;
+ final String failureMessage;
InvocationImpl(memberName, List<Object> positionalArguments,
{namedArguments,
List typeArguments,
this.isMethod = false,
this.isGetter = false,
- this.isSetter = false})
+ this.isSetter = false,
+ this.failureMessage = 'method not found'})
: memberName =
isSetter ? _setterSymbol(memberName) : _dartSymbol(memberName),
positionalArguments = List.unmodifiable(positionalArguments),
@@ -156,19 +158,27 @@
return value;
}
-/// Check that a function of a given type can be applied to
-/// actuals.
-bool _checkApply(FunctionType type, List actuals, namedActuals) {
+/// Returns an error message if function of a given [type] can't be applied to
+/// [actuals] and [namedActuals].
+///
+/// Returns `null` if all checks pass.
+String _argumentErrors(FunctionType type, List actuals, namedActuals) {
// Check for too few required arguments.
int actualsCount = JS('!', '#.length', actuals);
var required = type.args;
int requiredCount = JS('!', '#.length', required);
- if (actualsCount < requiredCount) return false;
+ if (actualsCount < requiredCount) {
+ return 'Dynamic call with too few arguments. '
+ 'Expected: $requiredCount Actual: $actualsCount';
+ }
// Check for too many postional arguments.
var extras = actualsCount - requiredCount;
var optionals = type.optionals;
- if (extras > JS<int>('!', '#.length', optionals)) return false;
+ if (extras > JS<int>('!', '#.length', optionals)) {
+ return 'Dynamic call with too many arguments. '
+ 'Expected: $requiredCount Actual: $actualsCount';
+ }
// Check if we have invalid named arguments.
Iterable names;
@@ -176,7 +186,9 @@
if (namedActuals != null) {
names = getOwnPropertyNames(namedActuals);
for (var name in names) {
- if (!JS('!', '#.hasOwnProperty(#)', named, name)) return false;
+ if (!JS('!', '#.hasOwnProperty(#)', named, name)) {
+ return "Dynamic call with unexpected named argument '$name'.";
+ }
}
}
// Now that we know the signature matches, we can perform type checks.
@@ -191,7 +203,7 @@
JS('', '#[#]._check(#[#])', named, name, namedActuals, name);
}
}
- return true;
+ return null;
}
_toSymbolName(symbol) => JS('', '''(() => {
@@ -242,14 +254,16 @@
let originalTarget = obj === void 0 ? f : obj;
- function callNSM() {
+ function callNSM(errorMessage) {
return $noSuchMethod(originalTarget, new $InvocationImpl.new(
$displayName, $args, {
namedArguments: $named,
typeArguments: $typeArgs,
- isMethod: true
+ isMethod: true,
+ failureMessage: errorMessage
}));
}
+ if ($f == null) return callNSM('Dynamic call of null.');
if (!($f instanceof Function)) {
// We're not a function (and hence not a method either)
// Grab the `call` method if it's not a function.
@@ -261,7 +275,8 @@
$f = ${bindCall(f, _canonicalMember(f, 'call'))};
$ftype = null;
}
- if ($f == null) return callNSM();
+ if ($f == null) return callNSM(
+ "Dynamic call of object has no instance method 'call'.");
}
// If f is a function, but not a method (no method type)
// then it should have been a function valued field, so
@@ -291,21 +306,23 @@
if ($typeArgs == null) {
$typeArgs = $ftype.instantiateDefaultBounds();
} else if ($typeArgs.length != formalCount) {
- return callNSM();
+ return callNSM('Dynamic call with incorrect number of type arguments. ' +
+ 'Expected: ' + formalCount + ' Actual: ' + $typeArgs.length);
} else {
$ftype.checkBounds($typeArgs);
}
$ftype = $ftype.instantiate($typeArgs);
} else if ($typeArgs != null) {
- return callNSM();
+ return callNSM('Dynamic call with unexpected type arguments. ' +
+ 'Expected: 0 Actual: ' + $typeArgs.length);
}
-
- if ($_checkApply($ftype, $args, $named)) {
+ let errorMessage = $_argumentErrors($ftype, $args, $named);
+ if (errorMessage == null) {
if ($typeArgs != null) $args = $typeArgs.concat($args);
if ($named != null) $args.push($named);
return $f.apply($obj, $args);
}
- return callNSM();
+ return callNSM(errorMessage);
})()''');
dcall(f, args, [@undefined named]) =>
@@ -434,9 +451,8 @@
result =
_ignoreTypeFailure(t1, typeFuture) || _ignoreTypeFailure(t1, typeArg);
} else {
- result = t1 is FunctionType && t2 is FunctionType ||
- isSubtypeOf(t2, unwrapType(Iterable)) &&
- isSubtypeOf(t1, unwrapType(Iterable));
+ result = isSubtypeOf(t2, unwrapType(Iterable)) &&
+ isSubtypeOf(t1, unwrapType(Iterable));
if (result) {
_warn('Ignoring cast fail from ${typeName(t1)} to ${typeName(t2)}');
}
@@ -532,6 +548,14 @@
}
final constantSets = JS('', 'new Map()');
+var _immutableSetConstructor;
+
+// We cannot invoke private class constructors directly in Dart.
+Set<E> _createImmutableSet<E>(JSArray<E> elements) {
+ _immutableSetConstructor ??=
+ JS('', '#.#', getLibrary('dart:collection'), '_ImmutableSet\$');
+ return JS('', 'new (#(#)).from(#)', _immutableSetConstructor, E, elements);
+}
Set<E> constSet<E>(JSArray<E> elements) {
var count = elements.length;
@@ -541,7 +565,7 @@
}
var result = JS('', '#.get(#)', map, E);
if (result != null) return result;
- result = ImmutableSet<E>.from(elements);
+ result = _createImmutableSet<E>(elements);
JS('', '#.set(#, #)', map, E, result);
return result;
}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
index 5e784a4..11ea1ae 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/rtti.dart
@@ -117,6 +117,7 @@
String getModuleName(Object module) => JS('', '#[#]', module, _moduleName);
final _loadedModules = JS('', 'new Map()');
+final _loadedPartMaps = JS('', 'new Map()');
final _loadedSourceMaps = JS('', 'new Map()');
List<String> getModuleNames() {
@@ -135,26 +136,87 @@
return module;
}
+/// Return the part map for a specific module.
+getModulePartMap(String name) => JS('', '#.get(#)', _loadedPartMaps, name);
+
/// Track all libraries
-void trackLibraries(String moduleName, Object libraries, String sourceMap) {
+void trackLibraries(
+ String moduleName, Object libraries, Object parts, String sourceMap) {
+ if (parts is String) {
+ // Added for backwards compatibility.
+ // package:build_web_compilers currently invokes this without [parts]
+ // in its bootstrap code.
+ sourceMap = parts as String;
+ parts = JS('', '{}');
+ }
JS('', '#.set(#, #)', _loadedSourceMaps, moduleName, sourceMap);
JS('', '#.set(#, #)', _loadedModules, moduleName, libraries);
+ JS('', '#.set(#, #)', _loadedPartMaps, moduleName, parts);
}
List<String> _libraries;
+Map<String, Object> _libraryObjects;
+Map<String, List<String>> _parts;
+
+_computeLibraryMetadata() {
+ _libraries = [];
+ _libraryObjects = {};
+ _parts = {};
+ var modules = getModuleNames();
+ for (var name in modules) {
+ // Add libraries from each module.
+ var module = getModuleLibraries(name);
+ var libraries = getOwnPropertyNames(module).cast<String>();
+ _libraries.addAll(libraries);
+ for (var library in libraries) {
+ _libraryObjects[library] = JS('', '#.#', module, library);
+ }
+
+ // Add parts from each module.
+ var partMap = getModulePartMap(name);
+ libraries = getOwnPropertyNames(partMap).cast<String>();
+ for (var library in libraries) {
+ _parts[library] = List.from(JS('List', '#.#', partMap, library));
+ }
+ }
+}
+
+/// Returns the JS library object for a given library [uri] or
+/// undefined / null if it isn't loaded. Top-level types and
+/// methods are available on this object.
+Object getLibrary(String uri) {
+ if (_libraryObjects == null) {
+ _computeLibraryMetadata();
+ }
+ return _libraryObjects[uri];
+}
/// Returns a JSArray of library uris (e.g,
/// ['dart:core', 'dart:_internal', ..., 'package:foo/bar.dart', ... 'main.dart'])
/// loaded in this application.
List<String> getLibraries() {
if (_libraries == null) {
- _libraries = [];
- var modules = getModuleNames();
- for (var name in modules) {
- var module = getModuleLibraries(name);
- List props = getOwnPropertyNames(module);
- _libraries.addAll(props.whereType());
- }
+ _computeLibraryMetadata();
}
return _libraries;
}
+
+/// Returns a JSArray of part uris for a given [libraryUri].
+/// The part uris will be relative to the [libraryUri].
+///
+/// E.g., invoking `getParts('package:intl/intl.dart')` returns (as of this
+/// writing): ```
+/// ["src/intl/bidi_formatter.dart", "src/intl/bidi_utils.dart",
+/// "src/intl/compact_number_format.dart", "src/intl/date_format.dart",
+/// "src/intl/date_format_field.dart", "src/intl/date_format_helpers.dart",
+/// "src/intl/number_format.dart"]
+/// ```
+///
+/// If [libraryUri] doesn't map to a library or maps to a library with no
+/// parts, an empty list is returned.
+List<String> getParts(String libraryUri) {
+ if (_parts == null) {
+ _computeLibraryMetadata();
+ }
+ return _parts[libraryUri] ?? [];
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
index 95b822a..2f6750e 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/js_helper.dart
@@ -738,10 +738,28 @@
/// Error thrown by DDC when an `assert()` fails (with or without a message).
class AssertionErrorImpl extends AssertionError {
- AssertionErrorImpl(message) : super(message);
- String toString() =>
- "Assertion failed: " +
- (message != null ? Error.safeToString(message) : "is not true");
+ final String _fileUri;
+ final int _line;
+ final int _column;
+ final String _conditionSource;
+
+ AssertionErrorImpl(Object message,
+ [this._fileUri, this._line, this._column, this._conditionSource])
+ : super(message);
+
+ String toString() {
+ var failureMessage = "";
+ if (_fileUri != null &&
+ _line != null &&
+ _column != null &&
+ _conditionSource != null) {
+ failureMessage += "$_fileUri:${_line}:${_column}\n$_conditionSource\n";
+ }
+ failureMessage +=
+ message != null ? Error.safeToString(message) : "is not true";
+
+ return "Assertion failed: $failureMessage";
+ }
}
/**
diff --git a/pkg/dev_compiler/tool/patch_sdk.dart b/pkg/dev_compiler/tool/patch_sdk.dart
index d5cb090..5b9a979 100755
--- a/pkg/dev_compiler/tool/patch_sdk.dart
+++ b/pkg/dev_compiler/tool/patch_sdk.dart
@@ -271,7 +271,7 @@
void _maybePatch(Declaration node) {
if (node is FieldDeclaration) return;
- Token externalKeyword = (node as dynamic).externalKeyword;
+ var externalKeyword = (node as dynamic).externalKeyword as Token;
if (externalKeyword == null) return;
var name = _qualifiedName(node);
@@ -361,7 +361,7 @@
result = "${parent.name.name}.";
}
- SimpleIdentifier name = (node as dynamic).name;
+ var name = (node as dynamic).name as SimpleIdentifier;
if (name != null) result += name.name;
// Make sure setters and getters don't collide.
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index d0615fd..f91b17d 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -7,8 +7,11 @@
enum ExperimentalFlag {
constantUpdate2018,
controlFlowCollections,
+ extensionMethods,
+ nonNullable,
setLiterals,
spreadCollections,
+ tripleShift,
}
ExperimentalFlag parseExperimentalFlag(String flag) {
@@ -17,10 +20,16 @@
return ExperimentalFlag.constantUpdate2018;
case "control-flow-collections":
return ExperimentalFlag.controlFlowCollections;
+ case "extension-methods":
+ return ExperimentalFlag.extensionMethods;
+ case "non-nullable":
+ return ExperimentalFlag.nonNullable;
case "set-literals":
return ExperimentalFlag.setLiterals;
case "spread-collections":
return ExperimentalFlag.spreadCollections;
+ case "triple-shift":
+ return ExperimentalFlag.tripleShift;
}
return null;
}
@@ -28,6 +37,9 @@
const Map<ExperimentalFlag, bool> defaultExperimentalFlags = {
ExperimentalFlag.constantUpdate2018: false,
ExperimentalFlag.controlFlowCollections: true,
+ ExperimentalFlag.extensionMethods: false,
+ ExperimentalFlag.nonNullable: false,
ExperimentalFlag.setLiterals: true,
ExperimentalFlag.spreadCollections: true,
+ ExperimentalFlag.tripleShift: false,
};
diff --git a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 3606b3d..c9969c5 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -11,10 +11,13 @@
import 'package:kernel/target/targets.dart' show Target;
-import '../api_prototype/compiler_options.dart' show CompilerOptions;
+import '../api_prototype/compiler_options.dart'
+ show CompilerOptions, parseExperimentalFlags;
import '../api_prototype/diagnostic_message.dart' show DiagnosticMessageHandler;
+import '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
+
import '../api_prototype/file_system.dart' show FileSystem;
import '../base/processed_options.dart' show ProcessedOptions;
@@ -41,6 +44,8 @@
export 'compiler_state.dart' show InitializedCompilerState;
+import 'util.dart' show equalMaps;
+
/// Initializes the compiler for a modular build.
///
/// Re-uses cached components from [_workerInputCache], and reloads them
@@ -54,6 +59,7 @@
Map<Uri, List<int>> workerInputDigests,
Target target,
FileSystem fileSystem,
+ Iterable<String> experiments,
bool outlineOnly) async {
final List<int> sdkDigest = workerInputDigests[sdkSummary];
if (sdkDigest == null) {
@@ -66,10 +72,13 @@
Map<Uri, WorkerInputComponent> workerInputCache =
oldState?.workerInputCache ?? new Map<Uri, WorkerInputComponent>();
bool startOver = false;
+ Map<ExperimentalFlag, bool> experimentalFlags =
+ parseExperimentalFlags(experiments, (e) => throw e);
if (oldState == null ||
oldState.incrementalCompiler == null ||
- oldState.incrementalCompiler.outlineOnly != outlineOnly) {
+ oldState.incrementalCompiler.outlineOnly != outlineOnly ||
+ !equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
// No - or immediately not correct - previous state.
startOver = true;
@@ -115,7 +124,17 @@
for (var lib in sdkComponent.libraries) {
lib.isExternal = cachedSdkInput.externalLibs.contains(lib.importUri);
}
+
+ // Make sure the canonical name root knows about the sdk - otherwise we
+ // won't be able to link to it when loading more outlines.
sdkComponent.adoptChildren();
+
+ // TODO(jensj): This is - at least currently - neccessary,
+ // although it's not entirely obvious why.
+ // It likely has to do with several outlines containing the same libraries.
+ // Once that stops (and we check for it) we can probably remove this,
+ // and instead only do it when about to reuse an outline in the
+ // 'inputSummaries.add(component);' line further down.
for (WorkerInputComponent cachedInput in workerInputCache.values) {
cachedInput.component.adoptChildren();
}
@@ -148,8 +167,6 @@
for (var lib in component.libraries) {
lib.isExternal = cachedInput.externalLibs.contains(lib.importUri);
}
- component.adoptChildren();
- component.computeCanonicalNames();
inputSummaries.add(component);
}
}
@@ -184,7 +201,8 @@
List<Uri> summaryInputs,
List<Uri> linkedInputs,
Target target,
- FileSystem fileSystem) async {
+ FileSystem fileSystem,
+ Iterable<String> experiments) async {
// TODO(sigmund): use incremental compiler when it supports our use case.
// Note: it is common for the summary worker to invoke the compiler with the
// same input summary URIs, but with different contents, so we'd need to be
@@ -198,7 +216,8 @@
..linkedDependencies = linkedInputs
..target = target
..fileSystem = fileSystem
- ..environmentDefines = const {};
+ ..environmentDefines = const {}
+ ..experimentalFlags = parseExperimentalFlags(experiments, (e) => throw e);
ProcessedOptions processedOpts = new ProcessedOptions(options: options);
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 8ec174d..e6f8ac6 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -32,6 +32,8 @@
import 'compiler_state.dart' show InitializedCompilerState;
+import 'util.dart' show equalLists, equalMaps;
+
export '../api_prototype/compiler_options.dart'
show CompilerOptions, parseExperimentalFlags;
@@ -116,30 +118,13 @@
Map<ExperimentalFlag, bool> experimentalFlags,
bool verify: false,
bool enableAsserts: false}) {
- bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
- if (a == null || b == null) return a == b;
- if (a.length != b.length) return false;
- for (var flag in a.keys) {
- if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
- }
- return true;
- }
-
- bool listEqual(List<Uri> a, List<Uri> b) {
- if (a.length != b.length) return false;
- for (int i = 0; i < a.length; ++i) {
- if (a[i] != b[i]) return false;
- }
- return true;
- }
-
linkedDependencies.sort((a, b) => a.toString().compareTo(b.toString()));
if (oldState != null &&
oldState.options.packagesFileUri == packagesFileUri &&
oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
- listEqual(oldState.options.linkedDependencies, linkedDependencies) &&
- mapEqual(oldState.options.experimentalFlags, experimentalFlags)) {
+ equalLists(oldState.options.linkedDependencies, linkedDependencies) &&
+ equalMaps(oldState.options.experimentalFlags, experimentalFlags)) {
return oldState;
}
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 3230a6b..852cd60 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -29,6 +29,8 @@
import 'compiler_state.dart'
show InitializedCompilerState, WorkerInputComponent, digestsEqual;
+import 'util.dart' show equalLists, equalMaps;
+
export '../api_prototype/compiler_options.dart' show CompilerOptions;
export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
@@ -79,29 +81,13 @@
{FileSystem fileSystem,
Map<ExperimentalFlag, bool> experiments}) async {
inputSummaries.sort((a, b) => a.toString().compareTo(b.toString()));
- bool listEqual(List<Uri> a, List<Uri> b) {
- if (a.length != b.length) return false;
- for (int i = 0; i < a.length; ++i) {
- if (a[i] != b[i]) return false;
- }
- return true;
- }
-
- bool mapEqual(Map<ExperimentalFlag, bool> a, Map<ExperimentalFlag, bool> b) {
- if (a == null || b == null) return a == b;
- if (a.length != b.length) return false;
- for (var flag in a.keys) {
- if (!b.containsKey(flag) || a[flag] != b[flag]) return false;
- }
- return true;
- }
if (oldState != null &&
oldState.options.sdkSummary == sdkSummary &&
oldState.options.packagesFileUri == packagesFile &&
oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
- listEqual(oldState.options.inputSummaries, inputSummaries) &&
- mapEqual(oldState.options.experimentalFlags, experiments)) {
+ equalLists(oldState.options.inputSummaries, inputSummaries) &&
+ equalMaps(oldState.options.experimentalFlags, experiments)) {
// Reuse old state.
// These libraries are marked external when compiling. If not un-marking
diff --git a/pkg/front_end/lib/src/api_unstable/util.dart b/pkg/front_end/lib/src/api_unstable/util.dart
new file mode 100644
index 0000000..146ddd0
--- /dev/null
+++ b/pkg/front_end/lib/src/api_unstable/util.dart
@@ -0,0 +1,23 @@
+// 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.
+
+bool equalLists<T>(List<T> a, List<T> b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) return false;
+ for (int i = 0; i < a.length; ++i) {
+ if (a[i] != b[i]) return false;
+ }
+ return true;
+}
+
+bool equalMaps<K, V>(Map<K, V> a, Map<K, V> b) {
+ if (identical(a, b)) return true;
+ if (a == null || b == null) return false;
+ if (a.length != b.length) return false;
+ for (K key in a.keys) {
+ if (!b.containsKey(key) || a[key] != b[key]) return false;
+ }
+ return true;
+}
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 3746481..a3e6cbe 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -316,7 +316,6 @@
assert(defaultExperimentalFlags.containsKey(flag),
"No default value for $flag.");
// TODO(askesc): Determine default flag value from specification file.
- if (flag == ExperimentalFlag.setLiterals) return true;
return _raw.experimentalFlags[flag] ?? defaultExperimentalFlags[flag];
}
diff --git a/pkg/front_end/lib/src/fasta/builder/class_builder.dart b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
index 05441e7..0ef4745 100644
--- a/pkg/front_end/lib/src/fasta/builder/class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/class_builder.dart
@@ -77,6 +77,8 @@
return library.partOfLibrary ?? library;
}
+ void buildAnnotations(LibraryBuilder library) {}
+
/// Registers a constructor redirection for this class and returns true if
/// this redirection gives rise to a cycle that has not been reported before.
bool checkConstructorCyclic(String source, String target) {
@@ -124,7 +126,7 @@
return constructors.lookup(name, charOffset, uri);
}
- void forEach(void f(String name, MemberBuilder builder)) {
+ void forEach(void f(String name, Declaration builder)) {
scope.forEach(f);
}
diff --git a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
index f456149..33f875f 100644
--- a/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/enum_builder.dart
@@ -12,7 +12,7 @@
}
class EnumConstantInfo {
- final List<MetadataBuilder<TypeBuilder>> metadata;
+ final List<MetadataBuilder> metadata;
final String name;
final int charOffset;
final String documentationComment;
diff --git a/pkg/front_end/lib/src/fasta/builder/library_builder.dart b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
index 9dbca65..ed544d6 100644
--- a/pkg/front_end/lib/src/fasta/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/library_builder.dart
@@ -235,6 +235,8 @@
}
void recordAccess(int charOffset, int length, Uri fileUri) {}
+
+ void buildAnnotations() {}
}
class LibraryLocalDeclarationIterator implements Iterator<Declaration> {
diff --git a/pkg/front_end/lib/src/fasta/builder/member_builder.dart b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
index 827fe5f..2dd5099 100644
--- a/pkg/front_end/lib/src/fasta/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/member_builder.dart
@@ -37,6 +37,8 @@
}
}
+ void buildAnnotations(LibraryBuilder library) {}
+
@override
String get fullNameForErrors => name;
}
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index cb656b4..f43b4a6 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -4,54 +4,6 @@
library fasta.metadata_builder;
-import 'builder.dart' show Declaration, TypeBuilder;
-
-import 'constructor_reference_builder.dart' show ConstructorReferenceBuilder;
-
-abstract class MetadataBuilder<T extends TypeBuilder> {
- final int charOffset;
-
- MetadataBuilder(Declaration parent, this.charOffset);
-
- factory MetadataBuilder.fromConstructor(
- ConstructorReferenceBuilder constructorReference,
- List<Object> arguments,
- Declaration parent,
- int charOffset) {
- return new ConstructorMetadataBuilder<T>(
- constructorReference, arguments, parent, charOffset);
- }
-
- factory MetadataBuilder.fromExpression(
- Object expression, String postfix, Declaration parent, int charOffset) {
- return new ExpressionMetadataBuilder<T>(
- expression, postfix, parent, charOffset);
- }
-}
-
-class ConstructorMetadataBuilder<T extends TypeBuilder>
- extends MetadataBuilder<T> {
- final ConstructorReferenceBuilder constructorReference;
-
- final List<Object> arguments;
-
- ConstructorMetadataBuilder(this.constructorReference, this.arguments,
- Declaration parent, int charOffset)
- : super(parent, charOffset);
-}
-
-/// Expression metadata (without arguments).
-///
-/// Matches this grammar rule:
-///
-/// '@' qualified (‘.’ identifier)?
-class ExpressionMetadataBuilder<T extends TypeBuilder>
- extends MetadataBuilder<T> {
- final Object qualified;
-
- final String identifier;
-
- ExpressionMetadataBuilder(
- this.qualified, this.identifier, Declaration parent, int charOffset)
- : super(parent, charOffset);
+abstract class MetadataBuilder {
+ int get charOffset;
}
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
index e941212..c2e5255 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -19,7 +19,7 @@
final List<TypeVariableBuilder<T, R>> typeVariables;
TypeAliasBuilder(
- List<MetadataBuilder<T>> metadata,
+ List<MetadataBuilder> metadata,
String name,
this.typeVariables,
this.type,
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index b28cf9f..32a5a31 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -14,7 +14,7 @@
abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
extends ModifierBuilder {
- final List<MetadataBuilder<T>> metadata;
+ final List<MetadataBuilder> metadata;
final int modifiers;
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index 6667e06..8247cbf 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -23,7 +23,7 @@
: super(null, typedef.name, null, null, parent, typedef.fileOffset,
typedef);
- List<MetadataBuilder<KernelTypeBuilder>> get metadata {
+ List<MetadataBuilder> get metadata {
return unimplemented("metadata", -1, null);
}
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 991c13b..e61cf1c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -233,16 +233,6 @@
message: r"""`assert` can't have more than two arguments.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeAsyncAsIdentifier = messageAsyncAsIdentifier;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageAsyncAsIdentifier = const MessageCode(
- "AsyncAsIdentifier",
- analyzerCodes: <String>["ASYNC_KEYWORD_USED_AS_IDENTIFIER"],
- message:
- r"""'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeAwaitAsIdentifier = messageAwaitAsIdentifier;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -273,6 +263,34 @@
message: r"""'await' can only be used in 'async' or 'async*' methods.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<Message Function(String name, String name2)>
+ templateBadTypeVariableInSupertype =
+ const Template<Message Function(String name, String name2)>(
+ messageTemplate:
+ r"""Found unsupported uses of '#name' in supertype '#name2'.""",
+ withArguments: _withArgumentsBadTypeVariableInSupertype);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name, String name2)>
+ codeBadTypeVariableInSupertype =
+ const Code<Message Function(String name, String name2)>(
+ "BadTypeVariableInSupertype",
+ templateBadTypeVariableInSupertype,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsBadTypeVariableInSupertype(String name, String name2) {
+ if (name.isEmpty) throw 'No name provided';
+ name = demangleMixinApplicationName(name);
+ if (name2.isEmpty) throw 'No name provided';
+ name2 = demangleMixinApplicationName(name2);
+ return new Message(codeBadTypeVariableInSupertype,
+ message:
+ """Found unsupported uses of '${name}' in supertype '${name2}'.""",
+ arguments: {'name': name, 'name2': name2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<
Message Function(
String name,
@@ -1925,17 +1943,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeCovariantAfterVar = messageCovariantAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageCovariantAfterVar = const MessageCode(
- "CovariantAfterVar",
- index: 8,
- message:
- r"""The modifier 'covariant' should be before the modifier 'var'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeCovariantAndStatic = messageCovariantAndStatic;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2924,27 +2931,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassBodyToSkip =
- const Template<Message Function(Token token)>(
- messageTemplate:
- r"""Expected a class or mixin body, but got '#lexeme'.""",
- withArguments: _withArgumentsExpectedClassBodyToSkip);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassBodyToSkip =
- const Code<Message Function(Token token)>(
- "ExpectedClassBodyToSkip", templateExpectedClassBodyToSkip,
- analyzerCodes: <String>["MISSING_CLASS_BODY"]);
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassBodyToSkip(Token token) {
- String lexeme = token.lexeme;
- return new Message(codeExpectedClassBodyToSkip,
- message: """Expected a class or mixin body, but got '${lexeme}'.""",
- arguments: {'token': token});
-}
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(Token token)> templateExpectedClassMember =
const Template<Message Function(Token token)>(
messageTemplate: r"""Expected a class member, but got '#lexeme'.""",
@@ -2965,24 +2951,27 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(Token token)> templateExpectedClassOrMixinBody =
- const Template<Message Function(Token token)>(
+const Template<Message Function(String string)>
+ templateExpectedClassOrMixinBody =
+ const Template<Message Function(String string)>(
messageTemplate:
- r"""Expected a class or mixin body, but got '#lexeme'.""",
+ r"""A #string must have a body, even if it is empty.""",
+ tipTemplate: r"""Try adding an empty body.""",
withArguments: _withArgumentsExpectedClassOrMixinBody);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(Token token)> codeExpectedClassOrMixinBody =
- const Code<Message Function(Token token)>(
+const Code<Message Function(String string)> codeExpectedClassOrMixinBody =
+ const Code<Message Function(String string)>(
"ExpectedClassOrMixinBody", templateExpectedClassOrMixinBody,
- analyzerCodes: <String>["MISSING_CLASS_BODY"]);
+ index: 8);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsExpectedClassOrMixinBody(Token token) {
- String lexeme = token.lexeme;
+Message _withArgumentsExpectedClassOrMixinBody(String string) {
+ if (string.isEmpty) throw 'No string provided';
return new Message(codeExpectedClassOrMixinBody,
- message: """Expected a class or mixin body, but got '${lexeme}'.""",
- arguments: {'token': token});
+ message: """A ${string} must have a body, even if it is empty.""",
+ tip: """Try adding an empty body.""",
+ arguments: {'string': string});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3011,7 +3000,7 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageExpectedElseOrComma = const MessageCode(
"ExpectedElseOrComma",
- index: 94,
+ index: 46,
message: r"""Expected 'else' or comma.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3224,7 +3213,7 @@
const Code<Message Function(String string)> codeExperimentNotEnabled =
const Code<Message Function(String string)>(
"ExperimentNotEnabled", templateExperimentNotEnabled,
- index: 93);
+ index: 48);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsExperimentNotEnabled(String string) {
@@ -3327,39 +3316,6 @@
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterConst = messageExternalAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterConst = const MessageCode(
- "ExternalAfterConst",
- index: 46,
- message:
- r"""The modifier 'external' should be before the modifier 'const'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterFactory = messageExternalAfterFactory;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterFactory = const MessageCode(
- "ExternalAfterFactory",
- index: 47,
- message:
- r"""The modifier 'external' should be before the modifier 'factory'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeExternalAfterStatic = messageExternalAfterStatic;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageExternalAfterStatic = const MessageCode(
- "ExternalAfterStatic",
- index: 48,
- message:
- r"""The modifier 'external' should be before the modifier 'static'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeExternalClass = messageExternalClass;
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -6315,7 +6271,7 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageInvalidSuperInInitializer = const MessageCode(
"InvalidSuperInInitializer",
- index: 95,
+ index: 47,
message:
r"""Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')""");
@@ -7388,7 +7344,7 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageOnlyTry = const MessageCode("OnlyTry",
- index: 92,
+ index: 20,
message:
r"""A try block must be followed by an 'on', 'catch', or 'finally' clause.""",
tip:
@@ -8739,42 +8695,11 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageStackOverflow = const MessageCode("StackOverflow",
- index: 91,
+ index: 19,
message: r"""The file has too many nested expressions or statements.""",
tip: r"""Try simplifying the code.""");
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterConst = messageStaticAfterConst;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterConst = const MessageCode(
- "StaticAfterConst",
- index: 20,
- message:
- r"""The modifier 'static' should be before the modifier 'const'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterFinal = messageStaticAfterFinal;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterFinal = const MessageCode(
- "StaticAfterFinal",
- index: 19,
- message:
- r"""The modifier 'static' should be before the modifier 'final'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeStaticAfterVar = messageStaticAfterVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageStaticAfterVar = const MessageCode("StaticAfterVar",
- index: 18,
- message: r"""The modifier 'static' should be before the modifier 'var'.""",
- tip: r"""Try re-ordering the modifiers.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeStaticAndInstanceConflict =
messageStaticAndInstanceConflict;
@@ -8847,7 +8772,7 @@
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const MessageCode messageSuperNullAware = const MessageCode("SuperNullAware",
- index: 90,
+ index: 18,
message:
r"""The operator '?.' cannot be used with 'super' because 'super' cannot be null.""",
tip: r"""Try replacing '?.' with '.'""");
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 52264f2..16d1187 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -96,6 +96,8 @@
final Component componentToInitializeFrom;
bool initializedFromDill = false;
Uri previousPackagesUri;
+ Map<String, Uri> previousPackagesMap;
+ Map<String, Uri> currentPackagesMap;
bool hasToCheckPackageUris = false;
Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
new Map<Uri, List<DiagnosticMessageFromJson>>();
@@ -137,6 +139,8 @@
hasToCheckPackageUris = hasToCheckPackageUris || bypassCache;
UriTranslator uriTranslator =
await c.options.getUriTranslator(bypassCache: bypassCache);
+ previousPackagesMap = currentPackagesMap;
+ currentPackagesMap = uriTranslator.packages.asMap();
ticker.logMs("Read packages file");
if (dillLoadedData == null) {
@@ -220,11 +224,19 @@
notReused: notReusedLibraries);
Set<Uri> reusedLibraryUris =
new Set<Uri>.from(reusedLibraries.map((b) => b.uri));
+ bool removedBuilders = false;
for (Uri uri in new Set<Uri>.from(dillLoadedData.loader.builders.keys)
..removeAll(reusedLibraryUris)) {
LibraryBuilder builder = dillLoadedData.loader.builders.remove(uri);
userBuilders?.remove(uri);
CompilerContext.current.uriToSource.remove(builder.fileUri);
+ removedBuilders = true;
+ }
+ if (removedBuilders) {
+ dillLoadedData.loader.libraries.clear();
+ for (LibraryBuilder builder in dillLoadedData.loader.builders.values) {
+ dillLoadedData.loader.libraries.add(builder.target);
+ }
}
if (hasToCheckPackageUris) {
@@ -823,10 +835,21 @@
if (importUri != fileUri && invalidatedUris.contains(fileUri)) {
return true;
}
- if (hasToCheckPackageUris &&
- importUri.scheme == "package" &&
- uriTranslator.translate(importUri, false) != fileUri) {
- return true;
+ if (hasToCheckPackageUris && importUri.scheme == "package") {
+ // Get package name, check if the base URI has changed for the package,
+ // if it has, translate the URI again,
+ // otherwise the URI cannot have changed.
+ String path = importUri.path;
+ int firstSlash = path.indexOf('/');
+ String packageName = path.substring(0, firstSlash);
+ if (previousPackagesMap == null ||
+ (previousPackagesMap[packageName] !=
+ currentPackagesMap[packageName])) {
+ Uri newFileUri = uriTranslator.translate(importUri, false);
+ if (newFileUri != fileUri) {
+ return true;
+ }
+ }
}
if (builders[importUri]?.isSynthetic ?? false) return true;
return false;
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 46f4f5e..393be7d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -509,7 +509,8 @@
}
ConstantContext savedConstantContext = pop();
- if (expression is! StaticAccessGenerator) {
+ if (expression is! StaticAccessGenerator &&
+ expression is! VariableUseGenerator) {
push(wrapInProblem(
toValue(expression), fasta.messageExpressionNotMetadata, noLength));
} else {
@@ -600,25 +601,7 @@
// `invalid-type`.
buildDartType(pop()); // Type.
}
- List<Expression> annotations = pop();
- // Fields with duplicate names are sorted out in the else branch of the
- // `declaration.next == null` above.
- if (annotations != null && fields.isNotEmpty) {
- inferAnnotations(annotations);
- Field field = fields.first.target;
- // The first (and often only field) will not get a clone.
- for (int i = 0; i < annotations.length; i++) {
- field.addAnnotation(annotations[i]);
- }
- for (int i = 1; i < fields.length; i++) {
- // We have to clone the annotations on the remaining fields.
- field = fields[i].target;
- cloner ??= new CloneVisitor();
- for (Expression annotation in annotations) {
- field.addAnnotation(cloner.clone(annotation));
- }
- }
- }
+ pop(); // Annotations.
resolveRedirectingFactoryTargets();
finishVariableMetadata();
@@ -750,8 +733,8 @@
}
@override
- void finishFunction(List<Expression> annotations, FormalParameters formals,
- AsyncMarker asyncModifier, Statement body) {
+ void finishFunction(
+ FormalParameters formals, AsyncMarker asyncModifier, Statement body) {
debugEvent("finishFunction");
typePromoter?.finished();
@@ -902,11 +885,6 @@
..fileOffset = body.fileOffset;
}
}
- Member target = builder.target;
- inferAnnotations(annotations);
- for (Expression annotation in annotations ?? const []) {
- target.addAnnotation(annotation);
- }
if (builder is KernelConstructorBuilder) {
finishConstructor(builder, asyncModifier);
} else if (builder is KernelProcedureBuilder) {
@@ -1154,6 +1132,14 @@
return expression;
}
+ Expression parseAnnotation(Token token) {
+ Parser parser = new Parser(this);
+ token = parser.parseMetadata(parser.syntheticPreviousToken(token));
+ Expression annotation = pop();
+ checkEmpty(token.charOffset);
+ return annotation;
+ }
+
void finishConstructor(
KernelConstructorBuilder builder, AsyncMarker asyncModifier) {
/// Quotes below are from [Dart Programming Language Specification, 4th
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 51d5070..b015270 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -135,6 +135,7 @@
}
class ConstantsTransformer extends Transformer {
+ final ConstantsBackend backend;
final ConstantEvaluator constantEvaluator;
final TypeEnvironment typeEnvironment;
@@ -146,7 +147,7 @@
final bool errorOnUnevaluatedConstant;
ConstantsTransformer(
- ConstantsBackend backend,
+ this.backend,
Map<String, String> environmentDefines,
this.keepFields,
this.keepVariables,
@@ -300,18 +301,11 @@
if (node.isConst) {
final Constant constant = evaluateWithContext(node, node.initializer);
constantEvaluator.env.addVariableValue(node, constant);
+ node.initializer = makeConstantExpression(constant, node.initializer)
+ ..parent = node;
- if (keepVariables) {
- // So the value of the variable is still available for debugging
- // purposes we convert the constant variable to be a final variable
- // initialized to the evaluated constant expression.
- node.initializer = makeConstantExpression(constant, node.initializer)
- ..parent = node;
- node.isFinal = true;
- node.isConst = false;
- } else {
- // Since we convert all use-sites of constants, the constant
- // [VariableDeclaration] is unused and we'll therefore remove it.
+ // If this constant is inlined, remove it.
+ if (!keepVariables && shouldInline(node.initializer)) {
return null;
}
} else {
@@ -324,20 +318,17 @@
visitField(Field node) {
return constantEvaluator.withNewEnvironment(() {
if (node.isConst) {
- // Since we convert all use-sites of constants, the constant [Field]
- // cannot be referenced anymore. We therefore get rid of it if
- // [keepFields] was not specified.
- if (!keepFields) {
- return null;
- }
-
- // Otherwise we keep the constant [Field] and convert it's initializer.
transformAnnotations(node.annotations, node);
if (node.initializer != null) {
node.initializer =
evaluateAndTransformWithContext(node, node.initializer)
..parent = node;
}
+
+ // If this constant is inlined, remove it.
+ if (!keepFields && shouldInline(node.initializer)) {
+ return null;
+ }
} else {
transformAnnotations(node.annotations, node);
if (node.initializer != null) {
@@ -357,7 +348,15 @@
visitStaticGet(StaticGet node) {
final Member target = node.target;
if (target is Field && target.isConst) {
- return evaluateAndTransformWithContext(node, node);
+ if (target.initializer != null) {
+ // Make sure the initializer is evaluated first.
+ target.initializer =
+ evaluateAndTransformWithContext(target, target.initializer)
+ ..parent = target;
+ if (shouldInline(target.initializer)) {
+ return evaluateAndTransformWithContext(node, node);
+ }
+ }
} else if (target is Procedure && target.kind == ProcedureKind.Method) {
return evaluateAndTransformWithContext(node, node);
}
@@ -370,8 +369,14 @@
}
visitVariableGet(VariableGet node) {
- if (node.variable.isConst) {
- return evaluateAndTransformWithContext(node, node);
+ final VariableDeclaration variable = node.variable;
+ if (variable.isConst) {
+ variable.initializer =
+ evaluateAndTransformWithContext(variable, variable.initializer)
+ ..parent = variable;
+ if (shouldInline(variable.initializer)) {
+ return evaluateAndTransformWithContext(node, node);
+ }
}
return super.visitVariableGet(node);
}
@@ -456,6 +461,13 @@
return new ConstantExpression(constant, node.getStaticType(typeEnvironment))
..fileOffset = node.fileOffset;
}
+
+ bool shouldInline(Expression initializer) {
+ if (initializer is ConstantExpression) {
+ return backend.shouldInlineConstant(initializer);
+ }
+ return true;
+ }
}
class ConstantEvaluator extends RecursiveVisitor<Constant> {
@@ -1591,6 +1603,7 @@
} else {
reportInvalid(
node, 'No support for ${target.runtimeType} in a static-get.');
+ return null;
}
});
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
index 1886808..c37724b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_body_builder.dart
@@ -42,6 +42,27 @@
: forest = const Fangorn(),
super.forField(member, typeInferrer);
+ KernelBodyBuilder.forAnnotation(
+ KernelLibraryBuilder library,
+ KernelClassBuilder classBuilder,
+ ModifierBuilder member,
+ Scope scope,
+ Scope parameterScope,
+ Uri fileUri)
+ : forest = const Fangorn(),
+ super(
+ library,
+ member,
+ scope,
+ parameterScope,
+ library.loader.hierarchy,
+ library.loader.coreTypes,
+ classBuilder,
+ member?.isInstanceMember ?? false,
+ fileUri,
+ library.loader.typeInferenceEngine
+ ?.createLocalTypeInferrer(fileUri, null, library));
+
@override
void enterThenForTypePromotion(Expression condition) {
typePromoter?.enterThen(condition);
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index afd74e5..0206595 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -34,6 +34,8 @@
export 'kernel_library_builder.dart' show KernelLibraryBuilder;
+export 'kernel_metadata_builder.dart' show KernelMetadataBuilder;
+
export 'kernel_mixin_application_builder.dart'
show KernelMixinApplicationBuilder;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
index 6ad083c..31214d6 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_class_builder.dart
@@ -105,6 +105,7 @@
Declaration,
KernelFunctionBuilder,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelNamedTypeBuilder,
KernelProcedureBuilder,
KernelRedirectingFactoryBuilder,
@@ -224,6 +225,19 @@
}
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ void build(String ignore, Declaration declaration) {
+ MemberBuilder member = declaration;
+ member.buildAnnotations(library);
+ }
+
+ KernelMetadataBuilder.buildAnnotations(
+ isPatch ? origin.target : cls, metadata, library, this, null, null);
+ constructors.forEach(build);
+ scope.forEach(build);
+ }
+
void checkSupertypes(CoreTypes coreTypes) {
// This method determines whether the class (that's being built) its super
// class appears both in 'extends' and 'implements' clauses and whether any
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 904f47d..39c70c9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -23,7 +23,9 @@
FieldBuilder,
ImplicitFieldType,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelTypeBuilder,
+ LibraryBuilder,
MetadataBuilder;
import 'kernel_shadow_ast.dart' show ShadowField;
@@ -91,6 +93,13 @@
return field;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ field, metadata, library, classBuilder, this, null);
+ }
+
Field get target => field;
void prepareTopLevelInference() {
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 80db2c8..983b7c7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -135,6 +135,7 @@
KernelTypeAliasBuilder,
KernelFunctionTypeBuilder,
KernelInvalidTypeBuilder,
+ KernelMetadataBuilder,
KernelMixinApplicationBuilder,
KernelNamedTypeBuilder,
KernelProcedureBuilder,
@@ -902,6 +903,12 @@
}
@override
+ void buildAnnotations() {
+ KernelMetadataBuilder.buildAnnotations(
+ library, metadata, this, null, null, null);
+ }
+
+ @override
void buildBuilder(Declaration declaration, LibraryBuilder coreLibrary) {
Class cls;
Member member;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
new file mode 100644
index 0000000..7bc39e6
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_metadata_builder.dart
@@ -0,0 +1,51 @@
+// 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.
+
+library fasta.kernel_metadata_builder;
+
+import 'package:kernel/ast.dart' show Annotatable, Class, Library;
+
+import 'kernel_body_builder.dart' show KernelBodyBuilder;
+
+import 'kernel_builder.dart'
+ show
+ KernelClassBuilder,
+ KernelLibraryBuilder,
+ MetadataBuilder,
+ MemberBuilder;
+
+import '../scanner.dart' show Token;
+
+import '../scope.dart' show Scope;
+
+class KernelMetadataBuilder extends MetadataBuilder {
+ final Token beginToken;
+
+ int get charOffset => beginToken.charOffset;
+
+ KernelMetadataBuilder(this.beginToken);
+
+ static void buildAnnotations(
+ Annotatable parent,
+ List<MetadataBuilder> metadata,
+ KernelLibraryBuilder library,
+ KernelClassBuilder classBuilder,
+ MemberBuilder member,
+ Scope parameterScope) {
+ if (metadata == null) return;
+ Uri fileUri = member?.fileUri ?? classBuilder?.fileUri ?? library.fileUri;
+ Scope scope = parent is Library || parent is Class || classBuilder == null
+ ? library.scope
+ : classBuilder.scope;
+ KernelBodyBuilder bodyBuilder = new KernelBodyBuilder.forAnnotation(
+ library, classBuilder, member, scope, parameterScope, fileUri);
+ for (int i = 0; i < metadata.length; ++i) {
+ KernelMetadataBuilder annotationBuilder = metadata[i];
+ parent.addAnnotation(
+ bodyBuilder.parseAnnotation(annotationBuilder.beginToken));
+ }
+ bodyBuilder.inferAnnotations(parent.annotations);
+ bodyBuilder.resolveRedirectingFactoryTargets();
+ }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
index 2434d09..c8d217b 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_procedure_builder.dart
@@ -65,6 +65,7 @@
FormalParameterBuilder,
KernelFormalParameterBuilder,
KernelLibraryBuilder,
+ KernelMetadataBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
@@ -361,6 +362,18 @@
return procedure;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ target,
+ metadata,
+ library,
+ classBuilder,
+ this,
+ computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+ }
+
Procedure get target => origin.procedure;
@override
@@ -483,6 +496,18 @@
return constructor;
}
+ @override
+ void buildAnnotations(LibraryBuilder library) {
+ ClassBuilder classBuilder = isClassMember ? parent : null;
+ KernelMetadataBuilder.buildAnnotations(
+ target,
+ metadata,
+ library,
+ classBuilder,
+ this,
+ computeFormalParameterScope(classBuilder?.scope ?? library.scope));
+ }
+
FunctionNode buildFunction(LibraryBuilder library) {
// According to the specification §9.3 the return type of a constructor
// function is its enclosing class.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 49d0344..83e30e9 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -279,6 +279,7 @@
loader.checkRedirectingFactories(myClasses);
loader.addNoSuchMethodForwarders(myClasses);
loader.checkMixins(myClasses);
+ loader.buildAnnotations();
installAllComponentProblems(loader.allComponentProblems);
loader.allComponentProblems.clear();
return component;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
index e9c4064..f5daa9d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
@@ -44,7 +44,7 @@
DartType thisType;
KernelTypeAliasBuilder(
- List<MetadataBuilder<KernelTypeBuilder>> metadata,
+ List<MetadataBuilder> metadata,
String name,
List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables,
KernelFunctionTypeBuilder type,
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index d05e0d8..6c04afb 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -19,6 +19,8 @@
import 'package:kernel/type_algebra.dart' show containsTypeVariable;
+import 'package:kernel/src/bounds_checks.dart' show Variance;
+
import 'package:kernel/util/graph.dart' show Graph, computeStrongComponents;
import 'kernel_builder.dart'
@@ -31,6 +33,7 @@
KernelFormalParameterBuilder,
KernelFunctionTypeBuilder,
KernelNamedTypeBuilder,
+ KernelTypeAliasBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
NamedTypeBuilder,
@@ -51,6 +54,79 @@
templateNonSimpleBoundViaReference,
templateNonSimpleBoundViaVariable;
+export 'package:kernel/src/bounds_checks.dart' show Variance;
+
+// Computes the variance of a variable in a type. The function can be run
+// before the types are resolved to compute variances of typedefs' type
+// variables. For that case if the type has its declaration set to null and its
+// name matches that of the variable, it's interpreted as an occurrence of a
+// type variable.
+int computeVariance(
+ KernelTypeVariableBuilder variable, KernelTypeBuilder type) {
+ if (type is KernelNamedTypeBuilder) {
+ TypeDeclarationBuilder declaration = type.declaration;
+ if (declaration == null || declaration is KernelTypeVariableBuilder) {
+ if (type.name == variable.name) {
+ return Variance.covariant;
+ } else {
+ return Variance.unrelated;
+ }
+ } else {
+ if (declaration is KernelClassBuilder) {
+ int result = Variance.unrelated;
+ if (type.arguments != null) {
+ for (KernelTypeBuilder argument in type.arguments) {
+ result = Variance.meet(result, computeVariance(variable, argument));
+ }
+ }
+ return result;
+ } else if (declaration is KernelTypeAliasBuilder) {
+ int result = Variance.unrelated;
+ if (type.arguments != null) {
+ for (int i = 0; i < type.arguments.length; ++i) {
+ result = Variance.meet(
+ result,
+ Variance.combine(
+ computeVariance(variable, type.arguments[i]),
+ computeVariance(
+ declaration.typeVariables[i], declaration.type)));
+ }
+ }
+ return result;
+ }
+ }
+ } else if (type is KernelFunctionTypeBuilder) {
+ int result = Variance.unrelated;
+ if (type.returnType != null) {
+ result =
+ Variance.meet(result, computeVariance(variable, type.returnType));
+ }
+ if (type.typeVariables != null) {
+ for (KernelTypeVariableBuilder typeVariable in type.typeVariables) {
+ // If [variable] is referenced in the bound at all, it makes the
+ // variance of [variable] in the entire type invariant. The invocation
+ // of [computeVariance] below is made to simply figure out if [variable]
+ // occurs in the bound.
+ if (typeVariable.bound != null &&
+ computeVariance(variable, typeVariable.bound) !=
+ Variance.unrelated) {
+ result = Variance.invariant;
+ }
+ }
+ }
+ if (type.formals != null) {
+ for (KernelFormalParameterBuilder formal in type.formals) {
+ result = Variance.meet(
+ result,
+ Variance.combine(Variance.contravariant,
+ computeVariance(variable, formal.type)));
+ }
+ }
+ return result;
+ }
+ return Variance.unrelated;
+}
+
KernelTypeBuilder substituteRange(
KernelTypeBuilder type,
Map<TypeVariableBuilder, KernelTypeBuilder> upperSubstitution,
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index bb60229..c596a7e 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -13,6 +13,11 @@
ForwardingListener([this.listener]);
@override
+ set suppressParseErrors(bool value) {
+ listener?.suppressParseErrors = value;
+ }
+
+ @override
Uri get uri => listener?.uri;
@override
@@ -61,13 +66,13 @@
}
@override
- void beginClassOrMixinBody(Token token) {
- listener?.beginClassOrMixinBody(token);
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+ listener?.beginClassDeclaration(begin, abstractToken, name);
}
@override
- void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
- listener?.beginClassDeclaration(begin, abstractToken, name);
+ void beginClassOrMixinBody(Token token) {
+ listener?.beginClassOrMixinBody(token);
}
@override
@@ -86,6 +91,11 @@
}
@override
+ void beginConditionalExpression(Token question) {
+ listener?.beginConditionalExpression(question);
+ }
+
+ @override
void beginConditionalUri(Token ifKeyword) {
listener?.beginConditionalUri(ifKeyword);
}
@@ -136,6 +146,11 @@
}
@override
+ void beginExtensionDeclaration(Token extensionKeyword, Token name) {
+ listener?.beginExtensionDeclaration(extensionKeyword, name);
+ }
+
+ @override
void beginFactoryMethod(
Token lastConsumed, Token externalToken, Token constToken) {
listener?.beginFactoryMethod(lastConsumed, externalToken, constToken);
@@ -162,16 +177,6 @@
}
@override
- void beginForStatement(Token token) {
- listener?.beginForStatement(token);
- }
-
- @override
- void beginForStatementBody(Token token) {
- listener?.beginForStatementBody(token);
- }
-
- @override
void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
Token covariantToken, Token varFinalOrConst) {
listener?.beginFormalParameter(
@@ -179,13 +184,23 @@
}
@override
+ void beginFormalParameterDefaultValueExpression() {
+ listener?.beginFormalParameterDefaultValueExpression();
+ }
+
+ @override
void beginFormalParameters(Token token, MemberKind kind) {
listener?.beginFormalParameters(token, kind);
}
@override
- void beginLocalFunctionDeclaration(Token token) {
- listener?.beginLocalFunctionDeclaration(token);
+ void beginForStatement(Token token) {
+ listener?.beginForStatement(token);
+ }
+
+ @override
+ void beginForStatementBody(Token token) {
+ listener?.beginForStatementBody(token);
}
@override
@@ -224,13 +239,13 @@
}
@override
- void beginThenControlFlow(Token token) {
- listener?.beginThenControlFlow(token);
+ void beginIfStatement(Token token) {
+ listener?.beginIfStatement(token);
}
@override
- void beginIfStatement(Token token) {
- listener?.beginIfStatement(token);
+ void beginImplicitCreationExpression(Token token) {
+ listener?.beginImplicitCreationExpression(token);
}
@override
@@ -274,6 +289,11 @@
}
@override
+ void beginLocalFunctionDeclaration(Token token) {
+ listener?.beginLocalFunctionDeclaration(token);
+ }
+
+ @override
void beginMember() {
listener?.beginMember();
}
@@ -367,6 +387,11 @@
}
@override
+ void beginThenControlFlow(Token token) {
+ listener?.beginThenControlFlow(token);
+ }
+
+ @override
void beginThenStatement(Token token) {
listener?.beginThenStatement(token);
}
@@ -485,13 +510,13 @@
}
@override
- void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
- listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
+ void endClassDeclaration(Token beginToken, Token endToken) {
+ listener?.endClassDeclaration(beginToken, endToken);
}
@override
- void endClassDeclaration(Token beginToken, Token endToken) {
- listener?.endClassDeclaration(beginToken, endToken);
+ void endClassOrMixinBody(int memberCount, Token beginToken, Token endToken) {
+ listener?.endClassOrMixinBody(memberCount, beginToken, endToken);
}
@override
@@ -505,6 +530,11 @@
}
@override
+ void endConditionalExpression(Token question, Token colon) {
+ listener?.endConditionalExpression(question, colon);
+ }
+
+ @override
void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
listener?.endConditionalUri(ifKeyword, leftParen, equalSign);
}
@@ -557,6 +587,11 @@
}
@override
+ void endExtensionDeclaration(Token onKeyword, Token token) {
+ listener?.endExtensionDeclaration(onKeyword, token);
+ }
+
+ @override
void endFactoryMethod(
Token beginToken, Token factoryKeyword, Token endToken) {
listener?.endFactoryMethod(beginToken, factoryKeyword, endToken);
@@ -580,11 +615,6 @@
}
@override
- void endForInControlFlow(Token token) {
- listener?.endForInControlFlow(token);
- }
-
- @override
void endForIn(Token endToken) {
listener?.endForIn(endToken);
}
@@ -595,21 +625,16 @@
}
@override
+ void endForInControlFlow(Token token) {
+ listener?.endForInControlFlow(token);
+ }
+
+ @override
void endForInExpression(Token token) {
listener?.endForInExpression(token);
}
@override
- void endForStatement(Token endToken) {
- listener?.endForStatement(endToken);
- }
-
- @override
- void endForStatementBody(Token token) {
- listener?.endForStatementBody(token);
- }
-
- @override
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
listener?.endFormalParameter(
@@ -617,14 +642,24 @@
}
@override
+ void endFormalParameterDefaultValueExpression() {
+ listener?.endFormalParameterDefaultValueExpression();
+ }
+
+ @override
void endFormalParameters(
int count, Token beginToken, Token endToken, MemberKind kind) {
listener?.endFormalParameters(count, beginToken, endToken, kind);
}
@override
- void endLocalFunctionDeclaration(Token endToken) {
- listener?.endLocalFunctionDeclaration(endToken);
+ void endForStatement(Token endToken) {
+ listener?.endForStatement(endToken);
+ }
+
+ @override
+ void endForStatementBody(Token token) {
+ listener?.endForStatementBody(token);
}
@override
@@ -674,6 +709,11 @@
}
@override
+ void endImplicitCreationExpression(Token token) {
+ listener?.endImplicitCreationExpression(token);
+ }
+
+ @override
void endImport(Token importKeyword, Token semicolon) {
listener?.endImport(importKeyword, semicolon);
}
@@ -704,25 +744,6 @@
}
@override
- void handleLiteralMapEntry(Token colon, Token endToken) {
- listener?.handleLiteralMapEntry(colon, endToken);
- }
-
- @override
- void handleLiteralSetOrMap(
- int count,
- Token leftBrace,
- Token constKeyword,
- Token rightBrace,
- // TODO(danrubel): hasSetEntry parameter exists for replicating existing
- // behavior and will be removed once unified collection has been enabled
- bool hasSetEntry,
- ) {
- listener?.handleLiteralSetOrMap(
- count, leftBrace, constKeyword, rightBrace, hasSetEntry);
- }
-
- @override
void endLiteralString(int interpolationCount, Token endToken) {
listener?.endLiteralString(interpolationCount, endToken);
}
@@ -733,6 +754,11 @@
}
@override
+ void endLocalFunctionDeclaration(Token endToken) {
+ listener?.endLocalFunctionDeclaration(endToken);
+ }
+
+ @override
void endMember() {
listener?.endMember();
}
@@ -983,21 +1009,11 @@
}
@override
- void beginConditionalExpression(Token question) {
- listener?.beginConditionalExpression(question);
- }
-
- @override
void handleConditionalExpressionColon() {
listener?.handleConditionalExpressionColon();
}
@override
- void endConditionalExpression(Token question, Token colon) {
- listener?.endConditionalExpression(question, colon);
- }
-
- @override
void handleContinueStatement(
bool hasTarget, Token continueKeyword, Token endToken) {
listener?.handleContinueStatement(hasTarget, continueKeyword, endToken);
@@ -1014,28 +1030,18 @@
}
@override
- void beginImplicitCreationExpression(Token token) {
- listener?.beginImplicitCreationExpression(token);
- }
-
- @override
- void endImplicitCreationExpression(Token token) {
- listener?.endImplicitCreationExpression(token);
- }
-
- @override
void handleElseControlFlow(Token elseToken) {
listener?.handleElseControlFlow(elseToken);
}
@override
- void handleEmptyStatement(Token token) {
- listener?.handleEmptyStatement(token);
+ void handleEmptyFunctionBody(Token semicolon) {
+ listener?.handleEmptyFunctionBody(semicolon);
}
@override
- void handleEmptyFunctionBody(Token semicolon) {
- listener?.handleEmptyFunctionBody(semicolon);
+ void handleEmptyStatement(Token token) {
+ listener?.handleEmptyStatement(token);
}
@override
@@ -1064,6 +1070,35 @@
}
@override
+ void handleForInitializerEmptyStatement(Token token) {
+ listener?.handleForInitializerEmptyStatement(token);
+ }
+
+ @override
+ void handleForInitializerExpressionStatement(Token token) {
+ listener?.handleForInitializerExpressionStatement(token);
+ }
+
+ @override
+ void handleForInitializerLocalVariableDeclaration(Token token) {
+ listener?.handleForInitializerLocalVariableDeclaration(token);
+ }
+
+ @override
+ void handleForInLoopParts(Token awaitToken, Token forToken,
+ Token leftParenthesis, Token inKeyword) {
+ listener?.handleForInLoopParts(
+ awaitToken, forToken, leftParenthesis, inKeyword);
+ }
+
+ @override
+ void handleForLoopParts(Token forKeyword, Token leftParen,
+ Token leftSeparator, int updateExpressionCount) {
+ listener?.handleForLoopParts(
+ forKeyword, leftParen, leftSeparator, updateExpressionCount);
+ }
+
+ @override
void handleFormalParameterWithoutValue(Token token) {
listener?.handleFormalParameterWithoutValue(token);
}
@@ -1084,8 +1119,8 @@
}
@override
- void handleRecoverImport(Token semicolon) {
- listener?.handleRecoverImport(semicolon);
+ void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
+ listener?.handleImportPrefix(deferredKeyword, asKeyword);
}
@override
@@ -1120,13 +1155,8 @@
}
@override
- void handleInvalidTypeArguments(Token token) {
- listener?.handleInvalidTypeArguments(token);
- }
-
- @override
- void handleInvalidTypeReference(Token token) {
- listener?.handleInvalidTypeReference(token);
+ void handleInvalidStatement(Token token, Message message) {
+ listener?.handleInvalidStatement(token, message);
}
void handleInvalidTopLevelBlock(Token token) {
@@ -1139,6 +1169,16 @@
}
@override
+ void handleInvalidTypeArguments(Token token) {
+ listener?.handleInvalidTypeArguments(token);
+ }
+
+ @override
+ void handleInvalidTypeReference(Token token) {
+ listener?.handleInvalidTypeReference(token);
+ }
+
+ @override
void handleIsOperator(Token isOperator, Token not) {
listener?.handleIsOperator(isOperator, not);
}
@@ -1170,11 +1210,30 @@
}
@override
+ void handleLiteralMapEntry(Token colon, Token endToken) {
+ listener?.handleLiteralMapEntry(colon, endToken);
+ }
+
+ @override
void handleLiteralNull(Token token) {
listener?.handleLiteralNull(token);
}
@override
+ void handleLiteralSetOrMap(
+ int count,
+ Token leftBrace,
+ Token constKeyword,
+ Token rightBrace,
+ // TODO(danrubel): hasSetEntry parameter exists for replicating existing
+ // behavior and will be removed once unified collection has been enabled
+ bool hasSetEntry,
+ ) {
+ listener?.handleLiteralSetOrMap(
+ count, leftBrace, constKeyword, rightBrace, hasSetEntry);
+ }
+
+ @override
void handleMixinHeader(Token mixinKeyword) {
listener?.handleMixinHeader(mixinKeyword);
}
@@ -1230,35 +1289,6 @@
}
@override
- void handleForInitializerEmptyStatement(Token token) {
- listener?.handleForInitializerEmptyStatement(token);
- }
-
- @override
- void handleForInitializerExpressionStatement(Token token) {
- listener?.handleForInitializerExpressionStatement(token);
- }
-
- @override
- void handleForInitializerLocalVariableDeclaration(Token token) {
- listener?.handleForInitializerLocalVariableDeclaration(token);
- }
-
- @override
- void handleForInLoopParts(Token awaitToken, Token forToken,
- Token leftParenthesis, Token inKeyword) {
- listener?.handleForInLoopParts(
- awaitToken, forToken, leftParenthesis, inKeyword);
- }
-
- @override
- void handleForLoopParts(Token forKeyword, Token leftParen,
- Token leftSeparator, int updateExpressionCount) {
- listener?.handleForLoopParts(
- forKeyword, leftParen, leftSeparator, updateExpressionCount);
- }
-
- @override
void handleNoFieldInitializer(Token token) {
listener?.handleNoFieldInitializer(token);
}
@@ -1279,13 +1309,13 @@
}
@override
- void handleNonNullAssertExpression(Token bang) {
- listener?.handleNonNullAssertExpression(bang);
+ void handleNoName(Token token) {
+ listener?.handleNoName(token);
}
@override
- void handleNoName(Token token) {
- listener?.handleNoName(token);
+ void handleNonNullAssertExpression(Token bang) {
+ listener?.handleNonNullAssertExpression(bang);
}
@override
@@ -1329,26 +1359,11 @@
}
@override
- void handleImportPrefix(Token deferredKeyword, Token asKeyword) {
- listener?.handleImportPrefix(deferredKeyword, asKeyword);
- }
-
- @override
void handleQualified(Token period) {
listener?.handleQualified(period);
}
@override
- void handleRecoverClassHeader() {
- listener?.handleRecoverClassHeader();
- }
-
- @override
- void handleRecoverMixinHeader() {
- listener?.handleRecoverMixinHeader();
- }
-
- @override
void handleRecoverableError(
Message message, Token startToken, Token endToken) {
if (forwardErrors) {
@@ -1357,8 +1372,18 @@
}
@override
- void handleInvalidStatement(Token token, Message message) {
- listener?.handleInvalidStatement(token, message);
+ void handleRecoverClassHeader() {
+ listener?.handleRecoverClassHeader();
+ }
+
+ @override
+ void handleRecoverImport(Token semicolon) {
+ listener?.handleRecoverImport(semicolon);
+ }
+
+ @override
+ void handleRecoverMixinHeader() {
+ listener?.handleRecoverMixinHeader();
}
@override
@@ -1382,12 +1407,6 @@
}
@override
- void handleUnescapeError(
- Message message, Token location, int offset, int length) {
- listener?.handleUnescapeError(message, location, offset, length);
- }
-
- @override
void handleStringPart(Token token) {
listener?.handleStringPart(token);
}
@@ -1438,13 +1457,9 @@
}
@override
- void beginFormalParameterDefaultValueExpression() {
- listener?.beginFormalParameterDefaultValueExpression();
- }
-
- @override
- void endFormalParameterDefaultValueExpression() {
- listener?.endFormalParameterDefaultValueExpression();
+ void handleUnescapeError(
+ Message message, Token location, int offset, int length) {
+ listener?.handleUnescapeError(message, location, offset, length);
}
@override
@@ -1468,17 +1483,12 @@
}
@override
- void reportNonNullAssertExpressionNotEnabled(Token bang) {
- listener?.reportNonNullAssertExpressionNotEnabled(bang);
- }
-
- @override
void reportNonNullableModifierError(Token modifierToken) {
listener?.reportNonNullableModifierError(modifierToken);
}
@override
- set suppressParseErrors(bool value) {
- listener?.suppressParseErrors = value;
+ void reportNonNullAssertExpressionNotEnabled(Token bang) {
+ listener?.reportNonNullAssertExpressionNotEnabled(bang);
}
}
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
index 460fec9..460dc1b 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -98,7 +98,8 @@
/// Identifier is the name being declared by a class declaration, a mixin
/// declaration, or a named mixin application, for example,
/// `Foo` in `class Foo = X with Y;`.
- static const classOrMixinDeclaration = const ClassOrMixinIdentifierContext();
+ static const classOrMixinOrExtensionDeclaration =
+ const ClassOrMixinOrExtensionIdentifierContext();
/// Identifier is the name of a type variable being declared (e.g. `Foo` in
/// `class C<Foo extends num> {}`).
diff --git a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
index 0dd6638..0d0fccb 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -43,9 +43,9 @@
}
}
-/// See [IdentifierContext.classOrMixinDeclaration].
-class ClassOrMixinIdentifierContext extends IdentifierContext {
- const ClassOrMixinIdentifierContext()
+/// See [IdentifierContext.classOrMixinOrExtensionDeclaration].
+class ClassOrMixinOrExtensionIdentifierContext extends IdentifierContext {
+ const ClassOrMixinOrExtensionIdentifierContext()
: super('classOrMixinDeclaration',
inDeclaration: true, isBuiltInIdentifierAllowed: false);
@@ -59,8 +59,8 @@
// Recovery
if (looksLikeStartOfNextTopLevelDeclaration(identifier) ||
- isOneOfOrEof(
- identifier, const ['<', '{', 'extends', 'with', 'implements'])) {
+ isOneOfOrEof(identifier,
+ const ['<', '{', 'extends', 'with', 'implements', 'on'])) {
identifier = parser.insertSyntheticIdentifier(token, this,
message: fasta.templateExpectedIdentifier.withArguments(identifier));
} else if (identifier.type.isBuiltIn) {
@@ -940,8 +940,6 @@
parser.reportRecoverableError(identifier, fasta.messageAwaitAsIdentifier);
} else if (optional('yield', identifier)) {
parser.reportRecoverableError(identifier, fasta.messageYieldAsIdentifier);
- } else if (optional('async', identifier)) {
- parser.reportRecoverableError(identifier, fasta.messageAsyncAsIdentifier);
}
}
}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 5239ab9..0e8f57d 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -151,7 +151,7 @@
logEvent("MixinOn");
}
- /// Handle the header of a class declaration. Substructures:
+ /// Handle the header of a mixin declaration. Substructures:
/// - metadata
/// - mixin name
/// - type variables
@@ -179,6 +179,20 @@
logEvent("MixinDeclaration");
}
+ /// Handle the beginning of an extension methods declaration. Substructures:
+ /// - metadata
+ /// - extension name
+ /// - type variables
+ void beginExtensionDeclaration(Token extensionKeyword, Token name) {}
+
+ /// Handle the end of an extension methods declaration. Substructures:
+ /// - substructures from [beginExtensionDeclaration]
+ /// - on type
+ /// - body
+ void endExtensionDeclaration(Token onKeyword, Token token) {
+ logEvent('ExtensionDeclaration');
+ }
+
void beginCombinators(Token token) {}
void endCombinators(int count) {
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 0c49fb1..93e717d 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -271,7 +271,7 @@
covariantToken = next;
if (varToken != null) {
- parser.reportRecoverableError(next, fasta.messageCovariantAfterVar);
+ reportModifierOutOfOrder(next, varToken.lexeme);
} else if (finalToken != null) {
reportModifierOutOfOrder(next, finalToken.lexeme);
} else if (lateToken != null) {
@@ -303,11 +303,11 @@
externalToken = next;
if (afterFactory) {
- parser.reportRecoverableError(next, fasta.messageExternalAfterFactory);
+ reportModifierOutOfOrder(next, 'factory');
} else if (constToken != null) {
- parser.reportRecoverableError(next, fasta.messageExternalAfterConst);
+ reportModifierOutOfOrder(next, constToken.lexeme);
} else if (staticToken != null) {
- parser.reportRecoverableError(next, fasta.messageExternalAfterStatic);
+ reportModifierOutOfOrder(next, staticToken.lexeme);
} else if (lateToken != null) {
reportModifierOutOfOrder(next, lateToken.lexeme);
}
@@ -399,11 +399,11 @@
staticToken = next;
if (constToken != null) {
- parser.reportRecoverableError(next, fasta.messageStaticAfterConst);
+ reportModifierOutOfOrder(next, constToken.lexeme);
} else if (finalToken != null) {
- parser.reportRecoverableError(next, fasta.messageStaticAfterFinal);
+ reportModifierOutOfOrder(next, finalToken.lexeme);
} else if (varToken != null) {
- parser.reportRecoverableError(next, fasta.messageStaticAfterVar);
+ reportModifierOutOfOrder(next, varToken.lexeme);
} else if (lateToken != null) {
reportModifierOutOfOrder(next, lateToken.lexeme);
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 6e60793..24fe512 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -500,13 +500,8 @@
reportRecoverableError(next, fasta.messageTopLevelOperator);
// Insert a synthetic identifier
// and continue parsing as a top level function.
- rewriter.insertToken(
- next,
- new SyntheticStringToken(
- TokenType.IDENTIFIER,
- '#synthetic_function_${next.charOffset}',
- next.next.charOffset,
- 0));
+ rewriter.insertSyntheticIdentifier(
+ next, '#synthetic_function_${next.charOffset}');
return parseTopLevelMemberImpl(next);
}
// Ignore any preceding modifiers and just report the unexpected token
@@ -590,23 +585,26 @@
return parseTopLevelMemberImpl(start);
} else {
parseTopLevelKeywordModifiers(start, keyword);
- if (identical(value, 'mixin')) {
- directiveState?.checkDeclaration();
- return parseMixin(keyword);
- } else if (identical(value, 'typedef')) {
- directiveState?.checkDeclaration();
- return parseTypedef(keyword);
- } else if (identical(value, 'library')) {
- directiveState?.checkLibrary(this, keyword);
- return parseLibraryName(keyword);
- } else if (identical(value, 'import')) {
+ if (identical(value, 'import')) {
directiveState?.checkImport(this, keyword);
return parseImport(keyword);
} else if (identical(value, 'export')) {
directiveState?.checkExport(this, keyword);
return parseExport(keyword);
+ } else if (identical(value, 'typedef')) {
+ directiveState?.checkDeclaration();
+ return parseTypedef(keyword);
+ } else if (identical(value, 'mixin')) {
+ directiveState?.checkDeclaration();
+ return parseMixin(keyword);
+ } else if (identical(value, 'extension')) {
+ directiveState?.checkDeclaration();
+ return parseExtension(keyword);
} else if (identical(value, 'part')) {
return parsePartOrPartOf(keyword, directiveState);
+ } else if (identical(value, 'library')) {
+ directiveState?.checkLibrary(this, keyword);
+ return parseLibraryName(keyword);
}
}
}
@@ -1109,9 +1107,7 @@
// Recovery: Report an error and insert synthetic `with` clause.
reportRecoverableError(
withKeyword, fasta.templateExpectedButGot.withArguments('with'));
- withKeyword =
- new SyntheticKeywordToken(Keyword.WITH, withKeyword.charOffset);
- rewriter.insertToken(token, withKeyword);
+ withKeyword = rewriter.insertSyntheticKeyword(token, Keyword.WITH);
if (!isValidTypeReference(withKeyword.next)) {
rewriter.insertSyntheticIdentifier(withKeyword);
}
@@ -1658,7 +1654,7 @@
Token skipBlock(Token token) {
// The scanner ensures that `{` always has a closing `}`.
- return ensureBlock(token, null).endGroup;
+ return ensureBlock(token, null, null).endGroup;
}
/// ```
@@ -1717,7 +1713,8 @@
}
}
} else {
- leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody);
+ // TODO(danrubel): merge this error message with missing class/mixin body
+ leftBrace = ensureBlock(token, fasta.templateExpectedEnumBody, null);
token = leftBrace.endGroup;
}
assert(optional('}', token));
@@ -1731,7 +1728,7 @@
Token begin = abstractToken ?? classKeyword;
listener.beginClassOrNamedMixinApplication(begin);
Token name = ensureIdentifier(
- classKeyword, IdentifierContext.classOrMixinDeclaration);
+ classKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
if (optional('=', token.next)) {
listener.beginNamedMixinApplication(begin, abstractToken, name);
@@ -1776,7 +1773,7 @@
if (!optional('{', token.next)) {
// Recovery
token = parseClassHeaderRecovery(start, begin, classKeyword);
- ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+ ensureBlock(token, null, 'class declaration');
}
token = parseClassOrMixinBody(token);
listener.endClassDeclaration(begin, token);
@@ -1934,7 +1931,7 @@
assert(optional('mixin', mixinKeyword));
listener.beginClassOrNamedMixinApplication(mixinKeyword);
Token name = ensureIdentifier(
- mixinKeyword, IdentifierContext.classOrMixinDeclaration);
+ mixinKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
Token headerStart =
computeTypeParamOrArg(name, true).parseVariables(name, this);
listener.beginMixinDeclaration(mixinKeyword, name);
@@ -1942,7 +1939,7 @@
if (!optional('{', token.next)) {
// Recovery
token = parseMixinHeaderRecovery(token, mixinKeyword, headerStart);
- ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+ ensureBlock(token, null, 'mixin declaration');
}
token = parseClassOrMixinBody(token);
listener.endMixinDeclaration(mixinKeyword, token);
@@ -2055,6 +2052,64 @@
return token;
}
+ /// ```
+ /// 'extension' <identifier><typeParameters>? 'on' <type> '?'?
+ // `{'
+ // <memberDeclaration>*
+ // `}'
+ /// ```
+ Token parseExtension(Token extensionKeyword) {
+ assert(optional('extension', extensionKeyword));
+ Token name = ensureIdentifier(
+ extensionKeyword, IdentifierContext.classOrMixinOrExtensionDeclaration);
+ Token token = computeTypeParamOrArg(name, true).parseVariables(name, this);
+ listener.beginExtensionDeclaration(extensionKeyword, name);
+ Token onKeyword = token.next;
+ if (!optional('on', onKeyword)) {
+ // Recovery
+ if (optional('extends', onKeyword) ||
+ optional('implements', onKeyword) ||
+ optional('with', onKeyword)) {
+ reportRecoverableError(
+ onKeyword, fasta.templateExpectedInstead.withArguments('on'));
+ } else {
+ reportRecoverableError(
+ token, fasta.templateExpectedAfterButGot.withArguments('on'));
+ onKeyword = rewriter.insertSyntheticKeyword(token, Keyword.ON);
+ }
+ }
+ TypeInfo typeInfo = computeType(onKeyword, true);
+ token = typeInfo.ensureTypeNotVoid(onKeyword, this);
+ if (!optional('{', token.next)) {
+ // Recovery
+ Token next = token.next;
+ while (!next.isEof) {
+ if (optional(',', next) ||
+ optional('extends', next) ||
+ optional('implements', next) ||
+ optional('on', next) ||
+ optional('with', next)) {
+ // Report an error and skip `,` or specific keyword
+ // optionally followed by an identifier
+ reportRecoverableErrorWithToken(next, fasta.templateUnexpectedToken);
+ token = next;
+ next = token.next;
+ if (next.isIdentifier) {
+ token = next;
+ next = token.next;
+ }
+ } else {
+ break;
+ }
+ }
+ ensureBlock(token, null, 'extension declaration');
+ }
+ // TODO(danrubel): Do not allow fields or constructors
+ token = parseClassOrMixinBody(token);
+ listener.endExtensionDeclaration(onKeyword, token);
+ return token;
+ }
+
Token parseStringPart(Token token) {
Token next = token.next;
if (next.kind != STRING_TOKEN) {
@@ -2223,13 +2278,8 @@
token = next;
next = token.next;
if (optional('(', next.next)) {
- rewriter.insertToken(
- next,
- new SyntheticStringToken(
- TokenType.IDENTIFIER,
- '#synthetic_identifier_${next.charOffset}',
- next.charOffset,
- 0));
+ rewriter.insertSyntheticIdentifier(
+ next, '#synthetic_identifier_${next.charOffset}');
}
}
}
@@ -2333,7 +2383,27 @@
name, name, lateToken, varFinalOrConst, isTopLevel);
++fieldCount;
}
- token = ensureSemicolon(token);
+ Token semicolon = token.next;
+ if (optional(';', semicolon)) {
+ token = semicolon;
+ } else {
+ // Recovery
+ if (isTopLevel &&
+ beforeType.next.isIdentifier &&
+ beforeType.next.lexeme == 'extension') {
+ // Looks like an extension method
+ // TODO(danrubel): Remove when extension methods are enabled by default
+ // because then 'extension' will be interpreted as a built-in
+ // and this code will never be executed
+ reportRecoverableError(
+ beforeType.next,
+ fasta.templateExperimentNotEnabled
+ .withArguments('extension-methods'));
+ token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
+ } else {
+ token = ensureSemicolon(token);
+ }
+ }
if (isTopLevel) {
listener.endTopLevelFields(staticToken, covariantToken, lateToken,
varFinalOrConst, fieldCount, beforeStart.next, token);
@@ -2496,8 +2566,7 @@
// expecting one of `,` or `;` or `{`
reportRecoverableError(
token, fasta.templateExpectedAfterButGot.withArguments(','));
- next = rewriter.insertToken(
- token, new SyntheticToken(TokenType.COMMA, token.next.charOffset));
+ next = rewriter.insertSyntheticToken(token, TokenType.COMMA);
}
}
mayParseFunctionExpressions = old;
@@ -2559,8 +2628,7 @@
// `this.<fieldname>=` is expected.
reportRecoverableError(
next, fasta.templateExpectedButGot.withArguments('.'));
- rewriter.insertToken(
- token, new SyntheticToken(TokenType.PERIOD, next.offset));
+ rewriter.insertSyntheticToken(token, TokenType.PERIOD);
token = rewriter.insertSyntheticIdentifier(token.next);
next = token.next;
}
@@ -2574,8 +2642,7 @@
// then fall through to insert the LHS and `=` of the assignment,
// otherwise insert an `=` and synthetic identifier.
if (!next2.isOperator && !optional('.', next2)) {
- token = rewriter.insertToken(
- next, new SyntheticToken(TokenType.EQ, next2.offset));
+ token = rewriter.insertSyntheticToken(next, TokenType.EQ);
token = insertSyntheticIdentifier(token, IdentifierContext.expression,
message: fasta.messageMissingAssignmentInInitializer,
messageOnToken: next);
@@ -2586,8 +2653,7 @@
token = insertSyntheticIdentifier(
token, IdentifierContext.fieldInitializer,
message: fasta.messageExpectedAnInitializer, messageOnToken: token);
- token = rewriter.insertToken(
- token, new SyntheticToken(TokenType.EQ, token.offset));
+ token = rewriter.insertSyntheticToken(token, TokenType.EQ);
token = rewriter.insertSyntheticIdentifier(token);
return parseInitializerExpressionRest(beforeExpression);
}
@@ -2600,7 +2666,7 @@
token = insertSyntheticIdentifier(
beforeExpression, IdentifierContext.fieldInitializer,
message: fasta.messageMissingAssignmentInInitializer);
- rewriter.insertToken(token, new SyntheticToken(TokenType.EQ, token.offset));
+ rewriter.insertSyntheticToken(token, TokenType.EQ);
return parseInitializerExpressionRest(beforeExpression);
}
@@ -2658,17 +2724,28 @@
}
/// If the next token is an opening curly brace, return it. Otherwise, use the
- /// given [template] to report an error, insert an opening and a closing curly
- /// brace, and return the newly inserted opening curly brace. If the
- /// [template] is `null`, use a default error message instead.
- Token ensureBlock(
- Token token, Template<Message Function(Token token)> template) {
+ /// given [template] or [blockKind] to report an error, insert an opening and
+ /// a closing curly brace, and return the newly inserted opening curly brace.
+ /// If [template] and [blockKind] are `null`, then use
+ /// a default error message instead.
+ Token ensureBlock(Token token,
+ Template<Message Function(Token token)> template, String blockKind) {
Token next = token.next;
if (optional('{', next)) return next;
- Message message = template == null
- ? fasta.templateExpectedButGot.withArguments('{')
- : template.withArguments(next);
- reportRecoverableError(next, message);
+ if (template == null) {
+ if (blockKind == null) {
+ // TODO(danrubel): rename ExpectedButGot to ExpectedBefore
+ reportRecoverableError(
+ next, fasta.templateExpectedButGot.withArguments('{'));
+ } else {
+ // TODO(danrubel): rename ExpectedClassOrMixinBody
+ // to ExpectedDeclarationOrClauseBody
+ reportRecoverableError(token,
+ fasta.templateExpectedClassOrMixinBody.withArguments(blockKind));
+ }
+ } else {
+ reportRecoverableError(next, template.withArguments(next));
+ }
return insertBlock(token);
}
@@ -2745,9 +2822,7 @@
// for users to understand and fix the error.
reportRecoverableError(findPreviousNonZeroLengthToken(token),
fasta.templateExpectedAfterButGot.withArguments(';'));
-
- return rewriter.insertToken(
- token, new SyntheticToken(TokenType.SEMICOLON, next.charOffset));
+ return rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
}
/// Report an error at the token after [token] that has the given [message].
@@ -2801,7 +2876,7 @@
Token skipClassOrMixinBody(Token token) {
// The scanner ensures that `{` always has a closing `}`.
- return ensureBlock(token, fasta.templateExpectedClassOrMixinBody);
+ return ensureBlock(token, null, null);
}
/// ```
@@ -3515,7 +3590,7 @@
begin = next = token.next;
// Fall through to parse the block.
} else {
- token = ensureBlock(token, fasta.templateExpectedFunctionBody);
+ token = ensureBlock(token, fasta.templateExpectedFunctionBody, null);
listener.handleInvalidFunctionBody(token);
return token.endGroup;
}
@@ -3637,7 +3712,8 @@
}
final value = token.next.stringValue;
if (identical(value, '{')) {
- return parseBlock(token);
+ // The scanner ensures that `{` always has a closing `}`.
+ return parseBlock(token, null);
} else if (identical(value, 'return')) {
return parseReturnStatement(token);
} else if (identical(value, 'var') || identical(value, 'final')) {
@@ -3886,7 +3962,7 @@
}
Token next = token.next;
TokenType type = next.type;
- int tokenLevel = _computePrecedence(type);
+ int tokenLevel = _computePrecedence(next);
for (int level = tokenLevel; level >= precedence; --level) {
int lastBinaryExpressionLevel = -1;
while (identical(tokenLevel, level)) {
@@ -3935,10 +4011,14 @@
rewriter.replaceTokenFollowing(token, replacement);
replacement.endToken = replacement.next;
token = parseArgumentOrIndexStar(token, noTypeParamOrArg);
+ } else if (identical(type, TokenType.BANG)) {
+ listener.handleNonNullAssertExpression(token.next);
+ token = next;
} else {
// Recovery
reportRecoverableErrorWithToken(
token.next, fasta.templateUnexpectedToken);
+ token = next;
}
} else if (identical(type, TokenType.IS)) {
token = parseIsOperatorRest(token);
@@ -3967,20 +4047,23 @@
}
next = token.next;
type = next.type;
- tokenLevel = _computePrecedence(type);
+ tokenLevel = _computePrecedence(next);
}
}
return token;
}
- int _computePrecedence(TokenType type) {
+ int _computePrecedence(Token token) {
+ TokenType type = token.type;
if (identical(type, TokenType.BANG)) {
// The '!' has prefix precedence but here it's being used as a
// postfix operator to assert the expression has a non-null value.
+ if (identical(token.next.type, TokenType.PERIOD)) {
+ return SELECTOR_PRECEDENCE;
+ }
return POSTFIX_PRECEDENCE;
- } else {
- return type.precedence;
}
+ return type.precedence;
}
Token parseCascadeExpression(Token token) {
@@ -4523,7 +4606,6 @@
token = typeParamOrArg.parseArguments(start, this);
if (optional('{', next)) {
if (typeParamOrArg.typeArgumentCount > 2) {
- // TODO(danrubel): remove code in listeners which report this error
listener.handleRecoverableError(
fasta.messageSetOrMapLiteralTooManyTypeArguments,
start.next,
@@ -4535,8 +4617,7 @@
// TODO(danrubel): Improve this error message.
reportRecoverableError(
next, fasta.templateExpectedButGot.withArguments('['));
- rewriter.insertToken(
- token, new SyntheticToken(TokenType.INDEX, next.charOffset));
+ rewriter.insertSyntheticToken(token, TokenType.INDEX);
}
return parseLiteralListSuffix(token, constKeyword);
}
@@ -5364,34 +5445,27 @@
// Recovery
reportRecoverableError(
leftParenthesis, fasta.templateExpectedButGot.withArguments('('));
- int offset = leftParenthesis.offset;
- BeginToken openParen = forToken
- .setNext(new SyntheticBeginToken(TokenType.OPEN_PAREN, offset));
+ BeginToken openParen = rewriter.insertToken(
+ forToken,
+ new SyntheticBeginToken(
+ TokenType.OPEN_PAREN, leftParenthesis.offset));
- Token loopPart;
+ Token token;
if (awaitToken != null) {
- loopPart = openParen.setNext(
- new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
- loopPart =
- loopPart.setNext(new SyntheticKeywordToken(Keyword.IN, offset));
- loopPart = loopPart.setNext(
- new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
+ token = rewriter.insertSyntheticIdentifier(openParen);
+ token = rewriter.insertSyntheticKeyword(token, Keyword.IN);
+ token = rewriter.insertSyntheticIdentifier(token);
} else {
- loopPart =
- openParen.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
- loopPart =
- loopPart.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
+ token = rewriter.insertSyntheticToken(openParen, TokenType.SEMICOLON);
+ token = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
}
- Token closeParen =
- loopPart.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
- openParen.endGroup = closeParen;
- Token identifier = closeParen
- .setNext(new SyntheticStringToken(TokenType.IDENTIFIER, '', offset));
- Token semicolon =
- identifier.setNext(new SyntheticToken(TokenType.SEMICOLON, offset));
- semicolon.setNext(leftParenthesis);
+ openParen.endGroup = token = rewriter.insertToken(token,
+ new SyntheticToken(TokenType.CLOSE_PAREN, leftParenthesis.offset));
+
+ token = rewriter.insertSyntheticIdentifier(token);
+ rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
leftParenthesis = openParen;
}
@@ -5400,7 +5474,7 @@
// parses the metadata, modifiers, and type of a local variable
// declaration if it exists. This enables capturing [beforeIdentifier]
// for later error reporting.
- return parseExpressionStatementOrDeclaration(forToken.next, true);
+ return parseExpressionStatementOrDeclaration(leftParenthesis, true);
}
/// Parse the remainder of the local variable declaration
@@ -5586,8 +5660,7 @@
if (!optional('while', whileToken)) {
reportRecoverableError(
whileToken, fasta.templateExpectedButGot.withArguments('while'));
- whileToken = rewriter.insertToken(token,
- new SyntheticKeywordToken(Keyword.WHILE, whileToken.charOffset));
+ whileToken = rewriter.insertSyntheticKeyword(token, Keyword.WHILE);
}
token = ensureParenthesizedCondition(whileToken);
token = ensureSemicolon(token);
@@ -5600,8 +5673,8 @@
/// '{' statement* '}'
/// ;
/// ```
- Token parseBlock(Token token) {
- Token begin = token = ensureBlock(token, null);
+ Token parseBlock(Token token, String blockKind) {
+ Token begin = token = ensureBlock(token, null, blockKind);
listener.beginBlock(begin);
int statementCount = 0;
Token startToken = token.next;
@@ -5630,7 +5703,8 @@
// because an error has already been reported by the caller.
Listener originalListener = listener;
listener = new ForwardingListener(listener)..forwardErrors = false;
- token = parseBlock(token);
+ // The scanner ensures that `{` always has a closing `}`.
+ token = parseBlock(token, null);
listener = originalListener;
listener.handleInvalidTopLevelBlock(begin);
return token;
@@ -5745,7 +5819,7 @@
Token tryKeyword = token.next;
assert(optional('try', tryKeyword));
listener.beginTryStatement(tryKeyword);
- Token lastConsumed = parseBlock(tryKeyword);
+ Token lastConsumed = parseBlock(tryKeyword, 'try statement');
token = lastConsumed.next;
int catchCount = 0;
@@ -5813,8 +5887,8 @@
rewriter.moveSynthetic(exceptionName, openParens.endGroup);
comma = null;
} else {
- comma = rewriter.insertToken(exceptionName,
- new SyntheticToken(TokenType.COMMA, comma.charOffset));
+ comma =
+ rewriter.insertSyntheticToken(exceptionName, TokenType.COMMA);
}
}
if (comma != null) {
@@ -5840,7 +5914,7 @@
token = lastConsumed.next;
}
listener.endCatchClause(token);
- lastConsumed = parseBlock(lastConsumed);
+ lastConsumed = parseBlock(lastConsumed, 'catch clause');
token = lastConsumed.next;
++catchCount;
listener.handleCatchBlock(onKeyword, catchKeyword, comma);
@@ -5850,7 +5924,7 @@
Token finallyKeyword = null;
if (optional('finally', token)) {
finallyKeyword = token;
- lastConsumed = parseBlock(token);
+ lastConsumed = parseBlock(token, 'finally clause');
token = lastConsumed.next;
listener.handleFinallyBlock(finallyKeyword);
} else {
@@ -5888,7 +5962,7 @@
/// ;
/// ```
Token parseSwitchBlock(Token token) {
- Token beginSwitch = token = ensureBlock(token, null);
+ Token beginSwitch = token = ensureBlock(token, null, 'switch statement');
listener.beginSwitchBlock(beginSwitch);
int caseCount = 0;
Token defaultKeyword = null;
@@ -6168,8 +6242,7 @@
next = next.next;
} else {
reportRecoverableError(next, fasta.messageMissingOperatorKeyword);
- rewriter.insertToken(
- beforeName, new SyntheticToken(Keyword.OPERATOR, next.offset));
+ rewriter.insertSyntheticKeyword(beforeName, Keyword.OPERATOR);
}
assert((next.isOperator && next.endGroup == null) ||
@@ -6265,9 +6338,7 @@
Token recoverFromStackOverflow(Token token) {
Token next = token.next;
reportRecoverableError(next, fasta.messageStackOverflow);
-
- next = new SyntheticToken(TokenType.SEMICOLON, token.offset);
- rewriter.insertToken(token, next);
+ next = rewriter.insertSyntheticToken(token, TokenType.SEMICOLON);
listener.handleEmptyStatement(next);
while (notEofOrValue('}', next)) {
diff --git a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
index 9a8b367..29ab789 100644
--- a/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
+++ b/pkg/front_end/lib/src/fasta/parser/token_stream_rewriter.dart
@@ -7,8 +7,10 @@
import '../../scanner/token.dart'
show
BeginToken,
+ Keyword,
SimpleToken,
SyntheticBeginToken,
+ SyntheticKeywordToken,
SyntheticStringToken,
SyntheticToken,
Token,
@@ -17,7 +19,7 @@
/// Provides the capability of inserting tokens into a token stream. This
/// implementation does this by rewriting the previous token to point to the
/// inserted token.
-class TokenStreamRewriter {
+class TokenStreamRewriter with _TokenStreamMixin {
// TODO(brianwilkerson):
//
// When we get to the point of removing `token.previous`, the plan is to
@@ -59,14 +61,6 @@
return leftParen;
}
- /// Insert a synthetic identifier after [token] and return the new identifier.
- Token insertSyntheticIdentifier(Token token) {
- return insertToken(
- token,
- new SyntheticStringToken(
- TokenType.IDENTIFIER, '', token.next.charOffset, 0));
- }
-
/// Insert [newToken] after [token] and return [newToken].
Token insertToken(Token token, Token newToken) {
newToken.setNext(token.next);
@@ -141,7 +135,9 @@
/// Provides the capability of adding tokens that lead into a token stream
/// without modifying the original token stream and not setting the any token's
/// `previous` field.
-class TokenStreamGhostWriter implements TokenStreamRewriter {
+class TokenStreamGhostWriter
+ with _TokenStreamMixin
+ implements TokenStreamRewriter {
@override
Token insertParens(Token token, bool includeIdentifier) {
Token next = token.next;
@@ -161,14 +157,6 @@
return leftParen;
}
- /// Insert a synthetic identifier after [token] and return the new identifier.
- Token insertSyntheticIdentifier(Token token) {
- return insertToken(
- token,
- new SyntheticStringToken(
- TokenType.IDENTIFIER, '', token.next.charOffset, 0));
- }
-
@override
Token insertToken(Token token, Token newToken) {
newToken.next = token.next;
@@ -204,3 +192,28 @@
return current;
}
}
+
+mixin _TokenStreamMixin {
+ /// Insert a synthetic identifier after [token] and return the new identifier.
+ Token insertSyntheticIdentifier(Token token, [String value]) {
+ return insertToken(
+ token,
+ new SyntheticStringToken(
+ TokenType.IDENTIFIER, value ?? '', token.next.charOffset, 0));
+ }
+
+ /// Insert a new synthetic [keyword] after [token] and return the new token.
+ Token insertSyntheticKeyword(Token token, Keyword keyword) => insertToken(
+ token, new SyntheticKeywordToken(keyword, token.next.charOffset));
+
+ /// Insert a new simple synthetic token of [newTokenType] after [token]
+ /// and return the new token.
+ Token insertSyntheticToken(Token token, TokenType newTokenType) {
+ assert(newTokenType is! Keyword, 'use insertSyntheticKeyword instead');
+ return insertToken(
+ token, new SyntheticToken(newTokenType, token.next.charOffset));
+ }
+
+ /// Insert [newToken] after [token] and return [newToken].
+ Token insertToken(Token token, Token newToken);
+}
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index 1125c14..cf3c27f 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -363,10 +363,8 @@
@override
void endLibraryName(Token libraryKeyword, Token semicolon) {
debugEvent("endLibraryName");
- pop(); // name
-
- Token metadata = pop();
- parseMetadata(library, metadata, library.target);
+ pop(); // Name.
+ pop(); // Annotations.
}
@override
@@ -537,7 +535,6 @@
ProcedureBuilder builder = lookupConstructor(beginToken, name);
if (bodyToken == null || optional("=", bodyToken.endGroup.next)) {
- parseMetadata(builder, metadata, builder.target);
buildRedirectingFactoryMethod(
bodyToken, builder, MemberKind.Factory, metadata);
} else {
@@ -709,18 +706,14 @@
debugEvent("beginClassOrMixinBody");
Token beginToken = pop();
Object name = pop();
- Token metadata = pop();
+ pop(); // Annotation begin token.
assert(currentClass == null);
assert(memberScope == library.scope);
if (name is ParserRecovery) {
currentClassIsParserRecovery = true;
return;
}
-
- Declaration classBuilder = lookupBuilder(beginToken, null, name);
- parseMetadata(classBuilder, metadata, classBuilder.target);
-
- currentClass = classBuilder;
+ currentClass = lookupBuilder(beginToken, null, name);
memberScope = currentClass.scope;
}
@@ -747,26 +740,9 @@
@override
void endEnum(Token enumKeyword, Token leftBrace, int count) {
debugEvent("Enum");
- List<Object> metadataAndValues =
- const FixedNullableList<Object>().pop(stack, count * 2);
- Object name = pop();
- Token metadata = pop();
- checkEmpty(enumKeyword.charOffset);
- if (name is ParserRecovery) return;
-
- ClassBuilder enumBuilder = lookupBuilder(enumKeyword, null, name);
- parseMetadata(enumBuilder, metadata, enumBuilder.target);
- if (metadataAndValues != null) {
- for (int i = 0; i < metadataAndValues.length; i += 2) {
- Token metadata = metadataAndValues[i];
- String valueName = metadataAndValues[i + 1];
- Declaration declaration = enumBuilder.scope.local[valueName];
- if (metadata != null) {
- parseMetadata(declaration, metadata, declaration.target);
- }
- }
- }
-
+ const FixedNullableList<Object>().pop(stack, count * 2);
+ pop(); // Name.
+ pop(); // Annotations begin token.
checkEmpty(enumKeyword.charOffset);
}
@@ -775,20 +751,9 @@
Token equals, Token implementsKeyword, Token endToken) {
debugEvent("NamedMixinApplication");
- Object name = pop();
- Token metadata = pop();
+ pop(); // Name.
+ pop(); // Annotations begin token.
checkEmpty(beginToken.charOffset);
- if (name is ParserRecovery) return;
-
- Declaration classBuilder = library.scopeBuilder[name];
- if (classBuilder != null) {
- // TODO(ahe): We shouldn't have to check for null here. The problem is
- // that we don't create a named mixin application if the mixins or
- // supertype are missing. Could we create a class instead? The nested
- // declarations wouldn't match up.
- parseMetadata(classBuilder, metadata, classBuilder.target);
- checkEmpty(beginToken.charOffset);
- }
}
AsyncMarker getAsyncMarker(StackListener listener) => listener.pop();
@@ -800,13 +765,11 @@
void listenerFinishFunction(
StackListener listener,
Token token,
- Token metadata,
MemberKind kind,
- List metadataConstants,
dynamic formals,
AsyncMarker asyncModifier,
dynamic body) {
- listener.finishFunction(metadataConstants, formals, asyncModifier, body);
+ listener.finishFunction(formals, asyncModifier, body);
}
/// Invokes the listener's [finishFields] method.
@@ -823,10 +786,9 @@
Token token = startToken;
try {
Parser parser = new Parser(listener);
- List metadataConstants;
if (metadata != null) {
parser.parseMetadataStar(parser.syntheticPreviousToken(metadata));
- metadataConstants = listener.pop();
+ listener.pop(); // Annotations.
}
token = parser.parseFormalParametersOpt(
parser.syntheticPreviousToken(token), kind);
@@ -840,8 +802,8 @@
parser.parseFunctionBody(token, isExpression, allowAbstract);
var body = listener.pop();
listener.checkEmpty(token.charOffset);
- listenerFinishFunction(listener, startToken, metadata, kind,
- metadataConstants, formals, asyncModifier, body);
+ listenerFinishFunction(
+ listener, startToken, kind, formals, asyncModifier, body);
} on DebugAbort {
rethrow;
} catch (e, s) {
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 24d3a08..43536a0 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -41,6 +41,7 @@
// TODO(ahe): The outline isn't supposed to import kernel-specific builders.
import '../kernel/kernel_builder.dart'
show
+ KernelMetadataBuilder,
KernelMixinApplicationBuilder,
KernelNamedTypeBuilder,
KernelTypeBuilder;
@@ -137,36 +138,23 @@
@override
void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
debugEvent("Metadata");
- List arguments = pop();
- popIfNotNull(periodBeforeName); // charOffset.
- String postfix = popIfNotNull(periodBeforeName);
- List<TypeBuilder> typeArguments = pop();
- if (arguments == null) {
- pop(); // charOffset
- Object expression = pop();
- push(new MetadataBuilder<KernelTypeBuilder>.fromExpression(
- expression, postfix, library, beginToken.charOffset));
- } else {
- int charOffset = pop();
- Object typeName = pop();
- if (typeName is ParserRecovery) {
- push(typeName);
- } else {
- push(new MetadataBuilder<KernelTypeBuilder>.fromConstructor(
- library.addConstructorReference(
- typeName, typeArguments, postfix, charOffset),
- arguments,
- library,
- beginToken.charOffset));
- }
+ pop(); // arguments
+ if (periodBeforeName != null) {
+ pop(); // offset
+ pop(); // constructor name
}
+ pop(); // type arguments
+ pop(); // offset
+ Object sentinel = pop(); // prefix or constructor
+ push(sentinel is ParserRecovery
+ ? sentinel
+ : new KernelMetadataBuilder(beginToken));
}
@override
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(const FixedNullableList<MetadataBuilder<KernelTypeBuilder>>()
- .pop(stack, count) ??
+ push(const FixedNullableList<MetadataBuilder>().pop(stack, count) ??
NullValue.Metadata);
}
@@ -212,7 +200,7 @@
List<Configuration> configurations = pop();
int uriOffset = popCharOffset();
String uri = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
library.addExport(metadata, uri, configurations, combinators,
exportKeyword.charOffset, uriOffset);
checkEmpty(exportKeyword.charOffset);
@@ -240,7 +228,7 @@
List<Configuration> configurations = pop();
int uriOffset = popCharOffset();
String uri = pop(); // For a conditional import, this is the default URI.
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(importKeyword.charOffset);
if (prefix is ParserRecovery) return;
library.addImport(
@@ -304,7 +292,7 @@
debugEvent("Part");
int charOffset = popCharOffset();
String uri = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
library.addPart(metadata, uri, charOffset);
checkEmpty(partKeyword.charOffset);
}
@@ -327,7 +315,7 @@
void handleIdentifier(Token token, IdentifierContext context) {
if (context == IdentifierContext.enumValueDeclaration) {
debugEvent("handleIdentifier");
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
if (token.isSynthetic) {
push(new ParserRecovery(token.charOffset));
} else {
@@ -435,7 +423,7 @@
popCharOffset();
String documentationComment = getDocumentationComment(libraryKeyword);
Object name = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
library.documentationComment = documentationComment;
if (name is! ParserRecovery) {
library.name = flattenName(name, offsetForToken(libraryKeyword), uri);
@@ -551,7 +539,7 @@
if (typeVariables != null && supertype is MixinApplicationBuilder) {
supertype.typeVariables = typeVariables;
}
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery) {
library.endNestedDeclaration("<syntax-error>");
@@ -589,7 +577,7 @@
pop(NullValue.TypeVariables);
int nameOffset = pop();
Object name = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop(NullValue.Metadata);
+ List<MetadataBuilder> metadata = pop(NullValue.Metadata);
checkEmpty(mixinToken.charOffset);
if (name is ParserRecovery) {
library.endNestedDeclaration("<syntax-error>");
@@ -657,7 +645,7 @@
if (isAbstract) {
modifiers |= abstractMask;
}
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(beginToken.charOffset);
library
.endNestedDeclaration("#method")
@@ -843,7 +831,7 @@
}
bool isConst = (modifiers & constMask) != 0;
int varFinalOrConstOffset = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
String documentationComment = getDocumentationComment(beginToken);
library
.endNestedDeclaration("#method")
@@ -938,7 +926,7 @@
pop();
int charOffset = pop();
Object name = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(beginToken.charOffset);
if (name is ParserRecovery || mixinApplication is ParserRecovery) {
library.endNestedDeclaration("<syntax-error>");
@@ -1033,7 +1021,7 @@
Object name = pop();
TypeBuilder type = nullIfParserRecovery(pop());
int modifiers = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
if (name is ParserRecovery) {
push(name);
} else {
@@ -1185,7 +1173,7 @@
int charOffset = pop(); // identifier char offset.
int startCharOffset = enumKeyword.charOffset;
Object name = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(enumKeyword.charOffset);
if (name is ParserRecovery) return;
library.addEnum(documentationComment, metadata, name, enumConstantInfos,
@@ -1282,7 +1270,7 @@
addProblem(messageTypedefNotFunction, equals.charOffset, equals.length);
}
}
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(typedefKeyword.charOffset);
library.addFunctionTypeAlias(documentationComment, metadata, name,
typeVariables, functionType, charOffset);
@@ -1305,7 +1293,7 @@
int modifiers = (staticToken != null ? staticMask : 0) |
(covariantToken != null ? covariantMask : 0) |
Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
checkEmpty(beginToken.charOffset);
if (fieldInfos == null) return;
String documentationComment = getDocumentationComment(beginToken);
@@ -1331,7 +1319,7 @@
varFinalOrConst.length);
modifiers &= ~constMask;
}
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
if (fieldInfos == null) return;
String documentationComment = getDocumentationComment(beginToken);
library.addFields(
@@ -1461,7 +1449,7 @@
debugEvent("endPartOf");
int charOffset = popCharOffset();
Object containingLibrary = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
if (hasName) {
library.addPartOf(metadata,
flattenName(containingLibrary, charOffset, uri), null, charOffset);
@@ -1511,7 +1499,7 @@
int charOffset = pop();
Object name = pop();
int modifiers = pop();
- List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
+ List<MetadataBuilder> metadata = pop();
if (name is ParserRecovery) {
library.endNestedDeclaration("<syntax-error>");
return;
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index e2a7840..28b8b90 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -11,7 +11,9 @@
import '../fasta_codes.dart'
show
+ Message,
noLength,
+ templateBadTypeVariableInSupertype,
templateConflictsWithConstructor,
templateConflictsWithFactory,
templateConflictsWithMember,
@@ -28,6 +30,7 @@
KernelClassBuilder,
KernelFieldBuilder,
KernelFunctionBuilder,
+ KernelInvalidTypeBuilder,
KernelLibraryBuilder,
KernelNamedTypeBuilder,
KernelTypeBuilder,
@@ -40,6 +43,8 @@
import '../kernel/kernel_shadow_ast.dart' show ShadowClass;
+import '../kernel/type_algorithms.dart' show Variance, computeVariance;
+
import '../problems.dart' show unexpected, unhandled;
ShadowClass initializeClass(
@@ -144,6 +149,7 @@
scope.forEach(buildBuilders);
constructors.forEach(buildBuilders);
+ supertype = checkSupertype(supertype);
actualCls.supertype =
supertype?.buildSupertype(library, charOffset, fileUri);
if (!isMixinDeclaration &&
@@ -160,6 +166,7 @@
fileUri);
actualCls.supertype = null;
}
+ mixedInType = checkSupertype(mixedInType);
actualCls.mixedInType =
mixedInType?.buildMixedInType(library, charOffset, fileUri);
actualCls.isMixinDeclaration = isMixinDeclaration;
@@ -167,9 +174,10 @@
// compile-time error.
cls.isAbstract = isAbstract;
if (interfaces != null) {
- for (KernelTypeBuilder interface in interfaces) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfaces[i] = checkSupertype(interfaces[i]);
Supertype supertype =
- interface.buildSupertype(library, charOffset, fileUri);
+ interfaces[i].buildSupertype(library, charOffset, fileUri);
if (supertype != null) {
// TODO(ahe): Report an error if supertype is null.
actualCls.implementedTypes.add(supertype);
@@ -234,6 +242,26 @@
return cls;
}
+ KernelTypeBuilder checkSupertype(KernelTypeBuilder supertype) {
+ if (typeVariables == null || supertype == null) return supertype;
+ Message message;
+ for (int i = 0; i < typeVariables.length; ++i) {
+ int variance = computeVariance(typeVariables[i], supertype);
+ if (variance == Variance.contravariant ||
+ variance == Variance.invariant) {
+ message = templateBadTypeVariableInSupertype.withArguments(
+ typeVariables[i].name, supertype.name);
+ library.addProblem(message, charOffset, noLength, fileUri);
+ }
+ }
+ if (message != null) {
+ return new KernelNamedTypeBuilder(supertype.name, null)
+ ..bind(new KernelInvalidTypeBuilder(supertype.name,
+ message.withLocation(fileUri, charOffset, noLength)));
+ }
+ return supertype;
+ }
+
void addSyntheticConstructor(Constructor constructor) {
String name = constructor.name.name;
cls.constructors.add(constructor);
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index fb12c34..3323184 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -396,26 +396,18 @@
void addFields(String documentationComment, List<MetadataBuilder> metadata,
int modifiers, T type, List<FieldInfo> fieldInfos) {
for (FieldInfo info in fieldInfos) {
- String name = info.name;
- int charOffset = info.charOffset;
- int charEndOffset = info.charEndOffset;
- bool hasInitializer = info.initializerTokenForInference != null;
- Token initializerTokenForInference =
+ Token startToken =
type != null || legacyMode ? null : info.initializerTokenForInference;
- if (initializerTokenForInference != null) {
- Token beforeLast = info.beforeLast;
- beforeLast.setNext(new Token.eof(beforeLast.next.offset));
+ if (startToken != null) {
+ // Extract only the tokens for the initializer expression from the
+ // token stream.
+ Token endToken = info.beforeLast;
+ endToken.setNext(new Token.eof(endToken.next.offset));
+ new Token.eof(startToken.previous.offset).setNext(startToken);
}
- addField(
- documentationComment,
- metadata,
- modifiers,
- type,
- name,
- charOffset,
- charEndOffset,
- initializerTokenForInference,
- hasInitializer);
+ bool hasInitializer = info.initializerTokenForInference != null;
+ addField(documentationComment, metadata, modifiers, type, info.name,
+ info.charOffset, info.charEndOffset, startToken, hasInitializer);
}
}
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 4c3b6c9..adffcbd 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -82,6 +82,7 @@
KernelProcedureBuilder,
KernelTypeBuilder,
LibraryBuilder,
+ MemberBuilder,
NamedTypeBuilder,
TypeBuilder;
@@ -947,6 +948,23 @@
ticker.logMs("Checked mixin declaration applications");
}
+ void buildAnnotations() {
+ builders.forEach((Uri uri, LibraryBuilder library) {
+ if (library.loader == this) {
+ library.buildAnnotations();
+ Iterator<Declaration> iterator = library.iterator;
+ while (iterator.moveNext()) {
+ Declaration declaration = iterator.current;
+ if (declaration is ClassBuilder) {
+ declaration.buildAnnotations(library);
+ } else if (declaration is MemberBuilder) {
+ declaration.buildAnnotations(library);
+ }
+ }
+ }
+ });
+ }
+
ClassHierarchyBuilder buildClassHierarchy(
List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
ClassHierarchyBuilder hierarchy = ClassHierarchyBuilder.build(
@@ -1036,17 +1054,17 @@
void transformListPostInference(List<TreeNode> list,
bool transformSetLiterals, bool transformCollections) {
- if (transformSetLiterals) {
- SetLiteralTransformer transformer = setLiteralTransformer ??=
- new SetLiteralTransformer(this,
- transformConst: !target.enableConstantUpdate2018);
+ if (transformCollections) {
+ CollectionTransformer transformer =
+ collectionTransformer ??= new CollectionTransformer(this);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
}
- if (transformCollections) {
- CollectionTransformer transformer =
- collectionTransformer ??= new CollectionTransformer(this);
+ if (transformSetLiterals) {
+ SetLiteralTransformer transformer = setLiteralTransformer ??=
+ new SetLiteralTransformer(this,
+ transformConst: !target.enableConstantUpdate2018);
for (int i = 0; i < list.length; ++i) {
list[i] = list[i].accept(transformer);
}
diff --git a/pkg/front_end/lib/src/fasta/source/stack_listener.dart b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
index db6a7cd..443b623 100644
--- a/pkg/front_end/lib/src/fasta/source/stack_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/stack_listener.dart
@@ -86,8 +86,8 @@
// TODO(ahe): This doesn't belong here. Only implemented by body_builder.dart
// and ast_builder.dart.
- void finishFunction(covariant List<Object> annotations, covariant formals,
- AsyncMarker asyncModifier, covariant body) {
+ void finishFunction(
+ covariant formals, AsyncMarker asyncModifier, covariant body) {
return unsupported("finishFunction", -1, uri);
}
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 6e82a7d..2ca6f77 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -50,18 +50,27 @@
bool enableConstantUpdate2018;
bool enableControlFlowCollections;
+ bool enableExtensionMethods;
+ bool enableNonNullable;
bool enableSetLiterals;
bool enableSpreadCollections;
+ bool enableTripleShift;
TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
: enableConstantUpdate2018 = CompilerContext.current.options
.isExperimentEnabled(ExperimentalFlag.constantUpdate2018),
enableControlFlowCollections = CompilerContext.current.options
.isExperimentEnabled(ExperimentalFlag.controlFlowCollections),
+ enableExtensionMethods = CompilerContext.current.options
+ .isExperimentEnabled(ExperimentalFlag.extensionMethods),
+ enableNonNullable = CompilerContext.current.options
+ .isExperimentEnabled(ExperimentalFlag.nonNullable),
enableSetLiterals = CompilerContext.current.options
.isExperimentEnabled(ExperimentalFlag.setLiterals),
enableSpreadCollections = CompilerContext.current.options
.isExperimentEnabled(ExperimentalFlag.spreadCollections),
+ enableTripleShift = CompilerContext.current.options
+ .isExperimentEnabled(ExperimentalFlag.tripleShift),
super(ticker);
/// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 0229457..0fccb0c 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -21,6 +21,7 @@
AsyncAsIdentifier/example: Fail
AwaitAsIdentifier/example: Fail
AwaitNotAsync/example: Fail
+BadTypeVariableInSupertype/analyzerCode: Fail
BuiltInIdentifierAsType/example: Fail
BuiltInIdentifierInDeclaration/example: Fail
CannotAssignToParenthesizedExpression/example: Fail
@@ -101,7 +102,6 @@
ContinueWithoutLabelInCase/script1: Fail
CouldNotParseUri/analyzerCode: Fail
CouldNotParseUri/example: Fail
-CovariantAfterVar/script1: Fail
CovariantAndStatic/script1: Fail
CovariantAndStatic/script2: Fail
CovariantMember/script1: Fail
@@ -359,7 +359,6 @@
SpreadMapEntryTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
SpreadTypeMismatch/analyzerCode: Fail # There's no analyzer code for that error yet.
StackOverflow/example: Fail
-StaticAfterConst/script1: Fail
SuperAsExpression/example: Fail
SuperAsIdentifier/example: Fail
SuperNullAware/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 42b24b6..8f1b921 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -208,7 +208,7 @@
bytes: [255]
ExperimentNotEnabled:
- index: 93
+ index: 48
template: "This requires the '#string' experiment to be enabled."
tip: "Try enabling this experiment by adding it to the command line when compiling and running."
analyzerCode: ParserErrorCode.EXPERIMENT_NOT_ENABLED
@@ -236,7 +236,7 @@
}
ExpectedElseOrComma:
- index: 94
+ index: 46
template: "Expected 'else' or comma."
analyzerCode: ParserErrorCode.EXPECTED_ELSE_OR_COMMA
@@ -413,10 +413,10 @@
class A implements FutureOr<int> {}
ExpectedClassOrMixinBody:
- template: "Expected a class or mixin body, but got '#lexeme'."
- analyzerCode: MISSING_CLASS_BODY
-
-ExpectedClassBodyToSkip: ExpectedClassOrMixinBody
+ index: 8
+ template: "A #string must have a body, even if it is empty."
+ tip: "Try adding an empty body."
+ analyzerCode: ParserErrorCode.EXPECTED_BODY
ExpectedDeclaration:
template: "Expected a declaration, but got '#lexeme'."
@@ -618,6 +618,11 @@
analyzerCode: ParserErrorCode.MODIFIER_OUT_OF_ORDER
script:
- "class C { factory const C() = prefix.B.foo; }"
+ - "class C { factory external C(); }"
+ - "class C { const external C(); }"
+ - "class C { static external f(); }"
+ - "class C { final static int f = 5; }"
+ - "class C { var static f; }"
TypeBeforeFactory:
index: 57
@@ -642,14 +647,6 @@
script:
- "class C { const m() {} }"
-CovariantAfterVar:
- index: 8
- template: "The modifier 'covariant' should be before the modifier 'var'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.COVARIANT_AFTER_VAR
- script:
- - "var covariant f;"
-
CovariantAndStatic:
index: 66
template: "Members can't be declared to be both 'covariant' and 'static'."
@@ -671,30 +668,6 @@
- "class C { static static var m; }"
- "class C { var var m; }"
-ExternalAfterConst:
- index: 46
- template: "The modifier 'external' should be before the modifier 'const'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.EXTERNAL_AFTER_CONST
- script:
- - "class C { const external C(); }"
-
-ExternalAfterFactory:
- index: 47
- template: "The modifier 'external' should be before the modifier 'factory'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.EXTERNAL_AFTER_FACTORY
- script:
- - "class C { factory external C(); }"
-
-ExternalAfterStatic:
- index: 48
- template: "The modifier 'external' should be before the modifier 'static'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.EXTERNAL_AFTER_STATIC
- script:
- - "class C { static external f(); }"
-
ExternalConstructorWithBody:
index: 87
template: "External constructors can't have a body."
@@ -809,30 +782,6 @@
- "class C { final var x = 5; }"
- "class C { var final x = 5; }"
-StaticAfterConst:
- index: 20
- template: "The modifier 'static' should be before the modifier 'const'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.STATIC_AFTER_CONST
- script:
- - "class C { const static int f; }"
-
-StaticAfterFinal:
- index: 19
- template: "The modifier 'static' should be before the modifier 'final'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.STATIC_AFTER_FINAL
- script:
- - "class C { final static int f = 5; }"
-
-StaticAfterVar:
- index: 18
- template: "The modifier 'static' should be before the modifier 'var'."
- tip: "Try re-ordering the modifiers."
- analyzerCode: ParserErrorCode.STATIC_AFTER_VAR
- script:
- - "class C { var static f; }"
-
StaticConstructor:
index: 4
template: "Constructors can't be static."
@@ -1043,7 +992,7 @@
}
StackOverflow:
- index: 91
+ index: 19
template: "The file has too many nested expressions or statements."
tip: "Try simplifying the code."
analyzerCode: ParserErrorCode.STACK_OVERFLOW
@@ -1165,10 +1114,6 @@
template: "Abstract methods can't use 'async', 'async*', or 'sync*'."
analyzerCode: NON_SYNC_ABSTRACT_METHOD
-AsyncAsIdentifier:
- analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
- template: "'async' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
-
AwaitAsIdentifier:
template: "'await' can't be used as an identifier in 'async', 'async*', or 'sync*' methods."
analyzerCode: ASYNC_KEYWORD_USED_AS_IDENTIFIER
@@ -1226,7 +1171,7 @@
analyzerCode: YIELD_IN_NON_GENERATOR
OnlyTry:
- index: 92
+ index: 20
template: "A try block must be followed by an 'on', 'catch', or 'finally' clause."
tip: "Try adding either a catch or finally clause, or remove the try statement."
analyzerCode: ParserErrorCode.MISSING_CATCH_OR_FINALLY
@@ -1294,7 +1239,7 @@
- "try {} catch (e, s, x) {}"
SuperNullAware:
- index: 90
+ index: 18
template: "The operator '?.' cannot be used with 'super' because 'super' cannot be null."
tip: "Try replacing '?.' with '.'"
analyzerCode: ParserErrorCode.INVALID_OPERATOR_QUESTIONMARK_PERIOD_FOR_SUPER
@@ -2542,7 +2487,7 @@
tip: "Normally, the specification is a file named 'libraries.json' in the Dart SDK install location."
InvalidSuperInInitializer:
- index: 95
+ index: 47
template: "Can only use 'super' in an initializer for calling the superclass constructor (e.g. 'super()' or 'super.namedConstructor()')"
analyzerCode: ParserErrorCode.INVALID_SUPER_IN_INITIALIZER
@@ -3612,3 +3557,9 @@
main() {
<int>[...null];
}
+
+BadTypeVariableInSupertype:
+ template: "Found unsupported uses of '#name' in supertype '#name2'."
+ script: >
+ class A<X> {}
+ class B<Y> extends A<Function(Y)> {}
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index 6987266..7f59d4b 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -241,5 +241,6 @@
"offset: 4, prefixGenerator: , isInitializer: false, isSuper: false)",
new KernelUnexpectedQualifiedUseGenerator(
helper, token, generator, false));
+ return Future<void>.value();
});
}
diff --git a/pkg/front_end/test/fasta/unlinked_scope_test.dart b/pkg/front_end/test/fasta/unlinked_scope_test.dart
index e58294c..fb933f8 100644
--- a/pkg/front_end/test/fasta/unlinked_scope_test.dart
+++ b/pkg/front_end/test/fasta/unlinked_scope_test.dart
@@ -108,5 +108,6 @@
testExpression("unresolved");
testExpression("a + b", "a.+(b)");
testExpression("a = b");
+ return Future<void>.value();
});
}
diff --git a/pkg/front_end/test/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index b5cffb2..a2ec791 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -307,7 +307,6 @@
for (String moduleName in world["modules"]) {
Component moduleComponent = moduleComponents[moduleName];
if (moduleComponent != null) {
- moduleComponent.computeCanonicalNames();
modulesToUse.add(moduleComponent);
}
}
diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart
index 605b5ac..0abc4cb 100644
--- a/pkg/front_end/test/src/base/processed_options_test.dart
+++ b/pkg/front_end/test/src/base/processed_options_test.dart
@@ -22,6 +22,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(ProcessedOptionsTest);
});
+ return Future<void>.value();
});
}
diff --git a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
index 319403e..a04857a 100644
--- a/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_on_enum_values.dart.outline.expect
@@ -11,7 +11,9 @@
final field core::int index;
final field core::String _name;
static const field core::List<self::Foo> values = const <self::Foo>[self::Foo::bar, self::Foo::baz, self::Foo::cafebabe];
+ @self::hest
static const field self::Foo bar = const self::Foo::•(0, "Foo.bar");
+ @self::Fisk::fisk<dynamic>(self::hest)
static const field self::Foo baz = const self::Foo::•(1, "Foo.baz");
static const field self::Foo cafebabe = const self::Foo::•(2, "Foo.cafebabe");
const constructor •(core::int index, core::String _name) → self::Foo
diff --git a/pkg/front_end/testcases/annotation_top.dart.outline.expect b/pkg/front_end/testcases/annotation_top.dart.outline.expect
index 6839b80..579ecba 100644
--- a/pkg/front_end/testcases/annotation_top.dart.outline.expect
+++ b/pkg/front_end/testcases/annotation_top.dart.outline.expect
@@ -1,3 +1,5 @@
+@test::a
+@test::A::•(1)
library test;
import self as self;
import "dart:core" as core;
@@ -8,12 +10,20 @@
const constructor •(core::int value) → self::A
;
}
+@self::a
+@self::A::•(2)
class C extends core::Object {
synthetic constructor •() → self::C
;
}
static const field core::Object a;
+@self::a
+@self::A::•(3)
static field core::int f1;
+@self::a
+@self::A::•(3)
static field core::int f2;
+@self::a
+@self::A::•(4)
static method main() → void
;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
new file mode 100644
index 0000000..3816961
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart
@@ -0,0 +1,87 @@
+// 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.
+
+typedef ContravariantUse<T> = Function(T);
+
+typedef InvariantUse<T> = T Function(T);
+
+class Empty {}
+
+class A<T> {}
+
+class B<T> extends A<Function(T)> {}
+
+class Bc<T> extends A<ContravariantUse<T>> {}
+
+class Bi<T> extends A<InvariantUse<T>> {}
+
+class C<T> implements A<Function(T)> {}
+
+class Cc<T> implements A<ContravariantUse<T>> {}
+
+class Ci<T> implements A<InvariantUse<T>> {}
+
+class D<T> = Object with A<Function(T)>;
+
+class Dc<T> = Object with A<ContravariantUse<T>>;
+
+class Di<T> = Object with A<InvariantUse<T>>;
+
+class E<T> = A<Function(T)> with Empty;
+
+class Ec<T> = A<ContravariantUse<T>> with Empty;
+
+class Ei<T> = A<InvariantUse<T>> with Empty;
+
+class F<T> extends Object with A<Function(T)> {}
+
+class Fc<T> extends Object with A<ContravariantUse<T>> {}
+
+class Fi<T> extends Object with A<InvariantUse<T>> {}
+
+class G<T> extends A<Function(T)> with Empty {}
+
+class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+
+class Gi<T> extends A<InvariantUse<T>> with Empty {}
+
+class Hff<T> extends A<Function(Function(T))> {}
+
+class Hfc<T> extends A<Function(ContravariantUse<T>)> {}
+
+class Hcf<T> extends A<ContravariantUse<Function(T)>> {}
+
+class Hcc<T> extends A<ContravariantUse<ContravariantUse<T>>> {}
+
+class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+
+class Iafc<T> extends A<A<Function(ContravariantUse<T>)>> {}
+
+class Iacf<T> extends A<A<ContravariantUse<Function(T)>>> {}
+
+class Ifac<T> extends A<Function(A<ContravariantUse<T>>)> {}
+
+class Ifca<T> extends A<Function(ContravariantUse<A<T>>)> {}
+
+class Icaf<T> extends A<ContravariantUse<A<Function(T)>>> {}
+
+class Icfa<T> extends A<ContravariantUse<Function(A<T>)>> {}
+
+class Jfff<T> extends A<Function(Function(Function(T)))> {}
+
+class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+
+class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+
+class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+
+class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+
+class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+
+class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+
+class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
new file mode 100644
index 0000000..060d1ab
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.hierarchy.expect
@@ -0,0 +1,917 @@
+Object:
+ superclasses:
+ interfaces:
+ classMembers:
+ Object._haveSameRuntimeType
+ Object.toString
+ Object.runtimeType
+ Object._toString
+ Object._simpleInstanceOf
+ Object._hashCodeRnd
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._objectHashCode
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Empty:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+B:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Bc:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Bi:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+C:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Cc:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Ci:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+D:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Dc:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Di:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+E:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Ec:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Ei:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Object with A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+F:
+ superclasses:
+ Object
+ -> _F&Object&A<T>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Object with A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Fc:
+ superclasses:
+ Object
+ -> _Fc&Object&A<T>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Object with A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Fi:
+ superclasses:
+ Object
+ -> _Fi&Object&A<T>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+A with Empty:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+G:
+ Longest path to Object: 3
+ superclasses:
+ A
+ -> _G&A&Empty<T>
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+A with Empty:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Gc:
+ Longest path to Object: 3
+ superclasses:
+ A
+ -> _Gc&A&Empty<T>
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+A with Empty:
+ Longest path to Object: 2
+ superclasses:
+ A
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Gi:
+ Longest path to Object: 3
+ superclasses:
+ A
+ -> _Gi&A&Empty<T>
+ interfaces: Empty, Object
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+ interfaceMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ interfaceSetters:
+
+Hff:
+ superclasses:
+ Object
+ -> A<(null) -> null>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Hfc:
+ superclasses:
+ Object
+ -> A<(null) -> null>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Hcf:
+ superclasses:
+ Object
+ -> A<ContravariantUse<(null) -> null>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Hcc:
+ superclasses:
+ Object
+ -> A<ContravariantUse<ContravariantUse<T>>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Hii:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Iafc:
+ superclasses:
+ Object
+ -> A<A<(null) -> null>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Iacf:
+ superclasses:
+ Object
+ -> A<A<ContravariantUse<(null) -> null>>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Ifac:
+ superclasses:
+ Object
+ -> A<(null) -> null>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Ifca:
+ superclasses:
+ Object
+ -> A<(null) -> null>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Icaf:
+ superclasses:
+ Object
+ -> A<ContravariantUse<A<(null) -> null>>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Icfa:
+ superclasses:
+ Object
+ -> A<ContravariantUse<(null) -> null>>
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jfff:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jffc:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jfcf:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jfcc:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jcff:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jcfc:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jccf:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+Jccc:
+ superclasses:
+ A
+ interfaces:
+ classMembers:
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+ synthetic constructor •() → self::Empty
+ : super core::Object::•()
+ ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bc<self::Bc::T>
+ : super core::Object::•()
+ ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bi<self::Bi::T>
+ : super core::Object::•()
+ ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Cc<self::Cc::T>
+ : super core::Object::•()
+ ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Ci<self::Ci::T>
+ : super core::Object::•()
+ ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::D<self::D::T>
+ : super core::Object::•()
+ ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Dc<self::Dc::T>
+ : super core::Object::•()
+ ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Di<self::Di::T>
+ : super core::Object::•()
+ ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::E<self::E::T>
+ : super core::Object::•()
+ ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ec<self::Ec::T>
+ : super core::Object::•()
+ ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ei<self::Ei::T>
+ : super core::Object::•()
+ ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+ synthetic constructor •() → self::F<self::F::T>
+ : super self::_F&Object&A::•()
+ ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+ synthetic constructor •() → self::Fc<self::Fc::T>
+ : super self::_Fc&Object&A::•()
+ ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+ synthetic constructor •() → self::Fi<self::Fi::T>
+ : super self::_Fi&Object&A::•()
+ ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+ synthetic constructor •() → self::G<self::G::T>
+ : super self::_G&A&Empty::•()
+ ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+ synthetic constructor •() → self::Gc<self::Gc::T>
+ : super self::_Gc&A&Empty::•()
+ ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+ synthetic constructor •() → self::Gi<self::Gi::T>
+ : super self::_Gi&A&Empty::•()
+ ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hff<self::Hff::T>
+ : super self::A::•()
+ ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hfc<self::Hfc::T>
+ : super self::A::•()
+ ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcf<self::Hcf::T>
+ : super self::A::•()
+ ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcc<self::Hcc::T>
+ : super self::A::•()
+ ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Hii<self::Hii::T>
+ : super core::Object::•()
+ ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iafc<self::Iafc::T>
+ : super self::A::•()
+ ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iacf<self::Iacf::T>
+ : super self::A::•()
+ ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Ifac<self::Ifac::T>
+ : super self::A::•()
+ ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Ifca<self::Ifca::T>
+ : super self::A::•()
+ ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Icaf<self::Icaf::T>
+ : super self::A::•()
+ ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Icfa<self::Icfa::T>
+ : super self::A::•()
+ ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfff<self::Jfff::T>
+ : super core::Object::•()
+ ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jffc<self::Jffc::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+ : super core::Object::•()
+ ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcff<self::Jcff::T>
+ : super core::Object::•()
+ ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+ : super core::Object::•()
+ ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccf<self::Jccf::T>
+ : super core::Object::•()
+ ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccc<self::Jccc::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.legacy.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+ synthetic constructor •() → self::Empty
+ : super core::Object::•()
+ ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bc<self::Bc::T>
+ : super core::Object::•()
+ ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bi<self::Bi::T>
+ : super core::Object::•()
+ ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Cc<self::Cc::T>
+ : super core::Object::•()
+ ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Ci<self::Ci::T>
+ : super core::Object::•()
+ ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::D<self::D::T>
+ : super core::Object::•()
+ ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Dc<self::Dc::T>
+ : super core::Object::•()
+ ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Di<self::Di::T>
+ : super core::Object::•()
+ ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::E<self::E::T>
+ : super core::Object::•()
+ ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::Ec<self::Ec::T>
+ : super core::Object::•()
+ ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::Ei<self::Ei::T>
+ : super core::Object::•()
+ ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+ synthetic constructor •() → self::F<self::F::T>
+ : super self::_F&Object&A::•()
+ ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+ synthetic constructor •() → self::Fc<self::Fc::T>
+ : super self::_Fc&Object&A::•()
+ ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+ synthetic constructor •() → self::Fi<self::Fi::T>
+ : super self::_Fi&Object&A::•()
+ ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+ synthetic constructor •() → self::G<self::G::T>
+ : super self::_G&A&Empty::•()
+ ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+ synthetic constructor •() → self::Gc<self::Gc::T>
+ : super self::_Gc&A&Empty::•()
+ ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+ synthetic constructor •() → self::Gi<self::Gi::T>
+ : super self::_Gi&A&Empty::•()
+ ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hff<self::Hff::T>
+ : super self::A::•()
+ ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hfc<self::Hfc::T>
+ : super self::A::•()
+ ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcf<self::Hcf::T>
+ : super self::A::•()
+ ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcc<self::Hcc::T>
+ : super self::A::•()
+ ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Hii<self::Hii::T>
+ : super core::Object::•()
+ ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iafc<self::Iafc::T>
+ : super self::A::•()
+ ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iacf<self::Iacf::T>
+ : super self::A::•()
+ ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Ifac<self::Ifac::T>
+ : super self::A::•()
+ ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Ifca<self::Ifca::T>
+ : super self::A::•()
+ ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Icaf<self::Icaf::T>
+ : super self::A::•()
+ ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Icfa<self::Icfa::T>
+ : super self::A::•()
+ ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfff<self::Jfff::T>
+ : super core::Object::•()
+ ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jffc<self::Jffc::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+ : super core::Object::•()
+ ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcff<self::Jcff::T>
+ : super core::Object::•()
+ ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+ : super core::Object::•()
+ ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccf<self::Jccf::T>
+ : super core::Object::•()
+ ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccc<self::Jccc::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
new file mode 100644
index 0000000..86bc0e3
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.outline.expect
@@ -0,0 +1,305 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+ synthetic constructor •() → self::Empty
+ ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bc<self::Bc::T>
+ ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bi<self::Bi::T>
+ ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Cc<self::Cc::T>
+ ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Ci<self::Ci::T>
+ ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::D<self::D::T>
+ : super core::Object::•()
+ ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Dc<self::Dc::T>
+ : super core::Object::•()
+ ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Di<self::Di::T>
+ : super core::Object::•()
+ ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::E<self::E::T>
+ ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ec<self::Ec::T>
+ ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ei<self::Ei::T>
+ ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+ synthetic constructor •() → self::F<self::F::T>
+ ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+ synthetic constructor •() → self::Fc<self::Fc::T>
+ ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+ synthetic constructor •() → self::Fi<self::Fi::T>
+ ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+ ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+ synthetic constructor •() → self::G<self::G::T>
+ ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+ ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+ synthetic constructor •() → self::Gc<self::Gc::T>
+ ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+ ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+ synthetic constructor •() → self::Gi<self::Gi::T>
+ ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hff<self::Hff::T>
+ ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hfc<self::Hfc::T>
+ ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcf<self::Hcf::T>
+ ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcc<self::Hcc::T>
+ ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Hii<self::Hii::T>
+ ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iafc<self::Iafc::T>
+ ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iacf<self::Iacf::T>
+ ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Ifac<self::Ifac::T>
+ ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Ifca<self::Ifca::T>
+ ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Icaf<self::Icaf::T>
+ ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Icfa<self::Icfa::T>
+ ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfff<self::Jfff::T>
+ ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jffc<self::Jffc::T>
+ ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+ ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+ ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcff<self::Jcff::T>
+ ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+ ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccf<self::Jccf::T>
+ ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccc<self::Jccc::T>
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
new file mode 100644
index 0000000..74cdea4
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+ synthetic constructor •() → self::Empty
+ : super core::Object::•()
+ ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bc<self::Bc::T>
+ : super core::Object::•()
+ ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bi<self::Bi::T>
+ : super core::Object::•()
+ ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Cc<self::Cc::T>
+ : super core::Object::•()
+ ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Ci<self::Ci::T>
+ : super core::Object::•()
+ ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::D<self::D::T>
+ : super core::Object::•()
+ ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Dc<self::Dc::T>
+ : super core::Object::•()
+ ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Di<self::Di::T>
+ : super core::Object::•()
+ ;
+}
+class E<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::E<self::E::T>
+ : super core::Object::•()
+ ;
+}
+class Ec<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ec<self::Ec::T>
+ : super core::Object::•()
+ ;
+}
+class Ei<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::Ei<self::Ei::T>
+ : super core::Object::•()
+ ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+ synthetic constructor •() → self::F<self::F::T>
+ : super self::_F&Object&A::•()
+ ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+ synthetic constructor •() → self::Fc<self::Fc::T>
+ : super self::_Fc&Object&A::•()
+ ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+ synthetic constructor •() → self::Fi<self::Fi::T>
+ : super self::_Fi&Object&A::•()
+ ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+ synthetic constructor •() → self::G<self::G::T>
+ : super self::_G&A&Empty::•()
+ ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+ synthetic constructor •() → self::Gc<self::Gc::T>
+ : super self::_Gc&A&Empty::•()
+ ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> = core::Object with self::Empty {
+ synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+ synthetic constructor •() → self::Gi<self::Gi::T>
+ : super self::_Gi&A&Empty::•()
+ ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hff<self::Hff::T>
+ : super self::A::•()
+ ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hfc<self::Hfc::T>
+ : super self::A::•()
+ ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcf<self::Hcf::T>
+ : super self::A::•()
+ ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcc<self::Hcc::T>
+ : super self::A::•()
+ ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Hii<self::Hii::T>
+ : super core::Object::•()
+ ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iafc<self::Iafc::T>
+ : super self::A::•()
+ ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iacf<self::Iacf::T>
+ : super self::A::•()
+ ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Ifac<self::Ifac::T>
+ : super self::A::•()
+ ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Ifca<self::Ifca::T>
+ : super self::A::•()
+ ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Icaf<self::Icaf::T>
+ : super self::A::•()
+ ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Icfa<self::Icfa::T>
+ : super self::A::•()
+ ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfff<self::Jfff::T>
+ : super core::Object::•()
+ ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jffc<self::Jffc::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+ : super core::Object::•()
+ ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcff<self::Jcff::T>
+ : super core::Object::•()
+ ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+ : super core::Object::•()
+ ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccf<self::Jccf::T>
+ : super core::Object::•()
+ ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccc<self::Jccc::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
new file mode 100644
index 0000000..87ac80d7
--- /dev/null
+++ b/pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart.strong.transformed.expect
@@ -0,0 +1,343 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> extends A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:15:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bc<T> extends A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:17:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Bi<T> extends A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:19:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class C<T> implements A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:21:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Cc<T> implements A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:23:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ci<T> implements A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:25:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class D<T> = Object with A<Function(T)>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:27:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Dc<T> = Object with A<ContravariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:29:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Di<T> = Object with A<InvariantUse<T>>;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:31:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class E<T> = A<Function(T)> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:33:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ec<T> = A<ContravariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:35:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Ei<T> = A<InvariantUse<T>> with Empty;
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:37:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class F<T> extends Object with A<Function(T)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:39:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fc<T> extends Object with A<ContravariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:41:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Fi<T> extends Object with A<InvariantUse<T>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:43:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class G<T> extends A<Function(T)> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:45:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gc<T> extends A<ContravariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:47:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Gi<T> extends A<InvariantUse<T>> with Empty {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:57:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Hii<T> extends A<InvariantUse<InvariantUse<T>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:71:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfff<T> extends A<Function(Function(Function(T)))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:73:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jffc<T> extends A<Function(Function(ContravariantUse<T>))> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:75:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcf<T> extends A<Function(ContravariantUse<Function(T)>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:77:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jfcc<T> extends A<Function(ContravariantUse<ContravariantUse<T>>)> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:79:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcff<T> extends A<ContravariantUse<Function(Function(T))>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:81:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jcfc<T> extends A<ContravariantUse<Function(ContravariantUse<T>)>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:83:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccf<T> extends A<ContravariantUse<ContravariantUse<Function(T)>>> {}
+// ^
+//
+// pkg/front_end/testcases/bad_type_variable_uses_in_supertypes.dart:85:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class Jccc<T> extends A<ContravariantUse<ContravariantUse<ContravariantUse<T>>>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef ContravariantUse<T extends core::Object = dynamic> = (T) → dynamic;
+typedef InvariantUse<T extends core::Object = dynamic> = (T) → T;
+class Empty extends core::Object {
+ synthetic constructor •() → self::Empty
+ : super core::Object::•()
+ ;
+}
+class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+}
+class Bc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bc<self::Bc::T>
+ : super core::Object::•()
+ ;
+}
+class Bi<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Bi<self::Bi::T>
+ : super core::Object::•()
+ ;
+}
+class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+class Cc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Cc<self::Cc::T>
+ : super core::Object::•()
+ ;
+}
+class Ci<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Ci<self::Ci::T>
+ : super core::Object::•()
+ ;
+}
+class D<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::D<self::D::T>
+ : super core::Object::•()
+ ;
+}
+class Dc<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Dc<self::Dc::T>
+ : super core::Object::•()
+ ;
+}
+class Di<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::Di<self::Di::T>
+ : super core::Object::•()
+ ;
+}
+class E<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::E<self::E::T>
+ : super core::Object::•()
+ ;
+}
+class Ec<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::Ec<self::Ec::T>
+ : super core::Object::•()
+ ;
+}
+class Ei<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::Ei<self::Ei::T>
+ : super core::Object::•()
+ ;
+}
+abstract class _F&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_F&Object&A<self::_F&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class F<T extends core::Object = dynamic> extends self::_F&Object&A<self::F::T> {
+ synthetic constructor •() → self::F<self::F::T>
+ : super self::_F&Object&A::•()
+ ;
+}
+abstract class _Fc&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fc&Object&A<self::_Fc&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fc<T extends core::Object = dynamic> extends self::_Fc&Object&A<self::Fc::T> {
+ synthetic constructor •() → self::Fc<self::Fc::T>
+ : super self::_Fc&Object&A::•()
+ ;
+}
+abstract class _Fi&Object&A<T extends core::Object = dynamic> extends core::Object {
+ const synthetic constructor •() → self::_Fi&Object&A<self::_Fi&Object&A::T>
+ : super core::Object::•()
+ ;
+}
+class Fi<T extends core::Object = dynamic> extends self::_Fi&Object&A<self::Fi::T> {
+ synthetic constructor •() → self::Fi<self::Fi::T>
+ : super self::_Fi&Object&A::•()
+ ;
+}
+abstract class _G&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_G&A&Empty<self::_G&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class G<T extends core::Object = dynamic> extends self::_G&A&Empty<self::G::T> {
+ synthetic constructor •() → self::G<self::G::T>
+ : super self::_G&A&Empty::•()
+ ;
+}
+abstract class _Gc&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_Gc&A&Empty<self::_Gc&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gc<T extends core::Object = dynamic> extends self::_Gc&A&Empty<self::Gc::T> {
+ synthetic constructor •() → self::Gc<self::Gc::T>
+ : super self::_Gc&A&Empty::•()
+ ;
+}
+abstract class _Gi&A&Empty<T extends core::Object = dynamic> extends core::Object implements self::Empty {
+ synthetic constructor •() → self::_Gi&A&Empty<self::_Gi&A&Empty::T>
+ : super core::Object::•()
+ ;
+}
+class Gi<T extends core::Object = dynamic> extends self::_Gi&A&Empty<self::Gi::T> {
+ synthetic constructor •() → self::Gi<self::Gi::T>
+ : super self::_Gi&A&Empty::•()
+ ;
+}
+class Hff<T extends core::Object = dynamic> extends self::A<((self::Hff::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hff<self::Hff::T>
+ : super self::A::•()
+ ;
+}
+class Hfc<T extends core::Object = dynamic> extends self::A<((self::Hfc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hfc<self::Hfc::T>
+ : super self::A::•()
+ ;
+}
+class Hcf<T extends core::Object = dynamic> extends self::A<((self::Hcf::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcf<self::Hcf::T>
+ : super self::A::•()
+ ;
+}
+class Hcc<T extends core::Object = dynamic> extends self::A<((self::Hcc::T) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Hcc<self::Hcc::T>
+ : super self::A::•()
+ ;
+}
+class Hii<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Hii<self::Hii::T>
+ : super core::Object::•()
+ ;
+}
+class Iafc<T extends core::Object = dynamic> extends self::A<self::A<((self::Iafc::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iafc<self::Iafc::T>
+ : super self::A::•()
+ ;
+}
+class Iacf<T extends core::Object = dynamic> extends self::A<self::A<((self::Iacf::T) → dynamic) → dynamic>> {
+ synthetic constructor •() → self::Iacf<self::Iacf::T>
+ : super self::A::•()
+ ;
+}
+class Ifac<T extends core::Object = dynamic> extends self::A<(self::A<(self::Ifac::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Ifac<self::Ifac::T>
+ : super self::A::•()
+ ;
+}
+class Ifca<T extends core::Object = dynamic> extends self::A<((self::A<self::Ifca::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Ifca<self::Ifca::T>
+ : super self::A::•()
+ ;
+}
+class Icaf<T extends core::Object = dynamic> extends self::A<(self::A<(self::Icaf::T) → dynamic>) → dynamic> {
+ synthetic constructor •() → self::Icaf<self::Icaf::T>
+ : super self::A::•()
+ ;
+}
+class Icfa<T extends core::Object = dynamic> extends self::A<((self::A<self::Icfa::T>) → dynamic) → dynamic> {
+ synthetic constructor •() → self::Icfa<self::Icfa::T>
+ : super self::A::•()
+ ;
+}
+class Jfff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfff<self::Jfff::T>
+ : super core::Object::•()
+ ;
+}
+class Jffc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jffc<self::Jffc::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcf<self::Jfcf::T>
+ : super core::Object::•()
+ ;
+}
+class Jfcc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jfcc<self::Jfcc::T>
+ : super core::Object::•()
+ ;
+}
+class Jcff<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcff<self::Jcff::T>
+ : super core::Object::•()
+ ;
+}
+class Jcfc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jcfc<self::Jcfc::T>
+ : super core::Object::•()
+ ;
+}
+class Jccf<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccf<self::Jccf::T>
+ : super core::Object::•()
+ ;
+}
+class Jccc<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::Jccc<self::Jccc::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/bug33099.dart.outline.expect b/pkg/front_end/testcases/bug33099.dart.outline.expect
index 42a5b20..24e4823 100644
--- a/pkg/front_end/testcases/bug33099.dart.outline.expect
+++ b/pkg/front_end/testcases/bug33099.dart.outline.expect
@@ -12,6 +12,7 @@
class MyTest extends core::Object {
synthetic constructor •() → self::MyTest
;
+ @self::failingTest
method foo() → void
;
}
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
index 459d870..6ddb363 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations.dart.outline.expect
@@ -8,10 +8,12 @@
const constructor named(core::List<core::String> l) → self::Foo
;
}
+@self::Foo::•(const <dynamic>[])
class Bar extends core::Object {
synthetic constructor •() → self::Bar
;
}
+@self::Foo::named(const <dynamic>[])
class Baz extends core::Object {
synthetic constructor •() → self::Baz
;
diff --git a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
index b4da95f..62d5559 100644
--- a/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/downwards_inference_annotations_class_members.dart.outline.expect
@@ -7,9 +7,12 @@
;
}
abstract class Bar extends core::Object {
+ @self::Foo::•(const <dynamic>[])
field dynamic x;
+ @self::Foo::•(const <dynamic>[])
constructor •() → self::Bar
;
+ @self::Foo::•(const <dynamic>[])
abstract method f() → void;
}
static method main() → dynamic
diff --git a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
index bf42edb..41bfd6e 100644
--- a/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/override_equals.dart.outline.expect
@@ -5,6 +5,7 @@
class NullEquality extends core::Object {
synthetic constructor •() → self::NullEquality
;
+ @core::override
operator ==(core::Object other) → core::Null
;
}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart b/pkg/front_end/testcases/interface_contravariant_from_class.dart
similarity index 93%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
rename to pkg/front_end/testcases/interface_contravariant_from_class.dart
index fc4ec48..0b50e14 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.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.
-/*@testedFeatures=checks*/
library test;
typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
similarity index 79%
copy from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
copy to pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
index 6f7dc10..c84fdc2 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.hierarchy.expect
@@ -56,11 +56,9 @@
C:
superclasses:
- Object
- -> B<F<T>>
- interfaces: I<F<T>>
+ B
+ interfaces:
classMembers:
- B.f
Object.toString
Object.runtimeType
Object._simpleInstanceOf
@@ -72,16 +70,3 @@
Object._simpleInstanceOfTrue
Object.==
classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
new file mode 100644
index 0000000..31e0650
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ ;
+ method f(core::int x) → self::B::T
+ ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ ;
+ abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..cc045f3
--- /dev/null
+++ b/pkg/front_end/testcases/interface_contravariant_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_contravariant_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f(core::int x) → self::B::T {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f(core::Object x) → self::I::T;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart
similarity index 93%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
rename to pkg/front_end/testcases/interface_covariantImpl_from_class.dart
index bf9a66b..a06fc2d 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.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.
-/*@testedFeatures=checks*/
library test;
typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
similarity index 79%
copy from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
copy to pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
index 6f7dc10..c84fdc2 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.hierarchy.expect
@@ -56,11 +56,9 @@
C:
superclasses:
- Object
- -> B<F<T>>
- interfaces: I<F<T>>
+ B
+ interfaces:
classMembers:
- B.f
Object.toString
Object.runtimeType
Object._simpleInstanceOf
@@ -72,16 +70,3 @@
Object._simpleInstanceOfTrue
Object.==
classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
new file mode 100644
index 0000000..3e3646c
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.outline.expect
@@ -0,0 +1,33 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ ;
+ method f((self::B::T) → void x, core::int y) → void
+ ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..b886daa
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantImpl_from_class.dart.strong.transformed.expect
@@ -0,0 +1,34 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantImpl_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart
similarity index 94%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
rename to pkg/front_end/testcases/interface_covariantInterface_from_class.dart
index 3b2bac1..010f354 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.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.
-/*@testedFeatures=checks*/
library test;
typedef void F<T>(T t);
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
similarity index 94%
rename from pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
rename to pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
index 6f7dc10..c43a8c7 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.hierarchy.expect
@@ -18,6 +18,24 @@
Object.==
classSetters:
+A:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ A.f
+ Object.toString
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
B:
superclasses:
Object
@@ -56,11 +74,9 @@
C:
superclasses:
- Object
- -> B<F<T>>
- interfaces: I<F<T>>
+ B
+ interfaces:
classMembers:
- B.f
Object.toString
Object.runtimeType
Object._simpleInstanceOf
@@ -72,16 +88,3 @@
Object._simpleInstanceOfTrue
Object.==
classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+ abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.legacy.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+ abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
new file mode 100644
index 0000000..c7028ce
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.outline.expect
@@ -0,0 +1,46 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ ;
+ abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ ;
+ method f((self::B::T) → void x, core::int y) → void
+ ;
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ ;
+}
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+ abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
new file mode 100644
index 0000000..e275052
--- /dev/null
+++ b/pkg/front_end/testcases/interface_covariantInterface_from_class.dart.strong.transformed.expect
@@ -0,0 +1,48 @@
+library test;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:13:7: Error: Found unsupported uses of 'T' in supertype 'A'.
+// class B<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:17:16: Error: Found unsupported uses of 'T' in supertype 'A'.
+// abstract class I<T> implements A<F<T>> {
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'B'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+// pkg/front_end/testcases/interface_covariantInterface_from_class.dart:21:16: Error: Found unsupported uses of 'T' in supertype 'I'.
+// abstract class C<T> extends B<F<T>> implements I<F<T>> {}
+// ^
+//
+import self as self;
+import "dart:core" as core;
+
+typedef F<T extends core::Object = dynamic> = (T) → void;
+abstract class A<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::A<self::A::T>
+ : super core::Object::•()
+ ;
+ abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
+}
+class B<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::B<self::B::T>
+ : super core::Object::•()
+ ;
+ method f((self::B::T) → void x, core::int y) → void {}
+}
+abstract class I<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::I<self::I::T>
+ : super core::Object::•()
+ ;
+ abstract method f((self::I::T) → void x, core::Object y) → void;
+}
+abstract class C<T extends core::Object = dynamic> extends core::Object {
+ synthetic constructor •() → self::C<self::C::T>
+ : super core::Object::•()
+ ;
+}
+static method main() → void {}
diff --git a/pkg/front_end/testcases/issue37027.dart b/pkg/front_end/testcases/issue37027.dart
new file mode 100644
index 0000000..385e2a4
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart
@@ -0,0 +1,9 @@
+// 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.
+class C {
+ final Set<int> s;
+ C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/issue37027.dart.hierarchy.expect b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
new file mode 100644
index 0000000..d7772a1
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.hierarchy.expect
@@ -0,0 +1,37 @@
+Object:
+ superclasses:
+ interfaces:
+ classMembers:
+ Object._haveSameRuntimeType
+ Object.toString
+ Object.runtimeType
+ Object._toString
+ Object._simpleInstanceOf
+ Object._hashCodeRnd
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._objectHashCode
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
+
+C:
+ superclasses:
+ Object
+ interfaces:
+ classMembers:
+ Object.toString
+ C.s
+ Object.runtimeType
+ Object._simpleInstanceOf
+ Object._instanceOf
+ Object.noSuchMethod
+ Object._identityHashCode
+ Object.hashCode
+ Object._simpleInstanceOfFalse
+ Object._simpleInstanceOfTrue
+ Object.==
+ classSetters:
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.expect b/pkg/front_end/testcases/issue37027.dart.legacy.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+// C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+// ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+// C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+ final field core::Set<core::int> s;
+ constructor •(core::List<core::int> ell) → self::C
+ : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
new file mode 100644
index 0000000..653b194
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.legacy.transformed.expect
@@ -0,0 +1,22 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue37027.dart:6:46: Error: Unexpected token 'if'.
+// C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+// ^^
+//
+// pkg/front_end/testcases/issue37027.dart:6:27: Error: Unexpected token 'for'.
+// C(List<int> ell) : s = {for (var e in ell) if (e.isOdd) 2 * e};
+// ^^^
+//
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+ final field core::Set<core::int> s;
+ constructor •(core::List<core::int> ell) → self::C
+ : self::C::s = <dynamic, dynamic>{}, super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.outline.expect b/pkg/front_end/testcases/issue37027.dart.outline.expect
new file mode 100644
index 0000000..dc4999b
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.outline.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+ final field core::Set<core::int> s;
+ constructor •(core::List<core::int> ell) → self::C
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.expect b/pkg/front_end/testcases/issue37027.dart.strong.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+ final field core::Set<core::int> s;
+ constructor •(core::List<core::int> ell) → self::C
+ : self::C::s = block {
+ final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+ for (core::int e in ell)
+ if(e.{core::int::isOdd})
+ #t1.{core::Set::add}(2.{core::num::*}(e));
+ } =>#t1, super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
new file mode 100644
index 0000000..2387135
--- /dev/null
+++ b/pkg/front_end/testcases/issue37027.dart.strong.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+import "dart:collection" as col;
+
+class C extends core::Object {
+ final field core::Set<core::int> s;
+ constructor •(core::List<core::int> ell) → self::C
+ : self::C::s = block {
+ final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>();
+ for (core::int e in ell)
+ if(e.{core::int::isOdd})
+ #t1.{core::Set::add}(2.{core::num::*}(e));
+ } =>#t1, super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/metadata_enum.dart.outline.expect b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
index 6fd993b..1ecf0f8 100644
--- a/pkg/front_end/testcases/metadata_enum.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_enum.dart.outline.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
+@self::a
class E extends core::Object {
final field core::int index;
final field core::String _name;
diff --git a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
index cec02ba..ec64387 100644
--- a/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
+++ b/pkg/front_end/testcases/metadata_named_mixin_application.dart.outline.expect
@@ -2,6 +2,7 @@
import self as self;
import "dart:core" as core;
+@self::a
class C = self::D with self::E {
synthetic constructor •() → self::C
: super self::D::•()
diff --git a/pkg/front_end/testcases/native_as_name.dart.outline.expect b/pkg/front_end/testcases/native_as_name.dart.outline.expect
index 6c2884c..b78f8ae 100644
--- a/pkg/front_end/testcases/native_as_name.dart.outline.expect
+++ b/pkg/front_end/testcases/native_as_name.dart.outline.expect
@@ -21,6 +21,7 @@
class Y2 extends self::Y1 {
synthetic constructor •() → self::Y2
;
+ @core::override
get native() → core::String
;
}
diff --git a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
index 9051099..cc16f53 100644
--- a/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
+++ b/pkg/front_end/testcases/override_check_generic_method_f_bounded.dart.outline.expect
@@ -14,6 +14,7 @@
class Hest extends core::Object implements self::Bar {
synthetic constructor •() → self::Hest
;
+ @core::override
method fisk<U extends self::Foo<self::Hest::fisk::U> = dynamic>() → void
;
}
diff --git a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
index 6a28c0d..44fbbbc 100644
--- a/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
+++ b/pkg/front_end/testcases/rasta/issue_000033.dart.outline.expect
@@ -1,5 +1,15 @@
library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Warning: Method not found: 'JS'.
+// @JS()
+// ^^
+//
import self as self;
+@invalid-expression "pkg/front_end/testcases/rasta/issue_000033.dart:5:2: Error: Method not found: 'JS'.
+@JS()
+ ^^"
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
index 5b95c2b..dc87a52 100644
--- a/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
+++ b/pkg/front_end/testcases/redirecting_factory_metadata.dart.outline.expect
@@ -6,6 +6,7 @@
static field dynamic _redirecting# = <dynamic>[self::Foo::•];
constructor named(dynamic p) → self::Foo
;
+ @self::forFactoryItself
static factory •(dynamic p) → self::Foo
let dynamic #redirecting_factory = self::Foo::named in invalid-expression;
}
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
index 9199ba0..b965c9b 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
@@ -19,9 +19,10 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
// class xxx xx XXX extends XXX {
-// ^^
+// ^^^
//
// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
// class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
index 9199ba0..b965c9b 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
@@ -19,9 +19,10 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
// class xxx xx XXX extends XXX {
-// ^^
+// ^^^
//
// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
// class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
index 0a38be0..69a888f 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
@@ -19,9 +19,10 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
// class xxx xx XXX extends XXX {
-// ^^
+// ^^^
//
// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
// class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
index 2e470e5..b99e909 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
@@ -19,9 +19,10 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
// class xxx xx XXX extends XXX {
-// ^^
+// ^^^
//
// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
// class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
index 2e470e5..b99e909 100644
--- a/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
@@ -19,9 +19,10 @@
//
// Problems in library:
//
-// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:11: Error: Expected a class or mixin body, but got 'xx'.
+// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:7: Error: A class declaration must have a body, even if it is empty.
+// Try adding an empty body.
// class xxx xx XXX extends XXX {
-// ^^
+// ^^^
//
// pkg/front_end/testcases/regress/issue_36647_lib2.dart:5:14: Error: Expected ';' after this.
// class xxx xx XXX extends XXX {
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
index 659526a..b13488b 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y;
+@self::y
static field core::int x;
static method main() → dynamic
;
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
index 4735cfe..69ebf3f 100644
--- a/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.expect
@@ -13,6 +13,7 @@
import "dart:core" as core;
static const field core::int y = 42;
+@self::y
static field core::int x;
static method main() → dynamic {
core::print(self::y);
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
deleted file mode 100644
index 7797a4a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/*@testedFeatures=checks*/
-library test;
-
-typedef void F<T>(T t);
-
-void expectTypeError(void callback()) {
- try {
- callback();
- throw 'Expected TypeError, did not occur';
- } on TypeError {}
-}
-
-void expect(Object value, Object expected) {
- if (value != expected) {
- throw 'Expected $expected, got $value';
- }
-}
-
-class B {
- F<int> get x {
- throw 'Should not be reached';
- }
-
- void set x(Object value) {
- throw 'Should not be reached';
- }
-}
-
-abstract class I<T> {
- F<T> get x;
- void set x(Object value);
-}
-
-abstract class M<T> {
- T get x => f();
- void set x(Object value) {
- throw 'Should not be reached';
- }
-
- T f();
-}
-
-abstract class C<T> = B with M<F<T>> implements I<T>;
-
-class D extends C<int> {
- F<int> f() => (int i) {
- expect(i, 1);
- };
-}
-
-void test(I<Object> iObj, I<int> iInt) {
- expectTypeError(() {
- // iObj.x is expected to return type (Object) -> void, but it returns
- // (int) -> void (which is a supertype of (Object) -> void), so that's a
- // type error.
- var x = iObj. /*@checkReturn=(Object) -> void*/ x;
- });
- // iInt.x is expected to return type (int) -> void, and it does.
- var x = iInt. /*@checkReturn=(int) -> void*/ x;
- x(1);
-}
-
-void main() {
- var d = new D();
- test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
deleted file mode 100644
index dc66ff9..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.hierarchy.expect
+++ /dev/null
@@ -1,150 +0,0 @@
-Object:
- superclasses:
- interfaces:
- classMembers:
- Object._haveSameRuntimeType
- Object.toString
- Object.runtimeType
- Object._toString
- Object._simpleInstanceOf
- Object._hashCodeRnd
- Object._instanceOf
- Object.noSuchMethod
- Object._objectHashCode
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-B:
- superclasses:
- Object
- interfaces:
- classMembers:
- Object.toString
- B.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- B.x
-
-I:
- superclasses:
- Object
- interfaces:
- classMembers:
- Object.toString
- I.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- I.x
-
-M:
- superclasses:
- Object
- interfaces:
- classMembers:
- M.f
- Object.toString
- M.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- M.x
-
-C:
- superclasses:
- Object
- -> B
- interfaces: M<F<T>>, I<T>
- classMembers:
- M.f
- Object.toString
- M.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- M.x
- interfaceMembers:
- M.f
- Object.toString
- M.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
- M.x
-
-D:
- superclasses:
- Object
- -> B
- -> C<int>
- interfaces: M<F<int>>, I<int>
- classMembers:
- D.f
- Object.toString
- M.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- M.x
- interfaceMembers:
- D.f
- Object.toString
- M.x
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
- M.x
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
deleted file mode 100644
index 0546d0e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.expect
+++ /dev/null
@@ -1,72 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
- synthetic constructor •() → self::B
- : super core::Object::•()
- ;
- get x() → (core::int) → void {
- throw "Should not be reached";
- }
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract get x() → (self::I::T) → void;
- abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::M<self::M::T>
- : super core::Object::•()
- ;
- get x() → self::M::T
- return this.{self::M::f}();
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
- abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-class D extends self::C<core::int> {
- synthetic constructor •() → self::D
- : super self::C::•()
- ;
- method f() → (core::int) → void
- return (core::int i) → dynamic {
- self::expect(i, 1);
- };
-}
-static method expectTypeError(() → void callback) → void {
- try {
- callback.call();
- throw "Expected TypeError, did not occur";
- }
- on core::TypeError catch(no-exception-var) {
- }
-}
-static method expect(core::Object value, core::Object expected) → void {
- if(!value.==(expected)) {
- throw "Expected ${expected}, got ${value}";
- }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
- self::expectTypeError(() → dynamic {
- dynamic x = iObj.x;
- });
- dynamic x = iInt.x;
- x.call(1);
-}
-static method main() → void {
- dynamic d = new self::D::•();
- self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
deleted file mode 100644
index 839a7dc..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,78 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
- synthetic constructor •() → self::B
- : super core::Object::•()
- ;
- get x() → (core::int) → void {
- throw "Should not be reached";
- }
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract get x() → (self::I::T) → void;
- abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::M<self::M::T>
- : super core::Object::•()
- ;
- get x() → self::M::T
- return this.{self::M::f}();
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
- abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B implements self::I<self::C::T>, self::M<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- get x() → (self::C::T) → void
- return this.{self::M::f}();
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
- abstract method f() → (self::C::T) → void;
-}
-class D extends self::C<core::int> {
- synthetic constructor •() → self::D
- : super self::C::•()
- ;
- method f() → (core::int) → void
- return (core::int i) → dynamic {
- self::expect(i, 1);
- };
-}
-static method expectTypeError(() → void callback) → void {
- try {
- callback.call();
- throw "Expected TypeError, did not occur";
- }
- on core::TypeError catch(no-exception-var) {
- }
-}
-static method expect(core::Object value, core::Object expected) → void {
- if(!value.==(expected)) {
- throw "Expected ${expected}, got ${value}";
- }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
- self::expectTypeError(() → dynamic {
- dynamic x = iObj.x;
- });
- dynamic x = iInt.x;
- x.call(1);
-}
-static method main() → void {
- dynamic d = new self::D::•();
- self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
deleted file mode 100644
index e432df6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.outline.expect
+++ /dev/null
@@ -1,47 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
- synthetic constructor •() → self::B
- ;
- get x() → (core::int) → void
- ;
- set x(core::Object value) → void
- ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- ;
- abstract get x() → (self::I::T) → void;
- abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::M<self::M::T>
- ;
- get x() → self::M::T
- ;
- set x(core::Object value) → void
- ;
- abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-class D extends self::C<core::int> {
- synthetic constructor •() → self::D
- ;
- method f() → (core::int) → void
- ;
-}
-static method expectTypeError(() → void callback) → void
- ;
-static method expect(core::Object value, core::Object expected) → void
- ;
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void
- ;
-static method main() → void
- ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
deleted file mode 100644
index 450603a..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart.strong.expect
+++ /dev/null
@@ -1,86 +0,0 @@
-library test;
-//
-// Problems in library:
-//
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:39:9: Error: The return type of the method 'M.x' is 'void Function(T)', which does not match the return type, 'void Function(int)', of the overridden method, 'B.x'.
-// Change to a subtype of 'void Function(int)'.
-// T get x => f();
-// ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:24:14: Context: This is the overridden method ('x').
-// F<int> get x {
-// ^
-// pkg/front_end/testcases/runtime_checks_new/mixin_forwarding_stub_getter.dart:47:16: Context: Override was introduced in the mixin application class 'C'.
-// abstract class C<T> = B with M<F<T>> implements I<T>;
-// ^
-//
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B extends core::Object {
- synthetic constructor •() → self::B
- : super core::Object::•()
- ;
- get x() → (core::int) → void {
- throw "Should not be reached";
- }
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract get x() → (self::I::T) → void;
- abstract set x(core::Object value) → void;
-}
-abstract class M<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::M<self::M::T>
- : super core::Object::•()
- ;
- get x() → self::M::T
- return this.{self::M::f}();
- set x(core::Object value) → void {
- throw "Should not be reached";
- }
- abstract method f() → self::M::T;
-}
-abstract class C<T extends core::Object = dynamic> = self::B with self::M<(self::C::T) → void> implements self::I<self::C::T> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-class D extends self::C<core::int> {
- synthetic constructor •() → self::D
- : super self::C::•()
- ;
- method f() → (core::int) → void
- return (core::int i) → core::Null {
- self::expect(i, 1);
- };
-}
-static method expectTypeError(() → void callback) → void {
- try {
- callback.call();
- throw "Expected TypeError, did not occur";
- }
- on core::TypeError catch(no-exception-var) {
- }
-}
-static method expect(core::Object value, core::Object expected) → void {
- if(!value.{core::Object::==}(expected)) {
- throw "Expected ${expected}, got ${value}";
- }
-}
-static method test(self::I<core::Object> iObj, self::I<core::int> iInt) → void {
- self::expectTypeError(() → core::Null {
- (core::Object) → void x = iObj.{self::I::x} as{TypeError} (core::Object) → void;
- });
- (core::int) → void x = iInt.{self::I::x} as{TypeError} (core::int) → void;
- x.call(1);
-}
-static method main() → void {
- self::D d = new self::D::•();
- self::test(d, d);
-}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 7d32948..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
deleted file mode 100644
index 6b7705e..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- ;
- method f(core::int x) → self::B::T
- ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- ;
- abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- ;
-}
-static method main() → void
- ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
deleted file mode 100644
index c8ec998..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_contravariant_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,24 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(core::int x) → self::B::T {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(core::Object x) → self::I::T;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- abstract forwarding-stub method f(core::Object x) → (self::C::T) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
deleted file mode 100644
index 6f7dc10..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,87 +0,0 @@
-Object:
- superclasses:
- interfaces:
- classMembers:
- Object._haveSameRuntimeType
- Object.toString
- Object.runtimeType
- Object._toString
- Object._simpleInstanceOf
- Object._hashCodeRnd
- Object._instanceOf
- Object.noSuchMethod
- Object._objectHashCode
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-B:
- superclasses:
- Object
- interfaces:
- classMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-I:
- superclasses:
- Object
- interfaces:
- classMembers:
- I.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-C:
- superclasses:
- Object
- -> B<F<T>>
- interfaces: I<F<T>>
- classMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index 5e95811..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,23 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
deleted file mode 100644
index 5526106..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.outline.expect
+++ /dev/null
@@ -1,22 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- ;
- method f((self::B::T) → void x, core::int y) → void
- ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- ;
-}
-static method main() → void
- ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
- return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
deleted file mode 100644
index 14a514f..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantImpl_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,25 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-class B<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void
- return super.{self::B::f}(x, y);
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
deleted file mode 100644
index dfb9fc6..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
+++ /dev/null
@@ -1,134 +0,0 @@
-Object:
- superclasses:
- interfaces:
- classMembers:
- Object._haveSameRuntimeType
- Object.toString
- Object.runtimeType
- Object._toString
- Object._simpleInstanceOf
- Object._hashCodeRnd
- Object._instanceOf
- Object.noSuchMethod
- Object._objectHashCode
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-A:
- superclasses:
- Object
- interfaces:
- classMembers:
- A.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
-
-B:
- Longest path to Object: 2
- superclasses:
- Object
- interfaces: A<F<T>>
- classMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
-
-I:
- Longest path to Object: 2
- superclasses:
- Object
- interfaces: A<F<T>>
- classMembers:
- I.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- interfaceMembers:
- I.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
-
-C:
- Longest path to Object: 3
- superclasses:
- Object
- -> B<F<T>>
- interfaces: A<F<F<T>>>, I<F<T>>
- classMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- classSetters:
- interfaceMembers:
- B.f
- Object.toString
- Object.runtimeType
- Object._simpleInstanceOf
- Object._instanceOf
- Object.noSuchMethod
- Object._identityHashCode
- Object.hashCode
- Object._simpleInstanceOfFalse
- Object._simpleInstanceOfTrue
- Object.==
- interfaceSetters:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
deleted file mode 100644
index df1249c..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.legacy.transformed.expect
+++ /dev/null
@@ -1,29 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f((self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
deleted file mode 100644
index c638537..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.outline.expect
+++ /dev/null
@@ -1,27 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T>
- ;
- abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
- synthetic constructor •() → self::B<self::B::T>
- ;
- method f((self::B::T) → void x, core::int y) → void
- ;
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
- synthetic constructor •() → self::I<self::I::T>
- ;
- abstract method f((self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- ;
-}
-static method main() → void
- ;
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
deleted file mode 100644
index fd2002b..0000000
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.strong.transformed.expect
+++ /dev/null
@@ -1,30 +0,0 @@
-library test;
-import self as self;
-import "dart:core" as core;
-
-typedef F<T extends core::Object = dynamic> = (T) → void;
-abstract class A<T extends core::Object = dynamic> extends core::Object {
- synthetic constructor •() → self::A<self::A::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl self::A::T x, core::int y) → void;
-}
-class B<T extends core::Object = dynamic> extends core::Object implements self::A<(self::B::T) → void> {
- synthetic constructor •() → self::B<self::B::T>
- : super core::Object::•()
- ;
- method f(generic-covariant-impl (self::B::T) → void x, core::int y) → void {}
-}
-abstract class I<T extends core::Object = dynamic> extends core::Object implements self::A<(self::I::T) → void> {
- synthetic constructor •() → self::I<self::I::T>
- : super core::Object::•()
- ;
- abstract method f(generic-covariant-impl (self::I::T) → void x, core::Object y) → void;
-}
-abstract class C<T extends core::Object = dynamic> extends self::B<(self::C::T) → void> implements self::I<(self::C::T) → void> {
- synthetic constructor •() → self::C<self::C::T>
- : super self::B::•()
- ;
- abstract forwarding-stub method f(generic-covariant-impl ((self::C::T) → void) → void x, core::Object y) → void;
-}
-static method main() → void {}
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index 0347606..a32cc66 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -25,6 +25,7 @@
await: TextSerializationFailure # Was: Pass
bad_setter_abstract: TextSerializationFailure # Was: Pass
bad_store: TextSerializationFailure # Was: Pass
+bad_type_variable_uses_in_supertypes: TextSerializationFailure
bounds_check_depends_on_inference: TextSerializationFailure # Was: Pass
bug21938: TypeCheckError
bug30695: TypeCheckError
@@ -670,6 +671,9 @@
instantiate_to_bound/typedef_omitted_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/typedef_raw_in_bound: TextSerializationFailure # Was: Pass
instantiate_to_bound/typedef_super_bounded_type: TextSerializationFailure # Was: Pass
+interface_contravariant_from_class: TextSerializationFailure
+interface_covariantImpl_from_class: TextSerializationFailure
+interface_covariantInterface_from_class: TextSerializationFailure
invalid_assignment: TextSerializationFailure # Was: Pass
invalid_cast: TextSerializationFailure # Was: Pass
invalid_type: TypeCheckError
@@ -677,6 +681,7 @@
issue34515: TextSerializationFailure
issue34899: TypeCheckError
issue35875: TextSerializationFailure
+issue37027: TextSerializationFailure
literals: TextSerializationFailure # Was: Pass
local_generic_function: TextSerializationFailure # Was: Pass
magic_const: TextSerializationFailure # Was: Pass
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index a3cd069..18b7445 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -192,6 +192,7 @@
// TODO(ahe): Extend this entry point so it can replace
// batchEntryPoint.
new IncrementalCompiler(c);
+ return Future<void>.value();
});
}
diff --git a/pkg/front_end/tool/fasta_perf.dart b/pkg/front_end/tool/fasta_perf.dart
index bd1ed2c..0ba6da6 100644
--- a/pkg/front_end/tool/fasta_perf.dart
+++ b/pkg/front_end/tool/fasta_perf.dart
@@ -217,7 +217,7 @@
// Note: this method converts the body to kernel, so we skip that here.
@override
- finishFunction(annotations, formals, asyncModifier, body) {}
+ finishFunction(formals, asyncModifier, body) {}
}
// Invoke the fasta kernel generator for the program starting in [entryUri]
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 30a5f5c..0a9e01b 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -192,6 +192,11 @@
Uri get fileUri;
}
+abstract class Annotatable {
+ List<Expression> get annotations;
+ void addAnnotation(Expression node);
+}
+
/// Indirection between a reference and its definition.
///
/// There is only one reference object per [NamedNode].
@@ -267,7 +272,8 @@
// ------------------------------------------------------------------------
@coq
-class Library extends NamedNode implements Comparable<Library>, FileUriNode {
+class Library extends NamedNode
+ implements Annotatable, Comparable<Library>, FileUriNode {
/// An import path to this library.
///
/// The [Uri] should have the `dart`, `package`, `app`, or `file` scheme.
@@ -721,7 +727,7 @@
/// rule directly, as doing so can obstruct transformations. It is possible to
/// transform a mixin application to become a regular class, and vice versa.
@coq
-class Class extends NamedNode implements FileUriNode {
+class Class extends NamedNode implements Annotatable, FileUriNode {
/// Start offset of the class in the source file it comes from.
///
/// Note that this includes annotations if any.
@@ -1086,7 +1092,7 @@
// ------------------------------------------------------------------------
@coq
-abstract class Member extends NamedNode implements FileUriNode {
+abstract class Member extends NamedNode implements Annotatable, FileUriNode {
/// End offset in the source file it comes from.
///
/// Valid values are from 0 and up, or -1 ([TreeNode.noOffset]) if the file
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 274942a..c5c5363 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -57,6 +57,15 @@
/// Number semantics to use for this backend.
NumberSemantics get numberSemantics => NumberSemantics.vm;
+
+ /// Inline control of constant variables. The given constant expression
+ /// is the initializer of a [Field] or [VariableDeclaration] node.
+ /// If this method returns `true`, the variable will be inlined at all
+ /// points of reference and the variable itself removed (unless overridden
+ /// by the `keepFields` or `keepVariables` flag to the constant transformer).
+ /// This method must be deterministic, i.e. it must always return the same
+ /// value for the same constant value and place in the AST.
+ bool shouldInlineConstant(ConstantExpression initializer) => true;
}
/// A target provides backend-specific options for generating kernel IR.
diff --git a/pkg/modular_test/lib/src/dependency_parser.dart b/pkg/modular_test/lib/src/dependency_parser.dart
deleted file mode 100644
index 51f2460..0000000
--- a/pkg/modular_test/lib/src/dependency_parser.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// 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 library defines how to read module dependencies from a Yaml
-/// specification. We expect to find specifications written in this format:
-///
-/// dependencies:
-/// b: a
-/// main: [b, expect]
-///
-/// Where:
-/// - Each name corresponds to a module.
-/// - Module names correlate to either a file, a folder, or a package.
-/// - A map entry contains all the dependencies of a module, if any.
-/// - If a module has a single dependency, it can be written as a single
-/// value.
-///
-/// The logic in this library mostly treats these names as strings, separately
-/// `loader.dart` is responsible for validating and attaching this dependency
-/// information to a set of module definitions.
-import 'package:yaml/yaml.dart';
-
-/// Parses [contents] containing a module dependencies specification written in
-/// yaml, and returns a normalized dependency map.
-///
-/// Note: some values in the map may not have a corresponding key. That may be
-/// the case for modules that have no dependencies and modules that are not
-/// specified in [contents] (e.g. modules that are supported by default).
-Map<String, List<String>> parseDependencyMap(String contents) {
- var spec = loadYaml(contents);
- if (spec is! YamlMap) {
- return _invalidSpecification("spec is not a map");
- }
- var dependencies = spec['dependencies'];
- if (dependencies == null) {
- return _invalidSpecification("no dependencies section");
- }
- if (dependencies is! YamlMap) {
- return _invalidSpecification("dependencies is not a map");
- }
-
- Map<String, List<String>> normalizedMap = {};
- dependencies.forEach((key, value) {
- if (key is! String) {
- _invalidSpecification("key: '$key' is not a string");
- }
- normalizedMap[key] = [];
- if (value is String) {
- normalizedMap[key].add(value);
- } else if (value is List) {
- value.forEach((entry) {
- if (entry is! String) {
- _invalidSpecification("entry: '$entry' is not a string");
- }
- normalizedMap[key].add(entry);
- });
- } else {
- _invalidSpecification(
- "entry: '$value' is not a string or a list of strings");
- }
- });
- return normalizedMap;
-}
-
-_invalidSpecification(String message) {
- throw new InvalidSpecificationError(message);
-}
-
-class InvalidSpecificationError extends Error {
- final String message;
- InvalidSpecificationError(this.message);
- String toString() => "Invalid specification: $message";
-}
diff --git a/pkg/modular_test/lib/src/generic_runner.dart b/pkg/modular_test/lib/src/generic_runner.dart
new file mode 100644
index 0000000..7a3786c
--- /dev/null
+++ b/pkg/modular_test/lib/src/generic_runner.dart
@@ -0,0 +1,151 @@
+// 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.
+
+/// A generic test runner that executes a list of tests, logs test results, and
+/// adds sharding support.
+///
+/// This library contains no logic related to the modular_test framework. It is
+/// used to help integrate tests with our test infrastructure.
+// TODO(sigmund): this library should move somewhere else.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+/// A generic test.
+abstract class Test {
+ /// Unique test name.
+ String get name;
+
+ /// Run the actual test.
+ Future<void> run();
+}
+
+class RunnerOptions {
+ /// Name of the test suite being run.
+ String suiteName;
+
+ /// Configuration name to use when writing result logs.
+ String configurationName;
+
+ /// Filter used to only run tests that match the filter name.
+ String filter;
+
+ /// Where log files are emitted.
+ ///
+ /// Note that all shards currently emit the same filenames, so two shards
+ /// shouldn't be given the same [logDir] otherwise they will overwrite each
+ /// other's log files.
+ Uri logDir;
+
+ /// Of [shards], which shard is currently being executed.
+ int shard;
+
+ /// How many shards will be used to run a suite.
+ int shards;
+
+ /// Whether to print verbose information.
+ bool verbose;
+
+ /// Template used to help developers reproduce the issue.
+ ///
+ /// The following substitutions are made:
+ /// * %executable is replaced with `Platform.executable`
+ /// * %script is replaced with the current `Platform.script`
+ /// * %name is replaced with the test name.
+ String reproTemplate;
+}
+
+class _TestOutcome {
+ /// Unique test name.
+ String name;
+
+ /// Whether, after running the test, the test matches its expectations. Null
+ /// before the test is executed.
+ bool matchedExpectations;
+
+ /// Additional output emitted by the test, only used when expectations don't
+ /// match and more details need to be provided.
+ String output;
+
+ /// Time used to run the test.
+ Duration elapsedTime;
+}
+
+Future<void> runSuite<T>(List<Test> tests, RunnerOptions options) async {
+ if (options.filter == null) {
+ if (options.logDir == null) {
+ print('warning: no output directory provided, logs wont be emitted.');
+ }
+ if (options.configurationName == null) {
+ print('warning: please provide a configuration name.');
+ }
+ }
+ var sortedTests = tests.toList()..sort((a, b) => a.name.compareTo(b.name));
+ List<_TestOutcome> testOutcomes = [];
+ int shard = options.shard;
+ int shards = options.shards;
+ for (int i = 0; i < sortedTests.length; i++) {
+ if (shards > 1 && i % shards != shard) continue;
+ var test = sortedTests[i];
+ var name = test.name;
+ if (options.verbose) stdout.write('$name: ');
+ if (options.filter != null && !name.contains(options.filter)) {
+ if (options.verbose) stdout.write('skipped\n');
+ continue;
+ }
+
+ var watch = new Stopwatch()..start();
+ var outcome = new _TestOutcome()..name = test.name;
+ try {
+ await test.run();
+ if (options.verbose) stdout.write('pass\n');
+ outcome.matchedExpectations = true;
+ } catch (e, st) {
+ var repro = options.reproTemplate
+ .replaceAll('%executable', Platform.resolvedExecutable)
+ .replaceAll('%script', Platform.script.path)
+ .replaceAll('%name', test.name);
+ outcome.matchedExpectations = false;
+ outcome.output = 'uncaught exception: $e\n$st\nTo repro run:\n $repro';
+ if (options.verbose) stdout.write('fail\n${outcome.output}');
+ }
+ watch.stop();
+ outcome.elapsedTime = watch.elapsed;
+ testOutcomes.add(outcome);
+ }
+
+ if (options.logDir == null) return;
+
+ List<String> results = [];
+ List<String> logs = [];
+ for (int i = 0; i < testOutcomes.length; i++) {
+ var test = testOutcomes[i];
+ final record = jsonEncode({
+ 'name': '${options.suiteName}/${test.name}',
+ 'configuration': options.configurationName,
+ 'suite': options.suiteName,
+ 'test_name': test.name,
+ 'time_ms': test.elapsedTime.inMilliseconds,
+ 'expected': 'Pass',
+ 'result': test.matchedExpectations ? 'Pass' : 'Fail',
+ 'matches': test.matchedExpectations,
+ });
+ results.add(record);
+ if (!test.matchedExpectations) {
+ final log = jsonEncode({
+ 'name': '${options.suiteName}/${test.name}',
+ 'configuration': options.configurationName,
+ 'result': test.matchedExpectations ? 'Pass' : 'Fail',
+ 'log': test.output,
+ });
+ logs.add(log);
+ }
+ }
+
+ File.fromUri(options.logDir.resolve('results.json'))
+ .writeAsStringSync(results.map((s) => '$s\n').join());
+ File.fromUri(options.logDir.resolve('logs.json'))
+ .writeAsStringSync(logs.map((s) => '$s\n').join());
+}
diff --git a/pkg/modular_test/lib/src/io_pipeline.dart b/pkg/modular_test/lib/src/io_pipeline.dart
index ed77f2d..21c57b6 100644
--- a/pkg/modular_test/lib/src/io_pipeline.dart
+++ b/pkg/modular_test/lib/src/io_pipeline.dart
@@ -22,53 +22,110 @@
/// Assets created on previous steps of the pipeline should be available under
/// `root.resolveUri(toUri(module, dataId))` and the output of this step
/// should be stored under `root.resolveUri(toUri(module, resultKind))`.
- Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri);
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags);
}
class IOPipeline extends Pipeline<IOModularStep> {
- /// A folder per step. The key is the data id produced by a specific step.
+ /// Folder that holds the results of each step during the run of the pipeline.
///
- /// This contains internal state used during the run of the pipeline, but is
- /// expected to be null before and after the pipeline is executed.
- Map<DataId, Uri> _tmpFolders;
- Map<DataId, Uri> get tmpFoldersForTesting => _tmpFolders;
- bool saveFoldersForTesting;
+ /// This value is usually null before and after the pipeline runs, but will be
+ /// non-null in two cases:
+ ///
+ /// * for testing purposes when using [saveIntermediateResultsForTesting].
+ ///
+ /// * to share results across pipeline runs when using [cacheSharedModules].
+ ///
+ /// When using [cacheSharedModules] the pipeline will only reuse data for
+ /// modules that are known to be shared (e.g. shared packages and sdk
+ /// libraries), and not modules that are test specific. File names will be
+ /// specific enough so that we can keep separate the artifacts created from
+ /// running tools under different configurations (with different flags).
+ Uri _resultsFolderUri;
+ Uri get resultFolderUriForTesting => _resultsFolderUri;
- IOPipeline(List<IOModularStep> steps, {this.saveFoldersForTesting: false})
- : super(steps);
+ /// A unique number to denote the current modular test configuration.
+ ///
+ /// When using [cacheSharedModules], a test can resuse the output of a
+ /// previous run of this pipeline if that output was generated with the same
+ /// configuration.
+ int _currentConfiguration;
+
+ final ConfigurationRegistry _registry;
+
+ /// Whether to keep alive the temporary folder used to store intermediate
+ /// results in order to inspect it later in test.
+ final bool saveIntermediateResultsForTesting;
+
+ IOPipeline(List<IOModularStep> steps,
+ {this.saveIntermediateResultsForTesting: false,
+ bool cacheSharedModules: false})
+ : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+ super(steps, cacheSharedModules);
@override
Future<void> run(ModularTest test) async {
- assert(_tmpFolders == null);
- _tmpFolders = {};
+ var resultsDir = null;
+ if (_resultsFolderUri == null) {
+ resultsDir = await Directory.systemTemp.createTemp('modular_test_res-');
+ _resultsFolderUri = resultsDir.uri;
+ }
+ if (cacheSharedModules) {
+ _currentConfiguration = _registry.computeConfigurationId(test);
+ }
await super.run(test);
- if (!saveFoldersForTesting) {
- for (var folder in _tmpFolders.values) {
- await Directory.fromUri(folder).delete(recursive: true);
- }
- _tmpFolders = null;
+ if (resultsDir != null &&
+ !saveIntermediateResultsForTesting &&
+ !cacheSharedModules) {
+ await resultsDir.delete(recursive: true);
+ _resultsFolderUri = null;
+ }
+ if (!saveIntermediateResultsForTesting) {
+ _currentConfiguration = null;
+ }
+ }
+
+ /// Delete folders that were kept around either because of
+ /// [saveIntermediateResultsForTesting] or because of [cacheSharedModules].
+ Future<void> cleanup() async {
+ if (_resultsFolderUri == null) return;
+ if (saveIntermediateResultsForTesting || cacheSharedModules) {
+ await Directory.fromUri(_resultsFolderUri).delete(recursive: true);
+ _resultsFolderUri = null;
}
}
@override
Future<void> runStep(IOModularStep step, Module module,
- Map<Module, Set<DataId>> visibleData) async {
- // Since data ids are unique throughout the pipeline, we use the first
- // result data id as a hint for the name of the temporary folder of a step.
- var stepFolder;
- for (var dataId in step.resultData) {
- stepFolder ??=
- await Directory.systemTemp.createTemp('modular_test_${dataId}-');
- _tmpFolders[dataId] ??=
- (await Directory.systemTemp.createTemp('modular_test_${dataId}_res-'))
- .uri;
+ Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+ if (cacheSharedModules && module.isShared) {
+ // If all expected outputs are already available, skip the step.
+ bool allCachedResultsFound = true;
+ for (var dataId in step.resultData) {
+ var cachedFile = File.fromUri(_resultsFolderUri
+ .resolve(_toFileName(module, dataId, configSpecific: true)));
+ if (!await cachedFile.exists()) {
+ allCachedResultsFound = false;
+ break;
+ }
+ }
+ if (allCachedResultsFound) {
+ step.notifyCached(module);
+ return;
+ }
}
+
+ // Each step is executed in a separate folder. To make it easier to debug
+ // issues, we include one of the step data ids in the name of the folder.
+ var stepId = step.resultData.first;
+ var stepFolder =
+ await Directory.systemTemp.createTemp('modular_test_${stepId}-');
for (var module in visibleData.keys) {
for (var dataId in visibleData[module]) {
- var filename = "${module.name}.${dataId.name}";
- var assetUri = _tmpFolders[dataId].resolve(filename);
- await File.fromUri(assetUri)
- .copy(stepFolder.uri.resolve(filename).toFilePath());
+ var assetUri = _resultsFolderUri
+ .resolve(_toFileName(module, dataId, configSpecific: true));
+ await File.fromUri(assetUri).copy(
+ stepFolder.uri.resolve(_toFileName(module, dataId)).toFilePath());
}
}
if (step.needsSources) {
@@ -81,19 +138,31 @@
}
await step.execute(module, stepFolder.uri,
- (Module m, DataId id) => Uri.parse("${m.name}.${id.name}"));
+ (Module m, DataId id) => Uri.parse(_toFileName(m, id)), flags);
for (var dataId in step.resultData) {
var outputFile =
- File.fromUri(stepFolder.uri.resolve("${module.name}.${dataId.name}"));
+ File.fromUri(stepFolder.uri.resolve(_toFileName(module, dataId)));
if (!await outputFile.exists()) {
throw StateError(
"Step '${step.runtimeType}' didn't produce an output file");
}
- await outputFile.copy(_tmpFolders[dataId]
- .resolve("${module.name}.${dataId.name}")
+ await outputFile.copy(_resultsFolderUri
+ .resolve(_toFileName(module, dataId, configSpecific: true))
.toFilePath());
}
await stepFolder.delete(recursive: true);
}
+
+ String _toFileName(Module module, DataId dataId,
+ {bool configSpecific: false}) {
+ var prefix =
+ cacheSharedModules && configSpecific && _currentConfiguration != null
+ ? _currentConfiguration
+ : '';
+ return "$prefix${module.name}.${dataId.name}";
+ }
+
+ String configSpecificResultFileNameForTesting(Module module, DataId dataId) =>
+ _toFileName(module, dataId, configSpecific: true);
}
diff --git a/pkg/modular_test/lib/src/loader.dart b/pkg/modular_test/lib/src/loader.dart
index ce00e49..b73da9b 100644
--- a/pkg/modular_test/lib/src/loader.dart
+++ b/pkg/modular_test/lib/src/loader.dart
@@ -17,11 +17,11 @@
/// [defaultPackagesInput]. The list of packages provided is expected to
/// be disjoint with those in [defaultPackagesInput].
/// * a modules.yaml file: a specification of dependencies between modules.
-/// The format is described in `dependencies_parser.dart`.
+/// The format is described in `test_specification_parser.dart`.
import 'dart:io';
import 'dart:convert';
import 'suite.dart';
-import 'dependency_parser.dart';
+import 'test_specification_parser.dart';
import 'find_sdk_root.dart';
import 'package:package_config/packages_file.dart' as package_config;
@@ -39,16 +39,25 @@
Uri root = await findRoot();
Map<String, Uri> defaultPackages =
package_config.parse(_defaultPackagesInput, root);
- Map<String, Module> modules = {};
- String spec;
+ Module sdkModule = await _createSdkModule(root);
+ Map<String, Module> modules = {'sdk': sdkModule};
+ String specString;
Module mainModule;
Map<String, Uri> packages = {};
- await for (var entry in folder.list(recursive: false)) {
+ var entries = folder.listSync(recursive: false).toList()
+ // Sort to avoid dependency on file system order.
+ ..sort(_compareFileSystemEntity);
+ for (var entry in entries) {
var entryUri = entry.uri;
if (entry is File) {
var fileName = entryUri.path.substring(testUri.path.length);
if (fileName.endsWith('.dart')) {
var moduleName = fileName.substring(0, fileName.indexOf('.dart'));
+ if (moduleName == 'sdk') {
+ return _invalidTest("The file '$fileName' defines a module called "
+ "'$moduleName' which conflicts with the sdk module "
+ "that is provided by default.");
+ }
if (defaultPackages.containsKey(moduleName)) {
return _invalidTest("The file '$fileName' defines a module called "
"'$moduleName' which conflicts with a package by the same name "
@@ -69,12 +78,17 @@
List<int> packagesBytes = await entry.readAsBytes();
packages = package_config.parse(packagesBytes, entryUri);
} else if (fileName == 'modules.yaml') {
- spec = await entry.readAsString();
+ specString = await entry.readAsString();
}
} else {
assert(entry is Directory);
var path = entryUri.path;
var moduleName = path.substring(testUri.path.length, path.length - 1);
+ if (moduleName == 'sdk') {
+ return _invalidTest("The folder '$moduleName' defines a module "
+ "which conflicts with the sdk module "
+ "that is provided by default.");
+ }
if (defaultPackages.containsKey(moduleName)) {
return _invalidTest("The folder '$moduleName' defines a module "
"which conflicts with a package by the same name "
@@ -88,7 +102,7 @@
packageBase: Uri.parse('$moduleName/'));
}
}
- if (spec == null) {
+ if (specString == null) {
return _invalidTest("modules.yaml file is missing");
}
if (mainModule == null) {
@@ -97,12 +111,16 @@
_addDefaultPackageEntries(packages, defaultPackages);
await _addModulePerPackage(packages, modules);
- _attachDependencies(parseDependencyMap(spec), modules);
- _attachDependencies(parseDependencyMap(_defaultPackagesSpec), modules);
+ TestSpecification spec = parseTestSpecification(specString);
+ _attachDependencies(spec.dependencies, modules);
+ _attachDependencies(
+ parseTestSpecification(_defaultPackagesSpec).dependencies, modules);
+ _addSdkDependencies(modules, sdkModule);
_detectCyclesAndRemoveUnreachable(modules, mainModule);
var sortedModules = modules.values.toList()
..sort((a, b) => a.name.compareTo(b.name));
- return new ModularTest(sortedModules, mainModule);
+ var sortedFlags = spec.flags.toList()..sort();
+ return new ModularTest(sortedModules, mainModule, sortedFlags);
}
/// Returns all source files recursively found in a folder as relative URIs.
@@ -142,6 +160,15 @@
});
}
+/// Make every module depend on the sdk module.
+void _addSdkDependencies(Map<String, Module> modules, Module sdkModule) {
+ for (var module in modules.values) {
+ if (module != sdkModule) {
+ module.dependencies.add(sdkModule);
+ }
+ }
+}
+
void _addDefaultPackageEntries(
Map<String, Uri> packages, Map<String, Uri> defaultPackages) {
for (var name in defaultPackages.keys) {
@@ -169,11 +196,35 @@
// module that is part of the test (package name and module name should
// match).
modules[packageName] = Module(packageName, [], rootUri, sources,
- isPackage: true, packageBase: Uri.parse('lib/'));
+ isPackage: true, packageBase: Uri.parse('lib/'), isShared: true);
}
}
}
+Future<Module> _createSdkModule(Uri root) async {
+ List<Uri> sources = [Uri.parse('sdk/lib/libraries.json')];
+
+ // Include all dart2js, ddc, vm library sources and patch files.
+ // Note: we don't extract the list of files from the libraries.json because
+ // it doesn't list files that are transitively imported.
+ var sdkLibrariesAndPatchesRoots = [
+ 'sdk/lib/',
+ 'runtime/lib/',
+ 'runtime/bin/',
+ 'pkg/dev_compiler/tool/input_sdk/',
+ ];
+ for (var path in sdkLibrariesAndPatchesRoots) {
+ var dir = Directory.fromUri(root.resolve(path));
+ await for (var file in dir.list(recursive: true)) {
+ if (file is File && file.path.endsWith(".dart")) {
+ sources.add(Uri.parse(file.uri.path.substring(root.path.length)));
+ }
+ }
+ }
+ sources..sort((a, b) => a.path.compareTo(b.path));
+ return Module('sdk', [], root, sources, isSdk: true, isShared: true);
+}
+
/// Trim the set of modules, and detect cycles while we are at it.
_detectCyclesAndRemoveUnreachable(Map<String, Module> modules, Module main) {
Set<Module> visiting = {};
@@ -244,3 +295,20 @@
InvalidTestError(this.message);
String toString() => "Invalid test: $message";
}
+
+/// Comparator to sort directories before files.
+int _compareFileSystemEntity(FileSystemEntity a, FileSystemEntity b) {
+ if (a is Directory) {
+ if (b is Directory) {
+ return a.path.compareTo(b.path);
+ } else {
+ return -1;
+ }
+ } else {
+ if (b is Directory) {
+ return 1;
+ } else {
+ return a.path.compareTo(b.path);
+ }
+ }
+}
diff --git a/pkg/modular_test/lib/src/memory_pipeline.dart b/pkg/modular_test/lib/src/memory_pipeline.dart
index 9ad5c43..d97586c 100644
--- a/pkg/modular_test/lib/src/memory_pipeline.dart
+++ b/pkg/modular_test/lib/src/memory_pipeline.dart
@@ -13,8 +13,11 @@
typedef SourceProvider = String Function(Uri);
abstract class MemoryModularStep extends ModularStep {
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider);
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags);
}
class MemoryPipeline extends Pipeline<MemoryModularStep> {
@@ -27,20 +30,60 @@
/// A copy of [_result] at the time the pipeline last finished running.
Map<Module, Map<DataId, Object>> resultsForTesting;
- MemoryPipeline(this._sources, List<MemoryModularStep> steps) : super(steps);
+ final ConfigurationRegistry _registry;
+
+ /// Cache of results when [cacheSharedModules] is true
+ final List<Map<Module, Map<DataId, Object>>> _resultCache;
+
+ MemoryPipeline(this._sources, List<MemoryModularStep> steps,
+ {bool cacheSharedModules: false})
+ : _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
+ _resultCache = cacheSharedModules ? [] : null,
+ super(steps, cacheSharedModules);
@override
Future<void> run(ModularTest test) async {
- assert(_results == null);
_results = {};
+ Map<Module, Map<DataId, Object>> cache = null;
+ if (cacheSharedModules) {
+ int id = _registry.computeConfigurationId(test);
+ if (id < _resultCache.length) {
+ cache = _resultCache[id];
+ } else {
+ assert(id == _resultCache.length);
+ _resultCache.add(cache = {});
+ }
+ _results.addAll(cache);
+ }
await super.run(test);
resultsForTesting = _results;
+ if (cacheSharedModules) {
+ for (var module in _results.keys) {
+ if (module.isShared) {
+ cache[module] = _results[module];
+ }
+ }
+ }
_results = null;
}
@override
Future<void> runStep(MemoryModularStep step, Module module,
- Map<Module, Set<DataId>> visibleData) async {
+ Map<Module, Set<DataId>> visibleData, List<String> flags) async {
+ if (cacheSharedModules && module.isShared) {
+ bool allCachedResultsFound = true;
+ for (var dataId in step.resultData) {
+ if (_results[module] == null || _results[module][dataId] == null) {
+ allCachedResultsFound = false;
+ break;
+ }
+ }
+ if (allCachedResultsFound) {
+ step.notifyCached(module);
+ return;
+ }
+ }
+
Map<Module, Map<DataId, Object>> inputData = {};
visibleData.forEach((module, dataIdSet) {
inputData[module] = {};
@@ -58,7 +101,8 @@
Map<DataId, Object> result = await step.execute(
module,
(Uri uri) => inputSources[uri],
- (Module m, DataId id) => inputData[m][id]);
+ (Module m, DataId id) => inputData[m][id],
+ flags);
for (var dataId in step.resultData) {
(_results[module] ??= {})[dataId] = result[dataId];
}
diff --git a/pkg/modular_test/lib/src/pipeline.dart b/pkg/modular_test/lib/src/pipeline.dart
index 64e08a7..c55f2f9 100644
--- a/pkg/modular_test/lib/src/pipeline.dart
+++ b/pkg/modular_test/lib/src/pipeline.dart
@@ -48,6 +48,9 @@
this.moduleDataNeeded: const [],
this.resultData,
this.onlyOnMain: false});
+
+ /// Notifies that the step was not executed, but cached instead.
+ void notifyCached(Module module) {}
}
/// An object to uniquely identify modular data produced by a modular step.
@@ -63,9 +66,13 @@
}
abstract class Pipeline<S extends ModularStep> {
+ /// Whether to cache the result of shared modules (e.g. shard packages and sdk
+ /// libraries) when multiple tests are run by this pipeline.
+ final bool cacheSharedModules;
+
final List<S> steps;
- Pipeline(this.steps) {
+ Pipeline(this.steps, this.cacheSharedModules) {
_validate();
}
@@ -114,7 +121,7 @@
// TODO(sigmund): validate that [ModularTest] has no cycles.
Map<Module, Set<DataId>> computedData = {};
for (var step in steps) {
- await _recursiveRun(step, test.mainModule, computedData, {}, {});
+ await _recursiveRun(step, test.mainModule, computedData, {}, test.flags);
}
}
@@ -122,22 +129,22 @@
S step,
Module module,
Map<Module, Set<DataId>> computedData,
- Set<Module> seen,
- Set<Module> parentDependencies) async {
- if (!seen.add(module)) return;
- parentDependencies.add(module);
- Set<Module> transitiveDependencies = {};
+ Map<Module, Set<Module>> transitiveDependencies,
+ List<String> flags) async {
+ if (transitiveDependencies.containsKey(module)) return;
+ var deps = transitiveDependencies[module] = {};
for (var dependency in module.dependencies) {
await _recursiveRun(
- step, dependency, computedData, seen, transitiveDependencies);
+ step, dependency, computedData, transitiveDependencies, flags);
+ deps.add(dependency);
+ deps.addAll(transitiveDependencies[dependency]);
}
- parentDependencies.addAll(transitiveDependencies);
if (step.onlyOnMain && !module.isMain) return;
// Include only requested data from transitive dependencies.
Map<Module, Set<DataId>> visibleData = {};
- transitiveDependencies.forEach((dep) {
+ deps.forEach((dep) {
visibleData[dep] = {};
for (var dataId in step.dependencyDataNeeded) {
if (computedData[dep].contains(dataId)) {
@@ -151,12 +158,12 @@
visibleData[module].add(dataId);
}
}
- await runStep(step, module, visibleData);
+ await runStep(step, module, visibleData, flags);
(computedData[module] ??= {}).addAll(step.resultData);
}
- Future<void> runStep(
- S step, Module module, Map<Module, Set<DataId>> visibleData);
+ Future<void> runStep(S step, Module module,
+ Map<Module, Set<DataId>> visibleData, List<String> flags);
}
class InvalidPipelineError extends Error {
diff --git a/pkg/modular_test/lib/src/runner.dart b/pkg/modular_test/lib/src/runner.dart
new file mode 100644
index 0000000..9c3b36f
--- /dev/null
+++ b/pkg/modular_test/lib/src/runner.dart
@@ -0,0 +1,110 @@
+// 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.
+
+/// A runner that executes a pipeline on a folder containing modular tests.
+import 'dart:io';
+
+import 'package:args/args.dart';
+import 'package:modular_test/src/io_pipeline.dart';
+import 'package:modular_test/src/loader.dart';
+import 'package:modular_test/src/suite.dart';
+
+import 'generic_runner.dart' as generic;
+
+Uri relativize(Uri uri, Uri base) {
+ return Uri.parse(uri.path.substring(base.path.length));
+}
+
+Future<void> runSuite(Uri suiteFolder, String suiteName, Options options,
+ IOPipeline pipeline) async {
+ var dir = Directory.fromUri(suiteFolder);
+ var entries = (await dir.list(recursive: false).toList())
+ .where((e) => e is Directory)
+ .map((e) => new _PipelineTest(e.uri, suiteFolder, options, pipeline))
+ .toList();
+
+ generic.runSuite(
+ entries,
+ new generic.RunnerOptions()
+ ..suiteName = suiteName
+ ..configurationName = options.configurationName
+ ..filter = options.filter
+ ..logDir = options.outputDirectory
+ ..shard = options.shard
+ ..shards = options.shards
+ ..verbose = options.verbose
+ ..reproTemplate = '%executable %script --verbose --filter %name');
+ await pipeline.cleanup();
+}
+
+class _PipelineTest implements generic.Test {
+ final String name;
+ final Uri uri;
+ final Options options;
+ final IOPipeline pipeline;
+
+ _PipelineTest(this.uri, Uri suiteFolder, this.options, this.pipeline)
+ // Use the name of the folder as the test name by trimming out the prefix
+ // from the suite and the trailing `/`.
+ : name = uri.path.substring(suiteFolder.path.length, uri.path.length - 1);
+
+ Future<void> run() async {
+ ModularTest test = await loadTest(uri);
+ if (options.verbose) print(test.debugString());
+ await pipeline.run(test);
+ }
+}
+
+class Options {
+ bool showSkipped = false;
+ bool verbose = false;
+ String filter = null;
+ int shards = 1;
+ int shard = 1;
+ String configurationName;
+ Uri outputDirectory;
+
+ static Options parse(List<String> args) {
+ var parser = new ArgParser()
+ ..addFlag('verbose',
+ abbr: 'v',
+ defaultsTo: false,
+ help: 'print detailed information about the test and modular steps')
+ ..addFlag('show-skipped',
+ defaultsTo: false,
+ help: 'print the name of the tests skipped by the filtering option')
+ ..addOption('filter',
+ help: 'only run tests containing this filter as a substring')
+ ..addOption('shards',
+ help: 'total number of shards a suite is going to be split into.',
+ defaultsTo: '1')
+ ..addOption('shard',
+ help: 'which shard this script is executing. This should be between 0'
+ ' and `shards - 1`.')
+ ..addOption('output-directory',
+ help: 'location where to emit the jsonl result and log files')
+ ..addOption('configuration-name',
+ help: 'configuration name to use for emitting jsonl result files.');
+ ArgResults argResults = parser.parse(args);
+ int shards = int.tryParse(argResults['shards']) ?? 1;
+ int shard;
+ if (shards > 1) {
+ shard = int.tryParse(argResults['shard']) ?? 1;
+ if (shard <= 0 || shard >= shards) {
+ print('Error: shard should be between 0 and ${shards - 1},'
+ ' but got $shard');
+ exit(1);
+ }
+ }
+ Uri toUri(s) => s == null ? null : Uri.base.resolve(s);
+ return Options()
+ ..showSkipped = argResults['show-skipped']
+ ..verbose = argResults['verbose']
+ ..filter = argResults['filter']
+ ..shards = shards
+ ..shard = shard
+ ..configurationName = argResults['configuration-name']
+ ..outputDirectory = toUri(argResults['output-directory']);
+ }
+}
diff --git a/pkg/modular_test/lib/src/suite.dart b/pkg/modular_test/lib/src/suite.dart
index 506349b..281c381 100644
--- a/pkg/modular_test/lib/src/suite.dart
+++ b/pkg/modular_test/lib/src/suite.dart
@@ -13,8 +13,23 @@
/// The module containing the main entry method.
final Module mainModule;
- ModularTest(this.modules, this.mainModule)
- : assert(mainModule != null && modules.length > 0);
+ /// Flags provided to tools that compile and execute the test.
+ final List<String> flags;
+
+ ModularTest(this.modules, this.mainModule, this.flags) {
+ if (mainModule == null) {
+ throw ArgumentError("main module was null");
+ }
+ if (flags == null) {
+ throw ArgumentError("flags was null");
+ }
+ if (modules == null || modules.length == 0) {
+ throw ArgumentError("modules cannot be null or empty");
+ }
+ for (var module in modules) {
+ module._validate();
+ }
+ }
String debugString() => modules.map((m) => m.debugString()).join('\n');
}
@@ -43,6 +58,9 @@
/// package name matches the module name.
bool isPackage;
+ /// Whether this module represents part of the sdk.
+ bool isSdk;
+
/// When [isPackage], the base where all package URIs are resolved against.
/// Stored as a relative [Uri] from [rootUri].
final Uri packageBase;
@@ -50,16 +68,56 @@
/// Whether this is the main entry module of a test.
bool isMain;
+ /// Whether this module is test specific or shared across tests. Usually this
+ /// will be true only for the SDK and shared packages like `package:expect`.
+ bool isShared;
+
Module(this.name, this.dependencies, this.rootUri, this.sources,
{this.mainSource,
this.isPackage: false,
this.isMain: false,
- this.packageBase}) {
+ this.packageBase,
+ this.isShared: false,
+ this.isSdk: false}) {
if (!_validModuleName.hasMatch(name)) {
throw ArgumentError("invalid module name: $name");
}
}
+ void _validate() {
+ if (!isPackage && !isShared && !isSdk) return;
+
+ // Note: we validate this now and not in the constructor because loader.dart
+ // may update `isPackage` after the module is created.
+ if (isSdk && isPackage) {
+ throw InvalidModularTestError("invalid module: $name is an sdk "
+ "module but was also marked as a package module.");
+ }
+
+ for (var dependency in dependencies) {
+ if (isPackage && !dependency.isPackage && !dependency.isSdk) {
+ throw InvalidModularTestError("invalid dependency: $name is a package "
+ "but it depends on ${dependency.name}, which is not.");
+ }
+ if (isShared && !dependency.isShared) {
+ throw InvalidModularTestError(
+ "invalid dependency: $name is a shared module "
+ "but it depends on ${dependency.name}, which is not.");
+ }
+ if (isSdk) {
+ // TODO(sigmund): we should allow to split sdk modules in smaller
+ // pieces. This requires a bit of work:
+ // - allow to compile subsets of the sdk (see #30957 regarding
+ // extraRequiredLibraries in CFE)
+ // - add logic to specify sdk dependencies.
+ throw InvalidModularTestError(
+ "invalid dependency: $name is an sdk module that depends on "
+ "${dependency.name}, but sdk modules are not expected to "
+ "have dependencies.");
+ }
+ }
+ }
+
@override
String toString() => '[module $name]';
@@ -70,7 +128,11 @@
buffer.write(': ');
buffer.write(isPackage ? 'package' : '(not package)');
buffer.write(', deps: {${dependencies.map((d) => d.name).join(", ")}}');
- buffer.write(', sources: {${sources.map((u) => "$u").join(', ')}}');
+ if (isSdk) {
+ buffer.write(', sources: {...omitted ${sources.length} sources...}');
+ } else {
+ buffer.write(', sources: {${sources.map((u) => "$u").join(', ')}}');
+ }
return '$buffer';
}
}
@@ -87,3 +149,28 @@
module.dependencies.forEach(helper);
return deps;
}
+
+/// A registry that can map a test configuration to a simple id.
+///
+/// This is used to help determine whether two tests are run with the same set
+/// of flags (the same configuration), and thus pipelines could reuse the
+/// results of shared modules from the first test when running the second test.
+class ConfigurationRegistry {
+ Map<String, int> _configurationId = {};
+
+ /// Compute an id to identify the configuration of a modular test.
+ ///
+ /// A configuration is defined in terms of the set of flags provided to a
+ /// test. If two test provided to this registry share the same set of flags,
+ /// the resulting ids are the same. Similarly, if the flags are different,
+ /// their ids will be different as well.
+ int computeConfigurationId(ModularTest test) {
+ return _configurationId[test.flags.join(' ')] ??= _configurationId.length;
+ }
+}
+
+class InvalidModularTestError extends Error {
+ final String message;
+ InvalidModularTestError(this.message);
+ String toString() => "Invalid modular test: $message";
+}
diff --git a/pkg/modular_test/lib/src/test_specification_parser.dart b/pkg/modular_test/lib/src/test_specification_parser.dart
new file mode 100644
index 0000000..d0eed3d
--- /dev/null
+++ b/pkg/modular_test/lib/src/test_specification_parser.dart
@@ -0,0 +1,110 @@
+// 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 library defines how to read a test specification from a Yaml
+/// file. We expect specifications written in this format:
+///
+/// dependencies:
+/// b: a
+/// main: [b, expect]
+/// flags:
+/// - constant-update-2018
+///
+/// Where the dependencies section describe how modules depend on one another,
+/// and the flags section show what flags are needed to run that specific test.
+///
+/// When defining dependencies:
+/// - Each name corresponds to a module.
+/// - Module names correlate to either a file, a folder, or a package.
+/// - A map entry contains all the dependencies of a module, if any.
+/// - If a module has a single dependency, it can be written as a single
+/// value.
+///
+/// The logic in this library mostly treats these names as strings, separately
+/// `loader.dart` is responsible for validating and attaching this dependency
+/// information to a set of module definitions.
+///
+/// The framework is agnostic of what the flags are, but at this time we only
+/// use the name of experimental language features. These are then used to
+/// decide what options to pass to the tools that compile and run the tests.
+import 'package:yaml/yaml.dart';
+
+/// Parses [contents] containing a module dependencies specification written in
+/// yaml, and returns a [TestSpecification].
+TestSpecification parseTestSpecification(String contents) {
+ var spec = loadYaml(contents);
+ if (spec is! YamlMap) {
+ return _invalidSpecification("spec is not a map");
+ }
+ var dependencies = spec['dependencies'];
+ if (dependencies == null) {
+ return _invalidSpecification("no dependencies section");
+ }
+ if (dependencies is! YamlMap) {
+ return _invalidSpecification("dependencies is not a map");
+ }
+
+ Map<String, List<String>> normalizedMap = {};
+ dependencies.forEach((key, value) {
+ if (key is! String) {
+ _invalidSpecification("key: '$key' is not a string");
+ }
+ normalizedMap[key] = [];
+ if (value is String) {
+ normalizedMap[key].add(value);
+ } else if (value is List) {
+ value.forEach((entry) {
+ if (entry is! String) {
+ _invalidSpecification("entry: '$entry' is not a string");
+ }
+ normalizedMap[key].add(entry);
+ });
+ } else {
+ _invalidSpecification(
+ "entry: '$value' is not a string or a list of strings");
+ }
+ });
+
+ List<String> normalizedFlags = [];
+ dynamic flags = spec['flags'];
+ if (flags is String) {
+ normalizedFlags.add(flags);
+ } else if (flags is List) {
+ normalizedFlags.addAll(flags.cast<String>());
+ } else if (flags != null) {
+ _invalidSpecification(
+ "flags: '$flags' expected to be string or list of strings");
+ }
+ return new TestSpecification(normalizedFlags, normalizedMap);
+}
+
+/// Data specifying details about a modular test including dependencies and
+/// flags that are necessary in order to properly run a test.
+///
+class TestSpecification {
+ /// Set of flags necessary to properly run a test.
+ ///
+ /// Usually this contains flags enabling language experiments.
+ final List<String> flags;
+
+ /// Dependencies of the modules that are expected to exist on the test.
+ ///
+ /// Note: some values in the map may not have a corresponding key. That may be
+ /// the case for modules that have no dependencies and modules that are not
+ /// specified explicitly because they are added automatically by the framework
+ /// (for instance, the module of `package:expect` or the sdk itself).
+ final Map<String, List<String>> dependencies;
+
+ TestSpecification(this.flags, this.dependencies);
+}
+
+_invalidSpecification(String message) {
+ throw new InvalidSpecificationError(message);
+}
+
+class InvalidSpecificationError extends Error {
+ final String message;
+ InvalidSpecificationError(this.message);
+ String toString() => "Invalid specification: $message";
+}
diff --git a/pkg/modular_test/test/io_pipeline_test.dart b/pkg/modular_test/test/io_pipeline_test.dart
index dd3d01f..db980f8 100644
--- a/pkg/modular_test/test/io_pipeline_test.dart
+++ b/pkg/modular_test/test/io_pipeline_test.dart
@@ -29,14 +29,17 @@
@override
Future<Pipeline<IOModularStep>> createPipeline(
- Map<Uri, String> sources, List<IOModularStep> steps) async {
+ Map<Uri, String> sources, List<IOModularStep> steps,
+ {bool cacheSharedModules: false}) async {
await Directory.fromUri(testRootUri).create();
for (var uri in sources.keys) {
var file = new File.fromUri(uri);
await file.create(recursive: true);
await file.writeAsStringSync(sources[uri]);
}
- return new IOPipeline(steps, saveFoldersForTesting: true);
+ return new IOPipeline(steps,
+ saveIntermediateResultsForTesting: true,
+ cacheSharedModules: cacheSharedModules);
}
@override
@@ -83,17 +86,15 @@
@override
String getResult(covariant IOPipeline pipeline, Module m, DataId dataId) {
- var folderUri = pipeline.tmpFoldersForTesting[dataId];
- var file = File.fromUri(folderUri.resolve("${m.name}.${dataId.name}"));
+ var folderUri = pipeline.resultFolderUriForTesting;
+ var file = File.fromUri(folderUri
+ .resolve(pipeline.configSpecificResultFileNameForTesting(m, dataId)));
return file.existsSync() ? file.readAsStringSync() : null;
}
@override
- Future<void> cleanup(Pipeline<IOModularStep> pipeline) async {
- var folders = (pipeline as IOPipeline).tmpFoldersForTesting.values;
- for (var folder in folders) {
- await Directory.fromUri(folder).delete(recursive: true);
- }
+ Future<void> cleanup(covariant IOPipeline pipeline) async {
+ pipeline.cleanup();
await Directory.fromUri(testRootUri).delete(recursive: true);
}
}
@@ -110,8 +111,8 @@
SourceOnlyStep(this.action, this.resultId, this.needsSources);
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
Map<Uri, String> sources = {};
for (var uri in module.sources) {
@@ -122,6 +123,9 @@
await File.fromUri(root.resolveUri(toUri(module, resultId)))
.writeAsString(action(sources));
}
+
+ @override
+ void notifyCached(Module module) {}
}
class ModuleDataStep implements IOModularStep {
@@ -138,14 +142,17 @@
: moduleDataNeeded = requestInput ? [inputId] : [];
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
var inputData = await _readHelper(module, root, inputId, toUri);
var result =
inputData == null ? "data for $module was null" : action(inputData);
await File.fromUri(root.resolveUri(toUri(module, resultId)))
.writeAsString(result);
}
+
+ @override
+ void notifyCached(Module module) {}
}
class TwoOutputStep implements IOModularStep {
@@ -164,8 +171,8 @@
this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
var inputData = await _readHelper(module, root, inputId, toUri);
var result1 =
inputData == null ? "data for $module was null" : action1(inputData);
@@ -176,6 +183,9 @@
await File.fromUri(root.resolveUri(toUri(module, result2Id)))
.writeAsString(result2);
}
+
+ @override
+ void notifyCached(Module module) {}
}
class LinkStep implements IOModularStep {
@@ -194,8 +204,8 @@
: dependencyDataNeeded = requestDependencies ? [depId] : [];
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
List<String> depsData = [];
for (var dependency in module.dependencies) {
var depData = await _readHelper(dependency, root, depId, toUri);
@@ -205,6 +215,9 @@
await File.fromUri(root.resolveUri(toUri(module, resultId)))
.writeAsString(action(inputData, depsData));
}
+
+ @override
+ void notifyCached(Module module) {}
}
class MainOnlyStep implements IOModularStep {
@@ -223,8 +236,8 @@
: dependencyDataNeeded = requestDependencies ? [depId] : [];
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
List<String> depsData = [];
for (var dependency in computeTransitiveDependencies(module)) {
var depData = await _readHelper(dependency, root, depId, toUri);
@@ -234,6 +247,9 @@
await File.fromUri(root.resolveUri(toUri(module, resultId)))
.writeAsString(action(inputData, depsData));
}
+
+ @override
+ void notifyCached(Module module) {}
}
Future<String> _readHelper(Module module, Uri root, DataId dataId,
diff --git a/pkg/modular_test/test/loader/dag/expectation.txt b/pkg/modular_test/test/loader/dag/expectation.txt
index 885c41f..38220ca 100644
--- a/pkg/modular_test/test/loader/dag/expectation.txt
+++ b/pkg/modular_test/test/loader/dag/expectation.txt
@@ -2,27 +2,44 @@
a
is package? no
- dependencies: b, c
+ is shared? no
+ is sdk? no
+ dependencies: b, c, sdk
a.dart
b
is package? no
- dependencies: d
+ is shared? no
+ is sdk? no
+ dependencies: d, sdk
b.dart
c
is package? no
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
c.dart
d
is package? no
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
d/d.dart
d/e.dart
main
**main module**
is package? no
- dependencies: a, b
+ is shared? no
+ is sdk? no
+ dependencies: a, b, sdk
main.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/dag_with_packages/.packages b/pkg/modular_test/test/loader/dag_with_packages/.packages
index 5f1a721..194aba9 100644
--- a/pkg/modular_test/test/loader/dag_with_packages/.packages
+++ b/pkg/modular_test/test/loader/dag_with_packages/.packages
@@ -1,2 +1,4 @@
a:a/
+b:b/
+d:d/
c:c/
diff --git a/pkg/modular_test/test/loader/dag_with_packages/expectation.txt b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
index df35ba5..961d6b8 100644
--- a/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
+++ b/pkg/modular_test/test/loader/dag_with_packages/expectation.txt
@@ -2,27 +2,44 @@
a
is package? yes
- dependencies: b, c
+ is shared? no
+ is sdk? no
+ dependencies: b, c, sdk
a.dart
b
- is package? no
- dependencies: d
+ is package? yes
+ is shared? no
+ is sdk? no
+ dependencies: d, sdk
b.dart
c
is package? yes
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
c.dart
d
- is package? no
- (no dependencies)
+ is package? yes
+ is shared? no
+ is sdk? no
+ dependencies: sdk
d/d.dart
d/e.dart
main
**main module**
is package? no
- dependencies: a, b
+ is shared? no
+ is sdk? no
+ dependencies: a, b, sdk
main.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
index cf449f3..48e0849 100644
--- a/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
+++ b/pkg/modular_test/test/loader/default_package_dependency_error/expectation.txt
@@ -2,7 +2,9 @@
expect
is package? yes
- dependencies: meta
+ is shared? yes
+ is sdk? no
+ dependencies: meta, sdk
lib/expect.dart
lib/matchers_lite.dart
lib/minitest.dart
@@ -10,11 +12,22 @@
main
**main module**
is package? no
- dependencies: expect
+ is shared? no
+ is sdk? no
+ dependencies: expect, sdk
main.dart
meta
is package? yes
- (no dependencies)
+ is shared? yes
+ is sdk? no
+ dependencies: sdk
lib/dart2js.dart
lib/meta.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/loader_test.dart b/pkg/modular_test/test/loader/loader_test.dart
index 4f5f59c..39b3081 100644
--- a/pkg/modular_test/test/loader/loader_test.dart
+++ b/pkg/modular_test/test/loader/loader_test.dart
@@ -4,34 +4,27 @@
/// Tests that the logic to load, parse, and validate modular tests.
import 'dart:io';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
+
+import 'package:test/test.dart';
import 'package:modular_test/src/loader.dart';
import 'package:modular_test/src/suite.dart';
import 'package:args/args.dart';
-main(List<String> args) {
+main(List<String> args) async {
var options = _Options.parse(args);
- asyncTest(() async {
- var baseUri = Platform.script.resolve('./');
- var baseDir = Directory.fromUri(baseUri);
- await for (var entry in baseDir.list(recursive: false)) {
- if (entry is Directory) {
- await _runTest(entry.uri, baseUri, options);
- }
+ var baseUri = Platform.script.resolve('./');
+ var baseDir = Directory.fromUri(baseUri);
+ await for (var entry in baseDir.list(recursive: false)) {
+ if (entry is Directory) {
+ var dirName = entry.uri.path.substring(baseDir.path.length);
+ test(dirName, () => _runTest(entry.uri, dirName, options),
+ skip: options.filter != null && !dirName.contains(options.filter));
}
- });
+ }
}
-Future<void> _runTest(Uri uri, Uri baseDir, _Options options) async {
- var dirName = uri.path.substring(baseDir.path.length);
- if (options.filter != null && !dirName.contains(options.filter)) {
- if (options.showSkipped) print("skipped: $dirName");
- return;
- }
-
- print("testing: $dirName");
+Future<void> _runTest(Uri uri, String dirName, _Options options) async {
String result;
String header =
"# This expectation file is generated by loader_test.dart\n\n";
@@ -44,7 +37,8 @@
var file = File.fromUri(uri.resolve('expectation.txt'));
if (!options.updateExpectations) {
- Expect.isTrue(await file.exists(), "expectation.txt file is missing");
+ expect(await file.exists(), isTrue,
+ reason: "expectation.txt file is missing");
var expectation = await file.readAsString();
if (expectation != result) {
print("expectation.txt doesn't match the result of the test. "
@@ -52,8 +46,7 @@
" ${Platform.executable} ${Platform.script} "
"--update --show-update --filter $dirName");
}
- Expect.equals(expectation, result);
- print(" expectation matches result.");
+ expect(expectation, result);
} else if (await file.exists() && (await file.readAsString() == result)) {
print(" expectation matches result and was up to date.");
} else {
@@ -76,10 +69,12 @@
}
buffer.write(module.name);
if (module.isMain) {
- Expect.equals(test.mainModule, module);
+ expect(test.mainModule, module);
buffer.write('\n **main module**');
}
buffer.write('\n is package? ${module.isPackage ? 'yes' : 'no'}');
+ buffer.write('\n is shared? ${module.isShared ? 'yes' : 'no'}');
+ buffer.write('\n is sdk? ${module.isSdk ? 'yes' : 'no'}');
if (module.dependencies.isEmpty) {
buffer.write('\n (no dependencies)');
} else {
@@ -89,6 +84,8 @@
if (module.sources.isEmpty) {
buffer.write('\n (no sources)');
+ } else if (module.isSdk) {
+ buffer.write('\n (sdk sources omitted)');
} else {
module.sources.forEach((uri) {
buffer.write('\n $uri');
@@ -103,7 +100,6 @@
class _Options {
bool updateExpectations = false;
bool showResultOnUpdate = false;
- bool showSkipped = false;
String filter = null;
static _Options parse(List<String> args) {
@@ -124,7 +120,6 @@
return _Options()
..updateExpectations = argResults['update']
..showResultOnUpdate = argResults['show-update']
- ..showSkipped = argResults['show-skipped']
..filter = argResults['filter'];
}
}
diff --git a/pkg/modular_test/test/loader/no_dependencies/expectation.txt b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
index f19449b..8af18d5 100644
--- a/pkg/modular_test/test/loader/no_dependencies/expectation.txt
+++ b/pkg/modular_test/test/loader/no_dependencies/expectation.txt
@@ -3,5 +3,14 @@
main
**main module**
is package? no
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
main.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/tree/expectation.txt b/pkg/modular_test/test/loader/tree/expectation.txt
index f438e22..d2c3d88 100644
--- a/pkg/modular_test/test/loader/tree/expectation.txt
+++ b/pkg/modular_test/test/loader/tree/expectation.txt
@@ -2,27 +2,44 @@
a
is package? no
- dependencies: b, c
+ is shared? no
+ is sdk? no
+ dependencies: b, c, sdk
a.dart
b
is package? no
- dependencies: d
+ is shared? no
+ is sdk? no
+ dependencies: d, sdk
b.dart
c
is package? no
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
c.dart
d
is package? no
- (no dependencies)
+ is shared? no
+ is sdk? no
+ dependencies: sdk
d/d.dart
d/e.dart
main
**main module**
is package? no
- dependencies: a
+ is shared? no
+ is sdk? no
+ dependencies: a, sdk
main.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/loader/valid_packages/expectation.txt b/pkg/modular_test/test/loader/valid_packages/expectation.txt
index dab4163..4ef3034 100644
--- a/pkg/modular_test/test/loader/valid_packages/expectation.txt
+++ b/pkg/modular_test/test/loader/valid_packages/expectation.txt
@@ -2,14 +2,18 @@
expect
is package? yes
- dependencies: meta
+ is shared? yes
+ is sdk? no
+ dependencies: meta, sdk
lib/expect.dart
lib/matchers_lite.dart
lib/minitest.dart
js
is package? yes
- (no dependencies)
+ is shared? yes
+ is sdk? no
+ dependencies: sdk
lib/js.dart
lib/js_util.dart
lib/src/varargs.dart
@@ -17,11 +21,22 @@
main
**main module**
is package? no
- dependencies: js, expect
+ is shared? no
+ is sdk? no
+ dependencies: js, expect, sdk
main.dart
meta
is package? yes
- (no dependencies)
+ is shared? yes
+ is sdk? no
+ dependencies: sdk
lib/dart2js.dart
lib/meta.dart
+
+sdk
+ is package? no
+ is shared? yes
+ is sdk? yes
+ (no dependencies)
+ (sdk sources omitted)
diff --git a/pkg/modular_test/test/memory_pipeline_test.dart b/pkg/modular_test/test/memory_pipeline_test.dart
index ba406e1..1d4da36 100644
--- a/pkg/modular_test/test/memory_pipeline_test.dart
+++ b/pkg/modular_test/test/memory_pipeline_test.dart
@@ -22,8 +22,10 @@
@override
FutureOr<Pipeline<MemoryModularStep>> createPipeline(
- Map<Uri, String> sources, List<MemoryModularStep> steps) {
- return new MemoryPipeline(sources, steps);
+ Map<Uri, String> sources, List<MemoryModularStep> steps,
+ {bool cacheSharedModules: false}) {
+ return new MemoryPipeline(sources, steps,
+ cacheSharedModules: cacheSharedModules);
}
@override
@@ -87,14 +89,20 @@
SourceOnlyStep(this.action, this.resultId, this.needsSources);
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags) {
Map<Uri, String> sources = {};
for (var uri in module.sources) {
sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
}
return Future.value({resultId: action(sources)});
}
+
+ @override
+ void notifyCached(Module module) {}
}
class ModuleDataStep implements MemoryModularStep {
@@ -110,13 +118,19 @@
ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
: moduleDataNeeded = requestInput ? [inputId] : [];
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags) {
var inputData = dataProvider(module, inputId) as String;
if (inputData == null)
return Future.value({resultId: "data for $module was null"});
return Future.value({resultId: action(inputData)});
}
+
+ @override
+ void notifyCached(Module module) {}
}
class TwoOutputStep implements MemoryModularStep {
@@ -134,8 +148,11 @@
TwoOutputStep(
this.action1, this.action2, this.inputId, this.result1Id, this.result2Id);
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags) {
var inputData = dataProvider(module, inputId) as String;
if (inputData == null)
return Future.value({
@@ -145,6 +162,9 @@
return Future.value(
{result1Id: action1(inputData), result2Id: action2(inputData)});
}
+
+ @override
+ void notifyCached(Module module) {}
}
class LinkStep implements MemoryModularStep {
@@ -162,14 +182,20 @@
bool requestDependencies)
: dependencyDataNeeded = requestDependencies ? [depId] : [];
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags) {
List<String> depsData = module.dependencies
.map((d) => dataProvider(d, depId) as String)
.toList();
var inputData = dataProvider(module, inputId) as String;
return Future.value({resultId: action(inputData, depsData)});
}
+
+ @override
+ void notifyCached(Module module) {}
}
class MainOnlyStep implements MemoryModularStep {
@@ -187,12 +213,18 @@
bool requestDependencies)
: dependencyDataNeeded = requestDependencies ? [depId] : [];
- Future<Map<DataId, Object>> execute(Module module,
- SourceProvider sourceProvider, ModuleDataProvider dataProvider) {
+ Future<Map<DataId, Object>> execute(
+ Module module,
+ SourceProvider sourceProvider,
+ ModuleDataProvider dataProvider,
+ List<String> flags) {
List<String> depsData = computeTransitiveDependencies(module)
.map((d) => dataProvider(d, depId) as String)
.toList();
var inputData = dataProvider(module, inputId) as String;
return Future.value({resultId: action(inputData, depsData)});
}
+
+ @override
+ void notifyCached(Module module) {}
}
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
index b09e611..7bfbf77 100644
--- a/pkg/modular_test/test/pipeline_common.dart
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -28,7 +28,8 @@
/// Creates a pipeline with the given sources and steps. Steps will be created
/// by other methods in this strategy to ensure they are compatible with to
/// the pipeline created here.
- FutureOr<Pipeline<S>> createPipeline(Map<Uri, String> sources, List<S> steps);
+ FutureOr<Pipeline<S>> createPipeline(Map<Uri, String> sources, List<S> steps,
+ {bool cacheSharedModules: false});
/// Create a step that applies [action] on all input files of the module, and
/// emits a result with the given [id]
@@ -98,15 +99,16 @@
};
var m1 = Module("a", const [], testStrategy.testRootUri,
- [Uri.parse("a1.dart"), Uri.parse("a2.dart")]);
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isShared: true);
var m2 = Module("b", [m1], testStrategy.testRootUri,
[Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")]);
var m3 = Module("c", [m2], testStrategy.testRootUri, [Uri.parse("c.dart")],
isMain: true);
- var singleModuleInput = ModularTest([m1], m1);
- var twoModuleInput = ModularTest([m1, m2], m2);
- var threeModuleInput = ModularTest([m1, m2, m3], m3);
+ var singleModuleInput = ModularTest([m1], m1, []);
+ var twoModuleInput = ModularTest([m1, m2], m2, []);
+ var threeModuleInput = ModularTest([m1, m2, m3], m3, []);
test('can read source data if requested', () async {
var concatStep =
@@ -310,6 +312,106 @@
expect(testStrategy.getResult(pipeline, m3, _joinId), "null\nnull\nc c0\n");
await testStrategy.cleanup(pipeline);
});
+
+ test('no reuse of existing results if not caching', () async {
+ int i = 1;
+ const counterId = const DataId("counter");
+ const linkId = const DataId("link");
+ // This step is not idempotent, we do this purposely to test whether caching
+ // is taking place.
+ var counterStep = testStrategy.createSourceOnlyStep(
+ action: (_) => '${i++}', resultId: counterId);
+ var linkStep = testStrategy.createLinkStep(
+ action: (String m, List<String> deps) => "${deps.join(',')},$m",
+ inputId: counterId,
+ depId: counterId,
+ resultId: linkId,
+ requestDependenciesData: true);
+ var pipeline = await testStrategy.createPipeline(
+ sources, <S>[counterStep, linkStep],
+ cacheSharedModules: false);
+ await pipeline.run(twoModuleInput);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+ expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+ await pipeline.run(threeModuleInput);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "3");
+ expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+ expect(testStrategy.getResult(pipeline, m3, counterId), "5");
+ expect(testStrategy.getResult(pipeline, m3, linkId), "4,5");
+
+ await testStrategy.cleanup(pipeline);
+ });
+
+ test('caching reuses existing results for the same configuration', () async {
+ int i = 1;
+ const counterId = const DataId("counter");
+ const linkId = const DataId("link");
+ var counterStep = testStrategy.createSourceOnlyStep(
+ action: (_) => '${i++}', resultId: counterId);
+ var linkStep = testStrategy.createLinkStep(
+ action: (String m, List<String> deps) => "${deps.join(',')},$m",
+ inputId: counterId,
+ depId: counterId,
+ resultId: linkId,
+ requestDependenciesData: true);
+ var pipeline = await testStrategy.createPipeline(
+ sources, <S>[counterStep, linkStep],
+ cacheSharedModules: true);
+ await pipeline.run(twoModuleInput);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+ expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+ await pipeline.run(threeModuleInput);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "1"); // cached!
+ expect(testStrategy.getResult(pipeline, m2, counterId), "3");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "1,3");
+ expect(testStrategy.getResult(pipeline, m3, counterId), "4");
+ expect(testStrategy.getResult(pipeline, m3, linkId), "3,4");
+
+ await testStrategy.cleanup(pipeline);
+ });
+
+ test('no reuse of existing results on different configurations', () async {
+ int i = 1;
+ const counterId = const DataId("counter");
+ const linkId = const DataId("link");
+ // This step is not idempotent, we do this purposely to test whether caching
+ // is taking place.
+ var counterStep = testStrategy.createSourceOnlyStep(
+ action: (_) => '${i++}', resultId: counterId);
+ var linkStep = testStrategy.createLinkStep(
+ action: (String m, List<String> deps) => "${deps.join(',')},$m",
+ inputId: counterId,
+ depId: counterId,
+ resultId: linkId,
+ requestDependenciesData: true);
+ var pipeline = await testStrategy.createPipeline(
+ sources, <S>[counterStep, linkStep],
+ cacheSharedModules: true);
+ var input1 = ModularTest([m1, m2], m2, []);
+ var input2 = ModularTest([m1, m2], m2, ['--foo']);
+ var input3 = ModularTest([m1, m2], m2, ['--foo']);
+ await pipeline.run(input1);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "1");
+ expect(testStrategy.getResult(pipeline, m2, counterId), "2");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "1,2");
+
+ await pipeline.run(input2);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // no cache!
+ expect(testStrategy.getResult(pipeline, m2, counterId), "4");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "3,4");
+
+ await pipeline.run(input3);
+ expect(testStrategy.getResult(pipeline, m1, counterId), "3"); // same config
+ expect(testStrategy.getResult(pipeline, m2, counterId), "5");
+ expect(testStrategy.getResult(pipeline, m2, linkId), "3,5");
+
+ await testStrategy.cleanup(pipeline);
+ });
}
DataId _concatId = const DataId("concat");
diff --git a/pkg/modular_test/test/dependency_parser_test.dart b/pkg/modular_test/test/specification_parser_test.dart
similarity index 63%
rename from pkg/modular_test/test/dependency_parser_test.dart
rename to pkg/modular_test/test/specification_parser_test.dart
index f536282..6940d5e9 100644
--- a/pkg/modular_test/test/dependency_parser_test.dart
+++ b/pkg/modular_test/test/specification_parser_test.dart
@@ -3,46 +3,46 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:test/test.dart';
-import 'package:modular_test/src/dependency_parser.dart';
+import 'package:modular_test/src/test_specification_parser.dart';
main() {
test('require dependencies section', () {
- expect(() => parseDependencyMap(""),
+ expect(() => parseTestSpecification(""),
throwsA(TypeMatcher<InvalidSpecificationError>()));
});
test('dependencies is a map', () {
- expect(() => parseDependencyMap("dependencies: []"),
+ expect(() => parseTestSpecification("dependencies: []"),
throwsA(TypeMatcher<InvalidSpecificationError>()));
});
test('dependencies can be a string or list of strings', () {
- parseDependencyMap('''
+ parseTestSpecification('''
dependencies:
a: b
''');
- parseDependencyMap('''
+ parseTestSpecification('''
dependencies:
a: [b, c]
''');
- expect(() => parseDependencyMap('''
+ expect(() => parseTestSpecification('''
dependencies:
a: 1
'''), throwsA(TypeMatcher<InvalidSpecificationError>()));
- expect(() => parseDependencyMap('''
+ expect(() => parseTestSpecification('''
dependencies:
a: true
'''), throwsA(TypeMatcher<InvalidSpecificationError>()));
- expect(() => parseDependencyMap('''
+ expect(() => parseTestSpecification('''
dependencies:
a: [false]
'''), throwsA(TypeMatcher<InvalidSpecificationError>()));
- expect(() => parseDependencyMap('''
+ expect(() => parseTestSpecification('''
dependencies:
a:
c: d
@@ -51,14 +51,26 @@
test('result map is normalized', () {
expect(
- parseDependencyMap('''
+ parseTestSpecification('''
dependencies:
a: [b, c]
b: d
- '''),
+ ''').dependencies,
equals({
'a': ['b', 'c'],
'b': ['d'],
}));
});
+
+ test('flags are normalized', () {
+ expect(parseTestSpecification('''
+ dependencies: {}
+ flags: "a"
+ ''').flags, equals(["a"]));
+
+ expect(parseTestSpecification('''
+ dependencies: {}
+ flags: ["a"]
+ ''').flags, equals(["a"]));
+ });
}
diff --git a/pkg/modular_test/test/validate_test.dart b/pkg/modular_test/test/validate_pipeline_test.dart
similarity index 92%
rename from pkg/modular_test/test/validate_test.dart
rename to pkg/modular_test/test/validate_pipeline_test.dart
index 8394dfe..a0b5759 100644
--- a/pkg/modular_test/test/validate_test.dart
+++ b/pkg/modular_test/test/validate_pipeline_test.dart
@@ -27,7 +27,7 @@
]);
});
- test('circular dependency is not allowed', () {
+ test('circular step dependency is not allowed', () {
var id1 = DataId("data_a");
expect(
() => validateSteps([
@@ -78,10 +78,10 @@
/// An implementation of [Pipeline] that simply validates the steps, but doesn't
/// do anything else.
class _NoopPipeline extends Pipeline {
- _NoopPipeline(List<ModularStep> steps) : super(steps);
+ _NoopPipeline(List<ModularStep> steps) : super(steps, false);
@override
Future<void> runStep(ModularStep step, Module module,
- Map<Module, Set<DataId>> visibleData) =>
+ Map<Module, Set<DataId>> visibleData, List<String> flags) =>
null;
}
diff --git a/pkg/modular_test/test/validate_suite_test.dart b/pkg/modular_test/test/validate_suite_test.dart
new file mode 100644
index 0000000..f335567
--- /dev/null
+++ b/pkg/modular_test/test/validate_suite_test.dart
@@ -0,0 +1,92 @@
+// 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.
+
+/// Unit test for validation of modular steps in a pipeline.
+import 'package:test/test.dart';
+import 'package:modular_test/src/suite.dart';
+
+main() {
+ test('module test is not empty', () {
+ expect(
+ () => ModularTest([], null, []), throwsA(TypeMatcher<ArgumentError>()));
+
+ var m = Module("a", [], Uri.parse("app:/"), []);
+ expect(() => ModularTest([], m, []), throwsA(TypeMatcher<ArgumentError>()));
+ });
+
+ test('module test must have a main module', () {
+ var m = Module("a", [], Uri.parse("app:/"), []);
+ expect(() => ModularTest([m], null, []),
+ throwsA(TypeMatcher<ArgumentError>()));
+ });
+
+ test('package must depend on package', () {
+ var m1a = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isPackage: false);
+ var m1b = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isPackage: true);
+
+ var m2a = Module("b", [m1a], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isPackage: true);
+ var m2b = Module("b", [m1b], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isPackage: true);
+ expect(() => ModularTest([m1a, m2a], m2a, []),
+ throwsA(TypeMatcher<InvalidModularTestError>()));
+ expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+ });
+
+ test('shared module must depend on shared modules', () {
+ var m1a = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isShared: false);
+ var m1b = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isShared: true);
+
+ var m2a = Module("b", [m1a], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isShared: true);
+ var m2b = Module("b", [m1b], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isShared: true);
+ expect(() => ModularTest([m1a, m2a], m2a, []),
+ throwsA(TypeMatcher<InvalidModularTestError>()));
+ expect(ModularTest([m1b, m2b], m2b, []), isNotNull);
+ });
+
+ test('sdk module must not have dependencies', () {
+ var m1a = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isSdk: false);
+ var m1b = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isSdk: true);
+
+ var m2a = Module("b", [m1a], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isSdk: true);
+ var m2b = Module("b", [m1b], Uri.parse("app:/"),
+ [Uri.parse("b/b1.dart"), Uri.parse("b/b2.dart")],
+ isSdk: true);
+ expect(() => ModularTest([m1a, m2a], m2a, []),
+ throwsA(TypeMatcher<InvalidModularTestError>()));
+ expect(() => ModularTest([m1b, m2b], m2b, []),
+ throwsA(TypeMatcher<InvalidModularTestError>()));
+ });
+
+ test('sdk module cannot be package module', () {
+ var m = Module("a", const [], Uri.parse("app:/"),
+ [Uri.parse("a1.dart"), Uri.parse("a2.dart")],
+ isSdk: true);
+ expect(ModularTest([m], m, []), isNotNull);
+
+ m.isPackage = true;
+ expect(() => ModularTest([m], m, []),
+ throwsA(TypeMatcher<InvalidModularTestError>()));
+ });
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 881f093..26698f9 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -24,6 +24,7 @@
analyzer/test/src/summary/resynthesize_kernel_test: Slow, Pass
analyzer/test/src/task/strong/checker_test: Slow, Pass
analyzer_plugin/test/plugin/folding_mixin_test: Slow, Pass
+dev_compiler/test/modular/*: Slow, Pass
dev_compiler/test/options/*: Skip # test needs fixes
dev_compiler/test/sourcemap/*: SkipByDesign # Skip sourcemap tests
dev_compiler/test/sourcemap/testfiles/*: SkipByDesign # Skip dev_compiler codegen tests
@@ -178,10 +179,10 @@
[ $compiler != dart2analyzer && $runtime != vm ]
dev_compiler/test/*: Skip
-modular_test/test/dependency_parser_test: SkipByDesign
modular_test/test/find_sdk_root1_test: SkipByDesign
modular_test/test/io_pipeline_test: SkipByDesign
modular_test/test/loader/loader_test: SkipByDesign
+modular_test/test/specification_parser_test: SkipByDesign
modular_test/test/src/find_sdk_root2_test: SkipByDesign
[ $compiler == dart2js && $runtime == chrome && $system == macos ]
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 1b1c268..62dbee4 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -8,7 +8,7 @@
// - "windows" -> "win".
// - "macos" -> "mac".
// - toString() on enum classes is just name.
-// - builderTag defaults to empty string, not null.
+// - builderTag and babel default to empty string, not null.
// Need to migrate test.dart to not expect the above before it can use this.
// READ ME! If you add a new field to this, make sure to add it to
@@ -247,6 +247,7 @@
var configuration = Configuration(
name, architecture, compiler, mode, runtime, system,
+ babel: stringOption("babel"),
builderTag: stringOption("builder-tag"),
vmOptions: stringListOption("vm-options"),
dart2jsOptions: stringListOption("dart2js-options"),
@@ -260,6 +261,7 @@
useAnalyzerCfe: boolOption("use-cfe"),
useAnalyzerFastaParser: boolOption("analyzer-use-fasta-parser"),
useBlobs: boolOption("use-blobs"),
+ useElf: boolOption("use-elf"),
useHotReload: boolOption("hot-reload"),
useHotReloadRollback: boolOption("hot-reload-rollback"),
useSdk: boolOption("use-sdk"));
@@ -284,13 +286,15 @@
final System system;
+ final String babel;
+
final String builderTag;
final List<String> vmOptions;
final List<String> dart2jsOptions;
- int timeout;
+ final int timeout;
final bool enableAsserts;
@@ -313,6 +317,7 @@
// TODO(rnystrom): What is this?
final bool useBlobs;
+ final bool useElf;
final bool useHotReload;
final bool useHotReloadRollback;
@@ -321,7 +326,8 @@
Configuration(this.name, this.architecture, this.compiler, this.mode,
this.runtime, this.system,
- {String builderTag,
+ {String babel,
+ String builderTag,
List<String> vmOptions,
List<String> dart2jsOptions,
int timeout,
@@ -334,13 +340,15 @@
bool useAnalyzerCfe,
bool useAnalyzerFastaParser,
bool useBlobs,
+ bool useElf,
bool useHotReload,
bool useHotReloadRollback,
bool useSdk})
- : builderTag = builderTag ?? "",
+ : babel = babel ?? "",
+ builderTag = builderTag ?? "",
vmOptions = vmOptions ?? <String>[],
dart2jsOptions = dart2jsOptions ?? <String>[],
- timeout = timeout,
+ timeout = timeout ?? -1,
enableAsserts = enableAsserts ?? false,
isChecked = isChecked ?? false,
isCsp = isCsp ?? false,
@@ -350,6 +358,7 @@
useAnalyzerCfe = useAnalyzerCfe ?? false,
useAnalyzerFastaParser = useAnalyzerFastaParser ?? false,
useBlobs = useBlobs ?? false,
+ useElf = useElf ?? false,
useHotReload = useHotReload ?? false,
useHotReloadRollback = useHotReloadRollback ?? false,
useSdk = useSdk ?? false;
@@ -362,6 +371,7 @@
mode == other.mode &&
runtime == other.runtime &&
system == other.system &&
+ babel == other.babel &&
builderTag == other.builderTag &&
vmOptions.join(" & ") == other.vmOptions.join(" & ") &&
dart2jsOptions.join(" & ") == other.dart2jsOptions.join(" & ") &&
@@ -375,6 +385,7 @@
useAnalyzerCfe == other.useAnalyzerCfe &&
useAnalyzerFastaParser == other.useAnalyzerFastaParser &&
useBlobs == other.useBlobs &&
+ useElf == other.useElf &&
useHotReload == other.useHotReload &&
useHotReloadRollback == other.useHotReloadRollback &&
useSdk == other.useSdk;
@@ -392,6 +403,7 @@
mode.hashCode ^
runtime.hashCode ^
system.hashCode ^
+ babel.hashCode ^
builderTag.hashCode ^
vmOptions.join(" & ").hashCode ^
dart2jsOptions.join(" & ").hashCode ^
@@ -406,6 +418,7 @@
useAnalyzerCfe,
useAnalyzerFastaParser,
useBlobs,
+ useElf,
useHotReload,
useHotReloadRollback,
useSdk
@@ -423,11 +436,13 @@
fields.add("runtime: $runtime");
fields.add("system: $system");
- if (builderTag != "") fields.add("builder-tag: $builderTag");
- if (vmOptions != "") fields.add("vm-options: [${vmOptions.join(", ")}]");
- if (dart2jsOptions != "")
+ if (babel.isNotEmpty) fields.add("babel: $babel");
+ if (builderTag.isNotEmpty) fields.add("builder-tag: $builderTag");
+ if (vmOptions.isNotEmpty)
+ fields.add("vm-options: [${vmOptions.join(", ")}]");
+ if (dart2jsOptions.isNotEmpty)
fields.add("dart2js-options: [${dart2jsOptions.join(", ")}]");
- if (timeout != 0) fields.add("timeout: $timeout");
+ if (timeout > 0) fields.add("timeout: $timeout");
if (enableAsserts) fields.add("enable-asserts");
if (isChecked) fields.add("checked");
if (isCsp) fields.add("csp");
@@ -458,20 +473,25 @@
fields.add("runtime: $runtime ${other.runtime}");
fields.add("system: $system ${other.system}");
- if (builderTag != "" || other.builderTag != "") {
- var tag = builderTag == "" ? "(none)" : builderTag;
- var otherTag = other.builderTag == "" ? "(none)" : other.builderTag;
- fields.add("builder-tag: $tag $otherTag");
+ if (babel.isNotEmpty || other.babel.isNotEmpty) {
+ var ours = babel == "" ? "(none)" : babel;
+ var theirs = other.babel == "" ? "(none)" : other.babel;
+ fields.add("babel: $ours $theirs");
}
- if (vmOptions != "" || other.vmOptions != "") {
- var tag = "[${vmOptions.join(", ")}]";
- var otherTag = "[${other.vmOptions.join(", ")}]";
- fields.add("vm-options: $tag $otherTag");
+ if (builderTag.isNotEmpty || other.builderTag.isNotEmpty) {
+ var ours = builderTag == "" ? "(none)" : builderTag;
+ var theirs = other.builderTag == "" ? "(none)" : other.builderTag;
+ fields.add("builder-tag: $ours $theirs");
}
- if (dart2jsOptions != "" || other.dart2jsOptions != "") {
- var tag = "[${dart2jsOptions.join(", ")}]";
- var otherTag = "[${other.dart2jsOptions.join(", ")}]";
- fields.add("dart2js-options: $tag $otherTag");
+ if (vmOptions.isNotEmpty || other.vmOptions.isNotEmpty) {
+ var ours = "[${vmOptions.join(", ")}]";
+ var theirs = "[${other.vmOptions.join(", ")}]";
+ fields.add("vm-options: $ours $theirs");
+ }
+ if (dart2jsOptions.isNotEmpty || other.dart2jsOptions.isNotEmpty) {
+ var ours = "[${dart2jsOptions.join(", ")}]";
+ var theirs = "[${other.dart2jsOptions.join(", ")}]";
+ fields.add("dart2js-options: $ours $theirs");
}
fields.add("timeout: $timeout ${other.timeout}");
if (enableAsserts || other.enableAsserts) {
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index 619c943..be1e4ee 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -146,7 +146,10 @@
if (options.bytecode && errors.isEmpty) {
await runWithFrontEndCompilerContext(script, options, component, () {
// TODO(alexmarkov): pass environment defines
- generateBytecode(component);
+ // TODO(alexmarkov): disable source positions and local variables
+ // in VM PRODUCT mode.
+ generateBytecode(component,
+ emitSourcePositions: true, emitLocalVarInfo: true);
});
}
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index b71650b..6401815 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -8,6 +8,7 @@
import 'dbc.dart';
import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
import 'source_positions.dart' show SourcePositions;
class Label {
@@ -53,6 +54,7 @@
// TODO(alexmarkov): figure out more efficient storage for generated bytecode.
final List<int> bytecode = new List<int>();
final ExceptionsTable exceptionsTable = new ExceptionsTable();
+ final LocalVariableTable localVariableTable = new LocalVariableTable();
final SourcePositions sourcePositions = new SourcePositions();
bool isUnreachable = false;
int currentSourcePosition = TreeNode.noOffset;
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index 4845307..db9fa71 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -386,15 +386,42 @@
return buf.getFloat64(0, Endian.little);
}
-class NamedEntryStatistics {
- final String name;
- int size = 0;
- int count = 0;
+class PackedUInt30DeltaEncoder {
+ int _last = 0;
- NamedEntryStatistics(this.name);
+ void write(BufferedWriter write, int value) {
+ write.writePackedUInt30(value - _last);
+ _last = value;
+ }
+}
- String toString() => "${name.padRight(40)}: ${size.toString().padLeft(10)}"
- " (count: ${count.toString().padLeft(8)})";
+class PackedUInt30DeltaDecoder {
+ int _last = 0;
+
+ int read(BufferedReader reader) {
+ int value = reader.readPackedUInt30() + _last;
+ _last = value;
+ return value;
+ }
+}
+
+class SLEB128DeltaEncoder {
+ int _last = 0;
+
+ void write(BufferedWriter writer, int value) {
+ writer.writeSLEB128(value - _last);
+ _last = value;
+ }
+}
+
+class SLEB128DeltaDecoder {
+ int _last = 0;
+
+ int read(BufferedReader reader) {
+ int value = reader.readSLEB128() + _last;
+ _last = value;
+ return value;
+ }
}
class LinkWriter {
@@ -428,6 +455,17 @@
}
}
+class NamedEntryStatistics {
+ final String name;
+ int size = 0;
+ int count = 0;
+
+ NamedEntryStatistics(this.name);
+
+ String toString() => "${name.padRight(40)}: ${size.toString().padLeft(10)}"
+ " (count: ${count.toString().padLeft(8)})";
+}
+
class BytecodeSizeStatistics {
static int componentSize = 0;
static int objectTableSize = 0;
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 2ee6f20..351a3e7 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -10,7 +10,7 @@
/// Before bumping current bytecode version format, make sure that
/// all users have switched to a VM which is able to consume new
/// version of bytecode.
-const int currentBytecodeFormatVersion = 7;
+const int currentBytecodeFormatVersion = 9;
/// Version of experimental / bleeding edge bytecode format.
/// Produced by bytecode generator when --use-future-bytecode-format
diff --git a/pkg/vm/lib/bytecode/declarations.dart b/pkg/vm/lib/bytecode/declarations.dart
index 5fde12c..1d8cfc5 100644
--- a/pkg/vm/lib/bytecode/declarations.dart
+++ b/pkg/vm/lib/bytecode/declarations.dart
@@ -12,6 +12,7 @@
show currentBytecodeFormatVersion, futureBytecodeFormatVersion;
import 'disassembler.dart' show BytecodeDisassembler;
import 'exceptions.dart' show ExceptionsTable;
+import 'local_variable_table.dart' show LocalVariableTable;
import 'object_table.dart' show ObjectTable, ObjectHandle, NameAndType;
import 'source_positions.dart' show SourcePositions;
@@ -140,10 +141,10 @@
((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
final position = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final endPosition = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final initializerCode =
((flags & hasInitializerFlag) != 0 && (flags & isStaticFlag) != 0)
? reader.readLinkOffset<Code>()
@@ -298,10 +299,10 @@
((flags & hasCustomScriptFlag) != 0) ? reader.readPackedObject() : null;
final position = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final endPosition = ((flags & hasSourcePositionsFlag) != 0)
? reader.readPackedUInt30() - 1
- : 0;
+ : TreeNode.noOffset;
final typeParameters = ((flags & hasTypeParamsFlag) != 0)
? new TypeParametersDeclaration.read(reader)
: null;
@@ -491,11 +492,13 @@
static const hasParameterFlagsFlag = 1 << 4;
static const hasForwardingStubTargetFlag = 1 << 5;
static const hasDefaultFunctionTypeArgsFlag = 1 << 6;
+ static const hasLocalVariablesFlag = 1 << 7;
final ConstantPool constantPool;
final List<int> bytecodes;
final ExceptionsTable exceptionsTable;
final SourcePositions sourcePositions;
+ final LocalVariableTable localVariables;
final List<ObjectHandle> nullableFields;
final List<ClosureDeclaration> closures;
final List<int> parameterFlags;
@@ -505,6 +508,8 @@
bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
bool get hasSourcePositions =>
sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+ bool get hasLocalVariables =>
+ localVariables != null && localVariables.isNotEmpty;
bool get hasNullableFields => nullableFields.isNotEmpty;
bool get hasClosures => closures.isNotEmpty;
@@ -517,13 +522,15 @@
(forwardingStubTargetCpIndex != null ? hasForwardingStubTargetFlag : 0) |
(defaultFunctionTypeArgsCpIndex != null
? hasDefaultFunctionTypeArgsFlag
- : 0);
+ : 0) |
+ (hasLocalVariables ? hasLocalVariablesFlag : 0);
Code(
this.constantPool,
this.bytecodes,
this.exceptionsTable,
this.sourcePositions,
+ this.localVariables,
this.nullableFields,
this.closures,
this.parameterFlags,
@@ -555,6 +562,9 @@
if (hasSourcePositions) {
writer.writeLinkOffset(sourcePositions);
}
+ if (hasLocalVariables) {
+ writer.writeLinkOffset(localVariables);
+ }
if (hasNullableFields) {
writer.writePackedList(nullableFields);
}
@@ -590,6 +600,9 @@
final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
? reader.readLinkOffset<SourcePositions>()
: null;
+ final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+ ? reader.readLinkOffset<LocalVariableTable>()
+ : null;
final List<ObjectHandle> nullableFields =
((flags & hasNullableFieldsFlag) != 0)
? reader.readPackedList<ObjectHandle>()
@@ -602,6 +615,7 @@
bytecodes,
exceptionsTable,
sourcePositions,
+ localVariables,
nullableFields,
closures,
parameterFlags,
@@ -616,6 +630,9 @@
"${new BytecodeDisassembler().disassemble(bytecodes, exceptionsTable, annotations: [
hasSourcePositions
? sourcePositions.getBytecodeAnnotations()
+ : const <int, String>{},
+ hasLocalVariables
+ ? localVariables.getBytecodeAnnotations()
: const <int, String>{}
])}}\n"
"$exceptionsTable"
@@ -628,12 +645,15 @@
}
class ClosureDeclaration {
- static const int flagHasOptionalPositionalParams = 1 << 0;
- static const int flagHasOptionalNamedParams = 1 << 1;
- static const int flagHasTypeParams = 1 << 2;
+ static const int hasOptionalPositionalParamsFlag = 1 << 0;
+ static const int hasOptionalNamedParamsFlag = 1 << 1;
+ static const int hasTypeParamsFlag = 1 << 2;
+ static const int hasSourcePositionsFlag = 1 << 3;
final ObjectHandle parent;
final ObjectHandle name;
+ final int position;
+ final int endPosition;
final List<NameAndType> typeParams;
final int numRequiredParams;
final int numNamedParams;
@@ -644,6 +664,8 @@
ClosureDeclaration(
this.parent,
this.name,
+ this.position,
+ this.endPosition,
this.typeParams,
this.numRequiredParams,
this.numNamedParams,
@@ -654,19 +676,27 @@
int flags = 0;
if (numRequiredParams != parameters.length) {
if (numNamedParams > 0) {
- flags |= flagHasOptionalNamedParams;
+ flags |= hasOptionalNamedParamsFlag;
} else {
- flags |= flagHasOptionalPositionalParams;
+ flags |= hasOptionalPositionalParamsFlag;
}
}
if (typeParams.isNotEmpty) {
- flags |= flagHasTypeParams;
+ flags |= hasTypeParamsFlag;
+ }
+ if (position != TreeNode.noOffset) {
+ flags |= hasSourcePositionsFlag;
}
writer.writePackedUInt30(flags);
writer.writePackedObject(parent);
writer.writePackedObject(name);
- if (flags & flagHasTypeParams != 0) {
+ if (flags & hasSourcePositionsFlag != 0) {
+ writer.writePackedUInt30(position + 1);
+ writer.writePackedUInt30(endPosition + 1);
+ }
+
+ if (flags & hasTypeParamsFlag != 0) {
writer.writePackedUInt30(typeParams.length);
for (var tp in typeParams) {
writer.writePackedObject(tp.name);
@@ -677,7 +707,7 @@
}
writer.writePackedUInt30(parameters.length);
if (flags &
- (flagHasOptionalPositionalParams | flagHasOptionalNamedParams) !=
+ (hasOptionalPositionalParamsFlag | hasOptionalNamedParamsFlag) !=
0) {
writer.writePackedUInt30(numRequiredParams);
}
@@ -692,8 +722,14 @@
final int flags = reader.readPackedUInt30();
final parent = reader.readPackedObject();
final name = reader.readPackedObject();
+ final position = ((flags & hasSourcePositionsFlag) != 0)
+ ? reader.readPackedUInt30() - 1
+ : TreeNode.noOffset;
+ final endPosition = ((flags & hasSourcePositionsFlag) != 0)
+ ? reader.readPackedUInt30() - 1
+ : TreeNode.noOffset;
List<NameAndType> typeParams;
- if ((flags & flagHasTypeParams) != 0) {
+ if ((flags & hasTypeParamsFlag) != 0) {
final int numTypeParams = reader.readPackedUInt30();
List<ObjectHandle> names = new List<ObjectHandle>.generate(
numTypeParams, (_) => reader.readPackedObject());
@@ -706,12 +742,12 @@
}
final numParams = reader.readPackedUInt30();
final numRequiredParams = (flags &
- (flagHasOptionalPositionalParams |
- flagHasOptionalNamedParams) !=
+ (hasOptionalPositionalParamsFlag |
+ hasOptionalNamedParamsFlag) !=
0)
? reader.readPackedUInt30()
: numParams;
- final numNamedParams = (flags & flagHasOptionalNamedParams != 0)
+ final numNamedParams = (flags & hasOptionalNamedParamsFlag != 0)
? (numParams - numRequiredParams)
: 0;
final List<NameAndType> parameters = new List<NameAndType>.generate(
@@ -719,14 +755,17 @@
(_) => new NameAndType(
reader.readPackedObject(), reader.readPackedObject()));
final returnType = reader.readPackedObject();
- return new ClosureDeclaration(parent, name, typeParams, numRequiredParams,
- numNamedParams, parameters, returnType);
+ return new ClosureDeclaration(parent, name, position, endPosition,
+ typeParams, numRequiredParams, numNamedParams, parameters, returnType);
}
@override
String toString() {
StringBuffer sb = new StringBuffer();
sb.write('Closure $parent::$name');
+ if (position != TreeNode.noOffset) {
+ sb.write(' pos = $position, end-pos = $endPosition');
+ }
if (typeParams.isNotEmpty) {
sb.write(' <${typeParams.join(', ')}>');
}
@@ -754,19 +793,28 @@
/// Bytecode of a nested function (closure).
/// Closures share the constant pool of a top-level member.
class ClosureCode {
+ static const hasExceptionsTableFlag = 1 << 0;
+ static const hasSourcePositionsFlag = 1 << 1;
+ static const hasLocalVariablesFlag = 1 << 2;
+
final List<int> bytecodes;
final ExceptionsTable exceptionsTable;
final SourcePositions sourcePositions;
+ final LocalVariableTable localVariables;
bool get hasExceptionsTable => exceptionsTable.blocks.isNotEmpty;
bool get hasSourcePositions =>
sourcePositions != null && sourcePositions.mapping.isNotEmpty;
+ bool get hasLocalVariables =>
+ localVariables != null && localVariables.isNotEmpty;
int get flags =>
- (hasExceptionsTable ? Code.hasExceptionsTableFlag : 0) |
- (hasSourcePositions ? Code.hasSourcePositionsFlag : 0);
+ (hasExceptionsTable ? hasExceptionsTableFlag : 0) |
+ (hasSourcePositions ? hasSourcePositionsFlag : 0) |
+ (hasLocalVariables ? hasLocalVariablesFlag : 0);
- ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions);
+ ClosureCode(this.bytecodes, this.exceptionsTable, this.sourcePositions,
+ this.localVariables);
void write(BufferedWriter writer) {
writer.writePackedUInt30(flags);
@@ -777,18 +825,25 @@
if (hasSourcePositions) {
writer.writeLinkOffset(sourcePositions);
}
+ if (hasLocalVariables) {
+ writer.writeLinkOffset(localVariables);
+ }
}
factory ClosureCode.read(BufferedReader reader) {
final int flags = reader.readPackedUInt30();
final List<int> bytecodes = _readBytecodeInstructions(reader);
- final exceptionsTable = ((flags & Code.hasExceptionsTableFlag) != 0)
+ final exceptionsTable = ((flags & hasExceptionsTableFlag) != 0)
? new ExceptionsTable.read(reader)
: new ExceptionsTable();
- final sourcePositions = ((flags & Code.hasSourcePositionsFlag) != 0)
+ final sourcePositions = ((flags & hasSourcePositionsFlag) != 0)
? reader.readLinkOffset<SourcePositions>()
: null;
- return new ClosureCode(bytecodes, exceptionsTable, sourcePositions);
+ final localVariables = ((flags & hasLocalVariablesFlag) != 0)
+ ? reader.readLinkOffset<LocalVariableTable>()
+ : null;
+ return new ClosureCode(
+ bytecodes, exceptionsTable, sourcePositions, localVariables);
}
@override
@@ -799,6 +854,9 @@
.disassemble(bytecodes, exceptionsTable, annotations: [
hasSourcePositions
? sourcePositions.getBytecodeAnnotations()
+ : const <int, String>{},
+ hasLocalVariables
+ ? localVariables.getBytecodeAnnotations()
: const <int, String>{}
]));
sb.writeln('}');
@@ -818,7 +876,7 @@
class Component {
static const int magicValue = 0x44424332; // 'DBC2'
- static const int numSections = 7;
+ static const int numSections = 8;
static const int sectionAlignment = 4;
// UInt32 magic, version, numSections x (numItems, offset)
@@ -830,6 +888,7 @@
List<Members> members = <Members>[];
List<Code> codes = <Code>[];
List<SourcePositions> sourcePositions = <SourcePositions>[];
+ List<LocalVariableTable> localVariables = <LocalVariableTable>[];
List<ObjectHandle> annotations = <ObjectHandle>[];
ObjectHandle mainLibrary;
@@ -850,6 +909,13 @@
annotationsWriter.writePackedObject(annot);
}
+ final BufferedWriter localVariablesWriter =
+ new BufferedWriter.fromWriter(writer);
+ for (var lv in localVariables) {
+ writer.linkWriter.put(lv, localVariablesWriter.offset);
+ lv.write(localVariablesWriter);
+ }
+
final BufferedWriter sourcePositionsWriter =
new BufferedWriter.fromWriter(writer);
for (var sp in sourcePositions) {
@@ -888,6 +954,7 @@
new _Section(members.length, membersWriter),
new _Section(codes.length, codesWriter),
new _Section(sourcePositions.length, sourcePositionsWriter),
+ new _Section(localVariables.length, localVariablesWriter),
new _Section(annotations.length, annotationsWriter),
];
assert(sections.length == numSections);
@@ -956,6 +1023,9 @@
final sourcePositionsNum = reader.readUInt32();
final sourcePositionsOffset = reader.readUInt32();
+ final localVariablesNum = reader.readUInt32();
+ final localVariablesOffset = reader.readUInt32();
+
final annotationsNum = reader.readUInt32();
final annotationsOffset = reader.readUInt32();
@@ -988,6 +1058,15 @@
sourcePositions.add(sp);
}
+ final localVariablesStart = start + localVariablesOffset;
+ reader.offset = localVariablesStart;
+ for (int i = 0; i < localVariablesNum; ++i) {
+ int offset = reader.offset - localVariablesStart;
+ LocalVariableTable lv = new LocalVariableTable.read(reader);
+ reader.linkReader.setOffset(lv, offset);
+ localVariables.add(lv);
+ }
+
final codesStart = start + codesOffset;
reader.offset = codesStart;
for (int i = 0; i < codesNum; ++i) {
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 216ac55..01a941d 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -35,6 +35,7 @@
hasFreeTypeParameters,
hasInstantiatorTypeArguments,
isUncheckedCall;
+import 'local_variable_table.dart' show LocalVariableTable;
import 'local_vars.dart' show LocalVariables;
import 'nullability_detector.dart' show NullabilityDetector;
import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType;
@@ -43,6 +44,8 @@
import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
import '../metadata/bytecode.dart';
+import 'dart:math' as math;
+
// This symbol is used as the name in assert assignable's to indicate it comes
// from an explicit 'as' check. This will cause the runtime to throw the right
// exception.
@@ -52,6 +55,7 @@
ast.Component component, {
bool enableAsserts: true,
bool emitSourcePositions: false,
+ bool emitLocalVarInfo: false,
bool emitAnnotations: false,
bool omitAssertSourcePositions: false,
bool useFutureBytecodeFormat: false,
@@ -78,6 +82,7 @@
environmentDefines,
enableAsserts,
emitSourcePositions,
+ emitLocalVarInfo,
emitAnnotations,
omitAssertSourcePositions,
useFutureBytecodeFormat,
@@ -95,6 +100,7 @@
final Map<String, String> environmentDefines;
final bool enableAsserts;
final bool emitSourcePositions;
+ final bool emitLocalVarInfo;
final bool emitAnnotations;
final bool omitAssertSourcePositions;
final bool useFutureBytecodeFormat;
@@ -134,6 +140,8 @@
List<BytecodeAssembler> savedAssemblers;
bool hasErrors;
int currentLoopDepth;
+ List<int> savedMaxSourcePositions;
+ int maxSourcePosition;
BytecodeGenerator(
ast.Component component,
@@ -144,6 +152,7 @@
this.environmentDefines,
this.enableAsserts,
this.emitSourcePositions,
+ this.emitLocalVarInfo,
this.emitAnnotations,
this.omitAssertSourcePositions,
this.useFutureBytecodeFormat,
@@ -664,10 +673,11 @@
_asyncAwaitCompleterGetFuture ??= libraryIndex.getMember(
'dart:async', '_AsyncAwaitCompleter', 'get:future');
- void _recordSourcePosition(TreeNode node) {
+ void _recordSourcePosition(int fileOffset) {
if (emitSourcePositions) {
- asm.currentSourcePosition = node.fileOffset;
+ asm.currentSourcePosition = fileOffset;
}
+ maxSourcePosition = math.max(maxSourcePosition, fileOffset);
}
void _generateNode(TreeNode node) {
@@ -675,7 +685,7 @@
return;
}
final savedSourcePosition = asm.currentSourcePosition;
- _recordSourcePosition(node);
+ _recordSourcePosition(node.fileOffset);
node.accept(this);
asm.currentSourcePosition = savedSourcePosition;
}
@@ -1149,12 +1159,14 @@
asm = new BytecodeAssembler();
savedAssemblers = <BytecodeAssembler>[];
currentLoopDepth = 0;
+ savedMaxSourcePositions = <int>[];
+ maxSourcePosition = node.fileOffset;
locals = new LocalVariables(node, enableAsserts);
locals.enterScope(node);
assert(!locals.isSyncYieldingFrame);
- _recordSourcePosition(node);
+ _recordSourcePosition(node.fileOffset);
_genPrologue(node, node.function);
_setupInitialContext(node.function);
if (node is Procedure && node.isInstanceMember) {
@@ -1186,6 +1198,12 @@
if (!hasErrors) {
Code code;
if (hasCode) {
+ if (emitLocalVarInfo && node.function != null) {
+ // Leave the scope which was entered in _setupInitialContext.
+ asm.localVariableTable
+ .leaveScope(asm.offset, node.function.fileEndOffset);
+ }
+
List<int> parameterFlags = null;
int forwardingStubTargetCpIndex = null;
int defaultFunctionTypeArgsCpIndex = null;
@@ -1208,6 +1226,7 @@
asm.bytecode,
asm.exceptionsTable,
finalizeSourcePositions(),
+ finalizeLocalVariables(),
nullableFields,
closures,
parameterFlags,
@@ -1257,6 +1276,16 @@
return asm.sourcePositions;
}
+ LocalVariableTable finalizeLocalVariables() {
+ final localVariables = asm.localVariableTable;
+ assert(!localVariables.hasActiveScopes);
+ if (localVariables.isEmpty) {
+ return null;
+ }
+ bytecodeComponent.localVariables.add(localVariables);
+ return localVariables;
+ }
+
void _genPrologue(Node node, FunctionNode function) {
if (locals.hasOptionalParameters) {
final int numOptionalPositional = function.positionalParameters.length -
@@ -1381,6 +1410,25 @@
void _setupInitialContext(FunctionNode function) {
_allocateContextIfNeeded();
+ if (emitLocalVarInfo && function != null) {
+ // Open scope after allocating context.
+ asm.localVariableTable.enterScope(
+ asm.offset, locals.currentContextLevel, function.fileOffset);
+ if (locals.hasContextVar) {
+ asm.localVariableTable
+ .recordContextVariable(asm.offset, locals.contextVarIndexInFrame);
+ }
+ if (locals.hasReceiver) {
+ _declareLocalVariable(locals.receiverVar, function.fileOffset);
+ }
+ for (var v in function.positionalParameters) {
+ _declareLocalVariable(v, function.fileOffset);
+ }
+ for (var v in locals.sortedNamedParameters) {
+ _declareLocalVariable(v, function.fileOffset);
+ }
+ }
+
if (locals.hasCapturedParameters) {
// Copy captured parameters to their respective locations in the context.
if (!isClosure) {
@@ -1408,6 +1456,22 @@
}
}
+ void _declareLocalVariable(
+ VariableDeclaration variable, int initializedPosition) {
+ assert(variable.name != null);
+ bool isCaptured = locals.isCaptured(variable);
+ asm.localVariableTable.declareVariable(
+ asm.offset,
+ isCaptured,
+ isCaptured
+ ? locals.getVarIndexInContext(variable)
+ : locals.getVarIndexInFrame(variable),
+ cp.addString(variable.name),
+ cp.addType(variable.type),
+ variable.fileOffset,
+ initializedPosition);
+ }
+
// TODO(alexmarkov): Revise if we need to AOT-compile from bytecode.
bool get canSkipTypeChecksForNonCovariantArguments =>
!isClosure && enclosingMember.name.name != 'call';
@@ -1618,6 +1682,15 @@
final savedLoopDepth = currentLoopDepth;
currentLoopDepth = 0;
+ int position = TreeNode.noOffset;
+ int endPosition = TreeNode.noOffset;
+ if (emitSourcePositions) {
+ position = (node is ast.FunctionDeclaration)
+ ? node.fileOffset
+ : function.fileOffset;
+ endPosition = function.fileEndOffset;
+ }
+
if (function.typeParameters.isNotEmpty) {
functionTypeParameters ??= new List<TypeParameter>();
functionTypeParameters.addAll(function.typeParameters);
@@ -1644,6 +1717,8 @@
objectTable
.getHandle(savedIsClosure ? parentFunction : enclosingMember),
objectTable.getNameHandle(null, name),
+ position,
+ endPosition,
function.typeParameters
.map((tp) => new NameAndType(
objectTable.getNameHandle(null, tp.name),
@@ -1658,6 +1733,7 @@
final int closureFunctionIndex = cp.addClosureFunction(closureIndex);
_genPrologue(node, function);
+ _recordSourcePosition(function.fileOffset);
Label continuationSwitchLabel;
int continuationSwitchVar;
@@ -1678,12 +1754,18 @@
// BytecodeAssembler eliminates this bytecode if it is unreachable.
asm.emitPushNull();
_genReturnTOS();
+ _recordSourcePosition(function.fileEndOffset);
if (locals.isSyncYieldingFrame) {
_genSyncYieldingEpilogue(
function, continuationSwitchLabel, continuationSwitchVar);
}
+ if (emitLocalVarInfo) {
+ // Leave the scope which was entered in _setupInitialContext.
+ asm.localVariableTable.leaveScope(asm.offset, function.fileEndOffset);
+ }
+
cp.addEndClosureFunctionScope();
if (function.typeParameters.isNotEmpty) {
@@ -1698,8 +1780,8 @@
locals.leaveScope();
- closure.code = new ClosureCode(
- asm.bytecode, asm.exceptionsTable, finalizeSourcePositions());
+ closure.code = new ClosureCode(asm.bytecode, asm.exceptionsTable,
+ finalizeSourcePositions(), finalizeLocalVariables());
_popAssemblerState();
yieldPoints = savedYieldPoints;
@@ -1803,15 +1885,35 @@
void _enterScope(TreeNode node) {
locals.enterScope(node);
_allocateContextIfNeeded();
+ if (emitLocalVarInfo) {
+ asm.localVariableTable
+ .enterScope(asm.offset, locals.currentContextLevel, node.fileOffset);
+ _startRecordingMaxPosition(node.fileOffset);
+ }
}
void _leaveScope() {
+ if (emitLocalVarInfo) {
+ asm.localVariableTable.leaveScope(asm.offset, _endRecordingMaxPosition());
+ }
if (locals.currentContextSize > 0) {
_genUnwindContext(locals.currentContextLevel - 1);
}
locals.leaveScope();
}
+ void _startRecordingMaxPosition(int fileOffset) {
+ savedMaxSourcePositions.add(maxSourcePosition);
+ maxSourcePosition = fileOffset;
+ }
+
+ int _endRecordingMaxPosition() {
+ int localMax = maxSourcePosition;
+ maxSourcePosition =
+ math.max(localMax, savedMaxSourcePositions.removeLast());
+ return localMax;
+ }
+
void _genUnwindContext(int targetContextLevel) {
int currentContextLevel = locals.currentContextLevel;
assert(currentContextLevel >= targetContextLevel);
@@ -3271,11 +3373,17 @@
if (isCaptured) {
_genPushContextForVariable(node);
}
+ int maxInitializerPosition = node.fileOffset;
if (node.initializer != null) {
+ _startRecordingMaxPosition(node.fileOffset);
_generateNode(node.initializer);
+ maxInitializerPosition = _endRecordingMaxPosition();
} else {
asm.emitPushNull();
}
+ if (emitLocalVarInfo && !asm.isUnreachable && node.name != null) {
+ _declareLocalVariable(node, maxInitializerPosition + 1);
+ }
_genStoreVar(node);
}
}
diff --git a/pkg/vm/lib/bytecode/local_variable_table.dart b/pkg/vm/lib/bytecode/local_variable_table.dart
new file mode 100644
index 0000000..fc49225
--- /dev/null
+++ b/pkg/vm/lib/bytecode/local_variable_table.dart
@@ -0,0 +1,234 @@
+// 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.
+
+library vm.bytecode.local_variable_table;
+
+import 'bytecode_serialization.dart';
+
+enum LocalVariableEntryKind {
+ invalid,
+ scope,
+ variableDeclaration,
+ contextVariable,
+}
+
+abstract class LocalVariableEntry {
+ static const KindMask = 0x0F;
+ static const IsCapturedFlag = 1 << 4;
+
+ LocalVariableEntryKind get kind;
+ int get flags => 0;
+ final int startPC;
+ void writeContents(BufferedWriter writer);
+
+ LocalVariableEntry(this.startPC);
+}
+
+class Scope extends LocalVariableEntry {
+ int endPC;
+ int contextLevel;
+ int position;
+ int endPosition;
+ final List<VariableDeclaration> variables = <VariableDeclaration>[];
+
+ Scope(int startPC, this.endPC, this.contextLevel, this.position,
+ this.endPosition)
+ : super(startPC);
+
+ @override
+ LocalVariableEntryKind get kind => LocalVariableEntryKind.scope;
+
+ @override
+ void writeContents(BufferedWriter writer) {
+ if (endPC == null) {
+ throw '$this is not closed';
+ }
+ writer.writePackedUInt30(endPC - startPC);
+ writer.writeSLEB128(contextLevel);
+ writer.writePackedUInt30(position + 1);
+ writer.writePackedUInt30(endPosition + 1);
+ }
+
+ Scope.readContents(BufferedReader reader, int startPC) : super(startPC) {
+ endPC = startPC = reader.readPackedUInt30();
+ contextLevel = reader.readSLEB128();
+ position = reader.readPackedUInt30() - 1;
+ endPosition = reader.readPackedUInt30() - 1;
+ }
+
+ @override
+ String toString() =>
+ 'scope (pc $startPC-$endPC pos $position-$endPosition context-level $contextLevel)';
+}
+
+class VariableDeclaration extends LocalVariableEntry {
+ bool isCaptured;
+ int index;
+ int name;
+ int type;
+ int position;
+ int initializedPosition;
+
+ VariableDeclaration(int startPC, this.isCaptured, this.index, this.name,
+ this.type, this.position, this.initializedPosition)
+ : super(startPC);
+
+ @override
+ LocalVariableEntryKind get kind => LocalVariableEntryKind.variableDeclaration;
+
+ @override
+ int get flags => (isCaptured ? LocalVariableEntry.IsCapturedFlag : 0);
+
+ @override
+ void writeContents(BufferedWriter writer) {
+ writer.writeSLEB128(index);
+ writer.writePackedUInt30(name);
+ writer.writePackedUInt30(type);
+ writer.writePackedUInt30(position + 1);
+ writer.writePackedUInt30(initializedPosition + 1);
+ }
+
+ VariableDeclaration.readContents(
+ BufferedReader reader, int startPC, int flags)
+ : super(startPC) {
+ isCaptured = (flags & LocalVariableEntry.IsCapturedFlag) != 0;
+ index = reader.readSLEB128();
+ name = reader.readPackedUInt30();
+ type = reader.readPackedUInt30();
+ position = reader.readPackedUInt30() - 1;
+ initializedPosition = reader.readPackedUInt30() - 1;
+ }
+
+ @override
+ String toString() =>
+ 'variable $index${isCaptured ? ' (captured)' : ''} pc $startPC, name CP#$name, type CP#$type, pos $position, init-pos $initializedPosition';
+}
+
+class ContextVariable extends LocalVariableEntry {
+ int index;
+
+ ContextVariable(int startPC, this.index) : super(startPC);
+
+ @override
+ LocalVariableEntryKind get kind => LocalVariableEntryKind.contextVariable;
+
+ @override
+ void writeContents(BufferedWriter writer) {
+ writer.writeSLEB128(index);
+ }
+
+ ContextVariable.readContents(BufferedReader reader, int startPC)
+ : super(startPC) {
+ index = reader.readSLEB128();
+ }
+
+ @override
+ String toString() => 'context variable $index';
+}
+
+/// Keeps information about declared local variables.
+class LocalVariableTable {
+ final scopes = <Scope>[];
+ final activeScopes = <Scope>[];
+ ContextVariable contextVariable;
+
+ LocalVariableTable();
+
+ void enterScope(int pc, int contextLevel, int position) {
+ final scope = new Scope(pc, null, contextLevel, position, null);
+ activeScopes.add(scope);
+ scopes.add(scope);
+ }
+
+ void declareVariable(int pc, bool isCaptured, int index, int nameCpIndex,
+ int typeCpIndex, int position, int initializedPosition) {
+ final variable = new VariableDeclaration(pc, isCaptured, index, nameCpIndex,
+ typeCpIndex, position, initializedPosition);
+ activeScopes.last.variables.add(variable);
+ }
+
+ void leaveScope(int pc, int endPosition) {
+ final scope = activeScopes.removeLast();
+ scope.endPC = pc;
+ scope.endPosition = endPosition;
+ if (scope.variables.isEmpty) {
+ scopes.remove(scope);
+ }
+ }
+
+ void recordContextVariable(int pc, int index) {
+ assert(contextVariable == null);
+ contextVariable = new ContextVariable(pc, index);
+ }
+
+ bool get isEmpty => scopes.isEmpty && contextVariable == null;
+
+ bool get isNotEmpty => !isEmpty;
+
+ bool get hasActiveScopes => activeScopes.isNotEmpty;
+
+ List<LocalVariableEntry> getEntries() {
+ final entries = <LocalVariableEntry>[];
+ if (contextVariable != null) {
+ entries.add(contextVariable);
+ }
+ for (Scope scope in scopes) {
+ entries.add(scope);
+ entries.addAll(scope.variables);
+ }
+ return entries;
+ }
+
+ void write(BufferedWriter writer) {
+ final entries = getEntries();
+ writer.writePackedUInt30(entries.length);
+ final encodeStartPC = new SLEB128DeltaEncoder();
+ for (var entry in entries) {
+ writer.writeByte(entry.kind.index | entry.flags);
+ encodeStartPC.write(writer, entry.startPC);
+ entry.writeContents(writer);
+ }
+ }
+
+ LocalVariableTable.read(BufferedReader reader) {
+ final int numEntries = reader.readPackedUInt30();
+ final decodeStartPC = new SLEB128DeltaDecoder();
+ Scope scope;
+ for (int i = 0; i < numEntries; ++i) {
+ final int kindAndFlags = reader.readByte();
+ final LocalVariableEntryKind kind = LocalVariableEntryKind
+ .values[kindAndFlags & LocalVariableEntry.KindMask];
+ final int flags = kindAndFlags & ~LocalVariableEntry.KindMask;
+ final int startPC = decodeStartPC.read(reader);
+ switch (kind) {
+ case LocalVariableEntryKind.scope:
+ scope = new Scope.readContents(reader, startPC);
+ scopes.add(scope);
+ break;
+ case LocalVariableEntryKind.variableDeclaration:
+ scope.variables.add(
+ new VariableDeclaration.readContents(reader, startPC, flags));
+ break;
+ case LocalVariableEntryKind.contextVariable:
+ contextVariable = new ContextVariable.readContents(reader, startPC);
+ break;
+ default:
+ throw 'Unexpected entry kind ${kind}';
+ }
+ }
+ }
+
+ Map<int, String> getBytecodeAnnotations() {
+ final map = <int, String>{};
+ for (var entry in getEntries()) {
+ final pc = entry.startPC;
+ if (map[pc] == null) {
+ map[pc] = entry.toString();
+ } else {
+ map[pc] = "${map[pc]}; $entry";
+ }
+ }
+ return map;
+ }
+}
diff --git a/pkg/vm/lib/bytecode/local_vars.dart b/pkg/vm/lib/bytecode/local_vars.dart
index 178bfa1..c321b4e 100644
--- a/pkg/vm/lib/bytecode/local_vars.dart
+++ b/pkg/vm/lib/bytecode/local_vars.dart
@@ -850,6 +850,9 @@
(_currentScope.tempsUsed + count) - _currentFrame.temporaries.length;
int local = _currentScope.localsUsed;
_currentScope.localsUsed += newSlots;
+ if (_currentScope.localsUsed > localVariableIndexLimit) {
+ throw new LocalVariableIndexOverflowException();
+ }
_updateFrameSize();
for (int i = 0; i < newSlots; i++) {
_currentFrame.temporaries.add(local + i);
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index 9c3f530..80324cc 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -1379,7 +1379,9 @@
ObjectHandle handle = _nodeCache[node];
if (handle == null) {
handle = node.accept(_nodeVisitor);
- _nodeCache[node] = handle;
+ if (handle != null && handle.isCacheable) {
+ _nodeCache[node] = handle;
+ }
} else {
++handle._useCount;
}
diff --git a/pkg/vm/lib/bytecode/source_positions.dart b/pkg/vm/lib/bytecode/source_positions.dart
index 22ed3b1..f0bef3d 100644
--- a/pkg/vm/lib/bytecode/source_positions.dart
+++ b/pkg/vm/lib/bytecode/source_positions.dart
@@ -4,7 +4,14 @@
library vm.bytecode.source_positions;
-import 'bytecode_serialization.dart' show BufferedWriter, BufferedReader;
+import 'bytecode_serialization.dart'
+ show
+ BufferedWriter,
+ BufferedReader,
+ PackedUInt30DeltaEncoder,
+ PackedUInt30DeltaDecoder,
+ SLEB128DeltaEncoder,
+ SLEB128DeltaDecoder;
/// Maintains mapping between bytecode instructions and source positions.
class SourcePositions {
@@ -53,41 +60,3 @@
new MapEntry(pc, 'source position $fileOffset'));
}
}
-
-class PackedUInt30DeltaEncoder {
- int _last = 0;
-
- void write(BufferedWriter write, int value) {
- write.writePackedUInt30(value - _last);
- _last = value;
- }
-}
-
-class PackedUInt30DeltaDecoder {
- int _last = 0;
-
- int read(BufferedReader reader) {
- int value = reader.readPackedUInt30() + _last;
- _last = value;
- return value;
- }
-}
-
-class SLEB128DeltaEncoder {
- int _last = 0;
-
- void write(BufferedWriter writer, int value) {
- writer.writeSLEB128(value - _last);
- _last = value;
- }
-}
-
-class SLEB128DeltaDecoder {
- int _last = 0;
-
- int read(BufferedReader reader) {
- int value = reader.readSLEB128() + _last;
- _last = value;
- return value;
- }
-}
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index d65f56b..0dd2962 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -113,6 +113,9 @@
args.addFlag('gen-bytecode', help: 'Generate bytecode', defaultsTo: false);
args.addFlag('emit-bytecode-source-positions',
help: 'Emit source positions in bytecode', defaultsTo: false);
+ args.addFlag('emit-bytecode-local-var-info',
+ help: 'Emit information about local variables in bytecode',
+ defaultsTo: false);
args.addFlag('emit-bytecode-annotations',
help: 'Emit Dart annotations in bytecode', defaultsTo: false);
args.addFlag('drop-ast',
@@ -166,6 +169,7 @@
final bool genBytecode = options['gen-bytecode'];
final bool emitBytecodeSourcePositions =
options['emit-bytecode-source-positions'];
+ final bool emitBytecodeLocalVarInfo = options['emit-bytecode-local-var-info'];
final bool emitBytecodeAnnotations = options['emit-bytecode-annotations'];
final bool dropAST = options['drop-ast'];
final bool useFutureBytecodeFormat = options['use-future-bytecode-format'];
@@ -226,6 +230,7 @@
environmentDefines: environmentDefines,
genBytecode: genBytecode,
emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+ emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
emitBytecodeAnnotations: emitBytecodeAnnotations,
dropAST: dropAST && !splitOutputByPackages,
useFutureBytecodeFormat: useFutureBytecodeFormat,
@@ -266,6 +271,7 @@
genBytecode: genBytecode,
enableAsserts: enableAsserts,
emitBytecodeSourcePositions: emitBytecodeSourcePositions,
+ emitBytecodeLocalVarInfo: emitBytecodeLocalVarInfo,
emitBytecodeAnnotations: emitBytecodeAnnotations,
dropAST: dropAST,
showBytecodeSizeStat: showBytecodeSizeStat,
@@ -287,6 +293,7 @@
Map<String, String> environmentDefines,
bool genBytecode: false,
bool emitBytecodeSourcePositions: false,
+ bool emitBytecodeLocalVarInfo: false,
bool emitBytecodeAnnotations: false,
bool dropAST: false,
bool useFutureBytecodeFormat: false,
@@ -320,6 +327,7 @@
generateBytecode(component,
enableAsserts: enableAsserts,
emitSourcePositions: emitBytecodeSourcePositions,
+ emitLocalVarInfo: emitBytecodeLocalVarInfo,
emitAnnotations: emitBytecodeAnnotations,
useFutureBytecodeFormat: useFutureBytecodeFormat,
environmentDefines: environmentDefines);
@@ -656,6 +664,7 @@
bool genBytecode: false,
bool enableAsserts: true,
bool emitBytecodeSourcePositions: false,
+ bool emitBytecodeLocalVarInfo: false,
bool emitBytecodeAnnotations: false,
bool dropAST: false,
bool showBytecodeSizeStat: false,
@@ -718,6 +727,7 @@
hierarchy: hierarchy,
enableAsserts: enableAsserts,
emitSourcePositions: emitBytecodeSourcePositions,
+ emitLocalVarInfo: emitBytecodeLocalVarInfo,
emitAnnotations: emitBytecodeAnnotations,
useFutureBytecodeFormat: useFutureBytecodeFormat,
environmentDefines: environmentDefines);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 4b40caf..d61ca95 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -275,9 +275,10 @@
}
bool _isStatic(Expression node) {
- if (node is! StaticGet) return false;
-
- return (node as StaticGet).target is Procedure;
+ if (node is StaticGet) {
+ return node.target is Procedure;
+ }
+ return node is ConstantExpression;
}
}
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 5310517..a56d500 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -83,11 +83,12 @@
new StreamController<List<int>>();
final ReceivePort compileCalled = new ReceivePort();
when(compiler.compile(any, any, generator: anyNamed('generator')))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
expect(invocation.positionalArguments[0], equals('server.dart'));
expect(
invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
compileCalled.sendPort.send(true);
+ return true;
});
Future<int> result = starter(
@@ -116,11 +117,12 @@
new StreamController<List<int>>();
final ReceivePort compileCalled = new ReceivePort();
when(compiler.compile(any, any, generator: anyNamed('generator')))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
expect(invocation.positionalArguments[0], equals('server.dart'));
expect(
invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
compileCalled.sendPort.send(true);
+ return true;
});
Future<int> result = starter(
@@ -141,12 +143,13 @@
final ReceivePort compileCalled = new ReceivePort();
int counter = 1;
when(compiler.compile(any, any, generator: anyNamed('generator')))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
expect(invocation.positionalArguments[0],
equals('server${counter++}.dart'));
expect(
invocation.positionalArguments[1]['sdk-root'], equals('sdkroot'));
compileCalled.sendPort.send(true);
+ return true;
});
Future<int> result = starter(
@@ -180,7 +183,7 @@
final ReceivePort recompileCalled = new ReceivePort();
when(compiler.recompileDelta(entryPoint: null))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
recompileCalled.sendPort.send(true);
});
Future<int> result = starter(
@@ -208,7 +211,7 @@
final ReceivePort recompileCalled = new ReceivePort();
when(compiler.recompileDelta(entryPoint: 'file2.dart'))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
recompileCalled.sendPort.send(true);
});
Future<int> result = starter(
@@ -275,7 +278,7 @@
final ReceivePort recompileCalled = new ReceivePort();
when(compiler.recompileDelta(entryPoint: null))
- .thenAnswer((Invocation invocation) {
+ .thenAnswer((Invocation invocation) async {
recompileCalled.sendPort.send(true);
});
Future<int> result = starter(
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 2b714ec..b223aaf 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -296,7 +296,7 @@
await compileAndSerialize(mainDill, libDill, compiler);
var list = new File(p.join(dir.path, 'myMain.dilllist'))..createSync();
- list.writeAsStringSync("#@dill\n../main.dart.dill\n../lib.dart.dill\n");
+ list.writeAsStringSync("#@dill\nmain.dart.dill\nlib.dart.dill\n");
Directory runFrom = new Directory(dir.path + "/runFrom")..createSync();
vm = await Process.start(Platform.resolvedExecutable, <String>[list.path],
workingDirectory: runFrom.path);
diff --git a/pkg/vm/tool/test_bytecode b/pkg/vm/tool/test_bytecode
deleted file mode 100755
index 9f800ab..0000000
--- a/pkg/vm/tool/test_bytecode
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2018, 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.
-
-# Script for generating bytecode in a kernel file using Dart 2 pipeline and
-# interpreting the resulting bytecode.
-
-# Usage
-# pkg/vm/tool/test_bytecode ~/foo.dart
-
-set -e
-
-# Pick the architecture and mode to test.
-BUILD_FLAGS="-m release -a x64"
-BUILD_SUBDIR="ReleaseX64"
-
-function follow_links() {
- file="$1"
- while [ -h "$file" ]; do
- # On Mac OS, readlink -f doesn't work.
- file="$(readlink "$file")"
- done
- echo "$file"
-}
-
-# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
-PROG_NAME="$(follow_links "$BASH_SOURCE")"
-
-# Handle the case where dart-sdk/bin has been symlinked to.
-CUR_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
-
-SDK_DIR="$CUR_DIR/../../.."
-BUILD_DIR="$SDK_DIR/out/$BUILD_SUBDIR"
-
-# Regenerate vm_platform_strong.dill to contain bytecode if needed:
-# $SDK_DIR/tools/gn.py $BUILD_FLAGS --bytecode
-# $SDK_DIR/tools/build.py $BUILD_FLAGS runtime
-
-# Generate dill file containing bytecode for input dart source.
-$CUR_DIR/gen_kernel --platform $BUILD_DIR/vm_platform_strong.dill \
- --gen-bytecode $@ -o $BUILD_DIR/test_bytecode.dill
-
-# Dump bytecode in generated vm_platform_strong.dill file to platform.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-# $BUILD_DIR/vm_platform_strong.dill $BUILD_DIR/platform.txt
-
-# Dump bytecode in generated test_bytecode.dill file to test_bytecode.txt.
-# $BUILD_DIR/dart $SDK_DIR/pkg/vm/bin/dump_kernel.dart \
-# $BUILD_DIR/test_bytecode.dill $BUILD_DIR/test_bytecode.txt
-
-# Required flag.
-DART_VM_FLAGS="--enable-interpreter $DART_VM_FLAGS"
-
-# Optional flags examples. Uncomment as needed.
-# DART_VM_FLAGS="--compilation-counter-threshold=-1 $DART_VM_FLAGS"
-# DART_VM_FLAGS="--force-log-flush --isolate-log-filter=\"\" $DART_VM_FLAGS"
-# DART_VM_FLAGS="--dump-kernel-bytecode $DART_VM_FLAGS"
-# DART_VM_FLAGS="--trace-interpreter-after=0 $DART_VM_FLAGS"
-
-# Execute dill file.
-exec $BUILD_DIR/dart $DART_VM_FLAGS $BUILD_DIR/test_bytecode.dill
-
diff --git a/runtime/bin/dfe.cc b/runtime/bin/dfe.cc
index 03ca32b..36efb0d 100644
--- a/runtime/bin/dfe.cc
+++ b/runtime/bin/dfe.cc
@@ -407,20 +407,34 @@
DISALLOW_COPY_AND_ASSIGN(KernelIRNode);
};
+class StringPointer {
+ public:
+ explicit StringPointer(char* c_str) : c_str_(c_str) {}
+ ~StringPointer() { free(c_str_); }
+
+ const char* c_str() { return c_str_; }
+
+ private:
+ char* c_str_;
+ DISALLOW_COPY_AND_ASSIGN(StringPointer);
+};
+
// Supports "kernel list" files as input.
// Those are text files that start with '#@dill' on new line, followed
// by absolute paths to kernel files or relative paths, that are relative
-// to dart process working directory.
+// to [script_uri] "kernel list" file.
// Below is an example of valid kernel list file:
// ```
// #@dill
// /projects/mytest/build/bin/main.vm.dill
// /projects/mytest/build/packages/mytest/lib.vm.dill
// ```
-static bool TryReadKernelListBuffer(uint8_t* buffer,
+static bool TryReadKernelListBuffer(const char* script_uri,
+ uint8_t* buffer,
intptr_t buffer_size,
uint8_t** kernel_ir,
intptr_t* kernel_ir_size) {
+ const char* kernel_list_dirname = DartUtils::DirName(script_uri);
KernelIRNode* kernel_ir_head = NULL;
KernelIRNode* kernel_ir_tail = NULL;
// Add all kernels to the linked list
@@ -432,7 +446,13 @@
*tail = '\0';
intptr_t this_kernel_size;
uint8_t* this_buffer;
- if (!TryReadFile(filename, &this_buffer, &this_kernel_size)) {
+
+ StringPointer absolute_filename(
+ File::IsAbsolutePath(filename)
+ ? strdup(filename)
+ : Utils::SCreate("%s%s", kernel_list_dirname, filename));
+ if (!TryReadFile(absolute_filename.c_str(), &this_buffer,
+ &this_kernel_size)) {
return false;
}
@@ -472,8 +492,8 @@
DartUtils::MagicNumber magic_number =
DartUtils::SniffForMagicNumber(buffer, *kernel_ir_size);
if (magic_number == DartUtils::kKernelListMagicNumber) {
- return TryReadKernelListBuffer(buffer, *kernel_ir_size, kernel_ir,
- kernel_ir_size);
+ return TryReadKernelListBuffer(script_uri, buffer, *kernel_ir_size,
+ kernel_ir, kernel_ir_size);
}
return TryReadSimpleKernelBuffer(buffer, kernel_ir, kernel_ir_size);
}
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 837b7a0..bae6f32 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -249,6 +249,7 @@
MutexLocker ml(&mutex_);
uint32_t events = 0;
fdio_unsafe_wait_end(fdio_, observed, &events);
+ LOG_INFO("IOHandle::WaitEnd: fd = %ld, events = %x\n", fd_, events);
return events;
}
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index f1c418c..200d6c2 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -7,8 +7,8 @@
#include <stddef.h>
#include <stdlib.h>
#include <sys/types.h>
+#include <csignal>
-#include "platform/assert.h"
#include "platform/globals.h"
#if defined(HOST_OS_WINDOWS)
#include <psapi.h>
@@ -16,6 +16,8 @@
#include <unistd.h>
#endif
+#include <setjmp.h>
+#include <signal.h>
#include <iostream>
#include <limits>
@@ -23,6 +25,9 @@
namespace dart {
+////////////////////////////////////////////////////////////////////////////////
+// Tests for Dart -> native calls.
+
// Sums two ints and adds 42.
// Simple function to test trampolines.
// Also used for testing argument exception on passing null instead of a Dart
@@ -449,7 +454,8 @@
return retval;
}
-// Functions for stress-testing GC by returning values that require boxing.
+////////////////////////////////////////////////////////////////////////////////
+// Functions for stress-testing.
DART_EXPORT int64_t MinInt64() {
return 0x8000000000000000;
@@ -505,10 +511,222 @@
char filename[256];
snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
FILE* f = freopen(filename, "w", stderr);
- ASSERT(f);
+ if (f == nullptr) {
+ fprintf(stderr, "Could not open temp file.\n");
+ Dart_PrepareToAbort();
+ abort();
+ }
printf("Got file %s\n", filename);
return getpid();
}
#endif
+////////////////////////////////////////////////////////////////////////////////
+// Tests for callbacks.
+
+#define CHECK(X) \
+ if (!(X)) { \
+ fprintf(stderr, "%s\n", "Check failed: " #X); \
+ return 1; \
+ }
+
+#define CHECK_EQ(X, Y) CHECK((X) == (Y))
+
+// Sanity test.
+DART_EXPORT int TestSimpleAddition(int (*add)(int, int)) {
+ CHECK_EQ(add(10, 20), 30);
+ return 0;
+}
+
+//// Following tests are copied from above, with the role of Dart and C++ code
+//// reversed.
+
+DART_EXPORT int TestIntComputation(
+ int64_t (*fn)(int8_t, int16_t, int32_t, int64_t)) {
+ CHECK_EQ(fn(125, 250, 500, 1000), 625);
+ CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+ CHECK_EQ(((int64_t)-0x8000000000000000LL),
+ fn(0, 0, 0, -0x8000000000000000LL));
+ return 0;
+}
+
+DART_EXPORT int TestUintComputation(
+ uint64_t (*fn)(uint8_t, uint16_t, uint32_t, uint64_t)) {
+ CHECK_EQ(0x7FFFFFFFFFFFFFFFLL, fn(0, 0, 0, 0x7FFFFFFFFFFFFFFFLL));
+ CHECK_EQ(-0x8000000000000000LL, fn(0, 0, 0, -0x8000000000000000LL));
+ CHECK_EQ(-1, (int64_t)fn(0, 0, 0, -1));
+ return 0;
+}
+
+DART_EXPORT int TestSimpleMultiply(double (*fn)(double)) {
+ CHECK_EQ(fn(2.0), 2.0 * 1.337);
+ return 0;
+}
+
+DART_EXPORT int TestSimpleMultiplyFloat(float (*fn)(float)) {
+ CHECK(std::abs(fn(2.0) - 2.0 * 1.337) < 0.001);
+ return 0;
+}
+
+DART_EXPORT int TestManyInts(intptr_t (*fn)(intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t,
+ intptr_t)) {
+ CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+ return 0;
+}
+
+DART_EXPORT int TestManyDoubles(double (*fn)(double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ double,
+ double)) {
+ CHECK_EQ(55, fn(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+ return 0;
+}
+
+DART_EXPORT int TestManyArgs(double (*fn)(intptr_t a,
+ float b,
+ intptr_t c,
+ double d,
+ intptr_t e,
+ float f,
+ intptr_t g,
+ double h,
+ intptr_t i,
+ float j,
+ intptr_t k,
+ double l,
+ intptr_t m,
+ float n,
+ intptr_t o,
+ double p,
+ intptr_t q,
+ float r,
+ intptr_t s,
+ double t)) {
+ CHECK(210.0 == fn(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13, 14.0,
+ 15, 16.0, 17, 18.0, 19, 20.0));
+ return 0;
+}
+
+DART_EXPORT int TestStore(int64_t* (*fn)(int64_t* a)) {
+ int64_t p[2] = {42, 1000};
+ int64_t* result = fn(p);
+ CHECK_EQ(*result, 1337);
+ CHECK_EQ(p[1], 1337);
+ CHECK_EQ(result, p + 1);
+ return 0;
+}
+
+DART_EXPORT int TestReturnNull(int32_t fn()) {
+ CHECK_EQ(fn(), 0);
+ return 0;
+}
+
+DART_EXPORT int TestNullPointers(int64_t* (*fn)(int64_t* ptr)) {
+ CHECK_EQ(fn(nullptr), nullptr);
+ int64_t p[2] = {0};
+ CHECK_EQ(fn(p), p + 1);
+ return 0;
+}
+
+struct CallbackTestData {
+ int success;
+ void (*callback)();
+};
+
+#if defined(TARGET_OS_LINUX)
+
+thread_local sigjmp_buf buf;
+void CallbackTestSignalHandler(int) {
+ siglongjmp(buf, 1);
+}
+
+int ExpectAbort(void (*fn)()) {
+ fprintf(stderr, "**** EXPECT STACKTRACE TO FOLLOW. THIS IS OK. ****\n");
+
+ struct sigaction old_action;
+ int result = __sigsetjmp(buf, /*savesigs=*/1);
+ if (result == 0) {
+ // Install signal handler.
+ struct sigaction handler;
+ handler.sa_handler = CallbackTestSignalHandler;
+ sigemptyset(&handler.sa_mask);
+ handler.sa_flags = 0;
+
+ sigaction(SIGABRT, &handler, &old_action);
+
+ fn();
+ } else {
+ // Caught the setjmp.
+ sigaction(SIGABRT, &old_action, NULL);
+ exit(0);
+ }
+ fprintf(stderr, "Expected abort!!!\n");
+ exit(1);
+}
+
+void* TestCallbackOnThreadOutsideIsolate(void* parameter) {
+ CallbackTestData* data = reinterpret_cast<CallbackTestData*>(parameter);
+ data->success = ExpectAbort(data->callback);
+ return NULL;
+}
+
+int TestCallbackOtherThreadHelper(void* (*tester)(void*), void (*fn)()) {
+ CallbackTestData data = {1, fn};
+ pthread_attr_t attr;
+ int result = pthread_attr_init(&attr);
+ CHECK_EQ(result, 0);
+
+ pthread_t tid;
+ result = pthread_create(&tid, &attr, tester, &data);
+ CHECK_EQ(result, 0);
+
+ result = pthread_attr_destroy(&attr);
+ CHECK_EQ(result, 0);
+
+ void* retval;
+ result = pthread_join(tid, &retval);
+
+ // Doesn't actually return because the other thread will exit when the test is
+ // finished.
+ return 1;
+}
+
+// Run a callback on another thread and verify that it triggers SIGABRT.
+DART_EXPORT int TestCallbackWrongThread(void (*fn)()) {
+ return TestCallbackOtherThreadHelper(&TestCallbackOnThreadOutsideIsolate, fn);
+}
+
+// Verify that we get SIGABRT when invoking a native callback outside an
+// isolate.
+DART_EXPORT int TestCallbackOutsideIsolate(void (*fn)()) {
+ Dart_Isolate current = Dart_CurrentIsolate();
+
+ Dart_ExitIsolate();
+ CallbackTestData data = {1, fn};
+ TestCallbackOnThreadOutsideIsolate(&data);
+ Dart_EnterIsolate(current);
+
+ return data.success;
+}
+
+DART_EXPORT int TestCallbackWrongIsolate(void (*fn)()) {
+ return ExpectAbort(fn);
+}
+
+#endif // defined(TARGET_OS_LINUX)
+
} // namespace dart
diff --git a/runtime/bin/file_fuchsia.cc b/runtime/bin/file_fuchsia.cc
index 1f60fca..74e3c50 100644
--- a/runtime/bin/file_fuchsia.cc
+++ b/runtime/bin/file_fuchsia.cc
@@ -255,9 +255,8 @@
if (NO_RETRY_EXPECTED(fstatat(ns.fd(), ns.path(), &st, 0)) == 0) {
// Everything but a directory and a link is a file to Dart.
return !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode);
- } else {
- return false;
}
+ return false;
}
bool File::Create(Namespace* namespc, const char* name) {
@@ -265,14 +264,17 @@
const int fd = NO_RETRY_EXPECTED(
openat(ns.fd(), ns.path(), O_RDONLY | O_CREAT | O_CLOEXEC, 0666));
if (fd < 0) {
+ Syslog::PrintErr("File::Create() openat(%ld, %s) failed: %s\n", ns.fd(),
+ ns.path(), strerror(errno));
return false;
}
// File.create returns a File, so we shouldn't be giving the illusion that the
// call has created a file or that a file already exists if there is already
// an entity at the same path that is a directory or a link.
- bool is_file = true;
+ bool is_file = false;
struct stat st;
if (NO_RETRY_EXPECTED(fstat(fd, &st)) == 0) {
+ is_file = true;
if (S_ISDIR(st.st_mode)) {
errno = EISDIR;
is_file = false;
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index af9741e..6af098e 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -83,6 +83,7 @@
kAppJIT,
kAppAOTBlobs,
kAppAOTAssembly,
+ kAppAOTElf,
kVMAOTAssembly,
};
static SnapshotKind snapshot_kind = kCore;
@@ -96,6 +97,7 @@
"app-jit",
"app-aot-blobs",
"app-aot-assembly",
+ "app-aot-elf",
"vm-aot-assembly",
NULL,
// clang-format on
@@ -146,7 +148,7 @@
static bool IsSnapshottingForPrecompilation() {
return (snapshot_kind == kAppAOTBlobs) ||
- (snapshot_kind == kAppAOTAssembly) ||
+ (snapshot_kind == kAppAOTAssembly) || (snapshot_kind == kAppAOTElf) ||
(snapshot_kind == kVMAOTAssembly);
}
@@ -315,7 +317,8 @@
}
break;
}
- case kAppAOTAssembly: {
+ case kAppAOTAssembly:
+ case kAppAOTElf: {
if (assembly_filename == NULL) {
Syslog::PrintErr(
"Building an AOT snapshot as assembly requires specifying "
@@ -420,10 +423,18 @@
if ((load_compilation_trace_filename != NULL) &&
((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+ // Finalize all classes. This ensures that there are no non-finalized
+ // classes in the gaps between cid ranges. Such classes prevent merging of
+ // cid ranges.
+ Dart_Handle result = Dart_FinalizeAllClasses();
+ CHECK_RESULT(result);
+ // Sort classes to have better cid ranges.
+ result = Dart_SortClasses();
+ CHECK_RESULT(result);
uint8_t* buffer = NULL;
intptr_t size = 0;
ReadFile(load_compilation_trace_filename, &buffer, &size);
- Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
+ result = Dart_LoadCompilationTrace(buffer, size);
free(buffer);
CHECK_RESULT(result);
}
@@ -613,16 +624,17 @@
CHECK_RESULT(result);
// Create a precompiled snapshot.
- bool as_assembly = assembly_filename != NULL;
- if (as_assembly) {
- ASSERT(snapshot_kind == kAppAOTAssembly);
+ if (snapshot_kind == kAppAOTAssembly) {
File* file = OpenFile(assembly_filename);
RefCntReleaseScope<File> rs(file);
result = Dart_CreateAppAOTSnapshotAsAssembly(StreamingWriteCallback, file);
CHECK_RESULT(result);
- } else {
- ASSERT(snapshot_kind == kAppAOTBlobs);
-
+ } else if (snapshot_kind == kAppAOTElf) {
+ File* file = OpenFile(assembly_filename);
+ RefCntReleaseScope<File> rs(file);
+ result = Dart_CreateAppAOTSnapshotAsElf(StreamingWriteCallback, file);
+ CHECK_RESULT(result);
+ } else if (snapshot_kind == kAppAOTBlobs) {
const uint8_t* shared_data = NULL;
const uint8_t* shared_instructions = NULL;
std::unique_ptr<MappedMemory> mapped_shared_data;
@@ -686,6 +698,8 @@
isolate_snapshot_instructions_buffer,
isolate_snapshot_instructions_size);
}
+ } else {
+ UNREACHABLE();
}
// Serialize obfuscation map if requested.
@@ -777,8 +791,9 @@
case kAppJIT:
CreateAndWriteAppJITSnapshot();
break;
- case kAppAOTBlobs:
case kAppAOTAssembly:
+ case kAppAOTBlobs:
+ case kAppAOTElf:
CreateAndWritePrecompiledSnapshot();
break;
case kVMAOTAssembly: {
diff --git a/runtime/bin/namespace_fuchsia.cc b/runtime/bin/namespace_fuchsia.cc
index da60ee0..6e93bcb 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -22,20 +22,32 @@
NamespaceImpl::NamespaceImpl(fdio_ns_t* fdio_ns)
: fdio_ns_(fdio_ns),
- rootfd_(fdio_ns_opendir(fdio_ns)),
cwd_(strdup("/")) {
- ASSERT(rootfd_ > 0);
+ rootfd_ = fdio_ns_opendir(fdio_ns);
+ if (rootfd_ < 0) {
+ FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+ strerror(errno));
+ }
cwdfd_ = dup(rootfd_);
- ASSERT(cwdfd_ > 0);
+ if (cwdfd_ < 0) {
+ FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+ strerror(errno));
+ }
}
NamespaceImpl::NamespaceImpl(const char* path)
: fdio_ns_(NULL),
- rootfd_(TEMP_FAILURE_RETRY(open(path, O_DIRECTORY))),
cwd_(strdup("/")) {
- ASSERT(rootfd_ > 0);
+ rootfd_ = TEMP_FAILURE_RETRY(open(path, O_DIRECTORY));
+ if (rootfd_ < 0) {
+ FATAL2("Failed to open file descriptor for namespace: errno=%d: %s", errno,
+ strerror(errno));
+ }
cwdfd_ = dup(rootfd_);
- ASSERT(cwdfd_ > 0);
+ if (cwdfd_ < 0) {
+ FATAL2("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
+ strerror(errno));
+ }
}
NamespaceImpl::~NamespaceImpl() {
@@ -54,7 +66,7 @@
NamespaceScope ns(namespc, new_path);
const intptr_t new_cwdfd =
TEMP_FAILURE_RETRY(openat(ns.fd(), ns.path(), O_DIRECTORY));
- if (new_cwdfd != 0) {
+ if (new_cwdfd < 0) {
return false;
}
diff --git a/runtime/bin/socket_base_fuchsia.cc b/runtime/bin/socket_base_fuchsia.cc
index b2f6524..a08257d 100644
--- a/runtime/bin/socket_base_fuchsia.cc
+++ b/runtime/bin/socket_base_fuchsia.cc
@@ -181,7 +181,13 @@
}
void SocketBase::GetError(intptr_t fd, OSError* os_error) {
- errno = ENOSYS;
+ IOHandle* handle = reinterpret_cast<IOHandle*>(fd);
+ ASSERT(handle->fd() >= 0);
+ int len = sizeof(errno);
+ int err = 0;
+ VOID_NO_RETRY_EXPECTED(getsockopt(handle->fd(), SOL_SOCKET, SO_ERROR, &err,
+ reinterpret_cast<socklen_t*>(&len)));
+ errno = err;
os_error->SetCodeAndMessage(OSError::kSystem, errno);
}
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart
index 870179c..4a87275 100644
--- a/runtime/bin/socket_patch.dart
+++ b/runtime/bin/socket_patch.dart
@@ -504,9 +504,21 @@
// indicate that the socket is fully connected.
socket.setHandlers(write: () {
timer.cancel();
+ connecting.remove(socket);
+ // From 'man 2 connect':
+ // After select(2) indicates writability, use getsockopt(2) to read
+ // the SO_ERROR option at level SOL_SOCKET to determine whether
+ // connect() completed successfully (SO_ERROR is zero) or
+ // unsuccessfully.
+ OSError osError = socket.nativeGetError();
+ if (osError.errorCode != 0) {
+ socket.close();
+ if (error == null) error = osError;
+ if (connecting.isEmpty) connectNext();
+ return;
+ }
socket.setListening(read: false, write: false);
completer.complete(socket);
- connecting.remove(socket);
connecting.forEach((s, t) {
t.cancel();
s.close();
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index f144ed4..7103341 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -3266,7 +3266,7 @@
* Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
* The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
* Dart_Initialize. The kDartIsolateSnapshotData and
- * kDartIsoalteSnapshotInstructions should be passed to Dart_CreateIsolate.
+ * kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
*
* The callback will be invoked one or more times to provide the assembly code.
*
@@ -3277,6 +3277,31 @@
void* callback_data);
/**
+ * Creates a precompiled snapshot.
+ * - A root library must have been loaded.
+ * - Dart_Precompile must have been called.
+ *
+ * Outputs an ELF shared library defining the symbols
+ * - kDartVmSnapshotData
+ * - kDartVmSnapshotInstructions
+ * - kDartIsolateSnapshotData
+ * - kDartIsolateSnapshotInstructions
+ *
+ * The shared library should be dynamically loaded by the embedder.
+ * Running this snapshot requires a VM compiled with DART_PRECOMPILED_SNAPSHOT.
+ * The kDartVmSnapshotData and kDartVmSnapshotInstructions should be passed to
+ * Dart_Initialize. The kDartIsolateSnapshotData and
+ * kDartIsolateSnapshotInstructions should be passed to Dart_CreateIsolate.
+ *
+ * The callback will be invoked one or more times to provide the binary output.
+ *
+ * \return A valid handle if no error occurs during the operation.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+ void* callback_data);
+
+/**
* Like Dart_CreateAppAOTSnapshotAsAssembly, but only includes
* kDartVmSnapshotData and kDartVmSnapshotInstructions.
*/
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 39b29ff..3b8f4d2 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -170,4 +170,9 @@
DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_ReadAllBytecode();
+/**
+ * Finalizes all classes.
+ */
+DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses();
+
#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 2046284..19c1919 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -1986,6 +1986,7 @@
_rsh(uDigits, maxUsed, 1, uDigits);
if (ac) {
if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+ // a += y
if (aIsNegative) {
if ((aDigits[maxUsed] != 0) ||
(_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -1997,6 +1998,7 @@
} else {
_absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
}
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2009,6 +2011,7 @@
}
_rsh(aDigits, abcdUsed, 1, aDigits);
} else if ((bDigits[0] & 1) == 1) {
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2025,6 +2028,7 @@
_rsh(vDigits, maxUsed, 1, vDigits);
if (ac) {
if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+ // c += y
if (cIsNegative) {
if ((cDigits[maxUsed] != 0) ||
(_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2036,6 +2040,7 @@
} else {
_absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
}
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2048,6 +2053,7 @@
}
_rsh(cDigits, abcdUsed, 1, cDigits);
} else if ((dDigits[0] & 1) == 1) {
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2061,8 +2067,10 @@
_rsh(dDigits, abcdUsed, 1, dDigits);
}
if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+ // u -= v
_absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
if (ac) {
+ // a -= c
if (aIsNegative == cIsNegative) {
var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
if (a_cmp_c > 0) {
@@ -2075,6 +2083,7 @@
_absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
}
}
+ // b -= d
if (bIsNegative == dIsNegative) {
var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
if (b_cmp_d > 0) {
@@ -2087,8 +2096,10 @@
_absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
}
} else {
+ // v -= u
_absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
if (ac) {
+ // c -= a
if (cIsNegative == aIsNegative) {
var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
if (c_cmp_a > 0) {
@@ -2101,6 +2112,7 @@
_absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
}
}
+ // d -= b
if (dIsNegative == bIsNegative) {
var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
if (d_cmp_b > 0) {
@@ -2132,25 +2144,18 @@
}
if (dIsNegative) {
- if ((dDigits[maxUsed] != 0) ||
+ while ((dDigits[maxUsed] != 0) ||
(_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x, d still negative
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
- }
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
}
- } else if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x
+ _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+ dIsNegative = false;
+ } else {
+ while ((dDigits[maxUsed] != 0) ||
+ (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+ // d -= x
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
}
}
diff --git a/runtime/lib/developer.dart b/runtime/lib/developer.dart
index 12ad8b7..cb35073 100644
--- a/runtime/lib/developer.dart
+++ b/runtime/lib/developer.dart
@@ -131,7 +131,7 @@
assert(id != null);
StringBuffer sb = new StringBuffer();
sb.write('{"jsonrpc":"2.0",');
- if (response._isError()) {
+ if (response.isError()) {
if (trace_service) {
print("vm-service: posting error response for request $id");
}
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 34a5530..5dd4367 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -9,6 +9,7 @@
#include "vm/class_finalizer.h"
#include "vm/compiler/assembler/assembler.h"
#include "vm/compiler/ffi.h"
+#include "vm/compiler/jit/compiler.h"
#include "vm/exceptions.h"
#include "vm/log.h"
#include "vm/native_arguments.h"
@@ -546,53 +547,68 @@
return raw_closure;
}
-// Generates assembly to trampoline from C++ back into Dart.
-static void* GenerateFfiInverseTrampoline(const Function& signature,
- void* dart_entry_point) {
+// Generates assembly to trampoline from native code into Dart.
+static uword CompileNativeCallback(const Function& c_signature,
+ const Function& dart_target) {
#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
UNREACHABLE();
-#elif !defined(TARGET_ARCH_X64)
+#elif defined(TARGET_ARCH_DBC)
// https://github.com/dart-lang/sdk/issues/35774
- UNREACHABLE();
-#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS) && \
- !defined(TARGET_OS_WINDOWS)
- // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
- // https://github.com/dart-lang/sdk/issues/35772 Arm64
- // https://github.com/dart-lang/sdk/issues/35773 DBC
- UNREACHABLE();
+ // FFI is supported, but callbacks are not.
+ Exceptions::ThrowUnsupportedError(
+ "FFI callbacks are not yet supported on DBC.");
#else
+ Thread* const thread = Thread::Current();
+ const int32_t callback_id = thread->AllocateFfiCallbackId();
- // TODO(dacoharkes): Implement this.
- // https://github.com/dart-lang/sdk/issues/35761
- // Look at StubCode::GenerateInvokeDartCodeStub.
- UNREACHABLE();
+ // Create a new Function named 'FfiCallback' and stick it in the 'dart:ffi'
+ // library. Note that these functions will never be invoked by Dart, so it
+ // doesn't matter that they all have the same name.
+ Zone* const Z = thread->zone();
+ const String& name =
+ String::ZoneHandle(Symbols::New(Thread::Current(), "FfiCallback"));
+ const Library& lib = Library::Handle(Library::FfiLibrary());
+ const Class& owner_class = Class::Handle(lib.toplevel_class());
+ const Function& function =
+ Function::Handle(Z, Function::New(name, RawFunction::kFfiTrampoline,
+ /*is_static=*/true,
+ /*is_const=*/false,
+ /*is_abstract=*/false,
+ /*is_external=*/false,
+ /*is_native=*/false, owner_class,
+ TokenPosition::kMinSource));
+ function.set_is_debuggable(false);
+
+ // Set callback-specific fields which the flow-graph builder needs to generate
+ // the body.
+ function.SetFfiCSignature(c_signature);
+ function.SetFfiCallbackId(callback_id);
+ function.SetFfiCallbackTarget(dart_target);
+
+ // We compile the callback immediately because we need to return a pointer to
+ // the entry-point. Native calls do not use patching like Dart calls, so we
+ // cannot compile it lazily.
+ const Object& result =
+ Object::Handle(Z, Compiler::CompileOptimizedFunction(thread, function));
+ if (result.IsError()) {
+ Exceptions::PropagateError(Error::Cast(result));
+ }
+ ASSERT(result.IsCode());
+ const Code& code = Code::Cast(result);
+
+ thread->SetFfiCallbackCode(callback_id, code);
+
+ return code.EntryPoint();
#endif
}
-// TODO(dacoharkes): Implement this feature.
-// https://github.com/dart-lang/sdk/issues/35761
-// For now, it always returns Pointer with address 0.
DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 1) {
GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0));
- Function& c_signature = Function::Handle(((Type&)type_arg).signature());
-
+ const Function& native_signature =
+ Function::Handle(((Type&)type_arg).signature());
Function& func = Function::Handle(closure.function());
- Code& code = Code::Handle(func.EnsureHasCode());
- void* entryPoint = reinterpret_cast<void*>(code.EntryPoint());
-
- THR_Print("Ffi_fromFunction: %s\n", type_arg.ToCString());
- THR_Print("Ffi_fromFunction: %s\n", c_signature.ToCString());
- THR_Print("Ffi_fromFunction: %s\n", closure.ToCString());
- THR_Print("Ffi_fromFunction: %s\n", func.ToCString());
- THR_Print("Ffi_fromFunction: %s\n", code.ToCString());
- THR_Print("Ffi_fromFunction: %p\n", entryPoint);
- THR_Print("Ffi_fromFunction: %" Pd "\n", code.Size());
-
- intptr_t address = reinterpret_cast<intptr_t>(
- GenerateFfiInverseTrampoline(c_signature, entryPoint));
-
TypeArguments& type_args = TypeArguments::Handle(zone);
type_args = TypeArguments::New(1);
type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
@@ -608,9 +624,19 @@
ClassFinalizer::FinalizeType(Class::Handle(), native_function_type);
native_function_type ^= native_function_type.Canonicalize();
- address = 0; // https://github.com/dart-lang/sdk/issues/35761
+ // The FE verifies that the target of a 'fromFunction' is a static method, so
+ // the value we see here must be a static tearoff. See ffi_use_sites.dart for
+ // details.
+ //
+ // TODO(36748): Define hot-reload semantics of native callbacks. We may need
+ // to look up the target by name.
+ ASSERT(func.IsImplicitClosureFunction());
+ func = func.parent_function();
+ ASSERT(func.is_static());
- Pointer& result = Pointer::Handle(Pointer::New(
+ const uword address = CompileNativeCallback(native_signature, func);
+
+ const Pointer& result = Pointer::Handle(Pointer::New(
native_function_type, Integer::Handle(zone, Integer::New(address))));
return result.raw();
@@ -682,7 +708,7 @@
} else if (loc.IsFpuRegister()) {
descr.SetFpuRegister(loc.fpu_reg(), arg_value);
} else {
- ASSERT(loc.IsStackSlot());
+ ASSERT(loc.IsStackSlot() || loc.IsDoubleStackSlot());
ASSERT(loc.stack_index() < num_stack_slots);
descr.SetStackSlotValue(loc.stack_index(), arg_value);
}
diff --git a/runtime/lib/ffi_patch.dart b/runtime/lib/ffi_patch.dart
index c8fde6c..6915d51 100644
--- a/runtime/lib/ffi_patch.dart
+++ b/runtime/lib/ffi_patch.dart
@@ -53,3 +53,21 @@
@patch
void free() native "Ffi_free";
}
+
+// This method gets called when an exception bubbles up to the native -> Dart
+// boundary from an FFI native callback. Since native code does not have any
+// concept of exceptions, the exception cannot be propagated any further.
+// Instead, print a warning with the exception and return 0/0.0 from the
+// callback.
+//
+// TODO(36856): Iron out the story behind exceptions.
+@pragma("vm:entry-point")
+void _handleExposedException(dynamic exception, dynamic stackTrace) {
+ print(
+ "==================== UNHANDLED EXCEPTION FROM FFI CALLBACK ====================");
+ print(
+ """ ** Native callbacks should not throw exceptions because they cannot be
+ propagated into native code. **""");
+ print("EXCEPTION: $exception");
+ print(stackTrace);
+}
diff --git a/runtime/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 2215806..3be3b2b 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -451,6 +451,8 @@
return 'collected';
case M.FunctionKind.native:
return 'native';
+ case M.FunctionKind.ffiTrampoline:
+ return 'ffi trampoline';
case M.FunctionKind.stub:
return 'stub';
case M.FunctionKind.tag:
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index 68bd5ae..098003b 100644
--- a/runtime/observatory/lib/src/models/objects/function.dart
+++ b/runtime/observatory/lib/src/models/objects/function.dart
@@ -21,6 +21,7 @@
invokeFieldDispatcher,
collected,
native,
+ ffiTrampoline,
stub,
tag,
signatureFunction,
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index a36dd23..dace8a9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1225,7 +1225,7 @@
/// State for a running isolate.
class Isolate extends ServiceObjectOwner implements M.Isolate {
- static const kLoggingStream = '_Logging';
+ static const kLoggingStream = 'Logging';
static const kExtensionStream = 'Extension';
VM get vm => owner;
@@ -2104,7 +2104,7 @@
static const kInspect = 'Inspect';
static const kDebuggerSettingsUpdate = '_DebuggerSettingsUpdate';
static const kConnectionClosed = 'ConnectionClosed';
- static const kLogging = '_Logging';
+ static const kLogging = 'Logging';
static const kExtension = 'Extension';
static const kServiceRegistered = 'ServiceRegistered';
static const kServiceUnregistered = 'ServiceUnregistered';
@@ -3036,6 +3036,8 @@
return M.FunctionKind.collected;
case 'Native':
return M.FunctionKind.native;
+ case 'FfiTrampoline':
+ return M.FunctionKind.ffiTrampoline;
case 'Stub':
return M.FunctionKind.stub;
case 'Tag':
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index ca2028a..f5eb252 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
var result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(3));
- expect(result['minor'], equals(14));
+ expect(result['minor'], equals(17));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 7815569..a3632e8 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -318,6 +318,20 @@
#endif
#endif
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM)
+#define TARGET_ARCH_IS_32_BIT 1
+#elif defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
+#define TARGET_ARCH_IS_64_BIT 1
+#elif defined(TARGET_ARCH_DBC)
+#if defined(ARCH_IS_32_BIT)
+#define TARGET_ARCH_IS_32_BIT 1
+#else
+#define TARGET_ARCH_IS_64_BIT 1
+#endif
+#else
+#error Automatic target architecture detection failed.
+#endif
+
// Verify that host and target architectures match, we cannot
// have a 64 bit Dart VM generating 32 bit code or vice-versa.
#if defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM64)
diff --git a/runtime/tests/vm/dart/regress36953_test.dart b/runtime/tests/vm/dart/regress36953_test.dart
new file mode 100644
index 0000000..617049b
--- /dev/null
+++ b/runtime/tests/vm/dart/regress36953_test.dart
@@ -0,0 +1,30 @@
+// 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.
+
+// Regression test for dartbug.com/36953: check that phi is inserted correctly
+// when try block has no normal exit.
+
+// VMOptions=--optimization_counter_threshold=10 --deterministic
+
+import "package:expect/expect.dart";
+
+void testBody() {
+ var v;
+ do {
+ try {} catch (e, st) {
+ continue;
+ }
+
+ try {
+ v = 10;
+ throw "";
+ } catch (e, st) {}
+ } while (v++ < 10);
+ Expect.equals(11, v);
+}
+
+void main() {
+ testBody();
+ testBody();
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 79a253b..143f5ca 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -259,18 +259,6 @@
[ $compiler == dart2analyzer || $compiler == dart2js ]
dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
-# Tests that use functionality not supported in Dart 2.
-[ ($compiler == dartk || $compiler == dartkb) || $compiler == dartkp ]
-cc/DartAPI_IsolateSetCheckedMode: SkipByDesign # Checked mode is not relevant for dart 2?
-cc/CompileFunction: SkipByDesign
-cc/InvokeDynamic_CompileError: SkipByDesign
-cc/InvokeStatic_CompileError: SkipByDesign
-cc/DartEntry: SkipByDesign
-cc/FindCodeObject: SkipByDesign
-cc/DartDynamicResolve: SkipByDesign
-cc/DartStaticResolve: SkipByDesign
-cc/CompileScript: SkipByDesign
-
[ $compiler == precompiler || $mode == product ]
cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 5ccc521..6b9f82f 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -177,3 +177,15 @@
":vm_platform_stripped",
]
}
+
+executable("offsets_extractor") {
+ configs += [
+ "..:dart_arch_config",
+ "..:dart_config",
+ ":libdart_vm_config",
+ ]
+ sources = [
+ "compiler/offsets_extractor.cc",
+ ]
+ include_dirs = [ ".." ]
+}
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 9404617..3268bb7 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -39,14 +39,6 @@
friend class IsolateReloadContext; // For VisitObjectPointers.
};
-#if defined(ARCH_IS_32_BIT)
-const int kSizeOfClassPairLog2 = 3;
-#else
-const int kSizeOfClassPairLog2 = 4;
-#endif
-
-COMPILE_ASSERT((1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize));
-
#ifndef PRODUCT
template <typename T>
class AllocStats {
@@ -261,6 +253,24 @@
static intptr_t ClassOffsetFor(intptr_t cid);
#ifndef PRODUCT
+ // Describes layout of heap stats for code generation. See offset_extractor.cc
+ struct ArrayLayout {
+ static intptr_t elements_start_offset() { return 0; }
+
+ static constexpr intptr_t kElementSize = sizeof(ClassHeapStats);
+ };
+#endif
+
+#if defined(ARCH_IS_32_BIT)
+ static constexpr int kSizeOfClassPairLog2 = 3;
+#else
+ static constexpr int kSizeOfClassPairLog2 = 4;
+#endif
+ static_assert(
+ (1 << kSizeOfClassPairLog2) == sizeof(ClassAndSize),
+ "Mismatch between sizeof(ClassAndSize) and kSizeOfClassPairLog2");
+
+#ifndef PRODUCT
// Called whenever a class is allocated in the runtime.
void UpdateAllocatedNew(intptr_t cid, intptr_t size) {
ClassHeapStats* stats = PreliminaryStatsAt(cid);
@@ -286,6 +296,11 @@
void UpdatePromoted();
// Used by the generated code.
+ static intptr_t class_heap_stats_table_offset() {
+ return OFFSET_OF(ClassTable, class_heap_stats_table_);
+ }
+
+ // Used by the generated code.
static intptr_t TableOffsetFor(intptr_t cid);
// Used by the generated code.
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index dba74ea..ae78790 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -1552,6 +1552,8 @@
WriteFromTo(bytecode);
s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
+ NOT_IN_PRODUCT(
+ s->Write<int32_t>(bytecode->ptr()->local_variables_binary_offset_));
}
}
@@ -1586,6 +1588,8 @@
ReadFromTo(bytecode);
bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
+ NOT_IN_PRODUCT(bytecode->ptr()->local_variables_binary_offset_ =
+ d->Read<int32_t>());
}
}
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 29b1fad..9fa7585 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2172,32 +2172,9 @@
}
void Precompiler::FinalizeAllClasses() {
- Library& lib = Library::Handle(Z);
- Class& cls = Class::Handle(Z);
-
- for (intptr_t i = 0; i < libraries_.Length(); i++) {
- lib ^= libraries_.At(i);
- if (!lib.Loaded()) {
- String& uri = String::Handle(Z, lib.url());
- String& msg = String::Handle(
- Z,
- String::NewFormatted("Library '%s' is not loaded. "
- "Did you forget to call Dart_FinalizeLoading?",
- uri.ToCString()));
- Jump(Error::Handle(Z, ApiError::New(msg)));
- }
-
- ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
- while (it.HasNext()) {
- cls = it.GetNextClass();
- if (cls.IsDynamicClass()) {
- continue; // class 'dynamic' is in the read-only VM isolate.
- }
- error_ = cls.EnsureIsFinalized(T);
- if (!error_.IsNull()) {
- Jump(error_);
- }
- }
+ error_ = Library::FinalizeAllClasses();
+ if (!error_.IsNull()) {
+ Jump(error_);
}
I->set_all_classes_finalized(true);
}
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 9a40633..dbfc95e 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -548,10 +548,12 @@
}
void Assembler::TransitionGeneratedToNative(Register destination_address,
+ Register exit_frame_fp,
Register addr,
Register state) {
// Save exit frame information to enable stack walking.
- StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+ StoreToOffset(kWord, exit_frame_fp, THR,
+ Thread::top_exit_frame_info_offset());
// Mark that the thread is executing native code.
StoreToOffset(kWord, destination_address, THR, Thread::vm_tag_offset());
@@ -2496,6 +2498,33 @@
}
}
+void Assembler::PushNativeCalleeSavedRegisters() {
+ // Save new context and C++ ABI callee-saved registers.
+ PushList(kAbiPreservedCpuRegs);
+
+ const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+ if (TargetCPUFeatures::vfp_supported()) {
+ ASSERT(2 * kAbiPreservedFpuRegCount < 16);
+ // Save FPU registers. 2 D registers per Q register.
+ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+ } else {
+ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
+ }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+ const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
+ // Restore C++ ABI callee-saved registers.
+ if (TargetCPUFeatures::vfp_supported()) {
+ // Restore FPU registers. 2 D registers per Q register.
+ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
+ } else {
+ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
+ }
+ // Restore CPU registers.
+ PopList(kAbiPreservedCpuRegs);
+}
+
void Assembler::MoveRegister(Register rd, Register rm, Condition cond) {
if (rd != rm) {
mov(rd, Operand(rm), cond);
@@ -3215,6 +3244,23 @@
}
}
+void Assembler::EmitEntryFrameVerification(Register scratch) {
+#if defined(DEBUG)
+ Label done;
+ ASSERT(!constant_pool_allowed());
+ LoadImmediate(scratch,
+ compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+ compiler::target::kWordSize);
+ add(scratch, scratch, Operand(FPREG));
+ cmp(scratch, Operand(SPREG));
+ b(&done, EQ);
+
+ Breakpoint();
+
+ Bind(&done);
+#endif
+}
+
void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
Comment("EnterCallRuntimeFrame");
// Preserve volatile CPU registers and PP.
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 7d2e40c..ceb1820 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -510,9 +510,12 @@
void ldrex(Register rd, Register rn, Condition cond = AL);
void strex(Register rd, Register rt, Register rn, Condition cond = AL);
- // Requires two temporary registers 'scratch0' and 'scratch1' (in addition to
- // TMP).
+ // Emit code to transition between generated and native modes.
+ //
+ // These require that CSP and SP are equal and aligned and require two scratch
+ // registers (in addition to TMP).
void TransitionGeneratedToNative(Register destination_address,
+ Register exit_frame_fp,
Register scratch0,
Register scratch1);
void TransitionNativeToGenerated(Register scratch0, Register scratch1);
@@ -917,6 +920,12 @@
void PushRegisters(const RegisterSet& regs);
void PopRegisters(const RegisterSet& regs);
+ // Push all registers which are callee-saved according to the ARM ABI.
+ void PushNativeCalleeSavedRegisters();
+
+ // Pop all registers which are callee-saved according to the ARM ABI.
+ void PopNativeCalleeSavedRegisters();
+
void CompareRegisters(Register rn, Register rm) { cmp(rn, Operand(rm)); }
void BranchIf(Condition condition, Label* label) { b(label, condition); }
@@ -1003,6 +1012,13 @@
void Ret();
void ReserveAlignedFrameSpace(intptr_t frame_space);
+ // In debug mode, this generates code to check that:
+ // FP + kExitLinkSlotFromEntryFp == SP
+ // or triggers breakpoint otherwise.
+ //
+ // Requires a scratch register in addition to the assembler temporary.
+ void EmitEntryFrameVerification(Register scratch);
+
// Create a frame for calling into runtime that preserves all volatile
// registers. Frame's SP is guaranteed to be correctly aligned and
// frame_space bytes are reserved under it.
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index 63775f1..d56909a 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -1164,6 +1164,23 @@
}
}
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+ Label done;
+ ASSERT(!constant_pool_allowed());
+ LoadImmediate(TMP,
+ compiler::target::frame_layout.exit_link_slot_from_entry_fp *
+ compiler::target::kWordSize);
+ add(TMP, TMP, Operand(FPREG));
+ cmp(TMP, Operand(SPREG));
+ b(&done, EQ);
+
+ Breakpoint();
+
+ Bind(&done);
+#endif
+}
+
void Assembler::RestoreCodePointer() {
ldr(CODE_REG, Address(FP, compiler::target::frame_layout.code_from_fp *
target::kWordSize));
@@ -1295,11 +1312,12 @@
}
void Assembler::TransitionGeneratedToNative(Register destination,
+ Register new_exit_rame,
Register state) {
Register addr = TMP2;
// Save exit frame information to enable stack walking.
- StoreToOffset(FPREG, THR,
+ StoreToOffset(new_exit_rame, THR,
compiler::target::Thread::top_exit_frame_info_offset());
// Mark that the thread is executing native code.
@@ -1826,6 +1844,41 @@
}
}
+void Assembler::PushNativeCalleeSavedRegisters() {
+ // Save the callee-saved registers.
+ for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
+ const Register r = static_cast<Register>(i);
+ // We use str instead of the Push macro because we will be pushing the PP
+ // register when it is not holding a pool-pointer since we are coming from
+ // C++ code.
+ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
+ }
+
+ // Save the bottom 64-bits of callee-saved V registers.
+ for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
+ const VRegister r = static_cast<VRegister>(i);
+ PushDouble(r);
+ }
+}
+
+void Assembler::PopNativeCalleeSavedRegisters() {
+ // Restore the bottom 64-bits of callee-saved V registers.
+ for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
+ const VRegister r = static_cast<VRegister>(i);
+ PopDouble(r);
+ }
+
+ // Restore C++ ABI callee-saved registers.
+ for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
+ Register r = static_cast<Register>(i);
+ // We use ldr instead of the Pop macro because we will be popping the PP
+ // register when it is not holding a pool-pointer since we are returning to
+ // C++ code. We also skip the dart stack pointer SP, since we are still
+ // using it as the stack pointer.
+ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
+ }
+}
+
} // namespace compiler
} // namespace dart
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index 1a0cfb7..cb9af12 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -438,6 +438,12 @@
void PushRegisters(const RegisterSet& registers);
void PopRegisters(const RegisterSet& registers);
+ // Push all registers which are callee-saved according to the ARM64 ABI.
+ void PushNativeCalleeSavedRegisters();
+
+ // Pop all registers which are callee-saved according to the ARM64 ABI.
+ void PopNativeCalleeSavedRegisters();
+
void MoveRegister(Register rd, Register rn) {
if (rd != rn) {
mov(rd, rn);
@@ -481,6 +487,11 @@
void ReserveAlignedFrameSpace(intptr_t frame_space);
+ // In debug mode, this generates code to check that:
+ // FP + kExitLinkSlotFromEntryFp == SP
+ // or triggers breakpoint otherwise.
+ void EmitEntryFrameVerification();
+
// Instruction pattern from entrypoint is used in Dart frame prologs
// to set up the frame and save a PC which can be used to figure out the
// RawInstruction object corresponding to the code running in the frame.
@@ -1524,9 +1535,13 @@
void LeaveFrame();
void Ret() { ret(LR); }
- // These require that CSP and SP are equal and aligned.
- // These require a scratch register (in addition to TMP/TMP2).
+ // Emit code to transition between generated mode and native mode.
+ //
+ // These require that CSP and SP are equal and aligned and require a scratch
+ // register (in addition to TMP/TMP2).
+
void TransitionGeneratedToNative(Register destination_address,
+ Register new_exit_frame,
Register scratch);
void TransitionNativeToGenerated(Register scratch);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index 32656b9..a451572 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2084,10 +2084,23 @@
}
}
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+ Label ok;
+ leal(EAX, Address(EBP, target::frame_layout.exit_link_slot_from_entry_fp *
+ target::kWordSize));
+ cmpl(EAX, ESP);
+ j(EQUAL, &ok);
+ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+ Bind(&ok);
+#endif
+}
+
void Assembler::TransitionGeneratedToNative(Register destination_address,
+ Register new_exit_frame,
Register scratch) {
// Save exit frame information to enable stack walking.
- movl(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+ movl(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
// Mark that the thread is executing native code.
movl(VMTagAddress(), destination_address);
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index df07d96..ad6149b 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -648,9 +648,23 @@
void MonomorphicCheckedEntry() {}
+ // In debug mode, this generates code to check that:
+ // FP + kExitLinkSlotFromEntryFp == SP
+ // or triggers breakpoint otherwise.
+ //
+ // Clobbers EAX.
+ void EmitEntryFrameVerification();
+
+ // Transitions safepoint and Thread state between generated and native code.
+ // Updates top-exit-frame info, VM tag and execution-state. Leaves/enters a
+ // safepoint.
+ //
// Require a temporary register 'tmp'.
// Clobber all non-CPU registers (e.g. XMM registers and the "FPU stack").
+ // However XMM0 is saved for convenience.
+
void TransitionGeneratedToNative(Register destination_address,
+ Register new_exit_frame,
Register scratch);
void TransitionNativeToGenerated(Register scratch);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 073a179..f9e725b 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -164,9 +164,10 @@
EmitUint8(0xC0 + (dst & 0x07));
}
-void Assembler::TransitionGeneratedToNative(Register destination_address) {
+void Assembler::TransitionGeneratedToNative(Register destination_address,
+ Register new_exit_frame) {
// Save exit frame information to enable stack walking.
- movq(Address(THR, Thread::top_exit_frame_info_offset()), FPREG);
+ movq(Address(THR, Thread::top_exit_frame_info_offset()), new_exit_frame);
movq(Assembler::VMTagAddress(), destination_address);
movq(Address(THR, compiler::target::Thread::execution_state_offset()),
@@ -1517,6 +1518,18 @@
}
}
+void Assembler::EmitEntryFrameVerification() {
+#if defined(DEBUG)
+ Label ok;
+ leaq(RAX, Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
+ target::kWordSize));
+ cmpq(RAX, RSP);
+ j(EQUAL, &ok);
+ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
+ Bind(&ok);
+#endif
+}
+
void Assembler::PushRegisters(intptr_t cpu_register_set,
intptr_t xmm_register_set) {
const intptr_t xmm_regs_count = RegisterSet::RegisterCount(xmm_register_set);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 1fe5400..4df9250 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -306,7 +306,8 @@
void setcc(Condition condition, ByteRegister dst);
- void TransitionGeneratedToNative(Register destination_address);
+ void TransitionGeneratedToNative(Register destination_address,
+ Register new_exit_frame);
void TransitionNativeToGenerated();
// Register-register, register-address and address-register instructions.
@@ -777,6 +778,13 @@
void LeaveFrame();
void ReserveAlignedFrameSpace(intptr_t frame_space);
+ // In debug mode, generates code to verify that:
+ // FP + kExitLinkSlotFromFp == SP
+ //
+ // Triggers breakpoint otherwise.
+ // Clobbers RAX.
+ void EmitEntryFrameVerification();
+
// Create a frame for calling into runtime that preserves all volatile
// registers. Frame's RSP is guaranteed to be correctly aligned and
// frame_space bytes are reserved under it.
diff --git a/runtime/vm/compiler/assembler/disassembler_kbc.cc b/runtime/vm/compiler/assembler/disassembler_kbc.cc
index 411e1cf..edd8506 100644
--- a/runtime/vm/compiler/assembler/disassembler_kbc.cc
+++ b/runtime/vm/compiler/assembler/disassembler_kbc.cc
@@ -8,6 +8,7 @@
#include "vm/compiler/assembler/disassembler_kbc.h"
#include "platform/assert.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/constants_kbc.h"
#include "vm/cpu.h"
#include "vm/instructions.h"
@@ -330,7 +331,6 @@
uword pc) {
const KBCInstr* instr = reinterpret_cast<const KBCInstr*>(pc);
const KernelBytecode::Opcode opcode = KernelBytecode::DecodeOpcode(instr);
- ASSERT(opcode < kOpcodeCount);
const intptr_t instr_size = KernelBytecode::kInstructionSize[opcode];
size_t name_size =
@@ -409,10 +409,35 @@
PcDescriptors::Handle(zone, bytecode.pc_descriptors());
THR_Print("%s}\n", descriptors.ToCString());
+ if (bytecode.HasSourcePositions()) {
+ THR_Print("Source positions for function '%s' {\n", function_fullname);
+ // 4 bits per hex digit + 2 for "0x".
+ const int addr_width = (kBitsPerWord / 4) + 2;
+ // "*" in a printf format specifier tells it to read the field width from
+ // the printf argument list.
+ THR_Print("%-*s\ttok-ix\n", addr_width, "pc");
+ kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+ while (iter.MoveNext()) {
+ THR_Print("%#-*" Px "\t%s\n", addr_width,
+ bytecode.PayloadStart() + iter.PcOffset(),
+ iter.TokenPos().ToCString());
+ }
+ THR_Print("}\n");
+ }
+
THR_Print("Exception Handlers for function '%s' {\n", function_fullname);
const ExceptionHandlers& handlers =
ExceptionHandlers::Handle(zone, bytecode.exception_handlers());
THR_Print("%s}\n", handlers.ToCString());
+
+ if (FLAG_print_variable_descriptors) {
+ THR_Print("Local variable descriptors for function '%s' {\n",
+ function_fullname);
+ const auto& var_descriptors =
+ LocalVarDescriptors::Handle(zone, bytecode.GetLocalVarDescriptors());
+ THR_Print("%s\n}\n", var_descriptors.ToCString());
+ }
+
#else
UNREACHABLE();
#endif
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 931ffa3..dc78a0e 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -142,6 +142,10 @@
}
}
+void ConstantPropagator::VisitNativeEntry(NativeEntryInstr* block) {
+ VisitFunctionEntry(block);
+}
+
void ConstantPropagator::VisitOsrEntry(OsrEntryInstr* block) {
for (auto def : *block->initial_definitions()) {
def->Accept(this);
@@ -192,6 +196,10 @@
// Nothing to do.
}
+void ConstantPropagator::VisitNativeReturn(NativeReturnInstr* instr) {
+ // Nothing to do.
+}
+
void ConstantPropagator::VisitThrow(ThrowInstr* instr) {
// Nothing to do.
}
@@ -365,6 +373,10 @@
SetValue(instr, non_constant_);
}
+void ConstantPropagator::VisitNativeParameter(NativeParameterInstr* instr) {
+ SetValue(instr, non_constant_);
+}
+
void ConstantPropagator::VisitPushArgument(PushArgumentInstr* instr) {
if (SetValue(instr, instr->value()->definition()->constant_value())) {
// The worklist implementation breaks down around push arguments,
@@ -844,9 +856,23 @@
}
void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) {
+ // This first part duplicates the work done in LoadClassIdInstr::Canonicalize,
+ // which replaces uses of LoadClassIdInstr where the object has a concrete
+ // type with a Constant. Canonicalize runs before the ConstantPropagation
+ // pass, so if that was all, this wouldn't be needed.
+ //
+ // However, the ConstantPropagator also runs as part of OptimizeBranches, and
+ // TypePropagation runs between it and the previous Canonicalize. Thus, the
+ // type may have become concrete and we should take that into account. Not
+ // doing so led to some benchmark regressions.
+ intptr_t cid = instr->object()->Type()->ToCid();
+ if (cid != kDynamicCid) {
+ SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid)));
+ return;
+ }
const Object& object = instr->object()->definition()->constant_value();
if (IsConstant(object)) {
- const intptr_t cid = object.GetClassId();
+ cid = object.GetClassId();
SetValue(instr, Smi::ZoneHandle(Z, Smi::New(cid)));
return;
}
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 7761a49..0a590a3 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -756,10 +756,12 @@
// to the kill set.
const bool is_function_entry = block->IsFunctionEntry();
const bool is_osr_entry = block->IsOsrEntry();
- if (is_function_entry || is_osr_entry || block->IsCatchBlockEntry()) {
+ const bool is_catch_block_entry = block->IsCatchBlockEntry();
+ if (is_function_entry || is_osr_entry || is_catch_block_entry) {
const intptr_t parameter_count =
- is_osr_entry ? flow_graph_->variable_count()
- : flow_graph_->num_direct_parameters();
+ (is_osr_entry || is_catch_block_entry)
+ ? flow_graph_->variable_count()
+ : flow_graph_->num_direct_parameters();
for (intptr_t i = 0; i < parameter_count; ++i) {
live_in->Remove(i);
kill->Add(i);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 73c21d8..eee9a38 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -42,6 +42,8 @@
false,
"Inlining interval diagnostics");
+DEFINE_FLAG(bool, enable_peephole, true, "Enable peephole optimization");
+
#if !defined(DART_PRECOMPILED_RUNTIME)
DEFINE_FLAG(bool,
@@ -511,6 +513,35 @@
line.ToCString());
}
+#if !defined(TARGET_ARCH_DBC)
+
+static bool IsPusher(Instruction* instr) {
+ if (auto def = instr->AsDefinition()) {
+ return def->HasTemp();
+ }
+ return false;
+}
+
+static bool IsPopper(Instruction* instr) {
+ // TODO(ajcbik): even allow deopt targets by making environment aware?
+ if (!instr->CanBecomeDeoptimizationTarget()) {
+ return !instr->IsPushArgument() && instr->ArgumentCount() == 0 &&
+ instr->InputCount() > 0;
+ }
+ return false;
+}
+
+#endif
+
+bool FlowGraphCompiler::IsPeephole(Instruction* instr) const {
+#if !defined(TARGET_ARCH_DBC)
+ if (FLAG_enable_peephole && !is_optimizing()) {
+ return IsPusher(instr) && IsPopper(instr->next());
+ }
+#endif
+ return false;
+}
+
void FlowGraphCompiler::VisitBlocks() {
CompactBlocks();
if (Assembler::EmittingComments()) {
@@ -585,7 +616,12 @@
pending_deoptimization_env_ = instr->env();
instr->EmitNativeCode(this);
pending_deoptimization_env_ = NULL;
- EmitInstructionEpilogue(instr);
+ if (IsPeephole(instr)) {
+ ASSERT(top_of_stack_ == nullptr);
+ top_of_stack_ = instr->AsDefinition();
+ } else {
+ EmitInstructionEpilogue(instr);
+ }
EndCodeSourceRange(instr->token_pos());
}
@@ -1075,22 +1111,19 @@
#if defined(PRODUCT)
// No debugger: no var descriptors.
#else
- // TODO(alexmarkov): revise local vars descriptors when compiling bytecode
- if (code.is_optimized() ||
- flow_graph().function().is_declared_in_bytecode() ||
- flow_graph().function().HasBytecode()) {
+ if (code.is_optimized()) {
// Optimized code does not need variable descriptors. They are
// only stored in the unoptimized version.
code.set_var_descriptors(Object::empty_var_descriptors());
return;
}
LocalVarDescriptors& var_descs = LocalVarDescriptors::Handle();
- if (parsed_function().node_sequence() == NULL) {
+ if (flow_graph().IsIrregexpFunction()) {
// Eager local var descriptors computation for Irregexp function as it is
// complicated to factor out.
// TODO(srdjan): Consider canonicalizing and reusing the local var
// descriptor for IrregexpFunction.
- ASSERT(flow_graph().IsIrregexpFunction());
+ ASSERT(parsed_function().node_sequence() == nullptr);
var_descs = LocalVarDescriptors::New(1);
RawLocalVarDescriptors::VarInfo info;
info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
@@ -1364,7 +1397,7 @@
: ic_data.arguments_descriptor());
ASSERT(ArgumentsDescriptor(arguments_descriptor).TypeArgsLen() ==
args_info.type_args_len);
- if (is_optimizing()) {
+ if (is_optimizing() && !ForcedOptimization()) {
EmitOptimizedStaticCall(function, arguments_descriptor,
args_info.count_with_type_args, deopt_id, token_pos,
locs, entry_kind);
@@ -1470,6 +1503,21 @@
bool blocked_registers[kNumberOfCpuRegisters];
+ // Connect input with peephole output for some special cases. All other
+ // cases are handled by simply allocating registers and generating code.
+ if (top_of_stack_ != nullptr) {
+ const intptr_t p = locs->input_count() - 1;
+ Location peephole = top_of_stack_->locs()->out(0);
+ if (locs->in(p).IsUnallocated() || locs->in(p).IsConstant()) {
+ // If input is unallocated, match with an output register, if set. Also,
+ // if input is a direct constant, but the peephole output is a register,
+ // use that register to avoid wasting the already generated code.
+ if (peephole.IsRegister()) {
+ locs->set_in(p, Location::RegisterLocation(peephole.reg()));
+ }
+ }
+ }
+
// Block all registers globally reserved by the assembler, etc and mark
// the rest as free.
for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
@@ -1518,10 +1566,17 @@
}
ASSERT(reg != kNoRegister || loc.IsConstant());
- // Inputs are consumed from the simulated frame. In case of a call argument
- // we leave it until the call instruction.
+ // Inputs are consumed from the simulated frame (or a peephole push/pop).
+ // In case of a call argument we leave it until the call instruction.
if (should_pop) {
- if (loc.IsConstant()) {
+ if (top_of_stack_ != nullptr) {
+ if (!loc.IsConstant()) {
+ // Moves top of stack location of the peephole into the required
+ // input. None of the required moves needs a temp register allocator.
+ EmitMove(locs->in(i), top_of_stack_->locs()->out(0), nullptr);
+ }
+ top_of_stack_ = nullptr; // consumed!
+ } else if (loc.IsConstant()) {
assembler()->Drop(1);
} else {
assembler()->PopRegister(reg);
@@ -2047,6 +2102,7 @@
intptr_t total_ic_calls,
Code::EntryKind entry_kind) {
ASSERT(is_optimizing());
+ ASSERT(complete || (failed != nullptr)); // Complete calls can't fail.
const Array& arguments_descriptor =
Array::ZoneHandle(zone(), args_info.ToArgumentsDescriptor());
@@ -2081,8 +2137,13 @@
if (smi_case != kNoCase) {
Label after_smi_test;
- EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
- /* jump_if_smi= */ false);
+ // If the call is complete and there are no other possible receiver
+ // classes - then receiver can only be a smi value and we don't need
+ // to check if it is a smi.
+ if (!(complete && non_smi_length == 0)) {
+ EmitTestAndCallSmiBranch(non_smi_length == 0 ? failed : &after_smi_test,
+ /* jump_if_smi= */ false);
+ }
// Do not use the code from the function, but let the code be patched so
// that we can record the outgoing edges to other code.
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 8795377..28c369b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -409,6 +409,11 @@
return block_order_;
}
+ // If 'ForcedOptimization()' returns 'true', we are compiling in optimized
+ // mode for a function which cannot deoptimize. Certain optimizations, e.g.
+ // speculative optimizations and call patching are disabled.
+ bool ForcedOptimization() const { return function().ForceOptimize(); }
+
const FlowGraph& flow_graph() const { return flow_graph_; }
BlockEntryInstr* current_block() const { return current_block_; }
@@ -1025,6 +1030,10 @@
void FrameStateClear();
#endif
+ // Returns true if instruction lookahead (window size one)
+ // is amenable to a peephole optimization.
+ bool IsPeephole(Instruction* instr) const;
+
// This struct contains either function or code, the other one being NULL.
class StaticCallsStruct : public ZoneAllocated {
public:
@@ -1089,6 +1098,11 @@
bool fully_intrinsified_ = false;
CodeStatistics* stats_;
+ // The definition whose value is supposed to be at the top of the
+ // expression stack. Used by peephole optimization (window size one)
+ // to eliminate redundant push/pop pairs.
+ Definition* top_of_stack_ = nullptr;
+
const Class& double_class_;
const Class& mint_class_;
const Class& float32x4_class_;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index d968031..598cc1c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -1309,6 +1309,8 @@
void FlowGraphCompiler::EmitMove(Location destination,
Location source,
TemporaryRegisterAllocator* allocator) {
+ if (destination.Equals(source)) return;
+
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ mov(destination.reg(), Operand(source.reg()));
@@ -1430,12 +1432,14 @@
if (TargetCPUFeatures::neon_supported()) {
const QRegister dst = destination.fpu_reg();
const QRegister src = source.fpu_reg();
+ ASSERT(dst != QTMP && src != QTMP);
__ vmovq(QTMP, src);
__ vmovq(src, dst);
__ vmovq(dst, QTMP);
} else {
const DRegister dst = EvenDRegisterOf(destination.fpu_reg());
const DRegister src = EvenDRegisterOf(source.fpu_reg());
+ ASSERT(dst != DTMP && src != DTMP);
__ vmovd(DTMP, src);
__ vmovd(src, dst);
__ vmovd(dst, DTMP);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 3eeac84..505a96a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -1160,8 +1160,8 @@
}
// Do not use the code from the function, but let the code be patched so that
// we can record the outgoing edges to other code.
- GenerateStaticDartCall(deopt_id, token_pos,
- RawPcDescriptors::kOther, locs, function);
+ GenerateStaticDartCall(deopt_id, token_pos, RawPcDescriptors::kOther, locs,
+ function);
__ Drop(count_with_type_args);
}
@@ -1297,6 +1297,8 @@
void FlowGraphCompiler::EmitMove(Location destination,
Location source,
TemporaryRegisterAllocator* allocator) {
+ if (destination.Equals(source)) return;
+
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ mov(destination.reg(), source.reg());
@@ -1309,6 +1311,10 @@
if (destination.IsRegister()) {
const intptr_t source_offset = source.ToStackSlotOffset();
__ LoadFromOffset(destination.reg(), source.base_reg(), source_offset);
+ } else if (destination.IsFpuRegister()) {
+ const intptr_t src_offset = source.ToStackSlotOffset();
+ VRegister dst = destination.fpu_reg();
+ __ LoadDFromOffset(dst, source.base_reg(), src_offset);
} else {
ASSERT(destination.IsStackSlot());
const intptr_t source_offset = source.ToStackSlotOffset();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 5cf94a8..4cea80a 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -1182,6 +1182,8 @@
void FlowGraphCompiler::EmitMove(Location destination,
Location source,
TemporaryRegisterAllocator* tmp) {
+ if (destination.Equals(source)) return;
+
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ movl(destination.reg(), source.reg());
@@ -1192,6 +1194,9 @@
} else if (source.IsStackSlot()) {
if (destination.IsRegister()) {
__ movl(destination.reg(), LocationToStackSlotAddress(source));
+ } else if (destination.IsFpuRegister()) {
+ // 32-bit float
+ __ movss(destination.fpu_reg(), LocationToStackSlotAddress(source));
} else {
ASSERT(destination.IsStackSlot());
Register scratch = tmp->AllocateTemporary();
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index c2aeb5e..170af1e 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -27,6 +27,7 @@
#include "vm/regexp_assembler_ir.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
+#include "vm/stack_frame.h"
#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/type_testing_stubs.h"
@@ -649,24 +650,75 @@
return cids;
}
-Cids* Cids::Create(Zone* zone, const ICData& ic_data, int argument_number) {
+Cids* Cids::CreateAndExpand(Zone* zone,
+ const ICData& ic_data,
+ int argument_number) {
Cids* cids = new (zone) Cids(zone);
cids->CreateHelper(zone, ic_data, argument_number,
/* include_targets = */ false);
cids->Sort(OrderById);
// Merge adjacent class id ranges.
- int dest = 0;
- for (int src = 1; src < cids->length(); src++) {
- if (cids->cid_ranges_[dest]->cid_end + 1 >=
- cids->cid_ranges_[src]->cid_start) {
- cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
- } else {
- dest++;
- if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+ {
+ int dest = 0;
+ for (int src = 1; src < cids->length(); src++) {
+ if (cids->cid_ranges_[dest]->cid_end + 1 >=
+ cids->cid_ranges_[src]->cid_start) {
+ cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+ } else {
+ dest++;
+ if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+ }
+ }
+ cids->SetLength(dest + 1);
+ }
+
+ // Merging/extending cid ranges is also done in CallTargets::CreateAndExpand.
+ // If changing this code, consider also adjusting CallTargets code.
+
+ if (cids->length() > 1 && argument_number == 0 && ic_data.HasOneTarget()) {
+ // Try harder to merge ranges if method lookups in the gaps result in the
+ // same target method.
+ const Function& target = Function::Handle(zone, ic_data.GetTargetAt(0));
+ if (!MethodRecognizer::PolymorphicTarget(target)) {
+ const auto& args_desc_array =
+ Array::Handle(zone, ic_data.arguments_descriptor());
+ ArgumentsDescriptor args_desc(args_desc_array);
+ const auto& name = String::Handle(zone, ic_data.target_name());
+ auto& fn = Function::Handle(zone);
+
+ intptr_t dest = 0;
+ for (intptr_t src = 1; src < cids->length(); src++) {
+ // Inspect all cids in the gap and see if they all resolve to the same
+ // target.
+ bool can_merge = true;
+ for (intptr_t cid = cids->cid_ranges_[dest]->cid_end + 1,
+ end = cids->cid_ranges_[src]->cid_start;
+ cid < end; ++cid) {
+ bool class_is_abstract = false;
+ if (FlowGraphCompiler::LookupMethodFor(cid, name, args_desc, &fn,
+ &class_is_abstract)) {
+ if (fn.raw() == target.raw()) {
+ continue;
+ }
+ if (class_is_abstract) {
+ continue;
+ }
+ }
+ can_merge = false;
+ break;
+ }
+
+ if (can_merge) {
+ cids->cid_ranges_[dest]->cid_end = cids->cid_ranges_[src]->cid_end;
+ } else {
+ dest++;
+ if (src != dest) cids->cid_ranges_[dest] = cids->cid_ranges_[src];
+ }
+ }
+ cids->SetLength(dest + 1);
}
}
- cids->SetLength(dest + 1);
return cids;
}
@@ -2727,6 +2779,11 @@
if (call->is_known_list_constructor() &&
IsFixedLengthArrayCid(call->Type()->ToCid())) {
return call->ArgumentAt(1);
+ } else if (call->function().recognized_kind() ==
+ MethodRecognizer::kByteDataFactory) {
+ // Similarly, we check for the ByteData constructor and forward its
+ // explicit length argument appropriately.
+ return call->ArgumentAt(1);
} else if (IsTypedDataViewFactory(call->function())) {
// Typed data view factories all take three arguments (after
// the implicit type arguments parameter):
@@ -2769,6 +2826,11 @@
if (StaticCallInstr* call = array->AsStaticCall()) {
if (IsTypedDataViewFactory(call->function())) {
return call->ArgumentAt(2);
+ } else if (call->function().recognized_kind() ==
+ MethodRecognizer::kByteDataFactory) {
+ // A _ByteDataView returned from the ByteData constructor always
+ // has an offset of 0.
+ return flow_graph->GetConstant(Smi::Handle(Smi::New(0)));
}
}
} else if (slot().IsTypeArguments()) {
@@ -2776,10 +2838,16 @@
if (StaticCallInstr* call = array->AsStaticCall()) {
if (call->is_known_list_constructor()) {
return call->ArgumentAt(0);
- } else if (call->function().recognized_kind() ==
- MethodRecognizer::kLinkedHashMap_getData) {
+ } else if (IsTypedDataViewFactory(call->function())) {
return flow_graph->constant_null();
}
+ switch (call->function().recognized_kind()) {
+ case MethodRecognizer::kByteDataFactory:
+ case MethodRecognizer::kLinkedHashMap_getData:
+ return flow_graph->constant_null();
+ default:
+ break;
+ }
} else if (CreateArrayInstr* create_array = array->AsCreateArray()) {
return create_array->element_type()->definition();
} else if (LoadFieldInstr* load_array = array->AsLoadField()) {
@@ -3522,6 +3590,11 @@
if (call->is_known_list_constructor() &&
LoadFieldInstr::IsFixedLengthArrayCid(call->Type()->ToCid())) {
length = call->ArgumentAt(1)->AsConstant();
+ } else if (call->function().recognized_kind() ==
+ MethodRecognizer::kByteDataFactory) {
+ length = call->ArgumentAt(1)->AsConstant();
+ } else if (LoadFieldInstr::IsTypedDataViewFactory(call->function())) {
+ length = call->ArgumentAt(3)->AsConstant();
}
if ((length != NULL) && length->value().IsSmi() &&
Smi::Cast(length->value()).Value() == expected_length) {
@@ -3651,6 +3724,9 @@
intptr_t length = targets.length();
+ // Merging/extending cid ranges is also done in Cids::CreateAndExpand.
+ // If changing this code, consider also adjusting Cids code.
+
// Spread class-ids to preceding classes where a lookup yields the same
// method. A polymorphic target is not really the same method since its
// behaviour depends on the receiver class-id, so we don't spread the
@@ -3825,7 +3901,9 @@
__ nop();
}
#endif
- __ Bind(compiler->GetJumpLabel(this));
+ if (tag() == Instruction::kFunctionEntry) {
+ __ Bind(compiler->GetJumpLabel(this));
+ }
// In the AOT compiler we want to reduce code size, so generate no
// fall-through code in [FlowGraphCompiler::CompileGraph()].
@@ -3877,6 +3955,11 @@
}
}
+LocationSummary* NativeEntryInstr::MakeLocationSummary(Zone* zone,
+ bool optimizing) const {
+ UNREACHABLE();
+}
+
LocationSummary* OsrEntryInstr::MakeLocationSummary(Zone* zone,
bool optimizing) const {
UNREACHABLE();
@@ -3982,6 +4065,43 @@
UNREACHABLE();
}
+void NativeParameterInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+#if !defined(TARGET_ARCH_DBC)
+ // The native entry frame has size -kExitLinkSlotFromFp. In order to access
+ // the top of stack from above the entry frame, we add a constant to account
+ // for the the two frame pointers and two return addresses of the entry frame.
+ constexpr intptr_t kEntryFramePadding = 4;
+ FrameRebase rebase(/*old_base=*/SPREG, /*new_base=*/FPREG,
+ -kExitLinkSlotFromEntryFp + kEntryFramePadding);
+ const Location dst = locs()->out(0);
+ const Location src = rebase.Rebase(loc_);
+ NoTemporaryAllocator no_temp;
+ compiler->EmitMove(dst, src, &no_temp);
+#else
+ UNREACHABLE();
+#endif
+}
+
+LocationSummary* NativeParameterInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+#if !defined(TARGET_ARCH_DBC)
+ ASSERT(opt);
+ Location input = Location::Any();
+ if (representation() == kUnboxedInt64 && compiler::target::kWordSize < 8) {
+ input = Location::Pair(Location::RequiresRegister(),
+ Location::RequiresFpuRegister());
+ } else {
+ input = RegisterKindForResult() == Location::kRegister
+ ? Location::RequiresRegister()
+ : Location::RequiresFpuRegister();
+ }
+ return LocationSummary::Make(zone, /*num_inputs=*/0, input,
+ LocationSummary::kNoCall);
+#else
+ UNREACHABLE();
+#endif
+}
+
bool ParallelMoveInstr::IsRedundant() const {
for (intptr_t i = 0; i < moves_.length(); i++) {
if (!moves_[i]->IsRedundant()) {
@@ -5370,6 +5490,16 @@
}
}
+LocationSummary* NativeReturnInstr::MakeLocationSummary(Zone* zone,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* locs = new (zone)
+ LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ locs->set_in(0, result_location_);
+ return locs;
+}
+
#undef Z
#else
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3e91b50..012ebad 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -336,18 +336,21 @@
M(JoinEntry, kNoGC) \
M(TargetEntry, kNoGC) \
M(FunctionEntry, kNoGC) \
+ M(NativeEntry, kNoGC) \
M(OsrEntry, kNoGC) \
M(IndirectEntry, kNoGC) \
M(CatchBlockEntry, kNoGC) \
M(Phi, kNoGC) \
M(Redefinition, kNoGC) \
M(Parameter, kNoGC) \
+ M(NativeParameter, kNoGC) \
M(LoadIndexedUnsafe, kNoGC) \
M(StoreIndexedUnsafe, kNoGC) \
M(TailCall, kNoGC) \
M(ParallelMove, kNoGC) \
M(PushArgument, kNoGC) \
M(Return, kNoGC) \
+ M(NativeReturn, kNoGC) \
M(Throw, kNoGC) \
M(ReThrow, kNoGC) \
M(Stop, _) \
@@ -555,7 +558,11 @@
explicit Cids(Zone* zone) : zone_(zone) {}
// Creates the off-heap Cids object that reflects the contents
// of the on-VM-heap IC data.
- static Cids* Create(Zone* zone, const ICData& ic_data, int argument_number);
+ // Ranges of Cids are merged if there is only one target function and
+ // it is used for all cids in the gaps between ranges.
+ static Cids* CreateAndExpand(Zone* zone,
+ const ICData& ic_data,
+ int argument_number);
static Cids* CreateMonomorphic(Zone* zone, intptr_t cid);
bool Equals(const Cids& other) const;
@@ -916,6 +923,28 @@
virtual bool UseSharedSlowPathStub(bool is_optimizing) const { return false; }
+ // 'RegisterKindForResult()' returns the register kind necessary to hold the
+ // result.
+ //
+ // This is not virtual because instructions should override representation()
+ // instead.
+ Location::Kind RegisterKindForResult() const {
+ const Representation rep = representation();
+#if !defined(TARGET_ARCH_DBC)
+ if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
+ (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
+ (rep == kUnboxedFloat64x2)) {
+ return Location::kFpuRegister;
+ }
+#else
+ // DBC supports only unboxed doubles and does not have distinguished FPU
+ // registers.
+ ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
+ (rep != kUnboxedFloat64x2));
+#endif
+ return Location::kRegister;
+ }
+
protected:
// GetDeoptId and/or CopyDeoptIdFrom.
friend class CallSiteInliner;
@@ -1614,6 +1643,33 @@
DISALLOW_COPY_AND_ASSIGN(FunctionEntryInstr);
};
+// Represents entry into a function from native code.
+//
+// Native entries are not allowed to have regular parameters. They should use
+// NativeParameter instead (which doesn't count as an initial definition).
+class NativeEntryInstr : public FunctionEntryInstr {
+ public:
+ NativeEntryInstr(const ZoneGrowableArray<Location>* argument_locations,
+ GraphEntryInstr* graph_entry,
+ intptr_t block_id,
+ intptr_t try_index,
+ intptr_t deopt_id,
+ intptr_t callback_id)
+ : FunctionEntryInstr(graph_entry, block_id, try_index, deopt_id),
+ callback_id_(callback_id),
+ argument_locations_(argument_locations) {}
+
+ DECLARE_INSTRUCTION(NativeEntry)
+
+ PRINT_TO_SUPPORT
+
+ private:
+ void SaveArgument(FlowGraphCompiler* compiler, Location loc) const;
+
+ const intptr_t callback_id_;
+ const ZoneGrowableArray<Location>* const argument_locations_;
+};
+
// Represents an OSR entrypoint to a function.
//
// The OSR entry has it's own initial definitions.
@@ -2193,6 +2249,57 @@
DISALLOW_COPY_AND_ASSIGN(ParameterInstr);
};
+// Native parameters are not treated as initial definitions because they cannot
+// be inlined and are only usable in optimized code. The location must be a
+// stack location relative to the position of the stack (SPREG) after
+// register-based arguments have been saved on entry to a native call. See
+// NativeEntryInstr::EmitNativeCode for more details.
+//
+// TOOD(33549): Unify with ParameterInstr.
+class NativeParameterInstr : public Definition {
+ public:
+ NativeParameterInstr(Location loc, Representation representation)
+ : loc_(loc), representation_(representation) {
+ if (loc.IsPairLocation()) {
+ for (intptr_t i : {0, 1}) {
+ ASSERT(loc_.Component(i).HasStackIndex() &&
+ loc_.Component(i).base_reg() == SPREG);
+ }
+ } else {
+ ASSERT(loc_.HasStackIndex() && loc_.base_reg() == SPREG);
+ }
+ }
+
+ DECLARE_INSTRUCTION(NativeParameter)
+
+ virtual Representation representation() const { return representation_; }
+
+ intptr_t InputCount() const { return 0; }
+ Value* InputAt(intptr_t i) const {
+ UNREACHABLE();
+ return NULL;
+ }
+
+ virtual bool ComputeCanDeoptimize() const { return false; }
+
+ virtual bool HasUnknownSideEffects() const { return false; }
+
+ // TODO(sjindel): We can make this more precise.
+ virtual CompileType ComputeType() const { return CompileType::Dynamic(); }
+
+ virtual bool MayThrow() const { return false; }
+
+ PRINT_OPERANDS_TO_SUPPORT
+
+ private:
+ virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
+
+ const Location loc_;
+ const Representation representation_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeParameterInstr);
+};
+
// Stores a tagged pointer to a slot accessible from a fixed register. It has
// the form:
//
@@ -2256,8 +2363,11 @@
// the frame. This is asserted via `inliner.cc::CalleeGraphValidator`.
class LoadIndexedUnsafeInstr : public TemplateDefinition<1, NoThrow> {
public:
- LoadIndexedUnsafeInstr(Value* index, intptr_t offset, CompileType result_type)
- : offset_(offset) {
+ LoadIndexedUnsafeInstr(Value* index,
+ intptr_t offset,
+ CompileType result_type,
+ Representation representation = kTagged)
+ : offset_(offset), representation_(representation) {
UpdateType(result_type);
SetInputAt(0, index);
}
@@ -2268,7 +2378,6 @@
ASSERT(index == 0);
return kTagged;
}
- virtual Representation representation() const { return kTagged; }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool HasUnknownSideEffects() const { return false; }
@@ -2284,6 +2393,7 @@
private:
const intptr_t offset_;
+ const Representation representation_;
DISALLOW_COPY_AND_ASSIGN(LoadIndexedUnsafeInstr);
};
@@ -2393,6 +2503,40 @@
DISALLOW_COPY_AND_ASSIGN(ReturnInstr);
};
+// Represents a return from a Dart function into native code.
+class NativeReturnInstr : public ReturnInstr {
+ public:
+ NativeReturnInstr(TokenPosition token_pos,
+ Value* value,
+ Representation rep,
+ Location result_location,
+ intptr_t deopt_id)
+ : ReturnInstr(token_pos, value, deopt_id),
+ result_representation_(rep),
+ result_location_(result_location) {}
+
+ DECLARE_INSTRUCTION(NativeReturn)
+
+ PRINT_OPERANDS_TO_SUPPORT
+
+ virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+ ASSERT(idx == 0);
+ return result_representation_;
+ }
+
+ virtual bool CanBecomeDeoptimizationTarget() const {
+ // Unlike ReturnInstr, NativeReturnInstr cannot be inlined (because it's
+ // returning into native code).
+ return false;
+ }
+
+ private:
+ const Representation result_representation_;
+ const Location result_location_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeReturnInstr);
+};
+
class ThrowInstr : public TemplateInstruction<0, Throws> {
public:
explicit ThrowInstr(TokenPosition token_pos, intptr_t deopt_id)
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index cf86087..e833159 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1023,7 +1023,8 @@
RawPcDescriptors::Kind::kOther, locs());
// Update information in the thread object and enter a safepoint.
- __ TransitionGeneratedToNative(branch, saved_fp, locs()->temp(1).reg());
+ __ TransitionGeneratedToNative(branch, FPREG, saved_fp,
+ locs()->temp(1).reg());
__ blx(branch);
@@ -1044,6 +1045,174 @@
__ PopRegister(TMP);
}
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ LeaveDartFrame();
+
+ // The dummy return address is in LR, no need to pop it as on Intel.
+
+ // These can be anything besides the return registers (R0 and R1) and THR
+ // (R10).
+ const Register vm_tag_reg = R2, old_exit_frame_reg = R3, tmp = R4, tmp1 = R5;
+
+ __ Pop(old_exit_frame_reg);
+
+ // Restore top_resource.
+ __ Pop(tmp);
+ __ StoreToOffset(kWord, tmp, THR,
+ compiler::target::Thread::top_resource_offset());
+
+ __ Pop(vm_tag_reg);
+
+ // Reset the exit frame info to
+ // old_exit_frame_reg *before* entering the safepoint.
+ __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp, tmp1);
+
+ __ PopNativeCalleeSavedRegisters();
+
+ // Leave the entry frame.
+ __ LeaveFrame(1 << LR | 1 << FP);
+
+ // Leave the dummy frame holding the pushed arguments.
+ __ LeaveFrame(1 << LR | 1 << FP);
+
+ __ Ret();
+
+ // For following blocks.
+ __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+ Location loc) const {
+ if (loc.IsPairLocation()) {
+ // Save higher-order component first, so bytes are in little-endian layout
+ // overall.
+ for (intptr_t i : {1, 0}) {
+ SaveArgument(compiler, loc.Component(i));
+ }
+ return;
+ }
+
+ if (loc.HasStackIndex()) return;
+
+ if (loc.IsRegister()) {
+ __ Push(loc.reg());
+ } else if (loc.IsFpuRegister()) {
+ const DRegister src = EvenDRegisterOf(loc.fpu_reg());
+ __ SubImmediateSetFlags(SPREG, SPREG, 8, AL);
+ __ StoreDToOffset(src, SPREG, 0);
+ } else {
+ UNREACHABLE();
+ }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (FLAG_precompiled_mode) {
+ UNREACHABLE();
+ }
+
+ // Constant pool cannot be used until we enter the actual Dart frame.
+ __ set_constant_pool_allowed(false);
+
+ __ Bind(compiler->GetJumpLabel(this));
+
+ // Create a dummy frame holding the pushed arguments. This simplifies
+ // NativeReturnInstr::EmitNativeCode.
+ __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+ // Save the argument registers, in reverse order.
+ for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+ SaveArgument(compiler, argument_locations_->At(i));
+ }
+
+ // Enter the entry frame.
+ __ EnterFrame((1 << FP) | (1 << LR), 0);
+
+ // Save a space for the code object.
+ __ PushImmediate(0);
+
+ __ PushNativeCalleeSavedRegisters();
+
+ // Load the thread object.
+ // TODO(35765): Fix linking issue on AOT.
+ // TOOD(35934): Exclude native callbacks from snapshots.
+ //
+ // Create another frame to align the frame before continuing in "native" code.
+ {
+ __ EnterFrame(1 << FP, 0);
+ __ ReserveAlignedFrameSpace(0);
+
+ __ LoadImmediate(
+ R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+ __ blx(R0);
+ __ mov(THR, Operand(R0));
+
+ __ LeaveFrame(1 << FP);
+ }
+
+ // Save the current VMTag on the stack.
+ __ LoadFromOffset(kWord, R0, THR, compiler::target::Thread::vm_tag_offset());
+ __ Push(R0);
+
+ // Save top resource.
+ const intptr_t top_resource_offset =
+ compiler::target::Thread::top_resource_offset();
+ __ LoadFromOffset(kWord, R0, THR, top_resource_offset);
+ __ Push(R0);
+ __ LoadImmediate(R0, 0);
+ __ StoreToOffset(kWord, R0, THR, top_resource_offset);
+
+ // Save top exit frame info. Don't set it to 0 yet --
+ // TransitionNativeToGenerated will handle that *after* leaving the safepoint.
+ __ LoadFromOffset(kWord, R0, THR,
+ compiler::target::Thread::top_exit_frame_info_offset());
+ __ Push(R0);
+
+ __ EmitEntryFrameVerification(R0);
+
+ __ TransitionNativeToGenerated(/*scratch0=*/R0, /*scratch1=*/R1);
+
+ // Now that the safepoint has ended, we can touch Dart objects without
+ // handles.
+
+ // Otherwise we'll clobber the argument sent from the caller.
+ ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+ CallingConventions::ArgumentRegisters[0] != TMP2 &&
+ CallingConventions::ArgumentRegisters[0] != R1);
+ __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+ __ LoadFromOffset(
+ kWord, R1, THR,
+ compiler::target::Thread::verify_callback_isolate_entry_point_offset());
+ __ blx(R1);
+
+ // Load the code object.
+ __ LoadFromOffset(kWord, R0, THR,
+ compiler::target::Thread::callback_code_offset());
+ __ LoadFieldFromOffset(kWord, R0, R0,
+ compiler::target::GrowableObjectArray::data_offset());
+ __ LoadFieldFromOffset(kWord, CODE_REG, R0,
+ compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kWordSize);
+
+ // Put the code object in the reserved slot.
+ __ StoreToOffset(kWord, CODE_REG, FPREG,
+ kPcMarkerSlotFromFp * compiler::target::kWordSize);
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ ldr(PP,
+ Address(THR, compiler::target::Thread::global_object_pool_offset()));
+ } else {
+ __ LoadImmediate(PP, 0); // GC safe value into PP.
+ }
+
+ // Load a dummy return address which suggests that we are inside of
+ // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+ __ LoadFromOffset(kWord, LR, THR,
+ compiler::target::Thread::invoke_dart_code_stub_offset());
+ __ LoadFieldFromOffset(kWord, LR, LR,
+ compiler::target::Code::entry_point_offset());
+
+ FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
@@ -1295,10 +1464,10 @@
(representation() == kUnboxedInt32x4) ||
(representation() == kUnboxedFloat64x2)) {
if (class_id() == kTypedDataFloat32ArrayCid) {
- // Need register <= Q7 for float operations.
+ // Need register < Q7 for float operations.
// TODO(fschneider): Add a register policy to specify a subset of
// registers.
- locs->set_out(0, Location::FpuRegisterLocation(Q7));
+ locs->set_out(0, Location::FpuRegisterLocation(Q6));
} else {
locs->set_out(0, Location::RequiresFpuRegister());
}
@@ -1599,8 +1768,8 @@
Location::RequiresRegister()));
break;
case kTypedDataFloat32ArrayCid:
- // Need low register (<= Q7).
- locs->set_in(2, Location::FpuRegisterLocation(Q7));
+ // Need low register (< Q7).
+ locs->set_in(2, Location::FpuRegisterLocation(Q6));
break;
case kTypedDataFloat64ArrayCid: // TODO(srdjan): Support Float64 constants.
case kTypedDataInt32x4ArrayCid:
@@ -5396,9 +5565,9 @@
const intptr_t kNumTemps = 0;
LocationSummary* result = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- // Low (<= Q7) Q registers are needed for the conversion instructions.
+ // Low (< Q7) Q registers are needed for the conversion instructions.
result->set_in(0, Location::RequiresFpuRegister());
- result->set_out(0, Location::FpuRegisterLocation(Q7));
+ result->set_out(0, Location::FpuRegisterLocation(Q6));
return result;
}
@@ -5415,8 +5584,8 @@
const intptr_t kNumTemps = 0;
LocationSummary* result = new (zone)
LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- // Low (<= Q7) Q registers are needed for the conversion instructions.
- result->set_in(0, Location::FpuRegisterLocation(Q7));
+ // Low (< Q7) Q registers are needed for the conversion instructions.
+ result->set_in(0, Location::FpuRegisterLocation(Q6));
result->set_out(0, Location::RequiresFpuRegister());
return result;
}
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 1bf08fc..15ae1de 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -916,7 +916,7 @@
__ mov(CSP, SP);
// Update information in the thread object and enter a safepoint.
- __ TransitionGeneratedToNative(branch, temp);
+ __ TransitionGeneratedToNative(branch, FPREG, temp);
__ blr(branch);
@@ -944,6 +944,177 @@
__ set_constant_pool_allowed(true);
}
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ LeaveDartFrame();
+
+ // The dummy return address is in LR, no need to pop it as on Intel.
+
+ // These can be anything besides the return register (R0) and THR (R26).
+ const Register vm_tag_reg = R1, old_exit_frame_reg = R2, tmp = R3;
+
+ __ Pop(old_exit_frame_reg);
+
+ // Restore top_resource.
+ __ Pop(tmp);
+ __ StoreToOffset(tmp, THR, compiler::target::Thread::top_resource_offset());
+
+ __ Pop(vm_tag_reg);
+
+ // Reset the exit frame info to
+ // old_exit_frame_reg *before* entering the safepoint.
+ __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+ __ PopNativeCalleeSavedRegisters();
+
+ // Leave the entry frame.
+ __ LeaveFrame();
+
+ // Leave the dummy frame holding the pushed arguments.
+ __ LeaveFrame();
+
+ // Restore the actual stack pointer from SPREG.
+ __ RestoreCSP();
+
+ __ Ret();
+
+ // For following blocks.
+ __ set_constant_pool_allowed(true);
+}
+
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+ Location loc) const {
+ ASSERT(!loc.IsPairLocation());
+
+ if (loc.HasStackIndex()) return;
+
+ if (loc.IsRegister()) {
+ __ Push(loc.reg());
+ } else if (loc.IsFpuRegister()) {
+ __ PushDouble(loc.fpu_reg());
+ } else {
+ UNREACHABLE();
+ }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (FLAG_precompiled_mode) {
+ UNREACHABLE();
+ }
+
+ // Constant pool cannot be used until we enter the actual Dart frame.
+ __ set_constant_pool_allowed(false);
+
+ __ Bind(compiler->GetJumpLabel(this));
+
+ // We don't use the regular stack pointer in ARM64, so we have to copy the
+ // native stack pointer into the Dart stack pointer.
+ __ SetupDartSP();
+
+ // Create a dummy frame holding the pushed arguments. This simplifies
+ // NativeReturnInstr::EmitNativeCode.
+ __ EnterFrame(0);
+
+ // Save the argument registers, in reverse order.
+ for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+ SaveArgument(compiler, argument_locations_->At(i));
+ }
+
+ // Enter the entry frame.
+ __ EnterFrame(0);
+
+ // Save a space for the code object.
+ __ PushImmediate(0);
+
+ __ PushNativeCalleeSavedRegisters();
+
+ // Load the thread object.
+ // TODO(35765): Fix linking issue on AOT.
+ // TOOD(35934): Exclude native callbacks from snapshots.
+ //
+ // Create another frame to align the frame before continuing in "native" code.
+ {
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+
+ __ LoadImmediate(
+ R0, reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback));
+ __ blr(R0);
+ __ mov(THR, R0);
+
+ __ LeaveFrame();
+ }
+
+ // Refresh write barrier mask.
+ __ ldr(BARRIER_MASK,
+ Address(THR, compiler::target::Thread::write_barrier_mask_offset()));
+
+ // Save the current VMTag on the stack.
+ __ LoadFromOffset(R0, THR, compiler::target::Thread::vm_tag_offset());
+ __ Push(R0);
+
+ // Save the top resource.
+ __ LoadFromOffset(R0, THR, compiler::target::Thread::top_resource_offset());
+ __ Push(R0);
+ __ StoreToOffset(ZR, THR, compiler::target::Thread::top_resource_offset());
+
+ // Save the top exit frame info. We don't set it to 0 yet in Thread because we
+ // need to leave the safepoint first.
+ __ LoadFromOffset(R0, THR,
+ compiler::target::Thread::top_exit_frame_info_offset());
+ __ Push(R0);
+
+ // In debug mode, verify that we've pushed the top exit frame info at the
+ // correct offset from FP.
+ __ EmitEntryFrameVerification();
+
+ // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+ // leaving the safepoint.
+ __ TransitionNativeToGenerated(R0);
+
+ // Now that the safepoint has ended, we can touch Dart objects without
+ // handles.
+
+ // Otherwise we'll clobber the argument sent from the caller.
+ ASSERT(CallingConventions::ArgumentRegisters[0] != TMP &&
+ CallingConventions::ArgumentRegisters[0] != TMP2 &&
+ CallingConventions::ArgumentRegisters[0] != R1);
+ __ LoadImmediate(CallingConventions::ArgumentRegisters[0], callback_id_);
+ __ LoadFromOffset(
+ R1, THR,
+ compiler::target::Thread::verify_callback_isolate_entry_point_offset());
+ __ blr(R1);
+
+ // Load the code object.
+ __ LoadFromOffset(R0, THR, compiler::target::Thread::callback_code_offset());
+ __ LoadFieldFromOffset(R0, R0,
+ compiler::target::GrowableObjectArray::data_offset());
+ __ LoadFieldFromOffset(CODE_REG, R0,
+ compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kWordSize);
+
+ // Put the code object in the reserved slot.
+ __ StoreToOffset(CODE_REG, FPREG,
+ kPcMarkerSlotFromFp * compiler::target::kWordSize);
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ ldr(PP,
+ Address(THR, compiler::target::Thread::global_object_pool_offset()));
+ __ sub(PP, PP, Operand(kHeapObjectTag)); // Pool in PP is untagged!
+ } else {
+ // We now load the pool pointer (PP) with a GC safe value as we are about to
+ // invoke dart code. We don't need a real object pool here.
+ // Smi zero does not work because ARM64 assumes PP to be untagged.
+ __ LoadObject(PP, compiler::NullObject());
+ }
+
+ // Load a dummy return address which suggests that we are inside of
+ // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+ __ LoadFromOffset(LR, THR,
+ compiler::target::Thread::invoke_dart_code_stub_offset());
+ __ LoadFieldFromOffset(LR, LR, compiler::target::Code::entry_point_offset());
+
+ FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
LocationSummary* OneByteStringFromCharCodeInstr::MakeLocationSummary(
Zone* zone,
bool opt) const {
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index dad840e..c869600 100644
--- a/runtime/vm/compiler/backend/il_dbc.cc
+++ b/runtime/vm/compiler/backend/il_dbc.cc
@@ -64,7 +64,8 @@
M(UnaryInt64Op) \
M(CheckedSmiOp) \
M(CheckedSmiComparison) \
- M(SimdOp)
+ M(SimdOp) \
+ M(NativeReturn)
// Location summaries actually are not used by the unoptimizing DBC compiler
// because we don't allocate any registers.
@@ -1002,6 +1003,10 @@
const intptr_t sigdesc_kidx = __ AddConstant(signature_descriptor);
__ FfiCall(sigdesc_kidx);
+ compiler->AddCurrentDescriptor(RawPcDescriptors::kOther, deopt_id(),
+ token_pos());
+ compiler->RecordAfterCallHelper(token_pos(), deopt_id(), 0,
+ FlowGraphCompiler::kHasResult, locs());
}
EMIT_NATIVE_CODE(NativeCall,
@@ -1392,18 +1397,23 @@
case kTypedDataUint8ClampedArrayCid:
case kExternalTypedDataUint8ArrayCid:
case kExternalTypedDataUint8ClampedArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint16ArrayCid:
+
case kOneByteStringCid:
case kTwoByteStringCid:
case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
return CompileType::FromCid(kSmiCid);
case kTypedDataInt32ArrayCid:
case kTypedDataUint32ArrayCid:
return CompileType::Int();
+ // These are unsupported on DBC and will cause a bailout during
+ // EmitNativeCode.
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kExternalTwoByteStringCid:
+ return CompileType::FromCid(kSmiCid);
+
default:
UNREACHABLE();
return CompileType::Dynamic();
@@ -1414,18 +1424,16 @@
switch (class_id_) {
case kArrayCid:
case kImmutableArrayCid:
+ return kTagged;
+ case kOneByteStringCid:
+ case kTwoByteStringCid:
case kTypedDataInt8ArrayCid:
case kTypedDataUint8ArrayCid:
case kTypedDataUint8ClampedArrayCid:
+ case kExternalOneByteStringCid:
case kExternalTypedDataUint8ArrayCid:
case kExternalTypedDataUint8ClampedArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint16ArrayCid:
- case kOneByteStringCid:
- case kTwoByteStringCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
- return kTagged;
+ return kUnboxedIntPtr;
case kTypedDataInt32ArrayCid:
return kUnboxedInt32;
case kTypedDataUint32ArrayCid:
@@ -1439,6 +1447,14 @@
return kUnboxedFloat32x4;
case kTypedDataFloat64x2ArrayCid:
return kUnboxedFloat64x2;
+
+ // These are unsupported on DBC and will cause a bailout during
+ // EmitNativeCode.
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ case kExternalTwoByteStringCid:
+ return kUnboxedIntPtr;
+
default:
UNREACHABLE();
return kTagged;
@@ -1457,18 +1473,13 @@
ASSERT(idx == 2);
switch (class_id_) {
case kArrayCid:
+ return kTagged;
case kOneByteStringCid:
- case kTwoByteStringCid:
- case kExternalOneByteStringCid:
- case kExternalTwoByteStringCid:
case kTypedDataInt8ArrayCid:
case kTypedDataUint8ArrayCid:
+ case kExternalOneByteStringCid:
case kExternalTypedDataUint8ArrayCid:
- case kTypedDataUint8ClampedArrayCid:
- case kExternalTypedDataUint8ClampedArrayCid:
- case kTypedDataInt16ArrayCid:
- case kTypedDataUint16ArrayCid:
- return kTagged;
+ return kUnboxedIntPtr;
case kTypedDataInt32ArrayCid:
return kUnboxedInt32;
case kTypedDataUint32ArrayCid:
@@ -1482,6 +1493,14 @@
return kUnboxedInt32x4;
case kTypedDataFloat64x2ArrayCid:
return kUnboxedFloat64x2;
+
+ // These are unsupported on DBC and will cause a bailout during
+ // EmitNativeCode.
+ case kTypedDataUint8ClampedArrayCid:
+ case kExternalTypedDataUint8ClampedArrayCid:
+ case kTypedDataInt16ArrayCid:
+ case kTypedDataUint16ArrayCid:
+ return kUnboxedIntPtr;
default:
UNREACHABLE();
return kTagged;
@@ -2150,6 +2169,10 @@
(licm_hoisted_ ? ICData::kHoisted : 0));
}
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ UNREACHABLE();
+}
+
} // namespace dart
#endif // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 403ca00..f71bb81 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -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.
+#include "platform/globals.h"
#include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
#if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
@@ -134,6 +135,65 @@
__ ret();
}
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ bool return_in_st0 = false;
+ if (result_representation_ == kUnboxedFloat ||
+ result_representation_ == kUnboxedDouble) {
+ ASSERT(locs()->in(0).IsFpuRegister() && locs()->in(0).fpu_reg() == XMM0);
+ return_in_st0 = true;
+ }
+
+ // Leave Dart frame.
+ __ LeaveFrame();
+
+ // EDI is the only sane choice for a temporary register here because:
+ //
+ // EDX is used for large return values.
+ // ESI == THR.
+ // Could be EBX or ECX, but that would make code below confusing.
+ const Register tmp = EDI;
+
+ // Pop dummy return address.
+ __ popl(tmp);
+
+ // Anything besides the return register(s!). Callee-saved registers will be
+ // restored later.
+ const Register vm_tag_reg = EBX, old_exit_frame_reg = ECX;
+
+ __ popl(old_exit_frame_reg);
+
+ // Restore top_resource.
+ __ popl(tmp);
+ __ movl(Address(THR, compiler::target::Thread::top_resource_offset()), tmp);
+
+ __ popl(vm_tag_reg);
+
+ // This will reset the exit frame info to old_exit_frame_reg *before* entering
+ // the safepoint.
+ __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg, tmp);
+
+ // Move XMM0 into ST0 if needed.
+ if (return_in_st0) {
+ if (result_representation_ == kUnboxedDouble) {
+ __ movsd(Address(SPREG, -8), XMM0);
+ __ fldl(Address(SPREG, -8));
+ } else {
+ __ movss(Address(SPREG, -4), XMM0);
+ __ flds(Address(SPREG, -4));
+ }
+ }
+
+ // Restore C++ ABI callee-saved registers.
+ __ popl(EDI);
+ __ popl(ESI);
+ __ popl(EBX);
+
+ // Leave the entry frame.
+ __ LeaveFrame();
+
+ __ ret();
+}
+
LocationSummary* LoadLocalInstr::MakeLocationSummary(Zone* zone,
bool opt) const {
const intptr_t kNumInputs = 0;
@@ -886,32 +946,22 @@
__ popl(tmp);
__ movl(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), tmp);
- __ TransitionGeneratedToNative(branch, tmp);
+ __ TransitionGeneratedToNative(branch, FPREG, tmp);
__ call(branch);
// The x86 calling convention requires floating point values to be returned on
// the "floating-point stack" (aka. register ST0). We don't use the
// floating-point stack in Dart, so we need to move the return value back into
// an XMM register.
- if (representation() == kUnboxedDouble || representation() == kUnboxedFloat) {
- __ subl(SPREG, Immediate(8));
- __ fstpl(Address(SPREG, 0));
- __ TransitionNativeToGenerated(tmp);
- __ fldl(Address(SPREG, 0));
- __ addl(SPREG, Immediate(8));
- } else {
- __ TransitionNativeToGenerated(tmp);
+ if (representation() == kUnboxedDouble) {
+ __ fstpl(Address(SPREG, -kDoubleSize));
+ __ movsd(XMM0, Address(SPREG, -kDoubleSize));
+ } else if (representation() == kUnboxedFloat) {
+ __ fstps(Address(SPREG, -kFloatSize));
+ __ movss(XMM0, Address(SPREG, -kFloatSize));
}
- if (representation() == kUnboxedDouble) {
- __ subl(SPREG, Immediate(8));
- __ fstpl(Address(SPREG, 0));
- __ movsd(XMM0, Address(SPREG, 0));
- } else if (representation() == kUnboxedFloat) {
- __ subl(SPREG, Immediate(4));
- __ fstps(Address(SPREG, 0));
- __ movss(XMM0, Address(SPREG, 0));
- }
+ __ TransitionNativeToGenerated(tmp);
// Leave dummy exit frame.
__ LeaveFrame();
@@ -920,6 +970,113 @@
__ popl(tmp);
}
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+ Location loc) const {
+ if (loc.IsPairLocation()) {
+ // Save the components in reverse order so that they will be in
+ // little-endian order on the stack.
+ for (intptr_t i : {1, 0}) {
+ SaveArgument(compiler, loc.Component(i));
+ }
+ return;
+ }
+
+ if (loc.HasStackIndex()) return;
+
+ if (loc.IsRegister()) {
+ __ pushl(loc.reg());
+ } else if (loc.IsFpuRegister()) {
+ __ subl(SPREG, Immediate(8));
+ __ movsd(Address(SPREG, 0), loc.fpu_reg());
+ } else {
+ UNREACHABLE();
+ }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Bind(compiler->GetJumpLabel(this));
+
+ // Enter the entry frame.
+ __ EnterFrame(0);
+
+ // Save a space for the code object.
+ __ xorl(EAX, EAX);
+ __ pushl(EAX);
+
+ // Save ABI callee-saved registers.
+ __ pushl(EBX);
+ __ pushl(ESI);
+ __ pushl(EDI);
+
+ // Load the thread object.
+ // TOOD(35934): Exclude native callbacks from snapshots.
+ // Linking in AOT is not relevant here since we don't support AOT for IA32.
+ // Create another frame to align the frame before continuing in "native" code.
+ {
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+
+ __ movl(
+ EAX,
+ Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+ __ call(EAX);
+ __ movl(THR, EAX);
+
+ __ LeaveFrame();
+ }
+
+ // Save the current VMTag on the stack.
+ __ movl(ECX, Assembler::VMTagAddress());
+ __ pushl(ECX);
+
+ // Save top resource.
+ __ pushl(Address(THR, compiler::target::Thread::top_resource_offset()));
+ __ movl(Address(THR, compiler::target::Thread::top_resource_offset()),
+ Immediate(0));
+
+ // Save top exit frame info. Stack walker expects it to be here.
+ __ pushl(
+ Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+ // In debug mode, verify that we've pushed the top exit frame info at the
+ // correct offset from FP.
+ __ EmitEntryFrameVerification();
+
+ // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+ // leaving the safepoint.
+ __ TransitionNativeToGenerated(EAX);
+
+ // Now that the safepoint has ended, we can hold Dart objects with bare hands.
+ // TODO(35934): fix linking issue
+ __ pushl(Immediate(callback_id_));
+ __ movl(EAX, Address(THR, compiler::target::Thread::
+ verify_callback_isolate_entry_point_offset()));
+ __ call(EAX);
+ __ popl(EAX);
+
+ // Load the code object.
+ __ movl(EAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+ __ movl(EAX, FieldAddress(
+ EAX, compiler::target::GrowableObjectArray::data_offset()));
+ __ movl(CODE_REG,
+ FieldAddress(EAX, compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kWordSize));
+
+ // Put the code object in the reserved slot.
+ __ movl(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+ CODE_REG);
+
+ // Push a dummy return address which suggests that we are inside of
+ // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+ __ movl(
+ EAX,
+ Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+ __ pushl(FieldAddress(EAX, compiler::target::Code::entry_point_offset()));
+
+ // Continue with Dart frame setup.
+ FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
static bool CanBeImmediateIndex(Value* value, intptr_t cid) {
ConstantInstr* constant = value->definition()->AsConstant();
if ((constant == NULL) || !Assembler::IsSafeSmi(constant->value())) {
@@ -1575,10 +1732,10 @@
Label ok, fail_label;
- Label* deopt =
- compiler->is_optimizing()
- ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
- : NULL;
+ Label* deopt = nullptr;
+ if (compiler->is_optimizing()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+ }
Label* fail = (deopt != NULL) ? deopt : &fail_label;
@@ -3732,9 +3889,10 @@
Register value = locs()->in(0).reg();
const Register result = locs()->out(0).reg();
const Register temp = CanDeoptimize() ? locs()->temp(0).reg() : kNoRegister;
- Label* deopt = CanDeoptimize() ? compiler->AddDeoptStub(
- GetDeoptId(), ICData::kDeoptUnboxInteger)
- : NULL;
+ Label* deopt = nullptr;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(GetDeoptId(), ICData::kDeoptUnboxInteger);
+ }
Label* out_of_range = !is_truncating() ? deopt : NULL;
const intptr_t lo_offset = Mint::value_offset();
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index fe7508f..a2f841d 100644
--- a/runtime/vm/compiler/backend/il_printer.cc
+++ b/runtime/vm/compiler/backend/il_printer.cc
@@ -524,12 +524,10 @@
void FfiCallInstr::PrintOperandsTo(BufferFormatter* f) const {
f->Print(" pointer=");
InputAt(TargetAddressIndex())->PrintTo(f);
- f->Print(" signature=%s",
- Type::Handle(signature_.SignatureType()).ToCString());
for (intptr_t i = 0, n = InputCount(); i < n - 1; ++i) {
f->Print(", ");
InputAt(i)->PrintTo(f);
- f->Print(" (at %s) ", arg_locations_[i].ToCString());
+ f->Print(" (@%s)", arg_locations_[i].ToCString());
}
}
@@ -1063,6 +1061,24 @@
BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
}
+void NativeEntryInstr::PrintTo(BufferFormatter* f) const {
+ f->Print("B%" Pd "[native function entry]:%" Pd, block_id(), GetDeoptId());
+ if (HasParallelMove()) {
+ f->Print("\n");
+ parallel_move()->PrintTo(f);
+ }
+ BlockEntryWithInitialDefs::PrintInitialDefinitionsTo(f);
+}
+
+void NativeReturnInstr::PrintOperandsTo(BufferFormatter* f) const {
+ value()->PrintTo(f);
+}
+
+void NativeParameterInstr::PrintOperandsTo(BufferFormatter* f) const {
+ f->Print("%s as %s", loc_.ToCString(),
+ RepresentationToCString(representation_));
+}
+
void CatchBlockEntryInstr::PrintTo(BufferFormatter* f) const {
f->Print("B%" Pd "[target catch try_idx %" Pd " catch_try_idx %" Pd "]",
block_id(), try_index(), catch_try_index());
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index e8bf0f8..7ffade3 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -139,6 +139,43 @@
__ set_constant_pool_allowed(true);
}
+void NativeReturnInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ LeaveDartFrame();
+
+ // Pop dummy return address.
+ __ popq(TMP);
+
+ // Anything besides the return register.
+ const Register vm_tag_reg = RBX, old_exit_frame_reg = RCX;
+
+ __ popq(old_exit_frame_reg);
+
+ // Restore top_resource.
+ __ popq(TMP);
+ __ movq(Address(THR, compiler::target::Thread::top_resource_offset()), TMP);
+
+ __ popq(vm_tag_reg);
+
+ // TransitionGeneratedToNative will reset the exit frame info to
+ // old_exit_frame_reg *before* entering the safepoint.
+ __ TransitionGeneratedToNative(vm_tag_reg, old_exit_frame_reg);
+
+ // Restore C++ ABI callee-saved registers.
+ __ PopRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+ CallingConventions::kCalleeSaveXmmRegisters);
+
+ // Leave the entry frame.
+ __ LeaveFrame();
+
+ // Leave the dummy frame holding the pushed arguments.
+ __ LeaveFrame();
+
+ __ ret();
+
+ // For following blocks.
+ __ set_constant_pool_allowed(true);
+}
+
static Condition NegateCondition(Condition condition) {
switch (condition) {
case EQUAL:
@@ -921,7 +958,7 @@
__ movq(Address(FPREG, kSavedCallerPcSlotFromFp * kWordSize), TMP);
// Update information in the thread object and enter a safepoint.
- __ TransitionGeneratedToNative(target_address);
+ __ TransitionGeneratedToNative(target_address, FPREG);
__ CallCFunction(target_address);
@@ -943,6 +980,132 @@
__ popq(TMP);
}
+void NativeEntryInstr::SaveArgument(FlowGraphCompiler* compiler,
+ Location loc) const {
+ ASSERT(!loc.IsPairLocation());
+
+ if (loc.HasStackIndex()) return;
+
+ if (loc.IsRegister()) {
+ __ pushq(loc.reg());
+ } else if (loc.IsFpuRegister()) {
+ __ movq(TMP, loc.fpu_reg());
+ __ pushq(TMP);
+ } else {
+ UNREACHABLE();
+ }
+}
+
+void NativeEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (FLAG_precompiled_mode) {
+ UNREACHABLE();
+ }
+
+ __ Bind(compiler->GetJumpLabel(this));
+
+ // Create a dummy frame holding the pushed arguments. This simplifies
+ // NativeReturnInstr::EmitNativeCode.
+ __ EnterFrame(0);
+
+ // Save the argument registers, in reverse order.
+ for (intptr_t i = argument_locations_->length(); i-- > 0;) {
+ SaveArgument(compiler, argument_locations_->At(i));
+ }
+
+ // Enter the entry frame. Push a dummy return address for consistency with
+ // EnterFrame on ARM(64).
+ __ PushImmediate(Immediate(0));
+ __ EnterFrame(0);
+
+ // Save a space for the code object.
+ __ PushImmediate(Immediate(0));
+
+ // InvokoeDartCodeStub saves the arguments descriptor here. We don't have one,
+ // but we need to follow the same frame layout for the stack walker.
+ __ PushImmediate(Immediate(0));
+
+ // Save ABI callee-saved registers.
+ __ PushRegisters(CallingConventions::kCalleeSaveCpuRegisters,
+ CallingConventions::kCalleeSaveXmmRegisters);
+
+ // Load the thread object.
+ // TODO(35765): Fix linking issue on AOT.
+ // TOOD(35934): Exclude native callbacks from snapshots.
+ //
+ // Create another frame to align the frame before continuing in "native" code.
+ {
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+
+ __ movq(
+ RAX,
+ Immediate(reinterpret_cast<int64_t>(DLRT_GetThreadForNativeCallback)));
+ __ call(RAX);
+ __ movq(THR, RAX);
+
+ __ LeaveFrame();
+ }
+
+ // Save the current VMTag on the stack.
+ __ movq(RAX, Assembler::VMTagAddress());
+ __ pushq(RAX);
+
+ // Save top resource.
+ __ pushq(Address(THR, compiler::target::Thread::top_resource_offset()));
+ __ movq(Address(THR, compiler::target::Thread::top_resource_offset()),
+ Immediate(0));
+
+ // Save top exit frame info. Stack walker expects it to be here.
+ __ pushq(
+ Address(THR, compiler::target::Thread::top_exit_frame_info_offset()));
+
+ // In debug mode, verify that we've pushed the top exit frame info at the
+ // correct offset from FP.
+ __ EmitEntryFrameVerification();
+
+ // TransitionNativeToGenerated will reset top exit frame info to 0 *after*
+ // leaving the safepoint.
+ __ TransitionNativeToGenerated();
+
+ // Now that the safepoint has ended, we can touch Dart objects without
+ // handles.
+ // Otherwise we'll clobber the argument sent from the caller.
+ COMPILE_ASSERT(RAX != CallingConventions::kArg1Reg);
+ __ movq(CallingConventions::kArg1Reg, Immediate(callback_id_));
+ __ movq(RAX, Address(THR, compiler::target::Thread::
+ verify_callback_isolate_entry_point_offset()));
+ __ call(RAX);
+
+ // Load the code object.
+ __ movq(RAX, Address(THR, compiler::target::Thread::callback_code_offset()));
+ __ movq(RAX, FieldAddress(
+ RAX, compiler::target::GrowableObjectArray::data_offset()));
+ __ movq(CODE_REG,
+ FieldAddress(RAX, compiler::target::Array::data_offset() +
+ callback_id_ * compiler::target::kWordSize));
+
+ // Put the code object in the reserved slot.
+ __ movq(Address(FPREG, kPcMarkerSlotFromFp * compiler::target::kWordSize),
+ CODE_REG);
+
+ if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
+ __ movq(PP, Address(THR,
+ compiler::target::Thread::global_object_pool_offset()));
+ } else {
+ __ xorq(PP, PP); // GC-safe value into PP.
+ }
+
+ // Push a dummy return address which suggests that we are inside of
+ // InvokeDartCodeStub. This is how the stack walker detects an entry frame.
+ __ movq(
+ RAX,
+ Address(THR, compiler::target::Thread::invoke_dart_code_stub_offset()));
+ __ pushq(FieldAddress(RAX, compiler::target::Code::entry_point_offset()));
+
+ // Continue with Dart frame setup.
+ FunctionEntryInstr::EmitNativeCode(compiler);
+}
+
static bool CanBeImmediateIndex(Value* index, intptr_t cid) {
if (!index->definition()->IsConstant()) return false;
const Object& constant = index->definition()->AsConstant()->value();
@@ -1665,10 +1828,10 @@
Label ok, fail_label;
- Label* deopt =
- compiler->is_optimizing()
- ? compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField)
- : NULL;
+ Label* deopt = NULL;
+ if (compiler->is_optimizing()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptGuardField);
+ }
Label* fail = (deopt != NULL) ? deopt : &fail_label;
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index d3b03a9..7be5d0e 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -3322,10 +3322,10 @@
// Insert receiver class or null check if needed.
switch (check) {
case FlowGraph::ToCheck::kCheckCid: {
- Instruction* check_class =
- flow_graph->CreateCheckClass(call->Receiver()->definition(),
- *Cids::Create(Z, *call->ic_data(), 0),
- call->deopt_id(), call->token_pos());
+ Instruction* check_class = flow_graph->CreateCheckClass(
+ call->Receiver()->definition(),
+ *Cids::CreateAndExpand(Z, *call->ic_data(), 0), call->deopt_id(),
+ call->token_pos());
flow_graph->InsertBefore(call, check_class, call->env(),
FlowGraph::kEffect);
break;
diff --git a/runtime/vm/compiler/backend/linearscan.cc b/runtime/vm/compiler/backend/linearscan.cc
index 4f5473c..b5fea9c 100644
--- a/runtime/vm/compiler/backend/linearscan.cc
+++ b/runtime/vm/compiler/backend/linearscan.cc
@@ -824,25 +824,6 @@
}
}
-static Location::Kind RegisterKindForResult(Instruction* instr) {
- const Representation rep = instr->representation();
-#if !defined(TARGET_ARCH_DBC)
- if ((rep == kUnboxedFloat) || (rep == kUnboxedDouble) ||
- (rep == kUnboxedFloat32x4) || (rep == kUnboxedInt32x4) ||
- (rep == kUnboxedFloat64x2)) {
- return Location::kFpuRegister;
- } else {
- return Location::kRegister;
- }
-#else
- // DBC supports only unboxed doubles and does not have distinguished FPU
- // registers.
- ASSERT((rep != kUnboxedFloat32x4) && (rep != kUnboxedInt32x4) &&
- (rep != kUnboxedFloat64x2));
- return Location::kRegister;
-#endif
-}
-
//
// When describing shape of live ranges in comments below we are going to use
// the following notation:
@@ -991,11 +972,11 @@
// All phi resolution moves are connected. Phi's live range is
// complete.
AssignSafepoints(phi, range);
- CompleteRange(range, RegisterKindForResult(phi));
+ CompleteRange(range, phi->RegisterKindForResult());
if (is_pair_phi) {
LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
AssignSafepoints(phi, second_range);
- CompleteRange(second_range, RegisterKindForResult(phi));
+ CompleteRange(second_range, phi->RegisterKindForResult());
}
move_idx += is_pair_phi ? 2 : 1;
@@ -1303,7 +1284,7 @@
}
AssignSafepoints(def, range);
- CompleteRange(range, RegisterKindForResult(def));
+ CompleteRange(range, def->RegisterKindForResult());
}
// Create and update live ranges corresponding to instruction's inputs,
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index 5f12916..1c405f9 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -366,7 +366,8 @@
void CallSpecializer::AddChecksForArgNr(InstanceCallInstr* call,
Definition* instr,
int argument_number) {
- const Cids* cids = Cids::Create(Z, *call->ic_data(), argument_number);
+ const Cids* cids =
+ Cids::CreateAndExpand(Z, *call->ic_data(), argument_number);
AddCheckClass(instr, *cids, call->deopt_id(), call->env(), call);
}
@@ -1502,7 +1503,7 @@
new (Z) Value(call->ArgumentAt(1)), call->deopt_id(),
result_cid);
const Cids* cids =
- Cids::Create(Z, ic_data, /* argument_number =*/0);
+ Cids::CreateAndExpand(Z, ic_data, /* argument_number =*/0);
AddCheckClass(min_max->left()->definition(), *cids,
call->deopt_id(), call->env(), call);
AddCheckClass(min_max->right()->definition(), *cids,
diff --git a/runtime/vm/compiler/ffi.cc b/runtime/vm/compiler/ffi.cc
index 823e8ef..665382a 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -9,6 +9,8 @@
#include "platform/globals.h"
#include "vm/compiler/backend/locations.h"
#include "vm/compiler/runtime_api.h"
+#include "vm/growable_array.h"
+#include "vm/stack_frame.h"
namespace dart {
@@ -182,7 +184,7 @@
class Location,
class Register,
class FpuRegister>
-class ArgumentFrameState : public ValueObject {
+class ArgumentAllocator : public ValueObject {
public:
Location AllocateArgument(Representation rep) {
switch (rep) {
@@ -207,9 +209,13 @@
}
// Argument must be spilled.
- if ((rep == kUnboxedInt64 || rep == kUnboxedDouble) &&
- compiler::target::kWordSize == 4) {
+ if (rep == kUnboxedInt64 && compiler::target::kWordSize == 4) {
return AllocateAlignedStackSlots(rep);
+ } else if (rep == kUnboxedDouble) {
+ // By convention, we always use DoubleStackSlot for doubles, even on
+ // 64-bit systems.
+ ASSERT(!CallingConventions::kAlignArguments);
+ return AllocateDoubleStackSlot();
} else {
return AllocateStackSlot();
}
@@ -221,6 +227,13 @@
CallingConventions::kStackPointerRegister);
}
+ Location AllocateDoubleStackSlot() {
+ const Location result = Location::DoubleStackSlot(
+ stack_height_in_slots, CallingConventions::kStackPointerRegister);
+ stack_height_in_slots += 8 / compiler::target::kWordSize;
+ return result;
+ }
+
// Allocates a pair of stack slots where the first stack slot is aligned to an
// 8-byte boundary, if necessary.
Location AllocateAlignedStackSlots(Representation rep) {
@@ -287,6 +300,68 @@
intptr_t stack_height_in_slots = 0;
};
+ZoneGrowableArray<Location>*
+CallbackArgumentTranslator::TranslateArgumentLocations(
+ const ZoneGrowableArray<Location>& arg_locs) {
+ auto& pushed_locs = *(new ZoneGrowableArray<Location>(arg_locs.length()));
+
+ CallbackArgumentTranslator translator;
+ for (intptr_t i = 0, n = arg_locs.length(); i < n; i++) {
+ translator.AllocateArgument(arg_locs[i]);
+ }
+ for (intptr_t i = 0, n = arg_locs.length(); i < n; ++i) {
+ pushed_locs.Add(translator.TranslateArgument(arg_locs[i]));
+ }
+
+ return &pushed_locs;
+}
+
+void CallbackArgumentTranslator::AllocateArgument(Location arg) {
+ if (arg.IsPairLocation()) {
+ AllocateArgument(arg.Component(0));
+ AllocateArgument(arg.Component(1));
+ return;
+ }
+ if (arg.HasStackIndex()) return;
+ ASSERT(arg.IsRegister() || arg.IsFpuRegister());
+ if (arg.IsRegister()) {
+ argument_slots_required_++;
+ } else {
+ argument_slots_required_ += 8 / compiler::target::kWordSize;
+ }
+}
+
+Location CallbackArgumentTranslator::TranslateArgument(Location arg) {
+ if (arg.IsPairLocation()) {
+ const Location low = TranslateArgument(arg.Component(0));
+ const Location high = TranslateArgument(arg.Component(1));
+ return Location::Pair(low, high);
+ }
+
+ if (arg.HasStackIndex()) {
+ // Add extra slots after the saved arguments for the return address and
+ // frame pointer of the dummy arguments frame, which will be between the
+ // saved argument registers and stack arguments. Also add slots for the
+ // shadow space if present (factored into
+ // kCallbackSlotsBeforeSavedArguments).
+ FrameRebase rebase(
+ /*old_base=*/SPREG, /*new_base=*/SPREG,
+ /*stack_delta=*/argument_slots_required_ +
+ kCallbackSlotsBeforeSavedArguments);
+ return rebase.Rebase(arg);
+ }
+
+ if (arg.IsRegister()) {
+ return Location::StackSlot(argument_slots_used_++, SPREG);
+ }
+
+ ASSERT(arg.IsFpuRegister());
+ const Location result =
+ Location::DoubleStackSlot(argument_slots_used_, SPREG);
+ argument_slots_used_ += 8 / compiler::target::kWordSize;
+ return result;
+}
+
// Takes a list of argument representations, and converts it to a list of
// argument locations based on calling convention.
template <class CallingConventions,
@@ -299,7 +374,7 @@
auto result = new ZoneGrowableArray<Location>(num_arguments);
// Loop through all arguments and assign a register or a stack location.
- ArgumentFrameState<CallingConventions, Location, Register, FpuRegister>
+ ArgumentAllocator<CallingConventions, Location, Register, FpuRegister>
frame_state;
for (intptr_t i = 0; i < num_arguments; i++) {
Representation rep = arg_reps[i];
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index cd8e96f..846775a 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -108,6 +108,31 @@
#endif // defined(TARGET_ARCH_DBC)
+// This classes translates the ABI location of arguments into the locations they
+// will inhabit after entry-frame setup in the invocation of a native callback.
+//
+// Native -> Dart callbacks must push all the arguments before executing any
+// Dart code because the reading the Thread from TLS requires calling a native
+// stub, and the argument registers are volatile on all ABIs we support.
+//
+// To avoid complicating initial definitions, all callback arguments are read
+// off the stack from their pushed locations, so this class updates the argument
+// positions to account for this.
+//
+// See 'NativeEntryInstr::EmitNativeCode' for details.
+class CallbackArgumentTranslator : public ValueObject {
+ public:
+ static ZoneGrowableArray<Location>* TranslateArgumentLocations(
+ const ZoneGrowableArray<Location>& arg_locs);
+
+ private:
+ void AllocateArgument(Location arg);
+ Location TranslateArgument(Location arg);
+
+ intptr_t argument_slots_used_ = 0;
+ intptr_t argument_slots_required_ = 0;
+};
+
} // namespace ffi
} // namespace compiler
diff --git a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
index efec2db..e8d1918 100644
--- a/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
+++ b/runtime/vm/compiler/ffi_dbc_trampoline_x64_linux_mac.S
@@ -18,15 +18,15 @@
/* Copy stack arguments. */
mov rax, [rbx+0x78] /* Load number of stack arguments. */
cmp rax, 0x0 /* Check if number of stack arguments is 0. */
-jz 2f /* Skip loop if no stack arguments. */
+jz .done /* Skip loop if no stack arguments. */
add rbx, 0x78 /* Offset RBX to point to stack arguments */
-1: /* Copy stack arguments loop. */
+.loop: /* Copy stack arguments loop. */
push [rbx+0x8*rax] /* Push stack argument. */
sub rax, 0x1 /* Decrement stack argument iterator. */
cmp rax, 0x0 /* Compare iterator with 0 */
-jnz 1b /* Loop while iterator is not 0 */
+jnz .loop /* Loop while iterator is not 0 */
sub rbx, 0x78 /* Restore RBX to original value. */
-2: /* End stack arguments loop. */
+.done: /* End stack arguments loop. */
/* Copy registers and fpu registers. */
mov rdi, [rbx+0x8] /* kArg1Reg */
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 61f37dfe..71a60b5 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -1951,7 +1951,7 @@
}
while (update_position &&
- pc_ >= source_pos_iter.BytecodeInstructionIndex()) {
+ static_cast<uword>(pc_) >= source_pos_iter.PcOffset()) {
position_ = source_pos_iter.TokenPos();
update_position = source_pos_iter.MoveNext();
}
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 690d873..e59d856 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -12,9 +12,11 @@
#include "vm/compiler/frontend/bytecode_scope_builder.h"
#include "vm/constants_kbc.h"
#include "vm/dart_entry.h"
+#include "vm/debugger.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
#include "vm/reusable_handles.h"
+#include "vm/stack_frame_kbc.h"
#include "vm/timeline.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -244,6 +246,7 @@
(flags & Code::kHasExceptionsTableFlag) != 0;
const bool has_source_positions =
(flags & Code::kHasSourcePositionsFlag) != 0;
+ const bool has_local_variables = (flags & Code::kHasLocalVariablesFlag) != 0;
const bool has_nullable_fields = (flags & Code::kHasNullableFieldsFlag) != 0;
const bool has_closures = (flags & Code::kHasClosuresFlag) != 0;
const bool has_parameters_flags = (flags & Code::kHasParameterFlagsFlag) != 0;
@@ -299,6 +302,8 @@
ReadSourcePositions(bytecode, has_source_positions);
+ ReadLocalVariables(bytecode, has_local_variables);
+
if (FLAG_dump_kernel_bytecode) {
KernelBytecodeDisassembler::Disassemble(function);
}
@@ -330,9 +335,11 @@
const intptr_t flags = helper_->reader_.ReadUInt();
const bool has_exceptions_table =
- (flags & Code::kHasExceptionsTableFlag) != 0;
+ (flags & ClosureCode::kHasExceptionsTableFlag) != 0;
const bool has_source_positions =
- (flags & Code::kHasSourcePositionsFlag) != 0;
+ (flags & ClosureCode::kHasSourcePositionsFlag) != 0;
+ const bool has_local_variables =
+ (flags & ClosureCode::kHasLocalVariablesFlag) != 0;
// Read closure bytecode and attach to closure function.
closure_bytecode = ReadBytecode(pool);
@@ -343,6 +350,8 @@
ReadSourcePositions(closure_bytecode, has_source_positions);
+ ReadLocalVariables(closure_bytecode, has_local_variables);
+
if (FLAG_dump_kernel_bytecode) {
KernelBytecodeDisassembler::Disassemble(closure);
}
@@ -352,9 +361,12 @@
void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
intptr_t closureIndex) {
- const int kHasOptionalPositionalParams = 1 << 0;
- const int kHasOptionalNamedParams = 1 << 1;
- const int kHasTypeParams = 1 << 2;
+ // Closure flags, must be in sync with ClosureDeclaration constants in
+ // pkg/vm/lib/bytecode/declarations.dart.
+ const int kHasOptionalPositionalParamsFlag = 1 << 0;
+ const int kHasOptionalNamedParamsFlag = 1 << 1;
+ const int kHasTypeParamsFlag = 1 << 2;
+ const int kHasSourcePositionsFlag = 1 << 3;
const intptr_t flags = helper_->reader_.ReadUInt();
@@ -369,20 +381,27 @@
String& name = String::CheckedHandle(Z, ReadObject());
ASSERT(name.IsSymbol());
+ TokenPosition position = TokenPosition::kNoSource;
+ TokenPosition end_position = TokenPosition::kNoSource;
+ if ((flags & kHasSourcePositionsFlag) != 0) {
+ position = helper_->ReadPosition();
+ end_position = helper_->ReadPosition();
+ }
+
const Function& closure = Function::Handle(
- Z, Function::NewClosureFunction(name, Function::Cast(parent),
- TokenPosition::kNoSource));
+ Z, Function::NewClosureFunction(name, Function::Cast(parent), position));
closure.set_is_declared_in_bytecode(true);
+ closure.set_end_token_pos(end_position);
closures_->SetAt(closureIndex, closure);
- Type& signature_type =
- Type::Handle(Z, ReadFunctionSignature(
- closure, (flags & kHasOptionalPositionalParams) != 0,
- (flags & kHasOptionalNamedParams) != 0,
- (flags & kHasTypeParams) != 0,
- /* has_positional_param_names = */ true));
+ Type& signature_type = Type::Handle(
+ Z, ReadFunctionSignature(closure,
+ (flags & kHasOptionalPositionalParamsFlag) != 0,
+ (flags & kHasOptionalNamedParamsFlag) != 0,
+ (flags & kHasTypeParamsFlag) != 0,
+ /* has_positional_param_names = */ true));
closure.SetSignatureType(signature_type);
}
@@ -397,8 +416,6 @@
if (has_type_params) {
ReadTypeParametersDeclaration(Class::Handle(Z), func);
- function_type_type_parameters_ =
- &TypeArguments::Handle(Z, func.type_parameters());
}
const intptr_t kImplicitClosureParam = 1;
@@ -480,6 +497,7 @@
// Do not set type parameters for factories, as VM uses class type
// parameters instead.
parameterized_function.set_type_parameters(type_parameters);
+ function_type_type_parameters_ = &type_parameters;
}
// Step b) Fill in the bounds of all [TypeParameter]s.
@@ -789,6 +807,21 @@
bytecode_component_->GetSourcePositionsOffset() + offset);
}
+void BytecodeReaderHelper::ReadLocalVariables(const Bytecode& bytecode,
+ bool has_local_variables) {
+ if (!has_local_variables) {
+ return;
+ }
+
+ intptr_t offset = helper_->reader_.ReadUInt();
+ USE(offset);
+
+#if !defined(PRODUCT)
+ bytecode.set_local_variables_binary_offset(
+ bytecode_component_->GetLocalVariablesOffset() + offset);
+#endif
+}
+
RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
const String& external_name) {
MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
@@ -902,6 +935,14 @@
const intptr_t sources_positions_offset =
start_offset + helper_->reader_.ReadUInt32();
+ intptr_t local_variables_offset = 0;
+ static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 9,
+ "Cleanup condition");
+ if (version >= 9) {
+ helper_->reader_.ReadUInt32(); // Skip localVariables.numItems
+ local_variables_offset = start_offset + helper_->reader_.ReadUInt32();
+ }
+
helper_->reader_.ReadUInt32(); // Skip annotations.numItems
const intptr_t annotations_offset =
start_offset + helper_->reader_.ReadUInt32();
@@ -924,11 +965,11 @@
helper_->reader_.set_offset(objects_contents_offset + objects_size);
const Array& bytecode_component_array = Array::Handle(
- Z,
- BytecodeComponentData::New(
- Z, version, num_objects, string_table_offset, strings_contents_offset,
- objects_contents_offset, main_offset, members_offset, codes_offset,
- sources_positions_offset, annotations_offset, Heap::kOld));
+ Z, BytecodeComponentData::New(
+ Z, version, num_objects, string_table_offset,
+ strings_contents_offset, objects_contents_offset, main_offset,
+ members_offset, codes_offset, sources_positions_offset,
+ local_variables_offset, annotations_offset, Heap::kOld));
BytecodeComponentData bytecode_component(bytecode_component_array);
@@ -2084,6 +2125,10 @@
return Smi::Value(Smi::RawCast(data_.At(kSourcePositionsOffset)));
}
+intptr_t BytecodeComponentData::GetLocalVariablesOffset() const {
+ return Smi::Value(Smi::RawCast(data_.At(kLocalVariablesOffset)));
+}
+
intptr_t BytecodeComponentData::GetAnnotationsOffset() const {
return Smi::Value(Smi::RawCast(data_.At(kAnnotationsOffset)));
}
@@ -2106,6 +2151,7 @@
intptr_t members_offset,
intptr_t codes_offset,
intptr_t source_positions_offset,
+ intptr_t local_variables_offset,
intptr_t annotations_offset,
Heap::Space space) {
const Array& data =
@@ -2136,6 +2182,9 @@
smi_handle = Smi::New(source_positions_offset);
data.SetAt(kSourcePositionsOffset, smi_handle);
+ smi_handle = Smi::New(local_variables_offset);
+ data.SetAt(kLocalVariablesOffset, smi_handle);
+
smi_handle = Smi::New(annotations_offset);
data.SetAt(kAnnotationsOffset, smi_handle);
@@ -2183,6 +2232,10 @@
bytecode_metadata_helper.ReadMetadata(function);
+#if !defined(PRODUCT)
+ thread->isolate()->debugger()->NotifyBytecodeLoaded(function);
+#endif
+
return Error::null();
} else {
return thread->StealStickyError();
@@ -2213,6 +2266,108 @@
annotation_field.bytecode_offset());
}
+#if !defined(PRODUCT)
+RawLocalVarDescriptors* BytecodeReader::ComputeLocalVarDescriptors(
+ Zone* zone,
+ const Function& function,
+ const Bytecode& bytecode) {
+ ASSERT(function.is_declared_in_bytecode());
+ ASSERT(function.HasBytecode());
+ ASSERT(!bytecode.IsNull());
+ ASSERT(function.bytecode() == bytecode.raw());
+
+ struct VarDesc {
+ const String* name;
+ RawLocalVarDescriptors::VarInfo info;
+ };
+ GrowableArray<VarDesc> vars(8);
+
+ if (function.IsLocalFunction()) {
+ const auto& parent = Function::Handle(zone, function.parent_function());
+ ASSERT(parent.is_declared_in_bytecode() && parent.HasBytecode());
+ const auto& parent_bytecode = Bytecode::Handle(zone, parent.bytecode());
+ const auto& parent_vars = LocalVarDescriptors::Handle(
+ zone, parent_bytecode.GetLocalVarDescriptors());
+ for (intptr_t i = 0; i < parent_vars.Length(); ++i) {
+ RawLocalVarDescriptors::VarInfo var_info;
+ parent_vars.GetInfo(i, &var_info);
+ // Include parent's context variable if variable's scope
+ // intersects with the local function range.
+ // It is not enough to check if local function is declared within the
+ // scope of variable, because in case of async functions closure has
+ // the same range as original function.
+ if (var_info.kind() == RawLocalVarDescriptors::kContextVar &&
+ ((var_info.begin_pos <= function.token_pos() &&
+ function.token_pos() <= var_info.end_pos) ||
+ (function.token_pos() <= var_info.begin_pos &&
+ var_info.begin_pos <= function.end_token_pos()))) {
+ vars.Add(
+ VarDesc{&String::Handle(zone, parent_vars.GetName(i)), var_info});
+ }
+ }
+ }
+
+ if (bytecode.HasLocalVariablesInfo()) {
+ intptr_t scope_id = 0;
+ intptr_t context_level = -1;
+ BytecodeLocalVariablesIterator local_vars(zone, bytecode);
+ while (local_vars.MoveNext()) {
+ switch (local_vars.Kind()) {
+ case BytecodeLocalVariablesIterator::kScope: {
+ ++scope_id;
+ context_level = local_vars.ContextLevel();
+ } break;
+ case BytecodeLocalVariablesIterator::kVariableDeclaration: {
+ VarDesc desc;
+ desc.name = &String::Handle(zone, local_vars.Name());
+ if (local_vars.IsCaptured()) {
+ desc.info.set_kind(RawLocalVarDescriptors::kContextVar);
+ desc.info.scope_id = context_level;
+ desc.info.set_index(local_vars.Index());
+ } else {
+ desc.info.set_kind(RawLocalVarDescriptors::kStackVar);
+ desc.info.scope_id = scope_id;
+ if (local_vars.Index() < 0) {
+ // Parameter
+ desc.info.set_index(-local_vars.Index() - kKBCParamEndSlotFromFp);
+ } else {
+ desc.info.set_index(-local_vars.Index());
+ }
+ }
+ desc.info.declaration_pos = local_vars.DeclarationTokenPos();
+ desc.info.begin_pos = local_vars.StartTokenPos();
+ desc.info.end_pos = local_vars.EndTokenPos();
+ vars.Add(desc);
+ } break;
+ case BytecodeLocalVariablesIterator::kContextVariable: {
+ ASSERT(local_vars.Index() >= 0);
+ const intptr_t context_variable_index = -local_vars.Index();
+ VarDesc desc;
+ desc.name = &Symbols::CurrentContextVar();
+ desc.info.set_kind(RawLocalVarDescriptors::kSavedCurrentContext);
+ desc.info.scope_id = 0;
+ desc.info.declaration_pos = TokenPosition::kMinSource;
+ desc.info.begin_pos = TokenPosition::kMinSource;
+ desc.info.end_pos = TokenPosition::kMinSource;
+ desc.info.set_index(context_variable_index);
+ vars.Add(desc);
+ } break;
+ }
+ }
+ }
+
+ if (vars.is_empty()) {
+ return Object::empty_var_descriptors().raw();
+ }
+ const LocalVarDescriptors& var_desc = LocalVarDescriptors::Handle(
+ zone, LocalVarDescriptors::New(vars.length()));
+ for (intptr_t i = 0; i < vars.length(); i++) {
+ var_desc.SetVar(i, *(vars[i].name), &vars[i].info);
+ }
+ return var_desc.raw();
+}
+#endif // !defined(PRODUCT)
+
static_assert(KernelBytecode::kMinSupportedBytecodeFormatVersion < 7,
"Cleanup support for old bytecode format versions");
void BytecodeReader::UseBytecodeVersion(intptr_t version) {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index 701cc2d..9353029 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -109,6 +109,15 @@
static const int kHasParameterFlagsFlag = 1 << 4;
static const int kHasForwardingStubTargetFlag = 1 << 5;
static const int kHasDefaultFunctionTypeArgsFlag = 1 << 6;
+ static const int kHasLocalVariablesFlag = 1 << 7;
+ };
+
+ // Closure code flags, must be in sync with ClosureCode constants in
+ // pkg/vm/lib/bytecode/declarations.dart.
+ struct ClosureCode {
+ static const int kHasExceptionsTableFlag = 1 << 0;
+ static const int kHasSourcePositionsFlag = 1 << 1;
+ static const int kHasLocalVariablesFlag = 1 << 2;
};
// Parameter flags, must be in sync with ParameterDeclaration constants in
@@ -131,7 +140,7 @@
private:
BytecodeReaderHelper* bytecode_reader_;
- TypeArguments* const saved_type_parameters_;
+ const TypeArguments* const saved_type_parameters_;
};
class FunctionScope : public ValueObject {
@@ -173,6 +182,7 @@
RawBytecode* ReadBytecode(const ObjectPool& pool);
void ReadExceptionsTable(const Bytecode& bytecode, bool has_exceptions_table);
void ReadSourcePositions(const Bytecode& bytecode, bool has_source_positions);
+ void ReadLocalVariables(const Bytecode& bytecode, bool has_local_variables);
RawTypedData* NativeEntry(const Function& function,
const String& external_name);
RawString* ConstructorName(const Class& cls, const String& name);
@@ -192,7 +202,7 @@
Zone* const zone_;
BytecodeComponentData* const bytecode_component_;
Array* closures_ = nullptr;
- TypeArguments* function_type_type_parameters_ = nullptr;
+ const TypeArguments* function_type_type_parameters_ = nullptr;
PatchClass* patch_class_ = nullptr;
Array* functions_ = nullptr;
intptr_t function_index_ = 0;
@@ -214,6 +224,7 @@
kMembersOffset,
kCodesOffset,
kSourcePositionsOffset,
+ kLocalVariablesOffset,
kAnnotationsOffset,
kNumFields
};
@@ -228,6 +239,7 @@
intptr_t GetMembersOffset() const;
intptr_t GetCodesOffset() const;
intptr_t GetSourcePositionsOffset() const;
+ intptr_t GetLocalVariablesOffset() const;
intptr_t GetAnnotationsOffset() const;
void SetObject(intptr_t index, const Object& obj) const;
RawObject* GetObject(intptr_t index) const;
@@ -244,6 +256,7 @@
intptr_t members_offset,
intptr_t codes_offset,
intptr_t source_positions_offset,
+ intptr_t local_variables_offset,
intptr_t annotations_offset,
Heap::Space space);
@@ -261,21 +274,27 @@
// Read annotation for the given annotation field.
static RawObject* ReadAnnotation(const Field& annotation_field);
+#if !defined(PRODUCT)
+ // Compute local variable descriptors for [function] with [bytecode].
+ static RawLocalVarDescriptors* ComputeLocalVarDescriptors(
+ Zone* zone,
+ const Function& function,
+ const Bytecode& bytecode);
+#endif
+
static void UseBytecodeVersion(intptr_t version);
};
class BytecodeSourcePositionsIterator : ValueObject {
public:
BytecodeSourcePositionsIterator(Zone* zone, const Bytecode& bytecode)
- : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
- pairs_remaining_(0),
- pc_shifter_(
- Isolate::Current()->is_using_old_bytecode_instructions() ? 2 : 0),
- cur_bci_(0),
- cur_token_pos_(TokenPosition::kNoSource.value()) {
+ : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))) {
if (bytecode.HasSourcePositions()) {
reader_.set_offset(bytecode.source_positions_binary_offset());
pairs_remaining_ = reader_.ReadUInt();
+ if (Isolate::Current()->is_using_old_bytecode_instructions()) {
+ pc_shifter_ = 2;
+ }
}
}
@@ -290,23 +309,130 @@
return true;
}
- intptr_t BytecodeInstructionIndex() const { return cur_bci_; }
-
- uword PcOffset() const {
- return KernelBytecode::BytecodePcToOffset(BytecodeInstructionIndex(),
- /* is_return_address = */ true);
- }
+ uword PcOffset() const { return cur_bci_; }
TokenPosition TokenPos() const { return TokenPosition(cur_token_pos_); }
private:
Reader reader_;
- intptr_t pairs_remaining_;
- intptr_t pc_shifter_;
- intptr_t cur_bci_;
- intptr_t cur_token_pos_;
+ intptr_t pairs_remaining_ = 0;
+ intptr_t pc_shifter_ = 0;
+ intptr_t cur_bci_ = 0;
+ intptr_t cur_token_pos_ = 0;
};
+#if !defined(PRODUCT)
+class BytecodeLocalVariablesIterator : ValueObject {
+ public:
+ // These constants should match corresponding constants in
+ // pkg/vm/lib/bytecode/local_variable_table.dart.
+ enum {
+ kInvalid,
+ kScope,
+ kVariableDeclaration,
+ kContextVariable,
+ };
+
+ static const intptr_t kKindMask = 0xF;
+ static const intptr_t kIsCapturedFlag = 1 << 4;
+
+ BytecodeLocalVariablesIterator(Zone* zone, const Bytecode& bytecode)
+ : reader_(ExternalTypedData::Handle(zone, bytecode.GetBinary(zone))),
+ object_pool_(ObjectPool::Handle(zone, bytecode.object_pool())) {
+ if (bytecode.HasLocalVariablesInfo()) {
+ reader_.set_offset(bytecode.local_variables_binary_offset());
+ entries_remaining_ = reader_.ReadUInt();
+ }
+ }
+
+ bool MoveNext() {
+ if (entries_remaining_ == 0) {
+ return false;
+ }
+ ASSERT(entries_remaining_ > 0);
+ --entries_remaining_;
+ cur_kind_and_flags_ = reader_.ReadByte();
+ cur_start_pc_ += reader_.ReadSLEB128();
+ switch (Kind()) {
+ case kScope:
+ cur_end_pc_ = cur_start_pc_ + reader_.ReadUInt();
+ cur_index_ = reader_.ReadSLEB128();
+ cur_token_pos_ = reader_.ReadPosition();
+ cur_end_token_pos_ = reader_.ReadPosition();
+ break;
+ case kVariableDeclaration:
+ cur_index_ = reader_.ReadSLEB128();
+ cur_name_ = reader_.ReadUInt();
+ cur_type_ = reader_.ReadUInt();
+ cur_declaration_token_pos_ = reader_.ReadPosition();
+ cur_token_pos_ = reader_.ReadPosition();
+ break;
+ case kContextVariable:
+ cur_index_ = reader_.ReadSLEB128();
+ break;
+ }
+ return true;
+ }
+
+ intptr_t Kind() const { return cur_kind_and_flags_ & kKindMask; }
+ bool IsScope() const { return Kind() == kScope; }
+ bool IsVariableDeclaration() const { return Kind() == kVariableDeclaration; }
+ bool IsContextVariable() const { return Kind() == kContextVariable; }
+
+ intptr_t StartPC() const { return cur_start_pc_; }
+ intptr_t EndPC() const {
+ ASSERT(IsScope() || IsVariableDeclaration());
+ return cur_end_pc_;
+ }
+ intptr_t ContextLevel() const {
+ ASSERT(IsScope());
+ return cur_index_;
+ }
+ TokenPosition StartTokenPos() const {
+ ASSERT(IsScope() || IsVariableDeclaration());
+ return cur_token_pos_;
+ }
+ TokenPosition EndTokenPos() const {
+ ASSERT(IsScope() || IsVariableDeclaration());
+ return cur_end_token_pos_;
+ }
+ intptr_t Index() const {
+ ASSERT(IsVariableDeclaration() || IsContextVariable());
+ return cur_index_;
+ }
+ RawString* Name() const {
+ ASSERT(IsVariableDeclaration());
+ return String::RawCast(object_pool_.ObjectAt(cur_name_));
+ }
+ RawAbstractType* Type() const {
+ ASSERT(IsVariableDeclaration());
+ return AbstractType::RawCast(object_pool_.ObjectAt(cur_type_));
+ }
+ TokenPosition DeclarationTokenPos() const {
+ ASSERT(IsVariableDeclaration());
+ return cur_declaration_token_pos_;
+ }
+ bool IsCaptured() const {
+ ASSERT(IsVariableDeclaration());
+ return (cur_kind_and_flags_ & kIsCapturedFlag) != 0;
+ }
+
+ private:
+ Reader reader_;
+ const ObjectPool& object_pool_;
+ intptr_t entries_remaining_ = 0;
+ intptr_t cur_kind_and_flags_ = 0;
+ intptr_t cur_start_pc_ = 0;
+ intptr_t cur_end_pc_ = 0;
+ intptr_t cur_index_ = -1;
+ intptr_t cur_name_ = -1;
+ intptr_t cur_type_ = -1;
+ TokenPosition cur_token_pos_ = TokenPosition::kNoSource;
+ TokenPosition cur_declaration_token_pos_ = TokenPosition::kNoSource;
+ TokenPosition cur_end_token_pos_ = TokenPosition::kNoSource;
+};
+#endif // !defined(PRODUCT)
+
bool IsStaticFieldGetterGeneratedAsInitializer(const Function& function,
Zone* zone);
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 2ac1adf..6da7494 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -82,7 +82,6 @@
}
helper.SetJustRead(ConstructorHelper::kInitializers);
BuildHash(helper.flags_);
- BuildHash(helper.annotation_count_);
}
void KernelFingerprintHelper::CalculateArgumentsFingerprint() {
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 6049959..f3524f5 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -16,6 +16,7 @@
#include "vm/compiler/jit/compiler.h"
#include "vm/kernel_loader.h"
#include "vm/longjump.h"
+#include "vm/native_entry.h"
#include "vm/object_store.h"
#include "vm/report.h"
#include "vm/resolver.h"
@@ -2440,6 +2441,31 @@
return Fragment(extend);
}
+Fragment FlowGraphBuilder::FfiExceptionalReturnValue(
+ const AbstractType& result_type,
+ Representation representation) {
+ ASSERT(optimizing_);
+ Object& result = Object::ZoneHandle(Z, Object::null());
+ if (representation == kUnboxedFloat || representation == kUnboxedDouble) {
+ result = Double::New(0.0, Heap::kOld);
+ } else {
+ result = Integer::New(0, Heap::kOld);
+ }
+ Fragment code;
+ code += Constant(result);
+ code += UnboxTruncate(representation);
+ return code;
+}
+
+#if !defined(TARGET_ARCH_DBC)
+Fragment FlowGraphBuilder::NativeReturn(Representation result) {
+ auto* instr = new (Z)
+ NativeReturnInstr(TokenPosition::kNoSource, Pop(), result,
+ compiler::ffi::ResultLocation(result), DeoptId::kNone);
+ return Fragment(instr);
+}
+#endif
+
Fragment FlowGraphBuilder::FfiPointerFromAddress(const Type& result_type) {
Fragment test;
TargetEntryInstr* null_entry;
@@ -2465,6 +2491,9 @@
Fragment box(not_null_entry);
{
Class& result_class = Class::ZoneHandle(Z, result_type.type_class());
+ // This class might only be instantiated as a return type of ffi calls.
+ result_class.EnsureIsFinalized(thread_);
+
TypeArguments& args = TypeArguments::ZoneHandle(Z, result_type.arguments());
// A kernel transform for FFI in the front-end ensures that type parameters
@@ -2498,8 +2527,69 @@
return Fragment(instr);
}
+Fragment FlowGraphBuilder::FfiConvertArgumentToDart(
+ const AbstractType& ffi_type,
+ const Representation native_representation) {
+ Fragment body;
+ if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += Box(kUnboxedFfiIntPtr);
+ body += FfiPointerFromAddress(Type::Cast(ffi_type));
+ } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
+ body += Drop();
+ body += NullConstant();
+ } else {
+ const Representation from_rep = native_representation;
+ const Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
+ if (from_rep != to_rep) {
+ body += BitCast(from_rep, to_rep);
+ } else {
+ body += FfiUnboxedExtend(from_rep, ffi_type);
+ }
+ body += Box(to_rep);
+ }
+ return body;
+}
+
+Fragment FlowGraphBuilder::FfiConvertArgumentToNative(
+ const Function& function,
+ const AbstractType& ffi_type,
+ const Representation native_representation) {
+ Fragment body;
+ // Check for 'null'. Only ffi.Pointers are allowed to be null.
+ if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += LoadLocal(MakeTemporary());
+ body <<=
+ new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
+ GetNextDeoptId(), TokenPosition::kNoSource);
+ }
+
+ if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
+ body += LoadAddressFromFfiPointer();
+ body += UnboxTruncate(kUnboxedFfiIntPtr);
+ } else {
+ Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
+ body += UnboxTruncate(from_rep);
+
+ Representation to_rep = native_representation;
+ if (from_rep != to_rep) {
+ body += BitCast(from_rep, to_rep);
+ } else {
+ body += FfiUnboxedExtend(from_rep, ffi_type);
+ }
+ }
+ return body;
+}
+
FlowGraph* FlowGraphBuilder::BuildGraphOfFfiTrampoline(
const Function& function) {
+ if (function.FfiCallbackTarget() != Function::null()) {
+ return BuildGraphOfFfiCallback(function);
+ } else {
+ return BuildGraphOfFfiNative(function);
+ }
+}
+
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiNative(const Function& function) {
graph_entry_ =
new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
@@ -2532,29 +2622,7 @@
for (intptr_t pos = 1; pos < function.num_fixed_parameters(); pos++) {
body += LoadLocal(parsed_function_->ParameterVariable(pos));
ffi_type = signature.ParameterTypeAt(pos);
-
- // Check for 'null'. Only ffi.Pointers are allowed to be null.
- if (!compiler::ffi::NativeTypeIsPointer(ffi_type)) {
- body += LoadLocal(parsed_function_->ParameterVariable(pos));
- body <<=
- new (Z) CheckNullInstr(Pop(), String::ZoneHandle(Z, function.name()),
- GetNextDeoptId(), TokenPosition::kNoSource);
- }
-
- if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
- body += LoadAddressFromFfiPointer();
- body += UnboxTruncate(kUnboxedFfiIntPtr);
- } else {
- Representation from_rep = compiler::ffi::TypeRepresentation(ffi_type);
- body += UnboxTruncate(from_rep);
-
- Representation to_rep = arg_reps[pos - 1];
- if (from_rep != to_rep) {
- body += BitCast(from_rep, to_rep);
- } else {
- body += FfiUnboxedExtend(from_rep, ffi_type);
- }
- }
+ body += FfiConvertArgumentToNative(function, ffi_type, arg_reps[pos - 1]);
}
// Push the function pointer, which is stored (boxed) in the first slot of the
@@ -2569,34 +2637,109 @@
body += FfiCall(signature, arg_reps, arg_locs, arg_host_locs);
ffi_type = signature.result_type();
- if (compiler::ffi::NativeTypeIsPointer(ffi_type)) {
- body += Box(kUnboxedFfiIntPtr);
- body += FfiPointerFromAddress(Type::Cast(ffi_type));
- } else if (compiler::ffi::NativeTypeIsVoid(ffi_type)) {
- body += Drop();
- body += NullConstant();
- } else {
#if !defined(TARGET_ARCH_DBC)
- Representation from_rep = compiler::ffi::ResultRepresentation(signature);
+ const Representation from_rep =
+ compiler::ffi::ResultRepresentation(signature);
#else
- Representation from_rep =
- compiler::ffi::ResultHostRepresentation(signature);
+ const Representation from_rep =
+ compiler::ffi::ResultHostRepresentation(signature);
#endif // !defined(TARGET_ARCH_DBC)
- Representation to_rep = compiler::ffi::TypeRepresentation(ffi_type);
- if (from_rep != to_rep) {
- body += BitCast(from_rep, to_rep);
- } else {
- body += FfiUnboxedExtend(from_rep, ffi_type);
- }
- body += Box(to_rep);
- }
-
+ body += FfiConvertArgumentToDart(ffi_type, from_rep);
body += Return(TokenPosition::kNoSource);
return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
prologue_info);
}
+FlowGraph* FlowGraphBuilder::BuildGraphOfFfiCallback(const Function& function) {
+#if !defined(TARGET_ARCH_DBC)
+ const Function& signature = Function::ZoneHandle(Z, function.FfiCSignature());
+ const auto& arg_reps = *compiler::ffi::ArgumentRepresentations(signature);
+ const auto& arg_locs = *compiler::ffi::ArgumentLocations(arg_reps);
+ const auto& callback_locs =
+ *compiler::ffi::CallbackArgumentTranslator::TranslateArgumentLocations(
+ arg_locs);
+
+ graph_entry_ =
+ new (Z) GraphEntryInstr(*parsed_function_, Compiler::kNoOSRDeoptId);
+
+ auto* const native_entry = new (Z) NativeEntryInstr(
+ &arg_locs, graph_entry_, AllocateBlockId(), CurrentTryIndex(),
+ GetNextDeoptId(), function.FfiCallbackId());
+
+ graph_entry_->set_normal_entry(native_entry);
+
+ Fragment function_body(native_entry);
+ function_body += CheckStackOverflowInPrologue(function.token_pos());
+
+ // Wrap the entire method in a big try/catch. This is important to ensure that
+ // the VM does not crash if the callback throws an exception.
+ const intptr_t try_handler_index = AllocateTryIndex();
+ Fragment body = TryCatch(try_handler_index);
+ ++try_depth_;
+
+ // Box and push the arguments.
+ AbstractType& ffi_type = AbstractType::Handle(Z);
+ for (intptr_t i = 0, n = callback_locs.length(); i < n; ++i) {
+ ffi_type = signature.ParameterTypeAt(i + 1);
+ auto* parameter =
+ new (Z) NativeParameterInstr(callback_locs[i], arg_reps[i]);
+ Push(parameter);
+ body <<= parameter;
+ body += FfiConvertArgumentToDart(ffi_type, arg_reps[i]);
+ body += PushArgument();
+ }
+
+ // Call the target.
+ //
+ // TODO(36748): Determine the hot-reload semantics of callbacks and update the
+ // rebind-rule accordingly.
+ body += StaticCall(TokenPosition::kNoSource,
+ Function::ZoneHandle(Z, function.FfiCallbackTarget()),
+ callback_locs.length(), Array::empty_array(),
+ ICData::kNoRebind);
+
+ ffi_type = signature.result_type();
+ const Representation result_rep =
+ compiler::ffi::ResultRepresentation(signature);
+ body += FfiConvertArgumentToNative(function, ffi_type, result_rep);
+ body += NativeReturn(result_rep);
+
+ --try_depth_;
+ function_body += body;
+
+ ++catch_depth_;
+ Fragment catch_body =
+ CatchBlockEntry(Array::empty_array(), try_handler_index,
+ /*needs_stacktrace=*/true, /*is_synthesized=*/true);
+
+ catch_body += LoadLocal(CurrentException());
+ catch_body += PushArgument();
+ catch_body += LoadLocal(CurrentStackTrace());
+ catch_body += PushArgument();
+
+ // Find '_handleExposedException(e, st)' from ffi_patch.dart and call it.
+ const Library& ffi_lib =
+ Library::Handle(Z, Library::LookupLibrary(thread_, Symbols::DartFfi()));
+ const Function& handler = Function::ZoneHandle(
+ Z, ffi_lib.LookupFunctionAllowPrivate(Symbols::HandleExposedException()));
+ ASSERT(!handler.IsNull());
+ catch_body += StaticCall(TokenPosition::kNoSource, handler, /*num_args=*/2,
+ /*arg_names=*/Array::empty_array(), ICData::kStatic);
+ catch_body += Drop();
+
+ catch_body += FfiExceptionalReturnValue(ffi_type, result_rep);
+ catch_body += NativeReturn(result_rep);
+ --catch_depth_;
+
+ PrologueInfo prologue_info(-1, -1);
+ return new (Z) FlowGraph(*parsed_function_, graph_entry_, last_used_block_id_,
+ prologue_info);
+#else
+ UNREACHABLE();
+#endif
+}
+
void FlowGraphBuilder::SetCurrentTryCatchBlock(TryCatchBlock* try_catch_block) {
try_catch_block_ = try_catch_block;
SetCurrentTryIndex(try_catch_block == nullptr ? kInvalidTryIndex
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 1e34e13..9ccc1a94 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -101,6 +101,8 @@
FlowGraph* BuildGraphOfNoSuchMethodDispatcher(const Function& function);
FlowGraph* BuildGraphOfInvokeFieldDispatcher(const Function& function);
FlowGraph* BuildGraphOfFfiTrampoline(const Function& function);
+ FlowGraph* BuildGraphOfFfiCallback(const Function& function);
+ FlowGraph* BuildGraphOfFfiNative(const Function& function);
Fragment NativeFunctionBody(const Function& function,
LocalVariable* first_parameter);
@@ -236,6 +238,26 @@
// the pointer.
Fragment FfiPointerFromAddress(const Type& result_type);
+ // Pushes an (unboxed) bogus value returned when a native -> Dart callback
+ // throws an exception.
+ Fragment FfiExceptionalReturnValue(const AbstractType& result_type,
+ const Representation target);
+
+ // Pops a Dart object and push the unboxed native version, according to the
+ // semantics of FFI argument translation.
+ Fragment FfiConvertArgumentToNative(
+ const Function& function,
+ const AbstractType& ffi_type,
+ const Representation native_representation);
+
+ // Reverse of 'FfiConvertArgumentToNative'.
+ Fragment FfiConvertArgumentToDart(const AbstractType& ffi_type,
+ const Representation native_representation);
+
+ // Return from a native -> Dart callback. Can only be used in conjunction with
+ // NativeEntry and NativeParameter are used.
+ Fragment NativeReturn(Representation result);
+
// Bit-wise cast between representations.
// Pops the input and pushes the converted result.
// Currently only works with equal sizes and floating point <-> integer.
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 26f5476..fcd1734 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -1367,6 +1367,55 @@
}
}
+#if defined(DEBUG)
+
+void MetadataHelper::VerifyMetadataMappings(
+ const ExternalTypedData& metadata_mappings) {
+ const intptr_t kUInt32Size = 4;
+ Reader reader(metadata_mappings);
+ if (reader.size() == 0) {
+ return;
+ }
+
+ // Scan through metadata mappings in reverse direction.
+
+ // Read metadataMappings length.
+ intptr_t offset = reader.size() - kUInt32Size;
+ const intptr_t metadata_num = reader.ReadUInt32At(offset);
+
+ if (metadata_num == 0) {
+ ASSERT(metadata_mappings.LengthInBytes() == kUInt32Size);
+ return;
+ }
+
+ // Read metadataMappings elements.
+ for (intptr_t i = 0; i < metadata_num; ++i) {
+ // Read nodeOffsetToMetadataOffset length.
+ offset -= kUInt32Size;
+ const intptr_t mappings_num = reader.ReadUInt32At(offset);
+
+ // Skip nodeOffsetToMetadataOffset.
+ offset -= mappings_num * 2 * kUInt32Size;
+
+ // Verify that node offsets are sorted.
+ intptr_t prev_node_offset = -1;
+ reader.set_offset(offset);
+ for (intptr_t j = 0; j < mappings_num; ++j) {
+ const intptr_t node_offset = reader.ReadUInt32();
+ const intptr_t md_offset = reader.ReadUInt32();
+
+ ASSERT(node_offset >= 0 && md_offset >= 0);
+ ASSERT(node_offset > prev_node_offset);
+ prev_node_offset = node_offset;
+ }
+
+ // Skip tag.
+ offset -= kUInt32Size;
+ }
+}
+
+#endif // defined(DEBUG)
+
MetadataHelper::MetadataHelper(KernelReaderHelper* helper,
const char* tag,
bool precompiler_only)
@@ -1386,25 +1435,6 @@
ASSERT((mappings_offset != 0) && (mappings_num != 0));
mappings_offset_ = mappings_offset;
mappings_num_ = mappings_num;
-
-#ifdef DEBUG
- // Verify that node offsets are sorted.
- {
- Reader reader(H.metadata_mappings());
- reader.set_offset(mappings_offset);
-
- intptr_t prev_node_offset = -1;
- for (intptr_t i = 0; i < mappings_num; ++i) {
- intptr_t node_offset = reader.ReadUInt32();
- intptr_t md_offset = reader.ReadUInt32();
-
- ASSERT((node_offset >= 0) && (md_offset >= 0));
- ASSERT(node_offset > prev_node_offset);
- prev_node_offset = node_offset;
- }
- }
-#endif // DEBUG
-
last_node_offset_ = kIntptrMax;
last_mapping_index_ = 0;
}
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 9508b70..4ca7a14 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -262,8 +262,8 @@
TokenPosition end_position_;
AsyncMarker async_marker_;
AsyncMarker dart_async_marker_;
- intptr_t total_parameter_count_;
- intptr_t required_parameter_count_;
+ intptr_t total_parameter_count_ = 0;
+ intptr_t required_parameter_count_ = 0;
private:
KernelReaderHelper* helper_;
@@ -314,7 +314,7 @@
}
TokenPosition position_;
- uint8_t flags_;
+ uint8_t flags_ = 0;
StringIndex name_index_;
private:
@@ -373,9 +373,9 @@
TokenPosition position_;
TokenPosition equals_position_;
- uint8_t flags_;
+ uint8_t flags_ = 0;
StringIndex name_index_;
- intptr_t annotation_count_;
+ intptr_t annotation_count_ = 0;
private:
KernelReaderHelper* helper_;
@@ -452,9 +452,9 @@
NameIndex canonical_name_;
TokenPosition position_;
TokenPosition end_position_;
- uint8_t flags_;
- intptr_t source_uri_index_;
- intptr_t annotation_count_;
+ uint8_t flags_ = 0;
+ intptr_t source_uri_index_ = 0;
+ intptr_t annotation_count_ = 0;
private:
KernelReaderHelper* helper_;
@@ -542,9 +542,9 @@
TokenPosition position_;
TokenPosition end_position_;
Kind kind_;
- uint8_t flags_;
- intptr_t source_uri_index_;
- intptr_t annotation_count_;
+ uint8_t flags_ = 0;
+ intptr_t source_uri_index_ = 0;
+ intptr_t annotation_count_ = 0;
// Only valid if the 'isForwardingStub' flag is set.
NameIndex forwarding_stub_super_target_;
@@ -606,9 +606,9 @@
TokenPosition start_position_;
TokenPosition position_;
TokenPosition end_position_;
- uint8_t flags_;
- intptr_t source_uri_index_;
- intptr_t annotation_count_;
+ uint8_t flags_ = 0;
+ intptr_t source_uri_index_ = 0;
+ intptr_t annotation_count_ = 0;
private:
KernelReaderHelper* helper_;
@@ -679,10 +679,10 @@
TokenPosition position_;
TokenPosition end_position_;
StringIndex name_index_;
- intptr_t source_uri_index_;
- intptr_t annotation_count_;
- intptr_t procedure_count_;
- uint8_t flags_;
+ intptr_t source_uri_index_ = 0;
+ intptr_t annotation_count_ = 0;
+ intptr_t procedure_count_ = 0;
+ uint8_t flags_ = 0;
private:
KernelReaderHelper* helper_;
@@ -741,10 +741,10 @@
bool IsExternal() const { return (flags_ & kExternal) != 0; }
bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; }
- uint8_t flags_;
+ uint8_t flags_ = 0;
NameIndex canonical_name_;
StringIndex name_index_;
- intptr_t source_uri_index_;
+ intptr_t source_uri_index_ = 0;
private:
KernelReaderHelper* helper_;
@@ -775,7 +775,7 @@
};
explicit LibraryDependencyHelper(KernelReaderHelper* helper)
- : annotation_count_(0), helper_(helper), next_read_(kFileOffset) {}
+ : helper_(helper), next_read_(kFileOffset) {}
void ReadUntilIncluding(Field field) {
ReadUntilExcluding(static_cast<Field>(static_cast<int>(field) + 1));
@@ -783,10 +783,10 @@
void ReadUntilExcluding(Field field);
- uint8_t flags_;
+ uint8_t flags_ = 0;
StringIndex name_index_;
NameIndex target_library_canonical_name_;
- intptr_t annotation_count_;
+ intptr_t annotation_count_ = 0;
private:
KernelReaderHelper* helper_;
@@ -803,6 +803,11 @@
const char* tag,
bool precompiler_only);
+#if defined(DEBUG)
+ static void VerifyMetadataMappings(
+ const ExternalTypedData& metadata_mappings);
+#endif
+
protected:
// Look for metadata mapping with node offset greater or equal than the given.
intptr_t FindMetadataMapping(intptr_t node_offset);
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index dde3667..10f5dd6 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -390,6 +390,18 @@
: Object::dynamic_type().raw()));
scope_->InsertParameterAt(i, variable);
}
+ // Callbacks need try/catch variables.
+ if (function.IsFfiTrampoline() &&
+ function.FfiCallbackTarget() != Function::null()) {
+ current_function_async_marker_ = FunctionNodeHelper::kSync;
+ ++depth_.try_;
+ AddTryVariables();
+ --depth_.try_;
+ ++depth_.catch_;
+ AddCatchVariables();
+ FinalizeCatchVariables();
+ --depth_.catch_;
+ }
break;
case RawFunction::kSignatureFunction:
case RawFunction::kIrregexpFunction:
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index da82ceb..d42a3cc 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -258,9 +258,7 @@
bool Compiler::CanOptimizeFunction(Thread* thread, const Function& function) {
#if !defined(PRODUCT)
- Isolate* isolate = thread->isolate();
- if (isolate->debugger()->IsStepping() ||
- isolate->debugger()->HasBreakpoint(function, thread->zone())) {
+ if (Debugger::IsDebugging(thread, function)) {
// We cannot set breakpoints and single step in optimized code,
// so do not optimize the function. Bump usage counter down to avoid
// repeatedly entering the runtime for an optimization attempt.
@@ -1110,16 +1108,27 @@
void Compiler::ComputeLocalVarDescriptors(const Code& code) {
ASSERT(!code.is_optimized());
const Function& function = Function::Handle(code.function());
- ParsedFunction* parsed_function = new ParsedFunction(
- Thread::Current(), Function::ZoneHandle(function.raw()));
ASSERT(code.var_descriptors() == Object::null());
// IsIrregexpFunction have eager var descriptors generation.
ASSERT(!function.IsIrregexpFunction());
+ if (function.is_declared_in_bytecode()) {
+ auto& var_descs = LocalVarDescriptors::Handle();
+ if (function.HasBytecode()) {
+ const auto& bytecode = Bytecode::Handle(function.bytecode());
+ var_descs = bytecode.GetLocalVarDescriptors();
+ } else {
+ var_descs = Object::empty_var_descriptors().raw();
+ }
+ code.set_var_descriptors(var_descs);
+ return;
+ }
// In background compilation, parser can produce 'errors": bailouts
// if state changed while compiling in background.
CompilerState state(Thread::Current());
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
+ ParsedFunction* parsed_function = new ParsedFunction(
+ Thread::Current(), Function::ZoneHandle(function.raw()));
ZoneGrowableArray<const ICData*>* ic_data_array =
new ZoneGrowableArray<const ICData*>();
ZoneGrowableArray<intptr_t>* context_level_array =
diff --git a/runtime/vm/compiler/offsets_extractor.cc b/runtime/vm/compiler/offsets_extractor.cc
new file mode 100644
index 0000000..ec0c866
--- /dev/null
+++ b/runtime/vm/compiler/offsets_extractor.cc
@@ -0,0 +1,103 @@
+// 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.
+
+#include <iostream>
+
+#include "vm/compiler/runtime_api.h"
+#include "vm/compiler/runtime_offsets_list.h"
+#include "vm/dart_entry.h"
+#include "vm/longjump.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/symbols.h"
+#include "vm/timeline.h"
+
+#if defined(TARGET_ARCH_ARM)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM)"
+#elif defined(TARGET_ARCH_X64)
+#define ARCH_DEF "defined(TARGET_ARCH_X64)"
+#elif defined(TARGET_ARCH_IA32)
+#define ARCH_DEF "defined(TARGET_ARCH_IA32)"
+#elif defined(TARGET_ARCH_ARM64)
+#define ARCH_DEF "defined(TARGET_ARCH_ARM64)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)"
+#elif defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+#define ARCH_DEF "defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)"
+#else
+#error Unknown architecture
+#endif
+
+namespace dart {
+
+void Assert::Fail(const char* format, ...) {
+ abort();
+}
+
+class OffsetsExtractor : public AllStatic {
+ public:
+ static void DumpOffsets() {
+#define PRINT_FIELD_OFFSET(Class, Name) \
+ std::cout << "static constexpr dart::word " #Class "_" #Name " = " \
+ << Class::Name() << ";\n";
+
+#define PRINT_ARRAY_LAYOUT(Class, Name) \
+ std::cout << "static constexpr dart::word " #Class \
+ "_elements_start_offset = " \
+ << Class::ArrayLayout::elements_start_offset() << ";\n"; \
+ std::cout << "static constexpr dart::word " #Class "_element_size = " \
+ << Class::ArrayLayout::kElementSize << ";\n";
+
+#define PRINT_ARRAY_STRUCTFIELD_OFFSET(Class, Name, ElementOffsetName, \
+ FieldOffset)
+
+#define PRINT_SIZEOF(Class, Name, What) \
+ std::cout << "static constexpr dart::word " #Class "_" #Name " = " \
+ << sizeof(What) << ";\n";
+
+#define PRINT_RANGE(Class, Name, Type, First, Last, Filter) \
+ { \
+ auto filter = Filter; \
+ bool comma = false; \
+ std::cout << "static dart::word " #Class "_" #Name "[] = {"; \
+ for (intptr_t i = static_cast<intptr_t>(First); \
+ i <= static_cast<intptr_t>(Last); i++) { \
+ auto v = static_cast<Type>(i); \
+ std::cout << (comma ? ", " : "") << (filter(v) ? Class::Name(v) : -1); \
+ comma = true; \
+ } \
+ std::cout << "};\n"; \
+ }
+
+#define PRINT_CONSTANT(Class, Name) \
+ std::cout << "static constexpr dart::word " #Class "_" #Name " = " \
+ << Class::Name << ";\n";
+
+#define PRECOMP_NO_CHECK(Code) Code
+
+ OFFSETS_LIST(PRINT_FIELD_OFFSET, PRINT_ARRAY_LAYOUT,
+ PRINT_ARRAY_STRUCTFIELD_OFFSET, PRINT_SIZEOF, PRINT_RANGE,
+ PRINT_CONSTANT, PRECOMP_NO_CHECK)
+
+#undef PRINT_FIELD_OFFSET
+#undef PRINT_ARRAY_LAYOUT
+#undef PRINT_ARRAY_STRUCTFIELD_OFFSET
+#undef PRINT_SIZEOF
+#undef PRINT_RANGE
+#undef PRINT_CONSTANT
+#undef PRECOMP_NO_CHECK
+ }
+};
+
+} // namespace dart
+
+int main(int argc, char* argv[]) {
+ std::cout << "#if " << ARCH_DEF << std::endl;
+ dart::OffsetsExtractor::DumpOffsets();
+ std::cout << "#endif // " << ARCH_DEF << std::endl;
+ return 0;
+}
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 6fc48f4..ffd7255 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -42,6 +42,7 @@
V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d) \
V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e) \
V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54) \
+ V(ByteData, ., ByteDataFactory, 0x0) \
V(_ByteDataView, get:offsetInBytes, ByteDataViewOffsetInBytes, 0x0) \
V(_ByteDataView, get:_typedData, ByteDataViewTypedData, 0x0) \
V(_TypedListView, get:offsetInBytes, TypedDataViewOffsetInBytes, 0x0) \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 758e065..c5a4a53 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -500,6 +500,7 @@
V(Thread, top_resource_offset) \
V(Thread, vm_tag_offset) \
V(Thread, safepoint_state_offset) \
+ V(Thread, callback_code_offset) \
V(TimelineStream, enabled_offset) \
V(TwoByteString, data_offset) \
V(Type, arguments_offset) \
@@ -582,6 +583,10 @@
word Thread::array_write_barrier_entry_point_offset() {
return dart::Thread::array_write_barrier_entry_point_offset();
}
+
+word Thread::verify_callback_isolate_entry_point_offset() {
+ return dart::Thread::verify_callback_entry_offset();
+}
#endif // !defined(TARGET_ARCH_DBC)
#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
@@ -723,7 +728,8 @@
}
#endif // !defined(PRODUCT)
-const word ClassTable::kSizeOfClassPairLog2 = dart::kSizeOfClassPairLog2;
+const word ClassTable::kSizeOfClassPairLog2 =
+ dart::ClassTable::kSizeOfClassPairLog2;
const intptr_t Instructions::kPolymorphicEntryOffset =
dart::Instructions::kPolymorphicEntryOffset;
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 29ff5ba..24ce301 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -572,6 +572,7 @@
static word write_barrier_wrappers_thread_offset(intptr_t regno);
static word array_write_barrier_entry_point_offset();
static word write_barrier_entry_point_offset();
+ static word verify_callback_isolate_entry_point_offset();
static word vm_tag_offset();
static uword vm_tag_compiled_id();
@@ -583,6 +584,8 @@
static uword native_execution_state();
static uword generated_execution_state();
+ static word callback_code_offset();
+
#if !defined(TARGET_ARCH_DBC)
static word write_barrier_code_offset();
static word array_write_barrier_code_offset();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
new file mode 100644
index 0000000..4540195
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -0,0 +1,1343 @@
+// 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.
+#ifndef RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
+
+#include "platform/globals.h"
+
+// The constants below correspond to the macros in runtime_offsets_list.h.
+
+// This file was generated by run_offsets_extractor.sh. It's checked in, rather
+// than being generated as part of the build, because simarm_x64 needs 32-bit
+// arm offsets, but is built on a 64-bit machine and offsets_extractor only
+// extracts offsets for the host architecture. This file needs to be regenerated
+// when the offsets change, which is usually detected by CheckOffsets() in
+// dart.cc.
+
+#if defined(TARGET_ARCH_ARM)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 20;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 48;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::word Thread_active_exception_offset = 612;
+static constexpr dart::word Thread_active_stacktrace_offset = 616;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::word Thread_dart_stream_offset = 644;
+static constexpr dart::word Thread_deoptimize_entry_offset = 232;
+static constexpr dart::word Thread_deoptimize_stub_offset = 164;
+static constexpr dart::word Thread_double_abs_address_offset = 264;
+static constexpr dart::word Thread_double_negate_address_offset = 260;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::word Thread_execution_state_offset = 628;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::word Thread_float_absolute_address_offset = 276;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 268;
+static constexpr dart::word Thread_float_zerow_address_offset = 280;
+static constexpr dart::word Thread_global_object_pool_offset = 620;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+ 128;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 240;
+static constexpr dart::word
+ Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+ 140;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::word Thread_resume_pc_offset = 624;
+static constexpr dart::word Thread_safepoint_state_offset = 632;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_code_offset = 108;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_verify_callback_entry_offset = 236;
+static constexpr dart::word Thread_callback_code_offset = 636;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+ 576, 580, 584, 588, 592, -1, 596, 600, 604, 608, -1, -1, -1, -1, -1, -1};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif // defined(TARGET_ARCH_ARM)
+
+#if defined(TARGET_ARCH_X64)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 32;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 96;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::word Thread_active_exception_offset = 1232;
+static constexpr dart::word Thread_active_stacktrace_offset = 1240;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::word Thread_dart_stream_offset = 1296;
+static constexpr dart::word Thread_deoptimize_entry_offset = 456;
+static constexpr dart::word Thread_deoptimize_stub_offset = 320;
+static constexpr dart::word Thread_double_abs_address_offset = 520;
+static constexpr dart::word Thread_double_negate_address_offset = 512;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::word Thread_execution_state_offset = 1264;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::word Thread_float_absolute_address_offset = 544;
+static constexpr dart::word Thread_float_negate_address_offset = 536;
+static constexpr dart::word Thread_float_not_address_offset = 528;
+static constexpr dart::word Thread_float_zerow_address_offset = 552;
+static constexpr dart::word Thread_global_object_pool_offset = 1248;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+ 248;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 472;
+static constexpr dart::word
+ Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+ 272;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::word Thread_resume_pc_offset = 1256;
+static constexpr dart::word Thread_safepoint_state_offset = 1272;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_code_offset = 208;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_verify_callback_entry_offset = 464;
+static constexpr dart::word Thread_callback_code_offset = 1280;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+ 1144, 1152, 1160, 1168, -1, -1, 1176, 1184,
+ 1192, 1200, 1208, -1, 1216, 1224, -1, -1};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif // defined(TARGET_ARCH_X64)
+
+#if defined(TARGET_ARCH_IA32)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 48;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 284;
+static constexpr dart::word Thread_active_exception_offset = 576;
+static constexpr dart::word Thread_active_stacktrace_offset = 580;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 112;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 196;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 244;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 200;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 132;
+static constexpr dart::word Thread_dart_stream_offset = 608;
+static constexpr dart::word Thread_deoptimize_entry_offset = 232;
+static constexpr dart::word Thread_deoptimize_stub_offset = 164;
+static constexpr dart::word Thread_double_abs_address_offset = 264;
+static constexpr dart::word Thread_double_negate_address_offset = 260;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 184;
+static constexpr dart::word Thread_execution_state_offset = 592;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 188;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 120;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 116;
+static constexpr dart::word Thread_float_absolute_address_offset = 276;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 268;
+static constexpr dart::word Thread_float_zerow_address_offset = 280;
+static constexpr dart::word Thread_global_object_pool_offset = 584;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 156;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 248;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+ 128;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 124;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 168;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 172;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 180;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 220;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 224;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 152;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 240;
+static constexpr dart::word
+ Thread_null_error_shared_with_fpu_regs_entry_point_offset = 208;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+ 140;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_entry_point_offset = 204;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_stub_offset = 136;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 252;
+static constexpr dart::word Thread_resume_pc_offset = 588;
+static constexpr dart::word Thread_safepoint_state_offset = 596;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 176;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 216;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 148;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 212;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 144;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_code_offset = 108;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 192;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_verify_callback_entry_offset = 236;
+static constexpr dart::word Thread_callback_code_offset = 600;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif // defined(TARGET_ARCH_IA32)
+
+#if defined(TARGET_ARCH_ARM64)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 28;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 8;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 96;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 560;
+static constexpr dart::word Thread_active_exception_offset = 1320;
+static constexpr dart::word Thread_active_stacktrace_offset = 1328;
+static constexpr dart::word Thread_array_write_barrier_code_offset = 216;
+static constexpr dart::word Thread_array_write_barrier_entry_point_offset = 384;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 480;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_call_to_runtime_entry_point_offset = 392;
+static constexpr dart::word Thread_call_to_runtime_stub_offset = 256;
+static constexpr dart::word Thread_dart_stream_offset = 1384;
+static constexpr dart::word Thread_deoptimize_entry_offset = 456;
+static constexpr dart::word Thread_deoptimize_stub_offset = 320;
+static constexpr dart::word Thread_double_abs_address_offset = 520;
+static constexpr dart::word Thread_double_negate_address_offset = 512;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_enter_safepoint_stub_offset = 360;
+static constexpr dart::word Thread_execution_state_offset = 1352;
+static constexpr dart::word Thread_exit_safepoint_stub_offset = 368;
+static constexpr dart::word Thread_fix_allocation_stub_code_offset = 232;
+static constexpr dart::word Thread_fix_callers_target_code_offset = 224;
+static constexpr dart::word Thread_float_absolute_address_offset = 544;
+static constexpr dart::word Thread_float_negate_address_offset = 536;
+static constexpr dart::word Thread_float_not_address_offset = 528;
+static constexpr dart::word Thread_float_zerow_address_offset = 552;
+static constexpr dart::word Thread_global_object_pool_offset = 1336;
+static constexpr dart::word Thread_ic_lookup_through_code_stub_offset = 304;
+static constexpr dart::word Thread_interpret_call_entry_point_offset = 488;
+static constexpr dart::word Thread_invoke_dart_code_from_bytecode_stub_offset =
+ 248;
+static constexpr dart::word Thread_invoke_dart_code_stub_offset = 240;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_lazy_deopt_from_return_stub_offset = 328;
+static constexpr dart::word Thread_lazy_deopt_from_throw_stub_offset = 336;
+static constexpr dart::word Thread_lazy_specialize_type_test_stub_offset = 352;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_megamorphic_call_checked_entry_offset = 432;
+static constexpr dart::word Thread_monomorphic_miss_entry_offset = 440;
+static constexpr dart::word Thread_monomorphic_miss_stub_offset = 296;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 472;
+static constexpr dart::word
+ Thread_null_error_shared_with_fpu_regs_entry_point_offset = 408;
+static constexpr dart::word Thread_null_error_shared_with_fpu_regs_stub_offset =
+ 272;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_entry_point_offset = 400;
+static constexpr dart::word
+ Thread_null_error_shared_without_fpu_regs_stub_offset = 264;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 496;
+static constexpr dart::word Thread_resume_pc_offset = 1344;
+static constexpr dart::word Thread_safepoint_state_offset = 1360;
+static constexpr dart::word Thread_slow_type_test_stub_offset = 344;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_entry_point_offset = 424;
+static constexpr dart::word
+ Thread_stack_overflow_shared_with_fpu_regs_stub_offset = 288;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_entry_point_offset = 416;
+static constexpr dart::word
+ Thread_stack_overflow_shared_without_fpu_regs_stub_offset = 280;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_code_offset = 208;
+static constexpr dart::word Thread_write_barrier_entry_point_offset = 376;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_verify_callback_entry_offset = 464;
+static constexpr dart::word Thread_callback_code_offset = 1368;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static dart::word Thread_write_barrier_wrappers_thread_offset[] = {
+ 1144, 1152, 1160, 1168, 1176, 1184, 1192, 1200, 1208, 1216, 1224,
+ 1232, 1240, 1248, 1256, -1, -1, -1, -1, 1264, 1272, 1280,
+ 1288, 1296, 1304, 1312, -1, -1, -1, -1, -1, -1};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif // defined(TARGET_ARCH_ARM64)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+static constexpr dart::word ObjectPool_elements_start_offset = 16;
+static constexpr dart::word ObjectPool_element_size = 8;
+static constexpr dart::word Array_kMaxElements = 576460752303423487;
+static constexpr dart::word Array_kMaxNewSpaceElements = 32765;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 4;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 10;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 2305843009213693951;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 32;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 48;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 16;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 8;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 40;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 24;
+static constexpr dart::word Array_data_offset = 24;
+static constexpr dart::word Array_length_offset = 16;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 8;
+static constexpr dart::word Class_declaration_type_offset = 112;
+static constexpr dart::word Class_num_type_arguments_offset = 186;
+static constexpr dart::word Class_super_type_offset = 88;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 176;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 96;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 104;
+static constexpr dart::word ClassHeapStats_state_offset = 272;
+static constexpr dart::word ClassTable_table_offset = 16;
+static constexpr dart::word Closure_context_offset = 40;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 24;
+static constexpr dart::word Closure_function_offset = 32;
+static constexpr dart::word Closure_function_type_arguments_offset = 16;
+static constexpr dart::word Closure_hash_offset = 48;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 8;
+static constexpr dart::word Code_object_pool_offset = 40;
+static constexpr dart::word Code_saved_instructions_offset = 48;
+static constexpr dart::word Code_owner_offset = 56;
+static constexpr dart::word Context_num_variables_offset = 8;
+static constexpr dart::word Context_parent_offset = 16;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 16;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 16;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 88;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 96;
+static constexpr dart::word Field_guarded_list_length_offset = 56;
+static constexpr dart::word Field_is_nullable_offset = 90;
+static constexpr dart::word Field_static_value_offset = 32;
+static constexpr dart::word Field_kind_bits_offset = 98;
+static constexpr dart::word Function_code_offset = 88;
+static constexpr dart::word Function_entry_point_offset = 8;
+static constexpr dart::word Function_unchecked_entry_point_offset = 16;
+static constexpr dart::word Function_usage_counter_offset = 132;
+static constexpr dart::word GrowableObjectArray_data_offset = 24;
+static constexpr dart::word GrowableObjectArray_length_offset = 16;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 8;
+static constexpr dart::word HeapPage_card_table_offset = 40;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 24;
+static constexpr dart::word ICData_entries_offset = 8;
+static constexpr dart::word ICData_owner_offset = 40;
+static constexpr dart::word ICData_state_bits_offset = 52;
+static constexpr dart::word ICData_receivers_static_type_offset = 32;
+static constexpr dart::word Isolate_class_table_offset = 48;
+static constexpr dart::word Isolate_current_tag_offset = 16;
+static constexpr dart::word Isolate_default_tag_offset = 24;
+static constexpr dart::word Isolate_ic_miss_code_offset = 32;
+static constexpr dart::word Isolate_object_store_offset = 40;
+static constexpr dart::word Isolate_single_step_offset = 88;
+static constexpr dart::word Isolate_user_tag_offset = 8;
+static constexpr dart::word LinkedHashMap_data_offset = 32;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 48;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 24;
+static constexpr dart::word LinkedHashMap_index_offset = 16;
+static constexpr dart::word LinkedHashMap_used_data_offset = 40;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 16;
+static constexpr dart::word MarkingStackBlock_top_offset = 8;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 32;
+static constexpr dart::word MegamorphicCache_buckets_offset = 8;
+static constexpr dart::word MegamorphicCache_mask_offset = 16;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 8;
+static constexpr dart::word NativeArguments_argv_offset = 16;
+static constexpr dart::word NativeArguments_retval_offset = 24;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 128;
+static constexpr dart::word ObjectStore_int_type_offset = 64;
+static constexpr dart::word ObjectStore_string_type_offset = 160;
+static constexpr dart::word OneByteString_data_offset = 16;
+static constexpr dart::word Pointer_c_memory_address_offset = 16;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 16;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 24;
+static constexpr dart::word SingleTargetCache_target_offset = 8;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 26;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 16;
+static constexpr dart::word StoreBufferBlock_top_offset = 8;
+static constexpr dart::word String_hash_offset = 4;
+static constexpr dart::word String_length_offset = 8;
+static constexpr dart::word SubtypeTestCache_cache_offset = 8;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 296;
+static constexpr dart::word Thread_active_exception_offset = 880;
+static constexpr dart::word Thread_active_stacktrace_offset = 888;
+static constexpr dart::word Thread_async_stack_trace_offset = 168;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 216;
+static constexpr dart::word Thread_bool_false_offset = 200;
+static constexpr dart::word Thread_bool_true_offset = 192;
+static constexpr dart::word Thread_dart_stream_offset = 944;
+static constexpr dart::word Thread_double_abs_address_offset = 256;
+static constexpr dart::word Thread_double_negate_address_offset = 248;
+static constexpr dart::word Thread_end_offset = 120;
+static constexpr dart::word Thread_execution_state_offset = 912;
+static constexpr dart::word Thread_float_absolute_address_offset = 280;
+static constexpr dart::word Thread_float_negate_address_offset = 272;
+static constexpr dart::word Thread_float_not_address_offset = 264;
+static constexpr dart::word Thread_float_zerow_address_offset = 288;
+static constexpr dart::word Thread_global_object_pool_offset = 896;
+static constexpr dart::word Thread_isolate_offset = 96;
+static constexpr dart::word Thread_marking_stack_block_offset = 144;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 208;
+static constexpr dart::word Thread_object_null_offset = 184;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 232;
+static constexpr dart::word Thread_resume_pc_offset = 904;
+static constexpr dart::word Thread_safepoint_state_offset = 920;
+static constexpr dart::word Thread_stack_limit_offset = 72;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 80;
+static constexpr dart::word Thread_store_buffer_block_offset = 136;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 128;
+static constexpr dart::word Thread_top_offset = 112;
+static constexpr dart::word Thread_top_resource_offset = 48;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 176;
+static constexpr dart::word Thread_vm_tag_offset = 160;
+static constexpr dart::word Thread_write_barrier_mask_offset = 88;
+static constexpr dart::word Thread_callback_code_offset = 928;
+static constexpr dart::word TimelineStream_enabled_offset = 16;
+static constexpr dart::word TwoByteString_data_offset = 16;
+static constexpr dart::word Type_arguments_offset = 32;
+static constexpr dart::word Type_hash_offset = 40;
+static constexpr dart::word Type_signature_offset = 48;
+static constexpr dart::word Type_type_class_id_offset = 24;
+static constexpr dart::word Type_type_state_offset = 60;
+static constexpr dart::word TypeArguments_instantiations_offset = 8;
+static constexpr dart::word TypeRef_type_offset = 24;
+static constexpr dart::word TypedDataBase_data_field_offset = 8;
+static constexpr dart::word TypedDataBase_length_offset = 16;
+static constexpr dart::word TypedDataView_data_offset = 24;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 32;
+static constexpr dart::word TypedData_data_offset = 24;
+static constexpr dart::word UserTag_tag_offset = 16;
+static constexpr dart::word Array_elements_start_offset = 24;
+static constexpr dart::word Array_element_size = 8;
+static constexpr dart::word TypeArguments_elements_start_offset = 32;
+static constexpr dart::word TypeArguments_element_size = 8;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 288;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 32;
+static dart::word Code_entry_point_offset[] = {8, 24, 16, 32};
+static dart::word Code_function_entry_point_offset[] = {8, 16};
+static constexpr dart::word Array_header_size = 24;
+static constexpr dart::word Context_header_size = 24;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 24;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 32;
+static constexpr dart::word String_InstanceSize = 16;
+static constexpr dart::word TypedData_InstanceSize = 24;
+#endif // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_64_BIT)
+
+#if defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+static constexpr dart::word ObjectPool_elements_start_offset = 8;
+static constexpr dart::word ObjectPool_element_size = 4;
+static constexpr dart::word Array_kMaxElements = 268435455;
+static constexpr dart::word Array_kMaxNewSpaceElements = 65533;
+static constexpr dart::word ClassTable_kSizeOfClassPairLog2 = 3;
+static constexpr dart::word Instructions_kMonomorphicEntryOffset = 0;
+static constexpr dart::word Instructions_kPolymorphicEntryOffset = 0;
+static constexpr dart::word HeapPage_kBytesPerCardLog2 = 9;
+static constexpr dart::word NativeEntry_kNumCallWrapperArguments = 2;
+static constexpr dart::word String_kMaxElements = 536870911;
+static constexpr dart::word SubtypeTestCache_kFunctionTypeArguments = 4;
+static constexpr dart::word SubtypeTestCache_kInstanceClassIdOrFunction = 1;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceDelayedFunctionTypeArguments = 6;
+static constexpr dart::word
+ SubtypeTestCache_kInstanceParentFunctionTypeArguments = 5;
+static constexpr dart::word SubtypeTestCache_kInstanceTypeArguments = 2;
+static constexpr dart::word SubtypeTestCache_kInstantiatorTypeArguments = 3;
+static constexpr dart::word SubtypeTestCache_kTestEntryLength = 7;
+static constexpr dart::word SubtypeTestCache_kTestResult = 0;
+static constexpr dart::word AbstractType_type_test_stub_entry_point_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_count_offset = 16;
+static constexpr dart::word ArgumentsDescriptor_first_named_entry_offset = 24;
+static constexpr dart::word ArgumentsDescriptor_named_entry_size = 8;
+static constexpr dart::word ArgumentsDescriptor_name_offset = 0;
+static constexpr dart::word ArgumentsDescriptor_position_offset = 4;
+static constexpr dart::word ArgumentsDescriptor_positional_count_offset = 20;
+static constexpr dart::word ArgumentsDescriptor_type_args_len_offset = 12;
+static constexpr dart::word Array_data_offset = 12;
+static constexpr dart::word Array_length_offset = 8;
+static constexpr dart::word Array_tags_offset = 0;
+static constexpr dart::word Array_type_arguments_offset = 4;
+static constexpr dart::word Class_declaration_type_offset = 56;
+static constexpr dart::word Class_num_type_arguments_offset = 102;
+static constexpr dart::word Class_super_type_offset = 44;
+static constexpr dart::word Class_type_arguments_field_offset_in_words_offset =
+ 92;
+static constexpr dart::word ClassHeapStats_TraceAllocationMask = 1;
+static constexpr dart::word ClassHeapStats_allocated_since_gc_new_space_offset =
+ 48;
+static constexpr dart::word
+ ClassHeapStats_allocated_size_since_gc_new_space_offset = 52;
+static constexpr dart::word ClassHeapStats_state_offset = 160;
+static constexpr dart::word ClassTable_table_offset = 8;
+static constexpr dart::word Closure_context_offset = 20;
+static constexpr dart::word Closure_delayed_type_arguments_offset = 12;
+static constexpr dart::word Closure_function_offset = 16;
+static constexpr dart::word Closure_function_type_arguments_offset = 8;
+static constexpr dart::word Closure_hash_offset = 24;
+static constexpr dart::word Closure_instantiator_type_arguments_offset = 4;
+static constexpr dart::word Code_object_pool_offset = 20;
+static constexpr dart::word Code_saved_instructions_offset = 24;
+static constexpr dart::word Code_owner_offset = 28;
+static constexpr dart::word Context_num_variables_offset = 4;
+static constexpr dart::word Context_parent_offset = 8;
+static constexpr dart::word Double_value_offset = 8;
+static constexpr dart::word ExternalOneByteString_external_data_offset = 12;
+static constexpr dart::word ExternalTwoByteString_external_data_offset = 12;
+static constexpr dart::word Float32x4_value_offset = 8;
+static constexpr dart::word Float64x2_value_offset = 8;
+static constexpr dart::word Field_guarded_cid_offset = 48;
+static constexpr dart::word Field_guarded_list_length_in_object_offset_offset =
+ 56;
+static constexpr dart::word Field_guarded_list_length_offset = 28;
+static constexpr dart::word Field_is_nullable_offset = 50;
+static constexpr dart::word Field_static_value_offset = 16;
+static constexpr dart::word Field_kind_bits_offset = 58;
+static constexpr dart::word Function_code_offset = 44;
+static constexpr dart::word Function_entry_point_offset = 4;
+static constexpr dart::word Function_unchecked_entry_point_offset = 8;
+static constexpr dart::word Function_usage_counter_offset = 76;
+static constexpr dart::word GrowableObjectArray_data_offset = 12;
+static constexpr dart::word GrowableObjectArray_length_offset = 8;
+static constexpr dart::word GrowableObjectArray_type_arguments_offset = 4;
+static constexpr dart::word HeapPage_card_table_offset = 20;
+static constexpr dart::word ICData_NumArgsTestedMask = 3;
+static constexpr dart::word ICData_NumArgsTestedShift = 0;
+static constexpr dart::word ICData_arguments_descriptor_offset = 12;
+static constexpr dart::word ICData_entries_offset = 4;
+static constexpr dart::word ICData_owner_offset = 20;
+static constexpr dart::word ICData_state_bits_offset = 28;
+static constexpr dart::word ICData_receivers_static_type_offset = 16;
+static constexpr dart::word Isolate_class_table_offset = 24;
+static constexpr dart::word Isolate_current_tag_offset = 8;
+static constexpr dart::word Isolate_default_tag_offset = 12;
+static constexpr dart::word Isolate_ic_miss_code_offset = 16;
+static constexpr dart::word Isolate_object_store_offset = 20;
+static constexpr dart::word Isolate_single_step_offset = 44;
+static constexpr dart::word Isolate_user_tag_offset = 4;
+static constexpr dart::word LinkedHashMap_data_offset = 16;
+static constexpr dart::word LinkedHashMap_deleted_keys_offset = 24;
+static constexpr dart::word LinkedHashMap_hash_mask_offset = 12;
+static constexpr dart::word LinkedHashMap_index_offset = 8;
+static constexpr dart::word LinkedHashMap_used_data_offset = 20;
+static constexpr dart::word MarkingStackBlock_pointers_offset = 8;
+static constexpr dart::word MarkingStackBlock_top_offset = 4;
+static constexpr dart::word MegamorphicCache_arguments_descriptor_offset = 16;
+static constexpr dart::word MegamorphicCache_buckets_offset = 4;
+static constexpr dart::word MegamorphicCache_mask_offset = 8;
+static constexpr dart::word Mint_value_offset = 8;
+static constexpr dart::word NativeArguments_argc_tag_offset = 4;
+static constexpr dart::word NativeArguments_argv_offset = 8;
+static constexpr dart::word NativeArguments_retval_offset = 12;
+static constexpr dart::word NativeArguments_thread_offset = 0;
+static constexpr dart::word ObjectStore_double_type_offset = 64;
+static constexpr dart::word ObjectStore_int_type_offset = 32;
+static constexpr dart::word ObjectStore_string_type_offset = 80;
+static constexpr dart::word OneByteString_data_offset = 12;
+static constexpr dart::word Pointer_c_memory_address_offset = 8;
+static constexpr dart::word SingleTargetCache_entry_point_offset = 8;
+static constexpr dart::word SingleTargetCache_lower_limit_offset = 12;
+static constexpr dart::word SingleTargetCache_target_offset = 4;
+static constexpr dart::word SingleTargetCache_upper_limit_offset = 14;
+static constexpr dart::word StoreBufferBlock_pointers_offset = 8;
+static constexpr dart::word StoreBufferBlock_top_offset = 4;
+static constexpr dart::word String_hash_offset = 8;
+static constexpr dart::word String_length_offset = 4;
+static constexpr dart::word SubtypeTestCache_cache_offset = 4;
+static constexpr dart::word Thread_AllocateArray_entry_point_offset = 152;
+static constexpr dart::word Thread_active_exception_offset = 444;
+static constexpr dart::word Thread_active_stacktrace_offset = 448;
+static constexpr dart::word Thread_async_stack_trace_offset = 84;
+static constexpr dart::word
+ Thread_auto_scope_native_wrapper_entry_point_offset = 112;
+static constexpr dart::word Thread_bool_false_offset = 104;
+static constexpr dart::word Thread_bool_true_offset = 100;
+static constexpr dart::word Thread_dart_stream_offset = 476;
+static constexpr dart::word Thread_double_abs_address_offset = 132;
+static constexpr dart::word Thread_double_negate_address_offset = 128;
+static constexpr dart::word Thread_end_offset = 60;
+static constexpr dart::word Thread_execution_state_offset = 460;
+static constexpr dart::word Thread_float_absolute_address_offset = 144;
+static constexpr dart::word Thread_float_negate_address_offset = 140;
+static constexpr dart::word Thread_float_not_address_offset = 136;
+static constexpr dart::word Thread_float_zerow_address_offset = 148;
+static constexpr dart::word Thread_global_object_pool_offset = 452;
+static constexpr dart::word Thread_isolate_offset = 48;
+static constexpr dart::word Thread_marking_stack_block_offset = 72;
+static constexpr dart::word Thread_no_scope_native_wrapper_entry_point_offset =
+ 108;
+static constexpr dart::word Thread_object_null_offset = 96;
+static constexpr dart::word Thread_predefined_symbols_address_offset = 120;
+static constexpr dart::word Thread_resume_pc_offset = 456;
+static constexpr dart::word Thread_safepoint_state_offset = 464;
+static constexpr dart::word Thread_stack_limit_offset = 36;
+static constexpr dart::word Thread_stack_overflow_flags_offset = 40;
+static constexpr dart::word Thread_store_buffer_block_offset = 68;
+static constexpr dart::word Thread_top_exit_frame_info_offset = 64;
+static constexpr dart::word Thread_top_offset = 56;
+static constexpr dart::word Thread_top_resource_offset = 24;
+static constexpr dart::word Thread_unboxed_int64_runtime_arg_offset = 88;
+static constexpr dart::word Thread_vm_tag_offset = 80;
+static constexpr dart::word Thread_write_barrier_mask_offset = 44;
+static constexpr dart::word Thread_callback_code_offset = 468;
+static constexpr dart::word TimelineStream_enabled_offset = 8;
+static constexpr dart::word TwoByteString_data_offset = 12;
+static constexpr dart::word Type_arguments_offset = 16;
+static constexpr dart::word Type_hash_offset = 20;
+static constexpr dart::word Type_signature_offset = 24;
+static constexpr dart::word Type_type_class_id_offset = 12;
+static constexpr dart::word Type_type_state_offset = 32;
+static constexpr dart::word TypeArguments_instantiations_offset = 4;
+static constexpr dart::word TypeRef_type_offset = 12;
+static constexpr dart::word TypedDataBase_data_field_offset = 4;
+static constexpr dart::word TypedDataBase_length_offset = 8;
+static constexpr dart::word TypedDataView_data_offset = 12;
+static constexpr dart::word TypedDataView_offset_in_bytes_offset = 16;
+static constexpr dart::word TypedData_data_offset = 12;
+static constexpr dart::word UserTag_tag_offset = 8;
+static constexpr dart::word Array_elements_start_offset = 12;
+static constexpr dart::word Array_element_size = 4;
+static constexpr dart::word TypeArguments_elements_start_offset = 16;
+static constexpr dart::word TypeArguments_element_size = 4;
+static constexpr dart::word ClassTable_elements_start_offset = 0;
+static constexpr dart::word ClassTable_element_size = 168;
+static constexpr dart::word ClassTable_class_heap_stats_table_offset = 16;
+static dart::word Code_entry_point_offset[] = {4, 12, 8, 16};
+static dart::word Code_function_entry_point_offset[] = {4, 8};
+static constexpr dart::word Array_header_size = 12;
+static constexpr dart::word Context_header_size = 12;
+static constexpr dart::word Double_InstanceSize = 16;
+static constexpr dart::word Float32x4_InstanceSize = 24;
+static constexpr dart::word Float64x2_InstanceSize = 24;
+static constexpr dart::word Instructions_UnalignedHeaderSize = 16;
+static constexpr dart::word Int32x4_InstanceSize = 24;
+static constexpr dart::word Mint_InstanceSize = 16;
+static constexpr dart::word NativeArguments_StructSize = 16;
+static constexpr dart::word String_InstanceSize = 12;
+static constexpr dart::word TypedData_InstanceSize = 12;
+#endif // defined(TARGET_ARCH_DBC) && defined(TARGET_ARCH_IS_32_BIT)
+
+#endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
new file mode 100644
index 0000000..6882e1c
--- /dev/null
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -0,0 +1,267 @@
+// 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.
+
+#ifndef RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
+#define RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
+
+// Macro list of all constants that differ based on whether the architecture is
+// 32-bit or 64-bit. They are used to allow the target architecture to differ
+// from the host, like this:
+// 1) The macros correspond to constants defined throughout the VM that are
+// sized based on the *host* architecture.
+// 2) offsets_extractor.cc prints these values to runtime_offsets_extracted.h,
+// for both 32 and 64 bit architectures.
+// 3) runtime_api.h presents the runtime_offsets_extracted.h constants in a way
+// designed to look like the original constants from 1), but now namespaced
+// to dart::compiler::target, and sized based on the *target* architecture.
+// 4) Users of the constants from 1) can now just add the namespace from 3) to
+// get all their constants sized based on the target rather than the host.
+
+// FIELD(Class, Name) Offset of a field within a class.
+// ARRAY(Class, Name) Offset of the first element and the size of the elements
+// in an array of this class.
+// ARRAY_STRUCTFIELD(Class, Name, Element, Field) Offset of a field within a
+// struct in an array of that struct, relative to the start of the array.
+// SIZEOF(Class, Name, What) Size of an object.
+// RANGE(Class, Name, Type, First, Last, Filter) An array of offsets generated
+// by passing a value of the given Type in the range from First to Last to
+// Class::Name() if Filter returns true for that value.
+// CONSTANT(Class, Name) Miscellaneous constant.
+// PRECOMP_NO_CHECK(Code) Don't check this offset in the precompiled runtime.
+#define OFFSETS_LIST(FIELD, ARRAY, ARRAY_STRUCTFIELD, SIZEOF, RANGE, CONSTANT, \
+ PRECOMP_NO_CHECK) \
+ ARRAY(ObjectPool, element_offset) \
+ CONSTANT(Array, kMaxElements) \
+ CONSTANT(Array, kMaxNewSpaceElements) \
+ CONSTANT(ClassTable, kSizeOfClassPairLog2) \
+ CONSTANT(Instructions, kMonomorphicEntryOffset) \
+ CONSTANT(Instructions, kPolymorphicEntryOffset) \
+ CONSTANT(HeapPage, kBytesPerCardLog2) \
+ CONSTANT(NativeEntry, kNumCallWrapperArguments) \
+ CONSTANT(String, kMaxElements) \
+ CONSTANT(SubtypeTestCache, kFunctionTypeArguments) \
+ CONSTANT(SubtypeTestCache, kInstanceClassIdOrFunction) \
+ CONSTANT(SubtypeTestCache, kInstanceDelayedFunctionTypeArguments) \
+ CONSTANT(SubtypeTestCache, kInstanceParentFunctionTypeArguments) \
+ CONSTANT(SubtypeTestCache, kInstanceTypeArguments) \
+ CONSTANT(SubtypeTestCache, kInstantiatorTypeArguments) \
+ CONSTANT(SubtypeTestCache, kTestEntryLength) \
+ CONSTANT(SubtypeTestCache, kTestResult) \
+ FIELD(AbstractType, type_test_stub_entry_point_offset) \
+ FIELD(ArgumentsDescriptor, count_offset) \
+ FIELD(ArgumentsDescriptor, first_named_entry_offset) \
+ FIELD(ArgumentsDescriptor, named_entry_size) \
+ FIELD(ArgumentsDescriptor, name_offset) \
+ FIELD(ArgumentsDescriptor, position_offset) \
+ FIELD(ArgumentsDescriptor, positional_count_offset) \
+ FIELD(ArgumentsDescriptor, type_args_len_offset) \
+ FIELD(Array, data_offset) \
+ FIELD(Array, length_offset) \
+ FIELD(Array, tags_offset) \
+ FIELD(Array, type_arguments_offset) \
+ FIELD(Class, declaration_type_offset) \
+ FIELD(Class, num_type_arguments_offset) \
+ FIELD(Class, super_type_offset) \
+ FIELD(Class, type_arguments_field_offset_in_words_offset) \
+ NOT_IN_PRODUCT(FIELD(ClassHeapStats, TraceAllocationMask)) \
+ NOT_IN_PRODUCT(FIELD(ClassHeapStats, allocated_since_gc_new_space_offset)) \
+ NOT_IN_PRODUCT( \
+ FIELD(ClassHeapStats, allocated_size_since_gc_new_space_offset)) \
+ NOT_IN_PRODUCT(FIELD(ClassHeapStats, state_offset)) \
+ FIELD(ClassTable, table_offset) \
+ FIELD(Closure, context_offset) \
+ FIELD(Closure, delayed_type_arguments_offset) \
+ FIELD(Closure, function_offset) \
+ FIELD(Closure, function_type_arguments_offset) \
+ FIELD(Closure, hash_offset) \
+ FIELD(Closure, instantiator_type_arguments_offset) \
+ FIELD(Code, object_pool_offset) \
+ FIELD(Code, saved_instructions_offset) \
+ FIELD(Code, owner_offset) \
+ FIELD(Context, num_variables_offset) \
+ FIELD(Context, parent_offset) \
+ FIELD(Double, value_offset) \
+ FIELD(ExternalOneByteString, external_data_offset) \
+ FIELD(ExternalTwoByteString, external_data_offset) \
+ FIELD(Float32x4, value_offset) \
+ FIELD(Float64x2, value_offset) \
+ PRECOMP_NO_CHECK(FIELD(Field, guarded_cid_offset)) \
+ PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_in_object_offset_offset)) \
+ PRECOMP_NO_CHECK(FIELD(Field, guarded_list_length_offset)) \
+ PRECOMP_NO_CHECK(FIELD(Field, is_nullable_offset)) \
+ FIELD(Field, static_value_offset) \
+ PRECOMP_NO_CHECK(FIELD(Field, kind_bits_offset)) \
+ FIELD(Function, code_offset) \
+ FIELD(Function, entry_point_offset) \
+ FIELD(Function, unchecked_entry_point_offset) \
+ PRECOMP_NO_CHECK(FIELD(Function, usage_counter_offset)) \
+ FIELD(GrowableObjectArray, data_offset) \
+ FIELD(GrowableObjectArray, length_offset) \
+ FIELD(GrowableObjectArray, type_arguments_offset) \
+ FIELD(HeapPage, card_table_offset) \
+ FIELD(ICData, NumArgsTestedMask) \
+ FIELD(ICData, NumArgsTestedShift) \
+ FIELD(ICData, arguments_descriptor_offset) \
+ FIELD(ICData, entries_offset) \
+ PRECOMP_NO_CHECK(FIELD(ICData, owner_offset)) \
+ PRECOMP_NO_CHECK(FIELD(ICData, state_bits_offset)) \
+ NOT_IN_PRECOMPILED_RUNTIME(FIELD(ICData, receivers_static_type_offset)) \
+ FIELD(Isolate, class_table_offset) \
+ FIELD(Isolate, current_tag_offset) \
+ FIELD(Isolate, default_tag_offset) \
+ FIELD(Isolate, ic_miss_code_offset) \
+ FIELD(Isolate, object_store_offset) \
+ NOT_IN_PRODUCT(FIELD(Isolate, single_step_offset)) \
+ FIELD(Isolate, user_tag_offset) \
+ FIELD(LinkedHashMap, data_offset) \
+ FIELD(LinkedHashMap, deleted_keys_offset) \
+ FIELD(LinkedHashMap, hash_mask_offset) \
+ FIELD(LinkedHashMap, index_offset) \
+ FIELD(LinkedHashMap, used_data_offset) \
+ FIELD(MarkingStackBlock, pointers_offset) \
+ FIELD(MarkingStackBlock, top_offset) \
+ FIELD(MegamorphicCache, arguments_descriptor_offset) \
+ FIELD(MegamorphicCache, buckets_offset) \
+ FIELD(MegamorphicCache, mask_offset) \
+ FIELD(Mint, value_offset) \
+ FIELD(NativeArguments, argc_tag_offset) \
+ FIELD(NativeArguments, argv_offset) \
+ FIELD(NativeArguments, retval_offset) \
+ FIELD(NativeArguments, thread_offset) \
+ FIELD(ObjectStore, double_type_offset) \
+ FIELD(ObjectStore, int_type_offset) \
+ FIELD(ObjectStore, string_type_offset) \
+ FIELD(OneByteString, data_offset) \
+ FIELD(Pointer, c_memory_address_offset) \
+ FIELD(SingleTargetCache, entry_point_offset) \
+ FIELD(SingleTargetCache, lower_limit_offset) \
+ FIELD(SingleTargetCache, target_offset) \
+ FIELD(SingleTargetCache, upper_limit_offset) \
+ FIELD(StoreBufferBlock, pointers_offset) \
+ FIELD(StoreBufferBlock, top_offset) \
+ FIELD(String, hash_offset) \
+ FIELD(String, length_offset) \
+ FIELD(SubtypeTestCache, cache_offset) \
+ FIELD(Thread, AllocateArray_entry_point_offset) \
+ FIELD(Thread, active_exception_offset) \
+ FIELD(Thread, active_stacktrace_offset) \
+ NOT_IN_DBC(FIELD(Thread, array_write_barrier_code_offset)) \
+ NOT_IN_DBC(FIELD(Thread, array_write_barrier_entry_point_offset)) \
+ FIELD(Thread, async_stack_trace_offset) \
+ FIELD(Thread, auto_scope_native_wrapper_entry_point_offset) \
+ FIELD(Thread, bool_false_offset) \
+ FIELD(Thread, bool_true_offset) \
+ NOT_IN_DBC(FIELD(Thread, call_to_runtime_entry_point_offset)) \
+ NOT_IN_DBC(FIELD(Thread, call_to_runtime_stub_offset)) \
+ FIELD(Thread, dart_stream_offset) \
+ NOT_IN_DBC(FIELD(Thread, deoptimize_entry_offset)) \
+ NOT_IN_DBC(FIELD(Thread, deoptimize_stub_offset)) \
+ FIELD(Thread, double_abs_address_offset) \
+ FIELD(Thread, double_negate_address_offset) \
+ FIELD(Thread, end_offset) \
+ NOT_IN_DBC(FIELD(Thread, enter_safepoint_stub_offset)) \
+ FIELD(Thread, execution_state_offset) \
+ NOT_IN_DBC(FIELD(Thread, exit_safepoint_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, fix_allocation_stub_code_offset)) \
+ NOT_IN_DBC(FIELD(Thread, fix_callers_target_code_offset)) \
+ FIELD(Thread, float_absolute_address_offset) \
+ FIELD(Thread, float_negate_address_offset) \
+ FIELD(Thread, float_not_address_offset) \
+ FIELD(Thread, float_zerow_address_offset) \
+ FIELD(Thread, global_object_pool_offset) \
+ NOT_IN_DBC(FIELD(Thread, ic_lookup_through_code_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, interpret_call_entry_point_offset)) \
+ NOT_IN_DBC(FIELD(Thread, invoke_dart_code_from_bytecode_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, invoke_dart_code_stub_offset)) \
+ FIELD(Thread, isolate_offset) \
+ NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_return_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, lazy_deopt_from_throw_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, lazy_specialize_type_test_stub_offset)) \
+ FIELD(Thread, marking_stack_block_offset) \
+ NOT_IN_DBC(FIELD(Thread, megamorphic_call_checked_entry_offset)) \
+ NOT_IN_DBC(FIELD(Thread, monomorphic_miss_entry_offset)) \
+ NOT_IN_DBC(FIELD(Thread, monomorphic_miss_stub_offset)) \
+ FIELD(Thread, no_scope_native_wrapper_entry_point_offset) \
+ NOT_IN_DBC( \
+ FIELD(Thread, null_error_shared_with_fpu_regs_entry_point_offset)) \
+ NOT_IN_DBC(FIELD(Thread, null_error_shared_with_fpu_regs_stub_offset)) \
+ NOT_IN_DBC( \
+ FIELD(Thread, null_error_shared_without_fpu_regs_entry_point_offset)) \
+ NOT_IN_DBC(FIELD(Thread, null_error_shared_without_fpu_regs_stub_offset)) \
+ FIELD(Thread, object_null_offset) \
+ FIELD(Thread, predefined_symbols_address_offset) \
+ FIELD(Thread, resume_pc_offset) \
+ FIELD(Thread, safepoint_state_offset) \
+ NOT_IN_DBC(FIELD(Thread, slow_type_test_stub_offset)) \
+ FIELD(Thread, stack_limit_offset) \
+ FIELD(Thread, stack_overflow_flags_offset) \
+ NOT_IN_DBC( \
+ FIELD(Thread, stack_overflow_shared_with_fpu_regs_entry_point_offset)) \
+ NOT_IN_DBC(FIELD(Thread, stack_overflow_shared_with_fpu_regs_stub_offset)) \
+ NOT_IN_DBC(FIELD(Thread, \
+ stack_overflow_shared_without_fpu_regs_entry_point_offset)) \
+ NOT_IN_DBC( \
+ FIELD(Thread, stack_overflow_shared_without_fpu_regs_stub_offset)) \
+ FIELD(Thread, store_buffer_block_offset) \
+ FIELD(Thread, top_exit_frame_info_offset) \
+ FIELD(Thread, top_offset) \
+ FIELD(Thread, top_resource_offset) \
+ FIELD(Thread, unboxed_int64_runtime_arg_offset) \
+ FIELD(Thread, vm_tag_offset) \
+ NOT_IN_DBC(FIELD(Thread, write_barrier_code_offset)) \
+ NOT_IN_DBC(FIELD(Thread, write_barrier_entry_point_offset)) \
+ FIELD(Thread, write_barrier_mask_offset) \
+ NOT_IN_DBC(FIELD(Thread, verify_callback_entry_offset)) \
+ FIELD(Thread, callback_code_offset) \
+ FIELD(TimelineStream, enabled_offset) \
+ FIELD(TwoByteString, data_offset) \
+ FIELD(Type, arguments_offset) \
+ FIELD(Type, hash_offset) \
+ FIELD(Type, signature_offset) \
+ FIELD(Type, type_class_id_offset) \
+ FIELD(Type, type_state_offset) \
+ FIELD(TypeArguments, instantiations_offset) \
+ FIELD(TypeRef, type_offset) \
+ FIELD(TypedDataBase, data_field_offset) \
+ FIELD(TypedDataBase, length_offset) \
+ FIELD(TypedDataView, data_offset) \
+ FIELD(TypedDataView, offset_in_bytes_offset) \
+ FIELD(TypedData, data_offset) \
+ FIELD(UserTag, tag_offset) \
+ ARRAY(Array, element_offset) \
+ ARRAY(TypeArguments, type_at_offset) \
+ NOT_IN_PRODUCT(ARRAY(ClassTable, ClassOffsetFor)) \
+ NOT_IN_PRODUCT(ARRAY_STRUCTFIELD( \
+ ClassTable, NewSpaceCounterOffsetFor, ClassOffsetFor, \
+ ClassHeapStats::allocated_since_gc_new_space_offset())) \
+ NOT_IN_PRODUCT(ARRAY_STRUCTFIELD( \
+ ClassTable, StateOffsetFor, ClassOffsetFor, \
+ ClassHeapStats::allocated_since_gc_new_space_offset())) \
+ NOT_IN_PRODUCT(ARRAY_STRUCTFIELD( \
+ ClassTable, NewSpaceSizeOffsetFor, ClassOffsetFor, \
+ ClassHeapStats::allocated_size_since_gc_new_space_offset())) \
+ NOT_IN_PRODUCT(FIELD(ClassTable, class_heap_stats_table_offset)) \
+ RANGE(Code, entry_point_offset, CodeEntryKind, CodeEntryKind::kNormal, \
+ CodeEntryKind::kMonomorphicUnchecked, \
+ [](CodeEntryKind value) { return true; }) \
+ RANGE(Code, function_entry_point_offset, CodeEntryKind, \
+ CodeEntryKind::kNormal, CodeEntryKind::kUnchecked, \
+ [](CodeEntryKind value) { return true; }) \
+ ONLY_IN_ARM_ARM64_X64(RANGE( \
+ Thread, write_barrier_wrappers_thread_offset, Register, 0, \
+ kNumberOfCpuRegisters - 1, \
+ [](Register reg) { return (kDartAvailableCpuRegs & (1 << reg)) != 0; })) \
+ SIZEOF(Array, header_size, RawArray) \
+ SIZEOF(Context, header_size, RawContext) \
+ SIZEOF(Double, InstanceSize, RawDouble) \
+ SIZEOF(Float32x4, InstanceSize, RawFloat32x4) \
+ SIZEOF(Float64x2, InstanceSize, RawFloat64x2) \
+ SIZEOF(Instructions, UnalignedHeaderSize, RawInstructions) \
+ SIZEOF(Int32x4, InstanceSize, RawInt32x4) \
+ SIZEOF(Mint, InstanceSize, RawMint) \
+ SIZEOF(NativeArguments, StructSize, NativeArguments) \
+ SIZEOF(String, InstanceSize, RawString) \
+ SIZEOF(TypedData, InstanceSize, RawTypedData)
+
+#endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_LIST_H_
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index e82fa9f..7f4f9e2 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -274,8 +274,13 @@
RegisterSet all_registers;
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers);
+
+ __ EnterFrame((1 << FP) | (1 << LR), 0);
+ __ ReserveAlignedFrameSpace(0);
__ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
__ blx(R0);
+ __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
__ PopRegisters(all_registers);
__ Ret();
}
@@ -284,12 +289,35 @@
RegisterSet all_registers;
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers);
+
+ __ EnterFrame((1 << FP) | (1 << LR), 0);
+ __ ReserveAlignedFrameSpace(0);
__ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ blx(R0);
+ __ LeaveFrame((1 << FP) | (1 << LR), 0);
+
__ PopRegisters(all_registers);
__ Ret();
}
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+ __ EnterFrame(1 << FP | 1 << LR, 0);
+ __ ReserveAlignedFrameSpace(0);
+
+ // First argument is already set up by the caller.
+ //
+ // Second argument is the return address of the caller.
+ __ mov(CallingConventions::ArgumentRegisters[1], Operand(LR));
+ ASSERT(R2 != CallingConventions::ArgumentRegisters[0] &&
+ R2 != CallingConventions::ArgumentRegisters[1]);
+ __ LoadFromOffset(kWord, R2, THR,
+ kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+ __ blx(R2);
+
+ __ LeaveFrame(1 << FP | 1 << LR);
+ __ Ret();
+}
+
void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
Assembler* assembler) {
GenerateSharedStub(
@@ -1031,17 +1059,7 @@
__ ldr(IP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
__ Push(IP);
- // Save new context and C++ ABI callee-saved registers.
- __ PushList(kAbiPreservedCpuRegs);
-
- const DRegister firstd = EvenDRegisterOf(kAbiFirstPreservedFpuReg);
- if (TargetCPUFeatures::vfp_supported()) {
- ASSERT(2 * kAbiPreservedFpuRegCount < 16);
- // Save FPU registers. 2 D registers per Q register.
- __ vstmd(DB_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
- } else {
- __ sub(SP, SP, Operand(kAbiPreservedFpuRegCount * kFpuRegisterSize));
- }
+ __ PushNativeCalleeSavedRegisters();
// Set up THR, which caches the current thread in Dart code.
if (THR != R3) {
@@ -1072,6 +1090,8 @@
#endif
__ Push(R9);
+ __ EmitEntryFrameVerification(R9);
+
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ LoadImmediate(R9, VMTag::kDartCompiledTagId);
@@ -1135,15 +1155,8 @@
__ Pop(R4);
__ StoreToOffset(kWord, R4, THR, target::Thread::vm_tag_offset());
- // Restore C++ ABI callee-saved registers.
- if (TargetCPUFeatures::vfp_supported()) {
- // Restore FPU registers. 2 D registers per Q register.
- __ vldmd(IA_W, SP, firstd, 2 * kAbiPreservedFpuRegCount);
- } else {
- __ AddImmediate(SP, kAbiPreservedFpuRegCount * kFpuRegisterSize);
- }
- // Restore CPU registers.
- __ PopList(kAbiPreservedCpuRegs);
+ __ PopNativeCalleeSavedRegisters();
+
__ set_constant_pool_allowed(false);
// Restore the frame pointer and return.
@@ -1748,7 +1761,7 @@
EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
}
- __ LeaveDartFrameAndReturn(); // Restores correct SP.
+ __ LeaveDartFrameAndReturn(); // Restores correct SP.
}
// Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 9bee589..c431835 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -209,12 +209,14 @@
RegisterSet all_registers;
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers);
- __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+ __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0);
__ mov(CSP, SP);
__ ldr(R0, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
__ blr(R0);
- __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+ __ LeaveFrame();
+
__ PopRegisters(all_registers);
__ mov(CSP, SP);
__ Ret();
@@ -224,17 +226,37 @@
RegisterSet all_registers;
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers);
- __ mov(CallingConventions::kFirstCalleeSavedCpuReg, SP);
+
+ __ EnterFrame(0);
__ ReserveAlignedFrameSpace(0);
__ mov(CSP, SP);
__ ldr(R0, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ blr(R0);
- __ mov(SP, CallingConventions::kFirstCalleeSavedCpuReg);
+ __ LeaveFrame();
+
__ PopRegisters(all_registers);
__ mov(CSP, SP);
__ Ret();
}
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+
+ // First argument is already set up by the caller.
+ //
+ // Second argument is the return address of the caller.
+ __ mov(CallingConventions::ArgumentRegisters[1], LR);
+ __ LoadFromOffset(R2, THR,
+ kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread());
+ __ mov(CSP, SP);
+ __ blr(R2);
+ __ mov(SP, CSP);
+
+ __ LeaveFrame();
+ __ Ret();
+}
+
// R1: The extracted method.
// R4: The type_arguments_field_offset (or 0)
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -1111,20 +1133,7 @@
__ ldr(TMP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
__ Push(TMP);
- // Save the callee-saved registers.
- for (int i = kAbiFirstPreservedCpuReg; i <= kAbiLastPreservedCpuReg; i++) {
- const Register r = static_cast<Register>(i);
- // We use str instead of the Push macro because we will be pushing the PP
- // register when it is not holding a pool-pointer since we are coming from
- // C++ code.
- __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
- }
-
- // Save the bottom 64-bits of callee-saved V registers.
- for (int i = kAbiFirstPreservedFpuReg; i <= kAbiLastPreservedFpuReg; i++) {
- const VRegister r = static_cast<VRegister>(i);
- __ PushDouble(r);
- }
+ __ PushNativeCalleeSavedRegisters();
// Set up THR, which caches the current thread in Dart code.
if (THR != R3) {
@@ -1218,21 +1227,7 @@
__ Pop(R4);
__ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
- // Restore the bottom 64-bits of callee-saved V registers.
- for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
- const VRegister r = static_cast<VRegister>(i);
- __ PopDouble(r);
- }
-
- // Restore C++ ABI callee-saved registers.
- for (int i = kAbiLastPreservedCpuReg; i >= kAbiFirstPreservedCpuReg; i--) {
- Register r = static_cast<Register>(i);
- // We use ldr instead of the Pop macro because we will be popping the PP
- // register when it is not holding a pool-pointer since we are returning to
- // C++ code. We also skip the dart stack pointer SP, since we are still
- // using it as the stack pointer.
- __ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
- }
+ __ PopNativeCalleeSavedRegisters();
// Restore the frame pointer and C stack pointer and return.
__ LeaveFrame();
@@ -1806,7 +1801,7 @@
// ensure that the object is in new-space or has remembered bit set.
EnsureIsNewOrRemembered(assembler, /*preserve_registers=*/false);
}
- __ LeaveStubFrame(); // Restores correct SP.
+ __ LeaveStubFrame(); // Restores correct SP.
__ ret();
}
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 806c130..f7fdf98 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -140,20 +140,61 @@
void StubCodeCompiler::GenerateEnterSafepointStub(Assembler* assembler) {
__ pushal();
+ __ subl(SPREG, Immediate(8));
+ __ movsd(Address(SPREG, 0), XMM0);
+
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
__ movl(EAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
__ call(EAX);
+ __ LeaveFrame();
+
+ __ movsd(XMM0, Address(SPREG, 0));
+ __ addl(SPREG, Immediate(8));
__ popal();
__ ret();
}
void StubCodeCompiler::GenerateExitSafepointStub(Assembler* assembler) {
__ pushal();
+ __ subl(SPREG, Immediate(8));
+ __ movsd(Address(SPREG, 0), XMM0);
+
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
__ movl(EAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ call(EAX);
+ __ LeaveFrame();
+
+ __ movsd(XMM0, Address(SPREG, 0));
+ __ addl(SPREG, Immediate(8));
__ popal();
__ ret();
}
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+
+ // The return address needs to be the second argument to
+ // VerifyCallbackIsolate.
+ __ movl(EAX, Address(FPREG, 4));
+ __ pushl(EAX);
+
+ // Argument to the stub is callback ID, which is also the first argument to
+ // VerifyCallbackIsolate.
+ __ movl(EAX, Address(FPREG, 8));
+ __ pushl(EAX);
+
+ // Call the VerifyCallbackIsolate runtime entry.
+ __ movl(EAX,
+ Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+ __ call(EAX);
+
+ __ LeaveFrame();
+ __ ret();
+}
+
void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
Assembler* assembler) {
__ Breakpoint();
@@ -858,6 +899,10 @@
__ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
+ // In debug mode, verify that we've pushed the top exit frame info at the
+ // correct offset from FP.
+ __ EmitEntryFrameVerification();
+
// Mark that the thread is executing Dart code. Do this after initializing the
// exit link for the profiler.
__ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 91728ca..92836b2 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -204,8 +204,13 @@
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers.cpu_registers(),
all_registers.fpu_registers());
+
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
__ movq(RAX, Address(THR, kEnterSafepointRuntimeEntry.OffsetFromThread()));
__ CallCFunction(RAX);
+ __ LeaveFrame();
+
__ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
__ ret();
}
@@ -215,12 +220,31 @@
all_registers.AddAllGeneralRegisters();
__ PushRegisters(all_registers.cpu_registers(),
all_registers.fpu_registers());
+
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
__ movq(RAX, Address(THR, kExitSafepointRuntimeEntry.OffsetFromThread()));
__ CallCFunction(RAX);
+ __ LeaveFrame();
+
__ PopRegisters(all_registers.cpu_registers(), all_registers.fpu_registers());
__ ret();
}
+void StubCodeCompiler::GenerateVerifyCallbackStub(Assembler* assembler) {
+ // SP points to return address, which needs to be the second argument to
+ // VerifyCallbackIsolate.
+ __ movq(CallingConventions::kArg2Reg, Address(SPREG, 0));
+
+ __ EnterFrame(0);
+ __ ReserveAlignedFrameSpace(0);
+ __ movq(RAX,
+ Address(THR, kVerifyCallbackIsolateRuntimeEntry.OffsetFromThread()));
+ __ CallCFunction(RAX);
+ __ LeaveFrame();
+ __ ret();
+}
+
// RBX: The extracted method.
// RDX: The type_arguments_field_offset (or 0)
void StubCodeCompiler::GenerateBuildMethodExtractorStub(
@@ -1086,19 +1110,8 @@
__ pushq(RAX);
// The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
- // in sync with the code below.
-#if defined(DEBUG)
- {
- Label ok;
- __ leaq(RAX,
- Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
- target::kWordSize));
- __ cmpq(RAX, RSP);
- __ j(EQUAL, &ok);
- __ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
- __ Bind(&ok);
- }
-#endif
+ // in sync with the code above.
+ __ EmitEntryFrameVerification();
__ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
Immediate(0));
@@ -1762,7 +1775,7 @@
// Create a stub frame.
__ EnterStubFrame(); // Uses PP to access class object.
- __ pushq(R9); // Setup space on stack for return value.
+ __ pushq(R9); // Setup space on stack for return value.
__ PushObject(
CastHandle<Object>(cls)); // Push class of object to be allocated.
if (is_cls_parameterized) {
diff --git a/runtime/vm/compiler_test.cc b/runtime/vm/compiler_test.cc
index d10c8c4..8bf0e39 100644
--- a/runtime/vm/compiler_test.cc
+++ b/runtime/vm/compiler_test.cc
@@ -16,19 +16,6 @@
namespace dart {
-ISOLATE_UNIT_TEST_CASE(CompileScript) {
- const char* kScriptChars =
- "class A {\n"
- " static foo() { return 42; }\n"
- "}\n";
- String& url = String::Handle(String::New("dart-test:CompileScript"));
- String& source = String::Handle(String::New(kScriptChars));
- Script& script =
- Script::Handle(Script::New(url, source, RawScript::kScriptTag));
- Library& lib = Library::Handle(Library::CoreLibrary());
- EXPECT(CompilerTest::TestCompileScript(lib, script));
-}
-
ISOLATE_UNIT_TEST_CASE(CompileFunction) {
const char* kScriptChars =
"class A {\n"
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 8a26be6..529d96c 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -749,7 +749,7 @@
// Maximum bytecode format version supported by VM.
// The range of supported versions should include version produced by bytecode
// generator (currentBytecodeFormatVersion in pkg/vm/lib/bytecode/dbc.dart).
- static const intptr_t kMaxSupportedBytecodeFormatVersion = 7;
+ static const intptr_t kMaxSupportedBytecodeFormatVersion = 9;
enum Opcode {
#define DECLARE_BYTECODE(name, encoding, kind, op1, op2, op3) k##name,
@@ -971,20 +971,12 @@
}
}
- DART_FORCE_INLINE static bool IsCallOpcode(const KBCInstr* instr) {
+ DART_FORCE_INLINE static bool IsCallOpcode_Old(const KBCInstr* instr) {
switch (DecodeOpcode(instr)) {
case KernelBytecode::kDirectCall_Old:
case KernelBytecode::kInterfaceCall_Old:
case KernelBytecode::kUncheckedInterfaceCall_Old:
case KernelBytecode::kDynamicCall_Old:
- case KernelBytecode::kDirectCall:
- case KernelBytecode::kDirectCall_Wide:
- case KernelBytecode::kInterfaceCall:
- case KernelBytecode::kInterfaceCall_Wide:
- case KernelBytecode::kUncheckedInterfaceCall:
- case KernelBytecode::kUncheckedInterfaceCall_Wide:
- case KernelBytecode::kDynamicCall:
- case KernelBytecode::kDynamicCall_Wide:
return true;
default:
@@ -1014,7 +1006,7 @@
// to new _GrowableList<E>(0).
return kNativeCallToGrowableListArgc;
}
- ASSERT(IsCallOpcode(call));
+ ASSERT(IsCallOpcode_Old(call));
return DecodeA(call);
}
@@ -1030,6 +1022,7 @@
// Converts bytecode PC into an offset.
// For return addresses used in PcDescriptors, PC is also augmented by 1.
+ // TODO(regis): Eliminate this correction.
static intptr_t BytecodePcToOffset(uint32_t pc, bool is_return_address) {
return pc + (is_return_address ? 1 : 0);
}
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 822cab8..bf929e9 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -6,6 +6,8 @@
#include "vm/clustered_snapshot.h"
#include "vm/code_observers.h"
+#include "vm/compiler/runtime_offsets_extracted.h"
+#include "vm/compiler/runtime_offsets_list.h"
#include "vm/cpu.h"
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
@@ -22,6 +24,7 @@
#include "vm/malloc_hooks.h"
#include "vm/message_handler.h"
#include "vm/metrics.h"
+#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_id_ring.h"
#include "vm/object_store.h"
@@ -84,36 +87,40 @@
};
static void CheckOffsets() {
+ // These offsets are embedded in precompiled instructions. We need the
+ // compiler and the runtime to agree.
bool ok = true;
#define CHECK_OFFSET(expr, offset) \
if ((expr) != (offset)) { \
- OS::PrintErr("%s got %" Pd " expected %" Pd "\n", #expr, (expr), \
+ OS::PrintErr("%s got %" Pd ", %s expected %" Pd "\n", #expr, \
+ static_cast<intptr_t>(expr), #offset, \
static_cast<intptr_t>(offset)); \
ok = false; \
}
-#if defined(TARGET_ARCH_ARM)
- // These offsets are embedded in precompiled instructions. We need simarm
- // (compiler) and arm (runtime) to agree.
- CHECK_OFFSET(Thread::stack_limit_offset(), 36);
- CHECK_OFFSET(Thread::object_null_offset(), 96);
- CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 14);
- CHECK_OFFSET(Isolate::object_store_offset(), 20);
- NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 168));
-#endif
-#if defined(TARGET_ARCH_ARM64)
- // These offsets are embedded in precompiled instructions. We need simarm64
- // (compiler) and arm64 (runtime) to agree.
- CHECK_OFFSET(Thread::stack_limit_offset(), 72);
- CHECK_OFFSET(Thread::object_null_offset(), 184);
- CHECK_OFFSET(SingleTargetCache::upper_limit_offset(), 26);
- CHECK_OFFSET(Isolate::object_store_offset(), 40);
- NOT_IN_PRODUCT(CHECK_OFFSET(sizeof(ClassHeapStats), 288));
-#endif
+#define CHECK_FIELD(Class, Name) CHECK_OFFSET(Class::Name(), Class##_##Name)
+#define CHECK_ARRAY(Class, Name) \
+ CHECK_OFFSET(Class::ArrayLayout::elements_start_offset(), \
+ Class##_elements_start_offset) \
+ CHECK_OFFSET(Class::ArrayLayout::kElementSize, Class##_element_size)
+#define CHECK_ARRAY_STRUCTFIELD(Class, Name, ElementOffsetName, FieldOffset)
+#define CHECK_SIZEOF(Class, Name, What) \
+ CHECK_OFFSET(sizeof(What), Class##_##Name)
+#define CHECK_RANGE(Class, Name, Type, First, Last, Filter)
+#define CHECK_CONSTANT(Class, Name) CHECK_OFFSET(Class::Name, Class##_##Name)
+
+ OFFSETS_LIST(CHECK_FIELD, CHECK_ARRAY, CHECK_ARRAY_STRUCTFIELD, CHECK_SIZEOF,
+ CHECK_RANGE, CHECK_CONSTANT, NOT_IN_PRECOMPILED_RUNTIME)
if (!ok) {
FATAL("CheckOffsets failed.");
}
+#undef CHECK_FIELD
+#undef CHECK_ARRAY
+#undef CHECK_ARRAY_STRUCTFIELD
+#undef CHECK_SIZEOF
+#undef CHECK_RANGE
+#undef CHECK_CONSTANT
#undef CHECK_OFFSET
}
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 7f7a646..55eb9ba 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -17,6 +17,8 @@
#include "vm/dart_api_state.h"
#include "vm/dart_entry.h"
#include "vm/debugger.h"
+#include "vm/dwarf.h"
+#include "vm/elf.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
#include "vm/kernel_loader.h"
#endif
@@ -5532,7 +5534,7 @@
const char* package_config) {
API_TIMELINE_DURATION(Thread::Current());
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_CompileToKernel is unsupported.");
@@ -5564,7 +5566,7 @@
const char* package_config,
const char* multiroot_filepaths,
const char* multiroot_scheme) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_CompileSourcesToKernel is unsupported.");
@@ -5586,7 +5588,7 @@
}
DART_EXPORT Dart_KernelCompilationResult Dart_KernelListDependencies() {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
#if defined(DART_PRECOMPILED_RUNTIME)
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Dart_KernelListDependencies is unsupported.");
@@ -6050,10 +6052,11 @@
CHECK_NULL(callback);
TIMELINE_DURATION(T, Isolate, "WriteVMAOTSnapshot");
- AssemblyImageWriter image_writer(T, callback, callback_data, NULL, NULL);
- uint8_t* vm_snapshot_data_buffer = NULL;
- FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer, NULL,
- ApiReallocate, &image_writer, NULL);
+ AssemblyImageWriter image_writer(T, callback, callback_data, nullptr,
+ nullptr);
+ uint8_t* vm_snapshot_data_buffer = nullptr;
+ FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+ nullptr, ApiReallocate, &image_writer, nullptr);
writer.WriteFullSnapshot();
@@ -6062,6 +6065,60 @@
}
DART_EXPORT Dart_Handle
+Dart_CreateAppAOTSnapshotAsElf(Dart_StreamingWriteCallback callback,
+ void* callback_data) {
+#if defined(TARGET_ARCH_IA32)
+ return Api::NewError("AOT compilation is not supported on IA32.");
+#elif defined(TARGET_ARCH_DBC)
+ return Api::NewError("AOT compilation is not supported on DBC.");
+#elif defined(TARGET_OS_WINDOWS)
+ return Api::NewError("Windows cannot load ELF.");
+#elif defined(TARGET_OS_MACOS)
+ return Api::NewError("macOS/iOS cannot load ELF.");
+#elif !defined(DART_PRECOMPILER)
+ return Api::NewError(
+ "This VM was built without support for AOT compilation.");
+#else
+ DARTSCOPE(Thread::Current());
+ API_TIMELINE_DURATION(T);
+
+ uint8_t* vm_snapshot_data_buffer = nullptr;
+ uint8_t* vm_snapshot_instructions_buffer = nullptr;
+ uint8_t* isolate_snapshot_data_buffer = nullptr;
+ uint8_t* isolate_snapshot_instructions_buffer = nullptr;
+
+ NOT_IN_PRODUCT(TimelineDurationScope tds2(T, Timeline::GetIsolateStream(),
+ "WriteAppAOTSnapshot"));
+ StreamingWriteStream elf_stream(2 * MB, callback, callback_data);
+ Elf* elf = new (Z) Elf(Z, &elf_stream);
+ Dwarf* dwarf = new (Z) Dwarf(Z, nullptr, elf);
+
+ BlobImageWriter vm_image_writer(T, &vm_snapshot_instructions_buffer,
+ ApiReallocate, /* initial_size= */ 2 * MB,
+ nullptr, nullptr, nullptr, elf, dwarf);
+ BlobImageWriter isolate_image_writer(
+ T, &isolate_snapshot_instructions_buffer, ApiReallocate,
+ /* initial_size= */ 2 * MB, /* shared_data_image= */ nullptr,
+ /* shared_instructions_image= */ nullptr, nullptr, elf, dwarf);
+ FullSnapshotWriter writer(Snapshot::kFullAOT, &vm_snapshot_data_buffer,
+ &isolate_snapshot_data_buffer, ApiReallocate,
+ &vm_image_writer, &isolate_image_writer);
+
+ writer.WriteFullSnapshot();
+ elf->AddROData("_kDartVmSnapshotData", vm_snapshot_data_buffer,
+ writer.VmIsolateSnapshotSize());
+ elf->AddROData("_kDartIsolateSnapshotData", isolate_snapshot_data_buffer,
+ writer.IsolateSnapshotSize());
+ // TODO(rmacnak): Generate .debug_frame / .eh_frame / .arm.exidx to
+ // providing unwinding information.
+ dwarf->Write();
+ elf->Finalize();
+
+ return Api::Success();
+#endif
+}
+
+DART_EXPORT Dart_Handle
Dart_CreateAppAOTSnapshotAsBlobs(uint8_t** vm_snapshot_data_buffer,
intptr_t* vm_snapshot_data_size,
uint8_t** vm_snapshot_instructions_buffer,
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 0682bb9..a8c490b 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -3629,56 +3629,6 @@
return Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size);
}
-VM_UNIT_TEST_CASE(DartAPI_IsolateSetCheckedMode) {
- const char* kScriptChars =
- "int bad1() {\n"
- " int foo = 'string';\n"
- " return foo;\n"
- "}\n"
- "\n"
- "int good1() {\n"
- " int five = 5;\n"
- " return five;"
- "}\n";
-
- // Create an isolate with checked mode flags.
- Dart_IsolateFlags api_flags;
- Isolate::FlagsInitialize(&api_flags);
- api_flags.enable_asserts = true;
- char* err;
- Dart_Isolate isolate =
- Dart_CreateIsolate(NULL, NULL, bin::core_isolate_snapshot_data,
- bin::core_isolate_snapshot_instructions, NULL, NULL,
- &api_flags, NULL, &err);
- if (isolate == NULL) {
- OS::PrintErr("Creation of isolate failed '%s'\n", err);
- free(err);
- }
- EXPECT(isolate != NULL);
-
- {
- Dart_Handle result;
- Dart_EnterScope();
- Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- EXPECT_VALID(lib);
- result = Dart_FinalizeLoading(false);
- EXPECT_VALID(result);
- result = Dart_Invoke(lib, NewString("bad1"), 0, NULL);
- EXPECT_ERROR(result,
- "Unhandled exception:\n"
- "type 'String' is not a subtype of type 'int' of 'foo'");
-
- result = Dart_Invoke(lib, NewString("good1"), 0, NULL);
- EXPECT_VALID(result);
- Dart_ExitScope();
- }
-
- EXPECT(isolate != NULL);
-
- // Shutdown the isolate.
- Dart_ShutdownIsolate();
-}
-
TEST_CASE(DartAPI_DebugName) {
Dart_Handle debug_name = Dart_DebugName();
EXPECT_VALID(debug_name);
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index a4c22c3..4bd384c 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -377,22 +377,6 @@
return names.raw();
}
-intptr_t ArgumentsDescriptor::type_args_len_offset() {
- return Array::element_offset(kTypeArgsLenIndex);
-}
-
-intptr_t ArgumentsDescriptor::count_offset() {
- return Array::element_offset(kCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::positional_count_offset() {
- return Array::element_offset(kPositionalCountIndex);
-}
-
-intptr_t ArgumentsDescriptor::first_named_entry_offset() {
- return Array::element_offset(kFirstNamedEntryIndex);
-}
-
RawArray* ArgumentsDescriptor::New(intptr_t type_args_len,
intptr_t num_arguments,
const Array& optional_arguments_names) {
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 23342d3..94764a3 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -49,10 +49,20 @@
RawArray* GetArgumentNames() const;
// Generated code support.
- static intptr_t type_args_len_offset();
- static intptr_t count_offset();
- static intptr_t positional_count_offset();
- static intptr_t first_named_entry_offset();
+ static intptr_t type_args_len_offset() {
+ return Array::element_offset(kTypeArgsLenIndex);
+ }
+
+ static intptr_t count_offset() { return Array::element_offset(kCountIndex); }
+
+ static intptr_t positional_count_offset() {
+ return Array::element_offset(kPositionalCountIndex);
+ }
+
+ static intptr_t first_named_entry_offset() {
+ return Array::element_offset(kFirstNamedEntryIndex);
+ }
+
static intptr_t name_offset() { return kNameOffset * kWordSize; }
static intptr_t position_offset() { return kPositionOffset * kWordSize; }
static intptr_t named_entry_size() { return kNamedEntrySize * kWordSize; }
diff --git a/runtime/vm/dart_entry_test.cc b/runtime/vm/dart_entry_test.cc
deleted file mode 100644
index 496c1a0..0000000
--- a/runtime/vm/dart_entry_test.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include "platform/globals.h"
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/resolver.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-ISOLATE_UNIT_TEST_CASE(DartEntry) {
- const char* kScriptChars =
- "class A {\n"
- " static foo() { return 42; }\n"
- "}\n";
- String& url = String::Handle(String::New("dart-test:DartEntry"));
- String& source = String::Handle(String::New(kScriptChars));
- Script& script =
- Script::Handle(Script::New(url, source, RawScript::kScriptTag));
- Library& lib = Library::Handle(Library::CoreLibrary());
- EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::ProcessPendingClasses());
- Class& cls =
- Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
- EXPECT(!cls.IsNull()); // No ambiguity error expected.
- String& name = String::Handle(String::New("foo"));
- Function& function = Function::Handle(cls.LookupStaticFunction(name));
- EXPECT(!function.IsNull());
-
- EXPECT(CompilerTest::TestCompileFunction(function));
- EXPECT(function.HasCode());
- const Smi& retval = Smi::Handle(reinterpret_cast<RawSmi*>(
- DartEntry::InvokeFunction(function, Object::empty_array())));
- EXPECT_EQ(Smi::New(42), retval.raw());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeStatic_CompileError) {
- const char* kScriptChars =
- "class A {\n"
- " static foo() { return ++++; }\n"
- "}\n";
- String& url = String::Handle(String::New("dart-test:DartEntry"));
- String& source = String::Handle(String::New(kScriptChars));
- Script& script =
- Script::Handle(Script::New(url, source, RawScript::kScriptTag));
- Library& lib = Library::Handle(Library::CoreLibrary());
- EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::ProcessPendingClasses());
- Class& cls =
- Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
- EXPECT(!cls.IsNull()); // No ambiguity error expected.
- String& name = String::Handle(String::New("foo"));
- Function& function = Function::Handle(cls.LookupStaticFunction(name));
- EXPECT(!function.IsNull());
- const Object& retval = Object::Handle(
- DartEntry::InvokeFunction(function, Object::empty_array()));
- EXPECT(retval.IsError());
- EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-ISOLATE_UNIT_TEST_CASE(InvokeDynamic_CompileError) {
- const char* kScriptChars =
- "class A {\n"
- " foo() { return ++++; }\n"
- "}\n";
- String& url = String::Handle(String::New("dart-test:DartEntry"));
- String& source = String::Handle(String::New(kScriptChars));
- Script& script =
- Script::Handle(Script::New(url, source, RawScript::kScriptTag));
- Library& lib = Library::Handle(Library::CoreLibrary());
- EXPECT_EQ(true, CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::ProcessPendingClasses());
- Class& cls =
- Class::Handle(lib.LookupClass(String::Handle(Symbols::New(thread, "A"))));
- EXPECT(!cls.IsNull()); // No ambiguity error expected.
-
- // Invoke the constructor.
- const Instance& instance = Instance::Handle(Instance::New(cls));
- const Array& constructor_arguments = Array::Handle(Array::New(1));
- constructor_arguments.SetAt(0, instance);
- String& constructor_name = String::Handle(Symbols::New(thread, "A."));
- Function& constructor =
- Function::Handle(cls.LookupConstructor(constructor_name));
- ASSERT(!constructor.IsNull());
- DartEntry::InvokeFunction(constructor, constructor_arguments);
-
- // Call foo.
- String& name = String::Handle(String::New("foo"));
- Function& function = Function::Handle(cls.LookupDynamicFunction(name));
- EXPECT(!function.IsNull());
- const Array& args = Array::Handle(Array::New(1));
- args.SetAt(0, instance);
- const Object& retval =
- Object::Handle(DartEntry::InvokeFunction(function, args));
- EXPECT(retval.IsError());
- EXPECT_SUBSTRING("++++", Error::Cast(retval).ToErrorCString());
-}
-
-} // namespace dart
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 13e4621..639314f 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -10,6 +10,7 @@
#include "vm/code_patcher.h"
#include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/frontend/bytecode_reader.h"
#include "vm/compiler/jit/compiler.h"
#include "vm/dart_entry.h"
#include "vm/deopt_instructions.h"
@@ -66,14 +67,13 @@
url_(script.url()),
token_pos_(token_pos),
end_token_pos_(end_token_pos),
- is_resolved_(false),
next_(NULL),
conditions_(NULL),
requested_line_number_(requested_line_number),
requested_column_number_(requested_column_number),
function_(Function::null()),
- line_number_(-1),
- column_number_(-1) {
+ bytecode_token_pos_(TokenPosition::kNoSource),
+ code_token_pos_(TokenPosition::kNoSource) {
ASSERT(!script.IsNull());
ASSERT(token_pos_.IsReal());
}
@@ -86,14 +86,13 @@
url_(url.raw()),
token_pos_(TokenPosition::kNoSource),
end_token_pos_(TokenPosition::kNoSource),
- is_resolved_(false),
next_(NULL),
conditions_(NULL),
requested_line_number_(requested_line_number),
requested_column_number_(requested_column_number),
function_(Function::null()),
- line_number_(-1),
- column_number_(-1) {
+ bytecode_token_pos_(TokenPosition::kNoSource),
+ code_token_pos_(TokenPosition::kNoSource) {
ASSERT(requested_line_number_ >= 0);
}
@@ -110,7 +109,8 @@
return breakpoints() != NULL;
}
-void BreakpointLocation::SetResolved(const Function& func,
+void BreakpointLocation::SetResolved(bool in_bytecode,
+ const Function& func,
TokenPosition token_pos) {
ASSERT(!IsLatent());
ASSERT(func.script() == script_);
@@ -120,53 +120,25 @@
function_ = func.raw();
token_pos_ = token_pos;
end_token_pos_ = token_pos;
- is_resolved_ = true;
+ if (in_bytecode) {
+ bytecode_token_pos_ = token_pos;
+ } else {
+ code_token_pos_ = token_pos;
+ }
}
-// TODO(hausner): Get rid of library parameter. A source breakpoint location
-// does not imply a library, since the same source code can be included
-// in more than one library, e.g. the text location of mixin functions.
-void BreakpointLocation::GetCodeLocation(Library* lib,
- Script* script,
+// Returned resolved pos is either in code or in bytecode.
+void BreakpointLocation::GetCodeLocation(Script* script,
TokenPosition* pos) const {
if (IsLatent()) {
- *lib = Library::null();
*script = Script::null();
*pos = TokenPosition::kNoSource;
} else {
*script = this->script();
*pos = token_pos_;
- if (IsResolved()) {
- const Function& func = Function::Handle(function_);
- ASSERT(!func.IsNull());
- const Class& cls = Class::Handle(func.origin());
- *lib = cls.library();
- } else {
- *lib = Library::null();
- }
}
}
-intptr_t BreakpointLocation::LineNumber() {
- ASSERT(IsResolved());
- // Compute line number lazily since it causes scanning of the script.
- if (line_number_ < 0) {
- const Script& script = Script::Handle(this->script());
- script.GetTokenLocation(token_pos_, &line_number_, NULL);
- }
- return line_number_;
-}
-
-intptr_t BreakpointLocation::ColumnNumber() {
- ASSERT(IsResolved());
- // Compute column number lazily since it causes scanning of the script.
- if (column_number_ < 0) {
- const Script& script = Script::Handle(this->script());
- script.GetTokenLocation(token_pos_, &line_number_, &column_number_);
- }
- return column_number_;
-}
-
void Breakpoint::set_bpt_location(BreakpointLocation* new_bpt_location) {
// Only latent breakpoints can be moved.
ASSERT((new_bpt_location == NULL) || bpt_location_->IsLatent());
@@ -208,6 +180,7 @@
void CodeBreakpoint::VisitObjectPointers(ObjectPointerVisitor* visitor) {
visitor->VisitPointer(reinterpret_cast<RawObject**>(&code_));
+ visitor->VisitPointer(reinterpret_cast<RawObject**>(&bytecode_));
#if !defined(TARGET_ARCH_DBC)
visitor->VisitPointer(reinterpret_cast<RawObject**>(&saved_value_));
#endif
@@ -225,6 +198,7 @@
sp_(sp),
ctx_(Context::ZoneHandle()),
code_(Code::ZoneHandle(code.raw())),
+ bytecode_(Bytecode::ZoneHandle()),
function_(Function::ZoneHandle(code.function())),
live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
token_pos_initialized_(false),
@@ -237,11 +211,44 @@
deopt_frame_(Array::ZoneHandle(deopt_frame.raw())),
deopt_frame_offset_(deopt_frame_offset),
kind_(kind),
- is_interpreted_(false), // TODO(regis): No bytecode debugging support.
vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
desc_indices_(8),
- pc_desc_(PcDescriptors::ZoneHandle()) {}
+ pc_desc_(PcDescriptors::ZoneHandle()) {
+ ASSERT(!function_.IsNull());
+}
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame::ActivationFrame(uword pc,
+ uword fp,
+ uword sp,
+ const Bytecode& bytecode,
+ ActivationFrame::Kind kind)
+ : pc_(pc),
+ fp_(fp),
+ sp_(sp),
+ ctx_(Context::ZoneHandle()),
+ code_(Code::ZoneHandle()),
+ bytecode_(Bytecode::ZoneHandle(bytecode.raw())),
+ function_(Function::ZoneHandle(bytecode.function())),
+ live_frame_((kind == kRegular) || (kind == kAsyncActivation)),
+ token_pos_initialized_(false),
+ token_pos_(TokenPosition::kNoSource),
+ try_index_(-1),
+ deopt_id_(DeoptId::kNone),
+ line_number_(-1),
+ column_number_(-1),
+ context_level_(-1),
+ deopt_frame_(Array::ZoneHandle()),
+ deopt_frame_offset_(0),
+ kind_(kind),
+ vars_initialized_(false),
+ var_descriptors_(LocalVarDescriptors::ZoneHandle()),
+ desc_indices_(8),
+ pc_desc_(PcDescriptors::ZoneHandle()) {
+ ASSERT(!function_.IsNull()); // Frames with bytecode stubs should be skipped.
+}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
ActivationFrame::ActivationFrame(Kind kind)
: pc_(0),
@@ -249,6 +256,7 @@
sp_(0),
ctx_(Context::ZoneHandle()),
code_(Code::ZoneHandle()),
+ bytecode_(Bytecode::ZoneHandle()),
function_(Function::ZoneHandle()),
live_frame_(kind == kRegular),
token_pos_initialized_(false),
@@ -260,7 +268,6 @@
deopt_frame_(Array::ZoneHandle()),
deopt_frame_offset_(0),
kind_(kind),
- is_interpreted_(false),
vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
desc_indices_(8),
@@ -272,6 +279,7 @@
sp_(0),
ctx_(Context::ZoneHandle()),
code_(Code::ZoneHandle()),
+ bytecode_(Bytecode::ZoneHandle()),
function_(Function::ZoneHandle()),
live_frame_(false),
token_pos_initialized_(false),
@@ -283,15 +291,21 @@
deopt_frame_(Array::ZoneHandle()),
deopt_frame_offset_(0),
kind_(kAsyncActivation),
- is_interpreted_(false),
vars_initialized_(false),
var_descriptors_(LocalVarDescriptors::ZoneHandle()),
desc_indices_(8),
pc_desc_(PcDescriptors::ZoneHandle()) {
// Extract the function and the code from the asynchronous activation.
function_ = async_activation.function();
- function_.EnsureHasCompiledUnoptimizedCode();
- code_ = function_.unoptimized_code();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (!function_.HasCode() && function_.HasBytecode()) {
+ bytecode_ = function_.bytecode();
+ }
+#endif
+ if (bytecode_.IsNull()) {
+ function_.EnsureHasCompiledUnoptimizedCode();
+ code_ = function_.unoptimized_code();
+ }
ctx_ = async_activation.context();
ASSERT(fp_ == 0);
ASSERT(!ctx_.IsNull());
@@ -462,7 +476,7 @@
}
bool Debugger::HasBreakpoint(const Function& func, Zone* zone) {
- if (!func.HasCode()) {
+ if (!func.HasCode() && !func.HasBytecode()) {
// If the function is not compiled yet, just check whether there
// is a user-defined breakpoint that falls into the token
// range of the function. This may be a false positive: the breakpoint
@@ -553,20 +567,26 @@
}
void ActivationFrame::GetPcDescriptors() {
+ ASSERT(!IsInterpreted()); // We need to set try_index_ simultaneously.
if (pc_desc_.IsNull()) {
pc_desc_ = code().pc_descriptors();
ASSERT(!pc_desc_.IsNull());
}
}
-// Compute token_pos_ and try_index_ and token_pos_initialized_.
+// Compute token_pos_ and token_pos_initialized_.
+// If not IsInterpreted(), then also compute try_index_ and deopt_id_.
TokenPosition ActivationFrame::TokenPos() {
if (!token_pos_initialized_) {
token_pos_initialized_ = true;
+ if (IsInterpreted()) {
+ token_pos_ = bytecode().GetTokenIndexOfPC(pc_);
+ return token_pos_;
+ }
token_pos_ = TokenPosition::kNoSource;
GetPcDescriptors();
PcDescriptors::Iterator iter(pc_desc_, RawPcDescriptors::kAnyKind);
- uword pc_offset = pc_ - code().PayloadStart();
+ const uword pc_offset = pc_ - code().PayloadStart();
while (iter.MoveNext()) {
if (iter.PcOffset() == pc_offset) {
try_index_ = iter.TryIndex();
@@ -580,6 +600,16 @@
}
intptr_t ActivationFrame::TryIndex() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (IsInterpreted()) {
+ if (pc_desc_.IsNull()) {
+ ASSERT(try_index_ == -1);
+ pc_desc_ = bytecode().pc_descriptors();
+ try_index_ = bytecode().GetTryIndexAtPc(pc_);
+ }
+ return try_index_;
+ }
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
if (!token_pos_initialized_) {
TokenPos(); // Side effect: computes token_pos_initialized_, try_index_.
}
@@ -587,6 +617,7 @@
}
intptr_t ActivationFrame::DeoptId() {
+ ASSERT(!IsInterpreted());
if (!token_pos_initialized_) {
TokenPos(); // Side effect: computes token_pos_initialized_, try_index_.
}
@@ -619,7 +650,7 @@
void ActivationFrame::GetVarDescriptors() {
if (var_descriptors_.IsNull()) {
- if (is_interpreted()) {
+ if (IsInterpreted()) {
// TODO(regis): Kernel bytecode does not yet provide var descriptors.
var_descriptors_ = Object::empty_var_descriptors().raw();
return;
@@ -652,8 +683,13 @@
OS::PrintErr("deopt_id_ %" Px "\n", deopt_id_);
OS::PrintErr("context_level_ %" Px "\n", context_level_);
DisassembleToStdout formatter;
- code().Disassemble(&formatter);
- PcDescriptors::Handle(code().pc_descriptors()).Print();
+ if (IsInterpreted()) {
+ bytecode().Disassemble(&formatter);
+ PcDescriptors::Handle(bytecode().pc_descriptors()).Print();
+ } else {
+ code().Disassemble(&formatter);
+ PcDescriptors::Handle(code().pc_descriptors()).Print();
+ }
StackFrameIterator frames(ValidationPolicy::kDontValidateFrames,
Thread::Current(),
StackFrameIterator::kNoCrossThreadIteration);
@@ -667,6 +703,9 @@
// Calculate the context level at the current token index of the frame.
intptr_t ActivationFrame::ContextLevel() {
+ // TODO(regis): get context level information using
+ // BytecodeLocalVariablesIterator for interpreted frames and compiled frames
+ // with a function coming from bytecode (function.is_declared_in_bytecode())
const Context& ctx = GetSavedCurrentContext();
if (context_level_ < 0 && !ctx.IsNull()) {
ASSERT(!code_.is_optimized());
@@ -808,7 +847,11 @@
AbstractType& type = Type::Handle();
const bool is_async =
function().IsAsyncClosure() || function().IsAsyncGenClosure();
- handlers = code().exception_handlers();
+ if (IsInterpreted()) {
+ handlers = bytecode().exception_handlers();
+ } else {
+ handlers = code().exception_handlers();
+ }
ASSERT(!handlers.IsNull());
intptr_t num_handlers_checked = 0;
while (try_index != kInvalidTryIndex) {
@@ -840,6 +883,10 @@
void ActivationFrame::ExtractTokenPositionFromAsyncClosure() {
// Attempt to determine the token position from the async closure.
+ if (IsInterpreted()) {
+ // TODO(regis): Implement.
+ return;
+ }
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
const Script& script = Script::Handle(zone, function().script());
@@ -1436,7 +1483,11 @@
const TokenPosition pos = TokenPos().SourcePosition();
jsobj->AddLocation(script, pos);
jsobj->AddProperty("function", function());
- jsobj->AddProperty("code", code());
+ if (IsInterpreted()) {
+ jsobj->AddProperty("bytecode", bytecode());
+ } else {
+ jsobj->AddProperty("code", code());
+ }
{
JSONArray jsvars(jsobj, "vars");
const int num_vars = NumLocalVariables();
@@ -1476,7 +1527,11 @@
const TokenPosition pos = TokenPos().SourcePosition();
jsobj->AddLocation(script, pos);
jsobj->AddProperty("function", function());
- jsobj->AddProperty("code", code());
+ if (IsInterpreted()) {
+ jsobj->AddProperty("bytecode", bytecode());
+ } else {
+ jsobj->AddProperty("code", code());
+ }
}
void ActivationFrame::PrintToJSONObjectAsyncSuspensionMarker(
@@ -1493,7 +1548,11 @@
const TokenPosition pos = TokenPos().SourcePosition();
jsobj->AddLocation(script, pos);
jsobj->AddProperty("function", function());
- jsobj->AddProperty("code", code());
+ if (IsInterpreted()) {
+ jsobj->AddProperty("bytecode", bytecode());
+ } else {
+ jsobj->AddProperty("code", code());
+ }
}
static bool IsFunctionVisible(const Function& function) {
@@ -1516,6 +1575,14 @@
ActivationFrame::kAsyncCausal));
}
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void DebuggerStackTrace::AddAsyncCausalFrame(uword pc,
+ const Bytecode& bytecode) {
+ trace_.Add(
+ new ActivationFrame(pc, 0, 0, bytecode, ActivationFrame::kAsyncCausal));
+}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
const uint8_t kSafepointKind = RawPcDescriptors::kIcCall |
RawPcDescriptors::kUnoptStaticCall |
RawPcDescriptors::kRuntimeCall;
@@ -1525,6 +1592,7 @@
uword pc,
RawPcDescriptors::Kind kind)
: code_(code.raw()),
+ bytecode_(Bytecode::null()),
token_pos_(token_pos),
pc_(pc),
line_number_(-1),
@@ -1545,12 +1613,37 @@
ASSERT((breakpoint_kind_ & kSafepointKind) != 0);
}
+CodeBreakpoint::CodeBreakpoint(const Bytecode& bytecode,
+ TokenPosition token_pos,
+ uword pc)
+ : code_(Code::null()),
+ bytecode_(bytecode.raw()),
+ token_pos_(token_pos),
+ pc_(pc),
+ line_number_(-1),
+ is_enabled_(false),
+ bpt_location_(NULL),
+ next_(NULL),
+ breakpoint_kind_(RawPcDescriptors::kAnyKind),
+#if !defined(TARGET_ARCH_DBC)
+ saved_value_(Code::null())
+#else
+ saved_value_(SimulatorBytecode::kTrap),
+ saved_value_fastsmi_(SimulatorBytecode::kTrap)
+#endif
+{
+ ASSERT(!bytecode.IsNull());
+ ASSERT(token_pos_.IsReal());
+ ASSERT(pc_ != 0);
+}
+
CodeBreakpoint::~CodeBreakpoint() {
// Make sure we don't leave patched code behind.
ASSERT(!IsEnabled());
// Poison the data so we catch use after free errors.
#ifdef DEBUG
code_ = Code::null();
+ bytecode_ = Bytecode::null();
pc_ = 0ul;
bpt_location_ = NULL;
next_ = NULL;
@@ -1559,7 +1652,12 @@
}
RawFunction* CodeBreakpoint::function() const {
- return Code::Handle(code_).function();
+ if (IsInterpreted()) {
+ ASSERT(Bytecode::Handle(bytecode_).function() != Function::null());
+ return Bytecode::Handle(bytecode_).function();
+ } else {
+ return Code::Handle(code_).function();
+ }
}
RawScript* CodeBreakpoint::SourceCode() {
@@ -1583,14 +1681,30 @@
void CodeBreakpoint::Enable() {
if (!is_enabled_) {
- PatchCode();
+ if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ SetBytecodeBreak();
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ PatchCode();
+ }
}
ASSERT(is_enabled_);
}
void CodeBreakpoint::Disable() {
if (is_enabled_) {
- RestoreCode();
+ if (IsInterpreted()) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ UnsetBytecodeBreak();
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ RestoreCode();
+ }
}
ASSERT(!is_enabled_);
}
@@ -1818,6 +1932,24 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
+ActivationFrame* Debugger::CollectDartFrame(Isolate* isolate,
+ uword pc,
+ StackFrame* frame,
+ const Bytecode& bytecode,
+ ActivationFrame::Kind kind) {
+ ASSERT(bytecode.ContainsInstructionAt(pc));
+ ActivationFrame* activation =
+ new ActivationFrame(pc, frame->fp(), frame->sp(), bytecode, kind);
+ if (FLAG_trace_debugger_stacktrace) {
+ const Context& ctx = activation->GetSavedCurrentContext();
+ OS::PrintErr("\tUsing saved context: %s\n", ctx.ToCString());
+ }
+ if (FLAG_trace_debugger_stacktrace) {
+ OS::PrintErr("\tLine number: %" Pd "\n", activation->LineNumber());
+ }
+ return activation;
+}
+
RawArray* Debugger::DeoptimizeToArray(Thread* thread,
StackFrame* frame,
const Code& code) {
@@ -1850,6 +1982,9 @@
Thread::Current(),
StackFrameIterator::kNoCrossThreadIteration);
Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ Bytecode& bytecode = Bytecode::Handle(zone);
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
Code& inlined_code = Code::Handle(zone);
Array& deopt_frame = Array::Handle(zone);
@@ -1862,14 +1997,21 @@
}
if (frame->IsDartFrame()) {
if (frame->is_interpreted()) {
- // TODO(regis): Support debugging of interpreted frames.
- // For now, do not abort, but skip the frame, as this code is run
- // while handling a stack overflow. See HandleStackOverflowTestCases.
- continue;
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ bytecode = frame->LookupDartBytecode();
+ if (bytecode.function() == Function::null()) {
+ continue; // Skip bytecode stub frame.
+ }
+ stack_trace->AddActivation(
+ CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ code = frame->LookupDartCode();
+ AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+ &inlined_code, &deopt_frame);
}
- code = frame->LookupDartCode();
- AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
- &inlined_code, &deopt_frame);
}
}
return stack_trace;
@@ -1917,7 +2059,11 @@
Isolate* isolate = thread->isolate();
DebuggerStackTrace* stack_trace = new DebuggerStackTrace(8);
+ Object& code_obj = Object::Handle(zone);
Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ Bytecode& bytecode = Bytecode::Handle(zone);
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
Smi& offset = Smi::Handle();
Code& inlined_code = Code::Handle(zone);
Array& deopt_frame = Array::Handle(zone);
@@ -1949,12 +2095,21 @@
ASSERT(frame != NULL);
if (frame->IsDartFrame()) {
if (frame->is_interpreted()) {
- // TODO(regis): Support debugging of interpreted frames.
- UNIMPLEMENTED();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ bytecode = frame->LookupDartBytecode();
+ if (bytecode.function() == Function::null()) {
+ continue; // Skip bytecode stub frame.
+ }
+ stack_trace->AddActivation(
+ CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ code = frame->LookupDartCode();
+ AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
+ &inlined_code, &deopt_frame);
}
- code = frame->LookupDartCode();
- AppendCodeFrames(thread, isolate, zone, stack_trace, frame, &code,
- &inlined_code, &deopt_frame);
synchronous_stack_trace_length--;
}
frame = iterator.NextFrame();
@@ -1965,19 +2120,27 @@
// activated.
while (!async_stack_trace.IsNull()) {
for (intptr_t i = 0; i < async_stack_trace.Length(); i++) {
- if (async_stack_trace.CodeAtFrame(i) == Code::null()) {
+ code_obj = async_stack_trace.CodeAtFrame(i);
+ if (code_obj.IsNull()) {
break;
}
- if (async_stack_trace.CodeAtFrame(i) ==
- StubCode::AsynchronousGapMarker().raw()) {
+ if (code_obj.raw() == StubCode::AsynchronousGapMarker().raw()) {
stack_trace->AddMarker(ActivationFrame::kAsyncSuspensionMarker);
// The frame immediately below the asynchronous gap marker is the
// identical to the frame above the marker. Skip the frame to enhance
// the readability of the trace.
i++;
} else {
- code = Code::RawCast(async_stack_trace.CodeAtFrame(i));
offset = Smi::RawCast(async_stack_trace.PcOffsetAtFrame(i));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (code_obj.IsBytecode()) {
+ bytecode ^= code_obj.raw();
+ uword pc = bytecode.PayloadStart() + offset.Value();
+ stack_trace->AddAsyncCausalFrame(pc, bytecode);
+ continue;
+ }
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ code ^= code_obj.raw();
uword pc = code.PayloadStart() + offset.Value();
if (code.is_optimized()) {
for (InlinedFunctionsIterator it(code, pc); !it.Done();
@@ -2027,6 +2190,7 @@
StackFrameIterator::kNoCrossThreadIteration);
Code& code = Code::Handle(zone);
+ Bytecode& bytecode = Bytecode::Handle(zone);
Smi& offset = Smi::Handle(zone);
Function& function = Function::Handle(zone);
Code& inlined_code = Code::Handle(zone);
@@ -2048,73 +2212,11 @@
}
if (frame->IsDartFrame()) {
if (frame->is_interpreted()) {
- // TODO(regis): Support debugging of interpreted frames.
- UNIMPLEMENTED();
- }
- code = frame->LookupDartCode();
- if (code.is_optimized()) {
- deopt_frame = DeoptimizeToArray(thread, frame, code);
- bool found_async_awaiter = false;
- bool abort_attempt_to_navigate_through_sync_async = false;
- for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
- it.Advance()) {
- inlined_code = it.code();
- function = it.function();
-
- if (skip_sync_async_frames_count > 0) {
- function_name = function.QualifiedScrubbedName();
- if (CheckAndSkipAsync(skip_sync_async_frames_count,
- function_name)) {
- skip_sync_async_frames_count--;
- } else {
- // Unexpected function in sync async call
- skip_sync_async_frames_count = -1;
- abort_attempt_to_navigate_through_sync_async = true;
- break;
- }
- }
-
- if (FLAG_trace_debugger_stacktrace) {
- ASSERT(!function.IsNull());
- OS::PrintErr(
- "CollectAwaiterReturnStackTrace: visiting inlined function: "
- "%s\n",
- function.ToFullyQualifiedCString());
- }
- intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
- if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
- ActivationFrame* activation = CollectDartFrame(
- isolate, it.pc(), frame, inlined_code, deopt_frame,
- deopt_frame_offset, ActivationFrame::kAsyncActivation);
- ASSERT(activation != NULL);
- stack_trace->AddActivation(activation);
- stack_has_async_function = true;
- // Grab the awaiter.
- async_activation ^= activation->GetAsyncAwaiter();
- found_async_awaiter = true;
- // async function might have been called synchronously, in which
- // case we need to keep going down the stack.
- // To determine how we are called we peek few more frames further
- // expecting to see Closure_call followed by
- // AsyncAwaitCompleter_start.
- // If we are able to see those functions we continue going down
- // thestack, if we are not, we break out of the loop as we are
- // not interested in exploring rest of the stack - there is only
- // dart-internal code left.
- skip_sync_async_frames_count = 2;
- } else {
- stack_trace->AddActivation(
- CollectDartFrame(isolate, it.pc(), frame, inlined_code,
- deopt_frame, deopt_frame_offset));
- }
+ bytecode = frame->LookupDartBytecode();
+ function = bytecode.function();
+ if (function.IsNull()) {
+ continue; // Skip bytecode stub frame.
}
- // Break out of outer loop.
- if (found_async_awaiter ||
- abort_attempt_to_navigate_through_sync_async) {
- break;
- }
- } else {
- function = code.function();
if (skip_sync_async_frames_count > 0) {
function_name = function.QualifiedScrubbedName();
@@ -2127,9 +2229,9 @@
}
if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
- ActivationFrame* activation = CollectDartFrame(
- isolate, frame->pc(), frame, code, Object::null_array(), 0,
- ActivationFrame::kAsyncActivation);
+ ActivationFrame* activation =
+ CollectDartFrame(isolate, frame->pc(), frame, bytecode,
+ ActivationFrame::kAsyncActivation);
ASSERT(activation != NULL);
stack_trace->AddActivation(activation);
stack_has_async_function = true;
@@ -2140,8 +2242,103 @@
// synchronously above.
skip_sync_async_frames_count = 2;
} else {
- stack_trace->AddActivation(CollectDartFrame(
- isolate, frame->pc(), frame, code, Object::null_array(), 0));
+ stack_trace->AddActivation(
+ CollectDartFrame(isolate, frame->pc(), frame, bytecode));
+ }
+ } else {
+ code = frame->LookupDartCode();
+ if (code.is_optimized()) {
+ deopt_frame = DeoptimizeToArray(thread, frame, code);
+ bool found_async_awaiter = false;
+ bool abort_attempt_to_navigate_through_sync_async = false;
+ for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done();
+ it.Advance()) {
+ inlined_code = it.code();
+ function = it.function();
+
+ if (skip_sync_async_frames_count > 0) {
+ function_name ^= function.QualifiedScrubbedName();
+ if (CheckAndSkipAsync(skip_sync_async_frames_count,
+ function_name)) {
+ skip_sync_async_frames_count--;
+ } else {
+ // Unexpected function in sync async call
+ skip_sync_async_frames_count = -1;
+ abort_attempt_to_navigate_through_sync_async = true;
+ break;
+ }
+ }
+
+ if (FLAG_trace_debugger_stacktrace) {
+ ASSERT(!function.IsNull());
+ OS::PrintErr(
+ "CollectAwaiterReturnStackTrace: visiting inlined function: "
+ "%s\n",
+ function.ToFullyQualifiedCString());
+ }
+ intptr_t deopt_frame_offset = it.GetDeoptFpOffset();
+ if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+ ActivationFrame* activation = CollectDartFrame(
+ isolate, it.pc(), frame, inlined_code, deopt_frame,
+ deopt_frame_offset, ActivationFrame::kAsyncActivation);
+ ASSERT(activation != NULL);
+ stack_trace->AddActivation(activation);
+ stack_has_async_function = true;
+ // Grab the awaiter.
+ async_activation ^= activation->GetAsyncAwaiter();
+ found_async_awaiter = true;
+ // async function might have been called synchronously, in which
+ // case we need to keep going down the stack.
+ // To determine how we are called we peek few more frames further
+ // expecting to see Closure_call followed by
+ // AsyncAwaitCompleter_start.
+ // If we are able to see those functions we continue going down
+ // thestack, if we are not, we break out of the loop as we are
+ // not interested in exploring rest of the stack - there is only
+ // dart-internal code left.
+ skip_sync_async_frames_count = 2;
+ } else {
+ stack_trace->AddActivation(
+ CollectDartFrame(isolate, it.pc(), frame, inlined_code,
+ deopt_frame, deopt_frame_offset));
+ }
+ }
+ // Break out of outer loop.
+ if (found_async_awaiter ||
+ abort_attempt_to_navigate_through_sync_async) {
+ break;
+ }
+ } else {
+ function = code.function();
+
+ if (skip_sync_async_frames_count > 0) {
+ function_name ^= function.QualifiedScrubbedName();
+ if (CheckAndSkipAsync(skip_sync_async_frames_count,
+ function_name)) {
+ skip_sync_async_frames_count--;
+ } else {
+ // Unexpected function in synchronous call of async function.
+ break;
+ }
+ }
+
+ if (function.IsAsyncClosure() || function.IsAsyncGenClosure()) {
+ ActivationFrame* activation = CollectDartFrame(
+ isolate, frame->pc(), frame, code, Object::null_array(), 0,
+ ActivationFrame::kAsyncActivation);
+ ASSERT(activation != NULL);
+ stack_trace->AddActivation(activation);
+ stack_has_async_function = true;
+ // Grab the awaiter.
+ async_activation ^= activation->GetAsyncAwaiter();
+ async_stack_trace ^= activation->GetCausalStack();
+ // see comment regarding skipping frames of async functions called
+ // synchronously above.
+ skip_sync_async_frames_count = 2;
+ } else {
+ stack_trace->AddActivation(CollectDartFrame(
+ isolate, frame->pc(), frame, code, Object::null_array(), 0));
+ }
}
}
}
@@ -2214,11 +2411,14 @@
frame = iterator.NextFrame();
}
ASSERT(frame != NULL);
+#if !defined(DART_PRECOMPILED_RUNTIME)
if (frame->is_interpreted()) {
- // TODO(regis): Support debugging of interpreted frames.
- UNIMPLEMENTED();
- return NULL;
+ Bytecode& bytecode = Bytecode::Handle(frame->LookupDartBytecode());
+ ActivationFrame* activation =
+ new ActivationFrame(frame->pc(), frame->fp(), frame->sp(), bytecode);
+ return activation;
}
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
Code& code = Code::Handle(frame->LookupDartCode());
ActivationFrame* activation = new ActivationFrame(
frame->pc(), frame->fp(), frame->sp(), code, Object::null_array(), 0);
@@ -2256,6 +2456,9 @@
Function& function = Function::Handle();
Object& code_object = Object::Handle();
Code& code = Code::Handle();
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ Bytecode& bytecode = Bytecode::Handle();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
const uword fp = 0;
const uword sp = 0;
@@ -2271,36 +2474,50 @@
// a shallow stack).
if (!code_object.IsNull()) {
if (code_object.IsBytecode()) {
- // TODO(regis): Support debugging of interpreted frames.
- UNIMPLEMENTED();
- }
- code ^= code_object.raw();
- ASSERT(code.IsFunctionCode());
- function = code.function();
- if (function.is_visible()) {
- ASSERT(function.raw() == code.function());
- uword pc =
- code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
- if (code.is_optimized() && ex_trace.expand_inlined()) {
- // Traverse inlined frames.
- for (InlinedFunctionsIterator it(code, pc); !it.Done();
- it.Advance()) {
- function = it.function();
- code = it.code();
- ASSERT(function.raw() == code.function());
- uword pc = it.pc();
- ASSERT(pc != 0);
- ASSERT(code.PayloadStart() <= pc);
- ASSERT(pc < (code.PayloadStart() + code.Size()));
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ bytecode ^= code_object.raw();
+ function = bytecode.function();
+ // Skip bytecode stub frames and frames with invisible function.
+ if (!function.IsNull() && function.is_visible()) {
+ ASSERT(function.raw() == bytecode.function());
+ uword pc =
+ bytecode.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+ ActivationFrame* activation =
+ new ActivationFrame(pc, fp, sp, bytecode);
+ stack_trace->AddActivation(activation);
+ }
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ code ^= code_object.raw();
+ ASSERT(code.IsFunctionCode());
+ function = code.function();
+ if (function.is_visible()) {
+ ASSERT(function.raw() == code.function());
+ uword pc =
+ code.PayloadStart() + Smi::Value(ex_trace.PcOffsetAtFrame(i));
+ if (code.is_optimized() && ex_trace.expand_inlined()) {
+ // Traverse inlined frames.
+ for (InlinedFunctionsIterator it(code, pc); !it.Done();
+ it.Advance()) {
+ function = it.function();
+ code = it.code();
+ ASSERT(function.raw() == code.function());
+ uword pc = it.pc();
+ ASSERT(pc != 0);
+ ASSERT(code.PayloadStart() <= pc);
+ ASSERT(pc < (code.PayloadStart() + code.Size()));
+ ActivationFrame* activation = new ActivationFrame(
+ pc, fp, sp, code, deopt_frame, deopt_frame_offset);
+ stack_trace->AddActivation(activation);
+ }
+ } else {
ActivationFrame* activation = new ActivationFrame(
pc, fp, sp, code, deopt_frame, deopt_frame_offset);
stack_trace->AddActivation(activation);
}
- } else {
- ActivationFrame* activation = new ActivationFrame(
- pc, fp, sp, code, deopt_frame, deopt_frame_offset);
- stack_trace->AddActivation(activation);
}
}
}
@@ -2431,12 +2648,12 @@
// algorithm, which would be simpler. I believe that it only needs
// two passes to support the recursive try-the-whole-function case.
// Rewrite this later, once there are more tests in place.
-TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
+TokenPosition Debugger::ResolveBreakpointPos(bool in_bytecode,
+ const Function& func,
TokenPosition requested_token_pos,
TokenPosition last_token_pos,
intptr_t requested_column,
TokenPosition exact_token_pos) {
- ASSERT(func.HasCode());
ASSERT(!func.HasOptimizedCode());
if (requested_token_pos < func.token_pos()) {
@@ -2448,9 +2665,25 @@
Zone* zone = Thread::Current()->zone();
Script& script = Script::Handle(zone, func.script());
- Code& code = Code::Handle(zone, func.unoptimized_code());
- ASSERT(!code.IsNull());
- PcDescriptors& desc = PcDescriptors::Handle(zone, code.pc_descriptors());
+ Code& code = Code::Handle(zone);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ Bytecode& bytecode = Bytecode::Handle(zone);
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ PcDescriptors& desc = PcDescriptors::Handle(zone);
+ if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ ASSERT(func.HasBytecode());
+ bytecode = func.bytecode();
+ ASSERT(!bytecode.IsNull());
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ ASSERT(func.HasCode());
+ code = func.unoptimized_code();
+ ASSERT(!code.IsNull());
+ desc = code.pc_descriptors();
+ }
// First pass: find the safe point which is closest to the beginning
// of the given token range.
@@ -2460,53 +2693,109 @@
// best_token_pos and exact_token_pos are only used
// if column number is provided.
TokenPosition best_token_pos = TokenPosition::kNoSource;
- PcDescriptors::Iterator iter(desc, kSafepointKind);
- while (iter.MoveNext()) {
- const TokenPosition pos = iter.TokenPos();
- if ((!pos.IsReal()) || (pos < requested_token_pos) ||
- (pos > last_token_pos)) {
- // Token is not in the target range.
- continue;
- }
- intptr_t token_start_column = -1;
- intptr_t token_line = -1;
- if (requested_column >= 0) {
- // Find next closest safepoint
- PcDescriptors::Iterator iter2(desc, kSafepointKind);
- TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
- while (iter2.MoveNext()) {
- const TokenPosition next = iter2.TokenPos();
- if (next < next_closest_token_position && next > pos) {
- next_closest_token_position = next;
+ if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+ while (iter.MoveNext()) {
+ const TokenPosition pos = iter.TokenPos();
+ if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+ (pos > last_token_pos)) {
+ // Token is not in the target range.
+ continue;
+ }
+
+ intptr_t token_start_column = -1;
+ intptr_t token_line = -1;
+ if (requested_column >= 0) {
+ kernel::BytecodeSourcePositionsIterator iter2(zone, bytecode);
+ TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+ while (iter2.MoveNext()) {
+ const TokenPosition next = iter2.TokenPos();
+ if (next < next_closest_token_position && next > pos) {
+ next_closest_token_position = next;
+ }
+ }
+
+ TokenPosition ignored;
+ TokenPosition end_of_line_pos;
+ script.GetTokenLocation(pos, &token_line, &token_start_column);
+ script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+ TokenPosition token_end_pos =
+ (end_of_line_pos < next_closest_token_position)
+ ? end_of_line_pos
+ : next_closest_token_position;
+
+ if ((token_end_pos < exact_token_pos) ||
+ (token_start_column > best_column)) {
+ // Prefer the token with the lowest column number compatible
+ // with the requested column.
+ continue;
}
}
- TokenPosition ignored;
- TokenPosition end_of_line_pos;
- script.GetTokenLocation(pos, &token_line, &token_start_column);
- script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
- TokenPosition token_end_pos =
- (end_of_line_pos < next_closest_token_position)
- ? end_of_line_pos
- : next_closest_token_position;
-
- if ((token_end_pos < exact_token_pos) ||
- (token_start_column > best_column)) {
- // Prefer the token with the lowest column number compatible
- // with the requested column.
- continue;
+ // Prefer the lowest (first) token pos.
+ if (pos < best_fit_pos) {
+ best_fit_pos = pos;
+ best_line = token_line;
+ best_column = token_start_column;
+ // best_token_pos is only used when column number is specified.
+ best_token_pos = TokenPosition(exact_token_pos.value() -
+ (requested_column - best_column));
}
}
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ PcDescriptors::Iterator iter(desc, kSafepointKind);
+ while (iter.MoveNext()) {
+ const TokenPosition pos = iter.TokenPos();
+ if ((!pos.IsReal()) || (pos < requested_token_pos) ||
+ (pos > last_token_pos)) {
+ // Token is not in the target range.
+ continue;
+ }
- // Prefer the lowest (first) token pos.
- if (pos < best_fit_pos) {
- best_fit_pos = pos;
- best_line = token_line;
- best_column = token_start_column;
- // best_token_pos is only used when column number is specified.
- best_token_pos = TokenPosition(exact_token_pos.value() -
- (requested_column - best_column));
+ intptr_t token_start_column = -1;
+ intptr_t token_line = -1;
+ if (requested_column >= 0) {
+ // Find next closest safepoint
+ PcDescriptors::Iterator iter2(desc, kSafepointKind);
+ TokenPosition next_closest_token_position = TokenPosition::kMaxSource;
+ while (iter2.MoveNext()) {
+ const TokenPosition next = iter2.TokenPos();
+ if (next < next_closest_token_position && next > pos) {
+ next_closest_token_position = next;
+ }
+ }
+
+ TokenPosition ignored;
+ TokenPosition end_of_line_pos;
+ script.GetTokenLocation(pos, &token_line, &token_start_column);
+ script.TokenRangeAtLine(token_line, &ignored, &end_of_line_pos);
+ TokenPosition token_end_pos =
+ (end_of_line_pos < next_closest_token_position)
+ ? end_of_line_pos
+ : next_closest_token_position;
+
+ if ((token_end_pos < exact_token_pos) ||
+ (token_start_column > best_column)) {
+ // Prefer the token with the lowest column number compatible
+ // with the requested column.
+ continue;
+ }
+ }
+
+ // Prefer the lowest (first) token pos.
+ if (pos < best_fit_pos) {
+ best_fit_pos = pos;
+ best_line = token_line;
+ best_column = token_start_column;
+ // best_token_pos is only used when column number is specified.
+ best_token_pos = TokenPosition(exact_token_pos.value() -
+ (requested_column - best_column));
+ }
}
}
@@ -2534,24 +2823,51 @@
}
uword lowest_pc_offset = kUwordMax;
- PcDescriptors::Iterator iter(desc, kSafepointKind);
- while (iter.MoveNext()) {
- const TokenPosition pos = iter.TokenPos();
- if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
- // Token is not on same line as best fit.
- continue;
- }
-
- if (requested_column >= 0) {
- if (pos != best_token_pos) {
+ if (in_bytecode) {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ kernel::BytecodeSourcePositionsIterator iter(zone, bytecode);
+ while (iter.MoveNext()) {
+ const TokenPosition pos = iter.TokenPos();
+ if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+ // Token is not on same line as best fit.
continue;
}
- }
- // Prefer the lowest pc offset.
- if (iter.PcOffset() < lowest_pc_offset) {
- lowest_pc_offset = iter.PcOffset();
- best_fit_pos = pos;
+ if (requested_column >= 0) {
+ if (pos != best_token_pos) {
+ continue;
+ }
+ }
+
+ // Prefer the lowest pc offset.
+ if (iter.PcOffset() < lowest_pc_offset) {
+ lowest_pc_offset = iter.PcOffset();
+ best_fit_pos = pos;
+ }
+ }
+#else
+ UNREACHABLE();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ } else {
+ PcDescriptors::Iterator iter(desc, kSafepointKind);
+ while (iter.MoveNext()) {
+ const TokenPosition pos = iter.TokenPos();
+ if (!pos.IsReal() || (pos < begin_pos) || (pos > end_of_line_pos)) {
+ // Token is not on same line as best fit.
+ continue;
+ }
+
+ if (requested_column >= 0) {
+ if (pos != best_token_pos) {
+ continue;
+ }
+ }
+
+ // Prefer the lowest pc offset.
+ if (iter.PcOffset() < lowest_pc_offset) {
+ lowest_pc_offset = iter.PcOffset();
+ best_fit_pos = pos;
+ }
}
}
return best_fit_pos;
@@ -2562,8 +2878,9 @@
// Since we have moved to the next line of the function, we no
// longer are requesting a specific column number.
if (last_token_pos < func.end_token_pos()) {
- return ResolveBreakpointPos(func, last_token_pos, func.end_token_pos(),
- -1 /* no column */, TokenPosition::kNoSource);
+ return ResolveBreakpointPos(in_bytecode, func, last_token_pos,
+ func.end_token_pos(), -1 /* no column */,
+ TokenPosition::kNoSource);
}
return TokenPosition::kNoSource;
}
@@ -2573,43 +2890,78 @@
ASSERT(loc->token_pos_.IsReal());
ASSERT((loc != NULL) && loc->IsResolved());
ASSERT(!func.HasOptimizedCode());
- Code& code = Code::Handle(func.unoptimized_code());
- ASSERT(!code.IsNull());
- PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
- uword lowest_pc_offset = kUwordMax;
- RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
- // Find the safe point with the lowest compiled code address
- // that maps to the token position of the source breakpoint.
- PcDescriptors::Iterator iter(desc, kSafepointKind);
- while (iter.MoveNext()) {
- if (iter.TokenPos() == loc->token_pos_) {
- if (iter.PcOffset() < lowest_pc_offset) {
- lowest_pc_offset = iter.PcOffset();
- lowest_kind = iter.Kind();
+ ASSERT(func.HasCode() || func.HasBytecode());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (func.HasBytecode()) {
+ Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+ ASSERT(!bytecode.IsNull());
+ uword lowest_pc_offset = kUwordMax;
+ if (bytecode.HasSourcePositions()) {
+ kernel::BytecodeSourcePositionsIterator iter(Thread::Current()->zone(),
+ bytecode);
+ while (iter.MoveNext()) {
+ if (iter.TokenPos() == loc->token_pos_) {
+ if (iter.PcOffset() < lowest_pc_offset) {
+ lowest_pc_offset = iter.PcOffset();
+ }
+ }
+ }
+ }
+ if (lowest_pc_offset != kUwordMax) {
+ uword lowest_pc = bytecode.PayloadStart() + lowest_pc_offset;
+ CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
+ if (code_bpt == NULL) {
+ // No code breakpoint for this code exists; create one.
+ code_bpt = new CodeBreakpoint(bytecode, loc->token_pos_, lowest_pc);
+ RegisterCodeBreakpoint(code_bpt);
+ }
+ code_bpt->set_bpt_location(loc);
+ if (loc->AnyEnabled()) {
+ code_bpt->Enable();
}
}
}
- if (lowest_pc_offset == kUwordMax) {
- return;
- }
- uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
- CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
- if (code_bpt == NULL) {
- // No code breakpoint for this code exists; create one.
- code_bpt =
- new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
- RegisterCodeBreakpoint(code_bpt);
- }
- code_bpt->set_bpt_location(loc);
- if (loc->AnyEnabled()) {
- code_bpt->Enable();
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+ if (func.HasCode()) {
+ Code& code = Code::Handle(func.unoptimized_code());
+ ASSERT(!code.IsNull());
+ PcDescriptors& desc = PcDescriptors::Handle(code.pc_descriptors());
+ uword lowest_pc_offset = kUwordMax;
+ RawPcDescriptors::Kind lowest_kind = RawPcDescriptors::kAnyKind;
+ // Find the safe point with the lowest compiled code address
+ // that maps to the token position of the source breakpoint.
+ PcDescriptors::Iterator iter(desc, kSafepointKind);
+ while (iter.MoveNext()) {
+ if (iter.TokenPos() == loc->token_pos_) {
+ if (iter.PcOffset() < lowest_pc_offset) {
+ lowest_pc_offset = iter.PcOffset();
+ lowest_kind = iter.Kind();
+ }
+ }
+ }
+ if (lowest_pc_offset != kUwordMax) {
+ uword lowest_pc = code.PayloadStart() + lowest_pc_offset;
+ CodeBreakpoint* code_bpt = GetCodeBreakpoint(lowest_pc);
+ if (code_bpt == NULL) {
+ // No code breakpoint for this code exists; create one.
+ code_bpt =
+ new CodeBreakpoint(code, loc->token_pos_, lowest_pc, lowest_kind);
+ RegisterCodeBreakpoint(code_bpt);
+ }
+ code_bpt->set_bpt_location(loc);
+ if (loc->AnyEnabled()) {
+ code_bpt->Enable();
+ }
+ }
}
}
-void Debugger::FindCompiledFunctions(const Script& script,
- TokenPosition start_pos,
- TokenPosition end_pos,
- GrowableObjectArray* function_list) {
+void Debugger::FindCompiledFunctions(
+ const Script& script,
+ TokenPosition start_pos,
+ TokenPosition end_pos,
+ GrowableObjectArray* bytecode_function_list,
+ GrowableObjectArray* code_function_list) {
Zone* zone = Thread::Current()->zone();
Class& cls = Class::Handle(zone);
Array& functions = Array::Handle(zone);
@@ -2624,13 +2976,23 @@
if ((function.token_pos() == start_pos) &&
(function.end_token_pos() == end_pos) &&
(function.script() == script.raw())) {
- if (function.HasCode() && function.is_debuggable()) {
- function_list->Add(function);
+ if (function.is_debuggable()) {
+ if (function.HasBytecode()) {
+ bytecode_function_list->Add(function);
+ }
+ if (function.HasCode()) {
+ code_function_list->Add(function);
+ }
}
if (function.HasImplicitClosureFunction()) {
function = function.ImplicitClosureFunction();
- if (function.HasCode() && function.is_debuggable()) {
- function_list->Add(function);
+ if (function.is_debuggable()) {
+ if (function.HasBytecode()) {
+ bytecode_function_list->Add(function);
+ }
+ if (function.HasCode()) {
+ code_function_list->Add(function);
+ }
}
}
}
@@ -2662,13 +3024,23 @@
if ((function.token_pos() == start_pos) &&
(function.end_token_pos() == end_pos) &&
(function.script() == script.raw())) {
- if (function.HasCode() && function.is_debuggable()) {
- function_list->Add(function);
+ if (function.is_debuggable()) {
+ if (function.HasBytecode()) {
+ bytecode_function_list->Add(function);
+ }
+ if (function.HasCode()) {
+ code_function_list->Add(function);
+ }
}
if (function.HasImplicitClosureFunction()) {
function = function.ImplicitClosureFunction();
- if (function.HasCode() && function.is_debuggable()) {
- function_list->Add(function);
+ if (function.is_debuggable()) {
+ if (function.HasBytecode()) {
+ bytecode_function_list->Add(function);
+ }
+ if (function.HasCode()) {
+ code_function_list->Add(function);
+ }
}
}
}
@@ -2800,6 +3172,71 @@
return false;
}
+BreakpointLocation* Debugger::SetCodeBreakpoints(
+ bool in_bytecode,
+ BreakpointLocation* loc,
+ const Script& script,
+ TokenPosition token_pos,
+ TokenPosition last_token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column,
+ TokenPosition exact_token_pos,
+ const GrowableObjectArray& functions) {
+ Function& function = Function::Handle();
+ function ^= functions.At(0);
+ TokenPosition breakpoint_pos =
+ ResolveBreakpointPos(in_bytecode, function, token_pos, last_token_pos,
+ requested_column, exact_token_pos);
+ if (!breakpoint_pos.IsReal()) {
+ return NULL;
+ }
+ if (loc == NULL) {
+ // Find an existing resolved breakpoint location.
+ loc = GetBreakpointLocation(
+ script, TokenPosition::kNoSource,
+ /* requested_line = */ -1,
+ /* requested_column = */ -1,
+ in_bytecode ? breakpoint_pos : TokenPosition::kNoSource,
+ !in_bytecode ? breakpoint_pos : TokenPosition::kNoSource);
+ }
+ if (loc == NULL) {
+ // Find an existing unresolved breakpoint location.
+ loc = GetBreakpointLocation(script, token_pos, requested_line,
+ requested_column);
+ }
+ if (loc == NULL) {
+ loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
+ requested_line, requested_column);
+ RegisterBreakpointLocation(loc);
+ }
+ // A source breakpoint for this location may already exists, but it may
+ // not yet be resolved in both bytecode and code.
+ if (loc->IsResolved(in_bytecode)) {
+ return loc;
+ }
+ loc->SetResolved(in_bytecode, function, breakpoint_pos);
+
+ // Create code breakpoints for all compiled functions we found.
+ Function& func = Function::Handle();
+ const intptr_t num_functions = functions.Length();
+ for (intptr_t i = 0; i < num_functions; i++) {
+ func ^= functions.At(i);
+ ASSERT((in_bytecode && func.HasBytecode()) ||
+ (!in_bytecode && func.HasCode()));
+ MakeCodeBreakpointAt(func, loc);
+ }
+ if (FLAG_verbose_debug) {
+ intptr_t line_number;
+ intptr_t column_number;
+ script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
+ OS::PrintErr(
+ "Resolved BP for "
+ "function '%s' at line %" Pd " col %" Pd "\n",
+ func.ToFullyQualifiedCString(), line_number, column_number);
+ }
+ return loc;
+}
+
BreakpointLocation* Debugger::SetBreakpoint(const Script& script,
TokenPosition token_pos,
TokenPosition last_token_pos,
@@ -2811,65 +3248,53 @@
if (!FindBestFit(script, token_pos, last_token_pos, &func)) {
return NULL;
}
+ // If func was not set (still Null), the best fit is a field.
} else {
func = function.raw();
+ if (!func.token_pos().IsReal()) {
+ return NULL; // Missing source positions in bytecode?
+ }
}
-
if (!func.IsNull()) {
// There may be more than one function object for a given function
// in source code. There may be implicit closure functions, and
// there may be copies of mixin functions. Collect all compiled
// functions whose source code range matches exactly the best fit
// function we found.
- GrowableObjectArray& functions =
+ GrowableObjectArray& bytecode_functions =
+ GrowableObjectArray::Handle(GrowableObjectArray::New());
+ GrowableObjectArray& code_functions =
GrowableObjectArray::Handle(GrowableObjectArray::New());
FindCompiledFunctions(script, func.token_pos(), func.end_token_pos(),
- &functions);
+ &bytecode_functions, &code_functions);
- if (functions.Length() > 0) {
+ if (bytecode_functions.Length() > 0 || code_functions.Length() > 0) {
// One or more function object containing this breakpoint location
// have already been compiled. We can resolve the breakpoint now.
- DeoptimizeWorld();
- func ^= functions.At(0);
- TokenPosition exact_token_pos = TokenPosition(-1);
- // if requested_column is larger than zero, [token_pos, last_token_pos]
+ // If requested_column is larger than zero, [token_pos, last_token_pos]
// governs one single line of code.
+ TokenPosition exact_token_pos = TokenPosition(-1);
if (token_pos != last_token_pos && requested_column >= 0) {
#if !defined(DART_PRECOMPILED_RUNTIME)
exact_token_pos =
FindExactTokenPosition(script, token_pos, requested_column);
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
- TokenPosition breakpoint_pos = ResolveBreakpointPos(
- func, token_pos, last_token_pos, requested_column, exact_token_pos);
- if (breakpoint_pos.IsReal()) {
- BreakpointLocation* loc = GetBreakpointLocation(script, breakpoint_pos,
- requested_column, true);
- if (loc != NULL) {
- // A source breakpoint for this location already exists.
- return loc;
- }
- loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
- requested_line, requested_column);
- loc->SetResolved(func, breakpoint_pos);
- RegisterBreakpointLocation(loc);
-
- // Create code breakpoints for all compiled functions we found.
- const intptr_t num_functions = functions.Length();
- for (intptr_t i = 0; i < num_functions; i++) {
- func ^= functions.At(i);
- ASSERT(func.HasCode());
- MakeCodeBreakpointAt(func, loc);
- }
- if (FLAG_verbose_debug) {
- intptr_t line_number;
- intptr_t column_number;
- script.GetTokenLocation(breakpoint_pos, &line_number, &column_number);
- OS::PrintErr(
- "Resolved BP for "
- "function '%s' at line %" Pd " col %" Pd "\n",
- func.ToFullyQualifiedCString(), line_number, column_number);
- }
+ // Since source positions may differ in code and bytecode, process
+ // breakpoints in bytecode and code separately.
+ BreakpointLocation* loc = NULL;
+ if (bytecode_functions.Length() > 0) {
+ loc = SetCodeBreakpoints(true, loc, script, token_pos, last_token_pos,
+ requested_line, requested_column,
+ exact_token_pos, bytecode_functions);
+ }
+ if (code_functions.Length() > 0) {
+ DeoptimizeWorld();
+ loc = SetCodeBreakpoints(false, loc, script, token_pos, last_token_pos,
+ requested_line, requested_column,
+ exact_token_pos, code_functions);
+ }
+ if (loc != NULL) {
return loc;
}
}
@@ -2894,7 +3319,7 @@
}
}
BreakpointLocation* loc =
- GetBreakpointLocation(script, token_pos, requested_column);
+ GetBreakpointLocation(script, token_pos, -1, requested_column);
if (loc == NULL) {
loc = new BreakpointLocation(script, token_pos, last_token_pos,
requested_line, requested_column);
@@ -3525,6 +3950,12 @@
return lib.IsDebuggable();
}
+bool Debugger::IsDebugging(Thread* thread, const Function& func) {
+ Debugger* debugger = thread->isolate()->debugger();
+ return debugger->IsStepping() ||
+ debugger->HasBreakpoint(func, thread->zone());
+}
+
void Debugger::SignalPausedEvent(ActivationFrame* top_frame, Breakpoint* bpt) {
resume_action_ = kContinue;
ResetSteppingFramePointers();
@@ -3836,7 +4267,7 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-void Debugger::NotifyCompilation(const Function& func) {
+void Debugger::HandleCodeChange(bool bytecode_loaded, const Function& func) {
if (breakpoint_locations_ == NULL) {
// Return with minimal overhead if there are no breakpoints.
return;
@@ -3868,6 +4299,8 @@
loc->requested_column_number());
#endif // !defined(DART_PRECOMPILED_RUNTIME)
}
+ // TODO(regis): Bytecode closures are not currently added to
+ // object_store()->closure_functions(). Should they? Revisit.
inner_function = FindInnermostClosure(func, token_pos);
if (!inner_function.IsNull()) {
// The local function of a function we just compiled cannot
@@ -3887,11 +4320,11 @@
// There is no local function within func that contains the
// breakpoint token position. Resolve the breakpoint if necessary
// and set the code breakpoints.
- if (!loc->IsResolved()) {
+ if (!loc->IsResolved(bytecode_loaded)) {
// Resolve source breakpoint in the newly compiled function.
- TokenPosition bp_pos =
- ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
- loc->requested_column_number(), token_pos);
+ TokenPosition bp_pos = ResolveBreakpointPos(
+ bytecode_loaded, func, loc->token_pos(), loc->end_token_pos(),
+ loc->requested_column_number(), token_pos);
if (!bp_pos.IsDebugPause()) {
if (FLAG_verbose_debug) {
OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
@@ -3901,34 +4334,28 @@
}
TokenPosition requested_pos = loc->token_pos();
TokenPosition requested_end_pos = loc->end_token_pos();
- loc->SetResolved(func, bp_pos);
+ loc->SetResolved(bytecode_loaded, func, bp_pos);
Breakpoint* bpt = loc->breakpoints();
while (bpt != NULL) {
if (FLAG_verbose_debug) {
OS::PrintErr(
"Resolved BP %" Pd
" to pos %s, "
- "line %" Pd " col %" Pd
- ", "
"function '%s' (requested range %s-%s, "
"requested col %" Pd ")\n",
- bpt->id(), loc->token_pos().ToCString(), loc->LineNumber(),
- loc->ColumnNumber(), func.ToFullyQualifiedCString(),
- requested_pos.ToCString(), requested_end_pos.ToCString(),
- loc->requested_column_number());
+ bpt->id(), loc->token_pos().ToCString(),
+ func.ToFullyQualifiedCString(), requested_pos.ToCString(),
+ requested_end_pos.ToCString(), loc->requested_column_number());
}
SendBreakpointEvent(ServiceEvent::kBreakpointResolved, bpt);
bpt = bpt->next();
}
}
- ASSERT(loc->IsResolved());
+ ASSERT(loc->IsResolved(bytecode_loaded));
if (FLAG_verbose_debug) {
Breakpoint* bpt = loc->breakpoints();
while (bpt != NULL) {
- OS::PrintErr("Setting breakpoint %" Pd " at line %" Pd " col %" Pd
- ""
- " for %s '%s'\n",
- bpt->id(), loc->LineNumber(), loc->ColumnNumber(),
+ OS::PrintErr("Setting breakpoint %" Pd " for %s '%s'\n", bpt->id(),
func.IsClosureFunction() ? "closure" : "function",
String::Handle(func.name()).ToCString());
bpt = bpt->next();
@@ -3998,7 +4425,7 @@
// If there is one, assert in debug build but silently drop
// the latent breakpoint in release build.
BreakpointLocation* existing_loc =
- GetBreakpointLocation(script, first_token_pos, column_number);
+ GetBreakpointLocation(script, first_token_pos, -1, column_number);
ASSERT(existing_loc == NULL);
if (existing_loc == NULL) {
// Create and register a new source breakpoint for the
@@ -4201,21 +4628,25 @@
needs_breakpoint_cleanup_ = false;
}
-BreakpointLocation* Debugger::GetBreakpointLocation(const Script& script,
- TokenPosition token_pos,
- intptr_t requested_column,
- bool is_resolved) {
+BreakpointLocation* Debugger::GetBreakpointLocation(
+ const Script& script,
+ TokenPosition token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column,
+ TokenPosition bytecode_token_pos,
+ TokenPosition code_token_pos) {
BreakpointLocation* loc = breakpoint_locations_;
while (loc != NULL) {
- // When BreakpointLocation has been resolved BreakpointLocation
- // should check only token position. Whether column or line
- // breakpoint should be the same once resolved into the
- // same token position.
- bool column_match =
- (is_resolved) ? true
- : (loc->requested_column_number_ == requested_column);
- if ((loc->script_ == script.raw()) && (loc->token_pos_ == token_pos) &&
- column_match) {
+ if (loc->script_ == script.raw() &&
+ (!token_pos.IsReal() || (loc->token_pos_ == token_pos)) &&
+ ((requested_line == -1) ||
+ (loc->requested_line_number_ == requested_line)) &&
+ ((requested_column == -1) ||
+ (loc->requested_column_number_ == requested_column)) &&
+ (!bytecode_token_pos.IsReal() ||
+ (loc->bytecode_token_pos_ == bytecode_token_pos)) &&
+ (!code_token_pos.IsReal() ||
+ (loc->code_token_pos_ == code_token_pos))) {
return loc;
}
loc = loc->next();
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index 05230cd..e186720 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -7,6 +7,7 @@
#include "include/dart_tools_api.h"
+#include "vm/constants_kbc.h"
#include "vm/kernel_isolate.h"
#include "vm/object.h"
#include "vm/port.h"
@@ -140,12 +141,7 @@
intptr_t requested_line_number() const { return requested_line_number_; }
intptr_t requested_column_number() const { return requested_column_number_; }
- intptr_t LineNumber();
- intptr_t ColumnNumber();
-
- void GetCodeLocation(Library* lib,
- Script* script,
- TokenPosition* token_pos) const;
+ void GetCodeLocation(Script* script, TokenPosition* token_pos) const;
Breakpoint* AddRepeated(Debugger* dbg);
Breakpoint* AddSingleShot(Debugger* dbg);
@@ -154,13 +150,21 @@
bool for_over_await);
bool AnyEnabled() const;
- bool IsResolved() const { return is_resolved_; }
+ bool IsResolved() const {
+ return bytecode_token_pos_.IsReal() || code_token_pos_.IsReal();
+ }
+ bool IsResolved(bool in_bytecode) const {
+ return in_bytecode ? bytecode_token_pos_.IsReal()
+ : code_token_pos_.IsReal();
+ }
bool IsLatent() const { return !token_pos_.IsReal(); }
private:
void VisitObjectPointers(ObjectPointerVisitor* visitor);
- void SetResolved(const Function& func, TokenPosition token_pos);
+ void SetResolved(bool in_bytecode,
+ const Function& func,
+ TokenPosition token_pos);
BreakpointLocation* next() const { return this->next_; }
void set_next(BreakpointLocation* value) { next_ = value; }
@@ -174,7 +178,6 @@
RawString* url_;
TokenPosition token_pos_;
TokenPosition end_token_pos_;
- bool is_resolved_;
BreakpointLocation* next_;
Breakpoint* conditions_;
intptr_t requested_line_number_;
@@ -182,22 +185,23 @@
// Valid for resolved breakpoints:
RawFunction* function_;
- intptr_t line_number_;
- intptr_t column_number_;
+ TokenPosition bytecode_token_pos_;
+ TokenPosition code_token_pos_;
friend class Debugger;
DISALLOW_COPY_AND_ASSIGN(BreakpointLocation);
};
-// CodeBreakpoint represents a location in compiled code. There may be
-// more than one CodeBreakpoint for one BreakpointLocation, e.g. when a
-// function gets compiled as a regular function and as a closure.
+// CodeBreakpoint represents a location in compiled or interpreted code.
+// There may be more than one CodeBreakpoint for one BreakpointLocation,
+// e.g. when a function gets compiled as a regular function and as a closure.
class CodeBreakpoint {
public:
CodeBreakpoint(const Code& code,
TokenPosition token_pos,
uword pc,
RawPcDescriptors::Kind kind);
+ CodeBreakpoint(const Bytecode& bytecode, TokenPosition token_pos, uword pc);
~CodeBreakpoint();
RawFunction* function() const;
@@ -211,6 +215,7 @@
void Enable();
void Disable();
bool IsEnabled() const { return is_enabled_; }
+ bool IsInterpreted() const { return bytecode_ != Bytecode::null(); }
RawCode* OrigStubAddress() const;
@@ -225,8 +230,11 @@
void PatchCode();
void RestoreCode();
+ void SetBytecodeBreak();
+ void UnsetBytecodeBreak();
RawCode* code_;
+ RawBytecode* bytecode_;
TokenPosition token_pos_;
uword pc_;
intptr_t line_number_;
@@ -271,6 +279,16 @@
ActivationFrame(uword pc, const Code& code);
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ ActivationFrame(uword pc,
+ uword fp,
+ uword sp,
+ const Bytecode& bytecode,
+ Kind kind = kRegular);
+
+ ActivationFrame(uword pc, const Bytecode& bytecode);
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
+
explicit ActivationFrame(Kind kind);
explicit ActivationFrame(const Closure& async_activation);
@@ -286,7 +304,11 @@
ASSERT(!code_.IsNull());
return code_;
}
- bool is_interpreted() const { return is_interpreted_; }
+ const Bytecode& bytecode() const {
+ ASSERT(!bytecode_.IsNull());
+ return bytecode_;
+ }
+ bool IsInterpreted() const { return !bytecode_.IsNull(); }
RawString* QualifiedFunctionName();
RawString* SourceUrl();
@@ -399,6 +421,7 @@
// The anchor of the context chain for this function.
Context& ctx_;
Code& code_;
+ Bytecode& bytecode_;
Function& function_;
bool live_frame_; // Is this frame a live frame?
bool token_pos_initialized_;
@@ -416,7 +439,6 @@
Kind kind_;
- bool is_interpreted_; // Running under kernel bytecode interpreter.
bool vars_initialized_;
LocalVarDescriptors& var_descriptors_;
ZoneGrowableArray<intptr_t> desc_indices_;
@@ -442,6 +464,7 @@
void AddActivation(ActivationFrame* frame);
void AddMarker(ActivationFrame::Kind marker);
void AddAsyncCausalFrame(uword pc, const Code& code);
+ void AddAsyncCausalFrame(uword pc, const Bytecode& bytecode);
ZoneGrowableArray<ActivationFrame*> trace_;
@@ -476,7 +499,12 @@
void OnIsolateRunnable();
- void NotifyCompilation(const Function& func);
+ void NotifyCompilation(const Function& func) {
+ HandleCodeChange(/* bytecode_loaded = */ false, func);
+ }
+ void NotifyBytecodeLoaded(const Function& func) {
+ HandleCodeChange(/* bytecode_loaded = */ true, func);
+ }
void NotifyDoneLoading();
RawFunction* ResolveFunction(const Library& library,
@@ -547,6 +575,7 @@
// debugger's zone.
bool HasBreakpoint(const Function& func, Zone* zone);
bool HasBreakpoint(const Code& code);
+ // A Bytecode version of HasBreakpoint is not needed.
// Returns true if the call at address pc is patched to point to
// a debugger stub.
@@ -598,6 +627,7 @@
void PrintSettingsToJSONObject(JSONObject* jsobj) const;
static bool IsDebuggable(const Function& func);
+ static bool IsDebugging(Thread* thread, const Function& func);
intptr_t limitBreakpointId() { return next_id_; }
@@ -626,19 +656,30 @@
void FindCompiledFunctions(const Script& script,
TokenPosition start_pos,
TokenPosition end_pos,
- GrowableObjectArray* function_list);
+ GrowableObjectArray* bytecode_function_list,
+ GrowableObjectArray* code_function_list);
bool FindBestFit(const Script& script,
TokenPosition token_pos,
TokenPosition last_token_pos,
Function* best_fit);
RawFunction* FindInnermostClosure(const Function& function,
TokenPosition token_pos);
- TokenPosition ResolveBreakpointPos(const Function& func,
+ TokenPosition ResolveBreakpointPos(bool in_bytecode,
+ const Function& func,
TokenPosition requested_token_pos,
TokenPosition last_token_pos,
intptr_t requested_column,
TokenPosition exact_token_pos);
void DeoptimizeWorld();
+ BreakpointLocation* SetCodeBreakpoints(bool in_bytecode,
+ BreakpointLocation* loc,
+ const Script& script,
+ TokenPosition token_pos,
+ TokenPosition last_token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column,
+ TokenPosition exact_token_pos,
+ const GrowableObjectArray& functions);
BreakpointLocation* SetBreakpoint(const Script& script,
TokenPosition token_pos,
TokenPosition last_token_pos,
@@ -654,10 +695,13 @@
intptr_t column);
void RegisterBreakpointLocation(BreakpointLocation* bpt);
void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
- BreakpointLocation* GetBreakpointLocation(const Script& script,
- TokenPosition token_pos,
- intptr_t requested_column,
- bool is_resolved = false);
+ BreakpointLocation* GetBreakpointLocation(
+ const Script& script,
+ TokenPosition token_pos,
+ intptr_t requested_line,
+ intptr_t requested_column,
+ TokenPosition bytecode_token_pos = TokenPosition::kNoSource,
+ TokenPosition code_token_pos = TokenPosition::kNoSource);
void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
// Returns NULL if no breakpoint exists for the given address.
CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
@@ -666,6 +710,8 @@
void PrintBreakpointsListToJSONArray(BreakpointLocation* sbpt,
JSONArray* jsarr) const;
+ void HandleCodeChange(bool bytecode_loaded, const Function& func);
+
ActivationFrame* TopDartFrame() const;
static ActivationFrame* CollectDartFrame(
Isolate* isolate,
@@ -676,6 +722,12 @@
intptr_t deopt_frame_offset,
ActivationFrame::Kind kind = ActivationFrame::kRegular);
#if !defined(DART_PRECOMPILED_RUNTIME)
+ static ActivationFrame* CollectDartFrame(
+ Isolate* isolate,
+ uword pc,
+ StackFrame* frame,
+ const Bytecode& bytecode,
+ ActivationFrame::Kind kind = ActivationFrame::kRegular);
static RawArray* DeoptimizeToArray(Thread* thread,
StackFrame* frame,
const Code& code);
diff --git a/runtime/vm/debugger_kbc.cc b/runtime/vm/debugger_kbc.cc
new file mode 100644
index 0000000..2bfbb65
--- /dev/null
+++ b/runtime/vm/debugger_kbc.cc
@@ -0,0 +1,33 @@
+// 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.
+
+#include "vm/globals.h"
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/debugger.h"
+#include "vm/instructions_kbc.h"
+
+namespace dart {
+
+#ifndef PRODUCT
+
+void CodeBreakpoint::SetBytecodeBreak() {
+ ASSERT(!is_enabled_);
+ ASSERT(!Isolate::Current()->is_using_old_bytecode_instructions());
+ // TODO(regis): Register pc_ (or the token pos range including pc_) with the
+ // interpreter as a debug break address.
+ is_enabled_ = true;
+}
+
+void CodeBreakpoint::UnsetBytecodeBreak() {
+ ASSERT(is_enabled_);
+ // TODO(regis): Unregister pc_ (or the token pos range including pc_) with the
+ // interpreter as a debug break address.
+ is_enabled_ = false;
+}
+#endif // !PRODUCT
+
+} // namespace dart
+
+#endif // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/dwarf.cc b/runtime/vm/dwarf.cc
index 1165836..29e5488 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -5,6 +5,7 @@
#include "vm/dwarf.h"
#include "vm/code_descriptors.h"
+#include "vm/elf.h"
#include "vm/object_store.h"
namespace dart {
@@ -51,26 +52,37 @@
InliningNode* children_next;
};
-Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream)
+Dwarf::Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf)
: zone_(zone),
- stream_(stream),
+ elf_(elf),
+ asm_stream_(stream),
+ bin_stream_(nullptr),
codes_(zone, 1024),
code_to_index_(zone),
functions_(zone, 1024),
function_to_index_(zone),
scripts_(zone, 1024),
script_to_index_(zone),
- temp_(0) {}
+ abstract_origins_(nullptr),
+ temp_(0) {
+ // Either assembler or direct to ELF.
+ RELEASE_ASSERT((stream == nullptr) != (elf == nullptr));
+}
intptr_t Dwarf::AddCode(const Code& code) {
+ intptr_t index = codes_.length();
+ AddCode(code, index);
+ return index;
+}
+
+void Dwarf::AddCode(const Code& code, intptr_t offset) {
RELEASE_ASSERT(!code.IsNull());
CodeIndexPair* pair = code_to_index_.Lookup(&code);
if (pair != NULL) {
- return pair->index_;
+ return; // UNREACHABLE?
}
- intptr_t index = codes_.length();
const Code& zone_code = Code::ZoneHandle(zone_, code.raw());
- code_to_index_.Insert(CodeIndexPair(&zone_code, index));
+ code_to_index_.Insert(CodeIndexPair(&zone_code, offset));
codes_.Add(&zone_code);
if (code.IsFunctionCode()) {
const Function& function = Function::Handle(zone_, code.function());
@@ -85,7 +97,6 @@
AddFunction(function);
}
}
- return index;
}
intptr_t Dwarf::AddFunction(const Function& function) {
@@ -140,23 +151,36 @@
void Dwarf::Print(const char* format, ...) {
va_list args;
va_start(args, format);
- stream_->VPrint(format, args);
+ asm_stream_->VPrint(format, args);
va_end(args);
}
-void Dwarf::WriteAbbreviations() {
-// Dwarf data mostly takes the form of a tree, whose nodes are called
-// DIEs. Each DIE begins with an abbreviation code, and the abbreviation
-// describes the attributes of that DIE and their representation.
+static uint8_t* ZoneReallocate(uint8_t* ptr,
+ intptr_t old_size,
+ intptr_t new_size) {
+ return Thread::Current()->zone()->Realloc<uint8_t>(ptr, old_size, new_size);
+}
+void Dwarf::WriteAbbreviations() {
+ // Dwarf data mostly takes the form of a tree, whose nodes are called
+ // DIEs. Each DIE begins with an abbreviation code, and the abbreviation
+ // describes the attributes of that DIE and their representation.
+
+ uint8_t* buffer = nullptr;
+ WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+ if (asm_stream_) {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_abbrev,regular,debug\n");
+ Print(".section __DWARF,__debug_abbrev,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_abbrev,\"\"\n");
+ Print(".section .debug_abbrev,\"\"\n");
#else
- UNIMPLEMENTED();
+ UNIMPLEMENTED();
#endif
+ } else {
+ bin_stream_ = &stream;
+ }
uleb128(kCompilationUnit); // Abbrev code.
uleb128(DW_TAG_compile_unit); // Type.
@@ -219,25 +243,44 @@
uleb128(0); // End of attributes.
uleb128(0); // End of abbreviations.
+
+ if (elf_) {
+ elf_->AddDebug(".debug_abbrev", buffer, stream.bytes_written());
+ bin_stream_ = nullptr;
+ }
}
void Dwarf::WriteCompilationUnit() {
-// 7.5.1.1 Compilation Unit Header
+ uint8_t* buffer = nullptr;
+ WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+ if (asm_stream_) {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_info,regular,debug\n");
+ Print(".section __DWARF,__debug_info,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_info,\"\"\n");
+ Print(".section .debug_info,\"\"\n");
#else
- UNIMPLEMENTED();
+ UNIMPLEMENTED();
#endif
- Print(".Ldebug_info:\n");
+ Print(".Ldebug_info:\n");
+ } else {
+ bin_stream_ = &stream;
+ }
+
+ // 7.5.1.1 Compilation Unit Header
// Unit length. Assignment to temp works around buggy Mac assembler.
- Print("Lcu_size = .Lcu_end - .Lcu_start\n");
- Print(".4byte Lcu_size\n");
- Print(".Lcu_start:\n");
+ intptr_t cu_size_fixup = 0;
+ intptr_t cu_start = 0;
+ if (asm_stream_) {
+ Print("Lcu_size = .Lcu_end - .Lcu_start\n");
+ Print(".4byte Lcu_size\n");
+ Print(".Lcu_start:\n");
+ } else {
+ cu_size_fixup = u4(0);
+ cu_start = position();
+ }
u2(2); // DWARF version 2
u4(0); // debug_abbrev_offset
@@ -250,24 +293,32 @@
const Library& root_library = Library::Handle(
zone_, Isolate::Current()->object_store()->root_library());
const String& root_uri = String::Handle(zone_, root_library.url());
- Print(".string \"%s\"\n", root_uri.ToCString()); // DW_AT_name
- Print(".string \"Dart VM\"\n"); // DW_AT_producer
- Print(".string \"\"\n"); // DW_AT_comp_dir
+ string(root_uri.ToCString()); // DW_AT_name
+ string("Dart VM"); // DW_AT_producer
+ string(""); // DW_AT_comp_dir
// DW_AT_low_pc
// The lowest instruction address in this object file that is part of our
// compilation unit. Dwarf consumers use this to quickly decide which
// compilation unit DIE to consult for a given pc.
- Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+ if (asm_stream_) {
+ Print(FORM_ADDR " _kDartIsolateSnapshotInstructions\n");
+ } else {
+ addr(0);
+ }
// DW_AT_high_pc
// The highest instruction address in this object file that is part of our
// compilation unit. Dwarf consumers use this to quickly decide which
// compilation unit DIE to consult for a given pc.
- intptr_t last_code_index = codes_.length() - 1;
- const Code& last_code = *(codes_[last_code_index]);
- Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
- last_code.Size());
+ if (asm_stream_) {
+ intptr_t last_code_index = codes_.length() - 1;
+ const Code& last_code = *(codes_[last_code_index]);
+ Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", last_code_index,
+ last_code.Size());
+ } else {
+ addr(elf_->NextMemoryOffset());
+ }
// DW_AT_stmt_list (offset into .debug_line)
// Indicates which line number program is associated with this compilation
@@ -280,12 +331,23 @@
uleb128(0); // End of children.
uleb128(0); // End of entries.
- Print(".Lcu_end:\n");
+
+ if (asm_stream_) {
+ Print(".Lcu_end:\n");
+ } else {
+ fixup_u4(cu_size_fixup, position() - cu_start);
+
+ elf_->AddDebug(".debug_info", buffer, stream.bytes_written());
+ bin_stream_ = nullptr;
+ }
}
void Dwarf::WriteAbstractFunctions() {
Script& script = Script::Handle(zone_);
String& name = String::Handle(zone_);
+ if (!asm_stream_) {
+ abstract_origins_ = zone_->Alloc<uint32_t>(functions_.length());
+ }
for (intptr_t i = 0; i < functions_.length(); i++) {
const Function& function = *(functions_[i]);
name = function.QualifiedUserVisibleName();
@@ -293,13 +355,18 @@
intptr_t file = LookupScript(script);
intptr_t line = 0; // Not known. Script has already lost its token stream.
- Print(".Lfunc%" Pd ":\n", i); // Label for DW_AT_abstract_origin references
+ if (asm_stream_) {
+ Print(".Lfunc%" Pd ":\n",
+ i); // Label for DW_AT_abstract_origin references
+ } else {
+ abstract_origins_[i] = position();
+ }
uleb128(kAbstractFunction);
- Print(".string \"%s\"\n", name.ToCString()); // DW_AT_name
- uleb128(file); // DW_AT_decl_file
- uleb128(line); // DW_AT_decl_line
- uleb128(DW_INL_inlined); // DW_AT_inline
- uleb128(0); // End of children.
+ string(name.ToCString()); // DW_AT_name
+ uleb128(file); // DW_AT_decl_file
+ uleb128(line); // DW_AT_decl_line
+ uleb128(DW_INL_inlined); // DW_AT_inline
+ uleb128(0); // End of children.
}
}
@@ -312,6 +379,11 @@
if (!code.IsFunctionCode()) {
continue;
}
+
+ CodeIndexPair* pair = code_to_index_.Lookup(&code);
+ RELEASE_ASSERT(pair != NULL);
+ intptr_t code_offset = pair->index_;
+
function = code.function();
intptr_t function_index = LookupFunction(function);
script = function.script();
@@ -320,15 +392,27 @@
// DW_AT_abstract_origin
// References a node written above in WriteAbstractFunctions.
// Assignment to temp works around buggy Mac assembler.
- intptr_t temp = temp_++;
- Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
- function_index);
- Print(".4byte Ltemp%" Pd "\n", temp);
+ if (asm_stream_) {
+ intptr_t temp = temp_++;
+ Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+ function_index);
+ Print(".4byte Ltemp%" Pd "\n", temp);
+ } else {
+ u4(abstract_origins_[function_index]);
+ }
// DW_AT_low_pc
- Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+ if (asm_stream_) {
+ Print(FORM_ADDR " .Lcode%" Pd "\n", i);
+ } else {
+ addr(code_offset);
+ }
// DW_AT_high_pc
- Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+ if (asm_stream_) {
+ Print(FORM_ADDR " .Lcode%" Pd " + %" Pd "\n", i, code.Size());
+ } else {
+ addr(code_offset + code.Size());
+ }
InliningNode* node = ExpandInliningTree(code);
if (node != NULL) {
@@ -435,15 +519,28 @@
// DW_AT_abstract_origin
// References a node written above in WriteAbstractFunctions.
// Assignment to temp works around buggy Mac assembler.
- intptr_t temp = temp_++;
- Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp, function_index);
- Print(".4byte Ltemp%" Pd "\n", temp);
+ if (asm_stream_) {
+ intptr_t temp = temp_++;
+ Print("Ltemp%" Pd " = .Lfunc%" Pd " - .Ldebug_info\n", temp,
+ function_index);
+ Print(".4byte Ltemp%" Pd "\n", temp);
+ } else {
+ u4(abstract_origins_[function_index]);
+ }
// DW_AT_low_pc
- Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
- node->start_pc_offset);
+ if (asm_stream_) {
+ Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+ node->start_pc_offset);
+ } else {
+ addr(root_code_index + node->start_pc_offset);
+ }
// DW_AT_high_pc
- Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
- node->end_pc_offset);
+ if (asm_stream_) {
+ Print(FORM_ADDR " .Lcode%" Pd " + %d\n", root_code_index,
+ node->end_pc_offset);
+ } else {
+ addr(root_code_index + node->end_pc_offset);
+ }
// DW_AT_call_file
uleb128(file);
// DW_AT_call_line
@@ -458,30 +555,50 @@
}
void Dwarf::WriteLines() {
+ uint8_t* buffer = nullptr;
+ WriteStream stream(&buffer, ZoneReallocate, 64 * KB);
+
+ if (asm_stream_) {
#if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
- Print(".section __DWARF,__debug_line,regular,debug\n");
+ Print(".section __DWARF,__debug_line,regular,debug\n");
#elif defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID) || \
defined(TARGET_OS_FUCHSIA)
- Print(".section .debug_line,\"\"\n");
+ Print(".section .debug_line,\"\"\n");
#else
- UNIMPLEMENTED();
+ UNIMPLEMENTED();
#endif
+ } else {
+ bin_stream_ = &stream;
+ }
// 6.2.4 The Line Number Program Header
// 1. unit_length. This encoding implies 32-bit DWARF.
- Print("Lline_size = .Lline_end - .Lline_start\n");
- Print(".4byte Lline_size\n");
-
- Print(".Lline_start:\n");
+ intptr_t line_size_fixup = 0;
+ intptr_t line_start = 0;
+ if (asm_stream_) {
+ Print("Lline_size = .Lline_end - .Lline_start\n");
+ Print(".4byte Lline_size\n");
+ Print(".Lline_start:\n");
+ } else {
+ line_size_fixup = u4(0);
+ line_start = position();
+ }
u2(2); // 2. DWARF version 2
// 3. header_length
// Assignment to temp works around buggy Mac assembler.
- Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
- Print(".4byte Llineheader_size\n");
- Print(".Llineheader_start:\n");
+ intptr_t lineheader_size_fixup = 0;
+ intptr_t lineheader_start = 0;
+ if (asm_stream_) {
+ Print("Llineheader_size = .Llineheader_end - .Llineheader_start\n");
+ Print(".4byte Llineheader_size\n");
+ Print(".Llineheader_start:\n");
+ } else {
+ lineheader_size_fixup = u4(0);
+ lineheader_start = position();
+ }
u1(1); // 4. minimum_instruction_length
u1(1); // 5. default_is_stmt (true for compatibility with dsymutil).
@@ -512,20 +629,24 @@
for (intptr_t i = 0; i < scripts_.length(); i++) {
const Script& script = *(scripts_[i]);
uri = script.url();
- Print(".string \"%s\"\n", uri.ToCString());
+ string(uri.ToCString()); // NOLINT
uleb128(0); // Include directory index.
uleb128(0); // File modification time.
uleb128(0); // File length.
}
u1(0); // End of file names.
- Print(".Llineheader_end:\n");
+ if (asm_stream_) {
+ Print(".Llineheader_end:\n");
+ } else {
+ fixup_u4(lineheader_size_fixup, position() - lineheader_start);
+ }
// 6.2.5 The Line Number Program
intptr_t previous_file = 1;
intptr_t previous_line = 1;
- intptr_t previous_code_index = -1;
+ intptr_t previous_code_offset = -1;
intptr_t previous_pc_offset = 0;
Function& root_function = Function::Handle(zone_);
@@ -537,6 +658,11 @@
for (intptr_t i = 0; i < codes_.length(); i++) {
const Code& code = *(codes_[i]);
+
+ CodeIndexPair* pair = code_to_index_.Lookup(&code);
+ RELEASE_ASSERT(pair != NULL);
+ intptr_t current_code_offset = pair->index_;
+
map = code.code_source_map();
if (map.IsNull()) {
continue;
@@ -591,18 +717,30 @@
u1(DW_LNS_copy);
// 4. Update LNP pc.
- if (previous_code_index == -1) {
+ if (previous_code_offset == -1) {
// This variant is relocatable.
u1(0); // This is an extended opcode
u1(1 + sizeof(void*)); // that is 5 or 9 bytes long
u1(DW_LNE_set_address);
- Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+ if (asm_stream_) {
+ Print(FORM_ADDR " .Lcode%" Pd " + %d\n", i, current_pc_offset);
+ } else {
+ addr(current_code_offset + current_pc_offset);
+ }
} else {
u1(DW_LNS_advance_pc);
- Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
- previous_code_index, current_pc_offset - previous_pc_offset);
+ if (asm_stream_) {
+ Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", i,
+ previous_code_offset,
+ current_pc_offset - previous_pc_offset);
+ } else {
+ intptr_t delta = current_code_offset - previous_code_offset +
+ current_pc_offset - previous_pc_offset;
+ RELEASE_ASSERT(delta > 0);
+ uleb128(delta);
+ }
}
- previous_code_index = i;
+ previous_code_offset = current_code_offset;
previous_pc_offset = current_pc_offset;
break;
}
@@ -635,16 +773,35 @@
// Advance pc to end of the compilation unit.
intptr_t last_code_index = codes_.length() - 1;
const Code& last_code = *(codes_[last_code_index]);
+
+ CodeIndexPair* pair = code_to_index_.Lookup(&last_code);
+ RELEASE_ASSERT(pair != NULL);
+ intptr_t last_code_offset = pair->index_;
+
u1(DW_LNS_advance_pc);
- Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
- previous_code_index, last_code.Size() - previous_pc_offset);
+ if (asm_stream_) {
+ Print(".uleb128 .Lcode%" Pd " - .Lcode%" Pd " + %" Pd "\n", last_code_index,
+ previous_code_offset, last_code.Size() - previous_pc_offset);
+ } else {
+ intptr_t delta = last_code_offset - previous_code_offset +
+ last_code.Size() - previous_pc_offset;
+ RELEASE_ASSERT(delta >= 0);
+ uleb128(delta);
+ }
// End of contiguous machine code.
u1(0); // This is an extended opcode
u1(1); // that is 1 byte long
u1(DW_LNE_end_sequence);
- Print(".Lline_end:\n");
+ if (asm_stream_) {
+ Print(".Lline_end:\n");
+ } else {
+ fixup_u4(line_size_fixup, position() - line_start);
+
+ elf_->AddDebug(".debug_line", buffer, stream.bytes_written());
+ bin_stream_ = nullptr;
+ }
}
#endif // DART_PRECOMPILER
diff --git a/runtime/vm/dwarf.h b/runtime/vm/dwarf.h
index cd68542..7d4f5b7 100644
--- a/runtime/vm/dwarf.h
+++ b/runtime/vm/dwarf.h
@@ -14,6 +14,7 @@
#ifdef DART_PRECOMPILER
+class Elf;
class InliningNode;
struct ScriptIndexPair {
@@ -117,8 +118,9 @@
class Dwarf : public ZoneAllocated {
public:
- Dwarf(Zone* zone, StreamingWriteStream* stream);
+ Dwarf(Zone* zone, StreamingWriteStream* stream, Elf* elf);
+ void AddCode(const Code& code, intptr_t offset);
intptr_t AddCode(const Code& code);
intptr_t AddFunction(const Function& function);
intptr_t AddScript(const Script& script);
@@ -181,11 +183,100 @@
};
void Print(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
- void sleb128(intptr_t value) { Print(".sleb128 %" Pd "\n", value); }
- void uleb128(uintptr_t value) { Print(".uleb128 %" Pd "\n", value); }
- void u1(uint8_t value) { Print(".byte %d\n", value); }
- void u2(uint16_t value) { Print(".2byte %d\n", value); }
- void u4(uint32_t value) { Print(".4byte %d\n", value); }
+ void sleb128(intptr_t value) {
+ if (asm_stream_) {
+ Print(".sleb128 %" Pd "\n", value);
+ } else {
+ bool is_last_part = false;
+ while (!is_last_part) {
+ uint8_t part = value & 0x7F;
+ value >>= 7;
+ if ((value == 0 && (part & 0x40) == 0) ||
+ (value == static_cast<intptr_t>(-1) && (part & 0x40) != 0)) {
+ is_last_part = true;
+ } else {
+ part |= 0x80;
+ }
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+ sizeof(part));
+ }
+ }
+ }
+ void uleb128(uintptr_t value) {
+ if (asm_stream_) {
+ Print(".uleb128 %" Pd "\n", value);
+ } else {
+ bool is_last_part = false;
+ while (!is_last_part) {
+ uint8_t part = value & 0x7F;
+ value >>= 7;
+ if (value == 0) {
+ is_last_part = true;
+ } else {
+ part |= 0x80;
+ }
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&part),
+ sizeof(part));
+ }
+ }
+ }
+ void u1(uint8_t value) {
+ if (asm_stream_) {
+ Print(".byte %d\n", value);
+ } else {
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+ sizeof(value));
+ }
+ }
+ void u2(uint16_t value) {
+ if (asm_stream_) {
+ Print(".2byte %d\n", value);
+ } else {
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+ sizeof(value));
+ }
+ }
+ intptr_t u4(uint32_t value) {
+ if (asm_stream_) {
+ Print(".4byte %d\n", value);
+ return -1;
+ } else {
+ intptr_t fixup = position();
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+ sizeof(value));
+ return fixup;
+ }
+ }
+ void fixup_u4(intptr_t position, uint32_t value) {
+ if (asm_stream_) {
+ UNREACHABLE();
+ } else {
+ memmove(bin_stream_->buffer() + position, &value, sizeof(value));
+ }
+ }
+ void addr(uword value) {
+ if (asm_stream_) {
+ UNREACHABLE();
+ } else {
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(&value),
+ sizeof(value));
+ }
+ }
+ void string(const char* cstr) { // NOLINT
+ if (asm_stream_) {
+ Print(".string \"%s\"\n", cstr); // NOLINT
+ } else {
+ bin_stream_->WriteBytes(reinterpret_cast<const uint8_t*>(cstr),
+ strlen(cstr) + 1);
+ }
+ }
+ intptr_t position() {
+ if (asm_stream_) {
+ UNREACHABLE();
+ } else {
+ return bin_stream_->Position();
+ }
+ }
void WriteAbbreviations();
void WriteCompilationUnit();
@@ -198,13 +289,16 @@
void WriteLines();
Zone* const zone_;
- StreamingWriteStream* stream_;
+ Elf* const elf_;
+ StreamingWriteStream* asm_stream_;
+ WriteStream* bin_stream_;
ZoneGrowableArray<const Code*> codes_;
CodeIndexMap code_to_index_;
ZoneGrowableArray<const Function*> functions_;
FunctionIndexMap function_to_index_;
ZoneGrowableArray<const Script*> scripts_;
ScriptIndexMap script_to_index_;
+ uint32_t* abstract_origins_;
intptr_t temp_;
};
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
new file mode 100644
index 0000000..206ead1
--- /dev/null
+++ b/runtime/vm/elf.cc
@@ -0,0 +1,750 @@
+// 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.
+
+#include "vm/elf.h"
+
+#include "platform/text_buffer.h"
+#include "vm/cpu.h"
+#include "vm/thread.h"
+
+namespace dart {
+
+#define ELFCLASS32 1
+#define ELFCLASS64 2
+
+static const intptr_t ELFDATA2LSB = 1;
+
+static const intptr_t ELFOSABI_SYSV = 0;
+
+#define EF_ARM_ABI_FLOAT_HARD 0x00000400
+#define EF_ARM_ABI_FLOAT_SOFT 0x00000200
+#define EF_ARM_ABI 0x05000000
+
+static const intptr_t ET_DYN = 3;
+
+#define EM_386 3
+#define EM_ARM 40
+#define EM_X86_64 62
+#define EM_AARCH64 183
+
+static const intptr_t EV_CURRENT = 1;
+
+static const intptr_t SHT_PROGBITS = 1;
+static const intptr_t SHT_STRTAB = 3;
+static const intptr_t SHT_HASH = 5;
+static const intptr_t SHT_DYNSYM = 11;
+static const intptr_t SHT_DYNAMIC = 6;
+
+static const intptr_t SHF_WRITE = 0x1;
+static const intptr_t SHF_ALLOC = 0x2;
+static const intptr_t SHF_EXECINSTR = 0x4;
+
+static const intptr_t SHN_UNDEF = 0;
+
+static const intptr_t STN_UNDEF = 0;
+
+static const intptr_t PT_LOAD = 1;
+static const intptr_t PT_DYNAMIC = 2;
+static const intptr_t PT_PHDR = 6;
+
+static const intptr_t PF_X = 1;
+static const intptr_t PF_W = 2;
+static const intptr_t PF_R = 4;
+
+static const intptr_t STB_GLOBAL = 1;
+
+static const intptr_t STT_OBJECT = 1; // I.e., data.
+static const intptr_t STT_FUNC = 2;
+
+static const intptr_t DT_HASH = 4;
+static const intptr_t DT_STRTAB = 5;
+static const intptr_t DT_SYMTAB = 6;
+static const intptr_t DT_STRSZ = 10;
+static const intptr_t DT_SYMENT = 11;
+
+#if defined(TARGET_ARCH_IS_32_BIT)
+static const intptr_t kElfHeaderSize = 52;
+static const intptr_t kElfSectionTableEntrySize = 40;
+static const intptr_t kElfProgramTableEntrySize = 32;
+static const intptr_t kElfSymbolTableEntrySize = 16;
+static const intptr_t kElfDynamicTableEntrySize = 8;
+#else
+static const intptr_t kElfHeaderSize = 64;
+static const intptr_t kElfSectionTableEntrySize = 64;
+static const intptr_t kElfProgramTableEntrySize = 56;
+static const intptr_t kElfSymbolTableEntrySize = 24;
+static const intptr_t kElfDynamicTableEntrySize = 16;
+#endif
+
+static const intptr_t kPageSize = 4096;
+
+class Section : public ZoneAllocated {
+ public:
+ Section() {}
+
+ virtual ~Section() {}
+ virtual void Write(Elf* stream) = 0;
+
+ // Linker view.
+ intptr_t section_name = 0; // Index into string table.
+ intptr_t section_type = 0;
+ intptr_t section_flags = 0;
+ intptr_t section_index = -1;
+ intptr_t section_link = SHN_UNDEF;
+ intptr_t section_info = 0;
+ intptr_t section_entry_size = 0;
+ intptr_t file_size = 0;
+ intptr_t file_offset = -1;
+
+ intptr_t alignment = 1;
+
+ // Loader view.
+ intptr_t segment_type = -1;
+ intptr_t segment_flags = 0;
+ intptr_t memory_size = 0;
+ intptr_t memory_offset = -1;
+};
+
+class ProgramBits : public Section {
+ public:
+ ProgramBits(bool allocate,
+ bool executable,
+ const uint8_t* bytes,
+ intptr_t size) {
+ section_type = SHT_PROGBITS;
+ if (allocate) {
+ section_flags = SHF_ALLOC;
+ if (executable) section_flags |= SHF_EXECINSTR;
+
+ segment_type = PT_LOAD;
+ segment_flags = PF_R;
+ if (executable) segment_flags |= PF_X;
+ }
+
+ bytes_ = bytes;
+ file_size = memory_size = size;
+ }
+
+ void Write(Elf* stream) { stream->WriteBytes(bytes_, memory_size); }
+
+ const uint8_t* bytes_;
+};
+
+class StringTable : public Section {
+ public:
+ StringTable() : text_(128) {
+ section_type = SHT_STRTAB;
+ section_flags = SHF_ALLOC;
+ segment_type = PT_LOAD;
+ segment_flags = PF_R;
+
+ text_.AddChar('\0');
+ memory_size = file_size = text_.length();
+ }
+
+ intptr_t AddString(const char* str) {
+ intptr_t offset = text_.length();
+ text_.AddString(str);
+ text_.AddChar('\0');
+ memory_size = file_size = text_.length();
+ return offset;
+ }
+
+ void Write(Elf* stream) {
+ stream->WriteBytes(reinterpret_cast<const uint8_t*>(text_.buf()),
+ text_.length());
+ }
+
+ TextBuffer text_;
+};
+
+class Symbol : public ZoneAllocated {
+ public:
+ const char* cstr;
+ intptr_t name;
+ intptr_t info;
+ intptr_t section;
+ intptr_t offset;
+ intptr_t size;
+};
+
+class SymbolTable : public Section {
+ public:
+ SymbolTable() {
+ section_type = SHT_DYNSYM;
+ section_flags = SHF_ALLOC;
+ segment_type = PT_LOAD;
+ segment_flags = PF_R;
+
+ section_entry_size = kElfSymbolTableEntrySize;
+ AddSymbol(NULL);
+ section_info = 1; // One "local" symbol, the reserved first entry.
+ }
+
+ void AddSymbol(Symbol* symbol) {
+ symbols_.Add(symbol);
+ memory_size += kElfSymbolTableEntrySize;
+ file_size += kElfSymbolTableEntrySize;
+ }
+
+ void Write(Elf* stream) {
+ // The first symbol table entry is reserved and must be all zeros.
+ {
+ const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ stream->WriteWord(0);
+ stream->WriteAddr(0);
+ stream->WriteWord(0);
+ stream->WriteByte(0);
+ stream->WriteByte(0);
+ stream->WriteHalf(0);
+#else
+ stream->WriteWord(0);
+ stream->WriteByte(0);
+ stream->WriteByte(0);
+ stream->WriteHalf(0);
+ stream->WriteAddr(0);
+ stream->WriteXWord(0);
+#endif
+ const intptr_t end = stream->position();
+ ASSERT((end - start) == kElfSymbolTableEntrySize);
+ }
+
+ for (intptr_t i = 1; i < symbols_.length(); i++) {
+ Symbol* symbol = symbols_[i];
+ const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ stream->WriteWord(symbol->name);
+ stream->WriteAddr(symbol->offset);
+ stream->WriteWord(symbol->size);
+ stream->WriteByte(symbol->info);
+ stream->WriteByte(0);
+ stream->WriteHalf(symbol->section);
+#else
+ stream->WriteWord(symbol->name);
+ stream->WriteByte(symbol->info);
+ stream->WriteByte(0);
+ stream->WriteHalf(symbol->section);
+ stream->WriteAddr(symbol->offset);
+ stream->WriteXWord(symbol->size);
+#endif
+ const intptr_t end = stream->position();
+ ASSERT((end - start) == kElfSymbolTableEntrySize);
+ }
+ }
+
+ intptr_t length() const { return symbols_.length(); }
+ Symbol* at(intptr_t i) const { return symbols_[i]; }
+
+ GrowableArray<Symbol*> symbols_;
+};
+
+static uint32_t ElfHash(const unsigned char* name) {
+ uint32_t h = 0;
+ while (*name) {
+ h = (h << 4) + *name++;
+ uint32_t g = h & 0xf0000000;
+ h ^= g;
+ h ^= g >> 24;
+ }
+ return h;
+}
+
+class SymbolHashTable : public Section {
+ public:
+ SymbolHashTable(StringTable* strtab, SymbolTable* symtab) {
+ section_type = SHT_HASH;
+ section_flags = SHF_ALLOC;
+ section_link = symtab->section_index;
+ segment_type = PT_LOAD;
+ segment_flags = PF_R;
+
+ nchain_ = symtab->length();
+ nbucket_ = symtab->length();
+
+ bucket_ = Thread::Current()->zone()->Alloc<int32_t>(nbucket_);
+ for (intptr_t i = 0; i < nbucket_; i++) {
+ bucket_[i] = STN_UNDEF;
+ }
+
+ chain_ = Thread::Current()->zone()->Alloc<int32_t>(nchain_);
+ for (intptr_t i = 0; i < nchain_; i++) {
+ chain_[i] = STN_UNDEF;
+ }
+
+ for (intptr_t i = 1; i < symtab->length(); i++) {
+ Symbol* symbol = symtab->at(i);
+ uint32_t hash = ElfHash((const unsigned char*)symbol->cstr);
+ uint32_t probe = hash % nbucket_;
+ chain_[i] = bucket_[probe]; // next = head
+ bucket_[probe] = i; // head = symbol
+ }
+
+ memory_size = file_size = 4 * (nbucket_ + nchain_ + 2);
+ }
+
+ void Write(Elf* stream) {
+ stream->WriteWord(nbucket_);
+ stream->WriteWord(nchain_);
+ for (intptr_t i = 0; i < nbucket_; i++) {
+ stream->WriteWord(bucket_[i]);
+ }
+ for (intptr_t i = 0; i < nchain_; i++) {
+ stream->WriteWord(chain_[i]);
+ }
+ }
+
+ private:
+ int32_t nbucket_;
+ int32_t nchain_;
+ int32_t* bucket_; // "Head"
+ int32_t* chain_; // "Next"
+};
+
+class DynamicTable : public Section {
+ public:
+ DynamicTable(StringTable* strtab,
+ SymbolTable* symtab,
+ SymbolHashTable* hash) {
+ section_type = SHT_DYNAMIC;
+ section_link = strtab->section_index;
+ section_flags = SHF_ALLOC | SHF_WRITE;
+ section_entry_size = kElfDynamicTableEntrySize;
+
+ segment_type = PT_LOAD;
+ segment_flags = PF_R | PF_W;
+
+ AddEntry(DT_HASH, hash->memory_offset);
+ AddEntry(DT_STRTAB, strtab->memory_offset);
+ AddEntry(DT_STRSZ, strtab->memory_size);
+ AddEntry(DT_SYMTAB, symtab->memory_offset);
+ AddEntry(DT_SYMENT, kElfSymbolTableEntrySize);
+ }
+
+ void Write(Elf* stream) {
+ for (intptr_t i = 0; i < entries_.length(); i++) {
+ const intptr_t start = stream->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ stream->WriteWord(entries_[i]->tag);
+ stream->WriteAddr(entries_[i]->value);
+#else
+ stream->WriteXWord(entries_[i]->tag);
+ stream->WriteAddr(entries_[i]->value);
+#endif
+ const intptr_t end = stream->position();
+ ASSERT((end - start) == kElfDynamicTableEntrySize);
+ }
+ }
+
+ class Entry {
+ public:
+ intptr_t tag;
+ intptr_t value;
+ };
+
+ void AddEntry(intptr_t tag, intptr_t value) {
+ Entry* entry = new Entry();
+ entry->tag = tag;
+ entry->value = value;
+ entries_.Add(entry);
+
+ memory_size += kElfDynamicTableEntrySize;
+ file_size += kElfDynamicTableEntrySize;
+ }
+
+ private:
+ GrowableArray<Entry*> entries_;
+};
+
+static uint8_t kNothing = 0;
+
+// The first section must be written out and contains only zeros.
+static const intptr_t kNumInvalidSections = 1;
+
+// Extra segments put in the program table that aren't reified in
+// Elf::segments_.
+static const intptr_t kNumImplicitSegments = 3;
+
+Elf::Elf(Zone* zone, StreamingWriteStream* stream)
+ : zone_(zone), stream_(stream), memory_offset_(0) {
+ // Assumed by various offset logic in this file.
+ ASSERT(stream_->position() == 0);
+
+ // We don't bother with a separate .shstrtab since all our strings will fit
+ // in a single page.
+ strtab_ = new (zone_) StringTable();
+ strtab_->section_name = strtab_->AddString(".dynstr");
+ AddSection(strtab_);
+
+ symtab_ = new (zone_) SymbolTable();
+ symtab_->section_name = strtab_->AddString(".dynsym");
+ symtab_->section_link = strtab_->section_index;
+ AddSection(symtab_);
+
+ // dlsym gets confused if a symbol's value is dso offset 0, treating this as a
+ // failed lookup instead of answering dso base + 0. dladdr answers the wrong
+ // dso base if we don't start allocating from 0 (answering the address of
+ // either the first or lowest PT_LOAD). Sacrifice the first page to work
+ // around these issues. (gcc places build metadata in the first page.)
+ AddROData("nothing", &kNothing, sizeof(kNothing));
+}
+
+void Elf::AddSection(Section* section) {
+ section->section_index = sections_.length() + kNumInvalidSections;
+ sections_.Add(section);
+}
+
+void Elf::AddSegment(Section* section) {
+ if (section->alignment < kPageSize) {
+ section->alignment = kPageSize;
+ }
+
+ memory_offset_ = Utils::RoundUp(memory_offset_, section->alignment);
+ section->memory_offset = memory_offset_;
+ memory_offset_ += section->memory_size;
+ segments_.Add(section);
+ memory_offset_ = Utils::RoundUp(memory_offset_, kPageSize);
+}
+
+intptr_t Elf::NextMemoryOffset() {
+ return memory_offset_;
+}
+
+intptr_t Elf::AddText(const char* name, const uint8_t* bytes, intptr_t size) {
+ ProgramBits* image = new (zone_) ProgramBits(true, true, bytes, size);
+ image->section_name = strtab_->AddString(".text");
+ AddSection(image);
+ AddSegment(image);
+
+ Symbol* symbol = new (zone_) Symbol();
+ symbol->cstr = name;
+ symbol->name = strtab_->AddString(name);
+ symbol->info = (STB_GLOBAL << 4) | STT_FUNC;
+ symbol->section = image->section_index;
+ // For shared libraries, this is the offset from the DSO base. For static
+ // libraries, this is section relative.
+ symbol->offset = image->memory_offset;
+ symbol->size = size;
+ symtab_->AddSymbol(symbol);
+
+ return symbol->offset;
+}
+
+intptr_t Elf::AddROData(const char* name, const uint8_t* bytes, intptr_t size) {
+ ProgramBits* image = new (zone_) ProgramBits(true, false, bytes, size);
+ image->section_name = strtab_->AddString(".rodata");
+ AddSection(image);
+ AddSegment(image);
+
+ Symbol* symbol = new (zone_) Symbol();
+ symbol->cstr = name;
+ symbol->name = strtab_->AddString(name);
+ symbol->info = (STB_GLOBAL << 4) | STT_OBJECT;
+ symbol->section = image->section_index;
+ // For shared libraries, this is the offset from the DSO base. For static
+ // libraries, this is section relative.
+ symbol->offset = image->memory_offset;
+ symbol->size = size;
+ symtab_->AddSymbol(symbol);
+
+ return symbol->offset;
+}
+
+void Elf::AddDebug(const char* name, const uint8_t* bytes, intptr_t size) {
+ ProgramBits* image = new (zone_) ProgramBits(false, false, bytes, size);
+ image->section_name = strtab_->AddString(name);
+ AddSection(image);
+}
+
+void Elf::Finalize() {
+ SymbolHashTable* hash = new (zone_) SymbolHashTable(strtab_, symtab_);
+ hash->section_name = strtab_->AddString(".hash");
+ AddSection(hash);
+ AddSegment(hash);
+
+ // Before finalizing the string table's memory size:
+ intptr_t name_dynamic = strtab_->AddString(".dynamic");
+
+ // Finalizes memory size of string and symbol tables.
+ AddSegment(strtab_);
+ AddSegment(symtab_);
+
+ dynamic_ = new (zone_) DynamicTable(strtab_, symtab_, hash);
+ dynamic_->section_name = name_dynamic;
+ AddSection(dynamic_);
+ AddSegment(dynamic_);
+
+ ComputeFileOffsets();
+
+ WriteHeader();
+ WriteProgramTable();
+ WriteSectionTable();
+ WriteSections();
+}
+
+void Elf::ComputeFileOffsets() {
+ intptr_t file_offset = kElfHeaderSize;
+
+ file_offset = Utils::RoundUp(file_offset, kPageSize);
+ program_table_file_offset_ = file_offset;
+ program_table_file_size_ =
+ (segments_.length() + kNumImplicitSegments) * kElfProgramTableEntrySize;
+ file_offset += program_table_file_size_;
+
+ section_table_file_offset_ = file_offset;
+ section_table_file_size_ =
+ (sections_.length() + kNumInvalidSections) * kElfSectionTableEntrySize;
+ file_offset += section_table_file_size_;
+
+ for (intptr_t i = 0; i < sections_.length(); i++) {
+ Section* section = sections_[i];
+ file_offset = Utils::RoundUp(file_offset, section->alignment);
+ section->file_offset = file_offset;
+ file_offset += section->file_size;
+ file_offset = Utils::RoundUp(file_offset, section->alignment);
+ }
+}
+
+void Elf::WriteHeader() {
+#if defined(TARGET_ARCH_IS_32_BIT)
+ uint8_t size = ELFCLASS32;
+#else
+ uint8_t size = ELFCLASS64;
+#endif
+ uint8_t e_ident[16] = {
+ 0x7f, 'E', 'L', 'F', size, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+ stream_->WriteBytes(e_ident, 16);
+
+ WriteHalf(ET_DYN); // Shared library.
+
+#if defined(TARGET_ARCH_IA32)
+ WriteHalf(EM_386);
+#elif defined(TARGET_ARCH_X64)
+ WriteHalf(EM_X86_64);
+#elif defined(TARGET_ARCH_ARM)
+ WriteHalf(EM_ARM);
+#elif defined(TARGET_ARCH_ARM64)
+ WriteHalf(EM_AARCH64);
+#else
+ // E.g., DBC.
+ FATAL("Unknown ELF architecture");
+#endif
+
+ WriteWord(EV_CURRENT); // Version
+ WriteAddr(0); // "Entry point"
+ WriteOff(program_table_file_offset_);
+ WriteOff(section_table_file_offset_);
+
+#if defined(TARGET_ARCH_ARM)
+ uword flags = EF_ARM_ABI |
+ (TargetCPUFeatures::hardfp_supported() ? EF_ARM_ABI_FLOAT_HARD
+ : EF_ARM_ABI_FLOAT_SOFT);
+#else
+ uword flags = 0;
+#endif
+ WriteWord(flags);
+
+ WriteHalf(kElfHeaderSize);
+ WriteHalf(kElfProgramTableEntrySize);
+ WriteHalf(segments_.length() + kNumImplicitSegments);
+ WriteHalf(kElfSectionTableEntrySize);
+ WriteHalf(sections_.length() + kNumInvalidSections);
+ WriteHalf(strtab_->section_index);
+
+ ASSERT(stream_->position() == kElfHeaderSize);
+}
+
+void Elf::WriteProgramTable() {
+ stream_->Align(kPageSize);
+
+ ASSERT(stream_->position() == program_table_file_offset_);
+
+ // Self-reference to program header table that Android wants for some reason.
+ // Must appear before any PT_LOAD entries.
+ {
+ ASSERT(kNumImplicitSegments == 3);
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(PT_PHDR);
+ WriteOff(program_table_file_offset_);
+ WriteAddr(memory_offset_);
+ WriteAddr(0); // Physical address, not used.
+ WriteWord(program_table_file_size_);
+ WriteWord(program_table_file_size_);
+ WriteWord(PF_R);
+ WriteWord(kPageSize);
+#else
+ WriteWord(PT_PHDR);
+ WriteWord(PF_R);
+ WriteOff(program_table_file_offset_);
+ WriteAddr(memory_offset_);
+ WriteAddr(0); // Physical address, not used.
+ WriteXWord(program_table_file_size_);
+ WriteXWord(program_table_file_size_);
+ WriteXWord(kPageSize);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfProgramTableEntrySize);
+ }
+
+ for (intptr_t i = 0; i < segments_.length(); i++) {
+ Section* section = segments_[i];
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(section->segment_type);
+ WriteOff(section->file_offset);
+ WriteAddr(section->memory_offset);
+ WriteAddr(0); // Physical address, not used.
+ WriteWord(section->file_size);
+ WriteWord(section->memory_size);
+ WriteWord(section->segment_flags);
+ WriteWord(section->alignment);
+#else
+ WriteWord(section->segment_type);
+ WriteWord(section->segment_flags);
+ WriteOff(section->file_offset);
+ WriteAddr(section->memory_offset);
+ WriteAddr(0); // Physical address, not used.
+ WriteXWord(section->file_size);
+ WriteXWord(section->memory_size);
+ WriteXWord(section->alignment);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfProgramTableEntrySize);
+ }
+
+ // Special case: the dynamic section requires both LOAD and DYNAMIC program
+ // header table entries.
+ {
+ ASSERT(kNumImplicitSegments == 3);
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(PT_DYNAMIC);
+ WriteOff(dynamic_->file_offset);
+ WriteAddr(dynamic_->memory_offset);
+ WriteAddr(0); // Physical address, not used.
+ WriteWord(dynamic_->file_size);
+ WriteWord(dynamic_->memory_size);
+ WriteWord(dynamic_->segment_flags);
+ WriteWord(dynamic_->alignment);
+#else
+ WriteWord(PT_DYNAMIC);
+ WriteWord(dynamic_->segment_flags);
+ WriteOff(dynamic_->file_offset);
+ WriteAddr(dynamic_->memory_offset);
+ WriteAddr(0); // Physical address, not used.
+ WriteXWord(dynamic_->file_size);
+ WriteXWord(dynamic_->memory_size);
+ WriteXWord(dynamic_->alignment);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfProgramTableEntrySize);
+ }
+
+ // Self-reference to program header table that Android wants for some reason.
+ {
+ ASSERT(kNumImplicitSegments == 3);
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(PT_LOAD);
+ WriteOff(program_table_file_offset_);
+ WriteAddr(memory_offset_);
+ WriteAddr(0); // Physical address, not used.
+ WriteWord(program_table_file_size_);
+ WriteWord(program_table_file_size_);
+ WriteWord(PF_R);
+ WriteWord(kPageSize);
+#else
+ WriteWord(PT_LOAD);
+ WriteWord(PF_R);
+ WriteOff(program_table_file_offset_);
+ WriteAddr(memory_offset_);
+ WriteAddr(0); // Physical address, not used.
+ WriteXWord(program_table_file_size_);
+ WriteXWord(program_table_file_size_);
+ WriteXWord(kPageSize);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfProgramTableEntrySize);
+ }
+}
+
+void Elf::WriteSectionTable() {
+ ASSERT(stream_->position() == section_table_file_offset_);
+
+ {
+ // The first entry in the section table is reserved and must be all zeros.
+ ASSERT(kNumInvalidSections == 1);
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(0);
+ WriteWord(0);
+ WriteWord(0);
+ WriteAddr(0);
+ WriteOff(0);
+ WriteWord(0);
+ WriteWord(0);
+ WriteWord(0);
+ WriteWord(0);
+ WriteWord(0);
+#else
+ WriteWord(0);
+ WriteWord(0);
+ WriteXWord(0);
+ WriteAddr(0);
+ WriteOff(0);
+ WriteXWord(0);
+ WriteWord(0);
+ WriteWord(0);
+ WriteXWord(0);
+ WriteXWord(0);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfSectionTableEntrySize);
+ }
+
+ for (intptr_t i = 0; i < sections_.length(); i++) {
+ Section* section = sections_[i];
+ const intptr_t start = stream_->position();
+#if defined(TARGET_ARCH_IS_32_BIT)
+ WriteWord(section->section_name);
+ WriteWord(section->section_type);
+ WriteWord(section->section_flags);
+ WriteAddr(section->memory_offset);
+ WriteOff(section->file_offset);
+ WriteWord(section->file_size); // Has different meaning for BSS.
+ WriteWord(section->section_link);
+ WriteWord(section->section_info);
+ WriteWord(section->alignment);
+ WriteWord(section->section_entry_size);
+#else
+ WriteWord(section->section_name);
+ WriteWord(section->section_type);
+ WriteXWord(section->section_flags);
+ WriteAddr(section->memory_offset);
+ WriteOff(section->file_offset);
+ WriteXWord(section->file_size); // Has different meaning for BSS.
+ WriteWord(section->section_link);
+ WriteWord(section->section_info);
+ WriteXWord(section->alignment);
+ WriteXWord(section->section_entry_size);
+#endif
+ const intptr_t end = stream_->position();
+ ASSERT((end - start) == kElfSectionTableEntrySize);
+ }
+}
+
+void Elf::WriteSections() {
+ for (intptr_t i = 0; i < sections_.length(); i++) {
+ Section* section = sections_[i];
+ stream_->Align(section->alignment);
+ ASSERT(stream_->position() == section->file_offset);
+ section->Write(this);
+ ASSERT(stream_->position() == section->file_offset + section->file_size);
+ stream_->Align(section->alignment);
+ }
+}
+
+} // namespace dart
diff --git a/runtime/vm/elf.h b/runtime/vm/elf.h
new file mode 100644
index 0000000..d49fd62
--- /dev/null
+++ b/runtime/vm/elf.h
@@ -0,0 +1,84 @@
+// 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.
+
+#ifndef RUNTIME_VM_ELF_H_
+#define RUNTIME_VM_ELF_H_
+
+#include "vm/allocation.h"
+#include "vm/datastream.h"
+#include "vm/growable_array.h"
+#include "vm/zone.h"
+
+namespace dart {
+
+class DynamicTable;
+class Section;
+class StringTable;
+class Symbol;
+class SymbolTable;
+
+class Elf : public ZoneAllocated {
+ public:
+ Elf(Zone* zone, StreamingWriteStream* stream);
+
+ intptr_t NextMemoryOffset();
+ intptr_t AddText(const char* name, const uint8_t* bytes, intptr_t size);
+ intptr_t AddROData(const char* name, const uint8_t* bytes, intptr_t size);
+ void AddDebug(const char* name, const uint8_t* bytes, intptr_t size);
+
+ void Finalize();
+
+ intptr_t position() const { return stream_->position(); }
+ void WriteBytes(const uint8_t* b, intptr_t size) {
+ stream_->WriteBytes(b, size);
+ }
+ void WriteByte(uint8_t value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+ void WriteHalf(uint16_t value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+ void WriteWord(uint32_t value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+ void WriteAddr(uword value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+ void WriteOff(uword value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+#if defined(TARGET_ARCH_IS_64_BIT)
+ void WriteXWord(uint64_t value) {
+ stream_->WriteBytes(reinterpret_cast<uint8_t*>(&value), sizeof(value));
+ }
+#endif
+
+ private:
+ void AddSection(Section* section);
+ void AddSegment(Section* section);
+
+ void ComputeFileOffsets();
+ void WriteHeader();
+ void WriteSectionTable();
+ void WriteProgramTable();
+ void WriteSections();
+
+ Zone* const zone_;
+ StreamingWriteStream* stream_;
+ GrowableArray<Section*> sections_;
+ GrowableArray<Section*> segments_;
+
+ intptr_t memory_offset_;
+ intptr_t section_table_file_offset_;
+ intptr_t section_table_file_size_;
+ intptr_t program_table_file_offset_;
+ intptr_t program_table_file_size_;
+ StringTable* strtab_;
+ SymbolTable* symtab_;
+ DynamicTable* dynamic_;
+};
+
+} // namespace dart
+
+#endif // RUNTIME_VM_ELF_H_
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 73a41f0..79361ba 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -995,6 +995,12 @@
Exceptions::ThrowByType(Exceptions::kRange, args);
}
+void Exceptions::ThrowUnsupportedError(const char* msg) {
+ const Array& args = Array::Handle(Array::New(1));
+ args.SetAt(0, String::Handle(String::New(msg)));
+ Exceptions::ThrowByType(Exceptions::kUnsupported, args);
+}
+
void Exceptions::ThrowRangeErrorMsg(const char* msg) {
const Array& args = Array::Handle(Array::New(1));
args.SetAt(0, String::Handle(String::New(msg)));
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 894f374..46b4d68 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -84,6 +84,7 @@
intptr_t expected_from,
intptr_t expected_to);
DART_NORETURN static void ThrowRangeErrorMsg(const char* msg);
+ DART_NORETURN static void ThrowUnsupportedError(const char* msg);
DART_NORETURN static void ThrowCompileTimeError(const LanguageError& error);
// Returns a RawInstance if the exception is successfully created,
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
deleted file mode 100644
index 1fe3662..0000000
--- a/runtime/vm/find_code_object_test.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/heap/pages.h"
-#include "vm/object.h"
-#include "vm/stack_frame.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 50000;
-#elif defined(TARGET_ARCH_DBC)
-static const int kScriptSize = 1 * MB;
-static const int kLoopCount = 60000;
-#else
-static const int kScriptSize = 512 * KB;
-static const int kLoopCount = 25000;
-#endif
-static char scriptChars[kScriptSize];
-
-ISOLATE_UNIT_TEST_CASE(FindCodeObject) {
- const int kNumFunctions = 1024;
-
- // Get access to the code index table.
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
-
- StackZone zone(thread);
- String& url = String::Handle(String::New("dart-test:FindCodeObject"));
- String& source = String::Handle();
- Script& script = Script::Handle();
- Library& lib = Library::Handle();
- Class& clsA = Class::Handle();
- Class& clsB = Class::Handle();
- String& function_name = String::Handle();
- Function& function = Function::Handle();
- char buffer[256];
-
- lib = Library::CoreLibrary();
-
- // Load up class A with 1024 functions.
- int written = Utils::SNPrint(scriptChars, kScriptSize, "class A {");
- for (int i = 0; i < kNumFunctions; i++) {
- Utils::SNPrint(buffer, 256,
- "static foo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
- written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
- }
- Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
- source = String::New(scriptChars);
- script = Script::New(url, source, RawScript::kScriptTag);
- EXPECT(CompilerTest::TestCompileScript(lib, script));
- clsA = lib.LookupClass(String::Handle(Symbols::New(thread, "A")));
- EXPECT(!clsA.IsNull());
- ClassFinalizer::ProcessPendingClasses();
- for (int i = 0; i < kNumFunctions; i++) {
- Utils::SNPrint(buffer, 256, "foo%d", i);
- function_name = String::New(buffer);
- function = clsA.LookupStaticFunction(function_name);
- EXPECT(!function.IsNull());
- EXPECT(CompilerTest::TestCompileFunction(function));
- const Code& code = Code::ZoneHandle(function.CurrentCode());
- EXPECT(!code.IsNull())
- EXPECT(function.HasCode());
- }
-
- // Now load up class B with 1024 functions.
- written = Utils::SNPrint(scriptChars, kScriptSize, "class B {");
- // Create one large function.
- Utils::SNPrint(buffer, sizeof(buffer), "static moo0([var i=1]) { ");
- written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
- // Generate a large function so that the code for this function when
- // compiled will reside in a large page.
- for (int i = 0; i < kLoopCount; i++) {
- Utils::SNPrint(buffer, sizeof(buffer), "i = i+i;");
- written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
- }
- Utils::SNPrint(buffer, sizeof(buffer), "return i; }");
- written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
- for (int i = 1; i < kNumFunctions; i++) {
- Utils::SNPrint(buffer, 256,
- "static moo%d([int i=1,int j=2,int k=3]){return i+j+k;}", i);
- written += Utils::SNPrint((scriptChars + written), (kScriptSize - written),
- "%s", buffer);
- }
- Utils::SNPrint((scriptChars + written), (kScriptSize - written), "}");
- url = String::New("dart-test:FindCodeObject");
- source = String::New(scriptChars);
- script = Script::New(url, source, RawScript::kScriptTag);
- EXPECT(CompilerTest::TestCompileScript(lib, script));
- clsB = lib.LookupClass(String::Handle(Symbols::New(thread, "B")));
- EXPECT(!clsB.IsNull());
- ClassFinalizer::ProcessPendingClasses();
- for (int i = 0; i < kNumFunctions; i++) {
- Utils::SNPrint(buffer, 256, "moo%d", i);
- function_name = String::New(buffer);
- function = clsB.LookupStaticFunction(function_name);
- EXPECT(!function.IsNull());
- EXPECT(CompilerTest::TestCompileFunction(function));
- const Code& code = Code::ZoneHandle(function.CurrentCode());
- EXPECT(!code.IsNull());
- EXPECT(function.HasCode());
- }
-
- // Now try and access these functions using the code index table.
- Code& code = Code::Handle();
- uword pc;
- Utils::SNPrint(buffer, 256, "foo%d", 123);
- function_name = String::New(buffer);
- function = clsA.LookupStaticFunction(function_name);
- EXPECT(!function.IsNull());
- code = function.CurrentCode();
- EXPECT(code.Size() > 16);
- pc = code.PayloadStart() + 16;
- EXPECT(Code::LookupCode(pc) == code.raw());
-
- Utils::SNPrint(buffer, 256, "moo%d", 54);
- function_name = String::New(buffer);
- function = clsB.LookupStaticFunction(function_name);
- EXPECT(!function.IsNull());
- code = function.CurrentCode();
- EXPECT(code.Size() > 16);
- pc = code.PayloadStart() + 16;
- EXPECT(Code::LookupCode(pc) == code.raw());
-
- // Lookup the large function
- Utils::SNPrint(buffer, 256, "moo%d", 0);
- function_name = String::New(buffer);
- function = clsB.LookupStaticFunction(function_name);
- EXPECT(!function.IsNull());
- code = function.CurrentCode();
- EXPECT(code.Size() > 16);
- pc = code.PayloadStart() + 16;
- EXPECT(code.Size() > kPageSize);
- EXPECT(Code::LookupCode(pc) == code.raw());
- EXPECT(code.Size() > (1 * MB));
- pc = code.PayloadStart() + (1 * MB);
- EXPECT(Code::LookupCode(pc) == code.raw());
-}
-
-} // namespace dart
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 7336f1f..1734984c 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -73,6 +73,25 @@
#define NOT_IN_PRECOMPILED(code) code
#endif // defined(DART_PRECOMPILED_RUNTIME)
+#if defined(TARGET_ARCH_DBC)
+#define NOT_IN_DBC(code)
+#else
+#define NOT_IN_DBC(code) code
+#endif // defined(TARGET_ARCH_DBC)
+
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \
+ defined(TARGET_ARCH_X64)
+#define ONLY_IN_ARM_ARM64_X64(code) code
+#else
+#define ONLY_IN_ARM_ARM64_X64(code)
+#endif
+
+#if defined(DART_PRECOMPILED_RUNTIME)
+#define NOT_IN_PRECOMPILED_RUNTIME(code)
+#else
+#define NOT_IN_PRECOMPILED_RUNTIME(code) code
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+
#if !defined(PRODUCT) || defined(HOST_OS_FUCHSIA) || defined(TARGET_OS_FUCHSIA)
#define SUPPORT_TIMELINE 1
#endif
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 34ede80..b3d16c8 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -7,6 +7,7 @@
#include "platform/assert.h"
#include "vm/compiler/backend/code_statistics.h"
#include "vm/dwarf.h"
+#include "vm/elf.h"
#include "vm/hash.h"
#include "vm/hash_map.h"
#include "vm/heap/heap.h"
@@ -359,10 +360,10 @@
const void* shared_instructions)
: ImageWriter(thread->heap(), shared_objects, shared_instructions, nullptr),
assembly_stream_(512 * KB, callback, callback_data),
- dwarf_(NULL) {
+ dwarf_(nullptr) {
#if defined(DART_PRECOMPILER)
Zone* zone = Thread::Current()->zone();
- dwarf_ = new (zone) Dwarf(zone, &assembly_stream_);
+ dwarf_ = new (zone) Dwarf(zone, &assembly_stream_, /* elf= */ nullptr);
#endif
}
@@ -676,12 +677,20 @@
intptr_t initial_size,
const void* shared_objects,
const void* shared_instructions,
- const void* reused_instructions)
+ const void* reused_instructions,
+ Elf* elf,
+ Dwarf* dwarf)
: ImageWriter(thread->heap(),
shared_objects,
shared_instructions,
reused_instructions),
- instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size) {
+ instructions_blob_stream_(instructions_blob_buffer, alloc, initial_size),
+ elf_(elf),
+ dwarf_(dwarf) {
+#ifndef DART_PRECOMPILER
+ RELEASE_ASSERT(elf_ == nullptr);
+ RELEASE_ASSERT(dwarf_ == nullptr);
+#endif
}
intptr_t BlobImageWriter::WriteByteSequence(uword start, uword end) {
@@ -693,6 +702,13 @@
}
void BlobImageWriter::WriteText(WriteStream* clustered_stream, bool vm) {
+#ifdef DART_PRECOMPILER
+ intptr_t segment_base = 0;
+ if (elf_ != nullptr) {
+ segment_base = elf_->NextMemoryOffset();
+ }
+#endif
+
// This header provides the gap to make the instructions snapshot look like a
// HeapPage.
intptr_t instructions_length = next_text_offset_;
@@ -733,6 +749,15 @@
ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
ASSERT(Utils::IsAligned(entry, sizeof(uword)));
+#ifdef DART_PRECOMPILER
+ const Code& code = *instructions_[i].code_;
+ if ((elf_ != nullptr) && !code.IsNull()) {
+ intptr_t segment_offset = instructions_blob_stream_.bytes_written() +
+ Instructions::HeaderSize();
+ dwarf_->AddCode(code, segment_base + segment_offset);
+ }
+#endif
+
// Write Instructions with the mark and read-only bits set.
uword marked_tags = insns.raw_ptr()->tags_;
marked_tags = RawObject::OldBit::update(true, marked_tags);
@@ -752,6 +777,17 @@
ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
}
+
+#ifdef DART_PRECOMPILER
+ if (elf_ != nullptr) {
+ const char* instructions_symbol = vm ? "_kDartVmSnapshotInstructions"
+ : "_kDartIsolateSnapshotInstructions";
+ intptr_t segment_base2 =
+ elf_->AddText(instructions_symbol, instructions_blob_stream_.buffer(),
+ instructions_blob_stream_.bytes_written());
+ ASSERT(segment_base == segment_base2);
+ }
+#endif
}
ImageReader::ImageReader(const uint8_t* data_image,
diff --git a/runtime/vm/image_snapshot.h b/runtime/vm/image_snapshot.h
index 1bc4260..720d855 100644
--- a/runtime/vm/image_snapshot.h
+++ b/runtime/vm/image_snapshot.h
@@ -23,6 +23,7 @@
// Forward declarations.
class Code;
class Dwarf;
+class Elf;
class Instructions;
class Object;
class RawApiError;
@@ -333,7 +334,9 @@
intptr_t initial_size,
const void* shared_objects,
const void* shared_instructions,
- const void* reused_instructions);
+ const void* reused_instructions,
+ Elf* elf = nullptr,
+ Dwarf* dwarf = nullptr);
virtual void WriteText(WriteStream* clustered_stream, bool vm);
@@ -345,6 +348,8 @@
intptr_t WriteByteSequence(uword start, uword end);
WriteStream instructions_blob_stream_;
+ Elf* elf_;
+ Dwarf* dwarf_;
DISALLOW_COPY_AND_ASSIGN(BlobImageWriter);
};
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index a0ba01e..e815a7f 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -896,7 +896,7 @@
} while (0)
#endif
-// Fetch next operation from PC, increment program counter and dispatch.
+// Fetch next operation from PC and dispatch.
#define DISPATCH() DISPATCH_OP(*pc)
// Load target of a jump instruction into PC.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index ba66dcd..028c1bc 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -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.
+#include <utility>
+
#include "vm/isolate.h"
#include "include/dart_api.h"
@@ -2107,8 +2109,8 @@
}
JSONObject jsobj(stream);
jsobj.AddProperty("type", (ref ? "@Isolate" : "Isolate"));
- jsobj.AddFixedServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
- static_cast<int64_t>(main_port()));
+ jsobj.AddServiceId(ISOLATE_SERVICE_ID_FORMAT_STRING,
+ static_cast<int64_t>(main_port()));
jsobj.AddProperty("name", name());
jsobj.AddPropertyF("number", "%" Pd64 "", static_cast<int64_t>(main_port()));
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 2cd529b..b153644 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -616,7 +616,7 @@
p_num_received_classes = &num_received_classes_;
p_num_received_procedures = &num_received_procedures_;
} else {
- Dart_KernelCompilationResult retval;
+ Dart_KernelCompilationResult retval = {};
if (kernel_buffer != NULL && kernel_buffer_size != 0) {
retval.kernel = const_cast<uint8_t*>(kernel_buffer);
retval.kernel_size = kernel_buffer_size;
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index 05f474e..aeaa9d0 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -500,6 +500,14 @@
va_end(args);
}
+void JSONObject::AddServiceId(const char* format, ...) const {
+ // Add the id property.
+ va_list args;
+ va_start(args, format);
+ stream_->VPrintfProperty("id", format, args);
+ va_end(args);
+}
+
void JSONObject::AddLocation(const Script& script,
TokenPosition token_pos,
TokenPosition end_token_pos) const {
@@ -516,10 +524,9 @@
ASSERT(bpt_loc->IsResolved());
Zone* zone = Thread::Current()->zone();
- Library& library = Library::Handle(zone);
Script& script = Script::Handle(zone);
TokenPosition token_pos = TokenPosition::kNoSource;
- bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+ bpt_loc->GetCodeLocation(&script, &token_pos);
AddLocation(script, token_pos);
}
@@ -528,10 +535,9 @@
ASSERT(!bpt_loc->IsResolved());
Zone* zone = Thread::Current()->zone();
- Library& library = Library::Handle(zone);
Script& script = Script::Handle(zone);
TokenPosition token_pos = TokenPosition::kNoSource;
- bpt_loc->GetCodeLocation(&library, &script, &token_pos);
+ bpt_loc->GetCodeLocation(&script, &token_pos);
JSONObject location(this, "location");
location.AddProperty("type", "UnresolvedSourceLocation");
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index c44a5f6..98d39f3 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -307,6 +307,7 @@
void AddServiceId(const Object& o) const { stream_->PrintServiceId(o); }
void AddFixedServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
+ void AddServiceId(const char* format, ...) const PRINTF_ATTRIBUTE(2, 3);
void AddLocation(
const Script& script,
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index a4a6eea..703a495 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -256,7 +256,7 @@
return array_object.raw();
}
-static void ProcessTokenPositionsEntry(
+static void CollectKernelDataTokenPositions(
const ExternalTypedData& kernel_data,
const Script& script,
const Script& entry_script,
@@ -278,6 +278,64 @@
token_position_collector.CollectTokenPositions(kernel_offset);
}
+static void CollectBytecodeTokenPositions(
+ const Bytecode& bytecode,
+ Zone* zone,
+ GrowableArray<intptr_t>* token_positions,
+ GrowableArray<intptr_t>* yield_positions) {
+ ASSERT(bytecode.HasSourcePositions());
+ BytecodeSourcePositionsIterator iter(zone, bytecode);
+ while (iter.MoveNext()) {
+ const TokenPosition pos = iter.TokenPos();
+ if (pos.IsReal()) {
+ // TODO(alexmarkov): collect yield positions from bytecode.
+ token_positions->Add(pos.value());
+ }
+ }
+}
+
+static void CollectBytecodeFunctionTokenPositions(
+ const Function& function,
+ GrowableArray<intptr_t>* token_positions,
+ GrowableArray<intptr_t>* yield_positions) {
+ Thread* thread = Thread::Current();
+ Zone* zone = thread->zone();
+ ASSERT(function.is_declared_in_bytecode());
+ if (!function.HasBytecode()) {
+ const Object& result = Object::Handle(
+ zone, BytecodeReader::ReadFunctionBytecode(thread, function));
+ if (!result.IsNull()) {
+ Exceptions::PropagateError(Error::Cast(result));
+ }
+ }
+ Bytecode& bytecode = Bytecode::Handle(zone, function.bytecode());
+ ASSERT(!bytecode.IsNull());
+ if (bytecode.HasSourcePositions()) {
+ CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+ yield_positions);
+ // Find closure functions in the object pool.
+ const ObjectPool& pool = ObjectPool::Handle(zone, bytecode.object_pool());
+ Object& object = Object::Handle(zone);
+ Function& closure = Function::Handle(zone);
+ for (intptr_t i = 0; i < pool.Length(); i++) {
+ ObjectPool::EntryType entry_type = pool.TypeAt(i);
+ if (entry_type != ObjectPool::EntryType::kTaggedObject) {
+ continue;
+ }
+ object = pool.ObjectAt(i);
+ if (object.IsFunction()) {
+ closure ^= object.raw();
+ if ((closure.kind() == RawFunction::kClosureFunction) &&
+ (closure.raw() != function.raw())) {
+ bytecode = closure.bytecode();
+ CollectBytecodeTokenPositions(bytecode, zone, token_positions,
+ yield_positions);
+ }
+ }
+ }
+ }
+}
+
void CollectTokenPositionsFor(const Script& interesting_script) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
@@ -325,29 +383,30 @@
continue;
}
data = temp_field.KernelData();
- ProcessTokenPositionsEntry(data, interesting_script, entry_script,
- temp_field.kernel_offset(),
- temp_field.KernelDataProgramOffset(),
- zone, &helper, &token_positions,
- &yield_positions);
+ CollectKernelDataTokenPositions(
+ data, interesting_script, entry_script,
+ temp_field.kernel_offset(),
+ temp_field.KernelDataProgramOffset(), zone, &helper,
+ &token_positions, &yield_positions);
}
temp_array = klass.functions();
for (intptr_t i = 0; i < temp_array.Length(); ++i) {
temp_function ^= temp_array.At(i);
entry_script = temp_function.script();
- // TODO(alexmarkov): collect token positions from bytecode
- if (temp_function.is_declared_in_bytecode()) {
- continue;
- }
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
- data = temp_function.KernelData();
- ProcessTokenPositionsEntry(data, interesting_script, entry_script,
- temp_function.kernel_offset(),
- temp_function.KernelDataProgramOffset(),
- zone, &helper, &token_positions,
- &yield_positions);
+ if (temp_function.is_declared_in_bytecode()) {
+ CollectBytecodeFunctionTokenPositions(
+ temp_function, &token_positions, &yield_positions);
+ } else {
+ data = temp_function.KernelData();
+ CollectKernelDataTokenPositions(
+ data, interesting_script, entry_script,
+ temp_function.kernel_offset(),
+ temp_function.KernelDataProgramOffset(), zone, &helper,
+ &token_positions, &yield_positions);
+ }
}
} else {
// Class isn't finalized yet: read the data attached to it.
@@ -362,27 +421,28 @@
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
- ProcessTokenPositionsEntry(data, interesting_script, entry_script,
- class_offset, library_kernel_offset, zone,
- &helper, &token_positions,
- &yield_positions);
+ CollectKernelDataTokenPositions(data, interesting_script,
+ entry_script, class_offset,
+ library_kernel_offset, zone, &helper,
+ &token_positions, &yield_positions);
}
} else if (entry.IsFunction()) {
temp_function ^= entry.raw();
- // TODO(alexmarkov): collect token positions from bytecode
- if (temp_function.is_declared_in_bytecode()) {
- continue;
- }
entry_script = temp_function.script();
if (entry_script.raw() != interesting_script.raw()) {
continue;
}
- data = temp_function.KernelData();
- ProcessTokenPositionsEntry(data, interesting_script, entry_script,
- temp_function.kernel_offset(),
- temp_function.KernelDataProgramOffset(),
- zone, &helper, &token_positions,
- &yield_positions);
+ if (temp_function.is_declared_in_bytecode()) {
+ CollectBytecodeFunctionTokenPositions(temp_function, &token_positions,
+ &yield_positions);
+ } else {
+ data = temp_function.KernelData();
+ CollectKernelDataTokenPositions(
+ data, interesting_script, entry_script,
+ temp_function.kernel_offset(),
+ temp_function.KernelDataProgramOffset(), zone, &helper,
+ &token_positions, &yield_positions);
+ }
} else if (entry.IsField()) {
const Field& field = Field::Cast(entry);
// TODO(alexmarkov): collect token positions from bytecode
@@ -395,10 +455,10 @@
continue;
}
data = field.KernelData();
- ProcessTokenPositionsEntry(data, interesting_script, entry_script,
- field.kernel_offset(),
- field.KernelDataProgramOffset(), zone,
- &helper, &token_positions, &yield_positions);
+ CollectKernelDataTokenPositions(
+ data, interesting_script, entry_script, field.kernel_offset(),
+ field.KernelDataProgramOffset(), zone, &helper, &token_positions,
+ &yield_positions);
}
}
}
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index ef25d78..abf5036 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -828,7 +828,7 @@
KernelCompilationRequest* next_;
KernelCompilationRequest* prev_;
- Dart_KernelCompilationResult result_;
+ Dart_KernelCompilationResult result_ = {};
};
Monitor* KernelCompilationRequest::requests_monitor_ = new Monitor();
@@ -848,7 +848,7 @@
// to finish initialization.
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
@@ -865,7 +865,7 @@
Dart_KernelCompilationResult KernelIsolate::ListDependencies() {
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
@@ -882,7 +882,7 @@
// to finish initialization.
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
@@ -903,7 +903,7 @@
bool is_static) {
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
@@ -923,7 +923,7 @@
// to finish initialization.
Dart_Port kernel_port = WaitForKernelPort();
if (kernel_port == ILLEGAL_PORT) {
- Dart_KernelCompilationResult result;
+ Dart_KernelCompilationResult result = {};
result.status = Dart_KernelCompilationStatus_Unknown;
result.error = strdup("Error while initializing Kernel isolate");
return result;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 962d878..4186f23 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -404,6 +404,10 @@
Z, reader.ExternalDataFromTo(program_->metadata_mappings_offset(),
program_->string_table_offset()));
+#if defined(DEBUG)
+ MetadataHelper::VerifyMetadataMappings(metadata_mappings);
+#endif
+
const Array& libraries_cache =
Array::Handle(Z, HashTables::New<UnorderedHashMap<SmiTraits>>(
program_->library_count(), Heap::kOld));
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 542ccc0..0bfca6d 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -4,6 +4,8 @@
#include "vm/message.h"
+#include <utility>
+
#include "vm/dart_entry.h"
#include "vm/json_stream.h"
#include "vm/object.h"
@@ -11,7 +13,7 @@
namespace dart {
-const Dart_Port Message::kIllegalPort;
+const Dart_Port Message::kIllegalPort = 0;
Message::Message(Dart_Port dest_port,
uint8_t* snapshot,
diff --git a/runtime/vm/message.h b/runtime/vm/message.h
index 4bf2303..03f3074 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -6,6 +6,7 @@
#define RUNTIME_VM_MESSAGE_H_
#include <memory>
+#include <utility>
#include "platform/assert.h"
#include "vm/allocation.h"
@@ -42,7 +43,7 @@
} OOBMsgTag;
// A port number which is never used.
- static const Dart_Port kIllegalPort = 0;
+ static const Dart_Port kIllegalPort;
// A new message to be sent between two isolates. The data handed to this
// message will be disposed by calling free() once the message object is
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index 9bf957d..df1859d 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -217,4 +217,24 @@
#endif // defined(DART_PRECOMPILED_RUNTIME)
}
+DART_EXPORT Dart_Handle Dart_FinalizeAllClasses() {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ return Api::NewError("%s: All classes are already finalized in AOT runtime.",
+ CURRENT_FUNC);
+#else
+ DARTSCOPE(Thread::Current());
+ API_TIMELINE_DURATION(T);
+ Dart_Handle result = Api::CheckAndFinalizePendingClasses(T);
+ if (Api::IsError(result)) {
+ return result;
+ }
+ CHECK_CALLBACK_STATE(T);
+ const Error& error = Error::Handle(T->zone(), Library::FinalizeAllClasses());
+ if (!error.IsNull()) {
+ return Api::NewHandle(T, error.raw());
+ }
+ return Api::Success();
+#endif // defined(DART_PRECOMPILED_RUNTIME)
+}
+
} // namespace dart
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 73cf977..08b8a5f 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5730,9 +5730,10 @@
StorePointer(&raw_ptr()->bytecode_, value.raw());
// We should not have loaded the bytecode if the function had code.
- ASSERT(!HasCode());
-
- if (FLAG_enable_interpreter) {
+ // However, we may load the bytecode to access source positions (see
+ // ProcessBytecodeTokenPositionsEntry in kernel.cc).
+ // In that case, do not install InterpretCall stub below.
+ if (FLAG_enable_interpreter && !HasCode()) {
// Set the code entry_point to InterpretCall stub.
SetInstructions(StubCode::InterpretCall());
}
@@ -6065,6 +6066,34 @@
return FfiTrampolineData::Cast(obj).c_signature();
}
+int32_t Function::FfiCallbackId() const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ return FfiTrampolineData::Cast(obj).callback_id();
+}
+
+void Function::SetFfiCallbackId(int32_t value) const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ FfiTrampolineData::Cast(obj).set_callback_id(value);
+}
+
+RawFunction* Function::FfiCallbackTarget() const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ return FfiTrampolineData::Cast(obj).callback_target();
+}
+
+void Function::SetFfiCallbackTarget(const Function& target) const {
+ ASSERT(IsFfiTrampoline());
+ const Object& obj = Object::Handle(raw_ptr()->data_);
+ ASSERT(!obj.IsNull());
+ FfiTrampolineData::Cast(obj).set_callback_target(target);
+}
+
RawType* Function::SignatureType() const {
Type& type = Type::Handle(ExistingSignatureType());
if (type.IsNull()) {
@@ -6185,10 +6214,18 @@
break;
case RawFunction::kDynamicInvocationForwarder:
return "DynamicInvocationForwarder";
- default:
- UNREACHABLE();
- return NULL;
+ break;
+ case RawFunction::kFfiTrampoline:
+ return "FfiTrampoline";
+ break;
}
+ // When you add a case to this switch, please also update the observatory.
+ // - runtime/observatory/lib/src/models/objects/function.dart (FunctionKind)
+ // - runtime/observatory/lib/src/elements/function_view.dart
+ // (_functionKindToString)
+ // - runtime/observatory/lib/src/service/object.dart (stringToFunctionKind)
+ UNREACHABLE();
+ return NULL;
}
void Function::SetRedirectionType(const Type& type) const {
@@ -7787,7 +7824,8 @@
bool Function::ShouldCompilerOptimize() const {
return !FLAG_enable_interpreter ||
- ((unoptimized_code() != Object::null()) && WasCompiled());
+ ((unoptimized_code() != Object::null()) && WasCompiled()) ||
+ ForceOptimize();
}
RawString* Function::UserVisibleName() const {
@@ -8221,12 +8259,22 @@
StorePointer(&raw_ptr()->c_signature_, value.raw());
}
+void FfiTrampolineData::set_callback_target(const Function& value) const {
+ StorePointer(&raw_ptr()->callback_target_, value.raw());
+}
+
+void FfiTrampolineData::set_callback_id(int32_t callback_id) const {
+ StoreNonPointer(&raw_ptr()->callback_id_, callback_id);
+}
+
RawFfiTrampolineData* FfiTrampolineData::New() {
ASSERT(Object::ffi_trampoline_data_class() != Class::null());
RawObject* raw =
Object::Allocate(FfiTrampolineData::kClassId,
FfiTrampolineData::InstanceSize(), Heap::kOld);
- return reinterpret_cast<RawFfiTrampolineData*>(raw);
+ RawFfiTrampolineData* data = reinterpret_cast<RawFfiTrampolineData*>(raw);
+ data->ptr()->callback_id_ = -1;
+ return data;
}
const char* FfiTrampolineData::ToCString() const {
@@ -12236,6 +12284,39 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
+
+RawError* Library::FinalizeAllClasses() {
+ Thread* thread = Thread::Current();
+ ASSERT(thread->IsMutatorThread());
+ Zone* zone = thread->zone();
+ Error& error = Error::Handle(zone);
+ const GrowableObjectArray& libs = GrowableObjectArray::Handle(
+ Isolate::Current()->object_store()->libraries());
+ Library& lib = Library::Handle(zone);
+ Class& cls = Class::Handle(zone);
+ for (int i = 0; i < libs.Length(); i++) {
+ lib ^= libs.At(i);
+ if (!lib.Loaded()) {
+ String& uri = String::Handle(zone, lib.url());
+ String& msg = String::Handle(
+ zone,
+ String::NewFormatted("Library '%s' is not loaded. "
+ "Did you forget to call Dart_FinalizeLoading?",
+ uri.ToCString()));
+ return ApiError::New(msg);
+ }
+ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate);
+ while (it.HasNext()) {
+ cls = it.GetNextClass();
+ error = cls.EnsureIsFinalized(thread);
+ if (!error.IsNull()) {
+ return error.raw();
+ }
+ }
+ }
+ return Error::null();
+}
+
RawError* Library::ReadAllBytecode() {
Thread* thread = Thread::Current();
ASSERT(thread->IsMutatorThread());
@@ -15122,6 +15203,9 @@
result.set_pc_descriptors(Object::empty_descriptors());
result.set_instructions_binary_offset(instructions_offset);
result.set_source_positions_binary_offset(0);
+#if !defined(PRODUCT)
+ result.set_local_variables_binary_offset(0);
+#endif
}
return result.raw();
}
@@ -15160,6 +15244,35 @@
#endif
}
+intptr_t Bytecode::GetTryIndexAtPc(uword return_address) const {
+#if defined(DART_PRECOMPILED_RUNTIME)
+ UNREACHABLE();
+#else
+ intptr_t try_index = -1;
+ const uword pc_offset = return_address - PayloadStart();
+ const PcDescriptors& descriptors = PcDescriptors::Handle(pc_descriptors());
+ PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
+ while (iter.MoveNext()) {
+ // PC descriptors for try blocks in bytecode are generated in pairs,
+ // marking start and end of a try block.
+ // See BytecodeMetadataHelper::ReadExceptionsTable for details.
+ const intptr_t current_try_index = iter.TryIndex();
+ const uword start_pc = iter.PcOffset();
+ if (pc_offset < start_pc) {
+ break;
+ }
+ const bool has_next = iter.MoveNext();
+ ASSERT(has_next);
+ const uword end_pc = iter.PcOffset();
+ if (start_pc <= pc_offset && pc_offset < end_pc) {
+ ASSERT(try_index < current_try_index);
+ try_index = current_try_index;
+ }
+ }
+ return try_index;
+#endif
+}
+
const char* Bytecode::ToCString() const {
return Thread::Current()->zone()->PrintToString("Bytecode(%s)",
QualifiedName());
@@ -15221,6 +15334,25 @@
return Bytecode::null();
}
+RawLocalVarDescriptors* Bytecode::GetLocalVarDescriptors() const {
+#if defined(PRODUCT) || defined(DART_PRECOMPILED_RUNTIME)
+ UNREACHABLE();
+ return LocalVarDescriptors::null();
+#else
+ Zone* zone = Thread::Current()->zone();
+ auto& var_descs = LocalVarDescriptors::Handle(zone, var_descriptors());
+ if (var_descs.IsNull()) {
+ const auto& func = Function::Handle(zone, function());
+ ASSERT(!func.IsNull());
+ var_descs =
+ kernel::BytecodeReader::ComputeLocalVarDescriptors(zone, func, *this);
+ ASSERT(!var_descs.IsNull());
+ set_var_descriptors(var_descs);
+ }
+ return var_descs.raw();
+#endif
+}
+
RawContext* Context::New(intptr_t num_variables, Heap::Space space) {
ASSERT(num_variables >= 0);
ASSERT(Object::context_class() != Class::null());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 725bc63..453e847 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2000,6 +2000,20 @@
// Can only be used on FFI trampolines.
RawFunction* FfiCSignature() const;
+ // Can only be called on FFI trampolines.
+ // -1 for Dart -> native calls.
+ int32_t FfiCallbackId() const;
+
+ // Can only be called on FFI trampolines.
+ void SetFfiCallbackId(int32_t value) const;
+
+ // Can only be called on FFI trampolines.
+ // Null for Dart -> native calls.
+ RawFunction* FfiCallbackTarget() const;
+
+ // Can only be called on FFI trampolines.
+ void SetFfiCallbackTarget(const Function& target) const;
+
// Return a new function with instantiated result and parameter types.
RawFunction* InstantiateSignatureFrom(
const TypeArguments& instantiator_type_arguments,
@@ -2169,6 +2183,8 @@
void AttachBytecode(const Bytecode& bytecode) const;
RawBytecode* bytecode() const { return raw_ptr()->bytecode_; }
inline bool HasBytecode() const;
+#else
+ inline bool HasBytecode() const { return false; }
#endif
virtual intptr_t Hash() const;
@@ -3131,6 +3147,12 @@
RawFunction* c_signature() const { return raw_ptr()->c_signature_; }
void set_c_signature(const Function& value) const;
+ RawFunction* callback_target() const { return raw_ptr()->callback_target_; }
+ void set_callback_target(const Function& value) const;
+
+ int32_t callback_id() const { return raw_ptr()->callback_id_; }
+ void set_callback_id(int32_t value) const;
+
static RawFfiTrampolineData* New();
FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
@@ -4027,6 +4049,8 @@
// Eagerly compile all classes and functions in the library.
static RawError* CompileAll(bool ignore_error = false);
#if !defined(DART_PRECOMPILED_RUNTIME)
+ // Finalize all classes in all libraries.
+ static RawError* FinalizeAllClasses();
// Eagerly read all bytecode.
static RawError* ReadAllBytecode();
#endif
@@ -4294,6 +4318,14 @@
sizeof(RawObjectPool::Entry) * index;
}
+ struct ArrayLayout {
+ static intptr_t elements_start_offset() {
+ return ObjectPool::data_offset();
+ }
+
+ static constexpr intptr_t kElementSize = sizeof(RawObjectPool::Entry);
+ };
+
EntryType TypeAt(intptr_t index) const {
return TypeBits::decode(raw_ptr()->entry_bits()[index]);
}
@@ -5001,7 +5033,7 @@
return ContainsInstructionAt(raw(), addr);
}
- static bool ContainsInstructionAt(RawCode* code, uword addr) {
+ static bool ContainsInstructionAt(const RawCode* code, uword addr) {
return Instructions::ContainsPc(code->ptr()->instructions_, addr);
}
@@ -5201,7 +5233,7 @@
#endif
}
- // Will compute local var descriptors is necessary.
+ // Will compute local var descriptors if necessary.
RawLocalVarDescriptors* GetLocalVarDescriptors() const;
RawExceptionHandlers* exception_handlers() const {
@@ -5474,6 +5506,7 @@
RawExternalTypedData* GetBinary(Zone* zone) const;
TokenPosition GetTokenIndexOfPC(uword pc) const;
+ intptr_t GetTryIndexAtPc(uword return_address) const;
intptr_t instructions_binary_offset() const {
return raw_ptr()->instructions_binary_offset_;
@@ -5492,6 +5525,38 @@
return (source_positions_binary_offset() != 0);
}
+#if !defined(PRODUCT)
+ intptr_t local_variables_binary_offset() const {
+ return raw_ptr()->local_variables_binary_offset_;
+ }
+ void set_local_variables_binary_offset(intptr_t value) const {
+ StoreNonPointer(&raw_ptr()->local_variables_binary_offset_, value);
+ }
+ bool HasLocalVariablesInfo() const {
+ return (local_variables_binary_offset() != 0);
+ }
+#endif // !defined(PRODUCT)
+
+ RawLocalVarDescriptors* var_descriptors() const {
+#if defined(PRODUCT)
+ UNREACHABLE();
+ return nullptr;
+#else
+ return raw_ptr()->var_descriptors_;
+#endif
+ }
+ void set_var_descriptors(const LocalVarDescriptors& value) const {
+#if defined(PRODUCT)
+ UNREACHABLE();
+#else
+ ASSERT(value.IsOld());
+ StorePointer(&raw_ptr()->var_descriptors_, value.raw());
+#endif
+ }
+
+ // Will compute local var descriptors if necessary.
+ RawLocalVarDescriptors* GetLocalVarDescriptors() const;
+
const char* Name() const;
const char* QualifiedName() const;
@@ -6208,6 +6273,14 @@
}
void SetTypeAt(intptr_t index, const AbstractType& value) const;
+ struct ArrayLayout {
+ static intptr_t elements_start_offset() {
+ return TypeArguments::type_at_offset(0);
+ }
+
+ static constexpr intptr_t kElementSize = kWordSize;
+ };
+
// The name of this type argument vector, e.g. "<T, dynamic, List<T>, Smi>".
RawString* Name() const { return SubvectorName(0, Length(), kInternalName); }
@@ -7989,6 +8062,12 @@
return OFFSET_OF_RETURNED_VALUE(RawArray, data) + kWordSize * index;
}
+ struct ArrayLayout {
+ static intptr_t elements_start_offset() { return Array::data_offset(); }
+
+ static constexpr intptr_t kElementSize = kWordSize;
+ };
+
static bool Equals(RawArray* a, RawArray* b) {
if (a == b) return true;
if (a->IsRawNull() || b->IsRawNull()) return false;
@@ -8268,6 +8347,14 @@
static RawGrowableObjectArray* New(const Array& array,
Heap::Space space = Heap::kNew);
+ static RawSmi* NoSafepointLength(const RawGrowableObjectArray* array) {
+ return array->ptr()->length_;
+ }
+
+ static RawArray* NoSafepointData(const RawGrowableObjectArray* array) {
+ return array->ptr()->data_;
+ }
+
private:
RawArray* DataArray() const { return data()->ptr(); }
RawObject** ObjectAddr(intptr_t index) const {
diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc
index 50a2952..a0d050e 100644
--- a/runtime/vm/os_thread_macos.cc
+++ b/runtime/vm/os_thread_macos.cc
@@ -88,20 +88,6 @@
DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
};
-// Spawned threads inherit their spawner's signal mask. We sometimes spawn
-// threads for running Dart code from a thread that is blocking SIGPROF.
-// This function explicitly unblocks SIGPROF so the profiler continues to
-// sample this thread.
-static void UnblockSIGPROF() {
- sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGPROF);
- int r = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
- USE(r);
- ASSERT(r == 0);
- ASSERT(!CHECK_IS_BLOCKING(SIGPROF));
-}
-
// Dispatch to the thread start function provided by the caller. This trampoline
// is used to ensure that the thread is properly destroyed if the thread just
// exits.
@@ -121,7 +107,6 @@
if (thread != NULL) {
OSThread::SetCurrent(thread);
thread->set_name(name);
- UnblockSIGPROF();
// Call the supplied thread start function handing it its parameters.
function(parameter);
}
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 27d808f..eb5d39a 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -537,7 +537,7 @@
RawBytecode* raw_bytecode = static_cast<RawBytecode*>(raw_obj);
uword start = raw_bytecode->ptr()->instructions_;
uword size = raw_bytecode->ptr()->instructions_size_;
- return (pc - start) < size;
+ return (pc - start) <= size; // pc may point past last instruction.
}
return false;
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 75e7a92..355cb6b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1013,7 +1013,19 @@
VISIT_FROM(RawObject*, signature_type_);
RawType* signature_type_;
RawFunction* c_signature_;
- VISIT_TO(RawObject*, c_signature_);
+
+ // Target Dart method for callbacks, otherwise null.
+ RawFunction* callback_target_;
+
+ VISIT_TO(RawObject*, callback_target_);
+
+ // Callback id for callbacks, otherwise 0.
+ //
+ // The callbacks ids are used so that native callbacks can lookup their own
+ // code objects, since native code doesn't pass code objects into function
+ // calls. The callback id is also used to for verifying that callbacks are
+ // called on the correct isolate. See DLRT_VerifyCallbackIsolate for details.
+ uint32_t callback_id_;
};
class RawField : public RawObject {
@@ -1337,13 +1349,21 @@
VISIT_FROM(RawObject*, object_pool_);
RawObjectPool* object_pool_;
RawFunction* function_;
+ RawArray* closures_;
RawExceptionHandlers* exception_handlers_;
RawPcDescriptors* pc_descriptors_;
+ NOT_IN_PRODUCT(RawLocalVarDescriptors* var_descriptors_);
+#if defined(PRODUCT)
VISIT_TO(RawObject*, pc_descriptors_);
+#else
+ VISIT_TO(RawObject*, var_descriptors_);
+#endif
+
RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
int32_t instructions_binary_offset_;
int32_t source_positions_binary_offset_;
+ NOT_IN_PRODUCT(int32_t local_variables_binary_offset_);
static bool ContainsPC(RawObject* raw_obj, uword pc);
@@ -1384,15 +1404,14 @@
uint32_t size_and_flags_;
uint32_t unchecked_entrypoint_pc_offset_;
-#if defined(DART_PRECOMPILER)
// There is a gap between size_and_flags_ and the entry point
// because we align entry point by 4 words on all platforms.
// This allows us to have a free field here without affecting
// the aligned size of the Instructions object header.
// This also means that entry point offset is the same
// whether this field is included or excluded.
+ // TODO(37103): This field should be removed.
CodeStatistics* stats_;
-#endif
// Variable length data follows here.
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
diff --git a/runtime/vm/resolver_test.cc b/runtime/vm/resolver_test.cc
deleted file mode 100644
index 6624b49..0000000
--- a/runtime/vm/resolver_test.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2012, 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.
-
-#include "vm/resolver.h"
-#include "platform/assert.h"
-#include "vm/class_finalizer.h"
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/symbols.h"
-#include "vm/unit_test.h"
-
-namespace dart {
-
-// Setup function for invocation.
-static void SetupFunction(const char* test_library_name,
- const char* test_class_name,
- const char* test_static_function_name,
- bool is_static) {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
-
- // Setup a dart class and function.
- char script_chars[1024];
- Utils::SNPrint(script_chars, sizeof(script_chars),
- "class Base {\n"
- " dynCall() { return 3; }\n"
- " static statCall() { return 4; }\n"
- "\n"
- "}\n"
- "class %s extends Base {\n"
- " %s %s(String s, int i) { return i; }\n"
- "}\n",
- test_class_name, is_static ? "static" : "",
- test_static_function_name);
-
- String& url = String::Handle(
- zone, is_static ? String::New("dart-test:DartStaticResolve")
- : String::New("dart-test:DartDynamicResolve"));
- String& source = String::Handle(zone, String::New(script_chars));
- Script& script =
- Script::Handle(zone, Script::New(url, source, RawScript::kScriptTag));
- const String& lib_name = String::Handle(zone, String::New(test_library_name));
- Library& lib = Library::Handle(zone, Library::New(lib_name));
- lib.Register(thread);
- EXPECT(CompilerTest::TestCompileScript(lib, script));
- EXPECT(ClassFinalizer::ProcessPendingClasses());
-}
-
-// Setup a static function for invocation.
-static void SetupStaticFunction(const char* test_library_name,
- const char* test_class_name,
- const char* test_static_function_name) {
- // Setup a static dart class and function.
- SetupFunction(test_library_name, test_class_name, test_static_function_name,
- true);
-}
-
-// Setup an instance function for invocation.
-static void SetupInstanceFunction(const char* test_library_name,
- const char* test_class_name,
- const char* test_function_name) {
- // Setup a static dart class and function.
- SetupFunction(test_library_name, test_class_name, test_function_name, false);
-}
-
-ISOLATE_UNIT_TEST_CASE(DartStaticResolve) {
- const char* test_library_name = "ResolverApp";
- const char* test_class_name = "A";
- const char* test_static_function_name = "static_foo";
- const int kTestValue = 42;
-
- // Setup a static function which can be invoked.
- SetupStaticFunction(test_library_name, test_class_name,
- test_static_function_name);
-
- const String& library_name = String::Handle(String::New(test_library_name));
- const Library& library =
- Library::Handle(Library::LookupLibrary(thread, library_name));
- const String& class_name = String::Handle(String::New(test_class_name));
- const String& static_function_name =
- String::Handle(String::New(test_static_function_name));
-
- // Now try to resolve and invoke the static function in this class.
- {
- const int kTypeArgsLen = 0;
- const int kNumArguments = 2;
- const Function& function = Function::Handle(Resolver::ResolveStatic(
- library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
- Object::empty_array()));
- EXPECT(!function.IsNull()); // No ambiguity error expected.
- const Array& args = Array::Handle(Array::New(kNumArguments));
- const String& arg0 = String::Handle(String::New("junk"));
- args.SetAt(0, arg0);
- const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
- args.SetAt(1, arg1);
- const Smi& retval = Smi::Handle(
- reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
- EXPECT_EQ(kTestValue, retval.Value());
- }
-
- // Now try to resolve a static function with invalid argument count.
- {
- const int kTypeArgsLen = 0;
- const int kNumArguments = 1;
- const Function& bad_function = Function::Handle(Resolver::ResolveStatic(
- library, class_name, static_function_name, kTypeArgsLen, kNumArguments,
- Object::empty_array()));
- EXPECT(bad_function.IsNull()); // No ambiguity error expected.
- }
-
- // Hierarchy walking.
- {
- const String& super_static_function_name =
- String::Handle(String::New("statCall"));
- const String& super_class_name = String::Handle(String::New("Base"));
- const int kTypeArgsLen = 0;
- const int kNumArguments = 0;
- const Function& super_function = Function::Handle(Resolver::ResolveStatic(
- library, super_class_name, super_static_function_name, kTypeArgsLen,
- kNumArguments, Object::empty_array()));
- EXPECT(!super_function.IsNull()); // No ambiguity error expected.
- }
-}
-
-ISOLATE_UNIT_TEST_CASE(DartDynamicResolve) {
- const char* test_library_name = "ResolverApp";
- const char* test_class_name = "A";
- const char* test_function_name = "foo";
- const int kTestValue = 42;
-
- // Setup a function which can be invoked.
- SetupInstanceFunction(test_library_name, test_class_name, test_function_name);
-
- // Now create an instance object of the class and try to
- // resolve a function in it.
- const String& lib_name = String::Handle(String::New(test_library_name));
- const Library& lib =
- Library::Handle(Library::LookupLibrary(thread, lib_name));
- ASSERT(!lib.IsNull());
- const Class& cls = Class::Handle(
- lib.LookupClass(String::Handle(Symbols::New(thread, test_class_name))));
- EXPECT(!cls.IsNull()); // No ambiguity error expected.
-
- Instance& receiver = Instance::Handle(Instance::New(cls));
- const String& function_name = String::Handle(String::New(test_function_name));
-
- // Now try to resolve and invoke the instance function in this class.
- {
- const int kTypeArgsLen = 0;
- const int kNumArguments = 3;
- ArgumentsDescriptor args_desc(
- Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
- const Function& function = Function::Handle(
- Resolver::ResolveDynamic(receiver, function_name, args_desc));
- EXPECT(!function.IsNull());
- const Array& args = Array::Handle(Array::New(kNumArguments));
- args.SetAt(0, receiver);
- const String& arg0 = String::Handle(String::New("junk"));
- args.SetAt(1, arg0);
- const Smi& arg1 = Smi::Handle(Smi::New(kTestValue));
- args.SetAt(2, arg1);
- const Smi& retval = Smi::Handle(
- reinterpret_cast<RawSmi*>(DartEntry::InvokeFunction(function, args)));
- EXPECT_EQ(kTestValue, retval.Value());
- }
-
- // Now try to resolve an instance function with invalid argument count.
- {
- const int kTypeArgsLen = 0;
- const int kNumArguments = 1;
- ArgumentsDescriptor args_desc(
- Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
- const Function& bad_function = Function::Handle(
- Resolver::ResolveDynamic(receiver, function_name, args_desc));
- EXPECT(bad_function.IsNull());
- }
-
- // Hierarchy walking.
- {
- const int kTypeArgsLen = 0;
- const int kNumArguments = 1;
- ArgumentsDescriptor args_desc(
- Array::Handle(ArgumentsDescriptor::New(kTypeArgsLen, kNumArguments)));
- const String& super_function_name = String::Handle(String::New("dynCall"));
- const Function& super_function = Function::Handle(
- Resolver::ResolveDynamic(receiver, super_function_name, args_desc));
- EXPECT(!super_function.IsNull());
- }
-}
-
-} // namespace dart
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 1a7ba2e..cac4d22 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -26,6 +26,7 @@
#include "vm/service_isolate.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
+#include "vm/thread.h"
#include "vm/thread_registry.h"
#include "vm/type_testing_stubs.h"
@@ -975,6 +976,7 @@
StackFrameIterator::kNoCrossThreadIteration);
StackFrame* caller_frame = iterator.NextFrame();
ASSERT(caller_frame != NULL);
+ ASSERT(!caller_frame->is_interpreted());
const Code& orig_stub = Code::Handle(
zone, isolate->debugger()->GetPatchedStubAddress(caller_frame->pc()));
const Error& error =
@@ -1963,13 +1965,13 @@
for (intptr_t i = 0; i < num_frames; i++) {
ActivationFrame* frame = stack->FrameAt(i);
#ifndef DART_PRECOMPILED_RUNTIME
- if (!frame->is_interpreted()) {
+ if (!frame->IsInterpreted()) {
// Ensure that we have unoptimized code.
frame->function().EnsureHasCompiledUnoptimizedCode();
}
// TODO(regis): Provide var descriptors in kernel bytecode.
const int num_vars =
- frame->is_interpreted() ? 0 : frame->NumLocalVariables();
+ frame->IsInterpreted() ? 0 : frame->NumLocalVariables();
#else
// Variable locations and number are unknown when precompiling.
const int num_vars = 0;
@@ -2129,8 +2131,14 @@
ASSERT(FLAG_enable_interpreter || optimizing_compilation);
ASSERT((!optimizing_compilation) || function.HasCode());
- if ((!optimizing_compilation) ||
+#if defined(PRODUCT)
+ if (!optimizing_compilation ||
Compiler::CanOptimizeFunction(thread, function)) {
+#else
+ if ((!optimizing_compilation && !Debugger::IsDebugging(thread, function)) ||
+ (optimizing_compilation &&
+ Compiler::CanOptimizeFunction(thread, function))) {
+#endif // defined(PRODUCT)
if (FLAG_background_compilation) {
if (FLAG_enable_inlining_annotations) {
FATAL("Cannot enable inlining annotations and background compilation");
@@ -2765,4 +2773,29 @@
}
DEFINE_RAW_LEAF_RUNTIME_ENTRY(ExitSafepoint, 0, false, &DFLRT_ExitSafepoint);
+// Not registered as a runtime entry because we can't use Thread to look it up.
+extern "C" Thread* DLRT_GetThreadForNativeCallback() {
+ Thread* const thread = Thread::Current();
+ if (thread == nullptr) {
+ FATAL("Cannot invoke native callback outside an isolate.");
+ }
+ if (thread->no_callback_scope_depth() != 0) {
+ FATAL("Cannot invoke native callback when API callbacks are prohibited.");
+ }
+ if (!thread->IsMutatorThread()) {
+ FATAL("Native callbacks must be invoked on the mutator thread.");
+ }
+ return thread;
+}
+
+extern "C" void DLRT_VerifyCallbackIsolate(int32_t callback_id,
+ uword return_address) {
+ Thread::Current()->VerifyCallbackIsolate(callback_id, return_address);
+}
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(
+ VerifyCallbackIsolate,
+ 1,
+ false /* is_float */,
+ reinterpret_cast<RuntimeFunction>(&DLRT_VerifyCallbackIsolate));
+
} // namespace dart
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index 85e9d7f2..f072c14 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -145,6 +145,9 @@
RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
LEAF_RUNTIME_ENTRY_LIST(DECLARE_LEAF_RUNTIME_ENTRY)
+// Expected to be called inside a safepoint.
+extern "C" Thread* DLRT_GetThreadForNativeCallback();
+
const char* DeoptReasonToCString(ICData::DeoptReasonId deopt_reason);
void DeoptimizeAt(const Code& optimized_code, StackFrame* frame);
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index dd4159d..b0c241e 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -84,7 +84,8 @@
V(RawBool*, CaseInsensitiveCompareUTF16, RawString*, RawSmi*, RawSmi*, \
RawSmi*) \
V(void, EnterSafepoint) \
- V(void, ExitSafepoint)
+ V(void, ExitSafepoint) \
+ V(void, VerifyCallbackIsolate, int32_t, uword)
} // namespace dart
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 50ba1c5..1db81b5 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -117,7 +117,7 @@
StreamInfo Service::gc_stream("GC");
StreamInfo Service::echo_stream("_Echo");
StreamInfo Service::graph_stream("_Graph");
-StreamInfo Service::logging_stream("_Logging");
+StreamInfo Service::logging_stream("Logging");
StreamInfo Service::extension_stream("Extension");
StreamInfo Service::timeline_stream("Timeline");
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 4b05099..3d2cb73 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 14
+#define SERVICE_PROTOCOL_MINOR_VERSION 17
class Array;
class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index a04b348..e993091 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.16
+# Dart VM Service Protocol 3.17
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.16_ of the Dart VM Service Protocol. This
+This document describes of _version 3.17_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
- [Isolate](#isolate)
- [Library](#library)
- [LibraryDependency](#librarydependency)
+ - [LogRecord](#logrecord)
- [MapAssociation](#mapassociation)
- [MemoryUsage](#memoryusage)
- [Message](#message)
@@ -546,7 +547,7 @@
If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
result of this evaluation are ignored. Defaults to false if not provided.
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
result of this evaluation are ignored. Defaults to false if not provided.
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
GC | GC
Extension | Extension
Timeline | TimelineEvents
+Logging | Logging
Additionally, some embedders provide the _Stdout_ and _Stderr_
streams. These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
// IsolateReloaded
// IsolateSpawn
string status [optional];
+
+ // LogRecord data.
+ //
+ // This is provided for the Logging event.
+ LogRecord logRecord [optional];
}
```
@@ -1506,6 +1513,9 @@
// Event from dart:developer.postEvent.
Extension
+
+ // Event from dart:developer.log.
+ Logging
}
```
@@ -2214,6 +2224,39 @@
A _LibraryDependency_ provides information about an import or export.
+### LogRecord
+
+```
+class LogRecord extends Response {
+ // The log message.
+ @Instance message;
+
+ // The timestamp.
+ int time;
+
+ // The severity level (a value between 0 and 2000).
+ //
+ // See the package:logging `Level` class for an overview of the possible
+ // values.
+ int level;
+
+ // A monotonically increasing sequence number.
+ int sequenceNumber;
+
+ // The name of the source of the log message.
+ @Instance loggerName;
+
+ // The zone where the log was emitted.
+ @Instance zone;
+
+ // An error object associated with this log event.
+ @Instance error;
+
+ // A stack trace associated with this log event.
+ @Instance stackTrace;
+}
+```
+
### MapAssociation
```
@@ -2811,5 +2854,6 @@
3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index 2b4edd8..5daf941 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.17-dev
+# Dart VM Service Protocol 3.18-dev
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.17-dev_ of the Dart VM Service Protocol. This
+This document describes of _version 3.18-dev_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -75,6 +75,7 @@
- [Isolate](#isolate)
- [Library](#library)
- [LibraryDependency](#librarydependency)
+ - [LogRecord](#logrecord)
- [MapAssociation](#mapassociation)
- [MemoryUsage](#memoryusage)
- [Message](#message)
@@ -546,7 +547,7 @@
If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
result of this evaluation are ignored. Defaults to false if not provided.
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
If an error occurs while evaluating the expression, an [@Error](#error)
@@ -579,7 +580,7 @@
If _disableBreakpoints_ is provided and set to true, any breakpoints hit as a
result of this evaluation are ignored. Defaults to false if not provided.
-If expression is failed to parse and compile, then [rpc error](#rpc-error) 113
+If the expression fails to parse and compile, then [rpc error](#rpc-error) 113
"Expression compilation error" is returned.
If an error occurs while evaluating the expression, an [@Error](#error)
@@ -947,6 +948,7 @@
GC | GC
Extension | Extension
Timeline | TimelineEvents
+Logging | Logging
Additionally, some embedders provide the _Stdout_ and _Stderr_
streams. These streams allow the client to subscribe to writes to
@@ -1424,6 +1426,11 @@
// IsolateReloaded
// IsolateSpawn
string status [optional];
+
+ // LogRecord data.
+ //
+ // This is provided for the Logging event.
+ LogRecord logRecord [optional];
}
```
@@ -1506,6 +1513,9 @@
// Event from dart:developer.postEvent.
Extension
+
+ // Event from dart:developer.log.
+ Logging
}
```
@@ -2214,6 +2224,39 @@
A _LibraryDependency_ provides information about an import or export.
+### LogRecord
+
+```
+class LogRecord extends Response {
+ // The log message.
+ @Instance message;
+
+ // The timestamp.
+ int time;
+
+ // The severity level (a value between 0 and 2000).
+ //
+ // See the package:logging `Level` class for an overview of the possible
+ // values.
+ int level;
+
+ // A monotonically increasing sequence number.
+ int sequenceNumber;
+
+ // The name of the source of the log message.
+ @Instance loggerName;
+
+ // The zone where the log was emitted.
+ @Instance zone;
+
+ // An error object associated with this log event.
+ @Instance error;
+
+ // A stack trace associated with this log event.
+ @Instance stackTrace;
+}
+```
+
### MapAssociation
```
@@ -2811,5 +2854,6 @@
3.14 | Flag 'profile_period' can now be set at runtime, allowing for the profiler sample rate to be changed while the program is running.
3.15 | Added `disableBreakpoints` parameter to `invoke`, `evaluate`, and `evaluateInFrame`.
3.16 | Add 'getMemoryUsage' RPC and 'MemoryUsage' object.
+3.17 | Add 'Logging' event kind and the LogRecord class.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index 5822378..66ee578 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -95,7 +95,7 @@
case kEmbedder:
return embedder_kind();
case kLogging:
- return "_Logging";
+ return "Logging";
case kDebuggerSettingsUpdate:
return "_DebuggerSettingsUpdate";
case kIllegal:
@@ -239,6 +239,7 @@
}
if (kind() == kLogging) {
JSONObject logRecord(&jsobj, "logRecord");
+ logRecord.AddProperty("type", "LogRecord");
logRecord.AddProperty64("sequenceNumber", log_record_.sequence_number);
logRecord.AddPropertyTimeMillis("time", log_record_.timestamp);
logRecord.AddProperty64("level", log_record_.level);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 21c3382..99726ee 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -3852,7 +3852,7 @@
{
BYTECODE(StoreIndexedUint8, A_B_C);
uint8_t* data = SimulatorHelpers::GetTypedData(FP[rA], FP[rB]);
- *data = Smi::Value(RAW_CAST(Smi, FP[rC]));
+ *data = static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
DISPATCH();
}
@@ -3860,8 +3860,8 @@
BYTECODE(StoreIndexedUntaggedUint8, A_B_C);
uint8_t* array = reinterpret_cast<uint8_t*>(FP[rA]);
RawSmi* index = RAW_CAST(Smi, FP[rB]);
- RawSmi* value = RAW_CAST(Smi, FP[rC]);
- array[Smi::Value(index)] = Smi::Value(value);
+ array[Smi::Value(index)] =
+ static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
DISPATCH();
}
@@ -3896,9 +3896,9 @@
BYTECODE(StoreIndexedOneByteString, A_B_C);
RawOneByteString* array = RAW_CAST(OneByteString, FP[rA]);
RawSmi* index = RAW_CAST(Smi, FP[rB]);
- RawSmi* value = RAW_CAST(Smi, FP[rC]);
ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
- array->ptr()->data()[Smi::Value(index)] = Smi::Value(value);
+ array->ptr()->data()[Smi::Value(index)] =
+ static_cast<uint8_t>(reinterpret_cast<word>(FP[rC]));
DISPATCH();
}
@@ -4007,14 +4007,15 @@
{
BYTECODE(LoadIndexedUint8, A_B_C);
uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
- FP[rA] = Smi::New(*data);
+ FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
DISPATCH();
}
{
BYTECODE(LoadIndexedInt8, A_B_C);
- uint8_t* data = SimulatorHelpers::GetTypedData(FP[rB], FP[rC]);
- FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data));
+ int8_t* data = reinterpret_cast<int8_t*>(
+ SimulatorHelpers::GetTypedData(FP[rB], FP[rC]));
+ FP[rA] = reinterpret_cast<RawObject*>(static_cast<word>(*data));
DISPATCH();
}
@@ -4036,9 +4037,10 @@
{
BYTECODE(LoadIndexedUntaggedInt8, A_B_C);
- uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
+ int8_t* data = reinterpret_cast<int8_t*>(FP[rB]);
RawSmi* index = RAW_CAST(Smi, FP[rC]);
- FP[rA] = Smi::New(*reinterpret_cast<int8_t*>(data + Smi::Value(index)));
+ FP[rA] = reinterpret_cast<RawObject*>(
+ static_cast<word>(data[Smi::Value(index)]));
DISPATCH();
}
@@ -4046,7 +4048,8 @@
BYTECODE(LoadIndexedUntaggedUint8, A_B_C);
uint8_t* data = reinterpret_cast<uint8_t*>(FP[rB]);
RawSmi* index = RAW_CAST(Smi, FP[rC]);
- FP[rA] = Smi::New(*reinterpret_cast<uint8_t*>(data + Smi::Value(index)));
+ FP[rA] = reinterpret_cast<RawObject*>(
+ static_cast<word>(data[Smi::Value(index)]));
DISPATCH();
}
@@ -4092,7 +4095,8 @@
RawOneByteString* array = RAW_CAST(OneByteString, FP[rB]);
RawSmi* index = RAW_CAST(Smi, FP[rC]);
ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
- FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+ FP[rA] = reinterpret_cast<RawObject*>(
+ static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
DISPATCH();
}
@@ -4101,7 +4105,8 @@
RawTwoByteString* array = RAW_CAST(TwoByteString, FP[rB]);
RawSmi* index = RAW_CAST(Smi, FP[rC]);
ASSERT(SimulatorHelpers::CheckIndex(index, array->ptr()->length_));
- FP[rA] = Smi::New(array->ptr()->data()[Smi::Value(index)]);
+ FP[rA] = reinterpret_cast<RawObject*>(
+ static_cast<word>(array->ptr()->data()[Smi::Value(index)]));
DISPATCH();
}
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 8f0e9cf..019cb7c 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -191,6 +191,10 @@
void SourceReport::PrintCallSitesData(JSONObject* jsobj,
const Function& function,
const Code& code) {
+ if (code.IsNull()) {
+ // TODO(regis): implement for bytecode.
+ return;
+ }
const TokenPosition begin_pos = function.token_pos();
const TokenPosition end_pos = function.end_token_pos();
@@ -230,6 +234,10 @@
void SourceReport::PrintCoverageData(JSONObject* jsobj,
const Function& function,
const Code& code) {
+ if (code.IsNull()) {
+ // TODO(regis): implement for bytecode.
+ return;
+ }
const TokenPosition begin_pos = function.token_pos();
const TokenPosition end_pos = function.end_token_pos();
@@ -312,15 +320,8 @@
void SourceReport::PrintPossibleBreakpointsData(JSONObject* jsobj,
const Function& func,
const Code& code) {
- const uint8_t kSafepointKind =
- (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
- RawPcDescriptors::kRuntimeCall);
const TokenPosition begin_pos = func.token_pos();
const TokenPosition end_pos = func.end_token_pos();
-
- const PcDescriptors& descriptors =
- PcDescriptors::Handle(zone(), code.pc_descriptors());
-
intptr_t func_length = (end_pos.Pos() - begin_pos.Pos()) + 1;
GrowableArray<char> possible(func_length);
possible.SetLength(func_length);
@@ -328,15 +329,37 @@
possible[i] = false;
}
- PcDescriptors::Iterator iter(descriptors, kSafepointKind);
- while (iter.MoveNext()) {
- const TokenPosition token_pos = iter.TokenPos();
- if ((token_pos < begin_pos) || (token_pos > end_pos)) {
- // Does not correspond to a valid source position.
- continue;
+ if (code.IsNull()) {
+ const Bytecode& bytecode = Bytecode::Handle(func.bytecode());
+ ASSERT(!bytecode.IsNull());
+ kernel::BytecodeSourcePositionsIterator iter(zone(), bytecode);
+ while (iter.MoveNext()) {
+ const TokenPosition token_pos = iter.TokenPos();
+ if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ // Does not correspond to a valid source position.
+ continue;
+ }
+ intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+ possible[token_offset] = true;
}
- intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
- possible[token_offset] = true;
+ } else {
+ const uint8_t kSafepointKind =
+ (RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall |
+ RawPcDescriptors::kRuntimeCall);
+
+ const PcDescriptors& descriptors =
+ PcDescriptors::Handle(zone(), code.pc_descriptors());
+
+ PcDescriptors::Iterator iter(descriptors, kSafepointKind);
+ while (iter.MoveNext()) {
+ const TokenPosition token_pos = iter.TokenPos();
+ if ((token_pos < begin_pos) || (token_pos > end_pos)) {
+ // Does not correspond to a valid source position.
+ continue;
+ }
+ intptr_t token_offset = token_pos.Pos() - begin_pos.Pos();
+ possible[token_offset] = true;
+ }
}
JSONArray bpts(jsobj, "possibleBreakpoints");
@@ -465,14 +488,8 @@
range.AddProperty("scriptIndex", GetScriptIndex(script));
range.AddProperty("startPos", begin_pos);
range.AddProperty("endPos", end_pos);
- // TODO(regis): What is the meaning of 'compiled' in the presence of bytecode?
- // If it means 'called', it should say 'true' if bytecode is present.
- range.AddProperty("compiled", !code.IsNull());
+ range.AddProperty("compiled", true); // bytecode or code.
- // TODO(regis): Do we want a report covering interpreted functions too?
- if (code.IsNull()) {
- return;
- }
if (IsReportRequested(kCallSites)) {
PrintCallSitesData(&range, func, code);
}
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index b1d4b79..4d97d94 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -180,11 +180,9 @@
if (is_interpreted()) {
const Bytecode& bytecode = Bytecode::Handle(zone, LookupDartBytecode());
ASSERT(!bytecode.IsNull());
- const Function& function = Function::Handle(zone, bytecode.function());
- ASSERT(!function.IsNull());
- return zone->PrintToString(
- "[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px ") bytecode %s ]",
- GetName(), sp(), fp(), pc(), function.ToFullyQualifiedCString());
+ return zone->PrintToString("[%-8s : sp(%#" Px ") fp(%#" Px ") pc(%#" Px
+ ") %s ]",
+ GetName(), sp(), fp(), pc(), bytecode.Name());
}
const Code& code = Code::Handle(zone, LookupDartCode());
ASSERT(!code.IsNull());
@@ -501,7 +499,6 @@
ASSERT(!bytecode.IsNull());
start = bytecode.PayloadStart();
handlers = bytecode.exception_handlers();
- descriptors = bytecode.pc_descriptors();
} else {
code = LookupDartCode();
if (code.IsNull()) {
@@ -520,33 +517,17 @@
*has_catch_all = info->has_catch_all;
return true;
}
- uword pc_offset = pc() - start;
if (handlers.num_entries() == 0) {
return false;
}
- PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
intptr_t try_index = -1;
if (is_interpreted()) {
- while (iter.MoveNext()) {
- // PC descriptors for try blocks in bytecode are generated in pairs,
- // marking start and end of a try block.
- // See BytecodeMetadataHelper::ReadExceptionsTable for details.
- const intptr_t current_try_index = iter.TryIndex();
- const uword start_pc = iter.PcOffset();
- if (pc_offset < start_pc) {
- break;
- }
- const bool has_next = iter.MoveNext();
- ASSERT(has_next);
- const uword end_pc = iter.PcOffset();
- if (start_pc <= pc_offset && pc_offset < end_pc) {
- ASSERT(try_index < current_try_index);
- try_index = current_try_index;
- }
- }
+ try_index = bytecode.GetTryIndexAtPc(pc());
} else {
+ uword pc_offset = pc() - code.PayloadStart();
+ PcDescriptors::Iterator iter(descriptors, RawPcDescriptors::kAnyKind);
while (iter.MoveNext()) {
const intptr_t current_try_index = iter.TryIndex();
if ((iter.PcOffset() == pc_offset) && (current_try_index != -1)) {
diff --git a/runtime/vm/stack_frame.h b/runtime/vm/stack_frame.h
index bf67520..7753a4f 100644
--- a/runtime/vm/stack_frame.h
+++ b/runtime/vm/stack_frame.h
@@ -134,8 +134,7 @@
protected:
explicit StackFrame(Thread* thread)
- : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {
- }
+ : fp_(0), sp_(0), pc_(0), thread_(thread), is_interpreted_(false) {}
// Name of the frame, used for generic frame printing functionality.
virtual const char* GetName() const {
diff --git a/runtime/vm/stack_frame_arm.h b/runtime/vm/stack_frame_arm.h
index 2b5dc3e..cf95a67 100644
--- a/runtime/vm/stack_frame_arm.h
+++ b/runtime/vm/stack_frame_arm.h
@@ -55,6 +55,12 @@
COMPILE_ASSERT(kAbiPreservedFpuRegCount == 4);
#endif
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
} // namespace dart
#endif // RUNTIME_VM_STACK_FRAME_ARM_H_
diff --git a/runtime/vm/stack_frame_arm64.h b/runtime/vm/stack_frame_arm64.h
index 3b8c726..b1b2288 100644
--- a/runtime/vm/stack_frame_arm64.h
+++ b/runtime/vm/stack_frame_arm64.h
@@ -49,6 +49,12 @@
COMPILE_ASSERT(kAbiPreservedCpuRegCount == 10);
COMPILE_ASSERT(kAbiPreservedFpuRegCount == 8);
+// For FFI native -> Dart callbacks, this is the number of stack slots between
+// arguments passed on stack and arguments saved in callback prologue.
+//
+// 2 = return adddress (1) + saved frame pointer (1).
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 2;
+
} // namespace dart
#endif // RUNTIME_VM_STACK_FRAME_ARM64_H_
diff --git a/runtime/vm/stack_frame_dbc.h b/runtime/vm/stack_frame_dbc.h
index 632f68c..e3d8395 100644
--- a/runtime/vm/stack_frame_dbc.h
+++ b/runtime/vm/stack_frame_dbc.h
@@ -81,6 +81,10 @@
// on all other architectures.
static const uword kInterruptStackLimit = 0;
+// TODO(37140): For FFI native -> Dart callbacks, the number of stack slots
+// between arguments passed on stack and arguments saved in callback prologue.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = -1;
+
} // namespace dart
#endif // RUNTIME_VM_STACK_FRAME_DBC_H_
diff --git a/runtime/vm/stack_frame_ia32.h b/runtime/vm/stack_frame_ia32.h
index b770cf7..70717c2 100644
--- a/runtime/vm/stack_frame_ia32.h
+++ b/runtime/vm/stack_frame_ia32.h
@@ -46,6 +46,10 @@
// Entry and exit frame layout.
static const int kExitLinkSlotFromEntryFp = -7;
+// All arguments are passed on the stack, so none need to be saved. Therefore
+// there is no frame for holding the saved arguments.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments = 0;
+
} // namespace dart
#endif // RUNTIME_VM_STACK_FRAME_IA32_H_
diff --git a/runtime/vm/stack_frame_x64.h b/runtime/vm/stack_frame_x64.h
index 00d0059..193db62 100644
--- a/runtime/vm/stack_frame_x64.h
+++ b/runtime/vm/stack_frame_x64.h
@@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_STACK_FRAME_X64_H_
#define RUNTIME_VM_STACK_FRAME_X64_H_
+#include "vm/constants_x64.h"
+
namespace dart {
/* X64 Dart Frame Layout
@@ -52,6 +54,13 @@
static const int kExitLinkSlotFromEntryFp = -10;
#endif // defined(_WIN64)
+// For FFI native -> Dart callbacks, the number of stack slots between arguments
+// passed on stack and arguments saved in callback prologue. 2 = return adddress
+// (1) + saved frame pointer (1). Also add slots for the shadow space, if
+// present.
+constexpr intptr_t kCallbackSlotsBeforeSavedArguments =
+ 2 + CallingConventions::kShadowSpaceBytes / kWordSize;
+
} // namespace dart
#endif // RUNTIME_VM_STACK_FRAME_X64_H_
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index 7f93f5b8..248c455 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -77,7 +77,8 @@
V(OneArgCheckInlineCacheWithExactnessCheck) \
V(OneArgOptimizedCheckInlineCacheWithExactnessCheck) \
V(EnterSafepoint) \
- V(ExitSafepoint)
+ V(ExitSafepoint) \
+ V(VerifyCallback)
#else
#define VM_STUB_CODE_LIST(V) \
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 845d780..f265e3e 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -179,6 +179,7 @@
V(GetterPrefix, "get:") \
V(GreaterEqualOperator, ">=") \
V(GrowRegExpStack, "_growRegExpStack") \
+ V(HandleExposedException, "_handleExposedException") \
V(HaveSameRuntimeType, "_haveSameRuntimeType") \
V(Hide, "hide") \
V(ICData, "ICData") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index 6b48726..71a9b2d 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -6,6 +6,7 @@
#include "vm/dart_api_state.h"
#include "vm/growable_array.h"
+#include "vm/heap/safepoint.h"
#include "vm/isolate.h"
#include "vm/json_stream.h"
#include "vm/lockers.h"
@@ -76,6 +77,7 @@
resume_pc_(0),
execution_state_(kThreadInNative),
safepoint_state_(0),
+ ffi_callback_code_(GrowableObjectArray::null()),
task_kind_(kUnknownTask),
dart_stream_(NULL),
thread_lock_(),
@@ -668,6 +670,7 @@
visitor->VisitPointer(reinterpret_cast<RawObject**>(&active_stacktrace_));
visitor->VisitPointer(reinterpret_cast<RawObject**>(&sticky_error_));
visitor->VisitPointer(reinterpret_cast<RawObject**>(&async_stack_trace_));
+ visitor->VisitPointer(reinterpret_cast<RawObject**>(&ffi_callback_code_));
#if !defined(DART_PRECOMPILED_RUNTIME)
if (interpreter() != NULL) {
@@ -936,4 +939,45 @@
}
}
+const intptr_t kInitialCallbackIdsReserved = 1024;
+int32_t Thread::AllocateFfiCallbackId() {
+ Zone* Z = isolate()->current_zone();
+ if (ffi_callback_code_ == GrowableObjectArray::null()) {
+ ffi_callback_code_ = GrowableObjectArray::New(kInitialCallbackIdsReserved);
+ }
+ const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+ array.Add(Code::Handle(Z, Code::null()));
+ return array.Length() - 1;
+}
+
+void Thread::SetFfiCallbackCode(int32_t callback_id, const Code& code) {
+ Zone* Z = isolate()->current_zone();
+ const auto& array = GrowableObjectArray::Handle(Z, ffi_callback_code_);
+ array.SetAt(callback_id, code);
+}
+
+void Thread::VerifyCallbackIsolate(int32_t callback_id, uword entry) {
+ NoSafepointScope _;
+
+ const RawGrowableObjectArray* const array = ffi_callback_code_;
+ if (array == GrowableObjectArray::null()) {
+ FATAL("Cannot invoke callback on incorrect isolate.");
+ }
+
+ const RawSmi* const length_smi =
+ GrowableObjectArray::NoSafepointLength(array);
+ const intptr_t length = Smi::Value(length_smi);
+
+ if (callback_id < 0 || callback_id >= length) {
+ FATAL("Cannot invoke callback on incorrect isolate.");
+ }
+
+ RawObject** const code_array =
+ Array::DataOf(GrowableObjectArray::NoSafepointData(array));
+ const RawCode* const code = Code::RawCast(code_array[callback_id]);
+ if (!Code::ContainsInstructionAt(code, entry)) {
+ FATAL("Cannot invoke callback on incorrect isolate.");
+ }
+}
+
} // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index c9d81bb..44bb9e6 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -168,8 +168,8 @@
V(uword, monomorphic_miss_entry_, StubCode::MonomorphicMiss().EntryPoint(), \
0) \
V(uword, optimize_entry_, StubCode::OptimizeFunction().EntryPoint(), 0) \
- V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0)
-
+ V(uword, deoptimize_entry_, StubCode::Deoptimize().EntryPoint(), 0) \
+ V(uword, verify_callback_entry_, StubCode::VerifyCallback().EntryPoint(), 0)
#endif
#define CACHED_ADDRESSES_LIST(V) \
@@ -315,6 +315,10 @@
return OFFSET_OF(Thread, safepoint_state_);
}
+ static intptr_t callback_code_offset() {
+ return OFFSET_OF(Thread, ffi_callback_code_);
+ }
+
TaskKind task_kind() const { return task_kind_; }
// Retrieves and clears the stack overflow flags. These are set by
@@ -768,6 +772,13 @@
}
}
+ int32_t AllocateFfiCallbackId();
+ void SetFfiCallbackCode(int32_t callback_id, const Code& code);
+
+ // Ensure that 'entry' points within the code of the callback identified by
+ // 'callback_id'. Aborts otherwise.
+ void VerifyCallbackIsolate(int32_t callback_id, uword entry);
+
Thread* next() const { return next_; }
// Visit all object pointers.
@@ -861,6 +872,7 @@
uword resume_pc_;
uword execution_state_;
uword safepoint_state_;
+ RawGrowableObjectArray* ffi_callback_code_;
// ---- End accessed from generated code. ----
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 398ecc8..168f264 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -685,8 +685,6 @@
val = lib.EvaluateCompiledExpression(kernel_bytes, kernel_length,
Array::empty_array(), param_values,
TypeArguments::null_type_arguments());
-
- free(const_cast<uint8_t*>(kernel_bytes));
}
return Api::NewHandle(thread, val.raw());
}
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index e646a21..a1f20bf 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -85,6 +85,7 @@
"debugger_arm64.cc",
"debugger_dbc.cc",
"debugger_ia32.cc",
+ "debugger_kbc.cc",
"debugger_x64.cc",
"deferred_objects.cc",
"deferred_objects.h",
@@ -95,6 +96,8 @@
"double_internals.h",
"dwarf.cc",
"dwarf.h",
+ "elf.cc",
+ "elf.h",
"exceptions.cc",
"exceptions.h",
"finalizable_data.h",
@@ -388,10 +391,8 @@
"cpuinfo_test.cc",
"custom_isolate_test.cc",
"dart_api_impl_test.cc",
- "dart_entry_test.cc",
"debugger_api_impl_test.cc",
"exceptions_test.cc",
- "find_code_object_test.cc",
"fixed_cache_test.cc",
"flags_test.cc",
"growable_array_test.cc",
@@ -430,7 +431,6 @@
"port_test.cc",
"profiler_test.cc",
"regexp_test.cc",
- "resolver_test.cc",
"ring_buffer_test.cc",
"scopes_test.cc",
"service_test.cc",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 595871a..cdb8ba4 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -331,19 +331,20 @@
return OS::VSCreate(this, format, args);
}
-StackZone::StackZone(ThreadState* thread) : StackResource(thread), zone_() {
+StackZone::StackZone(ThreadState* thread)
+ : StackResource(thread), zone_(new Zone()) {
if (FLAG_trace_zones) {
OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
reinterpret_cast<intptr_t>(this),
- reinterpret_cast<intptr_t>(&zone_));
+ reinterpret_cast<intptr_t>(zone_));
}
// This thread must be preventing safepoints or the GC could be visiting the
// chain of handle blocks we're about the mutate.
ASSERT(Thread::Current()->MayAllocateHandles());
- zone_.Link(thread->zone());
- thread->set_zone(&zone_);
+ zone_->Link(thread->zone());
+ thread->set_zone(zone_);
}
StackZone::~StackZone() {
@@ -351,13 +352,15 @@
// chain of handle blocks we're about the mutate.
ASSERT(Thread::Current()->MayAllocateHandles());
- ASSERT(thread()->zone() == &zone_);
- thread()->set_zone(zone_.previous_);
+ ASSERT(thread()->zone() == zone_);
+ thread()->set_zone(zone_->previous_);
if (FLAG_trace_zones) {
OS::PrintErr("*** Deleting Stack zone 0x%" Px "(0x%" Px ")\n",
reinterpret_cast<intptr_t>(this),
- reinterpret_cast<intptr_t>(&zone_));
+ reinterpret_cast<intptr_t>(zone_));
}
+
+ delete zone_;
}
} // namespace dart
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index b4aba7f..88e1ef9 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -177,19 +177,19 @@
explicit StackZone(ThreadState* thread);
// Delete all memory associated with the zone.
- ~StackZone();
+ virtual ~StackZone();
// Compute the total size of this zone. This includes wasted space that is
// due to internal fragmentation in the segments.
- uintptr_t SizeInBytes() const { return zone_.SizeInBytes(); }
+ uintptr_t SizeInBytes() const { return zone_->SizeInBytes(); }
// Computes the used space in the zone.
- intptr_t CapacityInBytes() const { return zone_.CapacityInBytes(); }
+ intptr_t CapacityInBytes() const { return zone_->CapacityInBytes(); }
- Zone* GetZone() { return &zone_; }
+ Zone* GetZone() { return zone_; }
private:
- Zone zone_;
+ Zone* zone_;
template <typename T>
friend class GrowableArray;
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index f1e72be..4e7d636 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -1958,6 +1958,14 @@
*/
int get contentLength;
+ /// The compression state of the response.
+ ///
+ /// This specifies whether the response bytes were compressed when they were
+ /// received across the wire and whether callers will receive compressed
+ /// or uncompressed bytes when they listed to this response's byte stream.
+ @Since("2.3.2")
+ HttpClientResponseCompressionState get compressionState;
+
/**
* Gets the persistent connection state returned by the server.
*
@@ -2037,6 +2045,49 @@
HttpConnectionInfo get connectionInfo;
}
+/// Enum that specifies the compression state of the byte stream of an
+/// [HttpClientResponse].
+///
+/// The values herein allow callers to answer the following questions as they
+/// pertain to an [HttpClientResponse]:
+///
+/// * Can the value of the response's `Content-Length` HTTP header be trusted?
+/// * Does the caller need to manually decompress the response's byte stream?
+///
+/// This enum is accessed via the [HttpClientResponse.compressionState] value.
+@Since("2.3.2")
+enum HttpClientResponseCompressionState {
+ /// The body of the HTTP response was received and remains in an uncompressed
+ /// state.
+ ///
+ /// In this state, the value of the `Content-Length` HTTP header, if
+ /// specified (non-negative), should match the number of bytes produced by
+ /// the response's byte stream.
+ notCompressed,
+
+ /// The body of the HTTP response was originally compressed, but by virtue of
+ /// the [HttpClient.autoUncompress] configuration option, it has been
+ /// automatically uncompressed.
+ ///
+ /// HTTP headers are not modified, so when a response has been uncompressed
+ /// in this way, the value of the `Content-Length` HTTP header cannot be
+ /// trusted, as it will contain the compressed content length, whereas the
+ /// stream of bytes produced by the response will contain uncompressed bytes.
+ decompressed,
+
+ /// The body of the HTTP response contains compressed bytes.
+ ///
+ /// In this state, the value of the `Content-Length` HTTP header, if
+ /// specified (non-negative), should match the number of bytes produced by
+ /// the response's byte stream.
+ ///
+ /// If the caller wishes to manually uncompress the body of the response,
+ /// it should consult the value of the `Content-Encoding` HTTP header to see
+ /// what type of compression has been applied. See
+ /// <https://tools.ietf.org/html/rfc2616#section-14.11> for more information.
+ compressed,
+}
+
abstract class HttpClientCredentials {}
/**
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index ea5eaff..dc9ff84 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -982,14 +982,24 @@
codeUnit >= 127 ||
separators.indexOf(name[i]) >= 0) {
throw new FormatException(
- "Invalid character in cookie name, code unit: '$codeUnit'");
+ "Invalid character in cookie name, code unit: '$codeUnit'",
+ name,
+ i);
}
}
- if (value[0] == '"' && value[value.length - 1] == '"') {
- value = value.substring(1, value.length - 1);
+ // Per RFC 6265, consider surrounding "" as part of the value, but otherwise
+ // double quotes are not allowed.
+ int start = 0;
+ int end = value.length;
+ if (2 <= value.length &&
+ value.codeUnits[start] == 0x22 &&
+ value.codeUnits[end - 1] == 0x22) {
+ start++;
+ end--;
}
- for (int i = 0; i < value.length; i++) {
+
+ for (int i = start; i < end; i++) {
int codeUnit = value.codeUnits[i];
if (!(codeUnit == 0x21 ||
(codeUnit >= 0x23 && codeUnit <= 0x2B) ||
@@ -997,7 +1007,9 @@
(codeUnit >= 0x3C && codeUnit <= 0x5B) ||
(codeUnit >= 0x5D && codeUnit <= 0x7E))) {
throw new FormatException(
- "Invalid character in cookie value, code unit: '$codeUnit'");
+ "Invalid character in cookie value, code unit: '$codeUnit'",
+ value,
+ i);
}
}
}
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index a70ca82..497516c 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -292,24 +292,35 @@
// The HttpClientRequest of this response.
final _HttpClientRequest _httpRequest;
- // Whether this response is configured to auto uncompress.
- final bool autoUncompress;
+ // The compression state of this response.
+ final HttpClientResponseCompressionState compressionState;
_HttpClientResponse(
_HttpIncoming _incoming, this._httpRequest, this._httpClient)
- : autoUncompress = _httpClient.autoUncompress,
+ : compressionState = _getCompressionState(_httpClient, _incoming.headers),
super(_incoming) {
// Set uri for potential exceptions.
_incoming.uri = _httpRequest.uri;
}
+ static HttpClientResponseCompressionState _getCompressionState(
+ _HttpClient httpClient, _HttpHeaders headers) {
+ if (headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+ return httpClient.autoUncompress
+ ? HttpClientResponseCompressionState.decompressed
+ : HttpClientResponseCompressionState.compressed;
+ } else {
+ return HttpClientResponseCompressionState.notCompressed;
+ }
+ }
+
int get statusCode => _incoming.statusCode;
String get reasonPhrase => _incoming.reasonPhrase;
X509Certificate get certificate {
var socket = _httpRequest._httpClientConnection._socket;
if (socket is SecureSocket) return socket.peerCertificate;
- throw new UnsupportedError("Socket is not a SecureSocket");
+ return null;
}
List<Cookie> get cookies {
@@ -381,8 +392,7 @@
return new Stream<List<int>>.empty().listen(null, onDone: onDone);
}
Stream<List<int>> stream = _incoming;
- if (autoUncompress &&
- headers.value(HttpHeaders.contentEncodingHeader) == "gzip") {
+ if (compressionState == HttpClientResponseCompressionState.decompressed) {
stream = stream.transform(gzip.decoder);
}
return stream.listen(onData,
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 998f42b..d0a1215 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -2352,6 +2352,7 @@
_rsh(uDigits, maxUsed, 1, uDigits);
if (ac) {
if (((aDigits[0] & 1) == 1) || ((bDigits[0] & 1) == 1)) {
+ // a += y
if (aIsNegative) {
if ((aDigits[maxUsed] != 0) ||
(_compareDigits(aDigits, maxUsed, yDigits, maxUsed)) > 0) {
@@ -2363,6 +2364,7 @@
} else {
_absAdd(aDigits, abcdUsed, yDigits, maxUsed, aDigits);
}
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2375,6 +2377,7 @@
}
_rsh(aDigits, abcdUsed, 1, aDigits);
} else if ((bDigits[0] & 1) == 1) {
+ // b -= x
if (bIsNegative) {
_absAdd(bDigits, abcdUsed, xDigits, maxUsed, bDigits);
} else if ((bDigits[maxUsed] != 0) ||
@@ -2391,6 +2394,7 @@
_rsh(vDigits, maxUsed, 1, vDigits);
if (ac) {
if (((cDigits[0] & 1) == 1) || ((dDigits[0] & 1) == 1)) {
+ // c += y
if (cIsNegative) {
if ((cDigits[maxUsed] != 0) ||
(_compareDigits(cDigits, maxUsed, yDigits, maxUsed) > 0)) {
@@ -2402,6 +2406,7 @@
} else {
_absAdd(cDigits, abcdUsed, yDigits, maxUsed, cDigits);
}
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2414,6 +2419,7 @@
}
_rsh(cDigits, abcdUsed, 1, cDigits);
} else if ((dDigits[0] & 1) == 1) {
+ // d -= x
if (dIsNegative) {
_absAdd(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
} else if ((dDigits[maxUsed] != 0) ||
@@ -2427,8 +2433,10 @@
_rsh(dDigits, abcdUsed, 1, dDigits);
}
if (_compareDigits(uDigits, maxUsed, vDigits, maxUsed) >= 0) {
+ // u -= v
_absSub(uDigits, maxUsed, vDigits, maxUsed, uDigits);
if (ac) {
+ // a -= c
if (aIsNegative == cIsNegative) {
var a_cmp_c = _compareDigits(aDigits, abcdUsed, cDigits, abcdUsed);
if (a_cmp_c > 0) {
@@ -2441,6 +2449,7 @@
_absAdd(aDigits, abcdUsed, cDigits, abcdUsed, aDigits);
}
}
+ // b -= d
if (bIsNegative == dIsNegative) {
var b_cmp_d = _compareDigits(bDigits, abcdUsed, dDigits, abcdUsed);
if (b_cmp_d > 0) {
@@ -2453,8 +2462,10 @@
_absAdd(bDigits, abcdUsed, dDigits, abcdUsed, bDigits);
}
} else {
+ // v -= u
_absSub(vDigits, maxUsed, uDigits, maxUsed, vDigits);
if (ac) {
+ // c -= a
if (cIsNegative == aIsNegative) {
var c_cmp_a = _compareDigits(cDigits, abcdUsed, aDigits, abcdUsed);
if (c_cmp_a > 0) {
@@ -2467,6 +2478,7 @@
_absAdd(cDigits, abcdUsed, aDigits, abcdUsed, cDigits);
}
}
+ // d -= b
if (dIsNegative == bIsNegative) {
var d_cmp_b = _compareDigits(dDigits, abcdUsed, bDigits, abcdUsed);
if (d_cmp_b > 0) {
@@ -2498,25 +2510,18 @@
}
if (dIsNegative) {
- if ((dDigits[maxUsed] != 0) ||
+ while ((dDigits[maxUsed] != 0) ||
(_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x, d still negative
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
- }
- } else {
- _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
- dIsNegative = false;
}
- } else if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
- _absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
- if ((dDigits[maxUsed] != 0) ||
- (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) > 0)) {
+ // d += x
+ _absSub(xDigits, maxUsed, dDigits, maxUsed, dDigits);
+ dIsNegative = false;
+ } else {
+ while ((dDigits[maxUsed] != 0) ||
+ (_compareDigits(dDigits, maxUsed, xDigits, maxUsed) >= 0)) {
+ // d -= x
_absSub(dDigits, abcdUsed, xDigits, maxUsed, dDigits);
}
}
diff --git a/sdk/lib/developer/extension.dart b/sdk/lib/developer/extension.dart
index c6f4cce..3cc4ede 100644
--- a/sdk/lib/developer/extension.dart
+++ b/sdk/lib/developer/extension.dart
@@ -9,19 +9,24 @@
/// If the RPC was successful, use [ServiceExtensionResponse.result], otherwise
/// use [ServiceExtensionResponse.error].
class ServiceExtensionResponse {
- final String _result;
- final int _errorCode;
- final String _errorDetail;
+ /// The result of a successful service protocol extension RPC.
+ final String result;
+
+ /// The error code associated with a failed service protocol extension RPC.
+ final int errorCode;
+
+ /// The details of a failed service protocol extension RPC.
+ final String errorDetail;
/// Creates a successful response to a service protocol extension RPC.
///
/// Requires [result] to be a JSON object encoded as a string. When forming
/// the JSON-RPC message [result] will be inlined directly.
ServiceExtensionResponse.result(String result)
- : _result = result,
- _errorCode = null,
- _errorDetail = null {
- ArgumentError.checkNotNull(_result, "result");
+ : result = result,
+ errorCode = null,
+ errorDetail = null {
+ ArgumentError.checkNotNull(result, "result");
}
/// Creates an error response to a service protocol extension RPC.
@@ -31,11 +36,11 @@
/// encoded as a string. When forming the JSON-RPC message [errorDetail] will
/// be inlined directly.
ServiceExtensionResponse.error(int errorCode, String errorDetail)
- : _result = null,
- _errorCode = errorCode,
- _errorDetail = errorDetail {
- _validateErrorCode(_errorCode);
- ArgumentError.checkNotNull(_errorDetail, "errorDetail");
+ : result = null,
+ errorCode = errorCode,
+ errorDetail = errorDetail {
+ _validateErrorCode(errorCode);
+ ArgumentError.checkNotNull(errorDetail, "errorDetail");
}
/// Invalid method parameter(s) error code.
@@ -83,20 +88,20 @@
throw new ArgumentError.value(errorCode, "errorCode", "Out of range");
}
- // ignore: unused_element, called from runtime/lib/developer.dart
- bool _isError() => (_errorCode != null) && (_errorDetail != null);
+ /// Determines if this response represents an error.
+ bool isError() => (errorCode != null) && (errorDetail != null);
// ignore: unused_element, called from runtime/lib/developer.dart
String _toString() {
- if (_result != null) {
- return _result;
+ if (result != null) {
+ return result;
} else {
- assert(_errorCode != null);
- assert(_errorDetail != null);
+ assert(errorCode != null);
+ assert(errorDetail != null);
return json.encode({
- 'code': _errorCode,
- 'message': _errorCodeMessage(_errorCode),
- 'data': {'details': _errorDetail}
+ 'code': errorCode,
+ 'message': _errorCodeMessage(errorCode),
+ 'data': {'details': errorDetail}
});
}
}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 656fa6b..eb75be5 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13944,6 +13944,8 @@
@JSName('innerHTML')
String _innerHtml;
+ String innerText;
+
@JSName('localName')
final String _localName;
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index c4f2692..5321ddf 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -10,6 +10,17 @@
LibTest/html/*: SkipByDesign # d8 is not a browser
WebPlatformTest/*: SkipByDesign # d8 is not a browser
+[ $compiler == dart2js && $runtime == ie11 ]
+LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListBase/ListBase_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/collection/ListMixin/ListMixin_class_A01_t06: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t04: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t05: SkipSlow # slow babeljs transformation
+LibTest/core/List/List_class_A01_t06: SkipSlow # slow babeljs transformation
+
[ $compiler == dart2js || $compiler == dartdevc || $compiler == dartdevk ]
Language/Expressions/Spawning_an_Isolate/new_isolate_t01: SkipByDesign
LibTest/io/*: SkipByDesign # dart:io not supported.
diff --git a/tests/compiler/dart2js/analyses/api_allowed.json b/tests/compiler/dart2js/analyses/api_allowed.json
index a7a08a3..cec99f0 100644
--- a/tests/compiler/dart2js/analyses/api_allowed.json
+++ b/tests/compiler/dart2js/analyses/api_allowed.json
@@ -28,10 +28,10 @@
"Dynamic invocation of '_js_helper::_execGlobal'.": 1,
"Dynamic access of 'start'.": 1,
"Dynamic access of 'end'.": 1,
- "Dynamic access of 'length'.": 3,
- "Dynamic invocation of '[]'.": 1,
"Dynamic invocation of 'call'.": 13,
+ "Dynamic access of 'length'.": 3,
"Dynamic invocation of 'codeUnitAt'.": 2,
+ "Dynamic invocation of '[]'.": 1,
"Dynamic access of 'iterator'.": 2,
"Dynamic invocation of 'replaceRange'.": 2
},
@@ -184,7 +184,7 @@
"org-dartlang-sdk:///sdk/lib/_internal/js_runtime/lib/core_patch.dart": {
"Dynamic access of 'dart.core::_digits'.": 2,
"Dynamic invocation of '<'.": 2,
- "Dynamic invocation of '[]'.": 19,
+ "Dynamic invocation of '[]'.": 17,
"Dynamic invocation of '+'.": 2,
"Dynamic invocation of 'dart.core::_absSubSetSign'.": 3,
"Dynamic invocation of 'dart.core::_absAndNotSetSign'.": 2,
@@ -244,4 +244,4 @@
"Dynamic access of 'port'.": 1,
"Dynamic invocation of 'dart._http::_toJSON'.": 1
}
-}
+}
\ No newline at end of file
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index 61f5c27..47d0c5c 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -6,6 +6,7 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/closure.dart';
import 'package:compiler/src/common.dart';
+import 'package:compiler/src/common/codegen.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/elements/entities.dart';
@@ -89,9 +90,9 @@
void registerCalls(Features features, String tag, js.Node node,
{String prefix = '', Set<js.PropertyAccess> handledAccesses}) {
forEachNode(node, onCall: (js.Call node) {
- js.Node target = node.target;
+ js.Node target = undefer(node.target);
if (target is js.PropertyAccess) {
- js.Node selector = target.selector;
+ js.Node selector = undefer(target.selector);
bool fixedNameCall = false;
String name;
if (selector is js.Name) {
@@ -125,7 +126,7 @@
return;
}
- js.Node receiver = node.receiver;
+ js.Node receiver = undefer(node.receiver);
String receiverName;
if (receiver is js.VariableUse) {
receiverName = receiver.name;
@@ -138,7 +139,7 @@
receiverName = 'this';
}
- js.Node selector = node.selector;
+ js.Node selector = undefer(node.selector);
String name;
if (selector is js.Name) {
name = selector.key;
@@ -229,9 +230,9 @@
}
forEachNode(code, onAssignment: (js.Assignment node) {
- js.Expression leftHandSide = node.leftHandSide;
+ js.Expression leftHandSide = undefer(node.leftHandSide);
if (leftHandSide is js.PropertyAccess) {
- js.Node selector = leftHandSide.selector;
+ js.Node selector = undefer(leftHandSide.selector);
String name;
if (selector is js.Name) {
name = selector.key;
@@ -272,3 +273,9 @@
return null;
}
}
+
+js.Node undefer(js.Node node) {
+ if (node is js.DeferredExpression) return undefer(node.value);
+ if (node is ModularName) return undefer(node.value);
+ return node;
+}
diff --git a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
index e79853c..b23c178 100644
--- a/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
+++ b/tests/compiler/dart2js/deferred_loading/deferred_loading_test.dart
@@ -105,7 +105,7 @@
{bool verbose: false}) {
JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
OutputUnitData data = closedWorld.outputUnitData;
- String value = outputUnitString(data.outputUnitForClass(cls));
+ String value = outputUnitString(data.outputUnitForClassForTesting(cls));
JsToElementMap elementMap = closedWorld.elementMap;
ClassDefinition definition = elementMap.getClassDefinition(cls);
@@ -141,7 +141,7 @@
String getMemberValue(MemberEntity member, Set<String> constants) {
StringBuffer sb = new StringBuffer();
- sb.write(outputUnitString(_data.outputUnitForMember(member)));
+ sb.write(outputUnitString(_data.outputUnitForMemberForTesting(member)));
if (constants.isNotEmpty) {
List<String> text = constants.toList()..sort();
sb.write(',constants=[${text.join(',')}]');
@@ -166,7 +166,7 @@
}
_registerValue(
new NodeId(span.begin, IdKind.node),
- outputUnitString(_data.outputUnitForConstant(constant)),
+ outputUnitString(_data.outputUnitForConstantForTesting(constant)),
node,
span,
actualMap,
diff --git a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
index 545c685..a207e12 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/dont_inline_deferred_constants_lib1.dart
@@ -17,7 +17,7 @@
/*strong.element: C2b:OutputUnit(1, {lib1})*/
const C2b = /*strong.OutputUnit(1, {lib1})*/ const C(1010);
-/*class: D:OutputUnit(main, {})*/
+/*class: D:null*/
class D {
/*strong.element: D.C3:OutputUnit(1, {lib1})*/
static const C3 = "string2";
diff --git a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
index 18f9ec3..4707d65 100644
--- a/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
+++ b/tests/compiler/dart2js/deferred_loading/libs/static_separate_lib1.dart
@@ -38,7 +38,7 @@
}
}
-/*class: C1:OutputUnit(main, {})*/
+/*class: C1:null*/
class C1 {
/*strong.element: C1.foo:OutputUnit(3, {lib2})*/
/*strongConst.element: C1.foo:
diff --git a/tests/compiler/dart2js/end_to_end/command_line_test.dart b/tests/compiler/dart2js/end_to_end/command_line_test.dart
index 88fb3e8..076b918 100644
--- a/tests/compiler/dart2js/end_to_end/command_line_test.dart
+++ b/tests/compiler/dart2js/end_to_end/command_line_test.dart
@@ -10,6 +10,7 @@
import 'package:expect/expect.dart';
import 'package:compiler/compiler_new.dart' as api;
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/dart2js.dart' as entry;
import 'package:compiler/src/options.dart' show CompilerOptions;
@@ -17,11 +18,191 @@
entry.enableWriteString = false;
asyncTest(() async {
await test([], exitCode: 1);
- await test(['foo.dart']);
+ await test(['foo.dart'], out: 'out.js');
+ await test(['foo.dart', '-ofoo.js'], out: 'foo.js');
+ await test(['foo.dart', '--out=foo.js'], out: 'foo.js');
+
+ await test([Flags.cfeOnly], exitCode: 1);
+ await test([Flags.cfeOnly, 'foo.dart'], out: 'out.dill');
+ await test([Flags.cfeOnly, 'foo.dart', '--out=out.dill'], out: 'out.dill');
+ await test([Flags.cfeOnly, 'foo.dart', Flags.readData], exitCode: 1);
+ await test(['foo.dart', Flags.readData, Flags.cfeOnly], exitCode: 1);
+ await test([Flags.cfeOnly, 'foo.dart', Flags.readCodegen], exitCode: 1);
+ await test(['foo.dart', Flags.readCodegen, Flags.cfeOnly], exitCode: 1);
+ await test([Flags.cfeOnly, 'foo.dart', Flags.writeData], exitCode: 1);
+ await test(['foo.dart', Flags.writeData, Flags.cfeOnly], exitCode: 1);
+ await test([Flags.cfeOnly, 'foo.dart', Flags.writeCodegen], exitCode: 1);
+ await test(['foo.dart', Flags.writeCodegen, Flags.cfeOnly], exitCode: 1);
+
+ await test([Flags.writeData, 'foo.dart'],
+ out: 'out.dill', writeData: 'out.dill.data');
+ await test(['${Flags.writeData}=foo.data', 'foo.dart', '--out=foo.dill'],
+ out: 'foo.dill', writeData: 'foo.data');
+ await test([Flags.readData, Flags.writeData, 'foo.dart'], exitCode: 1);
+ await test([Flags.writeData, Flags.readData, 'foo.dart'], exitCode: 1);
+ await test([Flags.readCodegen, Flags.writeData, 'foo.dart'], exitCode: 1);
+ await test([Flags.writeData, Flags.readCodegen, 'foo.dart'], exitCode: 1);
+
+ await test([Flags.readData, 'foo.dill'],
+ out: 'out.js', readData: 'foo.dill.data');
+ await test([Flags.readData, 'foo.dill', '--out=foo.js'],
+ out: 'foo.js', readData: 'foo.dill.data');
+ await test(['${Flags.readData}=out.data', 'foo.dill'],
+ out: 'out.js', readData: 'out.data');
+ await test(['${Flags.readData}=out.data', 'foo.dill', '--out=foo.js'],
+ out: 'foo.js', readData: 'out.data');
+
+ await test([
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShard}=0',
+ '${Flags.codegenShards}=2'
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShard}=0',
+ '${Flags.codegenShards}=2'
+ ],
+ out: 'out',
+ readData: 'foo.dill.data',
+ writeCodegen: 'out.code',
+ codegenShard: 0,
+ codegenShards: 2);
+ await test([
+ Flags.writeCodegen,
+ Flags.readData,
+ 'foo.dill',
+ '${Flags.codegenShard}=1',
+ '${Flags.codegenShards}=2'
+ ],
+ out: 'out',
+ readData: 'foo.dill.data',
+ writeCodegen: 'out.code',
+ codegenShard: 1,
+ codegenShards: 2);
+ await test([
+ '${Flags.readData}=foo.data',
+ '${Flags.writeCodegen}=foo.code',
+ 'foo.dill',
+ '${Flags.codegenShard}=0',
+ '${Flags.codegenShards}=3'
+ ],
+ out: 'out',
+ readData: 'foo.data',
+ writeCodegen: 'foo.code',
+ codegenShard: 0,
+ codegenShards: 3);
+ await test([
+ '${Flags.readData}=foo.data',
+ '${Flags.writeCodegen}',
+ 'foo.dill',
+ '--out=foo.js',
+ '${Flags.codegenShard}=0',
+ '${Flags.codegenShards}=2'
+ ],
+ out: 'foo.js',
+ readData: 'foo.data',
+ writeCodegen: 'foo.js.code',
+ codegenShard: 0,
+ codegenShards: 2);
+ await test([Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+ exitCode: 1);
+ await test([Flags.readCodegen, Flags.writeCodegen, 'foo.dill'],
+ exitCode: 1);
+ await test(
+ [Flags.readData, Flags.writeCodegen, 'foo.dill', Flags.readCodegen],
+ exitCode: 1);
+ await test(
+ [Flags.readCodegen, Flags.readData, Flags.writeCodegen, 'foo.dill'],
+ exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShard}=0'
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShards}=2'
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShards}=0'
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShard}=-1',
+ '${Flags.codegenShards}=2'
+ ], exitCode: 1);
+ await test([
+ Flags.readData,
+ Flags.writeCodegen,
+ 'foo.dill',
+ '${Flags.codegenShard}=2',
+ '${Flags.codegenShards}=2'
+ ], exitCode: 1);
+
+ await test([Flags.readCodegen, 'foo.dill', '${Flags.codegenShards}=2'],
+ out: 'out.js',
+ readData: 'foo.dill.data',
+ readCodegen: 'foo.dill.code',
+ codegenShards: 2);
+ await test([
+ '${Flags.readCodegen}=foo.code',
+ 'foo.dill',
+ '${Flags.codegenShards}=3'
+ ],
+ out: 'out.js',
+ readData: 'foo.dill.data',
+ readCodegen: 'foo.code',
+ codegenShards: 3);
+
+ await test([
+ Flags.readData,
+ Flags.readCodegen,
+ 'foo.dill',
+ '${Flags.codegenShards}=2'
+ ],
+ out: 'out.js',
+ readData: 'foo.dill.data',
+ readCodegen: 'foo.dill.code',
+ codegenShards: 2);
+ await test([
+ '${Flags.readData}=foo.data',
+ '${Flags.readCodegen}=foo.code',
+ 'foo.dill',
+ '${Flags.codegenShards}=3',
+ '-v'
+ ],
+ out: 'out.js',
+ readData: 'foo.data',
+ readCodegen: 'foo.code',
+ codegenShards: 3);
});
}
-Future test(List<String> arguments, {int exitCode}) async {
+Future test(List<String> arguments,
+ {int exitCode,
+ String out,
+ String readData,
+ String writeData,
+ String readCodegen,
+ String writeCodegen,
+ int codegenShard,
+ int codegenShards}) async {
print('--------------------------------------------------------------------');
print('dart2js ${arguments.join(' ')}');
print('--------------------------------------------------------------------');
@@ -47,8 +228,23 @@
Expect.equals(exitCode, actualExitCode, "Unexpected exit code");
if (actualExitCode == null) {
Expect.isNotNull(options, "Missing options object");
+ Expect.equals(toUri(out), options.outputUri, "Unexpected output uri.");
+ Expect.equals(
+ toUri(readData), options.readDataUri, "Unexpected readData uri");
+ Expect.equals(
+ toUri(writeData), options.writeDataUri, "Unexpected writeData uri");
+ Expect.equals(toUri(readCodegen), options.readCodegenUri,
+ "Unexpected readCodegen uri");
+ Expect.equals(toUri(writeCodegen), options.writeCodegenUri,
+ "Unexpected writeCodegen uri");
+ Expect.equals(
+ codegenShard, options.codegenShard, "Unexpected codegenShard uri");
+ Expect.equals(
+ codegenShards, options.codegenShards, "Unexpected codegenShards uri");
}
entry.compileFunc = oldCompileFunc;
entry.exitFunc = oldExitFunc;
}
+
+Uri toUri(String path) => path != null ? Uri.base.resolve(path) : null;
diff --git a/tests/compiler/dart2js/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index e424fad..3397753 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -11,6 +11,7 @@
import 'package:compiler/compiler_new.dart' as api;
import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/common/codegen.dart';
import 'package:compiler/src/common/work.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/dart2js.dart' as entry;
@@ -110,10 +111,15 @@
useNewSourceInfo: compiler.options.useNewSourceInfo);
@override
- WorldImpact generateCode(WorkItem work, JClosedWorld closedWorld,
- EntityLookup entityLookup, ComponentLookup componentLookup) {
+ WorldImpact generateCode(
+ WorkItem work,
+ JClosedWorld closedWorld,
+ CodegenResults codegenResults,
+ EntityLookup entityLookup,
+ ComponentLookup componentLookup) {
compiler.test('Compiler.codegen');
- return super.generateCode(work, closedWorld, entityLookup, componentLookup);
+ return super.generateCode(
+ work, closedWorld, codegenResults, entityLookup, componentLookup);
}
}
diff --git a/tests/compiler/dart2js/inlining/inlining_test.dart b/tests/compiler/dart2js/inlining/inlining_test.dart
index c6a8b92..8e73762 100644
--- a/tests/compiler/dart2js/inlining/inlining_test.dart
+++ b/tests/compiler/dart2js/inlining/inlining_test.dart
@@ -12,7 +12,7 @@
import 'package:compiler/src/js_backend/backend.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_world.dart';
-import 'package:compiler/src/ssa/builder_kernel.dart' as kernel;
+import 'package:compiler/src/ssa/builder_kernel.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'package:compiler/src/universe/use.dart';
import 'package:kernel/ast.dart' as ir;
@@ -53,6 +53,7 @@
final JavaScriptBackend backend;
final JsToElementMap _elementMap;
final ClosureData _closureDataLookup;
+ final InlineDataCache _inlineDataCache;
InliningIrComputer(
DiagnosticReporter reporter,
@@ -61,7 +62,8 @@
MemberEntity member,
this.backend,
this._closureDataLookup)
- : super(reporter, actualMap);
+ : this._inlineDataCache = new InlineDataCache(enableUserAssertions: true),
+ super(reporter, actualMap);
String getMemberValue(MemberEntity member) {
if (member is FunctionEntity) {
@@ -125,14 +127,16 @@
String getTooDifficultReasonForbidLoops(MemberEntity member) {
if (member is! FunctionEntity) return null;
- return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
- enableUserAssertions: true);
+ return _inlineDataCache
+ .getInlineData(_elementMap, member)
+ .cannotBeInlinedReason();
}
String getTooDifficultReasonAllowLoops(MemberEntity member) {
if (member is! FunctionEntity) return null;
- return kernel.InlineWeeder.cannotBeInlinedReason(_elementMap, member, null,
- allowLoops: true, enableUserAssertions: true);
+ return _inlineDataCache
+ .getInlineData(_elementMap, member)
+ .cannotBeInlinedReason(allowLoops: true);
}
@override
diff --git a/tests/compiler/dart2js/model/class_set_test.dart b/tests/compiler/dart2js/model/class_set_test.dart
index 5ceb1e8..ea78222 100644
--- a/tests/compiler/dart2js/model/class_set_test.dart
+++ b/tests/compiler/dart2js/model/class_set_test.dart
@@ -344,6 +344,7 @@
List<ClassEntity> visited = <ClassEntity>[];
classSet.forEachSubclass((cls) {
visited.add(cls);
+ return IterationStep.CONTINUE;
}, ClassHierarchyNode.ALL);
Expect.listEquals(
@@ -381,6 +382,7 @@
List<ClassEntity> visited = <ClassEntity>[];
classSet.forEachSubtype((cls) {
visited.add(cls);
+ return IterationStep.CONTINUE;
}, ClassHierarchyNode.ALL);
Expect.listEquals(
diff --git a/tests/compiler/dart2js/model/receiver_type_test.dart b/tests/compiler/dart2js/model/receiver_type_test.dart
index 663c6e3..3ad5042 100644
--- a/tests/compiler/dart2js/model/receiver_type_test.dart
+++ b/tests/compiler/dart2js/model/receiver_type_test.dart
@@ -6,6 +6,7 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/inferrer/typemasks/masks.dart';
+import 'package:compiler/src/universe/class_set.dart';
import 'package:compiler/src/universe/selector.dart';
import 'package:compiler/src/world.dart';
import 'package:expect/expect.dart';
@@ -49,7 +50,8 @@
Selector callSelector = new Selector.callClosure(0);
closedWorld.classHierarchy.forEachStrictSubclassOf(
closedWorld.commonElements.objectClass, (ClassEntity cls) {
- if (cls.library.canonicalUri.scheme != 'memory') return;
+ if (cls.library.canonicalUri.scheme != 'memory')
+ return IterationStep.CONTINUE;
TypeMask mask = new TypeMask.nonNullSubclass(cls, closedWorld);
TypeMask receiverType = closedWorld.computeReceiverType(callSelector, mask);
@@ -65,6 +67,7 @@
Expect.equals(expected, '$receiverType',
"Unexpected receiver type for $callSelector on $mask");
}
+ return IterationStep.CONTINUE;
});
Expect.equals(2, closureCount);
diff --git a/tests/compiler/dart2js/model/world_test.dart b/tests/compiler/dart2js/model/world_test.dart
index c49ff3d..b2106a8 100644
--- a/tests/compiler/dart2js/model/world_test.dart
+++ b/tests/compiler/dart2js/model/world_test.dart
@@ -99,6 +99,7 @@
List<ClassEntity> visited = <ClassEntity>[];
forEach(cls, (ClassEntity c) {
visited.add(c);
+ return IterationStep.CONTINUE;
});
checkClasses('forEach($property)', cls, visited, expectedClasses,
exact: exact);
@@ -424,6 +425,7 @@
if (allClasses.contains(other)) {
strictSubclasses.add(other);
}
+ return IterationStep.CONTINUE;
});
Expect.setEquals(subclasses, strictSubclasses,
"Unexpected strict subclasses of $cls: ${strictSubclasses}.");
@@ -433,6 +435,7 @@
if (allClasses.contains(other)) {
strictSubtypes.add(other);
}
+ return IterationStep.CONTINUE;
});
Expect.setEquals(subtypes, strictSubtypes,
"Unexpected strict subtypes of $cls: $strictSubtypes.");
diff --git a/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml b/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
index a02b69a..e8cdeea 100644
--- a/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
+++ b/tests/compiler/dart2js/modular/data/int_js_number/modules.yaml
@@ -6,3 +6,5 @@
# after serialization across modules.
dependencies:
main: def
+flags:
+ - constant-update-2018
diff --git a/tests/compiler/dart2js/modular/modular_test.dart b/tests/compiler/dart2js/modular/modular_test.dart
index 80aa857..fd60292 100644
--- a/tests/compiler/dart2js/modular/modular_test.dart
+++ b/tests/compiler/dart2js/modular/modular_test.dart
@@ -7,53 +7,40 @@
/// This is a shell that runs multiple tests, one per folder under `data/`.
import 'dart:io';
-import 'package:args/args.dart';
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
import 'package:modular_test/src/io_pipeline.dart';
-import 'package:modular_test/src/loader.dart';
import 'package:modular_test/src/pipeline.dart';
import 'package:modular_test/src/suite.dart';
+import 'package:modular_test/src/runner.dart';
-_Options _options;
-main(List<String> args) {
- _options = _Options.parse(args);
- asyncTest(() async {
- var baseUri = Platform.script.resolve('data/');
- var baseDir = Directory.fromUri(baseUri);
- await for (var entry in baseDir.list(recursive: false)) {
- if (entry is Directory) {
- await _runTest(entry.uri, baseUri);
- }
- }
- });
-}
-
-Future<void> _runTest(Uri uri, Uri baseDir) async {
- var dirName = uri.path.substring(baseDir.path.length);
- if (_options.filter != null && !dirName.contains(_options.filter)) {
- if (_options.showSkipped) print("skipped: $dirName");
- return;
- }
-
- print("testing: $dirName");
- ModularTest test = await loadTest(uri);
- if (_options.verbose) print(test.debugString());
- var pipeline = new IOPipeline([
- SourceToDillStep(),
- GlobalAnalysisStep(),
- Dart2jsBackendStep(),
- RunD8(),
- ]);
-
- await pipeline.run(test);
+Uri sdkRoot = Platform.script.resolve("../../../../");
+Options _options;
+main(List<String> args) async {
+ _options = Options.parse(args);
+ var suiteFolder = Platform.script.resolve('data/');
+ var suiteName = relativize(suiteFolder, sdkRoot).path;
+ await runSuite(
+ suiteFolder,
+ suiteName.substring(0, suiteName.length - 1), // remove trailing /
+ _options,
+ new IOPipeline([
+ SourceToDillStep(),
+ GlobalAnalysisStep(),
+ Dart2jsCodegenStep(codeId0),
+ Dart2jsCodegenStep(codeId1),
+ Dart2jsEmissionStep(),
+ RunD8(),
+ ], cacheSharedModules: true));
}
const dillId = const DataId("dill");
const updatedDillId = const DataId("udill");
const globalDataId = const DataId("gdata");
+const codeId = const ShardsDataId("code", 2);
+const codeId0 = const ShardDataId(codeId, 0);
+const codeId1 = const ShardDataId(codeId, 1);
const jsId = const DataId("js");
const txtId = const DataId("txt");
@@ -75,9 +62,10 @@
bool get onlyOnMain => false;
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
- if (_options.verbose) print("step: source-to-dill on $module");
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: source-to-dill on $module");
+
// We use non file-URI schemes for representeing source locations in a
// root-agnostic way. This allows us to refer to file across modules and
// across steps without exposing the underlying temporary folders that are
@@ -86,7 +74,7 @@
//
// Files in packages are defined in terms of `package:` URIs, while
// non-package URIs are defined using the `dart-dev-app` scheme.
- String rootScheme = 'dev-dart-app';
+ String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
String sourceToImportUri(Uri relativeUri) {
if (module.isPackage) {
var basePath = module.packageBase.path;
@@ -126,10 +114,30 @@
.writeAsString('$packagesContents');
var sdkRoot = Platform.script.resolve("../../../../");
- var platform =
- computePlatformBinariesLocation().resolve("dart2js_platform.dill");
+ List<String> sources;
+ List<String> extraArgs;
+ if (module.isSdk) {
+ // When no flags are passed, we can skip compilation and reuse the
+ // platform.dill created by build.py.
+ if (flags.isEmpty) {
+ var platform =
+ computePlatformBinariesLocation().resolve("dart2js_platform.dill");
+ var destination = root.resolveUri(toUri(module, dillId));
+ if (_options.verbose) {
+ print('command:\ncp $platform $destination');
+ }
+ await File.fromUri(platform).copy(destination.toFilePath());
+ return;
+ }
+ sources = ['dart:core'];
+ extraArgs = ['--libraries-file', '$rootScheme:///sdk/lib/libraries.json'];
+ assert(transitiveDependencies.isEmpty);
+ } else {
+ sources = module.sources.map(sourceToImportUri).toList();
+ extraArgs = ['--packages-file', '$rootScheme:/.packages'];
+ }
- List<String> workerArgs = [
+ List<String> args = [
sdkRoot.resolve("utils/bazel/kernel_worker.dart").toFilePath(),
'--no-summary-only',
'--target',
@@ -138,21 +146,24 @@
'$root',
'--multi-root-scheme',
rootScheme,
- '--dart-sdk-summary',
- '${platform}',
+ ...extraArgs,
'--output',
'${toUri(module, dillId)}',
- '--packages-file',
- '$rootScheme:/.packages',
...(transitiveDependencies
.expand((m) => ['--input-linked', '${toUri(m, dillId)}'])),
- ...(module.sources.expand((uri) => ['--source', sourceToImportUri(uri)])),
+ ...(sources.expand((String uri) => ['--source', uri])),
+ ...(flags.expand((String flag) => ['--enable-experiment', flag])),
];
- var result = await _runProcess(
- Platform.resolvedExecutable, workerArgs, root.toFilePath());
+ var result =
+ await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
_checkExitCode(result, this, module);
}
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: source-to-dill on $module");
+ }
}
// Step that invokes the dart2js global analysis on the main module by providing
@@ -174,9 +185,9 @@
bool get onlyOnMain => true;
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
- if (_options.verbose) print("step: dart2js global analysis on $module");
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: dart2js global analysis on $module");
Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
Iterable<String> dillDependencies =
transitiveDependencies.map((m) => '${toUri(m, dillId)}');
@@ -185,8 +196,9 @@
'--packages=${sdkRoot.toFilePath()}/.packages',
'package:compiler/src/dart2js.dart',
'${toUri(module, dillId)}',
- '--dill-dependencies=${dillDependencies.join(',')}',
- '--write-data=${toUri(module, globalDataId)}',
+ for (String flag in flags) '--enable-experiment=$flag',
+ '${Flags.dillDependencies}=${dillDependencies.join(',')}',
+ '${Flags.writeData}=${toUri(module, globalDataId)}',
'--out=${toUri(module, updatedDillId)}',
];
var result =
@@ -194,13 +206,24 @@
_checkExitCode(result, this, module);
}
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose)
+ print("\ncached step: dart2js global analysis on $module");
+ }
}
-// Step that invokes the dart2js backend on the main module given the results of
-// the global analysis step.
-class Dart2jsBackendStep implements IOModularStep {
+// Step that invokes the dart2js code generation on the main module given the
+// results of the global analysis step and produces one shard of the codegen
+// output.
+class Dart2jsCodegenStep implements IOModularStep {
+ final ShardDataId codeId;
+
+ Dart2jsCodegenStep(this.codeId);
+
@override
- List<DataId> get resultData => const [jsId];
+ List<DataId> get resultData => [codeId];
@override
bool get needsSources => false;
@@ -215,15 +238,64 @@
bool get onlyOnMain => true;
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: dart2js backend on $module");
+ var sdkRoot = Platform.script.resolve("../../../../");
+ List<String> args = [
+ '--packages=${sdkRoot.toFilePath()}/.packages',
+ 'package:compiler/src/dart2js.dart',
+ '${toUri(module, updatedDillId)}',
+ for (String flag in flags) '--enable-experiment=$flag',
+ '${Flags.readData}=${toUri(module, globalDataId)}',
+ '${Flags.writeCodegen}=${toUri(module, codeId.dataId)}',
+ '${Flags.codegenShard}=${codeId.shard}',
+ '${Flags.codegenShards}=${codeId.dataId.shards}',
+ ];
+ var result =
+ await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+
+ _checkExitCode(result, this, module);
+ }
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("cached step: dart2js backend on $module");
+ }
+}
+
+// Step that invokes the dart2js codegen enqueuer and emitter on the main module
+// given the results of the global analysis step and codegen shards.
+class Dart2jsEmissionStep implements IOModularStep {
+ @override
+ List<DataId> get resultData => const [jsId];
+
+ @override
+ bool get needsSources => false;
+
+ @override
+ List<DataId> get dependencyDataNeeded => const [];
+
+ @override
+ List<DataId> get moduleDataNeeded =>
+ const [updatedDillId, globalDataId, codeId0, codeId1];
+
+ @override
+ bool get onlyOnMain => true;
+
+ @override
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
if (_options.verbose) print("step: dart2js backend on $module");
var sdkRoot = Platform.script.resolve("../../../../");
List<String> args = [
'--packages=${sdkRoot.toFilePath()}/.packages',
'package:compiler/src/dart2js.dart',
'${toUri(module, updatedDillId)}',
- '--read-data=${toUri(module, globalDataId)}',
+ for (String flag in flags) '${Flags.enableLanguageExperiments}=$flag',
+ '${Flags.readData}=${toUri(module, globalDataId)}',
+ '${Flags.readCodegen}=${toUri(module, codeId)}',
+ '${Flags.codegenShards}=${codeId.shards}',
'--out=${toUri(module, jsId)}',
];
var result =
@@ -231,6 +303,11 @@
_checkExitCode(result, this, module);
}
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: dart2js backend on $module");
+ }
}
/// Step that runs the output of dart2js in d8 and saves the output.
@@ -251,9 +328,9 @@
bool get onlyOnMain => true;
@override
- Future<void> execute(
- Module module, Uri root, ModuleDataToRelativeUri toUri) async {
- if (_options.verbose) print("step: d8 on $module");
+ Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri,
+ List<String> flags) async {
+ if (_options.verbose) print("\nstep: d8 on $module");
var sdkRoot = Platform.script.resolve("../../../../");
List<String> d8Args = [
sdkRoot
@@ -269,6 +346,11 @@
await File.fromUri(root.resolveUri(toUri(module, txtId)))
.writeAsString(result.stdout);
}
+
+ @override
+ void notifyCached(Module module) {
+ if (_options.verbose) print("\ncached step: d8 on $module");
+ }
}
void _checkExitCode(ProcessResult result, IOModularStep step, Module module) {
@@ -277,8 +359,9 @@
stderr.write(result.stderr);
}
if (result.exitCode != 0) {
- exitCode = result.exitCode;
- Expect.fail("${step.runtimeType} failed on $module");
+ throw "${step.runtimeType} failed on $module:\n\n"
+ "stdout:\n${result.stdout}\n\n"
+ "stderr:\n${result.stderr}";
}
}
@@ -301,26 +384,31 @@
throw new UnsupportedError('Unsupported platform.');
}
-class _Options {
- bool showSkipped = false;
- bool verbose = false;
- String filter = null;
+class ShardsDataId implements DataId {
+ @override
+ final String name;
+ final int shards;
- static _Options parse(List<String> args) {
- var parser = new ArgParser()
- ..addFlag('verbose',
- abbr: 'v',
- defaultsTo: false,
- help: "print detailed information about the test and modular steps")
- ..addFlag('show-skipped',
- defaultsTo: false,
- help: "print the name of the tests skipped by the filtering option")
- ..addOption('filter',
- help: "only run tests containing this filter as a substring");
- ArgResults argResults = parser.parse(args);
- return _Options()
- ..showSkipped = argResults['show-skipped']
- ..verbose = argResults['verbose']
- ..filter = argResults['filter'];
+ const ShardsDataId(this.name, this.shards);
+
+ @override
+ String toString() => name;
+}
+
+class ShardDataId implements DataId {
+ final ShardsDataId dataId;
+ final int _shard;
+
+ const ShardDataId(this.dataId, this._shard);
+
+ int get shard {
+ assert(0 <= _shard && _shard < dataId.shards);
+ return _shard;
}
+
+ @override
+ String get name => '${dataId.name}${shard}';
+
+ @override
+ String toString() => name;
}
diff --git a/tests/compiler/dart2js/optimization/data/arithmetic.dart b/tests/compiler/dart2js/optimization/data/arithmetic.dart
index f8aad1b..3ec5b39 100644
--- a/tests/compiler/dart2js/optimization/data/arithmetic.dart
+++ b/tests/compiler/dart2js/optimization/data/arithmetic.dart
@@ -118,19 +118,19 @@
// Negation
////////////////////////////////////////////////////////////////////////////////
-/*element: negate:Specializer=[Negate],TypeConversion=[]*/
+/*element: negate:Specializer=[Negate],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
negate(o) {
return -o;
}
-/*element: negateNum:Specializer=[Negate],TypeConversion=[]*/
+/*element: negateNum:Specializer=[Negate],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
negateNum(o) {
return -o;
}
-/*element: negateNull:Specializer=[Negate],TypeConversion=[kind=receiver&type=num]*/
+/*element: negateNull:Specializer=[Negate],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
negateNull(o) {
return -o;
@@ -146,37 +146,37 @@
// Addition
////////////////////////////////////////////////////////////////////////////////
-/*element: add:Specializer=[Add],TypeConversion=[]*/
+/*element: add:Specializer=[Add],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
add(a, b) {
return a + b;
}
-/*element: addNumInt:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumInt:Specializer=[Add],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
addNumInt(a, b) {
return a + b;
}
-/*element: addIntNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addIntNum:Specializer=[Add],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
addIntNum(a, b) {
return a + b;
}
-/*element: addNumNum:Specializer=[Add],TypeConversion=[]*/
+/*element: addNumNum:Specializer=[Add],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
addNumNum(a, b) {
return a + b;
}
-/*element: addNullInt:Specializer=[Add],TypeConversion=[kind=receiver&type=num]*/
+/*element: addNullInt:Specializer=[Add],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
addNullInt(a, b) {
return a + b;
}
-/*element: addIntNull:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntNull:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
addIntNull(a, b) {
return a + b;
@@ -188,7 +188,7 @@
return a + b;
}
-/*element: addIntString:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+/*element: addIntString:Specializer=[Add],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
addIntString(a, b) {
return a + b;
@@ -198,49 +198,49 @@
// Subtraction
////////////////////////////////////////////////////////////////////////////////
-/*element: subtract:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtract:Specializer=[Subtract],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
subtract(a, b) {
return a - b;
}
-/*element: subtractNumInt:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumInt:Specializer=[Subtract],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
subtractNumInt(a, b) {
return a - b;
}
-/*element: subtractIntNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractIntNum:Specializer=[Subtract],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
subtractIntNum(a, b) {
return a - b;
}
-/*element: subtractNumNum:Specializer=[Subtract],TypeConversion=[]*/
+/*element: subtractNumNum:Specializer=[Subtract],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
subtractNumNum(a, b) {
return a - b;
}
-/*element: subtractNullInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractNullInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
subtractNullInt(a, b) {
return a - b;
}
-/*element: subtractIntNull:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntNull:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
subtractIntNull(a, b) {
return a - b;
}
-/*element: subtractStringInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+/*element: subtractStringInt:Specializer=[Subtract],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
subtractStringInt(a, b) {
return a - b;
}
-/*element: subtractIntString:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+/*element: subtractIntString:Specializer=[Subtract],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
subtractIntString(a, b) {
return a - b;
@@ -250,37 +250,37 @@
// Multiplication
////////////////////////////////////////////////////////////////////////////////
-/*element: multiply:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiply:Specializer=[Multiply],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
multiply(a, b) {
return a * b;
}
-/*element: multiplyNumInt:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumInt:Specializer=[Multiply],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
multiplyNumInt(a, b) {
return a * b;
}
-/*element: multiplyIntNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyIntNum:Specializer=[Multiply],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
multiplyIntNum(a, b) {
return a * b;
}
-/*element: multiplyNumNum:Specializer=[Multiply],TypeConversion=[]*/
+/*element: multiplyNumNum:Specializer=[Multiply],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
multiplyNumNum(a, b) {
return a * b;
}
-/*element: multiplyNullInt:Specializer=[Multiply],TypeConversion=[kind=receiver&type=num]*/
+/*element: multiplyNullInt:Specializer=[Multiply],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
multiplyNullInt(a, b) {
return a * b;
}
-/*element: multiplyIntNull:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntNull:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
multiplyIntNull(a, b) {
return a * b;
@@ -292,7 +292,7 @@
return a * b;
}
-/*element: multiplyIntString:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+/*element: multiplyIntString:Specializer=[Multiply],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
multiplyIntString(a, b) {
return a * b;
@@ -302,55 +302,55 @@
// Division
////////////////////////////////////////////////////////////////////////////////
-/*element: divide:Specializer=[Divide],TypeConversion=[]*/
+/*element: divide:Specializer=[Divide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
divide(a, b) {
return a / b;
}
-/*element: divideZero:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideZero:Specializer=[Divide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
divideZero(a) {
return a / 0;
}
-/*element: divideNumInt:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumInt:Specializer=[Divide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
divideNumInt(a, b) {
return a / b;
}
-/*element: divideIntNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideIntNum:Specializer=[Divide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
divideIntNum(a, b) {
return a / b;
}
-/*element: divideNumNum:Specializer=[Divide],TypeConversion=[]*/
+/*element: divideNumNum:Specializer=[Divide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
divideNumNum(a, b) {
return a / b;
}
-/*element: divideNullInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideNullInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
divideNullInt(a, b) {
return a / b;
}
-/*element: divideIntNull:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntNull:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
divideIntNull(a, b) {
return a / b;
}
-/*element: divideStringInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+/*element: divideStringInt:Specializer=[Divide],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
divideStringInt(a, b) {
return a / b;
}
-/*element: divideIntString:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+/*element: divideIntString:Specializer=[Divide],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
divideIntString(a, b) {
return a / b;
@@ -360,7 +360,7 @@
// Truncating division
////////////////////////////////////////////////////////////////////////////////
-/*element: truncatingDivide:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivide:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
truncatingDivide(a, b) {
return a ~/ 2;
@@ -372,13 +372,13 @@
return a ~/ 0;
}
-/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
truncatingDivideIntNonZero1(a) {
return a ~/ 1;
}
-/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],TypeConversion=[]*/
+/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
truncatingDivideIntNonZero2(a) {
return a ~/ 2;
@@ -390,7 +390,7 @@
return a ~/ b;
}
-/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],TypeConversion=[]*/
+/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
truncatingDivideNumNonZero(a) {
return a ~/ 2;
@@ -408,25 +408,25 @@
return a ~/ b;
}
-/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
truncatingDivideNullInt(a, b) {
return a ~/ b;
}
-/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
truncatingDivideIntNull(a, b) {
return a ~/ b;
}
-/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
truncatingDivideStringInt(a, b) {
return a ~/ b;
}
-/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
truncatingDivideIntString(a, b) {
return a ~/ b;
diff --git a/tests/compiler/dart2js/optimization/data/bit.dart b/tests/compiler/dart2js/optimization/data/bit.dart
index 51e3741..543a87d 100644
--- a/tests/compiler/dart2js/optimization/data/bit.dart
+++ b/tests/compiler/dart2js/optimization/data/bit.dart
@@ -92,49 +92,49 @@
// Bitwise and
////////////////////////////////////////////////////////////////////////////////
-/*element: bitAnd:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAnd:Specializer=[BitAnd],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitAnd(a, b) {
return a & b;
}
-/*element: bitAndNumInt:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumInt:Specializer=[BitAnd],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitAndNumInt(a, b) {
return a & b;
}
-/*element: bitAndIntNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndIntNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitAndIntNum(a, b) {
return a & b;
}
-/*element: bitAndNumNum:Specializer=[BitAnd],TypeConversion=[]*/
+/*element: bitAndNumNum:Specializer=[BitAnd],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitAndNumNum(a, b) {
return a & b;
}
-/*element: bitAndNullInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndNullInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitAndNullInt(a, b) {
return a & b;
}
-/*element: bitAndIntNull:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntNull:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitAndIntNull(a, b) {
return a & b;
}
-/*element: bitAndStringInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitAndStringInt:Specializer=[BitAnd],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitAndStringInt(a, b) {
return a & b;
}
-/*element: bitAndIntString:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+/*element: bitAndIntString:Specializer=[BitAnd],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitAndIntString(a, b) {
return a & b;
@@ -144,49 +144,49 @@
// Bitwise or
////////////////////////////////////////////////////////////////////////////////
-/*element: bitOr:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOr:Specializer=[BitOr],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitOr(a, b) {
return a | b;
}
-/*element: bitOrNumInt:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumInt:Specializer=[BitOr],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitOrNumInt(a, b) {
return a | b;
}
-/*element: bitOrIntNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrIntNum:Specializer=[BitOr],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitOrIntNum(a, b) {
return a | b;
}
-/*element: bitOrNumNum:Specializer=[BitOr],TypeConversion=[]*/
+/*element: bitOrNumNum:Specializer=[BitOr],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitOrNumNum(a, b) {
return a | b;
}
-/*element: bitOrNullInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrNullInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitOrNullInt(a, b) {
return a | b;
}
-/*element: bitOrIntNull:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntNull:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitOrIntNull(a, b) {
return a | b;
}
-/*element: bitOrStringInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitOrStringInt:Specializer=[BitOr],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitOrStringInt(a, b) {
return a | b;
}
-/*element: bitOrIntString:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+/*element: bitOrIntString:Specializer=[BitOr],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitOrIntString(a, b) {
return a | b;
@@ -196,49 +196,49 @@
// Bitwise xor
////////////////////////////////////////////////////////////////////////////////
-/*element: bitXor:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXor:Specializer=[BitXor],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitXor(a, b) {
return a ^ b;
}
-/*element: bitXorNumInt:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumInt:Specializer=[BitXor],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitXorNumInt(a, b) {
return a ^ b;
}
-/*element: bitXorIntNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorIntNum:Specializer=[BitXor],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitXorIntNum(a, b) {
return a ^ b;
}
-/*element: bitXorNumNum:Specializer=[BitXor],TypeConversion=[]*/
+/*element: bitXorNumNum:Specializer=[BitXor],PrimitiveCheck=[]*/
@pragma('dart2js:noInline')
bitXorNumNum(a, b) {
return a ^ b;
}
-/*element: bitXorNullInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorNullInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitXorNullInt(a, b) {
return a ^ b;
}
-/*element: bitXorIntNull:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntNull:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitXorIntNull(a, b) {
return a ^ b;
}
-/*element: bitXorStringInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+/*element: bitXorStringInt:Specializer=[BitXor],PrimitiveCheck=[kind=receiver&type=num]*/
@pragma('dart2js:noInline')
bitXorStringInt(a, b) {
return a ^ b;
}
-/*element: bitXorIntString:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+/*element: bitXorIntString:Specializer=[BitXor],PrimitiveCheck=[kind=argument&type=num]*/
@pragma('dart2js:noInline')
bitXorIntString(a, b) {
return a ^ b;
diff --git a/tests/compiler/dart2js/serialization/serialization_test_helper.dart b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
index 43ee996..9f48d01 100644
--- a/tests/compiler/dart2js/serialization/serialization_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/serialization_test_helper.dart
@@ -60,7 +60,7 @@
Map<OutputType, Map<String, String>> output = collector1.clear();
- compiler.emitJavaScriptCode(newGlobalInferenceResults);
+ compiler.generateJavaScriptCode(newGlobalInferenceResults);
Map<OutputType, Map<String, String>> newOutput = collector2.clear();
Expect.setEquals(output.keys, newOutput.keys, "Output type mismatch.");
diff --git a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
index f38c7a6..9e4273d 100644
--- a/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/helpers/sourcemap_helper.dart
@@ -262,6 +262,7 @@
}
return null;
}
+ return null;
});
}
}
diff --git a/tests/compiler/dart2js_native/compute_this_script_test.dart b/tests/compiler/dart2js_native/compute_this_script_test.dart
index 8519bc4..ee5c855 100644
--- a/tests/compiler/dart2js_native/compute_this_script_test.dart
+++ b/tests/compiler/dart2js_native/compute_this_script_test.dart
@@ -10,7 +10,7 @@
// This is somewhat brittle and relies on an implementation detail
// of our test runner, but I can think of no other way to test this.
// -- ahe
- if (!thisScript.endsWith('/out.js')) {
+ if (!thisScript.endsWith('/compute_this_script_test.js')) {
throw 'Unexpected script: "$thisScript"';
}
}
diff --git a/tests/compiler/dartdevc_native/const_test.dart b/tests/compiler/dartdevc_native/const_test.dart
new file mode 100644
index 0000000..b2dbf27
--- /dev/null
+++ b/tests/compiler/dartdevc_native/const_test.dart
@@ -0,0 +1,30 @@
+// 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:expect/expect.dart";
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+void main() {
+ var data = JS('', '[1, 2, 3, 4]');
+ Expect.isFalse(data is List<int>);
+
+ var list = dart.constList(data, dart.unwrapType(int));
+ Expect.isTrue(list is List<int>);
+ Expect.throws(() {
+ list[0] = 0;
+ });
+
+ var set = dart.constSet<int>(data);
+ Expect.isTrue(set is Set<int>);
+ Expect.isTrue(set.contains(3));
+ Expect.throws(() => set.clear());
+
+ var map = dart.constMap<int, int>(data);
+ Expect.isTrue(map is Map<int, int>);
+ Expect.equals(map[1], 2);
+ Expect.throws(() {
+ map[1] = 42;
+ });
+}
diff --git a/tests/compiler/dartdevc_native/libraries_part.dart b/tests/compiler/dartdevc_native/libraries_part.dart
new file mode 100644
index 0000000..d5ac766
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_part.dart
@@ -0,0 +1,5 @@
+// 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.
+
+part of 'libraries_test.dart';
diff --git a/tests/compiler/dartdevc_native/libraries_test.dart b/tests/compiler/dartdevc_native/libraries_test.dart
new file mode 100644
index 0000000..533eb5d
--- /dev/null
+++ b/tests/compiler/dartdevc_native/libraries_test.dart
@@ -0,0 +1,32 @@
+// 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:expect/expect.dart';
+import 'dart:_foreign_helper' show JS;
+import 'dart:_runtime' as dart;
+
+part 'libraries_part.dart';
+
+void main() {
+ // Test getLibraries()
+ var libraries = dart.getLibraries();
+ Expect.isTrue(libraries.contains('dart:core'));
+ Expect.isTrue(libraries.contains('package:expect/expect.dart'));
+
+ // Test getParts(...)
+ var expectParts = dart.getParts('package:expect/expect.dart');
+ Expect.isTrue(expectParts.isEmpty);
+
+ var testLibraries =
+ libraries.where((l) => l.endsWith('libraries_test.dart')).toList();
+ Expect.isTrue(testLibraries.length == 1);
+ var testParts = dart.getParts(testLibraries.first);
+ Expect.isTrue(testParts.length == 1);
+ Expect.isTrue(testParts.first.endsWith('libraries_part.dart'));
+
+ // Test getLibrary(...)
+ var core = dart.getLibrary('dart:core');
+ var stackTraceType = dart.wrapType(JS('', '#.StackTrace', core));
+ Expect.equals(StackTrace, stackTraceType);
+}
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 01dea1f..0b5b8c5 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -222,6 +222,15 @@
test(mediumNumber, new BigInt.from(137), new BigInt.from(77));
test(new BigInt.from(137), mediumNumber, new BigInt.from(540686667207353));
test(bigNumber, new BigInt.from(137), new BigInt.from(128));
+ var x = BigInt.parse(
+ "28ea16430c1f1072754aa5ebbfda0d790605a507c6c9758e88697b0b5dd9e74c",
+ radix: 16);
+ var m = BigInt.parse(
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f",
+ radix: 16);
+ var r = BigInt.parse("95929095851002583825372225918533539673793386278"
+ "360575987103577151530201707061", radix: 10);
+ test(x, m, r);
}
testGcd() {
diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status
index 2b170cf..0e982e4 100644
--- a/tests/ffi/ffi.status
+++ b/tests/ffi/ffi.status
@@ -11,7 +11,6 @@
# dartbug.com/35768: Structs not supported on 32-bit.
[ $arch == ia32 || $arch == arm || $arch == simdbc ]
function_structs_test: Skip
-function_callbacks_test: Skip
structs_test: Skip
# dartbug.com/35934
@@ -42,3 +41,6 @@
[ $system != android && $arch == arm ]
*: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309
+
+[ $arch == simdbc64 ]
+function_callbacks_test: Skip # Issue 37140
diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart
index 0ad50a9..fc2e46c 100644
--- a/tests/ffi/function_callbacks_test.dart
+++ b/tests/ffi/function_callbacks_test.dart
@@ -8,71 +8,192 @@
library FfiTest;
-import 'dart:ffi' as ffi;
-
+import 'dart:io';
+import 'dart:ffi';
+import 'dart:isolate';
import 'dylib_utils.dart';
import "package:expect/expect.dart";
-import 'coordinate.dart';
+typedef NativeCallbackTest = Int32 Function(Pointer);
+typedef NativeCallbackTestFn = int Function(Pointer);
-typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+final DynamicLibrary testLibrary = dlopenPlatformSpecific("ffi_test_functions");
-typedef CoordinateTrice = Coordinate Function(
- ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+class Test {
+ final String name;
+ final Pointer callback;
+ final bool skip;
-void main() {
- testFunctionWithFunctionPointer();
- testNativeFunctionWithFunctionPointer();
+ Test(this.name, this.callback, {bool skipIf: false}) : skip = skipIf {}
+
+ void run() {
+ if (skip) return;
+
+ final NativeCallbackTestFn tester = testLibrary
+ .lookupFunction<NativeCallbackTest, NativeCallbackTestFn>("Test$name");
+ final int testCode = tester(callback);
+ if (testCode != 0) {
+ Expect.fail("Test $name failed.");
+ }
+ }
}
-ffi.DynamicLibrary ffiTestFunctions =
- dlopenPlatformSpecific("ffi_test_functions");
+typedef SimpleAdditionType = Int32 Function(Int32, Int32);
+int simpleAddition(int x, int y) => x + y;
-/// pass a pointer to a c function as an argument to a c function
-void testFunctionWithFunctionPointer() {
- ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
- transposeCoordinatePointer =
- ffiTestFunctions.lookup("TransposeCoordinate");
+typedef IntComputationType = Int64 Function(Int8, Int16, Int32, Int64);
+int intComputation(int a, int b, int c, int d) => d - c + b - a;
- ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
- ffiTestFunctions.lookup("CoordinateUnOpTrice");
- CoordinateTrice coordinateUnOpTrice = p2.asFunction();
+typedef UintComputationType = Uint64 Function(Uint8, Uint16, Uint32, Uint64);
+int uintComputation(int a, int b, int c, int d) => d - c + b - a;
- Coordinate c1 = Coordinate(10.0, 20.0, null);
- c1.next = c1;
+typedef SimpleMultiplyType = Double Function(Double);
+double simpleMultiply(double x) => x * 1.337;
- Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+typedef SimpleMultiplyFloatType = Float Function(Float);
+double simpleMultiplyFloat(double x) => x * 1.337;
- print(result.runtimeType);
- print(result.x);
- print(result.y);
-
- c1.free();
+typedef ManyIntsType = IntPtr Function(IntPtr, IntPtr, IntPtr, IntPtr, IntPtr,
+ IntPtr, IntPtr, IntPtr, IntPtr, IntPtr);
+int manyInts(
+ int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
+ return a + b + c + d + e + f + g + h + i + j;
}
-typedef BinaryOp = int Function(int, int);
-
-typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
-
-typedef NativeIntptrBinOpLookup
- = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
-
-void testNativeFunctionWithFunctionPointer() {
- ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p1 =
- ffiTestFunctions.lookup("IntptrAdditionClosure");
- NativeIntptrBinOpLookup intptrAdditionClosure = p1.asFunction();
-
- ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
- intptrAdditionClosure();
- BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
- Expect.equals(37, intptrAddition(10, 27));
+typedef ManyDoublesType = Double Function(Double, Double, Double, Double,
+ Double, Double, Double, Double, Double, Double);
+double manyDoubles(double a, double b, double c, double d, double e, double f,
+ double g, double h, double i, double j) {
+ return a + b + c + d + e + f + g + h + i + j;
}
-int myPlus(int a, int b) => a + b;
+typedef ManyArgsType = Double Function(
+ IntPtr,
+ Float,
+ IntPtr,
+ Double,
+ IntPtr,
+ Float,
+ IntPtr,
+ Double,
+ IntPtr,
+ Float,
+ IntPtr,
+ Double,
+ IntPtr,
+ Float,
+ IntPtr,
+ Double,
+ IntPtr,
+ Float,
+ IntPtr,
+ Double);
+double manyArgs(
+ int _1,
+ double _2,
+ int _3,
+ double _4,
+ int _5,
+ double _6,
+ int _7,
+ double _8,
+ int _9,
+ double _10,
+ int _11,
+ double _12,
+ int _13,
+ double _14,
+ int _15,
+ double _16,
+ int _17,
+ double _18,
+ int _19,
+ double _20) {
+ return _1 +
+ _2 +
+ _3 +
+ _4 +
+ _5 +
+ _6 +
+ _7 +
+ _8 +
+ _9 +
+ _10 +
+ _11 +
+ _12 +
+ _13 +
+ _14 +
+ _15 +
+ _16 +
+ _17 +
+ _18 +
+ _19 +
+ _20;
+}
-typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
- ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef StoreType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> store(Pointer<Int64> ptr) => ptr.elementAt(1)..store(1337);
-typedef ApplyTo42And74Type = int Function(
- ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+typedef NullPointersType = Pointer<Int64> Function(Pointer<Int64>);
+Pointer<Int64> nullPointers(Pointer<Int64> ptr) => ptr?.elementAt(1);
+
+typedef ReturnNullType = Int32 Function();
+int returnNull() {
+ print('Expect "unhandled exception" error message to follow.');
+ return null;
+}
+
+typedef ReturnVoid = Void Function();
+void returnVoid() {}
+
+final List<Test> testcases = [
+ Test("SimpleAddition", fromFunction<SimpleAdditionType>(simpleAddition)),
+ Test("IntComputation", fromFunction<IntComputationType>(intComputation)),
+ Test("UintComputation", fromFunction<UintComputationType>(uintComputation)),
+ Test("SimpleMultiply", fromFunction<SimpleMultiplyType>(simpleMultiply)),
+ Test("SimpleMultiplyFloat",
+ fromFunction<SimpleMultiplyFloatType>(simpleMultiplyFloat)),
+ Test("ManyInts", fromFunction<ManyIntsType>(manyInts)),
+ Test("ManyDoubles", fromFunction<ManyDoublesType>(manyDoubles)),
+ Test("ManyArgs", fromFunction<ManyArgsType>(manyArgs)),
+ Test("Store", fromFunction<StoreType>(store)),
+ Test("NullPointers", fromFunction<NullPointersType>(nullPointers)),
+ Test("ReturnNull", fromFunction<ReturnNullType>(returnNull)),
+];
+
+testCallbackWrongThread() =>
+ Test("CallbackWrongThread", fromFunction<ReturnVoid>(returnVoid)).run();
+
+testCallbackOutsideIsolate() =>
+ Test("CallbackOutsideIsolate", fromFunction<ReturnVoid>(returnVoid)).run();
+
+isolateHelper(int callbackPointer) {
+ final Pointer<Void> ptr = fromAddress(callbackPointer);
+ final NativeCallbackTestFn tester =
+ testLibrary.lookupFunction<NativeCallbackTest, NativeCallbackTestFn>(
+ "TestCallbackWrongIsolate");
+ Expect.equals(0, tester(ptr));
+}
+
+testCallbackWrongIsolate() async {
+ final int callbackPointer = fromFunction<ReturnVoid>(returnVoid).address;
+ final ReceivePort exitPort = ReceivePort();
+ await Isolate.spawn(isolateHelper, callbackPointer,
+ errorsAreFatal: true, onExit: exitPort.sendPort);
+ await exitPort.first;
+}
+
+void main() async {
+ testcases.forEach((t) => t.run()); //# 00: ok
+
+ // These tests terminate the process after successful completion, so we have
+ // to run them separately.
+ //
+ // Since they use signal handlers they only run on Linux.
+ if (Platform.isLinux && !const bool.fromEnvironment("dart.vm.product")) {
+ testCallbackWrongThread(); //# 01: ok
+ testCallbackOutsideIsolate(); //# 02: ok
+ await testCallbackWrongIsolate(); //# 03: ok
+ }
+}
diff --git a/tests/ffi/regress_37100_test.dart b/tests/ffi/regress_37100_test.dart
new file mode 100644
index 0000000..7281042
--- /dev/null
+++ b/tests/ffi/regress_37100_test.dart
@@ -0,0 +1,25 @@
+// 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.
+//
+// SharedObjects=ffi_test_functions
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+
+import 'dylib_utils.dart';
+
+class EVP_MD extends Pointer<Void> {}
+
+DynamicLibrary ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");
+
+final EVP_sha1 = ffiTestFunctions
+ .lookupFunction<EVP_MD Function(), EVP_MD Function()>('LargePointer');
+
+main() {
+ int result = EVP_sha1().address;
+ // On 32 bit only the lowest 32 bits are returned, so only test those.
+ result &= 0x00000000FFFFFFFF;
+ Expect.equals(0x0000000082000000, result);
+}
diff --git a/tests/language_2/async_identifier_test.dart b/tests/language_2/async_identifier_test.dart
new file mode 100644
index 0000000..5af2722
--- /dev/null
+++ b/tests/language_2/async_identifier_test.dart
@@ -0,0 +1,209 @@
+// 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 'dart:async' as async;
+import 'async_lib.dart' as l; // Minimal library containing "int async;".
+
+// Adapted from Analyzer test testing where `async` was not previously allowed.
+
+// Helpers
+void ignore(argument) {}
+
+class GNamed {
+ void g({Object async = null}) {}
+}
+
+class AGet {
+ int get async => 1;
+ set async(int i) {}
+}
+
+class ACall {
+ int async() => 1;
+}
+
+main() {
+ // Each test declares a spearate async function, tests that `async`
+ // can occur in it, and makes sure the function is run.
+ {
+ const int async = 0;
+ f() async {
+ g(@async x) {}
+ g(0);
+ }
+
+ f();
+ }
+ {
+ f(c) async {
+ c.g(async: 0);
+ }
+
+ f(GNamed());
+ }
+ {
+ f() async {
+ var async = 1;
+ ignore(async);
+ }
+
+ f();
+ }
+ {
+ f() async* {
+ var async = 1;
+ ignore(async);
+ }
+
+ f().forEach(ignore);
+ }
+ {
+ f() async {
+ async:
+ while (true) {
+ break async;
+ }
+ }
+
+ f();
+ }
+ {
+ g() {}
+ f() async {
+ try {
+ g();
+ } catch (async) {}
+ }
+
+ f();
+ }
+ {
+ g() {}
+ f() async {
+ try {
+ g();
+ } catch (e, async) {}
+ }
+
+ f();
+ }
+ {
+ f() async {
+ async:
+ while (true) {
+ if (false) continue async;
+ break;
+ }
+ }
+
+ f();
+ }
+ {
+ var async;
+ f() async {
+ for (async in []) {}
+ }
+
+ f();
+ }
+ {
+ f() async {
+ g(int async) {}
+ g(0);
+ }
+
+ f();
+ }
+ {
+ f() async {
+ return new AGet().async;
+ }
+
+ f();
+ }
+ {
+ f() async {
+ return new ACall().async();
+ }
+
+ f();
+ }
+ {
+ f() async {
+ return new ACall()..async();
+ }
+
+ f();
+ }
+ {
+ g() {}
+ f() async {
+ async:
+ g();
+ }
+
+ f();
+ }
+ {
+ f() async {
+ int async() => null;
+ async();
+ }
+ }
+ {
+ f() async {
+ return async.Future.value(0);
+ }
+
+ f();
+ }
+ {
+ f() async {
+ new AGet().async = 1;
+ }
+
+ f();
+ }
+ {
+ f() async {
+ return new AGet()..async = 1;
+ }
+
+ f();
+ }
+ {
+ int async = 1;
+ f() async {
+ return "$async";
+ }
+
+ f();
+ }
+ {
+ f() async {
+ return l.async;
+ }
+
+ f();
+ }
+ {
+ f() async {
+ switch (0) {
+ async:
+ case 0:
+ break;
+ }
+ }
+
+ f();
+ }
+ {
+ f() sync* {
+ var async = 1;
+ ignore(async);
+ }
+
+ f();
+ }
+}
diff --git a/tests/language_2/async_lib.dart b/tests/language_2/async_lib.dart
new file mode 100644
index 0000000..a6be037
--- /dev/null
+++ b/tests/language_2/async_lib.dart
@@ -0,0 +1,7 @@
+// 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.
+
+// Helper library for async_identifier_test.dart
+
+int async;
diff --git a/tests/language_2/covariant_subtyping_with_substitution_test.dart b/tests/language_2/covariant_subtyping_with_substitution_test.dart
deleted file mode 100644
index 7cf2b52..0000000
--- a/tests/language_2/covariant_subtyping_with_substitution_test.dart
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2017, 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:expect/expect.dart';
-
-typedef F<T>(T x);
-
-class B<T> {
- void f(F<T> x) {}
-}
-
-abstract class I<U> {
- void f(U x);
-}
-
-class C<V> extends B<V> implements I<F<V>> {}
-
-void acceptsObject(Object o) {}
-
-void acceptsNum(num n) {}
-
-void g(I<F<num>> i) {
- i.f(acceptsObject);
- // i.f has static type (F<num>)->void, or ((num)->void)->void. Which means we
- // are statically allowed to pass acceptsNum to it. However, if i's runtime
- // type is C<Object>, then it extends B<Object>, so its f function requires
- // its argument to be F<Object>. This means that passing acceptsNum to f
- // would violate soundness (since acceptsNum has type F<num>, and F<num> is a
- // supertype of F<Object>). So we expect a type error here.
- Expect.throwsTypeError(() => i.f(acceptsNum));
-}
-
-void main() {
- g(new C<Object>());
-}
diff --git a/tests/language_2/extension_methods/syntax/extension_methods.dart b/tests/language_2/extension_methods/syntax/extension_methods.dart
new file mode 100644
index 0000000..51013db
--- /dev/null
+++ b/tests/language_2/extension_methods/syntax/extension_methods.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// SharedOptions=--enable-experiment=extension-methods
+
+import 'package:expect/expect.dart';
+
+class C {
+ int get one => 1;
+}
+
+extension E on C {
+ int get two => 2;
+}
+
+main() {
+ C c = C();
+ var result = c.one + c.two;
+ Expect.equals(result, 3);
+}
diff --git a/tests/language_2/known_identifier_usage_error_test.dart b/tests/language_2/known_identifier_usage_error_test.dart
index 9c96dc1..0d56f26 100644
--- a/tests/language_2/known_identifier_usage_error_test.dart
+++ b/tests/language_2/known_identifier_usage_error_test.dart
@@ -21,7 +21,7 @@
import 'dart:async';
Future<int> f1() async {
- int async = 1; //# 01: syntax error
+ int async = 1;
int await = 1; //# 02: syntax error
int yield = 1; //# 03: syntax error
@@ -32,7 +32,7 @@
}
Stream<int> f2() async* {
- int async = 1; //# 04: syntax error
+ int async = 1;
int await = 1; //# 05: syntax error
int yield = 1; //# 06: syntax error
@@ -43,7 +43,7 @@
}
Iterable<int> f3() sync* {
- int async = 1; //# 07: syntax error
+ int async = 1;
int await = 1; //# 08: syntax error
int yield = 1; //# 09: syntax error
diff --git a/tests/language_2/local_var_in_annotation_test.dart b/tests/language_2/local_var_in_annotation_test.dart
new file mode 100644
index 0000000..f6474f8
--- /dev/null
+++ b/tests/language_2/local_var_in_annotation_test.dart
@@ -0,0 +1,12 @@
+// 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.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/37065
+
+const x = 0;
+main(@x args) {
+ const z = 0;
+ foo(@z args) {}
+ bar(@x args) {}
+}
diff --git a/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
new file mode 100644
index 0000000..159731d
--- /dev/null
+++ b/tests/language_2/nnbd/resolution/null_assertion_null_type_test.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that the trailing "!" properly promotes the type `Null` to `Never`, by
+// verifying that it's statically ok to pass it to a function expecting a
+// non-null parameter.
+import 'package:expect/expect.dart';
+
+void f(int i) {}
+
+void g(Null n) {
+ // Statically ok because `Never <: int`. Throws at runtime.
+ f(n!);
+}
+
+main() {
+ Expect.throws(() => g(null));
+}
diff --git a/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
new file mode 100644
index 0000000..35e756e
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/equals_parameter_made_nullable_at_invoke_test.dart
@@ -0,0 +1,40 @@
+// 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 'dart:async';
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that Object.operator==(Object o) is the signature of ==, but that we can
+// still compare nullable values to Object.
+//
+// This is because a == b is essentially sugar for
+//
+// ```
+// identical(a, null) || identical (b, null)
+// ? identical(a, b)
+// : a.operator==(b);
+// ```
+//
+// It should not be required to handle `null` inside the implementation of
+// operator==, but it should not be an error to "assign null" to the parameter
+// of the comparison operator.
+main() {
+ Object o;
+ // Valid comparison.
+ o == null;
+
+ // Caveat: it is NOT that the argument is promoted to non-null. Otherwise,
+ // types which we can't cleanly promote, such as FutureOr<int?>, would not be
+ // assignable in comparisons.
+ FutureOr<int?> foInt;
+
+ // Valid comparison.
+ o == foInt;
+}
+
+class C {
+ // Valid override
+ @override
+ bool operator==(Object other) => identical(other, this);
+}
diff --git a/tests/language_2/nnbd/static_errors/implicit_downcasts.dart b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
new file mode 100644
index 0000000..6d8b7b4
--- /dev/null
+++ b/tests/language_2/nnbd/static_errors/implicit_downcasts.dart
@@ -0,0 +1,19 @@
+// 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.
+
+// SharedOptions=--enable-experiment=non-nullable
+
+// Test that it is an error to do what was once allowed as an "implicit
+// downcast."
+main() {
+ num asNum = 1;
+ Object asObject = 1;
+ dynamic asDynamic = 1;
+ int asInt1 = asNum; //# 01: compile-time error
+ double asDouble1 = asNum; //# 02: compile-time error
+ int asInt2 = asObject; //# 03: compile-time error
+ double asDouble2 = asObject; //# 04: compile-time error
+ String asString1 = asObject; //# 05: compile-time error
+ int asInt3 = asDynamic; //# 06: ok
+}
diff --git a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
index a991f55..ce24941 100644
--- a/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
+++ b/tests/language_2/nnbd/static_errors/unchecked_use_of_nullable_test.dart
@@ -9,7 +9,6 @@
int? x;
bool? cond;
List? list;
- dynamic dyn;
Function? func;
List<Function?> funcList;
Stream? stream;
@@ -51,8 +50,8 @@
cond != null; //# 33: ok
x?.isEven; //# 34: ok
x?.round(); //# 35: ok
- for(i in list) {}; //# 36: compile-time error
- await for(i in stream) {}; //# 37: compile-time error
+ for(var i in list) {}; //# 36: compile-time error
+ await for(var i in stream) {}; //# 37: compile-time error
assert(cond); //# 38: compile-time error
}
@@ -60,3 +59,148 @@
Iterable? iter;
yield* iter; //# 39: compile-time error
}
+
+void typeParametersNullableBounds<IQ extends int?, BQ extends bool?, LQ extends List?, FQ extends Function?, SQ extends Stream?>(
+ IQ x,
+ BQ cond,
+ LQ list,
+ FQ func,
+ List<FQ> funcList,
+ SQ stream,
+ ) async {
+ x.isEven; //# 40: compile-time error
+ x.round(); //# 41: compile-time error
+ x.toString(); //# 42: ok
+ x.hashCode; //# 43: ok
+ x.runtimeType; //# 44: ok
+ x.noSuchMethod(null); //# 45: ok
+ x + 1; //# 46: compile-time error
+ -x; //# 47: compile-time error
+ x++; //# 48: compile-time error
+ ++x; //# 49: compile-time error
+ x..isEven; //# 50: compile-time error
+ list[0]; //# 51: compile-time error
+ list[0] = 0; //# 52: compile-time error
+ x += 1; //# 53: compile-time error
+ x ??= null; //# 54: ok
+ x.round; //# 55: compile-time error
+ x.toString; //# 56: ok
+ x.noSuchMethod; //# 57: ok
+ func(); //# 58: compile-time error
+ funcList[0](); //# 59: compile-time error
+ funcList.single(); //# 60: compile-time error
+ throw x; //# 61: compile-time error
+ cond || true; //# 62: compile-time error
+ true || cond; //# 63: compile-time error
+ cond && true; //# 64: compile-time error
+ true && cond; //# 65: compile-time error
+ !cond; //# 66: compile-time error
+ cond ? null : null; //# 67: compile-time error
+ if (cond) {} //# 68: compile-time error
+ while (cond) {} //# 69: compile-time error
+ for (;cond;){} //# 70: compile-time error
+ do {} while (cond); //# 71: compile-time error
+ cond!; //# 72: ok
+ cond ?? null; //# 73: ok
+ cond == null; //# 74: ok
+ cond != null; //# 75: ok
+ x?.isEven; //# 76: ok
+ x?.round(); //# 77: ok
+ for(var i in list) {}; //# 78: compile-time error
+ await for(var i in stream) {}; //# 79: compile-time error
+ assert(cond); //# 39: compile-time error
+}
+
+void typeParametersNullableUses<I extends int, B extends bool, L extends List, F extends Function, S extends Stream>(
+ I? x,
+ B? cond,
+ L? list,
+ F? func,
+ List<F?> funcList,
+ S? stream,
+ ) async {
+ x.isEven; //# 80: compile-time error
+ x.round(); //# 81: compile-time error
+ x.toString(); //# 82: ok
+ x.hashCode; //# 83: ok
+ x.runtimeType; //# 84: ok
+ x.noSuchMethod(null); //# 85: ok
+ x + 1; //# 86: compile-time error
+ -x; //# 87: compile-time error
+ x++; //# 88: compile-time error
+ ++x; //# 89: compile-time error
+ x..isEven; //# 90: compile-time error
+ list[0]; //# 91: compile-time error
+ list[0] = 0; //# 92: compile-time error
+ x += 1; //# 93: compile-time error
+ x ??= null; //# 94: ok
+ x.round; //# 95: compile-time error
+ x.toString; //# 96: ok
+ x.noSuchMethod; //# 97: ok
+ func(); //# 98: compile-time error
+ funcList[0](); //# 99: compile-time error
+ funcList.single(); //# 100: compile-time error
+ throw x; //# 101: compile-time error
+ cond || true; //# 102: compile-time error
+ true || cond; //# 103: compile-time error
+ cond && true; //# 104: compile-time error
+ true && cond; //# 105: compile-time error
+ !cond; //# 106: compile-time error
+ cond ? null : null; //# 107: compile-time error
+ if (cond) {} //# 108: compile-time error
+ while (cond) {} //# 109: compile-time error
+ for (;cond;) {} //# 110: compile-time error
+ do {} while (cond); //# 111: compile-time error
+ cond!; //# 112: ok
+ cond ?? null; //# 113: ok
+ cond == null; //# 114: ok
+ cond != null; //# 115: ok
+ x?.isEven; //# 116: ok
+ x?.round(); //# 117: ok
+ for(var i in list) {}; //# 118: compile-time error
+ await for(var i in stream) {}; //# 119: compile-time error
+}
+
+void dynamicUses() async {
+ dynamic dyn;
+ dyn.isEven; //# 120: ok
+ dyn.round(); //# 121: ok
+ dyn.toString(); //# 122: ok
+ dyn.hashCode; //# 123: ok
+ dyn.runtimeType; //# 124: ok
+ dyn.noSuchMethod(null); //# 125: ok
+ dyn + 1; //# 126: ok
+ -dyn; //# 127: ok
+ dyn++; //# 128: ok
+ ++dyn; //# 129: ok
+ dyn..isEven; //# 130: ok
+ dyn[0]; //# 131: ok
+ dyn[0] = 0; //# 132: ok
+ dyn += 1; //# 133: ok
+ dyn ??= null; //# 134: ok
+ dyn.round; //# 135: ok
+ dyn.toString; //# 136: ok
+ dyn.noSuchMethod; //# 137: ok
+ dyn(); //# 138: ok
+ dyn[0](); //# 139: ok
+ dyn.single(); //# 140: ok
+ throw dyn; //# 141: ok
+ dyn || true; //# 142: ok
+ true || dyn; //# 143: ok
+ dyn && true; //# 144: ok
+ true && dyn; //# 145: ok
+ !dyn; //# 146: ok
+ dyn ? null : null; //# 147: ok
+ if (dyn) {} //# 148: ok
+ while (dyn) {} //# 149: ok
+ for (;dyn;) {} //# 150: ok
+ do {} while (dyn); //# 151: ok
+ dyn!; //# 152: ok
+ dyn ?? null; //# 153: ok
+ dyn == null; //# 154: ok
+ dyn != null; //# 155: ok
+ dyn?.isEven; //# 156: ok
+ dyn?.round(); //# 157: ok
+ for(var i in dyn) {}; //# 158: ok
+ await for(var i in dyn) {}; //# 159: ok
+}
diff --git a/tests/language_2/sync_generator2_test.dart b/tests/language_2/sync_generator2_test.dart
index 9e33f0c..feaee63 100644
--- a/tests/language_2/sync_generator2_test.dart
+++ b/tests/language_2/sync_generator2_test.dart
@@ -15,13 +15,10 @@
test01() sync* {
var yield = 0; // //# 01: syntax error
var await = 0; // //# 02: syntax error
- var async = 0; // //# 03: syntax error
bool yield() => false; //# 04: syntax error
bool await() => false; //# 05: syntax error
- bool async() => false; //# 06: syntax error
var x1 = sync;
- var x2 = async; // //# 07: syntax error
var x3 = await; // //# 08: syntax error
var x4 = await 55; // //# 09: compile-time error
var x4 = yield; // //# 10: syntax error
diff --git a/tests/lib_2/html/async_spawnuri_test.dart b/tests/lib_2/html/async_spawnuri_test.dart
deleted file mode 100644
index 1175a3e..0000000
--- a/tests/lib_2/html/async_spawnuri_test.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-library async_spawnuri_test;
-
-import 'package:unittest/unittest.dart';
-import 'package:unittest/html_config.dart';
-
-import 'dart:async';
-import 'dart:isolate';
-import 'dart:html';
-
-// OtherScripts=async_oneshot.dart async_periodictimer.dart async_cancellingisolate.dart
-main() {
- useHtmlConfiguration();
-
- test('one shot timer in pure isolate', () {
- var response = new ReceivePort();
- var remote = Isolate.spawnUri(
- Uri.parse('async_oneshot.dart'), ['START'], response.sendPort);
- remote.catchError((x) => expect("Error in oneshot isolate", x));
- expect(remote.then((_) => response.first), completion('DONE'));
- });
-
- test('periodic timer in pure isolate', () {
- var response = new ReceivePort();
- var remote = Isolate.spawnUri(
- Uri.parse('async_periodictimer.dart'), ['START'], response.sendPort);
- remote.catchError((x) => expect("Error in periodic timer isolate", x));
- expect(remote.then((_) => response.first), completion('DONE'));
- });
-
- test('cancellation in pure isolate', () {
- var response = new ReceivePort();
- var remote = Isolate.spawnUri(Uri.parse('async_cancellingisolate.dart'),
- ['START'], response.sendPort);
- remote.catchError((x) => expect("Error in cancelling isolate", x));
- expect(remote.then((_) => response.first), completion('DONE'));
- });
-}
diff --git a/tests/lib_2/isolate/browser/issue_12474_test.dart b/tests/lib_2/isolate/browser/issue_12474_test.dart
index aca9741..b1cfe70 100644
--- a/tests/lib_2/isolate/browser/issue_12474_test.dart
+++ b/tests/lib_2/isolate/browser/issue_12474_test.dart
@@ -2,11 +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.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_12474_child.dart
-// OtherScripts=package/issue_12474_lib.dart
-
import 'dart:isolate';
final SPAWN_PACKAGE_ROOT = Uri.parse(".");
diff --git a/tests/lib_2/isolate/error_at_spawnuri_test.dart b/tests/lib_2/isolate/error_at_spawnuri_test.dart
index d33ac09..5c428b9 100644
--- a/tests/lib_2/isolate/error_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
// 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.
-//
-// OtherScripts=error_at_spawnuri_iso.dart
library error_at_spawnuri;
diff --git a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
index 9643770..6e9a5a8 100644
--- a/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/error_exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
// 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.
-//
-// OtherScripts=error_exit_at_spawning_shared.dart
library error_exit_at_spawnuri;
diff --git a/tests/lib_2/isolate/exit_at_spawnuri_test.dart b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
index fd2287b..f415c66 100644
--- a/tests/lib_2/isolate/exit_at_spawnuri_test.dart
+++ b/tests/lib_2/isolate/exit_at_spawnuri_test.dart
@@ -1,8 +1,6 @@
// 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.
-//
-// OtherScripts=exit_at_spawnuri_iso.dart
library exit_at_spawn;
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
index 9da9678..74b6cc6 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate1_test.dart
@@ -2,13 +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.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate1.dart
-// OtherScripts=issue_21398_child_isolate11.dart
-
import 'dart:isolate';
-import 'dart:async';
import "package:expect/expect.dart";
import 'package:async_helper/async_helper.dart';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
index 27d49b9..0fe1043 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate2_test.dart
@@ -2,12 +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.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=deferred_loaded_lib.dart
-
import 'dart:isolate';
-import 'dart:async';
import "package:expect/expect.dart";
import 'package:async_helper/async_helper.dart';
diff --git a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
index 967d25f..ab413e9 100644
--- a/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_21398_parent_isolate_test.dart
@@ -2,12 +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.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_21398_child_isolate.dart
-
import 'dart:isolate';
-import 'dart:async';
import "package:expect/expect.dart";
import 'package:async_helper/async_helper.dart';
diff --git a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
index 6294767..2c1dc54 100644
--- a/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
+++ b/tests/lib_2/isolate/issue_24243_parent_isolate_test.dart
@@ -2,12 +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.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=issue_24243_child1_isolate.dart
-// OtherScripts=issue_24243_child2_isolate.dart
-// OtherScripts=issue_24243_child3_isolate.dart
-
import 'dart:collection';
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_multi_test.dart b/tests/lib_2/isolate/spawn_uri_multi_test.dart
index 6076617..2984fca 100644
--- a/tests/lib_2/isolate/spawn_uri_multi_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_multi_test.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Negative test to make sure that we are reaching all assertions.
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
library spawn_tests;
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
index 6d37e26..f558df5 100644
--- a/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_nested_vm_test.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Example of nested spawning of isolates from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_nested_child1_vm_isolate.dart spawn_uri_nested_child2_vm_isolate.dart
library NestedSpawnUriLibrary;
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_test.dart b/tests/lib_2/isolate/spawn_uri_test.dart
index 3f52215..e71fed7 100644
--- a/tests/lib_2/isolate/spawn_uri_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_test.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
library spawn_tests;
import 'dart:isolate';
diff --git a/tests/lib_2/isolate/spawn_uri_vm_test.dart b/tests/lib_2/isolate/spawn_uri_vm_test.dart
index 6bc2e6e..a3b8f61 100644
--- a/tests/lib_2/isolate/spawn_uri_vm_test.dart
+++ b/tests/lib_2/isolate/spawn_uri_vm_test.dart
@@ -3,9 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
// Example of spawning an isolate from a URI
-// Note: the following comment is used by test.dart to additionally compile the
-// other isolate's code.
-// OtherScripts=spawn_uri_child_isolate.dart
library spawn_tests;
import 'dart:isolate';
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 6cd2ce3..b96429f 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -10,7 +10,6 @@
convert/chunked_conversion_utf88_test: Slow
convert/utf85_test: Slow
developer/timeline_test: Skip # Not supported
-html/async_spawnuri_test: SkipByDesign
html/async_test: SkipByDesign
html/custom/document_register_basic_test: Slow
html/custom/document_register_type_extensions_test/construction: Slow
@@ -82,7 +81,6 @@
[ $compiler == dart2js && $runtime == d8 ]
async/dart2js_uncaught_error_test: RuntimeError
-html/async_spawnuri_test: RuntimeError
html/async_test: RuntimeError
html/audiobuffersourcenode_test: RuntimeError
html/audiocontext_test: RuntimeError
@@ -494,7 +492,6 @@
html/postmessage_structured_test: SkipByDesign
[ $compiler == dart2js && !$csp && $minified ]
-html/async_spawnuri_test: RuntimeError
html/async_test: RuntimeError
html/audiobuffersourcenode_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
html/audiocontext_test: Crash # NoSuchMethodError: Class 'JMethod' has no instance getter 'implementation'.
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 0532e64..4b47ff6 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -41,7 +41,6 @@
convert/streamed_conversion_json_utf8_encode_test: Pass, Timeout # Issue 29922
convert/streamed_conversion_utf8_decode_test: Slow, Pass, Timeout # Issue 29922
convert/utf85_test: Slow, Pass
-html/async_spawnuri_test: RuntimeError # Issue 29922
html/async_test: RuntimeError # Issue 29922
html/callback_list_test: Skip # Test requires user interaction to accept permissions.
html/custom/attribute_changed_callback_test: Skip # Issue 31577
diff --git a/tests/standalone_2/io/http_cookie_date_test.dart b/tests/standalone_2/io/http_cookie_date_test.dart
index 112d700..621d9e5 100644
--- a/tests/standalone_2/io/http_cookie_date_test.dart
+++ b/tests/standalone_2/io/http_cookie_date_test.dart
@@ -2,14 +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.
-library dart.http;
+library dart._http;
import "dart:async";
import "dart:collection";
import "dart:convert";
-import "dart:developer";
import "dart:io";
-import "dart:isolate";
import "dart:math";
import "dart:typed_data";
import "package:expect/expect.dart";
diff --git a/tests/standalone_2/io/http_cookie_test.dart b/tests/standalone_2/io/http_cookie_test.dart
index 50cad66..bfe9302 100644
--- a/tests/standalone_2/io/http_cookie_test.dart
+++ b/tests/standalone_2/io/http_cookie_test.dart
@@ -2,8 +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:async";
import "dart:io";
+
import "package:expect/expect.dart";
void testCookies() {
@@ -59,12 +59,28 @@
}
void testValidateCookieWithDoubleQuotes() {
- try {
- Cookie cookie = Cookie('key', '"double-quoted-value"');
- } catch (e) {
- Expect.fail("Unexpected error $e.\n"
- "Unable to parse cookie with value in double-quote characters.");
- }
+ Expect.equals(Cookie('key', 'value').toString(), 'key=value; HttpOnly');
+ Expect.equals(Cookie('key', '').toString(), 'key=; HttpOnly');
+ Expect.equals(Cookie('key', '""').toString(), 'key=""; HttpOnly');
+ Expect.equals(Cookie('key', '"value"').toString(), 'key="value"; HttpOnly');
+ Expect.equals(Cookie.fromSetCookieValue('key=value; HttpOnly').toString(),
+ 'key=value; HttpOnly');
+ Expect.equals(
+ Cookie.fromSetCookieValue('key=; HttpOnly').toString(), 'key=; HttpOnly');
+ Expect.equals(Cookie.fromSetCookieValue('key=""; HttpOnly').toString(),
+ 'key=""; HttpOnly');
+ Expect.equals(Cookie.fromSetCookieValue('key="value"; HttpOnly').toString(),
+ 'key="value"; HttpOnly');
+ Expect.throwsFormatException(() => Cookie('key', '"'));
+ Expect.throwsFormatException(() => Cookie('key', '"""'));
+ Expect.throwsFormatException(() => Cookie('key', '"x""'));
+ Expect.throwsFormatException(() => Cookie('key', '"x"y"'));
+ Expect.throwsFormatException(
+ () => Cookie.fromSetCookieValue('key="; HttpOnly'));
+ Expect.throwsFormatException(
+ () => Cookie.fromSetCookieValue('key="""; HttpOnly'));
+ Expect.throwsFormatException(
+ () => Cookie.fromSetCookieValue('key="x""; HttpOnly'));
}
void main() {
diff --git a/tests/standalone_2/io/raw_socket_test.dart b/tests/standalone_2/io/raw_socket_test.dart
index d46d1d6..cf8087d 100644
--- a/tests/standalone_2/io/raw_socket_test.dart
+++ b/tests/standalone_2/io/raw_socket_test.dart
@@ -79,13 +79,14 @@
RawSocket.startConnect(InternetAddress.loopbackIPv4, 0)
.then((ConnectionTask<RawSocket> task) {
task.cancel();
- task.socket.catchError((error) {
- Expect.isTrue(error is SocketException);
- asyncEnd();
- });
task.socket.then((s) {
Expect.fail("Unreachable");
+ }, onError: (e) {
+ Expect.isTrue(e is SocketException);
+ asyncEnd();
});
+ }, onError: (e) {
+ Expect.fail("Unreachable");
});
}
@@ -474,6 +475,21 @@
});
}
+void testClosedServer() {
+ asyncStart();
+ RawServerSocket.bind(InternetAddress.loopbackIPv4, 0).then((server) {
+ int port = server.port;
+ server.close().then((_) {
+ RawSocket.connect(InternetAddress.loopbackIPv4, server.port).then((_) {
+ Expect.fail('Connecting to the closed server socket should fail');
+ }, onError: (e) {
+ Expect.isTrue(e is SocketException);
+ asyncEnd();
+ });
+ });
+ });
+}
+
main() {
asyncStart();
testArguments();
@@ -491,5 +507,6 @@
testSocketZone();
testSocketZoneError();
testClosedError();
+ testClosedServer();
asyncEnd();
}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 69cdf98..1441048 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -106,7 +106,6 @@
io/http_client_connect_test: Skip # Flaky.
io/http_close_test: Crash
io/http_content_length_test: Skip # Flaky.
-io/http_cookie_test: Skip # Flaky
io/http_proxy_advanced_test: Skip # Flaky
io/http_proxy_test: Skip # Flaky.
io/http_response_deadline_test: Skip # Flaky.
diff --git a/third_party/babel/update.sh b/third_party/babel/update.sh
new file mode 100755
index 0000000..6b9ca5a
--- /dev/null
+++ b/third_party/babel/update.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+# Uploads a new version of d8 CIPD package
+set -e
+set -x
+
+if [ -z "$1" ]; then
+ echo "Usage: update.sh version"
+ exit 1
+fi
+
+version=$1
+
+tmpdir=$(mktemp -d)
+cleanup() {
+ rm -rf "$tmpdir"
+}
+trap cleanup EXIT HUP INT QUIT TERM PIPE
+cd "$tmpdir"
+
+for file in "babel.js" "babel.min.js" "LICENSE"
+do
+ curl -o $file "https://unpkg.com/@babel/standalone@$version/$file"
+done
+
+cipd create \
+ -name dart/third_party/babel \
+ -in . \
+ -install-mode copy \
+ -tag version:$version
diff --git a/tools/VERSION b/tools/VERSION
index fb1b7d6..c0e5702 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -34,6 +34,6 @@
MINOR 3
PATCH 2
PRERELEASE 0
-PRERELEASE_PATCH 0
+PRERELEASE_PATCH 1
ABI_VERSION 5
OLDEST_SUPPORTED_ABI_VERSION 3
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index b9af47b..0f6de4e 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -43,6 +43,7 @@
"tests/standalone/",
"tests/standalone_2/",
"tests/ffi/",
+ "third_party/babel/babel.min.js",
"third_party/d8/",
"third_party/observatory_pub_packages/packages/web_components/",
"third_party/pkg/",
@@ -245,7 +246,12 @@
"options": {
"use-sdk": true
}},
- "dart2js-win-(ie11|edge)": {
+ "dart2js-win-ie11": {
+ "options": {
+ "use-sdk": true,
+ "babel": "{\"presets\":[\"es2015\"]}"
+ }},
+ "dart2js-win-edge": {
"options": {
"use-sdk": true
}},
@@ -274,9 +280,9 @@
"options": {
"host-checked": true
}},
- "dartkp-android-(debug|product|release)-arm": {
+ "dartkp-android-(debug|product|release)-(arm|arm64)": {
"options": {
- "use-blobs": true
+ "use-elf": true
}},
"dartk-android-(debug|product|release)-(arm|arm64)": {},
"dartkp-linux-(debug|product|release)-(simarm|simarm64)": {
@@ -868,7 +874,8 @@
"-ndartdevc-checked-${system}-release-chrome",
"language_2",
"corelib_2",
- "lib_2"
+ "lib_2",
+ "dartdevc_native"
]
},
{
@@ -877,7 +884,8 @@
"-ndartdevk-checked-${system}-release-chrome",
"language_2",
"corelib_2",
- "lib_2"
+ "lib_2",
+ "dartdevc_native"
]
},
{
@@ -919,6 +927,27 @@
"pkg/dev_compiler/test/worker/worker_test.dart",
"-rnone"
]
+ },
+ {
+ "name": "ddc self host test",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
+ "arguments": [
+ "--enable-asserts",
+ "pkg/dev_compiler/bin/dartdevc.dart",
+ "-o=out/ReleaseX64/dartdevc.js",
+ "pkg/dev_compiler/bin/dartdevc.dart"
+ ]
+ },
+ {
+ "name": "ddk self host test",
+ "script": "out/ReleaseX64/dart-sdk/bin/dart",
+ "arguments": [
+ "--enable-asserts",
+ "pkg/dev_compiler/bin/dartdevc.dart",
+ "-k",
+ "-o=out/ReleaseX64/dartdevk.js",
+ "pkg/dev_compiler/bin/dartdevc.dart"
+ ]
}
]
},
@@ -941,7 +970,8 @@
"-ndartdevc-checked-mac-release-chrome",
"language_2",
"corelib_2",
- "lib_2"
+ "lib_2",
+ "dartdevc_native"
]
},
{
@@ -950,7 +980,8 @@
"-ndartdevk-checked-mac-release-chrome",
"language_2",
"corelib_2",
- "lib_2"
+ "lib_2",
+ "dartdevc_native"
]
},
{
@@ -992,6 +1023,27 @@
"pkg/dev_compiler/test/worker/worker_test.dart",
"-rnone"
]
+ },
+ {
+ "name": "ddc self host test",
+ "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+ "arguments": [
+ "--enable-asserts",
+ "pkg/dev_compiler/bin/dartdevc.dart",
+ "-o=xcodebuild/ReleaseX64/dartdevc.js",
+ "pkg/dev_compiler/bin/dartdevc.dart"
+ ]
+ },
+ {
+ "name": "ddk self host test",
+ "script": "xcodebuild/ReleaseX64/dart-sdk/bin/dart",
+ "arguments": [
+ "--enable-asserts",
+ "pkg/dev_compiler/bin/dartdevc.dart",
+ "-k",
+ "-o=xcodebuild/ReleaseX64/dartdevk.js",
+ "pkg/dev_compiler/bin/dartdevc.dart"
+ ]
}
]
},
diff --git a/tools/linux_dist_support/debian/rules b/tools/linux_dist_support/debian/rules
index 8c0665b..2ec324f 100755
--- a/tools/linux_dist_support/debian/rules
+++ b/tools/linux_dist_support/debian/rules
@@ -1,6 +1,8 @@
#!/usr/bin/make -f
export DH_VERBOSE = 1
+AOT_SUPPORTED_ARCHS := amd64 arm
+
# Use DEB_BUILD_OPTIONS's parallel=n option (see Policy 4.9.1)
ifneq (,$(findstring parallel,$(DEB_BUILD_OPTIONS)))
PARALLEL_JOBS := $(shell echo $(DEB_BUILD_OPTIONS) | \
@@ -11,17 +13,21 @@
ifeq (amd64,$(DEB_HOST_ARCH_CPU))
BUILD_TYPE += ReleaseX64
+BUILD_TYPE_PRODUCT += ProductX64
ARCH += x64
else
ifeq (i386,$(DEB_HOST_ARCH_CPU))
BUILD_TYPE += ReleaseIA32
+BUILD_TYPE_PRODUCT += ProductIA32
ARCH += ia32
else
ifeq (arm,$(DEB_HOST_ARCH_CPU))
ifeq ($(DEB_BUILD_ARCH_CPU),$(DEB_HOST_ARCH_CPU))
BUILD_TYPE += ReleaseARM
+BUILD_TYPE_PRODUCT += ProductARM
else
BUILD_TYPE += ReleaseXARM
+BUILD_TYPE_PRODUCT += ProductXARM
endif
ARCH += arm
else
@@ -30,6 +36,22 @@
endif
endif
+# Only run AOT builds for supported archs.
+ifneq (,$(findstring $(DEB_HOST_ARCH_CPU),$(AOT_SUPPORTED_ARCHS)))
+AOT_BUILD_CMD := \
+python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) \
+ copy_gen_kernel_snapshot copy_dart2aot; \
+python tools/build.py -v -m product -a $(ARCH) $(TOOLCHAIN) \
+ copy_gen_snapshot copy_dartaotruntime; \
+mkdir -p out/$(BUILD_TYPE)/dart-sdk/bin/utils; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/utils/gen_snapshot \
+ out/$(BUILD_TYPE)/dart-sdk/bin/utils/gen_snapshot; \
+cp out/$(BUILD_TYPE_PRODUCT)/dart-sdk/bin/dartaotruntime \
+ out/$(BUILD_TYPE)/dart-sdk/bin/dartaotruntime
+else
+AOT_BUILD_CMD := # empty
+endif
+
# Verbose?
ifeq (1,$(DH_VERBOSE))
BUILD_ARGS += V=1
@@ -52,6 +74,7 @@
override_dh_auto_build:
cd dart; \
python tools/build.py -v -m release -a $(ARCH) $(TOOLCHAIN) create_sdk; \
+ $(AOT_BUILD_CMD); \
cd ..
# Building the Dart SDK will already strip all binaries.
diff --git a/tools/make_version.py b/tools/make_version.py
index 4bb7f75..bf88617 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -69,7 +69,7 @@
def MakeFile(quiet, output_file, input_file, no_git_hash, custom_for_pub, version_file=None):
if version_file:
- version_string = utils.GetVersion(version_file)
+ version_string = utils.GetVersion(no_git_hash, version_file)
else:
version_string = MakeVersionString(quiet, no_git_hash, custom_for_pub)
diff --git a/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
new file mode 100644
index 0000000..ec58158
--- /dev/null
+++ b/tools/patches/flutter-flutter/445a23a9bc14a57ea6275e5d4da179f7cb0bbdb6.patch
@@ -0,0 +1,46 @@
+diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
+index 7d450be42..e158e33af 100644
+--- a/packages/flutter_test/lib/src/binding.dart
++++ b/packages/flutter_test/lib/src/binding.dart
+@@ -1763,9 +1763,10 @@ class _MockHttpResponse extends Stream<List<int>> implements HttpClientResponse
+ @override
+ int get contentLength => -1;
+
+- // @override
+- // TODO(tvolkert): Uncomment @override annotation once SDK change lands.
+- bool get autoUncompress => true;
++ @override
++ HttpClientResponseCompressionState get compressionState {
++ return HttpClientResponseCompressionState.decompressed;
++ }
+
+ @override
+ List<Cookie> get cookies => null;
+diff --git a/packages/flutter_tools/lib/src/base/io.dart b/packages/flutter_tools/lib/src/base/io.dart
+index 4c9d2250b..8b3535d54 100644
+--- a/packages/flutter_tools/lib/src/base/io.dart
++++ b/packages/flutter_tools/lib/src/base/io.dart
+@@ -47,6 +47,7 @@ export 'dart:io'
+ HttpClient,
+ HttpClientRequest,
+ HttpClientResponse,
++ HttpClientResponseCompressionState,
+ HttpHeaders,
+ HttpRequest,
+ HttpServer,
+diff --git a/packages/flutter_tools/test/commands/create_test.dart b/packages/flutter_tools/test/commands/create_test.dart
+index b5453cbb1..f7cdf6164 100644
+--- a/packages/flutter_tools/test/commands/create_test.dart
++++ b/packages/flutter_tools/test/commands/create_test.dart
+@@ -1172,6 +1172,11 @@ class MockHttpClientResponse extends Stream<List<int>> implements HttpClientResp
+ @override
+ String get reasonPhrase => '<reason phrase>';
+
++ @override
++ HttpClientResponseCompressionState get compressionState {
++ return HttpClientResponseCompressionState.decompressed;
++ }
++
+ @override
+ StreamSubscription<List<int>> listen(
+ void onData(List<int> event), {
diff --git a/tools/patches/flutter-flutter/apply.sh b/tools/patches/flutter-flutter/apply.sh
index 47043f0..2b3a280 100755
--- a/tools/patches/flutter-flutter/apply.sh
+++ b/tools/patches/flutter-flutter/apply.sh
@@ -23,3 +23,9 @@
if [ -e "$patch" ]; then
(cd flutter && git apply ../$patch)
fi
+
+pinned_dart_sdk=$(get_pinned_dart_version)
+patch=src/third_party/dart/tools/patches/flutter-flutter/${pinned_dart_sdk}.patch
+if [ -e "$patch" ]; then
+ (cd flutter && git apply ../$patch)
+fi
diff --git a/tools/run_offsets_extractor.sh b/tools/run_offsets_extractor.sh
new file mode 100755
index 0000000..4e1a5ad
--- /dev/null
+++ b/tools/run_offsets_extractor.sh
@@ -0,0 +1,42 @@
+#!/usr/bin/env bash
+# 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.
+
+set -e
+
+FILE="runtime/vm/compiler/runtime_offsets_extracted.h"
+
+# Make sure we're running in the SDK directory.
+if ! test -f "$FILE"; then
+ echo "Couldn't find $FILE"
+ echo "Make sure to run this script from the Dart SDK directory."
+ exit 1
+fi
+
+# We're regenerating the file, but we want to keep all the comments etc at the
+# top of the file. So just delete everything after the first "#if defined".
+LINE=$(grep "#if defined" "$FILE" -n | head -n 1 | sed "s/^\([0-9]*\):.*/\1/")
+TEMP="${FILE}.temp"
+head -n $(expr $LINE - 1) "$FILE" >"$TEMP"
+
+# Run offsets_extractor for every architecture and append the results.
+run() {
+ echo "" >>"$TEMP"
+ tools/gn.py --mode=release --arch=$1
+ tools/build.py --mode=release --arch=$1 offsets_extractor
+ out/$2/offsets_extractor >>"$TEMP"
+}
+run simarm ReleaseSIMARM
+run x64 ReleaseX64
+run ia32 ReleaseIA32
+run simarm64 ReleaseSIMARM64
+run simdbc64 ReleaseSIMDBC64
+run simdbc ReleaseSIMDBC
+
+# Cleanup.
+echo "" >>"$TEMP"
+echo "#endif // RUNTIME_VM_COMPILER_RUNTIME_OFFSETS_EXTRACTED_H_" >>"$TEMP"
+mv "$TEMP" "$FILE"
+git cl format "$FILE"
+echo -e "\n\nSuccessfully generated $FILE :)"
diff --git a/tools/test.dart b/tools/test.dart
index ae5213c..edb0f8c 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -3,7 +3,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.
-// Run tests like on the given builder.
+// Run tests like on the given builder and/or named configuration.
import 'dart:async';
import 'dart:collection';
@@ -55,7 +55,7 @@
await Process.run(executable, arguments, runInShell: runInShell);
if (processResult.exitCode != 0) {
final command =
- ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+ [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
throw new Exception("Command exited ${processResult.exitCode}: $command\n"
"${processResult.stdout}\n${processResult.stderr}");
}
@@ -73,7 +73,7 @@
final processResult = new ProcessResult(process.pid, exitCode, "", "");
if (processResult.exitCode != 0) {
final command =
- ([executable]..addAll(arguments)).map(simpleShellSingleQuote).join(" ");
+ [executable, ...arguments].map(simpleShellSingleQuote).join(" ");
throw new Exception("Command exited ${processResult.exitCode}: $command");
}
return processResult;
@@ -319,12 +319,18 @@
void main(List<String> args) async {
final parser = new ArgParser();
parser.addOption("builder",
- abbr: "b", help: "Run tests like on the given buider");
+ abbr: "b", help: "Run tests like on the given builder");
parser.addOption("branch",
abbr: "B",
help: "Select the builders building this branch",
defaultsTo: "master");
parser.addOption("commit", abbr: "C", help: "Compare with this commit");
+ parser.addFlag("deflake",
+ help: "Re-run failing newly tests $deflakingCount times.");
+ parser.addFlag("report-flakes",
+ help: "Report test failures for tests known to be flaky.\n"
+ "This ignores all flakiness data from CI but flakes\n"
+ "detected by --deflake will remain hidden");
parser.addFlag("list-configurations",
help: "Output list of configurations.", negatable: false);
parser.addOption("named-configuration",
@@ -354,8 +360,8 @@
Run tests and compare with the results on the given builder. Either the -n or
the -b option, or both, must be used. Any options following -- and non-option
-arguments will be forwarded to test.py invocations. The results for the specified
-named configuration will be downloaded from the specified builder. If only a
+arguments will be forwarded to test.py invocations. The specified named
+configuration's results will be downloaded from the specified builder. If only a
named configuration is specified, the results are downloaded from the
appropriate builders. If only a builder is specified, the default named
configuration is used if the builder only has a single named configuration.
@@ -404,7 +410,7 @@
exitCode = 1;
return;
}
- if (2 <= namedConfigurations.length) {
+ if (namedConfigurations.length > 1) {
final builder = builders.single;
stderr.writeln(
"error: The builder $builder is testing multiple named configurations");
@@ -418,7 +424,7 @@
}
final namedConfiguration = namedConfigurations.single;
final localConfiguration =
- options["local-configuration"] ?? namedConfiguration;
+ options["local-configuration"] as String ?? namedConfiguration;
for (final builder in builders) {
if (localConfiguration != namedConfiguration) {
print("Testing the named configuration $localConfiguration "
@@ -452,28 +458,34 @@
"as baseline instead of $commit for $builder");
inexactBuilds[builder] = buildSearchResult.commit;
}
- final buildNumber = buildSearchResult.build;
+ final buildNumber = buildSearchResult.build.toString();
print("Downloading results from builder $builder build $buildNumber...");
- await cpGsutil(
- buildFileCloudPath(builder, buildNumber.toString(), "results.json"),
+ await cpGsutil(buildFileCloudPath(builder, buildNumber, "results.json"),
"${outDirectory.path}/previous.json");
- await cpGsutil(
- buildFileCloudPath(builder, buildNumber.toString(), "flaky.json"),
- "${outDirectory.path}/flaky.json");
+ if (!options["report-flakes"]) {
+ await cpGsutil(buildFileCloudPath(builder, buildNumber, "flaky.json"),
+ "${outDirectory.path}/flaky.json");
+ }
print("Downloaded baseline results from builder $builder");
// Merge the results for the builders.
- if (2 <= builders.length) {
+ if (builders.length > 1) {
mergedResults
.addAll(await loadResultsMap("${outDirectory.path}/previous.json"));
- mergedFlaky
- .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+ if (!options["report-flakes"]) {
+ mergedFlaky
+ .addAll(await loadResultsMap("${outDirectory.path}/flaky.json"));
+ }
}
}
// Write out the merged results for the builders.
- if (2 <= builders.length) {
+ if (builders.length > 1) {
await new File("${outDirectory.path}/previous.json").writeAsString(
mergedResults.values.map((data) => jsonEncode(data) + "\n").join(""));
+ }
+
+ // Ensure that there is a flaky.json even if it wasn't downloaded.
+ if (builders.length > 1 || options["report-flakes"]) {
await new File("${outDirectory.path}/flaky.json").writeAsString(
mergedFlaky.values.map((data) => jsonEncode(data) + "\n").join(""));
}
@@ -502,62 +514,18 @@
"--silent-failures",
"--write-results",
"--write-logs",
- ]..addAll(options.rest);
+ ...options.rest,
+ ];
print("".padLeft(80, "="));
print("Running tests");
print("".padLeft(80, "="));
- await runProcessInheritStdio("python", ["tools/test.py"]..addAll(arguments),
+ await runProcessInheritStdio("python", ["tools/test.py", ...arguments],
runInShell: Platform.isWindows);
- // Find the list of tests to deflake.
- final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
- "tools/bots/compare_results.dart",
- "--changed",
- "--failing",
- "--passing",
- "--flakiness-data=${outDirectory.path}/flaky.json",
- "${outDirectory.path}/previous.json",
- "${outDirectory.path}/results.json",
- ]);
- final deflakeListPath = "${outDirectory.path}/deflake.list";
- final deflakeListFile = new File(deflakeListPath);
- await deflakeListFile.writeAsString(deflakeListOutput.stdout);
-
- // Deflake the changed tests.
- final deflakingResultsPaths = <String>[];
- for (int i = 1;
- deflakeListOutput.stdout != "" && i <= deflakingCount;
- i++) {
- print("".padLeft(80, "="));
- print("Running deflaking iteration $i");
- print("".padLeft(80, "="));
- final deflakeDirectory = new Directory("${outDirectory.path}/$i");
- await deflakeDirectory.create();
- final deflakeArguments = <String>[
- "--named-configuration=$localConfiguration",
- "--output-directory=${deflakeDirectory.path}",
- "--clean-exit",
- "--silent-failures",
- "--write-results",
- "--test-list=$deflakeListPath",
- ]..addAll(options.rest);
- await runProcessInheritStdio(
- "python", ["tools/test.py"]..addAll(deflakeArguments),
- runInShell: Platform.isWindows);
- deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+ if (options["deflake"]) {
+ await deflake(outDirectory, localConfiguration, options.rest);
}
- // Update the flakiness information based on what we've learned.
- print("Updating flakiness information...");
- await runProcess(
- Platform.resolvedExecutable,
- [
- "tools/bots/update_flakiness.dart",
- "--input=${outDirectory.path}/flaky.json",
- "--output=${outDirectory.path}/flaky.json",
- "${outDirectory.path}/results.json",
- ]..addAll(deflakingResultsPaths));
-
// Write out the final comparison.
print("".padLeft(80, "="));
print("Test Results");
@@ -589,3 +557,53 @@
await outDirectory.delete(recursive: true);
}
}
+
+void deflake(Directory outDirectory, String localConfiguration,
+ List<String> testPyArgs) async {
+ // Find the list of tests to deflake.
+ final deflakeListOutput = await runProcess(Platform.resolvedExecutable, [
+ "tools/bots/compare_results.dart",
+ "--changed",
+ "--failing",
+ "--passing",
+ "--flakiness-data=${outDirectory.path}/flaky.json",
+ "${outDirectory.path}/previous.json",
+ "${outDirectory.path}/results.json",
+ ]);
+ final deflakeListPath = "${outDirectory.path}/deflake.list";
+ final deflakeListFile = new File(deflakeListPath);
+ await deflakeListFile.writeAsString(deflakeListOutput.stdout);
+
+ // Deflake the changed tests.
+ final deflakingResultsPaths = <String>[];
+ for (int i = 1; deflakeListOutput.stdout != "" && i <= deflakingCount; i++) {
+ print("".padLeft(80, "="));
+ print("Running deflaking iteration $i");
+ print("".padLeft(80, "="));
+ final deflakeDirectory = new Directory("${outDirectory.path}/$i");
+ await deflakeDirectory.create();
+ final deflakeArguments = <String>[
+ "--named-configuration=$localConfiguration",
+ "--output-directory=${deflakeDirectory.path}",
+ "--clean-exit",
+ "--silent-failures",
+ "--write-results",
+ "--test-list=$deflakeListPath",
+ ...testPyArgs,
+ ];
+ await runProcessInheritStdio(
+ "python", ["tools/test.py", ...deflakeArguments],
+ runInShell: Platform.isWindows);
+ deflakingResultsPaths.add("${deflakeDirectory.path}/results.json");
+ }
+
+ // Update the flakiness information based on what we've learned.
+ print("Updating flakiness information...");
+ await runProcess(Platform.resolvedExecutable, [
+ "tools/bots/update_flakiness.dart",
+ "--input=${outDirectory.path}/flaky.json",
+ "--output=${outDirectory.path}/flaky.json",
+ "${outDirectory.path}/results.json",
+ ...deflakingResultsPaths,
+ ]);
+}
diff --git a/tools/testing/dart/babel_transform.js b/tools/testing/dart/babel_transform.js
new file mode 100644
index 0000000..5229e8a
--- /dev/null
+++ b/tools/testing/dart/babel_transform.js
@@ -0,0 +1,12 @@
+// 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.
+
+
+const babelStandalonePath = arguments[0];
+load(babelStandalonePath);
+const inputFilePath = arguments[2];
+const input = read(inputFilePath);
+const options = JSON.parse(arguments[1]);
+const output = Babel.transform(input, options).code;
+console.log(output);
diff --git a/tools/testing/dart/command.dart b/tools/testing/dart/command.dart
index d89b964..2eb7648 100644
--- a/tools/testing/dart/command.dart
+++ b/tools/testing/dart/command.dart
@@ -76,10 +76,15 @@
checked: checked);
}
- static Command adbPrecompiled(String precompiledRunner, String processTest,
- String testDirectory, List<String> arguments, bool useBlobs) {
- return new AdbPrecompilationCommand._(
- precompiledRunner, processTest, testDirectory, arguments, useBlobs);
+ static Command adbPrecompiled(
+ String precompiledRunner,
+ String processTest,
+ String testDirectory,
+ List<String> arguments,
+ bool useBlobs,
+ bool useElf) {
+ return new AdbPrecompilationCommand._(precompiledRunner, processTest,
+ testDirectory, arguments, useBlobs, useElf);
}
static Command adbDartk(String precompiledRunner, String processTest,
@@ -252,7 +257,8 @@
}
class CompilationCommand extends ProcessCommand {
- final String _outputFile;
+ /// The primary output file that will be created by this command.
+ final String outputFile;
/// If true, then the compilation is run even if the input files are older
/// than the output file.
@@ -261,7 +267,7 @@
CompilationCommand._(
String displayName,
- this._outputFile,
+ this.outputFile,
this._alwaysCompile,
this._bootstrapDependencies,
String executable,
@@ -274,7 +280,7 @@
CompilationCommand indexedCopy(int index) => CompilationCommand._(
displayName,
- _outputFile,
+ outputFile,
_alwaysCompile,
_bootstrapDependencies,
executable,
@@ -286,7 +292,7 @@
bool get outputIsUpToDate {
if (_alwaysCompile) return false;
- var file = new io.File(new Path("$_outputFile.deps").toNativePath());
+ var file = new io.File(new Path("$outputFile.deps").toNativePath());
if (!file.existsSync()) return false;
var lines = file.readAsLinesSync();
@@ -300,7 +306,7 @@
dependencies.addAll(_bootstrapDependencies);
var jsOutputLastModified = TestUtils.lastModifiedCache
- .getLastModified(new Uri(scheme: 'file', path: _outputFile));
+ .getLastModified(new Uri(scheme: 'file', path: outputFile));
if (jsOutputLastModified == null) return false;
for (var dependency in dependencies) {
@@ -316,14 +322,14 @@
void _buildHashCode(HashCodeBuilder builder) {
super._buildHashCode(builder);
- builder.addJson(_outputFile);
+ builder.addJson(outputFile);
builder.addJson(_alwaysCompile);
builder.addJson(_bootstrapDependencies);
}
bool _equal(CompilationCommand other) =>
super._equal(other) &&
- _outputFile == other._outputFile &&
+ outputFile == other.outputFile &&
_alwaysCompile == other._alwaysCompile &&
deepJsonCompare(_bootstrapDependencies, other._bootstrapDependencies);
}
@@ -347,7 +353,7 @@
@override
FastaCompilationCommand indexedCopy(int index) => FastaCompilationCommand._(
_compilerLocation,
- _outputFile,
+ outputFile,
_bootstrapDependencies,
executable,
arguments,
@@ -437,7 +443,7 @@
VMKernelCompilationCommand indexedCopy(int index) =>
VMKernelCompilationCommand._(
- _outputFile,
+ outputFile,
_alwaysCompile,
_bootstrapDependencies,
executable,
@@ -589,6 +595,7 @@
final String precompiledTestDirectory;
final List<String> arguments;
final bool useBlobs;
+ final bool useElf;
AdbPrecompilationCommand._(
this.precompiledRunnerFilename,
@@ -596,6 +603,7 @@
this.precompiledTestDirectory,
this.arguments,
this.useBlobs,
+ this.useElf,
{int index = 0})
: super._("adb_precompilation", index: index);
@@ -605,6 +613,7 @@
precompiledTestDirectory,
arguments,
useBlobs,
+ useElf,
index: index);
_buildHashCode(HashCodeBuilder builder) {
super._buildHashCode(builder);
@@ -612,12 +621,14 @@
builder.add(precompiledTestDirectory);
builder.add(arguments);
builder.add(useBlobs);
+ builder.add(useElf);
}
bool _equal(AdbPrecompilationCommand other) =>
super._equal(other) &&
precompiledRunnerFilename == other.precompiledRunnerFilename &&
useBlobs == other.useBlobs &&
+ useElf == other.useElf &&
arguments == other.arguments &&
precompiledTestDirectory == other.precompiledTestDirectory;
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 7c55c86..f3459d0 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -118,8 +118,6 @@
}
}
- // TODO(ahe): It shouldn't be necessary to pass [buildDir] to any of these
- // functions. It is fixed for a given configuration.
String computeCompilerPath() {
throw "Unknown compiler for: $runtimeType";
}
@@ -130,15 +128,6 @@
List<Uri> bootstrapDependencies() => const <Uri>[];
- /// Creates a [Command] to compile [inputFile] to [outputFile].
- Command createCommand(String inputFile, String outputFile,
- List<String> sharedOptions, Map<String, String> environment) {
- // TODO(rnystrom): See if this method can be unified with
- // computeCompilationArtifact() and/or computeCompilerArguments() for the
- // other compilers.
- throw new UnsupportedError("$this does not support createCommand().");
- }
-
CommandArtifact computeCompilationArtifact(
/// Each test has its own temporary directory to avoid name collisions.
@@ -188,6 +177,11 @@
List<String> originalArguments,
CommandArtifact artifact) {
var args = <String>[];
+ if (_isDebug) {
+ // Temporarily disable background compilation to avoid flaky crashes
+ // (see http://dartbug.com/30016 for details).
+ args.add('--no-background-compilation');
+ }
if (_useEnableAsserts) {
args.add('--enable_asserts');
}
@@ -481,10 +475,26 @@
List<String> arguments, Map<String, String> environmentOverrides) {
var compilerArguments = arguments.toList()
..addAll(_configuration.dart2jsOptions);
- return new CommandArtifact([
- computeCompilationCommand(
- '$tempDir/out.js', compilerArguments, environmentOverrides)
- ], '$tempDir/out.js', 'application/javascript');
+
+ var commands = <Command>[];
+ // TODO(athom): input filename extraction is copied from DDC. Maybe this
+ // should be passed to computeCompilationArtifact, instead?
+ var inputFile = arguments.last;
+ var inputFilename = (new Uri.file(inputFile)).pathSegments.last;
+ var out = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
+ var babel = _configuration.babel;
+ var babelOut = out;
+ if (babel != null && babel.isNotEmpty) {
+ out = out.replaceAll('.js', '.raw.js');
+ }
+ commands.add(computeCompilationCommand(
+ out, compilerArguments, environmentOverrides));
+
+ if (babel != null && babel.isNotEmpty) {
+ commands.add(computeBabelCommand(out, babelOut, babel));
+ }
+
+ return new CommandArtifact(commands, babelOut, 'application/javascript');
}
List<String> computeRuntimeArguments(
@@ -502,6 +512,22 @@
return runtimeConfiguration.dart2jsPreambles(preambleDir)
..add(artifact.filename);
}
+
+ Command computeBabelCommand(String input, String output, String options) {
+ var uri = Repository.uri;
+ var babelTransform =
+ uri.resolve('tools/testing/dart/babel_transform.js').toFilePath();
+ var babelStandalone =
+ uri.resolve('third_party/babel/babel.min.js').toFilePath();
+ return Command.compilation(
+ 'babel',
+ output,
+ [],
+ _configuration.runtimeConfiguration.d8FileName,
+ [babelTransform, "--", babelStandalone, options, input],
+ {},
+ alwaysCompile: true); // TODO(athom): ensure dependency tracking works.
+ }
}
/// Configuration for `dartdevc` and `dartdevk` (DDC with Kernel)
@@ -532,7 +558,7 @@
return result;
}
- Command createCommand(String inputFile, String outputFile,
+ Command _createCommand(String inputFile, String outputFile,
List<String> sharedOptions, Map<String, String> environment) {
/// This can be disabled to test DDC's hybrid mode (automatically converting
/// Analyzer summaries to Kernel files).
@@ -624,7 +650,7 @@
var outputFile = "$tempDir/${inputFilename.replaceAll('.dart', '.js')}";
return new CommandArtifact(
- [createCommand(inputFile, outputFile, sharedOptions, environment)],
+ [_createCommand(inputFile, outputFile, sharedOptions, environment)],
outputFile,
"application/javascript");
}
@@ -668,7 +694,7 @@
tempDir, arguments, environmentOverrides));
}
- if (!_configuration.useBlobs) {
+ if (!_configuration.useBlobs && !_configuration.useElf) {
commands.add(
computeAssembleCommand(tempDir, arguments, environmentOverrides));
if (!_configuration.keepGeneratedFiles) {
@@ -724,6 +750,9 @@
if (_configuration.useBlobs) {
args.add("--snapshot-kind=app-aot-blobs");
args.add("--blobs_container_filename=$tempDir/out.aotsnapshot");
+ } else if (_configuration.useElf) {
+ args.add("--snapshot-kind=app-aot-elf");
+ args.add("--assembly=$tempDir/out.aotsnapshot");
} else {
args.add("--snapshot-kind=app-aot-assembly");
args.add("--assembly=$tempDir/out.S");
@@ -1153,6 +1182,7 @@
args.add('--gen-bytecode');
args.add('--drop-ast');
args.add('--emit-bytecode-source-positions');
+ args.add('--emit-bytecode-local-var-info');
}
return Command.vmKernelCompilation(dillFile, true, bootstrapDependencies(),
@@ -1199,12 +1229,6 @@
List<Uri> bootstrapDependencies() => [_platformDill];
@override
- Command createCommand(String inputFile, String outputFile,
- List<String> sharedOptions, Map<String, String> environment) {
- throw new UnimplementedError();
- }
-
- @override
CommandArtifact computeCompilationArtifact(String tempDir,
List<String> arguments, Map<String, String> environmentOverrides) {
var output =
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index fac39a9..da990fb9 100644
--- a/tools/testing/dart/configuration.dart
+++ b/tools/testing/dart/configuration.dart
@@ -115,6 +115,7 @@
bool get useAnalyzerCfe => configuration.useAnalyzerCfe;
bool get useAnalyzerFastaParser => configuration.useAnalyzerFastaParser;
bool get useBlobs => configuration.useBlobs;
+ bool get useElf => configuration.useElf;
bool get useSdk => configuration.useSdk;
bool get useEnableAsserts => configuration.enableAsserts;
@@ -164,6 +165,7 @@
final String outputDirectory;
final String packageRoot;
final String suiteDirectory;
+ String get babel => configuration.babel;
String get builderTag => configuration.builderTag;
final List<String> reproducingArguments;
@@ -210,24 +212,30 @@
/// build/none_vm_release_x64
String get buildDirectory => system.outputDirectory + configurationDirectory;
+ int _timeout;
+
// TODO(whesse): Put non-default timeouts explicitly in configs, not this.
/// Calculates a default timeout based on the compiler and runtime used,
/// and the mode, architecture, etc.
int get timeout {
- if (configuration.timeout == null) {
- var isReload = hotReload || hotReloadRollback;
+ if (_timeout == null) {
+ if (configuration.timeout > 0) {
+ _timeout = configuration.timeout;
+ } else {
+ var isReload = hotReload || hotReloadRollback;
- var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
- var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
- mode: mode,
- isChecked: isChecked,
- isReload: isReload,
- arch: architecture);
+ var compilerMulitiplier = compilerConfiguration.timeoutMultiplier;
+ var runtimeMultiplier = runtimeConfiguration.timeoutMultiplier(
+ mode: mode,
+ isChecked: isChecked,
+ isReload: isReload,
+ arch: architecture);
- configuration.timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+ _timeout = 60 * compilerMulitiplier * runtimeMultiplier;
+ }
}
- return configuration.timeout;
+ return _timeout;
}
List<String> get standardOptions {
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index bf979ac..9519f1c 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -181,6 +181,9 @@
new _Option.bool(
'use_blobs', 'Use mmap instead of shared libraries for precompilation.',
hide: true),
+ new _Option.bool(
+ 'use_elf', 'Directly generate an ELF shared libraries for precompilation.',
+ hide: true),
new _Option.bool('keep_generated_files', 'Keep any generated files.',
abbr: 'k'),
new _Option.int('timeout', 'Timeout in seconds.', abbr: 't'),
@@ -222,7 +225,7 @@
new _Option.bool(
'silent_failures',
"Don't complain about failing tests. This is useful when in "
- "combination with --write-results.",
+ "combination with --write-results.",
hide: true),
new _Option.bool('report_in_json',
'When listing with --list, output result summary in JSON.',
@@ -250,12 +253,12 @@
new _Option.bool(
'write_results',
'Write results to a "${TestUtils.resultsFileName}" json file '
- 'located at the debug_output_directory.',
+ 'located at the debug_output_directory.',
hide: true),
new _Option.bool(
'write_logs',
'Include the stdout and stderr of tests that don\'t match expectations '
- 'in the "${TestUtils.logsFileName}" file',
+ 'in the "${TestUtils.logsFileName}" file',
hide: true),
new _Option.bool(
'reset_browser_configuration',
@@ -300,6 +303,11 @@
hide: true),
new _Option('shared_options', 'Extra shared options.', hide: true),
new _Option(
+ 'babel',
+ '''Transforms dart2js output with Babel. The value must be
+Babel options JSON.''',
+ hide: true),
+ new _Option(
'suite_dir', 'Additional directory to add to the testing matrix.',
hide: true),
new _Option('package_root', 'The package root to use for testing.',
@@ -688,6 +696,7 @@
useAnalyzerFastaParser:
data["analyzer_use_fasta_parser"] as bool,
useBlobs: data["use_blobs"] as bool,
+ useElf: data["use_elf"] as bool,
useSdk: data["use_sdk"] as bool,
useHotReload: data["hot_reload"] as bool,
useHotReloadRollback: data["hot_reload_rollback"] as bool,
@@ -696,6 +705,7 @@
isMinified: data["minified"] as bool,
vmOptions: vmOptions,
dart2jsOptions: dart2jsOptions,
+ babel: data['babel'] as String,
builderTag: data["builder_tag"] as String,
previewDart2: true);
var configuration = new TestConfiguration(
diff --git a/tools/testing/dart/runtime_configuration.dart b/tools/testing/dart/runtime_configuration.dart
index c523839..38c10b1 100644
--- a/tools/testing/dart/runtime_configuration.dart
+++ b/tools/testing/dart/runtime_configuration.dart
@@ -8,9 +8,7 @@
import 'compiler_configuration.dart';
import 'configuration.dart';
import 'repository.dart';
-// TODO(ahe): Remove this import, we can precompute all the values required
-// from TestSuite once the refactoring is complete.
-import 'test_suite.dart';
+import 'utils.dart';
/// Describes the commands to run a given test case or its compiled output.
///
@@ -50,10 +48,14 @@
case Runtime.dartPrecompiled:
if (configuration.system == System.android) {
return new DartPrecompiledAdbRuntimeConfiguration(
- useBlobs: configuration.useBlobs);
+ useBlobs: configuration.useBlobs,
+ useElf: configuration.useElf,
+ );
} else {
return new DartPrecompiledRuntimeConfiguration(
- useBlobs: configuration.useBlobs);
+ useBlobs: configuration.useBlobs,
+ useElf: configuration.useElf,
+ );
}
break;
@@ -78,7 +80,6 @@
}
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -88,9 +89,74 @@
throw "Unimplemented runtime '$runtimeType'";
}
+ /**
+ * The output directory for this suite's configuration.
+ */
+ String get buildDir => _configuration.buildDirectory;
+
List<String> dart2jsPreambles(Uri preambleDir) => [];
bool get shouldSkipNegativeTests => false;
+
+ /// Returns the path to the Dart VM executable.
+ String get dartVmBinaryFileName {
+ // Controlled by user with the option "--dart".
+ var dartExecutable = _configuration.dartPath;
+
+ if (dartExecutable == null) {
+ dartExecutable = dartVmExecutableFileName;
+ }
+
+ TestUtils.ensureExists(dartExecutable, _configuration);
+ return dartExecutable;
+ }
+
+ String get dartVmExecutableFileName {
+ return _configuration.useSdk
+ ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
+ : '$buildDir/dart$executableBinarySuffix';
+ }
+
+ String get dartPrecompiledBinaryFileName {
+ // Controlled by user with the option "--dart_precompiled".
+ var dartExecutable = _configuration.dartPrecompiledPath;
+
+ if (dartExecutable == null || dartExecutable == '') {
+ var suffix = executableBinarySuffix;
+ dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
+ }
+
+ TestUtils.ensureExists(dartExecutable, _configuration);
+ return dartExecutable;
+ }
+
+ String get processTestBinaryFileName {
+ var suffix = executableBinarySuffix;
+ var processTestExecutable = '$buildDir/process_test$suffix';
+ TestUtils.ensureExists(processTestExecutable, _configuration);
+ return processTestExecutable;
+ }
+
+ String get d8FileName {
+ var suffix = executableBinarySuffix;
+ var d8Dir = Repository.dir.append('third_party/d8');
+ var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
+ var d8 = d8Path.toNativePath();
+ TestUtils.ensureExists(d8, _configuration);
+ return d8;
+ }
+
+ String get jsShellFileName {
+ var executableSuffix = executableBinarySuffix;
+ var executable = 'jsshell$executableSuffix';
+ var jsshellDir = Repository.uri.resolve("tools/testing/bin").path;
+ var jsshell = '$jsshellDir/$executable';
+ TestUtils.ensureExists(jsshell, _configuration);
+ return jsshell;
+ }
+
+ String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
+ String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
}
/// The 'none' runtime configuration.
@@ -98,7 +164,6 @@
NoneRuntimeConfiguration() : super._subclass();
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -126,7 +191,6 @@
D8RuntimeConfiguration() : super('d8');
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -136,7 +200,7 @@
checkArtifact(artifact);
return [
Command.jsCommandLine(
- moniker, suite.d8FileName, arguments, environmentOverrides)
+ moniker, d8FileName, arguments, environmentOverrides)
];
}
@@ -150,7 +214,6 @@
JsshellRuntimeConfiguration() : super('jsshell');
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -159,7 +222,7 @@
checkArtifact(artifact);
return [
Command.jsCommandLine(
- moniker, suite.jsShellFileName, arguments, environmentOverrides)
+ moniker, jsShellFileName, arguments, environmentOverrides)
];
}
@@ -210,7 +273,6 @@
//// The standalone Dart VM binary, "dart" or "dart.exe".
class StandaloneDartRuntimeConfiguration extends DartVmRuntimeConfiguration {
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -228,9 +290,9 @@
if (isCrashExpected) {
arguments.insert(0, '--suppress-core-dump');
}
- String executable = suite.dartVmBinaryFileName;
+ String executable = dartVmBinaryFileName;
if (type == 'application/kernel-ir-fully-linked') {
- executable = suite.dartVmExecutableFileName;
+ executable = dartVmExecutableFileName;
}
return [Command.vm(executable, arguments, environmentOverrides)];
}
@@ -238,10 +300,12 @@
class DartPrecompiledRuntimeConfiguration extends DartVmRuntimeConfiguration {
final bool useBlobs;
- DartPrecompiledRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+ final bool useElf;
+ DartPrecompiledRuntimeConfiguration({bool useBlobs, bool useElf})
+ : useBlobs = useBlobs,
+ useElf = useElf;
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -254,8 +318,7 @@
}
return [
- Command.vm(
- suite.dartPrecompiledBinaryFileName, arguments, environmentOverrides)
+ Command.vm(dartPrecompiledBinaryFileName, arguments, environmentOverrides)
];
}
}
@@ -265,7 +328,6 @@
static const String DeviceTestDir = '/data/local/tmp/testing/test';
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -277,8 +339,8 @@
throw "dart cannot run files of type '$type'.";
}
- final String buildPath = suite.buildDir;
- final String processTest = suite.processTestBinaryFileName;
+ final String buildPath = buildDir;
+ final String processTest = processTestBinaryFileName;
return [
Command.adbDartk(buildPath, processTest, script, arguments, extraLibs)
];
@@ -292,10 +354,12 @@
'/data/local/tmp/precompilation-testing/test';
final bool useBlobs;
- DartPrecompiledAdbRuntimeConfiguration({bool useBlobs}) : useBlobs = useBlobs;
+ final bool useElf;
+ DartPrecompiledAdbRuntimeConfiguration({bool useBlobs, bool useElf})
+ : useBlobs = useBlobs,
+ useElf = useElf;
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
@@ -307,11 +371,11 @@
throw "dart_precompiled cannot run files of type '$type'.";
}
- String precompiledRunner = suite.dartPrecompiledBinaryFileName;
- String processTest = suite.processTestBinaryFileName;
+ String precompiledRunner = dartPrecompiledBinaryFileName;
+ String processTest = processTestBinaryFileName;
return [
Command.adbPrecompiled(
- precompiledRunner, processTest, script, arguments, useBlobs)
+ precompiledRunner, processTest, script, arguments, useBlobs, useElf)
];
}
}
@@ -333,17 +397,16 @@
}
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
List<String> extraLibs,
bool isCrashExpected) {
- String executable = suite.dartVmBinaryFileName;
+ String executable = dartVmBinaryFileName;
return selfCheckers
.map((String tester) => Command.vmBatch(
executable, tester, arguments, environmentOverrides,
- checked: suite.configuration.isChecked))
+ checked: _configuration.isChecked))
.toList();
}
@@ -356,7 +419,6 @@
// TODO(ahe): Remove this class.
class DummyRuntimeConfiguration extends DartVmRuntimeConfiguration {
List<Command> computeRuntimeCommands(
- TestSuite suite,
CommandArtifact artifact,
List<String> arguments,
Map<String, String> environmentOverrides,
diff --git a/tools/testing/dart/test_configurations.dart b/tools/testing/dart/test_configurations.dart
index 32b9559..68f97a4 100644
--- a/tools/testing/dart/test_configurations.dart
+++ b/tools/testing/dart/test_configurations.dart
@@ -35,6 +35,7 @@
new Path('tests/compiler/dart2js'),
new Path('tests/compiler/dart2js_extra'),
new Path('tests/compiler/dart2js_native'),
+ new Path('tests/compiler/dartdevc_native'),
new Path('tests/corelib_2'),
new Path('tests/kernel'),
new Path('tests/language_2'),
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart
index ed69296..1d13426 100644
--- a/tools/testing/dart/test_runner.dart
+++ b/tools/testing/dart/test_runner.dart
@@ -244,7 +244,7 @@
* it is longer than MAX_HEAD characters, and just keeps the head and
* the last TAIL_LENGTH characters of the output.
*/
-class OutputLog {
+class OutputLog implements StreamConsumer<List<int>> {
static const int MAX_HEAD = 500 * 1024;
static const int TAIL_LENGTH = 10 * 1024;
List<int> head = <int>[];
@@ -252,6 +252,7 @@
List<int> complete;
bool dataDropped = false;
bool hasNonUtf8 = false;
+ StreamSubscription _subscription;
OutputLog();
@@ -325,6 +326,53 @@
}
return complete;
}
+
+ @override
+ Future addStream(Stream<List<int>> stream) {
+ _subscription = stream.listen(this.add);
+ return _subscription.asFuture();
+ }
+
+ @override
+ Future close() {
+ toList();
+ return _subscription?.cancel();
+ }
+
+ Future cancel() {
+ return _subscription?.cancel();
+ }
+}
+
+// An [OutputLog] that tees the output to a file as well.
+class FileOutputLog extends OutputLog {
+ io.File _outputFile;
+ io.IOSink _sink;
+
+ FileOutputLog(this._outputFile);
+
+ @override
+ void add(List<int> data) {
+ super.add(data);
+ _sink ??= _outputFile.openWrite();
+ _sink.add(data);
+ }
+
+ @override
+ Future close() {
+ return Future.wait([
+ super.close(),
+ if (_sink != null) _sink.flush().whenComplete(_sink.close)
+ ]);
+ }
+
+ @override
+ Future cancel() {
+ return Future.wait([
+ super.cancel(),
+ if (_sink != null) _sink.flush().whenComplete(_sink.close)
+ ]);
+ }
}
// Helper to get a list of all child pids for a parent process.
@@ -381,16 +429,19 @@
int timeout;
bool timedOut = false;
DateTime startTime;
- Timer timeoutTimer;
int pid;
- OutputLog stdout = new OutputLog();
- OutputLog stderr = new OutputLog();
+ OutputLog stdout;
+ OutputLog stderr = OutputLog();
+ StreamConsumer stdoutConsumer;
List<String> diagnostics = <String>[];
bool compilationSkipped = false;
Completer<CommandOutput> completer;
TestConfiguration configuration;
- RunningProcess(this.command, this.timeout, {this.configuration});
+ RunningProcess(this.command, this.timeout,
+ {this.configuration, io.File outputFile}) {
+ stdout = outputFile != null ? FileOutputLog(outputFile) : OutputLog();
+ }
Future<CommandOutput> run() {
completer = new Completer<CommandOutput>();
@@ -410,44 +461,10 @@
environment: processEnvironment,
workingDirectory: command.workingDirectory);
processFuture.then((io.Process process) {
- StreamSubscription stdoutSubscription =
- _drainStream(process.stdout, stdout);
- StreamSubscription stderrSubscription =
- _drainStream(process.stderr, stderr);
-
- var stdoutCompleter = new Completer<Null>();
- var stderrCompleter = new Completer<Null>();
-
- bool stdoutDone = false;
- bool stderrDone = false;
+ var stdoutFuture = process.stdout.pipe(stdout);
+ var stderrFuture = process.stderr.pipe(stderr);
pid = process.pid;
- // This timer is used to close stdio to the subprocess once we got
- // the exitCode. Sometimes descendants of the subprocess keep stdio
- // handles alive even though the direct subprocess is dead.
- Timer watchdogTimer;
-
- closeStdout([_]) {
- if (!stdoutDone) {
- stdoutCompleter.complete();
- stdoutDone = true;
- if (stderrDone && watchdogTimer != null) {
- watchdogTimer.cancel();
- }
- }
- }
-
- closeStderr([_]) {
- if (!stderrDone) {
- stderrCompleter.complete();
- stderrDone = true;
-
- if (stdoutDone && watchdogTimer != null) {
- watchdogTimer.cancel();
- }
- }
- }
-
// Close stdin so that tests that try to block on input will fail.
process.stdin.close();
timeoutHandler() async {
@@ -507,30 +524,31 @@
}
}
- stdoutSubscription.asFuture().then(closeStdout);
- stderrSubscription.asFuture().then(closeStderr);
-
- process.exitCode.then((exitCode) {
- if (!stdoutDone || !stderrDone) {
- watchdogTimer = new Timer(MAX_STDIO_DELAY, () {
- DebugLogger.warning(
- "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
- watchdogTimer = null;
- stdoutSubscription.cancel();
- stderrSubscription.cancel();
- closeStdout();
- closeStderr();
- });
- }
-
- Future.wait([stdoutCompleter.future, stderrCompleter.future])
- .then((_) {
+ // Wait for the process to finish or timeout
+ process.exitCode
+ .timeout(Duration(seconds: timeout), onTimeout: timeoutHandler)
+ .then((exitCode) {
+ // This timeout is used to close stdio to the subprocess once we got
+ // the exitCode. Sometimes descendants of the subprocess keep stdio
+ // handles alive even though the direct subprocess is dead.
+ Future.wait([stdoutFuture, stderrFuture]).timeout(MAX_STDIO_DELAY,
+ onTimeout: () async {
+ DebugLogger.warning(
+ "$MAX_STDIO_DELAY_PASSED_MESSAGE (command: $command)");
+ await stdout.cancel();
+ await stderr.cancel();
+ _commandComplete(exitCode);
+ return null;
+ }).then((_) {
+ if (stdout is FileOutputLog) {
+ // Prevent logging data that has already been written to a file
+ // and is unlikely too add value in the logs because the command
+ // succeeded.
+ stdout.complete = <int>[];
+ }
_commandComplete(exitCode);
});
});
-
- timeoutTimer =
- new Timer(new Duration(seconds: timeout), timeoutHandler);
}).catchError((e) {
// TODO(floitsch): should we try to report the stacktrace?
print("Process error:");
@@ -543,9 +561,6 @@
}
void _commandComplete(int exitCode) {
- if (timeoutTimer != null) {
- timeoutTimer.cancel();
- }
var commandOutput = _createCommandOutput(command, exitCode);
completer.complete(commandOutput);
}
@@ -573,11 +588,6 @@
return commandOutput;
}
- StreamSubscription _drainStream(
- Stream<List<int>> source, OutputLog destination) {
- return source.listen(destination.add);
- }
-
Map<String, String> _createProcessEnvironment() {
var environment = new Map<String, String>.from(io.Platform.environment);
@@ -1209,7 +1219,8 @@
return _getBatchRunner(name)
.runCommand(name, command, timeout, command.arguments);
} else if (command is CompilationCommand &&
- globalConfiguration.batchDart2JS) {
+ globalConfiguration.batchDart2JS &&
+ command.displayName == 'dart2js') {
return _getBatchRunner("dart2js")
.runCommand("dart2js", command, timeout, command.arguments);
} else if (command is AnalysisCommand && globalConfiguration.batch) {
@@ -1243,6 +1254,12 @@
var name = command.displayName;
return _getBatchRunner(command.displayName + command.dartFile)
.runCommand(name, command, timeout, command.arguments);
+ } else if (command is CompilationCommand &&
+ command.displayName == 'babel') {
+ return new RunningProcess(command, timeout,
+ configuration: globalConfiguration,
+ outputFile: io.File(command.outputFile))
+ .run();
} else if (command is ProcessCommand) {
return new RunningProcess(command, timeout,
configuration: globalConfiguration)
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index 6202455..f00c75d 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -141,12 +141,6 @@
Map<String, String> get environmentOverrides => _environmentOverrides;
/**
- * Whether or not binaries should be found in the root build directory or
- * in the built SDK.
- */
- bool get useSdk => configuration.useSdk;
-
- /**
* The output directory for this suite's configuration.
*/
String get buildDir => configuration.buildDirectory;
@@ -165,80 +159,6 @@
return name;
}
- /// Returns the name of the Dart VM executable.
- String get dartVmBinaryFileName {
- // Controlled by user with the option "--dart".
- var dartExecutable = configuration.dartPath;
-
- if (dartExecutable == null) {
- dartExecutable = dartVmExecutableFileName;
- }
-
- TestUtils.ensureExists(dartExecutable, configuration);
- return dartExecutable;
- }
-
- String get dartVmExecutableFileName {
- return useSdk
- ? '$buildDir/dart-sdk/bin/dart$executableBinarySuffix'
- : '$buildDir/dart$executableBinarySuffix';
- }
-
- String get dartPrecompiledBinaryFileName {
- // Controlled by user with the option "--dart_precompiled".
- var dartExecutable = configuration.dartPrecompiledPath;
-
- if (dartExecutable == null || dartExecutable == '') {
- var suffix = executableBinarySuffix;
- dartExecutable = '$buildDir/dart_precompiled_runtime$suffix';
- }
-
- TestUtils.ensureExists(dartExecutable, configuration);
- return dartExecutable;
- }
-
- String get processTestBinaryFileName {
- var suffix = executableBinarySuffix;
- var processTestExecutable = '$buildDir/process_test$suffix';
- TestUtils.ensureExists(processTestExecutable, configuration);
- return processTestExecutable;
- }
-
- String get d8FileName {
- var suffix = getExecutableSuffix('d8');
- var d8Dir = Repository.dir.append('third_party/d8');
- var d8Path = d8Dir.append('${Platform.operatingSystem}/d8$suffix');
- var d8 = d8Path.toNativePath();
- TestUtils.ensureExists(d8, configuration);
- return d8;
- }
-
- String get jsShellFileName {
- var executableSuffix = getExecutableSuffix('jsshell');
- var executable = 'jsshell$executableSuffix';
- var jsshellDir = '${Repository.dir.toNativePath()}/tools/testing/bin';
- return '$jsshellDir/$executable';
- }
-
- /**
- * The file extension (if any) that should be added to the given executable
- * name for the current platform.
- */
- // TODO(ahe): Get rid of this. Use executableBinarySuffix instead.
- String getExecutableSuffix(String executable) {
- if (Platform.operatingSystem == 'windows') {
- if (executable == 'd8' || executable == 'vm' || executable == 'none') {
- return '.exe';
- } else {
- return '.bat';
- }
- }
- return '';
- }
-
- String get executableBinarySuffix => Platform.isWindows ? '.exe' : '';
- String get executableScriptSuffix => Platform.isWindows ? '.bat' : '';
-
/**
* Call the callback function onTest with a [TestCase] argument for each
* test in the suite. When all tests have been processed, call [onDone].
@@ -585,7 +505,7 @@
extraVmOptions = configuration.vmOptions,
super(configuration, suiteName, statusFilePaths) {
// Initialize _dart2JsBootstrapDependencies
- if (!useSdk) {
+ if (!configuration.useSdk) {
_dart2JsBootstrapDependencies = [];
} else {
_dart2JsBootstrapDependencies = [
@@ -933,7 +853,6 @@
return commands
..addAll(configuration.runtimeConfiguration.computeRuntimeCommands(
- this,
compilationArtifact,
runtimeArguments,
environment,
@@ -1028,30 +947,28 @@
var fileName = info.filePath.toNativePath();
var optionsFromFile = info.optionsFromFile;
var compilationTempDir = createCompilationOutputDirectory(info.filePath);
- var jsWrapperFileName = '$compilationTempDir/test.js';
var nameNoExt = info.filePath.filenameWithoutExtension;
+ var outputDir = compilationTempDir;
+ var commonArguments =
+ commonArgumentsFromFile(info.filePath, optionsFromFile);
// Use existing HTML document if available.
String content;
var customHtml = new File(
info.filePath.directoryPath.append('$nameNoExt.html').toNativePath());
if (customHtml.existsSync()) {
- jsWrapperFileName = '$tempDir/$nameNoExt.js';
+ outputDir = tempDir;
content = customHtml.readAsStringSync().replaceAll(
'%TEST_SCRIPTS%', '<script src="$nameNoExt.js"></script>');
} else {
// Synthesize an HTML file for the test.
if (configuration.compiler == Compiler.dart2js) {
- var scriptPath = _createUrlPathFromFile(new Path(jsWrapperFileName));
+ var scriptPath = _createUrlPathFromFile(
+ new Path('$compilationTempDir/$nameNoExt.js'));
content = dart2jsHtml(fileName, scriptPath);
} else {
var jsDir =
new Path(compilationTempDir).relativeTo(Repository.dir).toString();
- jsWrapperFileName =
- new Path('$compilationTempDir/$nameNoExt.js').toNativePath();
- // Always run with synchronous starts of `async` functions.
- // If we want to make this dependent on other parameters or flags,
- // this flag could be become conditional.
content = dartdevcHtml(nameNoExt, jsDir, configuration.compiler);
}
}
@@ -1062,36 +979,21 @@
// Construct the command(s) that compile all the inputs needed by the
// browser test.
var commands = <Command>[];
+ const supportedCompilers = {
+ Compiler.dart2js,
+ Compiler.dartdevc,
+ Compiler.dartdevk
+ };
+ assert(supportedCompilers.contains(configuration.compiler));
+ var sharedOptions = optionsFromFile["sharedOptions"] as List<String>;
+ var dart2jsOptions = optionsFromFile["dart2jsOptions"] as List<String>;
+ var ddcOptions = optionsFromFile["ddcOptions"] as List<String>;
- void addCompileCommand(String fileName, String toPath) {
- switch (configuration.compiler) {
- case Compiler.dart2js:
- commands.add(_dart2jsCompileCommand(
- fileName, toPath, tempDir, optionsFromFile));
- break;
-
- case Compiler.dartdevc:
- case Compiler.dartdevk:
- var ddcOptions = optionsFromFile["sharedOptions"] as List<String>;
- ddcOptions.addAll(optionsFromFile["ddcOptions"] as List<String>);
- commands.add(configuration.compilerConfiguration.createCommand(
- fileName, toPath, ddcOptions, environmentOverrides));
- break;
-
- default:
- assert(false);
- }
- }
-
- addCompileCommand(fileName, jsWrapperFileName);
-
- // Some tests require compiling multiple input scripts.
- for (var name in optionsFromFile['otherScripts'] as List<String>) {
- var namePath = new Path(name);
- var fromPath = info.filePath.directoryPath.join(namePath).toNativePath();
- var toPath = new Path('$tempDir/${namePath.filename}.js').toNativePath();
- addCompileCommand(fromPath, toPath);
- }
+ var args = configuration.compilerConfiguration.computeCompilerArguments(
+ null, sharedOptions, null, dart2jsOptions, ddcOptions, commonArguments);
+ var compilation = configuration.compilerConfiguration
+ .computeCompilationArtifact(outputDir, args, environmentOverrides);
+ commands.addAll(compilation.commands);
if (info.optionsFromFile['isMultiHtmlTest'] as bool) {
// Variables for browser multi-tests.
@@ -1128,43 +1030,6 @@
enqueueNewTestCase(fullName, commands, expectations, info);
}
- /// Creates a [Command] to compile a single .dart file using dart2js.
- Command _dart2jsCompileCommand(String inputFile, String outputFile,
- String dir, Map<String, dynamic> optionsFromFile) {
- var args = <String>[];
-
- if (compilerPath.endsWith('.dart')) {
- // Run the compiler script via the Dart VM.
- args.add(compilerPath);
- }
-
- args.addAll(configuration.standardOptions);
- args.addAll(configuration.dart2jsOptions);
-
- var packages = packagesArgument(optionsFromFile['packageRoot'] as String,
- optionsFromFile['packages'] as String);
- if (packages != null) args.add(packages);
-
- args.add('--out=$outputFile');
- args.add(inputFile);
-
- var options = optionsFromFile['sharedOptions'] as List<String>;
- if (options != null) args.addAll(options);
- options = optionsFromFile['dart2jsOptions'] as List<String>;
- if (options != null) args.addAll(options);
- if (configuration.compiler == Compiler.dart2js) {
- if (configuration.noPreviewDart2) {
- args.add("--no-preview-dart-2");
- } else {
- args.add("--preview-dart-2");
- }
- }
-
- return Command.compilation(Compiler.dart2js.name, outputFile,
- dart2JsBootstrapDependencies, compilerPath, args, environmentOverrides,
- alwaysCompile: !useSdk);
- }
-
List<String> commonArgumentsFromFile(
Path filePath, Map<String, dynamic> optionsFromFile) {
var args = configuration.standardOptions.toList();
@@ -1185,14 +1050,6 @@
}
}
- if (configuration.compiler == Compiler.dart2js) {
- if (configuration.noPreviewDart2) {
- args.add("--no-preview-dart-2");
- } else {
- args.add("--preview-dart-2");
- }
- }
-
args.add(filePath.toNativePath());
return args;
@@ -1241,12 +1098,6 @@
* // Environment=ENV_VAR1=foo bar
* // Environment=ENV_VAR2=bazz
*
- * - For tests that depend on compiling other files with dart2js (e.g.
- * isolate tests that use multiple source scripts), you can specify
- * additional files to compile using a comment too, as follows:
- *
- * // OtherScripts=file1.dart file2.dart
- *
* - Most tests are not web tests, but can (and will be) wrapped within
* an HTML file and another script file to test them also on browser
* environments (e.g. language and corelib tests are run this way).
@@ -1272,7 +1123,6 @@
}
RegExp testOptionsRegExp = new RegExp(r"// VMOptions=(.*)");
RegExp environmentRegExp = new RegExp(r"// Environment=(.*)");
- RegExp otherScriptsRegExp = new RegExp(r"// OtherScripts=(.*)");
RegExp otherResourcesRegExp = new RegExp(r"// OtherResources=(.*)");
RegExp sharedObjectsRegExp = new RegExp(r"// SharedObjects=(.*)");
RegExp packageRootRegExp = new RegExp(r"// PackageRoot=(.*)");
@@ -1365,12 +1215,6 @@
}
}
- var otherScripts = <String>[];
- matches = otherScriptsRegExp.allMatches(contents);
- for (var match in matches) {
- otherScripts.addAll(wordSplit(match[1]));
- }
-
var otherResources = <String>[];
matches = otherResourcesRegExp.allMatches(contents);
for (var match in matches) {
@@ -1438,7 +1282,6 @@
"hasCompileError": hasCompileError,
"hasRuntimeError": hasRuntimeError,
"hasStaticWarning": hasStaticWarning,
- "otherScripts": otherScripts,
"otherResources": otherResources,
"sharedObjects": sharedObjects,
"isMultitest": isMultitest,
@@ -1461,7 +1304,6 @@
"hasCompileError": false,
"hasRuntimeError": false,
"hasStaticWarning": false,
- "otherScripts": const [],
"isMultitest": false,
"isMultiHtmlTest": false,
"subtestNames": const [],
diff --git a/utils/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 8ebfaee..5cd62a0 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -128,7 +128,9 @@
..addOption('output')
..addFlag('reuse-compiler-result', defaultsTo: false)
..addFlag('use-incremental-compiler', defaultsTo: false)
- ..addFlag('track-widget-creation', defaultsTo: false);
+ ..addFlag('track-widget-creation', defaultsTo: false)
+ ..addMultiOption('enable-experiment',
+ help: 'Enable a language experiment when invoking the CFE.');
class ComputeKernelResult {
final bool succeeded;
@@ -167,8 +169,7 @@
if (multiRoots.isEmpty) multiRoots.add(Uri.base);
var fileSystem = new MultiRootFileSystem(parsedArgs['multi-root-scheme'],
multiRoots, fe.StandardFileSystem.instance);
- var sources =
- (parsedArgs['source'] as List<String>).map(Uri.base.resolve).toList();
+ var sources = (parsedArgs['source'] as List<String>).map(_toUri).toList();
var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
var summaryOnly = parsedArgs['summary-only'] as bool;
@@ -222,19 +223,11 @@
out.writeln('error: unsupported target: $targetName');
}
- // TODO(sigmund,jakemac): make it mandatory. We allow null while we migrate
- // existing clients of this tool.
- var librariesSpec = parsedArgs['libraries-file'] == null
- ? null
- : Uri.base.resolve(parsedArgs['libraries-file']);
+ List<Uri> linkedInputs =
+ (parsedArgs['input-linked'] as List<String>).map(_toUri).toList();
- List<Uri> linkedInputs = (parsedArgs['input-linked'] as List<String>)
- .map(Uri.base.resolve)
- .toList();
-
- List<Uri> summaryInputs = (parsedArgs['input-summary'] as List<String>)
- .map(Uri.base.resolve)
- .toList();
+ List<Uri> summaryInputs =
+ (parsedArgs['input-summary'] as List<String>).map(_toUri).toList();
fe.InitializedCompilerState state;
bool usingIncrementalCompiler = false;
@@ -253,27 +246,30 @@
inputDigests[uri] = input.digest;
}
+ // TODO(sigmund): add support for experiments with the incremental compiler.
state = await fe.initializeIncrementalCompiler(
previousState,
- Uri.base.resolve(parsedArgs['dart-sdk-summary']),
- Uri.base.resolve(parsedArgs['packages-file']),
- librariesSpec,
+ _toUri(parsedArgs['dart-sdk-summary']),
+ _toUri(parsedArgs['packages-file']),
+ _toUri(parsedArgs['libraries-file']),
summaryInputs,
inputDigests,
target,
fileSystem,
+ (parsedArgs['enable-experiment'] as List<String>),
summaryOnly);
} else {
state = await fe.initializeCompiler(
// TODO(sigmund): pass an old state once we can make use of it.
null,
- Uri.base.resolve(parsedArgs['dart-sdk-summary']),
- librariesSpec,
- Uri.base.resolve(parsedArgs['packages-file']),
+ _toUri(parsedArgs['dart-sdk-summary']),
+ _toUri(parsedArgs['libraries-file']),
+ _toUri(parsedArgs['packages-file']),
summaryInputs,
linkedInputs,
target,
- fileSystem);
+ fileSystem,
+ (parsedArgs['enable-experiment'] as List<String>));
}
void onDiagnostic(fe.DiagnosticMessage message) {
@@ -299,8 +295,6 @@
return Future.value(fe.serializeComponent(incrementalComponent));
});
-
- state.options.onDiagnostic = null; // See http://dartbug.com/36983.
} else if (summaryOnly) {
kernel = await fe.compileSummary(state, sources, onDiagnostic,
includeOffsets: false);
@@ -308,9 +302,12 @@
Component component =
await fe.compileComponent(state, sources, onDiagnostic);
kernel = fe.serializeComponent(component,
- filter: (library) => sources.contains(library.importUri),
+ filter: excludeNonSources
+ ? (library) => sources.contains(library.importUri)
+ : null,
includeOffsets: true);
}
+ state.options.onDiagnostic = null; // See http://dartbug.com/36983.
if (kernel != null) {
var outputFile = new File(parsedArgs['output']);
@@ -365,3 +362,8 @@
}
}
}
+
+Uri _toUri(String uriString) {
+ if (uriString == null) return null;
+ return Uri.base.resolve(uriString);
+}
diff --git a/utils/dartdevc/BUILD.gn b/utils/dartdevc/BUILD.gn
index 767bdb9..0fe884f 100644
--- a/utils/dartdevc/BUILD.gn
+++ b/utils/dartdevc/BUILD.gn
@@ -18,7 +18,7 @@
"--dart-sdk",
rebase_path("../../sdk"),
"--dart-sdk-summary",
- rebase_path(sdk_summary),
+ rebase_path(sdk_dill),
"-k",
"-o",
"dartdevc.js",