Version 2.0.0-dev.41.0
Merge commit 'bd6f28f4c73dce33427aa7236d939292c1e5ff5f' into dev
diff --git a/.packages b/.packages
index f306f3b..2b26bb9 100644
--- a/.packages
+++ b/.packages
@@ -17,7 +17,7 @@
barback:third_party/pkg/barback/lib
bazel_worker:third_party/pkg/bazel_worker/lib
boolean_selector:third_party/pkg/boolean_selector/lib
-browser:pkg/browser/lib
+browser:third_party/pkg/browser/lib
charcode:third_party/pkg/charcode/lib
charted:third_party/observatory_pub_packages/packages/charted/lib
cli_util:third_party/pkg/cli_util/lib
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1522229..3db5bcd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,35 @@
+## 2.0.0-dev.41.0
+
+### Tool Changes
+
+#### Pub
+
+* Pub will now automatically retry HTTP requests that fail with an IO error
+ ([issue 1826][pub#1826]).
+
+* `pub deps` now includes the SDK version. This makes the output more helpful
+ when included in bug reports ([issue 1827][pub#1827]).
+
+* `build` and `serve` now print a deprecation warning pointing users to
+ https://webdev.dartlang.org/dart-2 ([issue 1823][pub#1823]).
+
+[pub#1823]: https://github.com/dart-lang/pub/issues/1823
+[pub#1826]: https://github.com/dart-lang/pub/issues/1826
+[pub#1827]: https://github.com/dart-lang/pub/issues/1827
+
## 2.0.0-dev.40.0
+### Core library changes
+
+* The Web libraries were re-genereated using Chrome 63 WebIDLs.
+ See https://github.com/dart-lang/sdk/wiki/Chrome-63-Dart-Web-Libraries for
+ details.
+
## 2.0.0-dev.39.0
### Tool Changes
#### Pub
- * fixed bug in dart2js transformer when using the common front-end.
-## 2.0.0-dev.38.0
+* fixed bug in dart2js transformer when using the common front-end.
## 2.0.0-dev.37.0
### Tool Changes
diff --git a/DEPS b/DEPS
index e30ca30..35dcf73 100644
--- a/DEPS
+++ b/DEPS
@@ -68,6 +68,7 @@
"crypto_tag" : "@2.0.2+1",
"csslib_tag" : "@0.14.1",
"dart2js_info_tag" : "@0.5.5+1",
+ "browser_tag" : "@0.10.0+2",
# Note: updates to dart_style have to be coordinated carefully with
# the infrastructure-team so that the internal formatter in
@@ -99,7 +100,7 @@
"isolate_tag": "@1.1.0",
"jinja2_rev": "@2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_tag": "@2.0.6",
- "linter_tag": "@0.1.44",
+ "linter_tag": "@0.1.45",
"logging_tag": "@0.11.3+1",
"markdown_tag": "@1.1.1",
"matcher_tag": "@0.12.1+4",
@@ -115,7 +116,7 @@
"ply_rev": "@604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_tag": "@1.3.4",
"protobuf_tag": "@0.7.1",
- "pub_rev": "@dbe8be2bb8bca9b26ba7bd583272c62f9a0153fd",
+ "pub_rev": "@875d35005a7d33f367d70a3e31e9d3bad5d1ebd8",
"pub_semver_tag": "@1.3.2",
"quiver_tag": "@5aaa3f58c48608af5b027444d561270b53f15dbf",
"resource_rev":"@af5a5bf65511943398146cf146e466e5f0b95cb9",
@@ -207,6 +208,9 @@
Var("dart_root") + "/third_party/pkg/boolean_selector":
Var("dart_git") + "boolean_selector.git" +
Var("boolean_selector_tag"),
+ Var("dart_root") + "/third_party/pkg/browser":
+ Var("dart_git") + "browser.git" +
+ Var("browser_tag"),
Var("dart_root") + "/third_party/pkg/charcode":
Var("dart_git") + "charcode.git" + Var("charcode_tag"),
Var("dart_root") + "/third_party/pkg/cli_util":
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 87a23ef..2338bbe 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -3920,7 +3920,7 @@
An enumeration of the kinds of refactorings that can be created.
</p>
- <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
+ <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">EXTRACT_WIDGET</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
<p>
A description of a parameter in a method refactoring.
@@ -4501,6 +4501,7 @@
+
<dl><dt class="refactoring">CONVERT_GETTER_TO_METHOD</dt><dd>
<p>
Convert a getter into a method by removing the keyword get
@@ -4684,6 +4685,24 @@
expression or statements used to initiate the
refactoring will always be replaced.
</p>
+ </dd></dl></dd><dt class="refactoring">EXTRACT_WIDGET</dt><dd>
+ <p>
+ Create a new class that extends either StatelessWidget or StatefulWidget,
+ whose build() method is the widget creation expression, or a method
+ returning a Flutter widget, at the specified offset.
+ </p>
+
+
+ <h4>Feedback:</h4><dl></dl><h4>Options:</h4><dl><dt class="field"><b>name: String</b></dt><dd>
+
+ <p>
+ The name that the widget class should be given.
+ </p>
+ </dd><dt class="field"><b>stateful: bool</b></dt><dd>
+
+ <p>
+ True if a StatefulWidget should be created.
+ </p>
</dd></dl></dd><dt class="refactoring">INLINE_LOCAL_VARIABLE</dt><dd>
<p>
Inline the initializer expression of a local variable in
@@ -4818,7 +4837,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></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</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.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_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</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_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_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</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_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_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></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</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.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_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</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_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_KytheEntry">KytheEntry</a></li><li><a href="#type_KytheVName">KytheVName</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_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/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index c5873a5..3a6949a 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -10893,6 +10893,158 @@
}
/**
+ * extractWidget feedback
+ *
+ * {
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExtractWidgetFeedback extends RefactoringFeedback {
+ ExtractWidgetFeedback();
+
+ factory ExtractWidgetFeedback.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ return new ExtractWidgetFeedback();
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "extractWidget feedback", json);
+ }
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExtractWidgetFeedback) {
+ return true;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
+ * extractWidget options
+ *
+ * {
+ * "name": String
+ * "stateful": bool
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class ExtractWidgetOptions extends RefactoringOptions {
+ String _name;
+
+ bool _stateful;
+
+ /**
+ * The name that the widget class should be given.
+ */
+ String get name => _name;
+
+ /**
+ * The name that the widget class should be given.
+ */
+ void set name(String value) {
+ assert(value != null);
+ this._name = value;
+ }
+
+ /**
+ * True if a StatefulWidget should be created.
+ */
+ bool get stateful => _stateful;
+
+ /**
+ * True if a StatefulWidget should be created.
+ */
+ void set stateful(bool value) {
+ assert(value != null);
+ this._stateful = value;
+ }
+
+ ExtractWidgetOptions(String name, bool stateful) {
+ this.name = name;
+ this.stateful = stateful;
+ }
+
+ factory ExtractWidgetOptions.fromJson(
+ JsonDecoder jsonDecoder, String jsonPath, Object json) {
+ if (json == null) {
+ json = {};
+ }
+ if (json is Map) {
+ String name;
+ if (json.containsKey("name")) {
+ name = jsonDecoder.decodeString(jsonPath + ".name", json["name"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "name");
+ }
+ bool stateful;
+ if (json.containsKey("stateful")) {
+ stateful =
+ jsonDecoder.decodeBool(jsonPath + ".stateful", json["stateful"]);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "stateful");
+ }
+ return new ExtractWidgetOptions(name, stateful);
+ } else {
+ throw jsonDecoder.mismatch(jsonPath, "extractWidget options", json);
+ }
+ }
+
+ factory ExtractWidgetOptions.fromRefactoringParams(
+ EditGetRefactoringParams refactoringParams, Request request) {
+ return new ExtractWidgetOptions.fromJson(
+ new RequestDecoder(request), "options", refactoringParams.options);
+ }
+
+ @override
+ Map<String, dynamic> toJson() {
+ Map<String, dynamic> result = {};
+ result["name"] = name;
+ result["stateful"] = stateful;
+ return result;
+ }
+
+ @override
+ String toString() => json.encode(toJson());
+
+ @override
+ bool operator ==(other) {
+ if (other is ExtractWidgetOptions) {
+ return name == other.name && stateful == other.stateful;
+ }
+ return false;
+ }
+
+ @override
+ int get hashCode {
+ int hash = 0;
+ hash = JenkinsSmiHash.combine(hash, name.hashCode);
+ hash = JenkinsSmiHash.combine(hash, stateful.hashCode);
+ return JenkinsSmiHash.finish(hash);
+ }
+}
+
+/**
* FileKind
*
* enum {
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 7f56676..c827e0f 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -647,16 +647,16 @@
/**
* Process [options] for the given context [info].
*/
- void processOptionsForDriver(ContextInfo info,
- AnalysisOptionsImpl analysisOptions, Map<String, Object> options) {
+ void processOptionsForDriver(
+ ContextInfo info, AnalysisOptionsImpl analysisOptions, YamlMap options) {
if (options == null) {
return;
}
// Check for embedded options.
- Map embeddedOptions = _getEmbeddedOptions(info);
+ YamlMap embeddedOptions = _getEmbeddedOptions(info);
if (embeddedOptions != null) {
- options = _toStringMap(new Merger().merge(embeddedOptions, options));
+ options = new Merger().merge(embeddedOptions, options);
}
applyToAnalysisOptions(analysisOptions, options);
@@ -1127,8 +1127,8 @@
ContextInfo info = new ContextInfo(this, parent, folder, packagesFile,
normalizedPackageRoots[folder.path], disposition);
- File optionsFile = null;
- Map<String, Object> optionMap = null;
+ File optionsFile;
+ YamlMap optionMap;
try {
AnalysisOptionsProvider provider =
_createAnalysisOptionsProvider(disposition.packages);
@@ -1306,7 +1306,7 @@
/// skipped.
///
/// Returns null if there are no embedded/configured options.
- Map _getEmbeddedOptions(ContextInfo info) {
+ YamlMap _getEmbeddedOptions(ContextInfo info) {
Map embeddedOptions = null;
EmbedderYamlLocator locator =
info.disposition.getEmbedderLocator(resourceProvider);
@@ -1630,25 +1630,6 @@
return false;
}
- /**
- * If the given [object] is a map, and all of the keys in the map are strings,
- * return a map containing the same mappings. Otherwise, return `null`.
- */
- Map<String, Object> _toStringMap(Object object) {
- if (object is Map) {
- Map<String, Object> stringMap = new HashMap<String, Object>();
- for (var key in object.keys) {
- if (key is String) {
- stringMap[key] = object[key];
- } else {
- return null;
- }
- }
- return stringMap;
- }
- return null;
- }
-
void _updateContextPackageUriResolver(Folder contextFolder) {
ContextInfo info = getContextInfoFor(contextFolder);
AnalysisDriver driver = info.analysisDriver;
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 7e96426..3d0f6d2 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -25,6 +25,7 @@
import 'package:analysis_server/src/services/correction/status.dart';
import 'package:analysis_server/src/services/refactoring/refactoring.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
@@ -207,11 +208,9 @@
}
Future getFixes(Request request) async {
- var params = new EditGetFixesParams.fromRequest(request);
+ EditGetFixesParams params = new EditGetFixesParams.fromRequest(request);
String file = params.file;
int offset = params.offset;
-
- List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
//
// Allow plugins to start computing fixes.
//
@@ -228,29 +227,12 @@
//
// Compute fixes associated with server-generated errors.
//
- AnalysisResult result = await server.getAnalysisResult(file);
- if (result != null) {
- CompilationUnit unit = result.unit;
- LineInfo lineInfo = result.lineInfo;
- int requestLine = lineInfo.getLocation(offset).lineNumber;
- for (engine.AnalysisError error in result.errors) {
- int errorLine = lineInfo.getLocation(error.offset).lineNumber;
- if (errorLine == requestLine) {
- var context = new _DartFixContextImpl(server.resourceProvider,
- result.driver, new AstProviderForDriver(driver), unit, error);
- List<Fix> fixes =
- await new DefaultFixContributor().internalComputeFixes(context);
- if (fixes.isNotEmpty) {
- fixes.sort(Fix.SORT_BY_RELEVANCE);
- AnalysisError serverError =
- newAnalysisError_fromEngine(lineInfo, error);
- AnalysisErrorFixes errorFixes = new AnalysisErrorFixes(serverError);
- errorFixesList.add(errorFixes);
- fixes.forEach((fix) {
- errorFixes.fixes.add(fix.change);
- });
- }
- }
+ List<AnalysisErrorFixes> errorFixesList = null;
+ while (errorFixesList == null) {
+ try {
+ errorFixesList = await _computeServerErrorFixes(driver, file, offset);
+ } on InconsistentAnalysisException {
+ // Loop around to try again to compute the fixes.
}
}
//
@@ -531,6 +513,41 @@
new EditSortMembersResult(fileEdit).toResponse(request.id));
}
+ /**
+ * Compute and return the fixes associated with server-generated errors.
+ */
+ Future<List<AnalysisErrorFixes>> _computeServerErrorFixes(
+ AnalysisDriver driver, String file, int offset) async {
+ List<AnalysisErrorFixes> errorFixesList = <AnalysisErrorFixes>[];
+ AnalysisResult result = await server.getAnalysisResult(file);
+ if (result != null) {
+ CompilationUnit unit = result.unit;
+ LineInfo lineInfo = result.lineInfo;
+ int requestLine = lineInfo.getLocation(offset).lineNumber;
+ for (engine.AnalysisError error in result.errors) {
+ int errorLine = lineInfo.getLocation(error.offset).lineNumber;
+ if (errorLine == requestLine) {
+ AstProvider astProvider = new AstProviderForDriver(driver);
+ DartFixContext context = new _DartFixContextImpl(
+ server.resourceProvider, result.driver, astProvider, unit, error);
+ List<Fix> fixes =
+ await new DefaultFixContributor().internalComputeFixes(context);
+ if (fixes.isNotEmpty) {
+ fixes.sort(Fix.SORT_BY_RELEVANCE);
+ AnalysisError serverError =
+ newAnalysisError_fromEngine(lineInfo, error);
+ AnalysisErrorFixes errorFixes = new AnalysisErrorFixes(serverError);
+ errorFixesList.add(errorFixes);
+ fixes.forEach((fix) {
+ errorFixes.fixes.add(fix.change);
+ });
+ }
+ }
+ }
+ }
+ return errorFixesList;
+ }
+
Response _getAvailableRefactorings(Request request) {
_getAvailableRefactoringsImpl(request);
return Response.DELAYED_RESPONSE;
diff --git a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
index 19c6740..a36fc49 100644
--- a/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
+++ b/pkg/analysis_server/lib/src/protocol/protocol_internal.dart
@@ -193,6 +193,9 @@
if (kind == RefactoringKind.EXTRACT_METHOD) {
return new ExtractMethodFeedback.fromJson(jsonDecoder, jsonPath, json);
}
+ if (kind == RefactoringKind.EXTRACT_WIDGET) {
+ return new ExtractWidgetFeedback.fromJson(jsonDecoder, jsonPath, json);
+ }
if (kind == RefactoringKind.INLINE_LOCAL_VARIABLE) {
return new InlineLocalVariableFeedback.fromJson(
jsonDecoder, jsonPath, json);
@@ -218,6 +221,9 @@
if (kind == RefactoringKind.EXTRACT_METHOD) {
return new ExtractMethodOptions.fromJson(jsonDecoder, jsonPath, json);
}
+ if (kind == RefactoringKind.EXTRACT_WIDGET) {
+ return new ExtractWidgetOptions.fromJson(jsonDecoder, jsonPath, json);
+ }
if (kind == RefactoringKind.INLINE_METHOD) {
return new InlineMethodOptions.fromJson(jsonDecoder, jsonPath, json);
}
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 446edf9..15b3600 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -22,6 +22,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/java_core.dart';
@@ -46,6 +47,16 @@
*/
AnalysisDriver driver;
+ /**
+ * The analysis session to be used to create the change builder.
+ */
+ AnalysisSession session;
+
+ /**
+ * The helper wrapper around the [session].
+ */
+ AnalysisSessionHelper sessionHelper;
+
Source source;
String file;
@@ -68,10 +79,10 @@
TypeProvider _typeProvider;
- final Map<String, LibraryElement> libraryCache = {};
-
AssistProcessor(DartAssistContext dartContext) {
driver = dartContext.analysisDriver;
+ session = driver.currentSession;
+ sessionHelper = new AnalysisSessionHelper(session);
// source
source = dartContext.source;
file = dartContext.source.fullName;
@@ -95,11 +106,6 @@
*/
String get eol => utils.endOfLine;
- /**
- * Return the analysis session to be used to create the change builder.
- */
- AnalysisSession get session => driver.currentSession;
-
TypeProvider get typeProvider {
if (_typeProvider == null) {
_typeProvider = unitElement.context.typeProvider;
@@ -1394,10 +1400,13 @@
}));
buildText = SourceEdit.applySequence(buildText, buildTextEdits.reversed);
- var statefulWidgetClass =
- await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'StatefulWidget');
+ var statefulWidgetClass = await sessionHelper.getClass(
+ flutter.WIDGETS_LIBRARY_URI, 'StatefulWidget');
var stateClass =
- await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'State');
+ await sessionHelper.getClass(flutter.WIDGETS_LIBRARY_URI, 'State');
+ if (statefulWidgetClass == null || stateClass == null) {
+ return;
+ }
var stateType = stateClass.type.instantiate([widgetClassElement.type]);
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -1658,7 +1667,10 @@
ClassElement parentClassElement;
if (parentLibraryUri != null && parentClassName != null) {
parentClassElement =
- await _getExportedClass(parentLibraryUri, parentClassName);
+ await sessionHelper.getClass(parentLibraryUri, parentClassName);
+ if (parentClassElement == null) {
+ return;
+ }
}
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
@@ -1735,9 +1747,12 @@
@required String parentLibraryUri,
@required String parentClassName}) async {
ClassElement parentClassElement =
- await _getExportedClass(parentLibraryUri, parentClassName);
+ await sessionHelper.getClass(parentLibraryUri, parentClassName);
ClassElement widgetClassElement =
- await _getExportedClass(flutter.WIDGETS_LIBRARY_URI, 'Widget');
+ await sessionHelper.getClass(flutter.WIDGETS_LIBRARY_URI, 'Widget');
+ if (parentClassElement == null || widgetClassElement == null) {
+ return;
+ }
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
@@ -2968,20 +2983,6 @@
}
}
- /// Return the [ClassElement] with the given [className] that is exported
- /// from the library with the given [libraryUri], or `null` if the libary
- /// does not export a class with such name.
- Future<ClassElement> _getExportedClass(
- String libraryUri, String className) async {
- var libraryElement = await session.getLibraryByUri(libraryUri);
- var element = libraryElement.exportNamespace.get(className);
- if (element is ClassElement) {
- return element;
- } else {
- return null;
- }
- }
-
/**
* Returns the text of the given node in the unit.
*/
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 7c28a08..bb4a3b3 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -514,16 +514,36 @@
} else if (parent is VariableDeclaration && target == parent.initializer) {
toType = parent.name.staticType;
} else {
+ // TODO(brianwilkerson) Handle function arguments.
return;
}
- // TODO(brianwilkerson) I think it's more efficient to invoke `cast` before
- // invoking `toList()`, so check to see whether the cast should be inserted
- // before the end of the expression.
- // TODO(brianwilkerson) We should not produce a fix if the target is an
- // invocation of the `cast` method.
+ // TODO(brianwilkerson) Handle `toSet` in a manner similar to the below.
+ if (_isToListMethodInvocation(target)) {
+ Expression targetTarget = (target as MethodInvocation).target;
+ if (targetTarget != null) {
+ DartType targetTargetType = targetTarget.staticType;
+ if (_isDartCoreIterable(targetTargetType) ||
+ _isDartCoreList(targetTargetType) ||
+ _isDartCoreMap(targetTargetType) ||
+ _isDartCoreSet(targetTargetType)) {
+ target = targetTarget;
+ fromType = targetTargetType;
+ }
+ }
+ }
+ if (target is AsExpression) {
+ // TODO(brianwilkerson) Consider updating the right operand.
+ return;
+ }
bool needsParentheses = target.precedence < 15;
- if ((_isDartCoreList(fromType) && _isDartCoreList(toType)) ||
+ if (((_isDartCoreIterable(fromType) || _isDartCoreList(fromType)) &&
+ _isDartCoreList(toType)) ||
(_isDartCoreSet(fromType) && _isDartCoreSet(toType))) {
+ if (_isCastMethodInvocation(target)) {
+ // TODO(brianwilkerson) Consider updating the type arguments to the
+ // `cast` invocation.
+ return;
+ }
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
if (needsParentheses) {
@@ -540,6 +560,11 @@
});
_addFixFromBuilder(changeBuilder, DartFixKind.ADD_EXPLICIT_CAST);
} else if (_isDartCoreMap(fromType) && _isDartCoreMap(toType)) {
+ if (_isCastMethodInvocation(target)) {
+ // TODO(brianwilkerson) Consider updating the type arguments to the
+ // `cast` invocation.
+ return;
+ }
DartChangeBuilder changeBuilder = new DartChangeBuilder(session);
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
if (needsParentheses) {
@@ -3428,38 +3453,50 @@
return node is SimpleIdentifier && node.name == 'await';
}
- bool _isDartCoreList(DartType type) {
- if (type is! InterfaceType) {
+ bool _isCastMethodElement(MethodElement method) {
+ if (method.name != 'cast') {
return false;
}
- ClassElement element = type.element;
- if (element == null) {
- return false;
- }
- return element.name == "List" && element.library.isDartCore;
+ ClassElement definingClass = method.enclosingElement;
+ return _isDartCoreIterableElement(definingClass) ||
+ _isDartCoreListElement(definingClass) ||
+ _isDartCoreMapElement(definingClass) ||
+ _isDartCoreSetElement(definingClass);
}
- bool _isDartCoreMap(DartType type) {
- if (type is! InterfaceType) {
- return false;
+ bool _isCastMethodInvocation(Expression expression) {
+ if (expression is MethodInvocation) {
+ Element element = expression.methodName.staticElement;
+ return element is MethodElement && _isCastMethodElement(element);
}
- ClassElement element = type.element;
- if (element == null) {
- return false;
- }
- return element.name == "Map" && element.library.isDartCore;
+ return false;
}
- bool _isDartCoreSet(DartType type) {
- if (type is! InterfaceType) {
- return false;
- }
- ClassElement element = type.element;
- if (element == null) {
- return false;
- }
- return element.name == "Set" && element.library.isDartCore;
- }
+ bool _isDartCoreIterable(DartType type) =>
+ type is InterfaceType && _isDartCoreIterableElement(type.element);
+
+ bool _isDartCoreIterableElement(ClassElement element) =>
+ element != null &&
+ element.name == "Iterable" &&
+ element.library.isDartCore;
+
+ bool _isDartCoreList(DartType type) =>
+ type is InterfaceType && _isDartCoreListElement(type.element);
+
+ bool _isDartCoreListElement(ClassElement element) =>
+ element != null && element.name == "List" && element.library.isDartCore;
+
+ bool _isDartCoreMap(DartType type) =>
+ type is InterfaceType && _isDartCoreMapElement(type.element);
+
+ bool _isDartCoreMapElement(ClassElement element) =>
+ element != null && element.name == "Map" && element.library.isDartCore;
+
+ bool _isDartCoreSet(DartType type) =>
+ type is InterfaceType && _isDartCoreSetElement(type.element);
+
+ bool _isDartCoreSetElement(ClassElement element) =>
+ element != null && element.name == "Set" && element.library.isDartCore;
bool _isLibSrcPath(String path) {
List<String> parts = resourceProvider.pathContext.split(path);
@@ -3495,6 +3532,23 @@
return true;
}
+ bool _isToListMethodElement(MethodElement method) {
+ if (method.name != 'toList') {
+ return false;
+ }
+ ClassElement definingClass = method.enclosingElement;
+ return _isDartCoreIterableElement(definingClass) ||
+ _isDartCoreListElement(definingClass);
+ }
+
+ bool _isToListMethodInvocation(Expression expression) {
+ if (expression is MethodInvocation) {
+ Element element = expression.methodName.staticElement;
+ return element is MethodElement && _isToListMethodElement(element);
+ }
+ return false;
+ }
+
/**
* Removes any [ParenthesizedExpression] enclosing [expr].
*
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
new file mode 100644
index 0000000..fae6127
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -0,0 +1,426 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:analysis_server/src/protocol_server.dart' hide Element;
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/correction/util.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring_internal.dart';
+import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/analyzer.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:analyzer/src/generated/source.dart' show SourceRange;
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+/// [ExtractWidgetRefactoring] implementation.
+class ExtractWidgetRefactoringImpl extends RefactoringImpl
+ implements ExtractWidgetRefactoring {
+ final SearchEngine searchEngine;
+ final AnalysisSessionHelper sessionHelper;
+ final CompilationUnit unit;
+ final int offset;
+
+ CompilationUnitElement unitElement;
+ LibraryElement libraryElement;
+ CorrectionUtils utils;
+
+ ClassElement classBuildContext;
+ ClassElement classStatefulWidget;
+ ClassElement classStatelessWidget;
+ ClassElement classWidget;
+
+ @override
+ String name;
+
+ @override
+ bool stateful = false;
+
+ /// If [offset] is in a class, the node of this class, `null` otherwise.
+ ClassDeclaration _enclosingClassNode;
+
+ /// If [offset] is in a class, the element of this class, `null` otherwise.
+ ClassElement _enclosingClassElement;
+
+ /// The [CompilationUnitMember] that encloses the [offset].
+ CompilationUnitMember _enclosingUnitMember;
+
+ /// The widget creation expression to extract.
+ InstanceCreationExpression _expression;
+
+ /// The method returning widget to extract.
+ MethodDeclaration _method;
+
+ /// The parameters for the new widget class - referenced fields of the
+ /// [_enclosingClassElement], local variables referenced by [_expression],
+ /// and [_method] parameters.
+ List<_Parameter> _parameters = [];
+
+ ExtractWidgetRefactoringImpl(
+ this.searchEngine, AnalysisSession session, this.unit, this.offset)
+ : sessionHelper = new AnalysisSessionHelper(session) {
+ unitElement = unit.element;
+ libraryElement = unitElement.library;
+ utils = new CorrectionUtils(unit);
+ }
+
+ @override
+ String get refactoringName {
+ return 'Extract Widget';
+ }
+
+ @override
+ Future<RefactoringStatus> checkFinalConditions() async {
+ RefactoringStatus result = new RefactoringStatus();
+ result.addStatus(validateClassName(name));
+ return result;
+ }
+
+ @override
+ Future<RefactoringStatus> checkInitialConditions() async {
+ RefactoringStatus result = new RefactoringStatus();
+
+ result.addStatus(_checkSelection());
+ if (result.hasFatalError) {
+ return result;
+ }
+
+ _enclosingUnitMember = (_expression ?? _method).getAncestor(
+ (n) => n is CompilationUnitMember && n.parent is CompilationUnit);
+
+ result.addStatus(await _initializeParameters());
+ result.addStatus(await _initializeClasses());
+
+ return result;
+ }
+
+ @override
+ RefactoringStatus checkName() {
+ return validateClassName(name);
+ }
+
+ @override
+ Future<SourceChange> createChange() async {
+ String file = unitElement.source.fullName;
+ var changeBuilder = new DartChangeBuilder(sessionHelper.session);
+ await changeBuilder.addFileEdit(file, (builder) {
+ if (_expression != null) {
+ builder.addReplacement(range.node(_expression), (builder) {
+ _writeWidgetInstantiation(builder);
+ });
+ } else {
+ _removeMethodDeclaration(builder);
+ _replaceInvocationsWithInstantiations(builder);
+ }
+
+ _writeWidgetDeclaration(builder);
+ });
+ return changeBuilder.sourceChange;
+ }
+
+ @override
+ bool requiresPreview() => false;
+
+ /// Checks if [offset] is a widget creation expression that can be extracted.
+ RefactoringStatus _checkSelection() {
+ AstNode node = new NodeLocator2(offset, offset).searchWithin(unit);
+
+ // Find the enclosing class.
+ _enclosingClassNode = node?.getAncestor((n) => n is ClassDeclaration);
+ _enclosingClassElement = _enclosingClassNode?.element;
+
+ // new MyWidget(...)
+ if (node is InstanceCreationExpression && isWidgetCreation(node)) {
+ _expression = node;
+ return new RefactoringStatus();
+ }
+
+ // Widget myMethod(...) { ... }
+ for (; node != null; node = node.parent) {
+ if (node is FunctionBody) {
+ break;
+ }
+ if (node is MethodDeclaration) {
+ DartType returnType = node.returnType?.type;
+ if (isWidgetType(returnType) && node.body != null) {
+ _method = node;
+ return new RefactoringStatus();
+ }
+ break;
+ }
+ }
+
+ // Invalid selection.
+ return new RefactoringStatus.fatal(
+ 'Can only extract a widget expression or a method returning widget.');
+ }
+
+ Future<RefactoringStatus> _initializeClasses() async {
+ var result = new RefactoringStatus();
+
+ Future<ClassElement> getClass(String name) async {
+ const uri = 'package:flutter/widgets.dart';
+ var element = await sessionHelper.getClass(uri, name);
+ if (element == null) {
+ result.addFatalError("Unable to find '$name' in $uri");
+ }
+ return element;
+ }
+
+ classBuildContext = await getClass('BuildContext');
+ classStatelessWidget = await getClass('StatelessWidget');
+ classStatefulWidget = await getClass('StatefulWidget');
+ classWidget = await getClass('Widget');
+
+ return result;
+ }
+
+ /// Prepare referenced local variables and fields, that should be turned
+ /// into the widget class fields and constructor parameters.
+ Future<RefactoringStatus> _initializeParameters() async {
+ _ParametersCollector collector;
+ if (_expression != null) {
+ SourceRange localRange = range.node(_expression);
+ collector = new _ParametersCollector(_enclosingClassElement, localRange);
+ _expression.accept(collector);
+ }
+ if (_method != null) {
+ SourceRange localRange = range.node(_method);
+ collector = new _ParametersCollector(_enclosingClassElement, localRange);
+ _method.body.accept(collector);
+ }
+
+ _parameters
+ ..clear()
+ ..addAll(collector.parameters);
+
+ // We added fields, now add the method parameters.
+ if (_method != null) {
+ for (var parameter in _method.parameters.parameters) {
+ if (parameter is NormalFormalParameter) {
+ _parameters.add(new _Parameter(
+ parameter.identifier.name, parameter.element.type,
+ isMethodParameter: true));
+ }
+ }
+ }
+
+ return collector.status;
+ }
+
+ /// Remove the [_method] declaration.
+ void _removeMethodDeclaration(DartFileEditBuilder builder) {
+ SourceRange methodRange = range.node(_method);
+ SourceRange linesRange =
+ utils.getLinesRange(methodRange, skipLeadingEmptyLines: true);
+ builder.addDeletion(linesRange);
+ }
+
+ /// Replace invocations of the [_method] with instantiations of the new
+ /// widget class.
+ void _replaceInvocationsWithInstantiations(DartFileEditBuilder builder) {
+ var collector = new _MethodInvocationsCollector(_method.element);
+ _enclosingClassNode.accept(collector);
+ for (var invocation in collector.invocations) {
+ builder.addReplacement(
+ range.startEnd(invocation, invocation.argumentList.leftParenthesis),
+ (builder) {
+ builder.write('new $name(');
+
+ // Insert field references.
+ for (var parameter in _parameters) {
+ if (parameter.isMethodParameter) {
+ break;
+ }
+ if (parameter != _parameters.first) {
+ builder.write(', ');
+ }
+ builder.write(parameter.name);
+ }
+
+ // Separate references to fields and method arguments.
+ if (_parameters.isNotEmpty &&
+ invocation.argumentList.arguments.isNotEmpty) {
+ builder.write(', ');
+ }
+ },
+ );
+ }
+ }
+
+ /// Write declaration of the new widget class.
+ void _writeWidgetDeclaration(DartFileEditBuilder builder) {
+ builder.addInsertion(_enclosingUnitMember.end, (builder) {
+ builder.writeln();
+ builder.writeln();
+ builder.writeClassDeclaration(
+ name,
+ superclass: classStatelessWidget.type,
+ membersWriter: () {
+ if (_parameters.isNotEmpty) {
+ // Add the fields for the parameters.
+ for (var parameter in _parameters) {
+ builder.write(' ');
+ builder.writeFieldDeclaration(parameter.name,
+ isFinal: true, type: parameter.type);
+ builder.writeln();
+ }
+ builder.writeln();
+
+ // Add the constructor.
+ builder.write(' ');
+ builder.writeConstructorDeclaration(name,
+ fieldNames: _parameters.map((e) => e.name).toList());
+ builder.writeln();
+ builder.writeln();
+ }
+
+ // Widget build(BuildContext context) { ... }
+ builder.writeln(' @override');
+ builder.write(' ');
+ builder.writeFunctionDeclaration(
+ 'build',
+ returnType: classWidget.type,
+ parameterWriter: () {
+ builder.writeParameter('context', type: classBuildContext.type);
+ },
+ bodyWriter: () {
+ if (_expression != null) {
+ String indentOld = utils.getLinePrefix(_expression.offset);
+ String indentNew = ' ';
+
+ String code = utils.getNodeText(_expression);
+ code = code.replaceAll(
+ new RegExp('^$indentOld', multiLine: true), indentNew);
+
+ builder.writeln('{');
+
+ builder.write(' return ');
+ builder.write(code);
+ builder.writeln(';');
+
+ builder.writeln(' }');
+ } else {
+ String code = utils.getNodeText(_method.body);
+ builder.writeln(code);
+ }
+ },
+ );
+ },
+ );
+ });
+ }
+
+ /// Write instantiation of the new widget class.
+ void _writeWidgetInstantiation(DartEditBuilder builder) {
+ builder.write('new $name(');
+
+ for (var parameter in _parameters) {
+ if (parameter != _parameters.first) {
+ builder.write(', ');
+ }
+ builder.write(parameter.name);
+ }
+
+ builder.write(')');
+ }
+}
+
+class _MethodInvocationsCollector extends RecursiveAstVisitor<void> {
+ final MethodElement methodElement;
+ final List<MethodInvocation> invocations = [];
+
+ _MethodInvocationsCollector(this.methodElement);
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ if (node.methodName?.staticElement == methodElement) {
+ invocations.add(node);
+ } else {
+ super.visitMethodInvocation(node);
+ }
+ }
+}
+
+class _Parameter {
+ final String name;
+ final DartType type;
+
+ /// Whether the parameter is a parameter of the method being extracted.
+ final bool isMethodParameter;
+
+ _Parameter(this.name, this.type, {this.isMethodParameter = false});
+}
+
+class _ParametersCollector extends RecursiveAstVisitor<void> {
+ final ClassElement enclosingClass;
+ final SourceRange expressionRange;
+
+ final RefactoringStatus status = new RefactoringStatus();
+ final List<_Parameter> parameters = [];
+
+ List<ClassElement> enclosingClasses;
+
+ _ParametersCollector(this.enclosingClass, this.expressionRange);
+
+ @override
+ void visitSimpleIdentifier(SimpleIdentifier node) {
+ Element element = node.staticElement;
+ if (element == null) {
+ return;
+ }
+ String elementName = element.displayName;
+
+ DartType type;
+ if (element is MethodElement) {
+ if (_isMemberOfEnclosingClass(element)) {
+ status.addError(
+ "Reference to an enclosing class method cannot be extracted.");
+ }
+ } else if (element is LocalVariableElement) {
+ if (!expressionRange.contains(element.nameOffset)) {
+ if (node.inSetterContext()) {
+ status.addError("Write to '$elementName' cannot be extracted.");
+ } else {
+ type = element.type;
+ }
+ }
+ } else if (element is PropertyAccessorElement) {
+ PropertyInducingElement field = element.variable;
+ if (_isMemberOfEnclosingClass(field)) {
+ if (node.inSetterContext()) {
+ status.addError("Write to '$elementName' cannot be extracted.");
+ } else {
+ type = field.type;
+ }
+ }
+ }
+
+ if (type != null) {
+ parameters.add(new _Parameter(elementName, type));
+ }
+ }
+
+ /// Return `true` if the given [element] is a member of the [enclosingClass]
+ /// or one of its supertypes, interfaces, or mixins.
+ bool _isMemberOfEnclosingClass(Element element) {
+ if (enclosingClass != null) {
+ if (enclosingClasses == null) {
+ enclosingClasses = <ClassElement>[]
+ ..add(enclosingClass)
+ ..addAll(enclosingClass.allSupertypes.map((t) => t.element));
+ }
+ return enclosingClasses.contains(element.enclosingElement);
+ }
+ return false;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
index 1e51c6f..e336845 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/refactoring.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/services/refactoring/convert_method_to_getter.dart';
import 'package:analysis_server/src/services/refactoring/extract_local.dart';
import 'package:analysis_server/src/services/refactoring/extract_method.dart';
+import 'package:analysis_server/src/services/refactoring/extract_widget.dart';
import 'package:analysis_server/src/services/refactoring/inline_local.dart';
import 'package:analysis_server/src/services/refactoring/inline_method.dart';
import 'package:analysis_server/src/services/refactoring/rename_class_member.dart';
@@ -19,6 +20,7 @@
import 'package:analysis_server/src/services/refactoring/rename_local.dart';
import 'package:analysis_server/src/services/refactoring/rename_unit_member.dart';
import 'package:analysis_server/src/services/search/search_engine.dart';
+import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dart/element/ast_provider.dart';
@@ -220,6 +222,43 @@
}
/**
+ * [Refactoring] to extract a widget creation expression or a method returning
+ * a widget, into a new stateless or stateful widget.
+ */
+abstract class ExtractWidgetRefactoring implements Refactoring {
+ /**
+ * Returns a new [ExtractWidgetRefactoring] instance.
+ */
+ factory ExtractWidgetRefactoring(SearchEngine searchEngine,
+ AnalysisSession session, CompilationUnit unit, int offset) {
+ return new ExtractWidgetRefactoringImpl(
+ searchEngine, session, unit, offset);
+ }
+
+ /**
+ * The name that the class should be given.
+ */
+ void set name(String name);
+
+ /**
+ * Set to `true` if a subclass of `StatefulWidget` should be extracted,
+ * otherwise a subclass of `StatelessWidget` will be extracted.
+ */
+ void set stateful(bool stateful);
+
+ /**
+ * Validates that the [name] is a valid identifier and is appropriate for a
+ * class.
+ *
+ * It does not perform all the checks (such as checking for conflicts with any
+ * existing names in any of the scopes containing the current name), as many
+ * of these checks require search engine. Use [checkFinalConditions] for this
+ * level of checking.
+ */
+ RefactoringStatus checkName();
+}
+
+/**
* [Refactoring] to inline a local [VariableElement].
*/
abstract class InlineLocalRefactoring implements Refactoring {
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index b9727e8..f97f086 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -1816,6 +1816,12 @@
@reflectiveTest
class ContextManagerWithNewOptionsTest extends ContextManagerWithOptionsTest {
String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
+
+ @failingTest
+ test_analysis_options_parse_failure() async {
+ // We have lost the ability to detect errors of this form.
+ return super.test_analysis_options_parse_failure();
+ }
}
@reflectiveTest
@@ -2172,6 +2178,27 @@
expect(errorProcessors, isEmpty);
}
+ test_non_analyzable_files_not_considered() async {
+ // Set up project and get a reference to the driver.
+ manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+ Folder projectFolder = resourceProvider.newFolder(projPath);
+ var drivers = manager.getDriversInAnalysisRoot(projectFolder);
+ expect(drivers, hasLength(1));
+
+ // Add the driver to the manager so that it will receive the events.
+ manager.driverMap[projectFolder] = drivers[0];
+
+ // Ensure adding a file that shouldn't be analyzed is not picked up.
+ newFile('$projPath/test.txt');
+ await pumpEventQueue();
+ expect(drivers[0].hasFilesToAnalyze, false);
+
+ // Ensure modifying a file that shouldn't be analyzed is not picked up.
+ modifyFile('$projPath/test.txt', 'new content');
+ await pumpEventQueue();
+ expect(drivers[0].hasFilesToAnalyze, false);
+ }
+
@failingTest
test_optionsFile_update_strongMode() async {
// It appears that this fails because we are not correctly updating the
@@ -2432,27 +2459,6 @@
await new Future.delayed(new Duration(milliseconds: 1));
expect(callbacks.watchEvents, hasLength(1));
}
-
- test_non_analyzable_files_not_considered() async {
- // Set up project and get a reference to the driver.
- manager.setRoots(<String>[projPath], <String>[], <String, String>{});
- Folder projectFolder = resourceProvider.newFolder(projPath);
- var drivers = manager.getDriversInAnalysisRoot(projectFolder);
- expect(drivers, hasLength(1));
-
- // Add the driver to the manager so that it will receive the events.
- manager.driverMap[projectFolder] = drivers[0];
-
- // Ensure adding a file that shouldn't be analyzed is not picked up.
- newFile('$projPath/test.txt');
- await pumpEventQueue();
- expect(drivers[0].hasFilesToAnalyze, false);
-
- // Ensure modifying a file that shouldn't be analyzed is not picked up.
- modifyFile('$projPath/test.txt', 'new content');
- await pumpEventQueue();
- expect(drivers[0].hasFilesToAnalyze, false);
- }
}
class TestContextManagerCallbacks extends ContextManagerCallbacks {
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ae078f3..42db016 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1098,6 +1098,7 @@
* CONVERT_METHOD_TO_GETTER
* EXTRACT_LOCAL_VARIABLE
* EXTRACT_METHOD
+ * EXTRACT_WIDGET
* INLINE_LOCAL_VARIABLE
* INLINE_METHOD
* MOVE_FILE
@@ -1110,6 +1111,7 @@
"CONVERT_METHOD_TO_GETTER",
"EXTRACT_LOCAL_VARIABLE",
"EXTRACT_METHOD",
+ "EXTRACT_WIDGET",
"INLINE_LOCAL_VARIABLE",
"INLINE_METHOD",
"MOVE_FILE",
@@ -2463,6 +2465,27 @@
}));
/**
+ * extractWidget feedback
+ *
+ * {
+ * }
+ */
+final Matcher isExtractWidgetFeedback = new LazyMatcher(
+ () => new MatchesJsonObject("extractWidget feedback", null));
+
+/**
+ * extractWidget options
+ *
+ * {
+ * "name": String
+ * "stateful": bool
+ * }
+ */
+final Matcher isExtractWidgetOptions = new LazyMatcher(() =>
+ new MatchesJsonObject(
+ "extractWidget options", {"name": isString, "stateful": isBool}));
+
+/**
* flutter.outline params
*
* {
diff --git a/pkg/analysis_server/test/services/correction/fix_test.dart b/pkg/analysis_server/test/services/correction/fix_test.dart
index 486a6a6..0f23257 100644
--- a/pkg/analysis_server/test/services/correction/fix_test.dart
+++ b/pkg/analysis_server/test/services/correction/fix_test.dart
@@ -416,7 +416,7 @@
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
List<B> b;
- b = a.where((e) => e is B).toList().cast<B>();
+ b = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
@@ -484,6 +484,29 @@
''');
}
+ test_addExplicitCast_BAD_as() async {
+ await resolveTestUnit('''
+f(A a) {
+ C c = a as B;
+}
+class A {}
+class B {}
+class C {}
+''');
+ await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
+ }
+
+ test_addExplicitCast_BAD_cast() async {
+ await resolveTestUnit('''
+f(List<A> a) {
+ List<B> b = a.cast<A>();
+}
+class A {}
+class B {}
+''');
+ await assertNoFix(DartFixKind.ADD_EXPLICIT_CAST);
+ }
+
test_addExplicitCast_declaration_general() async {
await resolveTestUnit('''
f(A a) {
@@ -511,7 +534,7 @@
''');
await assertHasFix(DartFixKind.ADD_EXPLICIT_CAST, '''
f(List<A> a) {
- List<B> b = a.where((e) => e is B).toList().cast<B>();
+ List<B> b = a.where((e) => e is B).cast<B>().toList();
}
class A {}
class B {}
diff --git a/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
new file mode 100644
index 0000000..98bdf4e
--- /dev/null
+++ b/pkg/analysis_server/test/services/refactoring/extract_widget_test.dart
@@ -0,0 +1,827 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/extract_widget.dart';
+import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'abstract_refactoring.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ExtractWidgetTest);
+ });
+}
+
+@reflectiveTest
+class ExtractWidgetTest extends RefactoringTest {
+ ExtractWidgetRefactoringImpl refactoring;
+
+ test_checkAllConditions_selection() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+class C {}
+''');
+ _createRefactoringForStringOffset('class C');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.FATAL);
+ }
+
+ test_checkName() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text('AAA');
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ // null
+ refactoring.name = null;
+ assertRefactoringStatus(
+ refactoring.checkName(), RefactoringProblemSeverity.FATAL,
+ expectedMessage: 'Class name must not be null.');
+
+ // empty
+ refactoring.name = '';
+ assertRefactoringStatus(
+ refactoring.checkName(), RefactoringProblemSeverity.FATAL,
+ expectedMessage: 'Class name must not be empty.');
+
+ // OK
+ refactoring.name = 'Test';
+ assertRefactoringStatusOK(refactoring.checkName());
+ }
+
+ test_expression() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Row(
+ children: <Widget>[
+ new Column(
+ children: <Widget>[
+ new Text('AAA'),
+ new Text('BBB'),
+ ],
+ ),
+ new Text('CCC'),
+ new Text('DDD'),
+ ],
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Column');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Row(
+ children: <Widget>[
+ new Test(),
+ new Text('CCC'),
+ new Text('DDD'),
+ ],
+ );
+ }
+}
+
+class Test extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Column(
+ children: <Widget>[
+ new Text('AAA'),
+ new Text('BBB'),
+ ],
+ );
+ }
+}
+''');
+ }
+
+ test_expression_localFunction() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ Widget foo() {
+ return new Row(
+ children: <Widget>[
+ new Text('AAA'),
+ new Text('BBB'),
+ ],
+ );
+ }
+ return foo();
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ Widget foo() {
+ return new Row(
+ children: <Widget>[
+ new Test(),
+ new Text('BBB'),
+ ],
+ );
+ }
+ return foo();
+}
+
+class Test extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text('AAA');
+ }
+}
+''');
+ }
+
+ test_expression_topFunction() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ return new Row(
+ children: <Widget>[
+ new Text('AAA'),
+ new Text('BBB'),
+ ],
+ );
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+Widget main() {
+ return new Row(
+ children: <Widget>[
+ new Test(),
+ new Text('BBB'),
+ ],
+ );
+}
+
+class Test extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text('AAA');
+ }
+}
+''');
+ }
+
+ test_invocation_enclosingClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ foo();
+ },
+ );
+ }
+
+ void foo() {}
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+ }
+
+ test_invocation_enclosingSuperClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+abstract class MyInterface {
+ void foo();
+}
+
+abstract class MyWidget extends StatelessWidget implements MyInterface {
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ foo();
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+ }
+
+ test_invocation_otherClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+ void foo() {}
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ c.foo();
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+ void foo() {}
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new Test(c);
+ }
+}
+
+class Test extends StatelessWidget {
+ final C c;
+
+ Test(this.c);
+
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ c.foo();
+ },
+ );
+ }
+}
+''');
+ }
+
+ test_method() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return createColumn();
+ }
+
+ Widget createColumn() {
+ var a = new Text('AAA');
+ var b = new Text('BBB');
+ return new Column(
+ children: <Widget>[a, b],
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('createColumn() {');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Test();
+ }
+}
+
+class Test extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ var a = new Text('AAA');
+ var b = new Text('BBB');
+ return new Column(
+ children: <Widget>[a, b],
+ );
+ }
+}
+''');
+ }
+
+ test_method_parameters() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String foo;
+
+ @override
+ Widget build(BuildContext context) {
+ int bar = 1;
+ return new Row(
+ children: <Widget>[
+ createColumn('aaa', bar),
+ createColumn('bbb', 2),
+ ],
+ );
+ }
+
+ Widget createColumn(String p1, int p2) {
+ var a = new Text('$foo $p1');
+ var b = new Text('$p2');
+ return new Column(
+ children: <Widget>[a, b],
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('createColumn(String');
+
+ await _assertSuccessfulRefactoring(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String foo;
+
+ @override
+ Widget build(BuildContext context) {
+ int bar = 1;
+ return new Row(
+ children: <Widget>[
+ new Test(foo, 'aaa', bar),
+ new Test(foo, 'bbb', 2),
+ ],
+ );
+ }
+}
+
+class Test extends StatelessWidget {
+ final String foo;
+ final String p1;
+ final int p2;
+
+ Test(this.foo, this.p1, this.p2);
+
+ @override
+ Widget build(BuildContext context) {
+ var a = new Text('$foo $p1');
+ var b = new Text('$p2');
+ return new Column(
+ children: <Widget>[a, b],
+ );
+ }
+}
+''');
+ }
+
+ test_parameters_field_read_enclosingClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String field;
+
+ @override
+ Widget build(BuildContext context) {
+ return new Text(field);
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String field;
+
+ @override
+ Widget build(BuildContext context) {
+ return new Test(field);
+ }
+}
+
+class Test extends StatelessWidget {
+ final String field;
+
+ Test(this.field);
+
+ @override
+ Widget build(BuildContext context) {
+ return new Text(field);
+ }
+}
+''');
+ }
+
+ test_parameters_field_read_otherClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+ String field;
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new Text(c.field);
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+ String field;
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new Test(c);
+ }
+}
+
+class Test extends StatelessWidget {
+ final C c;
+
+ Test(this.c);
+
+ @override
+ Widget build(BuildContext context) {
+ return new Text(c.field);
+ }
+}
+''');
+ }
+
+ test_parameters_field_read_topLevelVariable() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+String field;
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text(field);
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+String field;
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Test();
+ }
+}
+
+class Test extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text(field);
+ }
+}
+''');
+ }
+
+ test_parameters_field_write_enclosingClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String field;
+
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ field = '';
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+ }
+
+ test_parameters_field_write_enclosingSuperClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+abstract class MySuperWidget extends StatelessWidget {
+ String field;
+}
+
+class MyWidget extends MySuperWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ field = '';
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+ }
+
+ test_parameters_field_write_otherClass() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class C {
+ String field;
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ c.field = '';
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class C {
+ String field;
+}
+
+class MyWidget extends StatelessWidget {
+ C c = new C();
+
+ @override
+ Widget build(BuildContext context) {
+ return new Test(c);
+ }
+}
+
+class Test extends StatelessWidget {
+ final C c;
+
+ Test(this.c);
+
+ @override
+ Widget build(BuildContext context) {
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ c.field = '';
+ },
+ );
+ }
+}
+''');
+ }
+
+ test_parameters_local_read_enclosingScope() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ String local;
+ return new Text(local);
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ String local;
+ return new Test(local);
+ }
+}
+
+class Test extends StatelessWidget {
+ final String local;
+
+ Test(this.local);
+
+ @override
+ Widget build(BuildContext context) {
+ return new Text(local);
+ }
+}
+''');
+ }
+
+ test_parameters_local_write_enclosingScope() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ String local;
+ return new GestureDetector(
+ child: new Text(''),
+ onTap: () {
+ local = '';
+ },
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new GestureDetector');
+
+ RefactoringStatus status = await refactoring.checkAllConditions();
+ assertRefactoringStatus(status, RefactoringProblemSeverity.ERROR);
+ }
+
+ test_parameters_readField_readLocal() async {
+ addFlutterPackage();
+ await indexTestUnit(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String field;
+
+ @override
+ Widget build(BuildContext context) {
+ String local;
+ return new Column(
+ children: <Widget>[
+ new Text(field),
+ new Text(local),
+ ],
+ );
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Column');
+
+ await _assertSuccessfulRefactoring('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ String field;
+
+ @override
+ Widget build(BuildContext context) {
+ String local;
+ return new Test(field, local);
+ }
+}
+
+class Test extends StatelessWidget {
+ final String field;
+ final String local;
+
+ Test(this.field, this.local);
+
+ @override
+ Widget build(BuildContext context) {
+ return new Column(
+ children: <Widget>[
+ new Text(field),
+ new Text(local),
+ ],
+ );
+ }
+}
+''');
+ }
+
+ test_refactoringName() async {
+ addFlutterPackage();
+ await indexTestUnit('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return new Text('AAA');
+ }
+}
+''');
+ _createRefactoringForStringOffset('new Text');
+ expect(refactoring.refactoringName, 'Extract Widget');
+ }
+
+ Future<void> _assertRefactoringChange(String expectedCode) async {
+ SourceChange refactoringChange = await refactoring.createChange();
+ this.refactoringChange = refactoringChange;
+ assertTestChangeResult(expectedCode);
+ }
+
+ /**
+ * Checks that all conditions are OK and the result of applying the change
+ * to [testUnit] is [expectedCode].
+ */
+ Future<void> _assertSuccessfulRefactoring(String expectedCode) async {
+ await assertRefactoringConditionsOK();
+ await _assertRefactoringChange(expectedCode);
+ }
+
+ void _createRefactoring(int offset) {
+ refactoring = new ExtractWidgetRefactoring(
+ searchEngine, driver.currentSession, testUnit, offset);
+ refactoring.name = 'Test';
+ }
+
+ /**
+ * Creates a new refactoring in [refactoring] at the offset of the given
+ * [search] pattern.
+ */
+ void _createRefactoringForStringOffset(String search) {
+ int offset = findOffset(search);
+ _createRefactoring(offset);
+ }
+}
diff --git a/pkg/analysis_server/test/services/refactoring/test_all.dart b/pkg/analysis_server/test/services/refactoring/test_all.dart
index b845a98..9a75af9 100644
--- a/pkg/analysis_server/test/services/refactoring/test_all.dart
+++ b/pkg/analysis_server/test/services/refactoring/test_all.dart
@@ -8,6 +8,7 @@
import 'convert_method_to_getter_test.dart' as convert_method_to_getter_test;
import 'extract_local_test.dart' as extract_local_test;
import 'extract_method_test.dart' as extract_method_test;
+import 'extract_widget_test.dart' as extract_widget_test;
import 'inline_local_test.dart' as inline_local_test;
import 'inline_method_test.dart' as inline_method_test;
import 'naming_conventions_test.dart' as naming_conventions_test;
@@ -26,6 +27,7 @@
convert_method_to_getter_test.main();
extract_local_test.main();
extract_method_test.main();
+ extract_widget_test.main();
inline_local_test.main();
inline_method_test.main();
naming_conventions_test.main();
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java
new file mode 100644
index 0000000..e429a61
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetFeedback.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExtractWidgetFeedback extends RefactoringFeedback {
+
+ public static final ExtractWidgetFeedback[] EMPTY_ARRAY = new ExtractWidgetFeedback[0];
+
+ public static final List<ExtractWidgetFeedback> EMPTY_LIST = Lists.newArrayList();
+
+ /**
+ * Constructor for {@link ExtractWidgetFeedback}.
+ */
+ public ExtractWidgetFeedback() {
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExtractWidgetFeedback) {
+ ExtractWidgetFeedback other = (ExtractWidgetFeedback) obj;
+ return
+ true;
+ }
+ return false;
+ }
+
+ public static ExtractWidgetFeedback fromJson(JsonObject jsonObject) {
+ return new ExtractWidgetFeedback();
+ }
+
+ public static List<ExtractWidgetFeedback> fromJsonArray(JsonArray jsonArray) {
+ if (jsonArray == null) {
+ return EMPTY_LIST;
+ }
+ ArrayList<ExtractWidgetFeedback> list = new ArrayList<ExtractWidgetFeedback>(jsonArray.size());
+ Iterator<JsonElement> iterator = jsonArray.iterator();
+ while (iterator.hasNext()) {
+ list.add(fromJson(iterator.next().getAsJsonObject()));
+ }
+ return list;
+ }
+
+ @Override
+ public int hashCode() {
+ HashCodeBuilder builder = new HashCodeBuilder();
+ return builder.toHashCode();
+ }
+
+ public JsonObject toJson() {
+ JsonObject jsonObject = new JsonObject();
+ return jsonObject;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java
new file mode 100644
index 0000000..355f9e3
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/ExtractWidgetOptions.java
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class ExtractWidgetOptions extends RefactoringOptions {
+
+ public static final ExtractWidgetOptions[] EMPTY_ARRAY = new ExtractWidgetOptions[0];
+
+ public static final List<ExtractWidgetOptions> EMPTY_LIST = Lists.newArrayList();
+
+ /**
+ * The name that the widget class should be given.
+ */
+ private String name;
+
+ /**
+ * True if a StatefulWidget should be created.
+ */
+ private boolean stateful;
+
+ /**
+ * Constructor for {@link ExtractWidgetOptions}.
+ */
+ public ExtractWidgetOptions(String name, boolean stateful) {
+ this.name = name;
+ this.stateful = stateful;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ExtractWidgetOptions) {
+ ExtractWidgetOptions other = (ExtractWidgetOptions) obj;
+ return
+ ObjectUtilities.equals(other.name, name) &&
+ other.stateful == stateful;
+ }
+ return false;
+ }
+
+ public static ExtractWidgetOptions fromJson(JsonObject jsonObject) {
+ String name = jsonObject.get("name").getAsString();
+ boolean stateful = jsonObject.get("stateful").getAsBoolean();
+ return new ExtractWidgetOptions(name, stateful);
+ }
+
+ public static List<ExtractWidgetOptions> fromJsonArray(JsonArray jsonArray) {
+ if (jsonArray == null) {
+ return EMPTY_LIST;
+ }
+ ArrayList<ExtractWidgetOptions> list = new ArrayList<ExtractWidgetOptions>(jsonArray.size());
+ Iterator<JsonElement> iterator = jsonArray.iterator();
+ while (iterator.hasNext()) {
+ list.add(fromJson(iterator.next().getAsJsonObject()));
+ }
+ return list;
+ }
+
+ /**
+ * The name that the widget class should be given.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * True if a StatefulWidget should be created.
+ */
+ public boolean stateful() {
+ return stateful;
+ }
+
+ @Override
+ public int hashCode() {
+ HashCodeBuilder builder = new HashCodeBuilder();
+ builder.append(name);
+ builder.append(stateful);
+ return builder.toHashCode();
+ }
+
+ /**
+ * The name that the widget class should be given.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * True if a StatefulWidget should be created.
+ */
+ public void setStateful(boolean stateful) {
+ this.stateful = stateful;
+ }
+
+ public JsonObject toJson() {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("name", name);
+ jsonObject.addProperty("stateful", stateful);
+ return jsonObject;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ builder.append("name=");
+ builder.append(name + ", ");
+ builder.append("stateful=");
+ builder.append(stateful);
+ builder.append("]");
+ return builder.toString();
+ }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
index 8ea691e..5a6fa35 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RefactoringKind.java
@@ -23,6 +23,8 @@
public static final String EXTRACT_METHOD = "EXTRACT_METHOD";
+ public static final String EXTRACT_WIDGET = "EXTRACT_WIDGET";
+
public static final String INLINE_LOCAL_VARIABLE = "INLINE_LOCAL_VARIABLE";
public static final String INLINE_METHOD = "INLINE_METHOD";
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index a151081..dcccfc0 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -4237,6 +4237,29 @@
</field>
</options>
</refactoring>
+ <refactoring kind="EXTRACT_WIDGET">
+ <p>
+ Create a new class that extends either StatelessWidget or StatefulWidget,
+ whose build() method is the widget creation expression, or a method
+ returning a Flutter widget, at the specified offset.
+ </p>
+ <feedback>
+ </feedback>
+ <options>
+ <field name="name">
+ <ref>String</ref>
+ <p>
+ The name that the widget class should be given.
+ </p>
+ </field>
+ <field name="stateful">
+ <ref>bool</ref>
+ <p>
+ True if a StatefulWidget should be created.
+ </p>
+ </field>
+ </options>
+ </refactoring>
<refactoring kind="INLINE_LOCAL_VARIABLE">
<p>
Inline the initializer expression of a local variable in
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 4745a4f..9aff4bc 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,38 @@
+## 0.31.2-alpha.1
+
+* Don't expect type arguments for class type parameters of static methods.
+ (#32396)
+* Beginnings of changes to make analyzer code --preview-dart-2 safe, though
+ this version is not vetted for that.
+* Infer type arguments in constructor redirections (#30855)
+* Report errors on "as void" and "is void".
+* Fix instantiating typedefs to bounds (#32114)
+* preview-dart-2 implies strong-mode now and other preview-dart-2 fixes.
+* Store method invocation arguments in summaries when needed for inference (partial fix for #32394)
+* Fix top-level inference and implicit creation (#32397)
+* Do not hint when only a responsive asset exists (#32250)
+* Do not hint when using a deprecated parameter in the defining function
+ (#32468)
+* Fix parsing of super expressions (#32393)
+* Disable conflicting generics test in the task model (#32421)
+* Change how we find analysis roots (#31343, #31344)
+* Fix problem with AST re-writing interacting poorly with inference (#32342)
+* Disallow if a class inconsistently implements a generic interface.
+* Infer void for operator[]= return in task mode for DDC (#32241)
+* Finish and improve mixin type inference in the analyzer (#32146, #32353, #32372)
+* Many enhancements to getElementDeclarations() (#29510, #32495)
+* Remove hint when there's no return from a Future<void> and async method.
+* Add a code range to ElementDeclaration (#29510)
+* Many, many fasta parser changes and improvements.
+* Add missing void annotation (#32161)
+* Add more null-aware hints (#32239)
+* Fix implicit new/const computation (#32221)
+* Treat invocations on dynamic as unknown, except for return type of == (#32173)
+* Fix crash in generic function type argument of unresolved class (#32162)
+* Fix path formatting on windows (#32095)
+* front_end implementation of mixin type inference (#31984)
+* analysis_options no longer breaks some properties (#31345)
+
## 0.31.2-alpha.0
* front_end handling of callable classes (#32064)
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index b7ab961..8e58253 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -105,10 +105,7 @@
* might be inconsistent with any previously returned results.
*/
class InconsistentAnalysisException extends AnalysisException {
- /**
- * Initialize a newly created exception to have the given [message] and
- * [cause].
- */
- InconsistentAnalysisException([String message, CaughtException cause])
- : super(message, cause);
+ InconsistentAnalysisException()
+ : super('Requested result might be inconsistent with previously '
+ 'returned results');
}
diff --git a/pkg/analyzer/lib/exception/exception.dart b/pkg/analyzer/lib/exception/exception.dart
index 8014115..876d432 100644
--- a/pkg/analyzer/lib/exception/exception.dart
+++ b/pkg/analyzer/lib/exception/exception.dart
@@ -27,7 +27,7 @@
String toString() {
StringBuffer buffer = new StringBuffer();
- buffer.write("AnalysisException: ");
+ buffer.write('$runtimeType: ');
buffer.writeln(message);
if (cause != null) {
buffer.write('Caused by ');
diff --git a/pkg/analyzer/lib/plugin/options.dart b/pkg/analyzer/lib/plugin/options.dart
index e0ce5f4..e259428 100644
--- a/pkg/analyzer/lib/plugin/options.dart
+++ b/pkg/analyzer/lib/plugin/options.dart
@@ -4,8 +4,6 @@
/// Support for client code that wants to consume options contributed to the
/// analysis options file.
-library analyzer.plugin.options;
-
import 'package:analyzer/error/listener.dart';
import 'package:yaml/yaml.dart';
@@ -41,5 +39,5 @@
///
abstract class OptionsValidator {
/// Validate [options], reporting any errors to the given [reporter].
- void validate(ErrorReporter reporter, Map<String, YamlNode> options);
+ void validate(ErrorReporter reporter, YamlMap options);
}
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index 40b53e7..550f3e3 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -27,10 +27,10 @@
/// Recursively merge options referenced by an include directive
/// and remove the include directive from the resulting options map.
/// Return an empty options map if the file does not exist.
- Map<String, YamlNode> getOptions(Folder root, {bool crawlUp: false}) {
+ YamlMap getOptions(Folder root, {bool crawlUp: false}) {
File optionsFile = getOptionsFile(root, crawlUp: crawlUp);
if (optionsFile == null) {
- return const <String, YamlNode>{};
+ return new YamlMap();
}
return getOptionsFromFile(optionsFile);
}
@@ -62,7 +62,7 @@
/// Recursively merge options referenced by an include directive
/// and remove the include directive from the resulting options map.
/// Return an empty options map if the file does not exist.
- Map<String, YamlNode> getOptionsFromFile(File file) {
+ YamlMap getOptionsFromFile(File file) {
return getOptionsFromSource(new FileSource(file));
}
@@ -70,10 +70,9 @@
/// Recursively merge options referenced by an include directive
/// and remove the include directive from the resulting options map.
/// Return an empty options map if the file does not exist.
- Map<String, YamlNode> getOptionsFromSource(Source source) {
- Map<String, YamlNode> options =
- getOptionsFromString(_readAnalysisOptions(source));
- YamlNode node = options.remove(AnalyzerOptions.include);
+ YamlMap getOptionsFromSource(Source source) {
+ YamlMap options = getOptionsFromString(_readAnalysisOptions(source));
+ YamlNode node = getValue(options, AnalyzerOptions.include);
if (sourceFactory != null && node is YamlScalar) {
var path = node.value;
if (path is String) {
@@ -88,55 +87,21 @@
/// An include directive, if present, will be left as-is,
/// and the referenced options will NOT be merged into the result.
/// Return an empty options map if the source is null.
- Map<String, YamlNode> getOptionsFromString(String optionsSource) {
- Map<String, YamlNode> options = <String, YamlNode>{};
+ YamlMap getOptionsFromString(String optionsSource) {
if (optionsSource == null) {
- return options;
+ return new YamlMap();
}
-
- YamlNode safelyLoadYamlNode() {
- try {
- return loadYamlNode(optionsSource);
- } on YamlException catch (e) {
- throw new OptionsFormatException(e.message, e.span);
- } catch (e) {
- throw new OptionsFormatException('Unable to parse YAML document.');
+ try {
+ YamlNode doc = loadYamlNode(optionsSource);
+ if (doc is YamlMap) {
+ return doc;
}
+ return new YamlMap();
+ } on YamlException catch (e) {
+ throw new OptionsFormatException(e.message, e.span);
+ } catch (e) {
+ throw new OptionsFormatException('Unable to parse YAML document.');
}
-
- YamlNode doc = safelyLoadYamlNode();
-
- // Empty options.
- if (doc is YamlScalar && doc.value == null) {
- return options;
- }
- if ((doc != null) && (doc is! YamlMap)) {
- throw new OptionsFormatException(
- 'Bad options file format (expected map, got ${doc.runtimeType})',
- doc.span);
- }
- if (doc is YamlMap) {
- doc.nodes.forEach((k, YamlNode v) {
- var key;
- if (k is YamlScalar) {
- key = k.value;
- }
- if (key is! String) {
- throw new OptionsFormatException(
- 'Bad options file format (expected String scope key, '
- 'got ${k.runtimeType})',
- (k ?? doc).span);
- }
- if (v != null && v is! YamlNode) {
- throw new OptionsFormatException(
- 'Bad options file format (expected Node value, '
- 'got ${v.runtimeType}: `${v.toString()}`)',
- doc.span);
- }
- options[key] = v;
- });
- }
- return options;
}
/// Merge the given options contents where the values in [defaults] may be
@@ -151,8 +116,7 @@
/// * maps are merged recursively.
/// * if map values cannot be merged, the overriding value is taken.
///
- Map<String, YamlNode> merge(
- Map<String, YamlNode> defaults, Map<String, YamlNode> overrides) =>
+ YamlMap merge(YamlMap defaults, YamlMap overrides) =>
new Merger().mergeMap(defaults, overrides);
/// Read the contents of [source] as a string.
diff --git a/pkg/analyzer/lib/source/error_processor.dart b/pkg/analyzer/lib/source/error_processor.dart
index a4a6f77..153f42e 100644
--- a/pkg/analyzer/lib/source/error_processor.dart
+++ b/pkg/analyzer/lib/source/error_processor.dart
@@ -2,8 +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.
-library analyzer.source.error_processor;
-
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -28,7 +26,7 @@
/// new ErrorConfig({'missing_return' : 'error'});
/// will create a processor config that turns `missing_return` hints into
/// errors.
- ErrorConfig(Object codeMap) {
+ ErrorConfig(YamlNode codeMap) {
_processMap(codeMap);
}
@@ -45,20 +43,13 @@
}
}
- void _processMap(Object codes) {
+ void _processMap(YamlNode codes) {
if (codes is YamlMap) {
- // TODO(pq): stop traversing nodes and unify w/ standard map handling
codes.nodes.forEach((k, v) {
if (k is YamlScalar && v is YamlScalar) {
_process(k.value, v.value);
}
});
- } else if (codes is Map) {
- codes.forEach((k, v) {
- if (k is String) {
- _process(k, v);
- }
- });
}
}
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index ea45784..4162aa8 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -2,8 +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.
-library analyzer.src.context.context_builder;
-
import 'dart:collection';
import 'dart:core';
@@ -435,7 +433,7 @@
AnalysisOptionsImpl options = createDefaultOptions();
File optionsFile = getOptionsFile(path);
- Map<String, YamlNode> optionMap;
+ YamlMap optionMap;
if (optionsFile != null) {
try {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 43a1d47..5c6e63d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -326,6 +326,9 @@
/**
* The current analysis session.
+ *
+ * TODO(brianwilkerson) Create a new session when the current session might
+ * produce inconsistent results.
*/
AnalysisSessionImpl _currentSession;
@@ -353,7 +356,7 @@
_sourceFactory = sourceFactory.clone(),
_sdkBundle = sdkBundle,
_externalSummaries = externalSummaries {
- _createNewSession();
+ _currentSession = new AnalysisSessionImpl(this);
_onResults = _resultController.stream.asBroadcastStream();
_testView = new AnalysisDriverTestView(this);
_createFileTracker();
@@ -1119,7 +1122,6 @@
* of state.
*/
void _changeHook() {
- _createNewSession();
_priorityResults.clear();
_scheduler.notify(this);
}
@@ -1385,13 +1387,6 @@
}
/**
- * Create a new analysis session, so invalidating the current one.
- */
- void _createNewSession() {
- _currentSession = new AnalysisSessionImpl(this);
- }
-
- /**
* Fill [_salt] with data.
*/
void _fillSalt() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 9125b01..8704035 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -150,9 +150,6 @@
*/
void _fillUriToLibraryCache(LibraryElement library) {
Source source = library.source;
- if (source == null) {
- print('zzzzz');
- }
String uri = source.uri.toString();
if (_uriToLibraryCache[uri] == null) {
_uriToLibraryCache[uri] = library;
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
new file mode 100644
index 0000000..1644e8f
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -0,0 +1,32 @@
+// 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.
+
+import 'dart:async';
+
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// A wrapper around [AnalysisSession] that provides additional utilities.
+///
+/// The methods in this class that return analysis results will throw an
+/// [InconsistentAnalysisException] if the result to be returned might be
+/// inconsistent with any previously returned results.
+class AnalysisSessionHelper {
+ final AnalysisSession session;
+
+ AnalysisSessionHelper(this.session);
+
+ /// Return the [ClassElement] with the given [className] that is exported
+ /// from the library with the given [libraryUri], or `null` if the library
+ /// does not export a class with such name.
+ Future<ClassElement> getClass(String libraryUri, String className) async {
+ var libraryElement = await session.getLibraryByUri(libraryUri);
+ var element = libraryElement.exportNamespace.get(className);
+ if (element is ClassElement) {
+ return element;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 2ca77de..14b817f 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -22,12 +22,7 @@
import 'package:front_end/src/fasta/scanner.dart' hide StringToken;
import 'package:front_end/src/scanner/errors.dart' show translateErrorToken;
import 'package:front_end/src/scanner/token.dart'
- show
- StringToken,
- SyntheticBeginToken,
- SyntheticStringToken,
- SyntheticToken,
- CommentToken;
+ show StringToken, SyntheticBeginToken, SyntheticStringToken, SyntheticToken;
import 'package:front_end/src/fasta/problems.dart' show unhandled;
import 'package:front_end/src/fasta/messages.dart'
@@ -205,7 +200,7 @@
String value = unescapeString(token.lexeme);
push(ast.simpleStringLiteral(token, value));
} else {
- List parts = popList(1 + interpolationCount * 2);
+ List<Object> parts = popTypedList(1 + interpolationCount * 2);
Token first = parts.first;
Token last = parts.last;
Quote quote = analyzeQuote(first.lexeme);
@@ -250,7 +245,7 @@
void handleStringJuxtaposition(int literalCount) {
debugEvent("StringJuxtaposition");
- push(ast.adjacentStrings(popList(literalCount)));
+ push(ast.adjacentStrings(popTypedList(literalCount)));
}
void endArguments(int count, Token leftParenthesis, Token rightParenthesis) {
@@ -258,7 +253,7 @@
assert(optional(')', rightParenthesis));
debugEvent("Arguments");
- List expressions = popList(count);
+ List<Expression> expressions = popTypedList(count);
ArgumentList arguments =
ast.argumentList(leftParenthesis, expressions, rightParenthesis);
push(ast.methodInvocation(null, null, null, null, arguments));
@@ -382,7 +377,7 @@
assert(optional('}', rightBracket));
debugEvent("BlockFunctionBody");
- List statements = popList(count);
+ List<Statement> statements = popTypedList(count);
if (leftBracket != null) {
exitLocalScope();
}
@@ -542,7 +537,7 @@
assert(optional(':', colon));
debugEvent("Initializers");
- List<Object> initializerObjects = popList(count) ?? const [];
+ List<Object> initializerObjects = popTypedList(count) ?? const [];
if (!isFullAst) return;
push(colon);
@@ -608,7 +603,7 @@
debugEvent("VariableInitializer");
Expression initializer = pop();
- Identifier identifier = pop();
+ SimpleIdentifier identifier = pop();
// TODO(ahe): Don't push initializers, instead install them.
push(ast.variableDeclaration(identifier, assignmentOperator, initializer));
}
@@ -676,7 +671,7 @@
assert(optionalOrNull(';', semicolon));
debugEvent("VariablesDeclaration");
- List<VariableDeclaration> variables = popList(count);
+ List<VariableDeclaration> variables = popTypedList(count);
_Modifiers modifiers = pop(NullValue.Modifiers);
TypeAnnotation type = pop();
Token keyword = modifiers?.finalConstOrVarKeyword;
@@ -703,7 +698,7 @@
assert(optional('}', rightBracket));
debugEvent("Block");
- List<Statement> statements = popList(count) ?? <Statement>[];
+ List<Statement> statements = popTypedList(count) ?? <Statement>[];
exitLocalScope();
push(ast.block(leftBracket, statements, rightBracket));
}
@@ -722,7 +717,7 @@
debugEvent("ForStatement");
Statement body = pop();
- List<Expression> updates = popList(updateExpressionCount);
+ List<Expression> updates = popTypedList(updateExpressionCount);
Statement conditionStatement = pop();
Object initializerPart = pop();
exitLocalScope();
@@ -766,7 +761,7 @@
assert(optional(']', rightBracket));
debugEvent("LiteralList");
- List<Expression> expressions = popList(count);
+ List<Expression> expressions = popTypedList(count);
TypeArgumentList typeArguments = pop();
push(ast.listLiteral(
constKeyword, typeArguments, leftBracket, expressions, rightBracket));
@@ -819,7 +814,7 @@
assert(optional('}', rightBracket));
debugEvent("LiteralMap");
- List<MapLiteralEntry> entries = popList(count) ?? <MapLiteralEntry>[];
+ List<MapLiteralEntry> entries = popTypedList(count) ?? <MapLiteralEntry>[];
TypeArgumentList typeArguments = pop();
push(ast.mapLiteral(
constKeyword, typeArguments, leftBracket, entries, rightBracket));
@@ -838,7 +833,7 @@
assert(optional('#', hashToken));
debugEvent("LiteralSymbol");
- List<Token> components = popList(tokenCount);
+ List<Token> components = popTypedList(tokenCount);
push(ast.symbolLiteral(hashToken, components));
}
@@ -1006,7 +1001,7 @@
debugEvent("OptionalFormalParameters");
push(new _OptionalFormalParameters(
- popList(count), leftDelimeter, rightDelimeter));
+ popTypedList(count), leftDelimeter, rightDelimeter));
}
void handleValuedFormalParameter(Token equals, Token token) {
@@ -1103,7 +1098,7 @@
Comment comment = _findComment(metadata,
thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);
- FormalParameter node;
+ NormalFormalParameter node;
if (typeOrFunctionTypedParameter is FunctionTypedFormalParameter) {
// This is a temporary AST node that was constructed in
// [endFunctionTypedFormalParameter]. We now deconstruct it and create
@@ -1153,16 +1148,17 @@
}
ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
+ FormalParameter parameter = node;
if (analyzerKind != ParameterKind.REQUIRED) {
- node = ast.defaultFormalParameter(
+ parameter = ast.defaultFormalParameter(
node, analyzerKind, defaultValue?.separator, defaultValue?.value);
} else if (defaultValue != null) {
// An error is reported if a required parameter has a default value.
// Record it as named parameter for recovery.
- node = ast.defaultFormalParameter(node, ParameterKind.NAMED,
+ parameter = ast.defaultFormalParameter(node, ParameterKind.NAMED,
defaultValue.separator, defaultValue.value);
}
- push(node);
+ push(parameter);
}
@override
@@ -1188,7 +1184,7 @@
assert(optional(')', rightParen));
debugEvent("FormalParameters");
- List rawParameters = popList(count) ?? const <Object>[];
+ List<Object> rawParameters = popTypedList(count) ?? const <Object>[];
List<FormalParameter> parameters = <FormalParameter>[];
Token leftDelimiter;
Token rightDelimiter;
@@ -1211,7 +1207,7 @@
assert(optional('}', rightBracket));
debugEvent("SwitchBlock");
- List<List<SwitchMember>> membersList = popList(caseCount);
+ List<List<SwitchMember>> membersList = popTypedList(caseCount);
exitBreakTarget();
exitLocalScope();
List<SwitchMember> members =
@@ -1250,9 +1246,9 @@
: optional(':', colonAfterDefault));
debugEvent("SwitchCase");
- List<Statement> statements = popList(statementCount);
- List<SwitchMember> members = popList(expressionCount) ?? [];
- List<Label> labels = popList(labelCount);
+ List<Statement> statements = popTypedList(statementCount);
+ List<SwitchMember> members = popTypedList(expressionCount) ?? [];
+ List<Label> labels = popTypedList(labelCount);
if (defaultKeyword != null) {
members.add(ast.switchDefault(
<Label>[], defaultKeyword, colonAfterDefault, <Statement>[]));
@@ -1338,7 +1334,7 @@
debugEvent("TryStatement");
Block finallyBlock = popIfNotNull(finallyKeyword);
- List<CatchClause> catchClauses = popList(catchCount);
+ List<CatchClause> catchClauses = popTypedList(catchCount);
Block body = pop();
push(ast.tryStatement(
tryKeyword, body, catchClauses, finallyKeyword, finallyBlock));
@@ -1460,7 +1456,7 @@
if (count == 0) {
push(NullValue.Modifiers);
} else {
- push(new _Modifiers(popList(count)));
+ push(new _Modifiers(popTypedList(count)));
}
}
@@ -1621,7 +1617,7 @@
assert(firstIdentifier.isIdentifier);
debugEvent("DottedName");
- List<SimpleIdentifier> components = popList(count);
+ List<SimpleIdentifier> components = popTypedList(count);
push(ast.dottedName(components));
}
@@ -1674,14 +1670,14 @@
void endConditionalUris(int count) {
debugEvent("ConditionalUris");
- push(popList(count) ?? NullValue.ConditionalUris);
+ push(popTypedList<Configuration>(count) ?? NullValue.ConditionalUris);
}
@override
void handleIdentifierList(int count) {
debugEvent("IdentifierList");
- push(popList(count) ?? NullValue.IdentifierList);
+ push(popTypedList<SimpleIdentifier>(count) ?? NullValue.IdentifierList);
}
@override
@@ -1703,9 +1699,15 @@
}
@override
+ void endCombinators(int count) {
+ debugEvent("Combinators");
+ push(popTypedList<Combinator>(count) ?? NullValue.Combinators);
+ }
+
+ @override
void endTypeList(int count) {
debugEvent("TypeList");
- push(popList(count) ?? NullValue.TypeList);
+ push(popTypedList<TypeName>(count) ?? NullValue.TypeList);
}
@override
@@ -1719,8 +1721,9 @@
}
@override
- void beginClassDeclaration(Token beginToken, Token name) {
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
assert(classDeclaration == null);
+ push(new _Modifiers()..abstractKeyword = abstractToken);
}
@override
@@ -1752,7 +1755,7 @@
debugEvent("ClassImplements");
if (implementsKeyword != null) {
- List<TypeName> interfaces = popList(interfacesCount);
+ List<TypeName> interfaces = popTypedList(interfacesCount);
push(ast.implementsClause(implementsKeyword, interfaces));
} else {
push(NullValue.IdentifierList);
@@ -1773,9 +1776,9 @@
ImplementsClause implementsClause = pop(NullValue.IdentifierList);
WithClause withClause = pop(NullValue.WithClause);
ExtendsClause extendsClause = pop(NullValue.ExtendsClause);
+ _Modifiers modifiers = pop();
TypeParameterList typeParameters = pop();
SimpleIdentifier name = pop();
- _Modifiers modifiers = pop();
Token abstractKeyword = modifiers?.abstractKeyword;
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, classKeyword);
@@ -1835,6 +1838,12 @@
}
@override
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {
+ push(new _Modifiers()..abstractKeyword = abstractToken);
+ }
+
+ @override
void endMixinApplication(Token withKeyword) {
assert(optionalOrNull('with', withKeyword));
debugEvent("MixinApplication");
@@ -1862,9 +1871,9 @@
var superclass = mixinApplication.supertype;
var withClause = ast.withClause(
mixinApplication.withKeyword, mixinApplication.mixinTypes);
+ _Modifiers modifiers = pop();
TypeParameterList typeParameters = pop();
SimpleIdentifier name = pop();
- _Modifiers modifiers = pop();
Token abstractKeyword = modifiers?.abstractKeyword;
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, beginToken);
@@ -1887,7 +1896,7 @@
debugEvent("LabeledStatement");
Statement statement = pop();
- List<Label> labels = popList(labelCount);
+ List<Label> labels = popTypedList(labelCount);
push(ast.labeledStatement(labels, statement));
}
@@ -1968,7 +1977,7 @@
if (libraryNameOrUri is StringLiteral) {
uri = libraryNameOrUri;
} else {
- name = ast.libraryIdentifier(libraryNameOrUri);
+ name = ast.libraryIdentifier(libraryNameOrUri as List<SimpleIdentifier>);
}
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, partKeyword);
@@ -2096,10 +2105,11 @@
SimpleIdentifier name = pop();
TypeAnnotation returnType = pop();
TypeParameterList typeParameters = pop();
+ List<Annotation> metadata = pop(NullValue.Metadata);
FunctionExpression functionExpression =
ast.functionExpression(typeParameters, parameters, body);
push(ast.functionDeclarationStatement(ast.functionDeclaration(
- null, null, null, returnType, null, name, functionExpression)));
+ null, metadata, null, returnType, null, name, functionExpression)));
}
@override
@@ -2107,13 +2117,17 @@
debugEvent("FunctionName");
}
- void endTopLevelFields(int count, Token beginToken, Token semicolon) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token semicolon) {
assert(optional(';', semicolon));
debugEvent("TopLevelFields");
- List<VariableDeclaration> variables = popList(count);
+ List<VariableDeclaration> variables = popTypedList(count);
TypeAnnotation type = pop();
- _Modifiers modifiers = pop();
+ _Modifiers modifiers = new _Modifiers()
+ ..staticKeyword = staticToken
+ ..covariantKeyword = covariantToken
+ ..finalConstOrVarKeyword = varFinalOrConst;
Token keyword = modifiers?.finalConstOrVarKeyword;
var variableList =
ast.variableDeclarationList(null, null, keyword, type, variables);
@@ -2147,7 +2161,7 @@
assert(optional('>', endToken));
debugEvent("TypeVariables");
- List<TypeParameter> typeParameters = popList(count);
+ List<TypeParameter> typeParameters = popTypedList(count);
push(ast.typeParameterList(beginToken, typeParameters, endToken));
}
@@ -2367,8 +2381,15 @@
// this).
type = null;
}
- declarations.add(ast.genericTypeAlias(comment, metadata, typedefKeyword,
- name, templateParameters, equals, type, semicolon));
+ declarations.add(ast.genericTypeAlias(
+ comment,
+ metadata,
+ typedefKeyword,
+ name,
+ templateParameters,
+ equals,
+ type as GenericFunctionType,
+ semicolon));
}
}
@@ -2378,7 +2399,7 @@
assert(optional('{', leftBrace));
debugEvent("Enum");
- List<EnumConstantDeclaration> constants = popList(count);
+ List<EnumConstantDeclaration> constants = popTypedList(count);
SimpleIdentifier name = pop();
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata, enumKeyword);
@@ -2392,18 +2413,22 @@
assert(optional('>', rightBracket));
debugEvent("TypeArguments");
- List<TypeAnnotation> arguments = popList(count);
+ List<TypeAnnotation> arguments = popTypedList(count);
push(ast.typeArgumentList(leftBracket, arguments, rightBracket));
}
@override
- void endFields(int count, Token beginToken, Token semicolon) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token semicolon) {
assert(optional(';', semicolon));
debugEvent("Fields");
- List<VariableDeclaration> variables = popList(count);
+ List<VariableDeclaration> variables = popTypedList(count);
TypeAnnotation type = pop();
- _Modifiers modifiers = pop();
+ _Modifiers modifiers = new _Modifiers()
+ ..staticKeyword = staticToken
+ ..covariantKeyword = covariantToken
+ ..finalConstOrVarKeyword = varFinalOrConst;
var variableList = ast.variableDeclarationList(
null, null, modifiers?.finalConstOrVarKeyword, type, variables);
Token covariantKeyword = modifiers?.covariantKeyword;
@@ -2469,7 +2494,7 @@
void endMetadataStar(int count) {
debugEvent("MetadataStar");
- push(popList(count) ?? NullValue.Metadata);
+ push(popTypedList<Annotation>(count) ?? NullValue.Metadata);
}
ParameterKind _toAnalyzerParameterKind(FormalParameterKind type) {
@@ -2810,7 +2835,7 @@
/// Parse a documentation comment. Return the documentation comment that was
/// parsed, or `null` if there was no comment.
- Comment _parseDocumentationCommentOpt(CommentToken commentToken) {
+ Comment _parseDocumentationCommentOpt(Token commentToken) {
List<Token> tokens = <Token>[];
while (commentToken != null) {
if (commentToken.lexeme.startsWith('/**') ||
@@ -2894,6 +2919,25 @@
bool optionalOrNull(String value, Token token) {
return token == null || identical(value, token.stringValue);
}
+
+ List<T> popTypedList<T>(int count, [List<T> list]) {
+ if (count == 0) return null;
+ assert(stack.arrayLength >= count);
+
+ final table = stack.array;
+ final length = stack.arrayLength;
+
+ final tailList = list ?? new List<T>.filled(count, null, growable: true);
+ final startIndex = length - count;
+ for (int i = 0; i < count; i++) {
+ final value = table[startIndex + i];
+ tailList[i] = value is NullValue ? null : value;
+ table[startIndex + i] = null;
+ }
+ stack.arrayLength -= count;
+
+ return tailList;
+ }
}
/// Data structure placed on the stack to represent a mixin application (a
diff --git a/pkg/analyzer/lib/src/generated/utilities_general.dart b/pkg/analyzer/lib/src/generated/utilities_general.dart
index 3cb3393..968cad3 100644
--- a/pkg/analyzer/lib/src/generated/utilities_general.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_general.dart
@@ -2,12 +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 analyzer.src.generated.utilities_general;
-
import 'dart:async';
import 'dart:collection';
import 'dart:developer' show UserTag;
+import 'package:yaml/yaml.dart';
+
export 'package:front_end/src/base/jenkins_smi_hash.dart' show JenkinsSmiHash;
/**
@@ -27,6 +27,9 @@
* value could not be converted.
*/
bool toBool(Object value) {
+ if (value is YamlScalar) {
+ value = (value as YamlScalar).value;
+ }
if (value is bool) {
return value;
}
diff --git a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
deleted file mode 100644
index 558aeb6..0000000
--- a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
+++ /dev/null
@@ -1,3082 +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.
-library kernel.analyzer.ast_from_analyzer;
-
-import 'package:kernel/ast.dart' as ast;
-import 'package:kernel/frontend/super_initializers.dart';
-import 'package:kernel/log.dart';
-import 'package:kernel/type_algebra.dart';
-import 'package:kernel/transformations/flags.dart';
-import 'package:analyzer/dart/ast/token.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/kernel/loader.dart';
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:kernel/frontend/accessors.dart';
-
-/// Provides reference-level access to libraries, classes, and members.
-///
-/// "Reference level" objects are incomplete nodes that have no children but
-/// can be used for linking until the loader promotes the node to a higher
-/// loading level.
-///
-/// The [ReferenceScope] is the most restrictive scope in a hierarchy of scopes
-/// that provide increasing amounts of contextual information. [TypeScope] is
-/// used when type parameters might be in scope, and [MemberScope] is used when
-/// building the body of a [ast.Member].
-class ReferenceScope {
- final ReferenceLevelLoader loader;
-
- ReferenceScope(this.loader);
-
- bool get strongMode => loader.strongMode;
-
- ast.Library getLibraryReference(LibraryElement element) {
- if (element == null) return null;
- return loader.getLibraryReference(getBaseElement(element));
- }
-
- ast.Class getRootClassReference() {
- return loader.getRootClassReference();
- }
-
- ast.Class getClassReference(ClassElement element) {
- return loader.getClassReference(getBaseElement(element));
- }
-
- ast.Member getMemberReference(Element element) {
- return loader.getMemberReference(getBaseElement(element));
- }
-
- static Element getBaseElement(Element element) {
- while (element is Member) {
- element = (element as Member).baseElement;
- }
- return element;
- }
-
- static bool supportsConcreteGet(Element element) {
- return (element is PropertyAccessorElement &&
- element.isGetter &&
- !element.isAbstract) ||
- element is FieldElement ||
- element is TopLevelVariableElement ||
- element is MethodElement && !element.isAbstract ||
- isTopLevelFunction(element);
- }
-
- static bool supportsInterfaceGet(Element element) {
- return (element is PropertyAccessorElement && element.isGetter) ||
- element is FieldElement ||
- element is MethodElement;
- }
-
- static bool supportsConcreteSet(Element element) {
- return (element is PropertyAccessorElement &&
- element.isSetter &&
- !element.isAbstract) ||
- element is FieldElement && !element.isFinal && !element.isConst ||
- element is TopLevelVariableElement &&
- !element.isFinal &&
- !element.isConst;
- }
-
- static bool supportsInterfaceSet(Element element) {
- return (element is PropertyAccessorElement && element.isSetter) ||
- element is FieldElement && !element.isFinal && !element.isConst;
- }
-
- static bool supportsConcreteIndexGet(Element element) {
- return element is MethodElement &&
- element.name == '[]' &&
- !element.isAbstract;
- }
-
- static bool supportsInterfaceIndexGet(Element element) {
- return element is MethodElement && element.name == '[]';
- }
-
- static bool supportsConcreteIndexSet(Element element) {
- return element is MethodElement &&
- element.name == '[]=' &&
- !element.isAbstract;
- }
-
- static bool supportsInterfaceIndexSet(Element element) {
- return element is MethodElement && element.name == '[]=';
- }
-
- static bool supportsConcreteMethodCall(Element element) {
- // Note that local functions are not valid targets for method calls because
- // they are not "methods" or even "procedures" in our AST.
- return element is MethodElement && !element.isAbstract ||
- isTopLevelFunction(element) ||
- element is ConstructorElement && element.isFactory;
- }
-
- static bool supportsInterfaceMethodCall(Element element) {
- return element is MethodElement;
- }
-
- static bool supportsConstructorCall(Element element) {
- return element is ConstructorElement && !element.isFactory;
- }
-
- ast.Member _resolveGet(
- Element element, Element auxiliary, bool predicate(Element element)) {
- element = desynthesizeGetter(element);
- if (predicate(element)) return getMemberReference(element);
- if (element is PropertyAccessorElement && element.isSetter) {
- // The getter is sometimes stored as the 'corresponding getter' instead
- // of the 'auxiliary' element.
- auxiliary ??= element.correspondingGetter;
- }
- auxiliary = desynthesizeGetter(auxiliary);
- if (predicate(auxiliary)) return getMemberReference(auxiliary);
- return null;
- }
-
- ast.Member resolveConcreteGet(Element element, Element auxiliary) {
- return _resolveGet(element, auxiliary, supportsConcreteGet);
- }
-
- ast.Member resolveInterfaceGet(Element element, Element auxiliary) {
- if (!strongMode) return null;
- return _resolveGet(element, auxiliary, supportsInterfaceGet);
- }
-
- DartType getterTypeOfElement(Element element) {
- if (element is VariableElement) {
- return element.type;
- } else if (element is PropertyAccessorElement && element.isGetter) {
- return element.returnType;
- } else {
- return null;
- }
- }
-
- /// Returns the interface target of a `call` dispatch to the given member.
- ///
- /// For example, if the member is a field of type C, the target will be the
- /// `call` method of class C, if it has such a method.
- ///
- /// If the class C has a getter or field named `call`, this method returns
- /// `null` - the static type system does support typed calls with indirection.
- ast.Member resolveInterfaceFunctionCall(Element element) {
- if (!strongMode || element == null) return null;
- return resolveInterfaceFunctionCallOnType(getterTypeOfElement(element));
- }
-
- /// Returns the `call` method of [callee], if it has one, otherwise `null`.
- ast.Member resolveInterfaceFunctionCallOnType(DartType callee) {
- return callee is InterfaceType
- ? resolveInterfaceMethod(callee.getMethod('call'))
- : null;
- }
-
- ast.Member _resolveSet(
- Element element, Element auxiliary, bool predicate(Element element)) {
- element = desynthesizeSetter(element);
- if (predicate(element)) {
- return getMemberReference(element);
- }
- if (element is PropertyAccessorElement && element.isSetter) {
- // The setter is sometimes stored as the 'corresponding setter' instead
- // of the 'auxiliary' element.
- auxiliary ??= element.correspondingGetter;
- }
- auxiliary = desynthesizeSetter(auxiliary);
- if (predicate(auxiliary)) {
- return getMemberReference(auxiliary);
- }
- return null;
- }
-
- ast.Member resolveConcreteSet(Element element, Element auxiliary) {
- return _resolveSet(element, auxiliary, supportsConcreteSet);
- }
-
- ast.Member resolveInterfaceSet(Element element, Element auxiliary) {
- if (!strongMode) return null;
- return _resolveSet(element, auxiliary, supportsInterfaceSet);
- }
-
- ast.Member resolveConcreteIndexGet(Element element, Element auxiliary) {
- if (supportsConcreteIndexGet(element)) {
- return getMemberReference(element);
- }
- if (supportsConcreteIndexGet(auxiliary)) {
- return getMemberReference(auxiliary);
- }
- return null;
- }
-
- ast.Member resolveInterfaceIndexGet(Element element, Element auxiliary) {
- if (!strongMode) return null;
- if (supportsInterfaceIndexGet(element)) {
- return getMemberReference(element);
- }
- if (supportsInterfaceIndexGet(auxiliary)) {
- return getMemberReference(auxiliary);
- }
- return null;
- }
-
- ast.Member resolveConcreteIndexSet(Element element, Element auxiliary) {
- if (supportsConcreteIndexSet(element)) {
- return getMemberReference(element);
- }
- if (supportsConcreteIndexSet(auxiliary)) {
- return getMemberReference(auxiliary);
- }
- return null;
- }
-
- ast.Member resolveInterfaceIndexSet(Element element, Element auxiliary) {
- if (!strongMode) return null;
- if (supportsInterfaceIndexSet(element)) {
- return getMemberReference(element);
- }
- if (supportsInterfaceIndexSet(auxiliary)) {
- return getMemberReference(auxiliary);
- }
- return null;
- }
-
- ast.Member resolveConcreteMethod(Element element) {
- if (supportsConcreteMethodCall(element)) {
- return getMemberReference(element);
- }
- return null;
- }
-
- ast.Member resolveInterfaceMethod(Element element) {
- if (!strongMode) return null;
- if (supportsInterfaceMethodCall(element)) {
- return getMemberReference(element);
- }
- return null;
- }
-
- ast.Constructor resolveConstructor(Element element) {
- if (supportsConstructorCall(element)) {
- return getMemberReference(element);
- }
- return null;
- }
-
- ast.Field resolveField(Element element) {
- if (element is FieldElement && !element.isSynthetic) {
- return getMemberReference(element);
- }
- return null;
- }
-
- /// A static accessor that generates a 'throw NoSuchMethodError' when a
- /// read or write access could not be resolved.
- Accessor staticAccess(String name, Element element, [Element auxiliary]) {
- return new _StaticAccessor(
- this,
- name,
- resolveConcreteGet(element, auxiliary),
- resolveConcreteSet(element, auxiliary));
- }
-
- /// An accessor that generates a 'throw NoSuchMethodError' on both read
- /// and write access.
- Accessor unresolvedAccess(String name) {
- return new _StaticAccessor(this, name, null, null);
- }
-}
-
-class TypeScope extends ReferenceScope {
- final Map<TypeParameterElement, ast.TypeParameter> localTypeParameters =
- <TypeParameterElement, ast.TypeParameter>{};
- TypeAnnotationBuilder _typeBuilder;
-
- TypeScope(ReferenceLevelLoader loader) : super(loader) {
- _typeBuilder = new TypeAnnotationBuilder(this);
- }
-
- String get location => '?';
-
- bool get allowClassTypeParameters => false;
-
- ast.DartType get defaultTypeParameterBound => getRootClassReference().rawType;
-
- ast.TypeParameter tryGetTypeParameterReference(TypeParameterElement element) {
- return localTypeParameters[element] ??
- loader.tryGetClassTypeParameter(element);
- }
-
- ast.TypeParameter getTypeParameterReference(TypeParameterElement element) {
- return localTypeParameters[element] ??
- loader.tryGetClassTypeParameter(element) ??
- (localTypeParameters[element] = new ast.TypeParameter(element.name));
- }
-
- ast.TypeParameter makeTypeParameter(TypeParameterElement element,
- {ast.DartType bound}) {
- var typeParameter = getTypeParameterReference(element);
- assert(bound != null);
- typeParameter.bound = bound;
- return typeParameter;
- }
-
- ast.DartType buildType(DartType type) {
- return _typeBuilder.buildFromDartType(type);
- }
-
- ast.Supertype buildSupertype(DartType type) {
- if (type is InterfaceType) {
- var classElement = type.element;
- if (classElement == null) return getRootClassReference().asRawSupertype;
- var classNode = getClassReference(classElement);
- if (classNode.typeParameters.isEmpty ||
- classNode.typeParameters.length != type.typeArguments.length) {
- return classNode.asRawSupertype;
- } else {
- return new ast.Supertype(classNode,
- type.typeArguments.map(buildType).toList(growable: false));
- }
- }
- return getRootClassReference().asRawSupertype;
- }
-
- ast.DartType buildTypeAnnotation(AstNode node) {
- return _typeBuilder.build(node);
- }
-
- ast.DartType buildOptionalTypeAnnotation(AstNode node) {
- return node == null ? null : _typeBuilder.build(node);
- }
-
- ast.DartType getInferredType(Expression node) {
- if (!strongMode) return const ast.DynamicType();
- // TODO: Is this official way to get the strong-mode inferred type?
- return buildType(node.staticType);
- }
-
- ast.DartType getInferredTypeArgument(Expression node, int index) {
- var type = getInferredType(node);
- return type is ast.InterfaceType && index < type.typeArguments.length
- ? type.typeArguments[index]
- : const ast.DynamicType();
- }
-
- ast.DartType getInferredReturnType(Expression node) {
- var type = getInferredType(node);
- return type is ast.FunctionType ? type.returnType : const ast.DynamicType();
- }
-
- List<ast.DartType> getInferredInvocationTypeArguments(
- InvocationExpression node) {
- if (!strongMode) return <ast.DartType>[];
- ast.DartType inferredFunctionType = buildType(node.staticInvokeType);
- ast.DartType genericFunctionType = buildType(node.function.staticType);
- if (genericFunctionType is ast.FunctionType) {
- if (genericFunctionType.typeParameters.isEmpty) return <ast.DartType>[];
- // Attempt to unify the two types to obtain a substitution of the type
- // variables. If successful, use the substituted types in the order
- // they occur in the type parameter list.
- var substitution = unifyTypes(genericFunctionType.withoutTypeParameters,
- inferredFunctionType, genericFunctionType.typeParameters.toSet());
- if (substitution != null) {
- return genericFunctionType.typeParameters
- .map((p) => substitution[p] ?? const ast.DynamicType())
- .toList();
- }
- return new List<ast.DartType>.filled(
- genericFunctionType.typeParameters.length, const ast.DynamicType(),
- growable: true);
- } else {
- return <ast.DartType>[];
- }
- }
-
- List<ast.DartType> buildOptionalTypeArgumentList(TypeArgumentList node) {
- if (node == null) return null;
- return _typeBuilder.buildList(node.arguments);
- }
-
- List<ast.DartType> buildTypeArgumentList(TypeArgumentList node) {
- return _typeBuilder.buildList(node.arguments);
- }
-
- List<ast.TypeParameter> buildOptionalTypeParameterList(TypeParameterList node,
- {bool strongModeOnly: false}) {
- if (node == null) return <ast.TypeParameter>[];
- if (strongModeOnly && !strongMode) return <ast.TypeParameter>[];
- return node.typeParameters.map(buildTypeParameter).toList();
- }
-
- ast.TypeParameter buildTypeParameter(TypeParameter node) {
- return makeTypeParameter(node.element,
- bound: buildOptionalTypeAnnotation(node.bound) ??
- defaultTypeParameterBound);
- }
-
- ConstructorElement findDefaultConstructor(ClassElement class_) {
- for (var constructor in class_.constructors) {
- // Note: isDefaultConstructor checks if the constructor is suitable for
- // being invoked without arguments. It does not imply that it is
- // synthetic.
- if (constructor.isDefaultConstructor && !constructor.isFactory) {
- return constructor;
- }
- }
- return null;
- }
-
- ast.FunctionNode buildFunctionInterface(FunctionTypedElement element) {
- var positional = <ast.VariableDeclaration>[];
- var named = <ast.VariableDeclaration>[];
- int requiredParameterCount = 0;
- // Initialize type parameters in two passes: put them into scope,
- // and compute the bounds afterwards while they are all in scope.
- var typeParameters = <ast.TypeParameter>[];
- var typeParameterElements =
- element is ConstructorElement && element.isFactory
- ? element.enclosingElement.typeParameters
- : element.typeParameters;
- if (strongMode || element is ConstructorElement) {
- for (var parameter in typeParameterElements) {
- var parameterNode = new ast.TypeParameter(parameter.name);
- typeParameters.add(parameterNode);
- localTypeParameters[parameter] = parameterNode;
- }
- }
- for (int i = 0; i < typeParameters.length; ++i) {
- var parameter = typeParameterElements[i];
- var parameterNode = typeParameters[i];
- parameterNode.bound = parameter.bound == null
- ? defaultTypeParameterBound
- : buildType(parameter.bound);
- }
- for (var parameter in element.parameters) {
- var parameterNode = new ast.VariableDeclaration(parameter.name,
- type: buildType(parameter.type));
- if (parameter.isNotOptional) {
- positional.add(parameterNode);
- ++requiredParameterCount;
- } else if (parameter.isOptionalPositional) {
- positional.add(parameterNode);
- } else if (parameter.isNamed) {
- named.add(parameterNode);
- }
- }
- var returnType = element is ConstructorElement
- ? const ast.VoidType()
- : buildType(element.returnType);
- return new ast.FunctionNode(null,
- typeParameters: typeParameters,
- positionalParameters: positional,
- namedParameters: named,
- requiredParameterCount: requiredParameterCount,
- returnType: returnType)
- ..fileOffset = element.nameOffset;
- }
-}
-
-class ExpressionScope extends TypeScope {
- ast.Library currentLibrary;
- final Map<LocalElement, ast.VariableDeclaration> localVariables =
- <LocalElement, ast.VariableDeclaration>{};
-
- ExpressionBuilder _expressionBuilder;
- StatementBuilder _statementBuilder;
-
- ExpressionScope(ReferenceLevelLoader loader, this.currentLibrary)
- : super(loader) {
- assert(currentLibrary != null);
- _expressionBuilder = new ExpressionBuilder(this);
- _statementBuilder = new StatementBuilder(this);
- }
-
- bool get allowThis => false; // Overridden by MemberScope.
-
- ast.Name buildName(SimpleIdentifier node) {
- return new ast.Name(node.name, currentLibrary);
- }
-
- ast.Statement buildStatement(Statement node) {
- return _statementBuilder.build(node);
- }
-
- ast.Statement buildOptionalFunctionBody(FunctionBody body) {
- if (body == null ||
- body is EmptyFunctionBody ||
- body is NativeFunctionBody) {
- return null;
- }
- return buildMandatoryFunctionBody(body);
- }
-
- ast.Statement buildMandatoryFunctionBody(FunctionBody body) {
- try {
- if (body is BlockFunctionBody) {
- return buildStatement(body.block);
- } else if (body is ExpressionFunctionBody) {
- if (bodyHasVoidReturn(body)) {
- return new ast.ExpressionStatement(buildExpression(body.expression));
- } else {
- return new ast.ReturnStatement(buildExpression(body.expression))
- ..fileOffset = body.expression.offset;
- }
- } else {
- return internalError('Missing function body');
- }
- } on _CompilationError catch (e) {
- return new ast.ExpressionStatement(buildThrowCompileTimeError(e.message));
- }
- }
-
- ast.AsyncMarker getAsyncMarker({bool isAsync: false, bool isStar: false}) {
- return ast.AsyncMarker.values[(isAsync ? 2 : 0) + (isStar ? 1 : 0)];
- }
-
- ast.FunctionNode buildFunctionNode(
- FormalParameterList formalParameters, FunctionBody body,
- {TypeName returnType,
- List<ast.TypeParameter> typeParameters,
- ast.DartType inferredReturnType}) {
- // TODO(asgerf): This will in many cases rebuild the interface built by
- // TypeScope.buildFunctionInterface.
- var positional = <ast.VariableDeclaration>[];
- var named = <ast.VariableDeclaration>[];
- int requiredParameterCount = 0;
- var formals = formalParameters?.parameters ?? const <FormalParameter>[];
- for (var parameter in formals) {
- var declaration = makeVariableDeclaration(parameter.element,
- initializer: parameter is DefaultFormalParameter
- ? buildOptionalTopLevelExpression(parameter.defaultValue)
- : null,
- type: buildType(
- resolutionMap.elementDeclaredByFormalParameter(parameter).type));
- if (parameter.isRequired) {
- positional.add(declaration);
- ++requiredParameterCount;
- declaration.initializer = null;
- } else if (parameter.isOptionalPositional) {
- positional.add(declaration);
- } else if (parameter.isNamed) {
- named.add(declaration);
- }
- }
- int offset = formalParameters?.offset ?? body.offset;
- int endOffset = body.endToken.offset;
- ast.AsyncMarker asyncMarker =
- getAsyncMarker(isAsync: body.isAsynchronous, isStar: body.isGenerator);
- return new ast.FunctionNode(buildOptionalFunctionBody(body),
- typeParameters: typeParameters,
- positionalParameters: positional,
- namedParameters: named,
- requiredParameterCount: requiredParameterCount,
- returnType: buildOptionalTypeAnnotation(returnType) ??
- inferredReturnType ??
- const ast.DynamicType(),
- asyncMarker: asyncMarker,
- dartAsyncMarker: asyncMarker)
- ..fileOffset = offset
- ..fileEndOffset = endOffset;
- }
-
- ast.Expression buildOptionalTopLevelExpression(Expression node) {
- return node == null ? null : buildTopLevelExpression(node);
- }
-
- ast.Expression buildTopLevelExpression(Expression node) {
- try {
- return _expressionBuilder.build(node);
- } on _CompilationError catch (e) {
- return buildThrowCompileTimeError(e.message);
- }
- }
-
- ast.Expression buildExpression(Expression node) {
- return _expressionBuilder.build(node);
- }
-
- ast.Expression buildOptionalExpression(Expression node) {
- return node == null ? null : _expressionBuilder.build(node);
- }
-
- Accessor buildLeftHandValue(Expression node) {
- return _expressionBuilder.buildLeftHandValue(node);
- }
-
- ast.Expression buildStringLiteral(Expression node) {
- List<ast.Expression> parts = <ast.Expression>[];
- new StringLiteralPartBuilder(this, parts).build(node);
- return parts.length == 1 && parts[0] is ast.StringLiteral
- ? parts[0]
- : new ast.StringConcatenation(parts);
- }
-
- ast.Expression buildThis() {
- return allowThis
- ? new ast.ThisExpression()
- : emitCompileTimeError(CompileTimeErrorCode.INVALID_REFERENCE_TO_THIS);
- }
-
- ast.Initializer buildInitializer(ConstructorInitializer node) {
- try {
- return new InitializerBuilder(this).build(node);
- } on _CompilationError catch (_) {
- return new ast.InvalidInitializer();
- }
- }
-
- bool isFinal(Element element) {
- return element is VariableElement && element.isFinal ||
- element is FunctionElement;
- }
-
- bool isConst(Element element) {
- return element is VariableElement && element.isConst;
- }
-
- ast.VariableDeclaration getVariableReference(LocalElement element) {
- return localVariables.putIfAbsent(element, () {
- return new ast.VariableDeclaration(element.name,
- isFinal: isFinal(element), isConst: isConst(element))
- ..fileOffset = element.nameOffset;
- });
- }
-
- ast.DartType getInferredVariableType(Element element) {
- if (!strongMode) return const ast.DynamicType();
- if (element is FunctionTypedElement) {
- return buildType(element.type);
- } else if (element is VariableElement) {
- return buildType(element.type);
- } else {
- log.severe('Unexpected variable element: $element');
- return const ast.DynamicType();
- }
- }
-
- ast.VariableDeclaration makeVariableDeclaration(LocalElement element,
- {ast.DartType type, ast.Expression initializer, int equalsOffset}) {
- var declaration = getVariableReference(element);
- if (equalsOffset != null) declaration.fileEqualsOffset = equalsOffset;
- declaration.type = type ?? getInferredVariableType(element);
- if (initializer != null) {
- declaration.initializer = initializer..parent = declaration;
- }
- return declaration;
- }
-
- /// Returns true if [arguments] can be accepted by [target]
- /// (not taking type checks into account).
- bool areArgumentsCompatible(
- FunctionTypedElement target, ast.Arguments arguments) {
- var positionals = arguments.positional;
- var parameters = target.parameters;
- // If the first unprovided parameter is required, there are too few
- // positional arguments.
- if (positionals.length < parameters.length &&
- parameters[positionals.length].isNotOptional) {
- return false;
- }
- // If there are more positional arguments than parameters, or if the last
- // positional argument corresponds to a named parameter, there are too many
- // positional arguments.
- if (positionals.length > parameters.length) return false;
- if (positionals.isNotEmpty && parameters[positionals.length - 1].isNamed) {
- return false; // Too many positional arguments.
- }
- if (arguments.named.isEmpty) return true;
- int firstNamedParameter = positionals.length;
- while (firstNamedParameter < parameters.length &&
- !parameters[firstNamedParameter].isNamed) {
- ++firstNamedParameter;
- }
- namedLoop:
- for (int i = 0; i < arguments.named.length; ++i) {
- String name = arguments.named[i].name;
- for (int j = firstNamedParameter; j < parameters.length; ++j) {
- if (parameters[j].isNamed && parameters[j].name == name) {
- continue namedLoop;
- }
- }
- return false;
- }
- return true;
- }
-
- /// Throws a NoSuchMethodError corresponding to a call to [memberName] on
- /// [receiver] with the given [arguments].
- ///
- /// If provided, [candidateTarget] provides the expected arity and argument
- /// names for the best candidate target.
- ast.Expression buildThrowNoSuchMethodError(
- ast.Expression receiver, String memberName, ast.Arguments arguments,
- {Element candidateTarget}) {
- // TODO(asgerf): When we have better integration with patch files, use
- // the internal constructor that provides a more detailed error message.
- ast.Expression candidateArgumentNames;
- if (candidateTarget is FunctionTypedElement) {
- candidateArgumentNames = new ast.ListLiteral(candidateTarget.parameters
- .map((p) => new ast.StringLiteral(p.name))
- .toList());
- } else {
- candidateArgumentNames = new ast.NullLiteral();
- }
- return new ast.Throw(new ast.ConstructorInvocation(
- loader.getCoreClassConstructorReference('NoSuchMethodError'),
- new ast.Arguments(<ast.Expression>[
- receiver,
- new ast.SymbolLiteral(memberName),
- new ast.ListLiteral(arguments.positional),
- new ast.MapLiteral(arguments.named.map((arg) {
- return new ast.MapEntry(new ast.SymbolLiteral(arg.name), arg.value);
- }).toList()),
- candidateArgumentNames
- ])));
- }
-
- ast.Expression buildThrowCompileTimeError(String message) {
- // The spec does not mandate a specific behavior in face of a compile-time
- // error. We just throw a string. The VM throws an uncatchable exception
- // for this case.
- // TOOD(asgerf): Should we add uncatchable exceptions to kernel?
- return new ast.Throw(new ast.StringLiteral(message));
- }
-
- ast.Expression buildThrowCompileTimeErrorFromCode(ErrorCode code,
- [List arguments]) {
- return buildThrowCompileTimeError(makeErrorMessage(code, arguments));
- }
-
- static final RegExp _errorMessagePattern = new RegExp(r'\{(\d+)\}');
-
- String makeErrorMessage(ErrorCode error, [List arguments]) {
- String message = error.message;
- if (arguments != null) {
- message = message.replaceAllMapped(_errorMessagePattern, (m) {
- String numberString = m.group(1);
- int index = int.parse(numberString);
- return arguments[index];
- });
- }
- return message;
- }
-
- /// Throws an exception that will be caught at the function level, to replace
- /// the entire function with a throw.
- emitCompileTimeError(ErrorCode error, [List arguments]) {
- throw new _CompilationError(makeErrorMessage(error, arguments));
- }
-
- ast.Expression buildThrowAbstractClassInstantiationError(String name) {
- return new ast.Throw(new ast.ConstructorInvocation(
- loader.getCoreClassConstructorReference(
- 'AbstractClassInstantiationError'),
- new ast.Arguments(<ast.Expression>[new ast.StringLiteral(name)])));
- }
-
- ast.Expression buildThrowFallThroughError() {
- return new ast.Throw(new ast.ConstructorInvocation(
- loader.getCoreClassConstructorReference('FallThroughError'),
- new ast.Arguments.empty()));
- }
-
- emitInvalidConstant([ErrorCode error]) {
- error ??= CompileTimeErrorCode.INVALID_CONSTANT;
- return emitCompileTimeError(error);
- }
-
- internalError(String message) {
- throw 'Internal error when compiling $location: $message';
- }
-
- unsupportedFeature(String feature) {
- throw new _CompilationError('$feature is not supported');
- }
-
- ast.Expression buildAnnotation(Annotation annotation) {
- Element element = annotation.element;
- if (annotation.arguments == null) {
- var target = resolveConcreteGet(element, null);
- return target == null
- ? new ast.InvalidExpression(null)
- : new ast.StaticGet(target);
- } else if (element is ConstructorElement && element.isConst) {
- var target = resolveConstructor(element);
- return target == null
- ? new ast.InvalidExpression(null)
- : new ast.ConstructorInvocation(
- target, _expressionBuilder.buildArguments(annotation.arguments),
- isConst: true);
- } else {
- return new ast.InvalidExpression(null);
- }
- }
-
- void addTransformerFlag(int flags) {
- // Overridden by MemberScope.
- }
-
- /// True if the body of the given method must return nothing.
- bool hasVoidReturn(ExecutableElement element) {
- return (strongMode && element.returnType.isVoid) ||
- (element is PropertyAccessorElement && element.isSetter) ||
- element.name == '[]=';
- }
-
- bool bodyHasVoidReturn(FunctionBody body) {
- AstNode parent = body.parent;
- return parent is MethodDeclaration && hasVoidReturn(parent.element) ||
- parent is FunctionDeclaration && hasVoidReturn(parent.element);
- }
-}
-
-/// A scope in which class type parameters are in scope, while not in scope
-/// of a specific member.
-class ClassScope extends ExpressionScope {
- @override
- bool get allowClassTypeParameters => true;
-
- ClassScope(ReferenceLevelLoader loader, ast.Library library)
- : super(loader, library);
-}
-
-/// Translates expressions, statements, and other constructs into [ast] nodes.
-///
-/// Naming convention:
-/// - `buildX` may not be given null as argument (it may crash the compiler).
-/// - `buildOptionalX` returns null or an empty list if given null
-/// - `buildMandatoryX` returns an invalid node if given null.
-class MemberScope extends ExpressionScope {
- /// A reference to the member currently being upgraded to body level.
- final ast.Member currentMember;
-
- MemberScope(ReferenceLevelLoader loader, ast.Member currentMember)
- : currentMember = currentMember,
- super(loader, currentMember.enclosingLibrary) {
- assert(currentMember != null);
- }
-
- ast.Class get currentClass => currentMember.enclosingClass;
-
- bool get allowThis => _memberHasThis(currentMember);
-
- @override
- bool get allowClassTypeParameters {
- return currentMember.isInstanceMember || currentMember is ast.Constructor;
- }
-
- /// Returns a string for debugging use, indicating the location of the member
- /// being built.
- String get location {
- var library = currentMember.enclosingLibrary?.importUri ?? '<No Library>';
- var className = currentMember.enclosingClass == null
- ? null
- : (currentMember.enclosingClass?.name ?? '<Anonymous Class>');
- var member =
- currentMember.name?.name ?? '<Anonymous ${currentMember.runtimeType}>';
- return [library, className, member].join('::');
- }
-
- bool _memberHasThis(ast.Member member) {
- return member is ast.Procedure && !member.isStatic ||
- member is ast.Constructor;
- }
-
- void addTransformerFlag(int flags) {
- currentMember.transformerFlags |= flags;
- }
-}
-
-class LabelStack {
- final List<String> labels; // Contains null for unlabeled targets.
- final LabelStack next;
- final List<ast.Statement> jumps = <ast.Statement>[];
- bool isSwitchTarget = false;
-
- LabelStack(String label, this.next) : labels = <String>[label];
- LabelStack.unlabeled(this.next) : labels = <String>[null];
- LabelStack.switchCase(String label, this.next)
- : isSwitchTarget = true,
- labels = <String>[label];
- LabelStack.many(this.labels, this.next);
-}
-
-class StatementBuilder extends GeneralizingAstVisitor<ast.Statement> {
- final ExpressionScope scope;
- LabelStack breakStack, continueStack;
-
- StatementBuilder(this.scope, [this.breakStack, this.continueStack]);
-
- ast.Statement build(Statement node) {
- ast.Statement result = node.accept(this);
- result.fileOffset = _getOffset(node);
- return result;
- }
-
- ast.Statement buildOptional(Statement node) {
- ast.Statement result = node?.accept(this);
- result?.fileOffset = _getOffset(node);
- return result;
- }
-
- int _getOffset(AstNode node) {
- return node.offset;
- }
-
- ast.Statement buildInScope(
- Statement node, LabelStack breakNode, LabelStack continueNode) {
- var oldBreak = this.breakStack;
- var oldContinue = this.continueStack;
- breakStack = breakNode;
- continueStack = continueNode;
- var result = build(node);
- this.breakStack = oldBreak;
- this.continueStack = oldContinue;
- return result;
- }
-
- void buildBlockMember(Statement node, List<ast.Statement> output) {
- if (node is LabeledStatement &&
- node.statement is VariableDeclarationStatement) {
- // If a variable is labeled, its scope is part of the enclosing block.
- LabeledStatement labeled = node;
- node = labeled.statement;
- }
- if (node is VariableDeclarationStatement) {
- VariableDeclarationList list = node.variables;
- ast.DartType type = scope.buildOptionalTypeAnnotation(list.type);
- for (VariableDeclaration decl in list.variables) {
- LocalElement local = decl.element as dynamic; // Cross cast.
- output.add(scope.makeVariableDeclaration(local,
- type: type,
- initializer: scope.buildOptionalExpression(decl.initializer),
- equalsOffset: decl.equals?.offset));
- }
- } else {
- output.add(build(node));
- }
- }
-
- ast.Statement makeBreakTarget(ast.Statement node, LabelStack stackNode) {
- if (stackNode.jumps.isEmpty) return node;
- var labeled = new ast.LabeledStatement(node);
- for (var jump in stackNode.jumps) {
- (jump as ast.BreakStatement).target = labeled;
- }
- return labeled;
- }
-
- LabelStack findLabelTarget(String label, LabelStack stack) {
- while (stack != null) {
- if (stack.labels.contains(label)) return stack;
- stack = stack.next;
- }
- return null;
- }
-
- ast.Statement visitAssertStatement(AssertStatement node) {
- return new ast.AssertStatement(scope.buildExpression(node.condition),
- message: scope.buildOptionalExpression(node.message));
- }
-
- ast.Statement visitBlock(Block node) {
- List<ast.Statement> statements = <ast.Statement>[];
- for (Statement statement in node.statements) {
- buildBlockMember(statement, statements);
- }
- return new ast.Block(statements);
- }
-
- ast.Statement visitBreakStatement(BreakStatement node) {
- var stackNode = findLabelTarget(node.label?.name, breakStack);
- if (stackNode == null) {
- return node.label == null
- ? scope.emitCompileTimeError(ParserErrorCode.BREAK_OUTSIDE_OF_LOOP)
- : scope.emitCompileTimeError(
- CompileTimeErrorCode.LABEL_UNDEFINED, [node.label.name]);
- }
- var result = new ast.BreakStatement(null);
- stackNode.jumps.add(result);
- return result;
- }
-
- ast.Statement visitContinueStatement(ContinueStatement node) {
- var stackNode = findLabelTarget(node.label?.name, continueStack);
- if (stackNode == null) {
- return node.label == null
- ? scope.emitCompileTimeError(ParserErrorCode.CONTINUE_OUTSIDE_OF_LOOP)
- : scope.emitCompileTimeError(
- CompileTimeErrorCode.LABEL_UNDEFINED, [node.label.name]);
- }
- var result = stackNode.isSwitchTarget
- ? new ast.ContinueSwitchStatement(null)
- : new ast.BreakStatement(null);
- stackNode.jumps.add(result);
- return result;
- }
-
- void addLoopLabels(Statement loop, LabelStack continueNode) {
- AstNode parent = loop.parent;
- if (parent is LabeledStatement) {
- for (var label in parent.labels) {
- continueNode.labels.add(label.label.name);
- }
- }
- }
-
- ast.Statement visitDoStatement(DoStatement node) {
- LabelStack breakNode = new LabelStack.unlabeled(breakStack);
- LabelStack continueNode = new LabelStack.unlabeled(continueStack);
- addLoopLabels(node, continueNode);
- var body = buildInScope(node.body, breakNode, continueNode);
- var loop = new ast.DoStatement(makeBreakTarget(body, continueNode),
- scope.buildExpression(node.condition));
- return makeBreakTarget(loop, breakNode);
- }
-
- ast.Statement visitWhileStatement(WhileStatement node) {
- LabelStack breakNode = new LabelStack.unlabeled(breakStack);
- LabelStack continueNode = new LabelStack.unlabeled(continueStack);
- addLoopLabels(node, continueNode);
- var body = buildInScope(node.body, breakNode, continueNode);
- var loop = new ast.WhileStatement(scope.buildExpression(node.condition),
- makeBreakTarget(body, continueNode));
- return makeBreakTarget(loop, breakNode);
- }
-
- ast.Statement visitEmptyStatement(EmptyStatement node) {
- return new ast.EmptyStatement();
- }
-
- ast.Statement visitExpressionStatement(ExpressionStatement node) {
- return new ast.ExpressionStatement(scope.buildExpression(node.expression));
- }
-
- static String _getLabelName(Label label) {
- return label.label.name;
- }
-
- ast.Statement visitLabeledStatement(LabeledStatement node) {
- // Only set up breaks here. Loops handle labeling on their own.
- var breakNode = new LabelStack.many(
- node.labels.map(_getLabelName).toList(), breakStack);
- var body = buildInScope(node.statement, breakNode, continueStack);
- return makeBreakTarget(body, breakNode);
- }
-
- static bool isBreakingExpression(ast.Expression node) {
- return node is ast.Throw || node is ast.Rethrow;
- }
-
- static bool isBreakingStatement(ast.Statement node) {
- return node is ast.BreakStatement ||
- node is ast.ContinueSwitchStatement ||
- node is ast.ReturnStatement ||
- node is ast.ExpressionStatement &&
- isBreakingExpression(node.expression);
- }
-
- ast.Statement visitSwitchStatement(SwitchStatement node) {
- // Group all cases into case blocks. Use parallel lists to collect the
- // intermediate terms until we are ready to create the AST nodes.
- LabelStack breakNode = new LabelStack.unlabeled(breakStack);
- LabelStack continueNode = continueStack;
- var cases = <ast.SwitchCase>[];
- var bodies = <List<Statement>>[];
- var labelToNode = <String, ast.SwitchCase>{};
- ast.SwitchCase currentCase = null;
- for (var member in node.members) {
- if (currentCase != null && currentCase.isDefault) {
- var error = member is SwitchCase
- ? ParserErrorCode.SWITCH_HAS_CASE_AFTER_DEFAULT_CASE
- : ParserErrorCode.SWITCH_HAS_MULTIPLE_DEFAULT_CASES;
- return scope.emitCompileTimeError(error);
- }
- if (currentCase == null) {
- currentCase = new ast.SwitchCase(<ast.Expression>[], <int>[], null);
- cases.add(currentCase);
- }
- if (member is SwitchCase) {
- var expression = scope.buildExpression(member.expression);
- currentCase.expressions.add(expression..parent = currentCase);
- currentCase.expressionOffsets.add(expression.fileOffset);
- } else {
- currentCase.isDefault = true;
- }
- for (Label label in member.labels) {
- continueNode =
- new LabelStack.switchCase(label.label.name, continueNode);
- labelToNode[label.label.name] = currentCase;
- }
- if (member.statements?.isNotEmpty ?? false) {
- bodies.add(member.statements);
- currentCase = null;
- }
- }
- if (currentCase != null) {
- // Close off a trailing block.
- bodies.add(const <Statement>[]);
- currentCase = null;
- }
- // Now that the label environment is set up, build the bodies.
- var oldBreak = this.breakStack;
- var oldContinue = this.continueStack;
- this.breakStack = breakNode;
- this.continueStack = continueNode;
- for (int i = 0; i < cases.length; ++i) {
- var blockNodes = <ast.Statement>[];
- for (var statement in bodies[i]) {
- buildBlockMember(statement, blockNodes);
- }
- if (blockNodes.isEmpty || !isBreakingStatement(blockNodes.last)) {
- if (i < cases.length - 1) {
- blockNodes.add(
- new ast.ExpressionStatement(scope.buildThrowFallThroughError()));
- } else {
- var jump = new ast.BreakStatement(null);
- blockNodes.add(jump);
- breakNode.jumps.add(jump);
- }
- }
- cases[i].body = new ast.Block(blockNodes)..parent = cases[i];
- }
- // Unwind the stack of case labels and bind their jumps to the case target.
- while (continueNode != oldContinue) {
- for (var jump in continueNode.jumps) {
- (jump as ast.ContinueSwitchStatement).target =
- labelToNode[continueNode.labels.first];
- }
- continueNode = continueNode.next;
- }
- var expression = scope.buildExpression(node.expression);
- var result = new ast.SwitchStatement(expression, cases);
- this.breakStack = oldBreak;
- this.continueStack = oldContinue;
- return makeBreakTarget(result, breakNode);
- }
-
- ast.Statement visitForStatement(ForStatement node) {
- List<ast.VariableDeclaration> variables = <ast.VariableDeclaration>[];
- ast.Expression initialExpression;
- if (node.variables != null) {
- VariableDeclarationList list = node.variables;
- var type = scope.buildOptionalTypeAnnotation(list.type);
- for (var variable in list.variables) {
- LocalElement local = variable.element as dynamic; // Cross cast.
- variables.add(scope.makeVariableDeclaration(local,
- initializer: scope.buildOptionalExpression(variable.initializer),
- type: type,
- equalsOffset: variable.equals?.offset));
- }
- } else if (node.initialization != null) {
- initialExpression = scope.buildExpression(node.initialization);
- }
- var breakNode = new LabelStack.unlabeled(breakStack);
- var continueNode = new LabelStack.unlabeled(continueStack);
- addLoopLabels(node, continueNode);
- var body = buildInScope(node.body, breakNode, continueNode);
- var loop = new ast.ForStatement(
- variables,
- scope.buildOptionalExpression(node.condition),
- node.updaters.map(scope.buildExpression).toList(),
- makeBreakTarget(body, continueNode));
- loop = makeBreakTarget(loop, breakNode);
- if (initialExpression != null) {
- return new ast.Block(<ast.Statement>[
- new ast.ExpressionStatement(initialExpression),
- loop
- ]);
- }
- return loop;
- }
-
- DartType iterableElementType(DartType iterable) {
- if (iterable is InterfaceType) {
- var iterator = iterable.lookUpInheritedGetter('iterator')?.returnType;
- if (iterator is InterfaceType) {
- return iterator.lookUpInheritedGetter('current')?.returnType;
- }
- }
- return null;
- }
-
- DartType streamElementType(DartType stream) {
- if (stream is InterfaceType) {
- var class_ = stream.element;
- if (class_.library.isDartAsync &&
- class_.name == 'Stream' &&
- stream.typeArguments.length == 1) {
- return stream.typeArguments[0];
- }
- }
- return null;
- }
-
- ast.Statement visitForEachStatement(ForEachStatement node) {
- ast.VariableDeclaration variable;
- Accessor leftHand;
- if (node.loopVariable != null) {
- DeclaredIdentifier loopVariable = node.loopVariable;
- variable = scope.makeVariableDeclaration(loopVariable.element,
- type: scope.buildOptionalTypeAnnotation(loopVariable.type));
- } else if (node.identifier != null) {
- leftHand = scope.buildLeftHandValue(node.identifier);
- variable = new ast.VariableDeclaration(null, isFinal: true);
- if (scope.strongMode) {
- var containerType = node.iterable.staticType;
- DartType elementType = node.awaitKeyword != null
- ? streamElementType(containerType)
- : iterableElementType(containerType);
- if (elementType != null) {
- variable.type = scope.buildType(elementType);
- }
- }
- }
- var breakNode = new LabelStack.unlabeled(breakStack);
- var continueNode = new LabelStack.unlabeled(continueStack);
- addLoopLabels(node, continueNode);
- var body = buildInScope(node.body, breakNode, continueNode);
- if (leftHand != null) {
- // Desugar
- //
- // for (x in e) BODY
- //
- // to
- //
- // for (var tmp in e) {
- // x = tmp;
- // BODY
- // }
- body = new ast.Block(<ast.Statement>[
- new ast.ExpressionStatement(leftHand
- .buildAssignment(new ast.VariableGet(variable), voidContext: true)),
- body
- ]);
- }
- var loop = new ast.ForInStatement(
- variable,
- scope.buildExpression(node.iterable),
- makeBreakTarget(body, continueNode),
- isAsync: node.awaitKeyword != null)
- ..fileOffset = node.offset;
- return makeBreakTarget(loop, breakNode);
- }
-
- ast.Statement visitIfStatement(IfStatement node) {
- return new ast.IfStatement(scope.buildExpression(node.condition),
- build(node.thenStatement), buildOptional(node.elseStatement));
- }
-
- ast.Statement visitReturnStatement(ReturnStatement node) {
- return new ast.ReturnStatement(
- scope.buildOptionalExpression(node.expression));
- }
-
- ast.Catch buildCatchClause(CatchClause node) {
- var exceptionVariable = node.exceptionParameter == null
- ? null
- : scope.makeVariableDeclaration(node.exceptionParameter.staticElement);
- var stackTraceVariable = node.stackTraceParameter == null
- ? null
- : scope.makeVariableDeclaration(node.stackTraceParameter.staticElement);
- return new ast.Catch(exceptionVariable, build(node.body),
- stackTrace: stackTraceVariable,
- guard: scope.buildOptionalTypeAnnotation(node.exceptionType) ??
- const ast.DynamicType());
- }
-
- ast.Statement visitTryStatement(TryStatement node) {
- ast.Statement statement = build(node.body);
- if (node.catchClauses.isNotEmpty) {
- statement = new ast.TryCatch(
- statement, node.catchClauses.map(buildCatchClause).toList());
- }
- if (node.finallyBlock != null) {
- statement = new ast.TryFinally(statement, build(node.finallyBlock));
- }
- return statement;
- }
-
- ast.Statement visitVariableDeclarationStatement(
- VariableDeclarationStatement node) {
- // This is only reached when a variable is declared in non-block level,
- // because visitBlock intercepts visits to its children.
- // An example where we hit this case is:
- //
- // if (foo) var x = 5, y = x + 1;
- //
- // We wrap these in a block:
- //
- // if (foo) {
- // var x = 5;
- // var y = x + 1;
- // }
- //
- // Note that the use of a block here is required by the kernel language,
- // even if there is only one variable declaration.
- List<ast.Statement> statements = <ast.Statement>[];
- buildBlockMember(node, statements);
- return new ast.Block(statements);
- }
-
- ast.Statement visitYieldStatement(YieldStatement node) {
- return new ast.YieldStatement(scope.buildExpression(node.expression),
- isYieldStar: node.star != null);
- }
-
- ast.Statement visitFunctionDeclarationStatement(
- FunctionDeclarationStatement node) {
- var declaration = node.functionDeclaration;
- var expression = declaration.functionExpression;
- LocalElement element = declaration.element as dynamic; // Cross cast.
- return new ast.FunctionDeclaration(
- scope.makeVariableDeclaration(element,
- type: scope.buildType(declaration.element.type)),
- scope.buildFunctionNode(expression.parameters, expression.body,
- typeParameters: scope.buildOptionalTypeParameterList(
- expression.typeParameters,
- strongModeOnly: true),
- returnType: declaration.returnType))
- ..fileOffset = node.offset;
- }
-
- @override
- visitStatement(Statement node) {
- return scope.internalError('Unhandled statement ${node.runtimeType}');
- }
-}
-
-class ExpressionBuilder
- extends GeneralizingAstVisitor /* <ast.Expression | Accessor> */ {
- final ExpressionScope scope;
- ast.VariableDeclaration cascadeReceiver;
- ExpressionBuilder(this.scope);
-
- ast.Expression build(Expression node) {
- var result = node.accept(this);
- if (result is Accessor) {
- result = result.buildSimpleRead();
- }
- // For some method invocations we have already set a file offset to
- // override the default behavior of _getOffset.
- if (node is! MethodInvocation || result.fileOffset < 0) {
- result.fileOffset = _getOffset(node);
- }
- return result;
- }
-
- int _getOffset(AstNode node) {
- if (node is MethodInvocation) {
- return node.methodName.offset;
- } else if (node is InstanceCreationExpression) {
- return node.constructorName.offset;
- } else if (node is BinaryExpression) {
- return node.operator.offset;
- } else if (node is PrefixedIdentifier) {
- return node.identifier.offset;
- } else if (node is AssignmentExpression) {
- return _getOffset(node.leftHandSide);
- } else if (node is PropertyAccess) {
- return node.propertyName.offset;
- } else if (node is IsExpression) {
- return node.isOperator.offset;
- } else if (node is AsExpression) {
- return node.asOperator.offset;
- } else if (node is StringLiteral) {
- // Use a catch-all for StringInterpolation and AdjacentStrings:
- // the debugger stops at the end.
- return node.end;
- } else if (node is IndexExpression) {
- return node.leftBracket.offset;
- }
- return node.offset;
- }
-
- Accessor buildLeftHandValue(Expression node) {
- var result = node.accept(this);
- if (result is Accessor) {
- return result;
- } else {
- return new ReadOnlyAccessor(result, ast.TreeNode.noOffset);
- }
- }
-
- ast.Expression visitAsExpression(AsExpression node) {
- return new ast.AsExpression(
- build(node.expression), scope.buildTypeAnnotation(node.type));
- }
-
- ast.Expression visitAssignmentExpression(AssignmentExpression node) {
- bool voidContext = isInVoidContext(node);
- String operator = node.operator.value();
- var leftHand = buildLeftHandValue(node.leftHandSide);
- var rightHand = build(node.rightHandSide);
- if (operator == '=') {
- return leftHand.buildAssignment(rightHand, voidContext: voidContext);
- } else if (operator == '??=') {
- return leftHand.buildNullAwareAssignment(
- rightHand, scope.buildType(node.staticType),
- voidContext: voidContext);
- } else {
- // Cut off the trailing '='.
- var name = new ast.Name(operator.substring(0, operator.length - 1));
- return leftHand.buildCompoundAssignment(name, rightHand,
- offset: node.offset,
- voidContext: voidContext,
- interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
- }
- }
-
- ast.Expression visitAwaitExpression(AwaitExpression node) {
- return new ast.AwaitExpression(build(node.expression));
- }
-
- ast.Arguments buildSingleArgument(Expression node) {
- return new ast.Arguments(<ast.Expression>[build(node)]);
- }
-
- ast.Expression visitBinaryExpression(BinaryExpression node) {
- String operator = node.operator.value();
- if (operator == '&&' || operator == '||') {
- return new ast.LogicalExpression(
- build(node.leftOperand), operator, build(node.rightOperand));
- }
- if (operator == '??') {
- ast.Expression leftOperand = build(node.leftOperand);
- if (leftOperand is ast.VariableGet) {
- return new ast.ConditionalExpression(
- buildIsNull(leftOperand, offset: node.leftOperand.offset),
- build(node.rightOperand),
- new ast.VariableGet(leftOperand.variable),
- scope.getInferredType(node));
- } else {
- var variable = new ast.VariableDeclaration.forValue(leftOperand);
- return new ast.Let(
- variable,
- new ast.ConditionalExpression(
- buildIsNull(new ast.VariableGet(variable),
- offset: leftOperand.fileOffset),
- build(node.rightOperand),
- new ast.VariableGet(variable),
- scope.getInferredType(node)));
- }
- }
- bool isNegated = false;
- if (operator == '!=') {
- isNegated = true;
- operator = '==';
- }
- ast.Expression expression;
- if (node.leftOperand is SuperExpression) {
- scope.addTransformerFlag(TransformerFlag.superCalls);
- expression = new ast.SuperMethodInvocation(
- new ast.Name(operator),
- buildSingleArgument(node.rightOperand),
- scope.resolveConcreteMethod(node.staticElement));
- } else {
- expression = new ast.MethodInvocation(
- build(node.leftOperand),
- new ast.Name(operator),
- buildSingleArgument(node.rightOperand),
- scope.resolveInterfaceMethod(node.staticElement));
- }
- return isNegated ? new ast.Not(expression) : expression;
- }
-
- ast.Expression visitBooleanLiteral(BooleanLiteral node) {
- return new ast.BoolLiteral(node.value);
- }
-
- ast.Expression visitDoubleLiteral(DoubleLiteral node) {
- return new ast.DoubleLiteral(node.value);
- }
-
- ast.Expression visitIntegerLiteral(IntegerLiteral node) {
- return new ast.IntLiteral(node.value);
- }
-
- ast.Expression visitNullLiteral(NullLiteral node) {
- return new ast.NullLiteral();
- }
-
- ast.Expression visitSimpleStringLiteral(SimpleStringLiteral node) {
- return new ast.StringLiteral(node.value);
- }
-
- ast.Expression visitStringLiteral(StringLiteral node) {
- return scope.buildStringLiteral(node);
- }
-
- static Object _getTokenValue(Token token) {
- return token.value();
- }
-
- ast.Expression visitSymbolLiteral(SymbolLiteral node) {
- String value = node.components.map(_getTokenValue).join('.');
- return new ast.SymbolLiteral(value);
- }
-
- ast.Expression visitCascadeExpression(CascadeExpression node) {
- var receiver = build(node.target);
- // If receiver is a variable it would be tempting to reuse it, but it
- // might be reassigned in one of the cascade sections.
- var receiverVariable = new ast.VariableDeclaration.forValue(receiver,
- type: scope.getInferredType(node.target));
- var oldReceiver = this.cascadeReceiver;
- cascadeReceiver = receiverVariable;
- ast.Expression result = new ast.VariableGet(receiverVariable);
- for (var section in node.cascadeSections.reversed) {
- var dummy = new ast.VariableDeclaration.forValue(build(section));
- result = new ast.Let(dummy, result);
- }
- cascadeReceiver = oldReceiver;
- return new ast.Let(receiverVariable, result);
- }
-
- ast.Expression makeCascadeReceiver() {
- assert(cascadeReceiver != null);
- return new ast.VariableGet(cascadeReceiver);
- }
-
- ast.Expression visitConditionalExpression(ConditionalExpression node) {
- return new ast.ConditionalExpression(
- build(node.condition),
- build(node.thenExpression),
- build(node.elseExpression),
- scope.getInferredType(node));
- }
-
- ast.Expression visitFunctionExpression(FunctionExpression node) {
- return new ast.FunctionExpression(scope.buildFunctionNode(
- node.parameters, node.body,
- typeParameters: scope.buildOptionalTypeParameterList(
- node.typeParameters,
- strongModeOnly: true),
- inferredReturnType: scope.getInferredReturnType(node)));
- }
-
- ast.Arguments buildArguments(ArgumentList valueArguments,
- {TypeArgumentList explicitTypeArguments,
- List<ast.DartType> inferTypeArguments()}) {
- var positional = <ast.Expression>[];
- var named = <ast.NamedExpression>[];
- for (var argument in valueArguments.arguments) {
- if (argument is NamedExpression) {
- named.add(new ast.NamedExpression(
- argument.name.label.name, build(argument.expression)));
- } else if (named.isNotEmpty) {
- return scope.emitCompileTimeError(
- ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT);
- } else {
- positional.add(build(argument));
- }
- }
- List<ast.DartType> typeArguments;
- if (explicitTypeArguments != null) {
- typeArguments = scope.buildTypeArgumentList(explicitTypeArguments);
- } else if (inferTypeArguments != null) {
- typeArguments = inferTypeArguments();
- }
- return new ast.Arguments(positional, named: named, types: typeArguments);
- }
-
- ast.Arguments buildArgumentsForInvocation(InvocationExpression node) {
- if (scope.strongMode) {
- return buildArguments(node.argumentList,
- explicitTypeArguments: node.typeArguments,
- inferTypeArguments: () =>
- scope.getInferredInvocationTypeArguments(node));
- } else {
- return buildArguments(node.argumentList);
- }
- }
-
- static final ast.Name callName = new ast.Name('call');
-
- ast.Expression visitFunctionExpressionInvocation(
- FunctionExpressionInvocation node) {
- return new ast.MethodInvocation(
- build(node.function),
- callName,
- buildArgumentsForInvocation(node),
- scope.resolveInterfaceFunctionCallOnType(node.function.staticType));
- }
-
- visitPrefixedIdentifier(PrefixedIdentifier node) {
- switch (ElementKind.of(node.prefix.staticElement)) {
- case ElementKind.CLASS:
- case ElementKind.LIBRARY:
- case ElementKind.PREFIX:
- case ElementKind.IMPORT:
- if (node.identifier.staticElement != null) {
- // Should be resolved to a static access.
- // Do not invoke 'build', because the identifier should be seen as a
- // left-hand value or an expression depending on the context.
- return visitSimpleIdentifier(node.identifier);
- }
- // Unresolved access on a class or library.
- return scope.unresolvedAccess(node.identifier.name);
-
- case ElementKind.DYNAMIC:
- case ElementKind.FUNCTION_TYPE_ALIAS:
- case ElementKind.TYPE_PARAMETER:
- // TODO: Check with the spec to see exactly when a type literal can be
- // used in a property access without surrounding parentheses.
- // For now, just fall through to the property access case.
-
- case ElementKind.FIELD:
- case ElementKind.TOP_LEVEL_VARIABLE:
- case ElementKind.FUNCTION:
- case ElementKind.METHOD:
- case ElementKind.GETTER:
- case ElementKind.SETTER:
- case ElementKind.LOCAL_VARIABLE:
- case ElementKind.PARAMETER:
- case ElementKind.ERROR:
- Element element = node.identifier.staticElement;
- Element auxiliary = node.identifier.auxiliaryElements?.staticElement;
- return PropertyAccessor.make(
- build(node.prefix),
- scope.buildName(node.identifier),
- scope.resolveInterfaceGet(element, auxiliary),
- scope.resolveInterfaceSet(element, auxiliary));
-
- case ElementKind.UNIVERSE:
- case ElementKind.NAME:
- case ElementKind.CONSTRUCTOR:
- case ElementKind.EXPORT:
- case ElementKind.LABEL:
- default:
- return scope.internalError(
- 'Unexpected element kind: ${node.prefix.staticElement}');
- }
- }
-
- bool isStatic(Element element) {
- if (element is ClassMemberElement) {
- return element.isStatic || element.enclosingElement == null;
- }
- if (element is PropertyAccessorElement) {
- return element.isStatic || element.enclosingElement == null;
- }
- if (element is FunctionElement) {
- return element.isStatic;
- }
- return false;
- }
-
- visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.staticElement;
- switch (ElementKind.of(element)) {
- case ElementKind.CLASS:
- case ElementKind.DYNAMIC:
- case ElementKind.FUNCTION_TYPE_ALIAS:
- case ElementKind.TYPE_PARAMETER:
- return new ast.TypeLiteral(scope.buildTypeAnnotation(node));
-
- case ElementKind.ERROR: // This covers the case where nothing was found.
- if (!scope.allowThis) {
- return scope.unresolvedAccess(node.name);
- }
- return PropertyAccessor.make(
- scope.buildThis(), scope.buildName(node), null, null);
-
- case ElementKind.FIELD:
- case ElementKind.TOP_LEVEL_VARIABLE:
- case ElementKind.GETTER:
- case ElementKind.SETTER:
- case ElementKind.METHOD:
- Element auxiliary = node.auxiliaryElements?.staticElement;
- if (isStatic(element)) {
- return scope.staticAccess(node.name, element, auxiliary);
- }
- if (!scope.allowThis) {
- return scope.unresolvedAccess(node.name);
- }
- return PropertyAccessor.make(
- scope.buildThis(),
- scope.buildName(node),
- scope.resolveInterfaceGet(element, auxiliary),
- scope.resolveInterfaceSet(element, auxiliary));
-
- case ElementKind.FUNCTION:
- FunctionElement function = element;
- if (isTopLevelFunction(function)) {
- return scope.staticAccess(node.name, function);
- }
- if (function == function.library.loadLibraryFunction) {
- return scope.unsupportedFeature('Deferred loading');
- }
- return new VariableAccessor(
- scope.getVariableReference(function), null, ast.TreeNode.noOffset);
-
- case ElementKind.LOCAL_VARIABLE:
- case ElementKind.PARAMETER:
- VariableElement variable = element;
- var type = identical(node.staticType, variable.type)
- ? null
- : scope.buildType(node.staticType);
- return new VariableAccessor(
- scope.getVariableReference(element), type, ast.TreeNode.noOffset);
-
- case ElementKind.IMPORT:
- case ElementKind.LIBRARY:
- case ElementKind.PREFIX:
- return scope.emitCompileTimeError(
- CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
- [node.name]);
-
- case ElementKind.COMPILATION_UNIT:
- case ElementKind.CONSTRUCTOR:
- case ElementKind.EXPORT:
- case ElementKind.LABEL:
- case ElementKind.UNIVERSE:
- case ElementKind.NAME:
- default:
- return scope.internalError('Unexpected element kind: $element');
- }
- }
-
- visitIndexExpression(IndexExpression node) {
- Element element = node.staticElement;
- Element auxiliary = node.auxiliaryElements?.staticElement;
- if (node.isCascaded) {
- return IndexAccessor.make(
- makeCascadeReceiver(),
- build(node.index),
- scope.resolveInterfaceIndexGet(element, auxiliary),
- scope.resolveInterfaceIndexSet(element, auxiliary));
- } else if (node.target is SuperExpression) {
- scope.addTransformerFlag(TransformerFlag.superCalls);
- return new SuperIndexAccessor(
- build(node.index),
- scope.resolveConcreteIndexGet(element, auxiliary),
- scope.resolveConcreteIndexSet(element, auxiliary),
- ast.TreeNode.noOffset);
- } else {
- return IndexAccessor.make(
- build(node.target),
- build(node.index),
- scope.resolveInterfaceIndexGet(element, auxiliary),
- scope.resolveInterfaceIndexSet(element, auxiliary));
- }
- }
-
- /// Follows any number of redirecting factories, returning the effective
- /// target or `null` if a cycle is found.
- ///
- /// The returned element is a [Member] if the type arguments to the effective
- /// target are different from the original arguments.
- ConstructorElement getEffectiveFactoryTarget(ConstructorElement element) {
- ConstructorElement anchor = null;
- int n = 1;
- while (element.isFactory && element.redirectedConstructor != null) {
- element = element.redirectedConstructor;
- var base = ReferenceScope.getBaseElement(element);
- if (base == anchor) return null; // Cyclic redirection.
- if (n & ++n == 0) {
- anchor = base;
- }
- }
- return element;
- }
-
- /// Forces the list of type arguments to have the specified length. If the
- /// length was changed, all type arguments are changed to `dynamic`.
- void _coerceTypeArgumentArity(List<ast.DartType> typeArguments, int arity) {
- if (typeArguments.length != arity) {
- typeArguments.length = arity;
- typeArguments.fillRange(0, arity, const ast.DynamicType());
- }
- }
-
- ast.Expression visitInstanceCreationExpression(
- InstanceCreationExpression node) {
- ConstructorElement element = node.staticElement;
- ClassElement classElement = element?.enclosingElement;
- List<ast.DartType> inferTypeArguments() {
- var inferredType = scope.getInferredType(node);
- if (inferredType is ast.InterfaceType) {
- return inferredType.typeArguments.toList();
- }
- int numberOfTypeArguments =
- classElement == null ? 0 : classElement.typeParameters.length;
- return new List<ast.DartType>.filled(
- numberOfTypeArguments, const ast.DynamicType(),
- growable: true);
- }
-
- var arguments = buildArguments(node.argumentList,
- explicitTypeArguments: node.constructorName.type.typeArguments,
- inferTypeArguments: inferTypeArguments);
- ast.Expression noSuchMethodError() {
- return node.isConst
- ? scope.emitInvalidConstant()
- : scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), '${node.constructorName}', arguments,
- candidateTarget: element);
- }
-
- if (element == null) {
- return noSuchMethodError();
- }
- assert(classElement != null);
- var redirect = getEffectiveFactoryTarget(element);
- if (redirect == null) {
- return scope.buildThrowCompileTimeError(
- CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT.message);
- }
- if (redirect != element) {
- ast.InterfaceType returnType = scope.buildType(redirect.returnType);
- arguments.types
- ..clear()
- ..addAll(returnType.typeArguments);
- element = redirect;
- classElement = element.enclosingElement;
- }
- element = ReferenceScope.getBaseElement(element);
- if (node.isConst && !element.isConst) {
- return scope
- .emitInvalidConstant(CompileTimeErrorCode.CONST_WITH_NON_CONST);
- }
- if (classElement.isEnum) {
- return scope.emitCompileTimeError(CompileTimeErrorCode.INSTANTIATE_ENUM);
- }
- _coerceTypeArgumentArity(
- arguments.types, classElement.typeParameters.length);
- if (element.isFactory) {
- ast.Member target = scope.resolveConcreteMethod(element);
- if (target is ast.Procedure &&
- scope.areArgumentsCompatible(element, arguments)) {
- return new ast.StaticInvocation(target, arguments,
- isConst: node.isConst);
- } else {
- return noSuchMethodError();
- }
- }
- if (classElement.isAbstract) {
- return node.isConst
- ? scope.emitInvalidConstant()
- : scope.buildThrowAbstractClassInstantiationError(classElement.name);
- }
- ast.Constructor constructor = scope.resolveConstructor(element);
- if (constructor != null &&
- scope.areArgumentsCompatible(element, arguments)) {
- return new ast.ConstructorInvocation(constructor, arguments,
- isConst: node.isConst);
- } else {
- return noSuchMethodError();
- }
- }
-
- ast.Expression visitIsExpression(IsExpression node) {
- if (node.notOperator != null) {
- // Put offset on the IsExpression for "is!" cases:
- // As it is wrapped in a not, it won't get an offset otherwise.
- return new ast.Not(new ast.IsExpression(
- build(node.expression), scope.buildTypeAnnotation(node.type))
- ..fileOffset = _getOffset(node));
- } else {
- return new ast.IsExpression(
- build(node.expression), scope.buildTypeAnnotation(node.type));
- }
- }
-
- /// Emit a method invocation, either as a direct call `o.f(x)` or decomposed
- /// into a getter and function invocation `o.f.call(x)`.
- ast.Expression buildDecomposableMethodInvocation(ast.Expression receiver,
- ast.Name name, ast.Arguments arguments, Element targetElement) {
- // Try to emit a typed call to an interface method.
- ast.Procedure targetMethod = scope.resolveInterfaceMethod(targetElement);
- if (targetMethod != null) {
- return new ast.MethodInvocation(receiver, name, arguments, targetMethod);
- }
- // Try to emit a typed call to getter or field and call the returned
- // function.
- ast.Member targetGetter = scope.resolveInterfaceGet(targetElement, null);
- if (targetGetter != null) {
- return new ast.MethodInvocation(
- new ast.PropertyGet(receiver, name, targetGetter),
- callName,
- arguments,
- scope.resolveInterfaceFunctionCall(targetElement));
- }
- // Emit a dynamic call.
- return new ast.MethodInvocation(receiver, name, arguments);
- }
-
- ast.Expression visitMethodInvocation(MethodInvocation node) {
- Element element = node.methodName.staticElement;
- if (element != null && element == element.library?.loadLibraryFunction) {
- return scope.unsupportedFeature('Deferred loading');
- }
- var target = node.target;
- if (node.isCascaded) {
- return buildDecomposableMethodInvocation(
- makeCascadeReceiver(),
- scope.buildName(node.methodName),
- buildArgumentsForInvocation(node),
- element);
- } else if (target is SuperExpression) {
- scope.addTransformerFlag(TransformerFlag.superCalls);
- return new ast.SuperMethodInvocation(
- scope.buildName(node.methodName),
- buildArgumentsForInvocation(node),
- scope.resolveConcreteMethod(element));
- } else if (isLocal(element)) {
- // Set the offset directly: Normally the offset is at the start of the
- // method, but in this case, because we insert a '.call', we want it at
- // the end instead.
- return new ast.MethodInvocation(
- new ast.VariableGet(scope.getVariableReference(element)),
- callName,
- buildArgumentsForInvocation(node),
- scope.resolveInterfaceFunctionCall(element))
- ..fileOffset = node.methodName.end;
- } else if (isStaticMethod(element)) {
- var method = scope.resolveConcreteMethod(element);
- var arguments = buildArgumentsForInvocation(node);
- if (method == null || !scope.areArgumentsCompatible(element, arguments)) {
- return scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), node.methodName.name, arguments,
- candidateTarget: element);
- }
- return new ast.StaticInvocation(method, arguments);
- } else if (isStaticVariableOrGetter(element)) {
- var method = scope.resolveConcreteGet(element, null);
- if (method == null) {
- return scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), node.methodName.name, new ast.Arguments([]),
- candidateTarget: element);
- }
- // Set the offset directly: Normally the offset is at the start of the
- // method, but in this case, because we insert a '.call', we want it at
- // the end instead.
- return new ast.MethodInvocation(
- new ast.StaticGet(method),
- callName,
- buildArgumentsForInvocation(node),
- scope.resolveInterfaceFunctionCall(element))
- ..fileOffset = node.methodName.end;
- } else if (target == null && !scope.allowThis ||
- target is Identifier && target.staticElement is ClassElement ||
- target is Identifier && target.staticElement is PrefixElement) {
- return scope.buildThrowNoSuchMethodError(new ast.NullLiteral(),
- node.methodName.name, buildArgumentsForInvocation(node),
- candidateTarget: element);
- } else if (target == null) {
- return buildDecomposableMethodInvocation(
- scope.buildThis(),
- scope.buildName(node.methodName),
- buildArgumentsForInvocation(node),
- element);
- } else if (node.operator.value() == '?.') {
- var receiver = makeOrReuseVariable(build(target));
- return makeLet(
- receiver,
- new ast.ConditionalExpression(
- buildIsNull(new ast.VariableGet(receiver)),
- new ast.NullLiteral(),
- buildDecomposableMethodInvocation(
- new ast.VariableGet(receiver),
- scope.buildName(node.methodName),
- buildArgumentsForInvocation(node),
- element)
- ..fileOffset = node.methodName.offset,
- scope.buildType(node.staticType)));
- } else {
- return buildDecomposableMethodInvocation(
- build(node.target),
- scope.buildName(node.methodName),
- buildArgumentsForInvocation(node),
- element);
- }
- }
-
- ast.Expression visitNamedExpression(NamedExpression node) {
- return scope.internalError('Unexpected named expression');
- }
-
- ast.Expression visitParenthesizedExpression(ParenthesizedExpression node) {
- return build(node.expression);
- }
-
- bool isInVoidContext(Expression node) {
- AstNode parent = node.parent;
- return parent is ForStatement &&
- (parent.updaters.contains(node) || parent.initialization == node) ||
- parent is ExpressionStatement ||
- parent is ExpressionFunctionBody && scope.bodyHasVoidReturn(parent);
- }
-
- ast.Expression visitPostfixExpression(PostfixExpression node) {
- String operator = node.operator.value();
- switch (operator) {
- case '++':
- case '--':
- var leftHand = buildLeftHandValue(node.operand);
- var binaryOperator = new ast.Name(operator[0]);
- return leftHand.buildPostfixIncrement(binaryOperator,
- offset: node.operator.offset,
- voidContext: isInVoidContext(node),
- interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
-
- default:
- return scope.internalError('Invalid postfix operator $operator');
- }
- }
-
- ast.Expression visitPrefixExpression(PrefixExpression node) {
- String operator = node.operator.value();
- switch (operator) {
- case '-':
- case '~':
- var name = new ast.Name(operator == '-' ? 'unary-' : '~');
- if (node.operand is SuperExpression) {
- scope.addTransformerFlag(TransformerFlag.superCalls);
- return new ast.SuperMethodInvocation(name, new ast.Arguments.empty(),
- scope.resolveConcreteMethod(node.staticElement));
- }
- return new ast.MethodInvocation(
- build(node.operand),
- name,
- new ast.Arguments.empty(),
- scope.resolveInterfaceMethod(node.staticElement));
-
- case '!':
- return new ast.Not(build(node.operand));
-
- case '++':
- case '--':
- var leftHand = buildLeftHandValue(node.operand);
- var binaryOperator = new ast.Name(operator[0]);
- return leftHand.buildPrefixIncrement(binaryOperator,
- offset: node.offset,
- interfaceTarget: scope.resolveInterfaceMethod(node.staticElement));
-
- default:
- return scope.internalError('Invalid prefix operator $operator');
- }
- }
-
- visitPropertyAccess(PropertyAccess node) {
- Element element = node.propertyName.staticElement;
- Element auxiliary = node.propertyName.auxiliaryElements?.staticElement;
- var getter = scope.resolveInterfaceGet(element, auxiliary);
- var setter = scope.resolveInterfaceSet(element, auxiliary);
- Expression target = node.target;
- if (node.isCascaded) {
- return PropertyAccessor.make(makeCascadeReceiver(),
- scope.buildName(node.propertyName), getter, setter);
- } else if (node.target is SuperExpression) {
- scope.addTransformerFlag(TransformerFlag.superCalls);
- return new SuperPropertyAccessor(
- scope.buildName(node.propertyName),
- scope.resolveConcreteGet(element, auxiliary),
- scope.resolveConcreteSet(element, auxiliary),
- ast.TreeNode.noOffset);
- } else if (target is Identifier && target.staticElement is ClassElement) {
- // Note that this case also covers null-aware static access on a class,
- // which is equivalent to a regular static access.
- return scope.staticAccess(node.propertyName.name, element, auxiliary);
- } else if (node.operator.value() == '?.') {
- return new NullAwarePropertyAccessor(
- build(target),
- scope.buildName(node.propertyName),
- getter,
- setter,
- scope.buildType(node.staticType),
- ast.TreeNode.noOffset);
- } else {
- return PropertyAccessor.make(
- build(target), scope.buildName(node.propertyName), getter, setter);
- }
- }
-
- ast.Expression visitRethrowExpression(RethrowExpression node) {
- return new ast.Rethrow();
- }
-
- ast.Expression visitSuperExpression(SuperExpression node) {
- return scope
- .emitCompileTimeError(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT);
- }
-
- ast.Expression visitThisExpression(ThisExpression node) {
- return scope.buildThis();
- }
-
- ast.Expression visitThrowExpression(ThrowExpression node) {
- return new ast.Throw(build(node.expression));
- }
-
- ast.Expression visitListLiteral(ListLiteral node) {
- ast.DartType type = node.typeArguments?.arguments?.isNotEmpty ?? false
- ? scope.buildTypeAnnotation(node.typeArguments.arguments[0])
- : scope.getInferredTypeArgument(node, 0);
- return new ast.ListLiteral(node.elements.map(build).toList(),
- typeArgument: type, isConst: node.constKeyword != null);
- }
-
- ast.Expression visitMapLiteral(MapLiteral node) {
- ast.DartType key, value;
- if (node.typeArguments != null && node.typeArguments.arguments.length > 1) {
- key = scope.buildTypeAnnotation(node.typeArguments.arguments[0]);
- value = scope.buildTypeAnnotation(node.typeArguments.arguments[1]);
- } else {
- key = scope.getInferredTypeArgument(node, 0);
- value = scope.getInferredTypeArgument(node, 1);
- }
- return new ast.MapLiteral(node.entries.map(buildMapEntry).toList(),
- keyType: key, valueType: value, isConst: node.constKeyword != null);
- }
-
- ast.MapEntry buildMapEntry(MapLiteralEntry node) {
- return new ast.MapEntry(build(node.key), build(node.value));
- }
-
- ast.Expression visitExpression(Expression node) {
- return scope.internalError('Unhandled expression ${node.runtimeType}');
- }
-}
-
-class StringLiteralPartBuilder extends GeneralizingAstVisitor<Null> {
- final ExpressionScope scope;
- final List<ast.Expression> output;
- StringLiteralPartBuilder(this.scope, this.output);
-
- void build(Expression node) {
- node.accept(this);
- }
-
- void buildInterpolationElement(InterpolationElement node) {
- node.accept(this);
- }
-
- visitSimpleStringLiteral(SimpleStringLiteral node) {
- output.add(new ast.StringLiteral(node.value));
- }
-
- visitAdjacentStrings(AdjacentStrings node) {
- node.strings.forEach(build);
- }
-
- visitStringInterpolation(StringInterpolation node) {
- node.elements.forEach(buildInterpolationElement);
- }
-
- visitInterpolationString(InterpolationString node) {
- output.add(new ast.StringLiteral(node.value));
- }
-
- visitInterpolationExpression(InterpolationExpression node) {
- output.add(scope.buildExpression(node.expression));
- }
-}
-
-class TypeAnnotationBuilder extends GeneralizingAstVisitor<ast.DartType> {
- final TypeScope scope;
-
- TypeAnnotationBuilder(this.scope);
-
- ast.DartType build(AstNode node) {
- return node.accept(this);
- }
-
- List<ast.DartType> buildList(Iterable<AstNode> node) {
- return node.map(build).toList();
- }
-
- /// Replace unbound type variables in [type] with 'dynamic' and convert
- /// to an [ast.DartType].
- ast.DartType buildClosedTypeFromDartType(DartType type) {
- return convertType(type, <TypeParameterElement>[]);
- }
-
- /// Convert to an [ast.DartType] and keep type variables.
- ast.DartType buildFromDartType(DartType type) {
- return convertType(type, null);
- }
-
- /// True if [parameter] should not be reified, because spec mode does not
- /// currently reify generic method type parameters.
- bool isUnreifiedTypeParameter(TypeParameterElement parameter) {
- return !scope.strongMode && parameter.enclosingElement is! ClassElement;
- }
-
- /// Converts [type] to an [ast.DartType], while replacing unbound type
- /// variables with 'dynamic'.
- ///
- /// If [boundVariables] is null, no type variables are replaced, otherwise all
- /// type variables except those in [boundVariables] are replaced. In other
- /// words, it represents the bound variables, or "all variables" if omitted.
- ast.DartType convertType(
- DartType type, List<TypeParameterElement> boundVariables) {
- if (type is TypeParameterType) {
- if (isUnreifiedTypeParameter(type.element)) {
- return const ast.DynamicType();
- }
- if (boundVariables == null || boundVariables.contains(type)) {
- var typeParameter = scope.tryGetTypeParameterReference(type.element);
- if (typeParameter == null) {
- // The analyzer sometimes gives us a type parameter that was not
- // bound anywhere. Make sure we do not emit a dangling reference.
- if (type.element.bound != null) {
- return convertType(type.element.bound, []);
- }
- return const ast.DynamicType();
- }
- if (!scope.allowClassTypeParameters &&
- typeParameter.parent is ast.Class) {
- return const ast.InvalidType();
- }
- return new ast.TypeParameterType(typeParameter);
- } else {
- return const ast.DynamicType();
- }
- } else if (type is InterfaceType) {
- var classNode = scope.getClassReference(type.element);
- if (type.typeArguments.length == 0) {
- return classNode.rawType;
- }
- if (type.typeArguments.length != classNode.typeParameters.length) {
- log.warning('Type parameter arity error in $type');
- return const ast.InvalidType();
- }
- return new ast.InterfaceType(
- classNode, convertTypeList(type.typeArguments, boundVariables));
- } else if (type is FunctionType) {
- // TODO: Avoid infinite recursion in case of illegal circular typedef.
- boundVariables?.addAll(type.typeParameters);
- var positionals =
- concatenate(type.normalParameterTypes, type.optionalParameterTypes);
- var result = new ast.FunctionType(
- convertTypeList(positionals, boundVariables),
- convertType(type.returnType, boundVariables),
- typeParameters:
- convertTypeParameterList(type.typeFormals, boundVariables),
- namedParameters:
- convertTypeMap(type.namedParameterTypes, boundVariables),
- requiredParameterCount: type.normalParameterTypes.length);
- boundVariables?.removeRange(
- boundVariables.length - type.typeParameters.length,
- boundVariables.length);
- return result;
- } else if (type.isUndefined) {
- log.warning('Unresolved type found in ${scope.location}');
- return const ast.InvalidType();
- } else if (type.isVoid) {
- return const ast.VoidType();
- } else if (type.isDynamic) {
- return const ast.DynamicType();
- } else {
- log.severe('Unexpected DartType: $type');
- return const ast.InvalidType();
- }
- }
-
- static Iterable<E> concatenate<E>(Iterable<E> x, Iterable<E> y) =>
- <Iterable<E>>[x, y].expand((z) => z);
-
- ast.TypeParameter convertTypeParameter(TypeParameterElement typeParameter,
- List<TypeParameterElement> boundVariables) {
- return scope.makeTypeParameter(typeParameter,
- bound: typeParameter.bound == null
- ? scope.defaultTypeParameterBound
- : convertType(typeParameter.bound, boundVariables));
- }
-
- List<ast.TypeParameter> convertTypeParameterList(
- Iterable<TypeParameterElement> typeParameters,
- List<TypeParameterElement> boundVariables) {
- if (typeParameters.isEmpty) return const <ast.TypeParameter>[];
- return typeParameters
- .map((tp) => convertTypeParameter(tp, boundVariables))
- .toList();
- }
-
- List<ast.DartType> convertTypeList(
- Iterable<DartType> types, List<TypeParameterElement> boundVariables) {
- if (types.isEmpty) return const <ast.DartType>[];
- return types.map((t) => convertType(t, boundVariables)).toList();
- }
-
- List<ast.NamedType> convertTypeMap(
- Map<String, DartType> types, List<TypeParameterElement> boundVariables) {
- if (types.isEmpty) return const <ast.NamedType>[];
- List<ast.NamedType> result = <ast.NamedType>[];
- types.forEach((name, type) {
- result.add(new ast.NamedType(name, convertType(type, boundVariables)));
- });
- sortAndRemoveDuplicates(result);
- return result;
- }
-
- ast.DartType visitSimpleIdentifier(SimpleIdentifier node) {
- Element element = node.staticElement;
- switch (ElementKind.of(element)) {
- case ElementKind.CLASS:
- return scope.getClassReference(element).rawType;
-
- case ElementKind.DYNAMIC:
- return const ast.DynamicType();
-
- case ElementKind.FUNCTION_TYPE_ALIAS:
- FunctionTypeAliasElement functionType = element;
- return buildClosedTypeFromDartType(functionType.type);
-
- case ElementKind.TYPE_PARAMETER:
- var typeParameter = scope.getTypeParameterReference(element);
- if (!scope.allowClassTypeParameters &&
- typeParameter.parent is ast.Class) {
- return const ast.InvalidType();
- }
- if (isUnreifiedTypeParameter(element)) {
- return const ast.DynamicType();
- }
- return new ast.TypeParameterType(typeParameter);
-
- case ElementKind.COMPILATION_UNIT:
- case ElementKind.CONSTRUCTOR:
- case ElementKind.EXPORT:
- case ElementKind.IMPORT:
- case ElementKind.LABEL:
- case ElementKind.LIBRARY:
- case ElementKind.PREFIX:
- case ElementKind.UNIVERSE:
- case ElementKind.ERROR: // This covers the case where nothing was found.
- case ElementKind.FIELD:
- case ElementKind.TOP_LEVEL_VARIABLE:
- case ElementKind.GETTER:
- case ElementKind.SETTER:
- case ElementKind.METHOD:
- case ElementKind.LOCAL_VARIABLE:
- case ElementKind.PARAMETER:
- case ElementKind.FUNCTION:
- case ElementKind.NAME:
- default:
- log.severe('Invalid type annotation: $element');
- return const ast.InvalidType();
- }
- }
-
- visitPrefixedIdentifier(PrefixedIdentifier node) {
- return build(node.identifier);
- }
-
- visitTypeName(TypeName node) {
- return buildFromDartType(node.type);
- }
-
- visitNode(AstNode node) {
- log.severe('Unexpected type annotation: $node');
- return new ast.InvalidType();
- }
-}
-
-class InitializerBuilder extends GeneralizingAstVisitor<ast.Initializer> {
- final MemberScope scope;
-
- InitializerBuilder(this.scope);
-
- ast.Initializer build(ConstructorInitializer node) {
- return node.accept(this);
- }
-
- visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
- var target = scope.resolveField(node.fieldName.staticElement);
- if (target == null) {
- return new ast.InvalidInitializer();
- }
- return new ast.FieldInitializer(
- target, scope.buildExpression(node.expression));
- }
-
- visitSuperConstructorInvocation(SuperConstructorInvocation node) {
- var target = scope.resolveConstructor(node.staticElement);
- if (target == null) {
- return new ast.InvalidInitializer();
- }
- scope.addTransformerFlag(TransformerFlag.superCalls);
- return new ast.SuperInitializer(
- target, scope._expressionBuilder.buildArguments(node.argumentList));
- }
-
- visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
- var target = scope.resolveConstructor(node.staticElement);
- if (target == null) {
- return new ast.InvalidInitializer();
- }
- return new ast.RedirectingInitializer(
- target, scope._expressionBuilder.buildArguments(node.argumentList));
- }
-
- visitNode(AstNode node) {
- log.severe('Unexpected constructor initializer: ${node.runtimeType}');
- return new ast.InvalidInitializer();
- }
-}
-
-/// A utility to build a function with a static error in its body.
-ast.FunctionNode _brokenFunction() {
- return new ast.FunctionNode(
- new ast.ExpressionStatement(new ast.InvalidExpression(null)));
-}
-
-/// Brings a class from hierarchy level to body level.
-//
-// TODO(asgerf): Error recovery during class construction is currently handled
-// locally, but this can in theory break global invariants in the kernel IR.
-// To safely compile code with compile-time errors, we may need a recovery
-// pass to enforce all kernel invariants before it is given to the backend.
-class ClassBodyBuilder extends GeneralizingAstVisitor<Null> {
- final ClassScope scope;
- final ExpressionScope annotationScope;
- final ast.Class currentClass;
- final ClassElement element;
- ast.Library get currentLibrary => currentClass.enclosingLibrary;
-
- ClassBodyBuilder(
- ReferenceLevelLoader loader, ast.Class currentClass, this.element)
- : this.currentClass = currentClass,
- scope = new ClassScope(loader, currentClass.enclosingLibrary),
- annotationScope =
- new ExpressionScope(loader, currentClass.enclosingLibrary);
-
- void build(CompilationUnitMember node) {
- if (node == null) {
- buildBrokenClass();
- return;
- }
- node.accept(this);
- }
-
- /// Builds an empty class for broken classes that have no AST.
- ///
- /// This should only be used to recover from a compile-time error.
- void buildBrokenClass() {
- currentClass.name = element.name;
- currentClass.supertype = scope.getRootClassReference().asRawSupertype;
- currentClass.constructors.add(new ast.Constructor(_brokenFunction())
- ..fileOffset = element.nameOffset);
- }
-
- void addAnnotations(List<Annotation> annotations) {
- // Class type parameters are not in scope in the annotation list.
- for (var annotation in annotations) {
- currentClass.addAnnotation(annotationScope.buildAnnotation(annotation));
- }
- }
-
- void _buildMemberBody(ast.Member member, Element element, AstNode node) {
- new MemberBodyBuilder(scope.loader, member, element).build(node);
- }
-
- /// True if the given class member should not be emitted, and does not
- /// correspond to any Kernel member.
- ///
- /// This is true for redirecting factories with a resolved target. These are
- /// always bypassed at the call site.
- bool _isIgnoredMember(ClassMember node) {
- if (node is ConstructorDeclaration && node.factoryKeyword != null) {
- var element = resolutionMap.elementDeclaredByConstructorDeclaration(node);
- return element.redirectedConstructor != null &&
- (element.isSynthetic || scope.loader.ignoreRedirectingFactories);
- } else {
- return false;
- }
- }
-
- visitClassDeclaration(ClassDeclaration node) {
- addAnnotations(node.metadata);
- ast.Class classNode = currentClass;
- assert(classNode.members.isEmpty); // All members will be added here.
-
- bool foundConstructor = false;
- for (var member in node.members) {
- if (_isIgnoredMember(member)) continue;
- if (member is FieldDeclaration) {
- for (var variable in member.fields.variables) {
- // Ignore fields inserted through error recovery.
- if (variable.isSynthetic || variable.length == 0) continue;
- var field = scope.getMemberReference(variable.element);
- classNode.addMember(field);
- _buildMemberBody(field, variable.element, variable);
- }
- } else {
- var memberNode = scope.getMemberReference(member.element);
- classNode.addMember(memberNode);
- _buildMemberBody(memberNode, member.element, member);
- if (member is ConstructorDeclaration) {
- foundConstructor = true;
- }
- }
- }
-
- if (!foundConstructor) {
- var defaultConstructor = scope.findDefaultConstructor(node.element);
- if (defaultConstructor != null) {
- assert(defaultConstructor.enclosingElement == node.element);
- if (!defaultConstructor.isSynthetic) {
- throw 'Non-synthetic default constructor not in list of members. '
- '$node $element $defaultConstructor';
- }
- var memberNode = scope.getMemberReference(defaultConstructor);
- classNode.addMember(memberNode);
- buildDefaultConstructor(memberNode, defaultConstructor);
- }
- }
-
- addDefaultInstanceFieldInitializers(classNode);
- }
-
- void buildDefaultConstructor(
- ast.Constructor constructor, ConstructorElement element) {
- var function = constructor.function;
- function.body = new ast.EmptyStatement()..parent = function;
- var class_ = element.enclosingElement;
- if (class_.supertype != null) {
- // DESIGN TODO: If the super class is a mixin application, we will link to
- // a constructor not in the immediate super class. This is a problem due
- // to the fact that mixed-in fields come with initializers which need to
- // be executed by a constructor. The mixin transformer takes care of
- // this by making forwarding constructors and the super initializers will
- // be rewritten to use them (see `transformations/mixin_full_resolution`).
- var superConstructor =
- scope.findDefaultConstructor(class_.supertype.element);
- var target = scope.resolveConstructor(superConstructor);
- if (target == null) {
- constructor.initializers
- .add(new ast.InvalidInitializer()..parent = constructor);
- } else {
- var arguments = new ast.Arguments.empty();
- constructor.initializers.add(
- new ast.SuperInitializer(target, arguments)..parent = constructor);
- }
- }
- }
-
- /// Adds initializers to instance fields that are have no initializer and are
- /// not initialized by all constructors in the class.
- void addDefaultInstanceFieldInitializers(ast.Class node) {
- List<ast.Field> uninitializedFields = new List<ast.Field>();
- for (var field in node.fields) {
- if (field.initializer != null || field.isStatic) continue;
- uninitializedFields.add(field);
- }
- if (uninitializedFields.isEmpty) return;
- constructorLoop:
- for (var constructor in node.constructors) {
- var remainingFields = uninitializedFields.toSet();
- for (var initializer in constructor.initializers) {
- if (initializer is ast.FieldInitializer) {
- remainingFields.remove(initializer.field);
- } else if (initializer is ast.RedirectingInitializer) {
- // The target constructor will be checked in another iteration.
- continue constructorLoop;
- }
- }
- for (var field in remainingFields) {
- if (field.initializer == null) {
- field.initializer = new ast.NullLiteral()..parent = field;
- }
- }
- }
- }
-
- /// True for the `values` field of an `enum` class.
- static bool _isValuesField(FieldElement field) => field.name == 'values';
-
- /// True for the `index` field of an `enum` class.
- static bool _isIndexField(FieldElement field) => field.name == 'index';
-
- visitEnumDeclaration(EnumDeclaration node) {
- addAnnotations(node.metadata);
- ast.Class classNode = currentClass;
-
- var intType = scope.loader.getCoreClassReference('int').rawType;
- var indexFieldElement = element.fields.firstWhere(_isIndexField);
- ast.Field indexField = scope.getMemberReference(indexFieldElement);
- indexField.type = intType;
- classNode.addMember(indexField);
-
- var stringType = scope.loader.getCoreClassReference('String').rawType;
- ast.Field nameField = new ast.Field(
- new ast.Name('_name', scope.currentLibrary),
- type: stringType,
- isFinal: true,
- fileUri: classNode.fileUri);
- classNode.addMember(nameField);
-
- var indexParameter = new ast.VariableDeclaration('index', type: intType);
- var nameParameter = new ast.VariableDeclaration('name', type: stringType);
- var function = new ast.FunctionNode(new ast.EmptyStatement(),
- positionalParameters: [indexParameter, nameParameter]);
- var superConstructor = scope.loader.getRootClassConstructorReference();
- var constructor = new ast.Constructor(function,
- name: new ast.Name(''),
- isConst: true,
- initializers: [
- new ast.FieldInitializer(
- indexField, new ast.VariableGet(indexParameter)),
- new ast.FieldInitializer(
- nameField, new ast.VariableGet(nameParameter)),
- new ast.SuperInitializer(superConstructor, new ast.Arguments.empty())
- ])
- ..fileOffset = element.nameOffset;
- classNode.addMember(constructor);
-
- int index = 0;
- var enumConstantFields = <ast.Field>[];
- for (var constant in node.constants) {
- ast.Field field = scope.getMemberReference(constant.element);
- field.initializer = new ast.ConstructorInvocation(
- constructor,
- new ast.Arguments([
- new ast.IntLiteral(index),
- new ast.StringLiteral('${classNode.name}.${field.name.name}')
- ]),
- isConst: true)
- ..parent = field;
- field.type = classNode.rawType;
- classNode.addMember(field);
- ++index;
- enumConstantFields.add(field);
- }
-
- // Add the 'values' field.
- var valuesFieldElement = element.fields.firstWhere(_isValuesField);
- ast.Field valuesField = scope.getMemberReference(valuesFieldElement);
- var enumType = classNode.rawType;
- valuesField.type = new ast.InterfaceType(
- scope.loader.getCoreClassReference('List'), <ast.DartType>[enumType]);
- valuesField.initializer = new ast.ListLiteral(
- enumConstantFields.map(_makeStaticGet).toList(),
- isConst: true,
- typeArgument: enumType)
- ..parent = valuesField;
- classNode.addMember(valuesField);
-
- // Add the 'toString()' method.
- var body = new ast.ReturnStatement(
- new ast.DirectPropertyGet(new ast.ThisExpression(), nameField));
- var toStringFunction = new ast.FunctionNode(body, returnType: stringType);
- var toStringMethod = new ast.Procedure(
- new ast.Name('toString'), ast.ProcedureKind.Method, toStringFunction,
- fileUri: classNode.fileUri);
- classNode.addMember(toStringMethod);
- }
-
- visitClassTypeAlias(ClassTypeAlias node) {
- addAnnotations(node.metadata);
- assert(node.withClause != null && node.withClause.mixinTypes.isNotEmpty);
- ast.Class classNode = currentClass;
- for (var constructor in element.constructors) {
- var constructorNode = scope.getMemberReference(constructor);
- classNode.addMember(constructorNode);
- buildMixinConstructor(constructorNode, constructor);
- }
- }
-
- void buildMixinConstructor(
- ast.Constructor constructor, ConstructorElement element) {
- var function = constructor.function;
- function.body = new ast.EmptyStatement()..parent = function;
- // Call the corresponding constructor in super class.
- ClassElement classElement = element.enclosingElement;
- var targetConstructor = classElement.supertype.element.constructors
- .firstWhere((c) => c.name == element.name);
- var positionalArguments = constructor.function.positionalParameters
- .map(_makeVariableGet)
- .toList();
- var namedArguments = constructor.function.namedParameters
- .map(_makeNamedExpressionFrom)
- .toList();
- constructor.initializers.add(new ast.SuperInitializer(
- scope.getMemberReference(targetConstructor),
- new ast.Arguments(positionalArguments, named: namedArguments))
- ..parent = constructor);
- }
-
- visitNode(AstNode node) {
- throw 'Unsupported class declaration: ${node.runtimeType}';
- }
-}
-
-/// Brings a member from reference level to body level.
-class MemberBodyBuilder extends GeneralizingAstVisitor<Null> {
- final MemberScope scope;
- final Element element;
- ast.Member get currentMember => scope.currentMember;
-
- MemberBodyBuilder(
- ReferenceLevelLoader loader, ast.Member member, this.element)
- : scope = new MemberScope(loader, member);
-
- void build(AstNode node) {
- if (node != null) {
- currentMember.fileEndOffset = node.endToken.offset;
- node.accept(this);
- } else {
- buildBrokenMember();
- }
- }
-
- /// Builds an empty member.
- ///
- /// This should only be used to recover from a compile-time error.
- void buildBrokenMember() {
- var member = currentMember;
- member.name = new ast.Name(element.name, scope.currentLibrary);
- if (member is ast.Procedure) {
- member.function = _brokenFunction()..parent = member;
- } else if (member is ast.Constructor) {
- member.function = _brokenFunction()..parent = member;
- }
- }
-
- void addAnnotations(List<Annotation> annotations) {
- for (var annotation in annotations) {
- currentMember.addAnnotation(scope.buildAnnotation(annotation));
- }
- }
-
- void handleNativeBody(FunctionBody body) {
- if (body is NativeFunctionBody) {
- currentMember.isExternal = true;
- currentMember.addAnnotation(new ast.ConstructorInvocation(
- scope.loader.getCoreClassConstructorReference('ExternalName',
- library: 'dart:_internal'),
- new ast.Arguments(<ast.Expression>[
- new ast.StringLiteral(body.stringLiteral.stringValue)
- ]),
- isConst: true));
- }
- }
-
- visitConstructorDeclaration(ConstructorDeclaration node) {
- if (node.factoryKeyword != null) {
- buildFactoryConstructor(node);
- } else {
- buildGenerativeConstructor(node);
- }
- }
-
- void buildGenerativeConstructor(ConstructorDeclaration node) {
- if (currentMember is! ast.Constructor) {
- buildBrokenMember();
- return;
- }
- addAnnotations(node.metadata);
- ast.Constructor constructor = currentMember;
- constructor.function = scope.buildFunctionNode(node.parameters, node.body,
- inferredReturnType: const ast.VoidType())
- ..parent = constructor;
- handleNativeBody(node.body);
- if (node.body is EmptyFunctionBody && !constructor.isExternal) {
- var function = constructor.function;
- function.body = new ast.EmptyStatement()..parent = function;
- }
- for (var parameter in node.parameters.parameterElements) {
- if (parameter is FieldFormalParameterElement) {
- ast.Initializer initializer;
- if (parameter.field == null) {
- initializer = new ast.LocalInitializer(
- new ast.VariableDeclaration.forValue(scope
- .buildThrowCompileTimeErrorFromCode(
- CompileTimeErrorCode.INITIALIZER_FOR_NON_EXISTENT_FIELD,
- [parameter.name])));
- } else {
- initializer = new ast.FieldInitializer(
- scope.getMemberReference(parameter.field),
- new ast.VariableGet(scope.getVariableReference(parameter)));
- }
- constructor.initializers.add(initializer..parent = constructor);
- }
- }
- bool hasExplicitConstructorCall = false;
- for (var initializer in node.initializers) {
- var node = scope.buildInitializer(initializer);
- constructor.initializers.add(node..parent = constructor);
- if (node is ast.SuperInitializer || node is ast.RedirectingInitializer) {
- hasExplicitConstructorCall = true;
- }
- }
- ClassElement classElement = resolutionMap
- .elementDeclaredByConstructorDeclaration(node)
- .enclosingElement;
- if (classElement.supertype != null && !hasExplicitConstructorCall) {
- ConstructorElement targetElement =
- scope.findDefaultConstructor(classElement.supertype.element);
- ast.Constructor target = scope.resolveConstructor(targetElement);
- ast.Initializer initializer = target == null
- ? new ast.InvalidInitializer()
- : new ast.SuperInitializer(
- target, new ast.Arguments(<ast.Expression>[]));
- constructor.initializers.add(initializer..parent = constructor);
- } else {
- moveSuperInitializerLast(constructor);
- }
- }
-
- void buildFactoryConstructor(ConstructorDeclaration node) {
- if (currentMember is! ast.Procedure) {
- buildBrokenMember();
- return;
- }
- addAnnotations(node.metadata);
- ast.Procedure procedure = currentMember;
- ClassElement classElement = resolutionMap
- .elementDeclaredByConstructorDeclaration(node)
- .enclosingElement;
- ast.Class classNode = procedure.enclosingClass;
- var types = getFreshTypeParameters(classNode.typeParameters);
- for (int i = 0; i < classElement.typeParameters.length; ++i) {
- scope.localTypeParameters[classElement.typeParameters[i]] =
- types.freshTypeParameters[i];
- }
- var inferredReturnType = types.freshTypeParameters.isEmpty
- ? classNode.rawType
- : new ast.InterfaceType(
- classNode,
- types.freshTypeParameters
- .map(makeTypeParameterType)
- .toList(growable: false));
- var function = scope.buildFunctionNode(node.parameters, node.body,
- typeParameters: types.freshTypeParameters,
- inferredReturnType: inferredReturnType);
- procedure.function = function..parent = procedure;
- handleNativeBody(node.body);
- if (node.redirectedConstructor != null) {
- // Add a new synthetic field to [classNode] for representing factory
- // constructors. This is used by the new frontend engine to support
- // resolving source code.
- //
- // The synthetic field looks like this:
- //
- // final _redirecting# = [c1, ..., cn];
- //
- // Where each c1 ... cn are an instance of [StaticGet] whose target is
- // the redirecting factory created above. The new frontend engine reads
- // this field and rewrites them.
- //
- // TODO(ahe): Generate the correct factory body instead. This requires
- // access to default values from other files, we'll probably never do
- // that in this file, and instead rely on the new compiler for this.
- var element = resolutionMap.elementDeclaredByConstructorDeclaration(node);
- assert(!element.isSynthetic);
- var expression;
- if (node.element.redirectedConstructor != null) {
- assert(!scope.loader.ignoreRedirectingFactories);
- ConstructorElement element = node.element.redirectedConstructor;
- while (element.isFactory && element.redirectedConstructor != null) {
- element = element.redirectedConstructor;
- }
- ast.Member target = scope.getMemberReference(element);
- assert(target != null);
- expression = new ast.Let(
- new ast.VariableDeclaration.forValue(new ast.StaticGet(target)),
- new ast.InvalidExpression(null));
- ast.Name constructors =
- new ast.Name("_redirecting#", scope.currentLibrary);
- ast.Field constructorsField;
- for (ast.Field field in classNode.fields) {
- if (field.name == constructors) {
- constructorsField = field;
- break;
- }
- }
- if (constructorsField == null) {
- ast.ListLiteral literal = new ast.ListLiteral(<ast.Expression>[]);
- constructorsField = new ast.Field(constructors,
- isStatic: true, initializer: literal, fileUri: classNode.fileUri)
- ..fileOffset = classNode.fileOffset;
- classNode.addMember(constructorsField);
- }
- ast.ListLiteral literal = constructorsField.initializer;
- literal.expressions.add(new ast.StaticGet(procedure)..parent = literal);
- } else {
- var name = node.redirectedConstructor.type.name.name;
- if (node.redirectedConstructor.name != null) {
- name += '.' + node.redirectedConstructor.name.name;
- }
- // TODO(asgerf): Sometimes a TypeError should be thrown.
- expression = scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), name, new ast.Arguments.empty());
- }
- var function = procedure.function;
- function.body = new ast.ExpressionStatement(expression)
- ..parent = function;
- }
- }
-
- visitMethodDeclaration(MethodDeclaration node) {
- addAnnotations(node.metadata);
- ast.Procedure procedure = currentMember;
- procedure.function = scope.buildFunctionNode(node.parameters, node.body,
- returnType: node.returnType,
- inferredReturnType: scope.buildType(
- resolutionMap.elementDeclaredByMethodDeclaration(node).returnType),
- typeParameters: scope.buildOptionalTypeParameterList(
- node.typeParameters,
- strongModeOnly: true))
- ..parent = procedure;
- handleNativeBody(node.body);
- }
-
- visitVariableDeclaration(VariableDeclaration node) {
- addAnnotations(node.metadata);
- ast.Field field = currentMember;
- field.type = scope.buildType(
- resolutionMap.elementDeclaredByVariableDeclaration(node).type);
- if (node.initializer != null) {
- field.initializer = scope.buildTopLevelExpression(node.initializer)
- ..parent = field;
- } else if (field.isStatic) {
- // Add null initializer to static fields without an initializer.
- // For instance fields, this is handled when building the class.
- field.initializer = new ast.NullLiteral()..parent = field;
- }
- }
-
- visitFunctionDeclaration(FunctionDeclaration node) {
- addAnnotations(node.metadata);
- var function = node.functionExpression;
- ast.Procedure procedure = currentMember;
- procedure.function = scope.buildFunctionNode(
- function.parameters, function.body,
- returnType: node.returnType,
- typeParameters: scope.buildOptionalTypeParameterList(
- function.typeParameters,
- strongModeOnly: true))
- ..parent = procedure;
- handleNativeBody(function.body);
- }
-
- visitNode(AstNode node) {
- log.severe('Unexpected class or library member: $node');
- }
-}
-
-/// Internal exception thrown from the expression or statement builder when a
-/// compilation error is found.
-///
-/// This is then caught at the function level to replace the entire function
-/// body (or field initializer) with a throw.
-class _CompilationError {
- String message;
-
- _CompilationError(this.message);
-}
-
-/// Constructor alias for [ast.TypeParameterType], use instead of a closure.
-ast.DartType makeTypeParameterType(ast.TypeParameter parameter) {
- return new ast.TypeParameterType(parameter);
-}
-
-/// Constructor alias for [ast.VariableGet], use instead of a closure.
-ast.VariableGet _makeVariableGet(ast.VariableDeclaration variable) {
- return new ast.VariableGet(variable);
-}
-
-/// Constructor alias for [ast.StaticGet], use instead of a closure.
-ast.StaticGet _makeStaticGet(ast.Field field) {
- return new ast.StaticGet(field);
-}
-
-/// Create a named expression with the name and value of the given variable.
-ast.NamedExpression _makeNamedExpressionFrom(ast.VariableDeclaration variable) {
- return new ast.NamedExpression(variable.name, new ast.VariableGet(variable));
-}
-
-/// A [StaticAccessor] that throws a NoSuchMethodError when a suitable target
-/// could not be resolved.
-class _StaticAccessor extends StaticAccessor {
- final ExpressionScope scope;
- final String name;
-
- _StaticAccessor(
- this.scope, this.name, ast.Member readTarget, ast.Member writeTarget)
- : super(readTarget, writeTarget, ast.TreeNode.noOffset);
-
- @override
- makeInvalidRead() {
- return scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), name, new ast.Arguments([]));
- }
-
- @override
- makeInvalidWrite(ast.Expression value) {
- return scope.buildThrowNoSuchMethodError(
- new ast.NullLiteral(), name, new ast.Arguments([value]));
- }
-}
-
-bool isTopLevelFunction(Element element) {
- return element is FunctionElement &&
- element.enclosingElement is CompilationUnitElement;
-}
-
-bool isLocalFunction(Element element) {
- return element is FunctionElement &&
- element.enclosingElement is! CompilationUnitElement &&
- element.enclosingElement is! LibraryElement;
-}
-
-bool isLocal(Element element) {
- return isLocalFunction(element) ||
- element is LocalVariableElement ||
- element is ParameterElement;
-}
-
-bool isInstanceMethod(Element element) {
- return element is MethodElement && !element.isStatic;
-}
-
-bool isStaticMethod(Element element) {
- return element is MethodElement && element.isStatic ||
- isTopLevelFunction(element);
-}
-
-bool isStaticVariableOrGetter(Element element) {
- element = desynthesizeGetter(element);
- return element is FieldElement && element.isStatic ||
- element is TopLevelVariableElement;
-}
-
-Element desynthesizeGetter(Element element) {
- if (element == null || !element.isSynthetic) return element;
- if (element is PropertyAccessorElement) return element.variable;
- if (element is FieldElement) return element.getter;
- return element;
-}
-
-Element desynthesizeSetter(Element element) {
- if (element == null || !element.isSynthetic) return element;
- if (element is PropertyAccessorElement) return element.variable;
- if (element is FieldElement) return element.setter;
- return element;
-}
-
-void sortAndRemoveDuplicates<T extends Comparable<T>>(List<T> list) {
- list.sort();
- int deleted = 0;
- for (int i = 1; i < list.length; ++i) {
- var item = list[i];
- if (list[i - 1].compareTo(item) == 0) {
- ++deleted;
- } else if (deleted > 0) {
- list[i - deleted] = item;
- }
- }
- if (deleted > 0) {
- list.length -= deleted;
- }
-}
diff --git a/pkg/analyzer/lib/src/kernel/loader.dart b/pkg/analyzer/lib/src/kernel/loader.dart
deleted file mode 100644
index 73dd076..0000000
--- a/pkg/analyzer/lib/src/kernel/loader.dart
+++ /dev/null
@@ -1,1026 +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.
-library kernel.analyzer.loader;
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' as io;
-
-import 'package:analyzer/analyzer.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/source/package_map_resolver.dart';
-import 'package:analyzer/src/dart/element/member.dart';
-import 'package:analyzer/src/dart/scanner/scanner.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/parser.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/summary/summary_sdk.dart';
-import 'package:kernel/application_root.dart';
-import 'package:package_config/discovery.dart';
-import 'package:package_config/packages.dart';
-
-import 'package:kernel/ast.dart' as ast;
-import 'package:kernel/target/targets.dart' show Target;
-import 'package:kernel/type_algebra.dart';
-import 'package:analyzer/src/kernel/ast_from_analyzer.dart';
-
-/// Options passed to the Dart frontend.
-class DartOptions {
- /// True if user code should be loaded in strong mode.
- bool strongMode;
-
- /// True if the Dart SDK should be loaded in strong mode.
- bool strongModeSdk;
-
- /// Path to the sdk sources, ignored if sdkSummary is provided.
- String sdk;
-
- /// Path to a summary of the sdk sources.
- String sdkSummary;
-
- /// Path to the `.packages` file.
- String packagePath;
-
- /// Root used to relativize app file-urls, making them machine agnostic.
- ApplicationRoot applicationRoot;
-
- Map<Uri, Uri> customUriMappings;
-
- /// Environment definitions provided via `-Dkey=value`.
- Map<String, String> declaredVariables;
-
- DartOptions(
- {bool strongMode: false,
- bool strongModeSdk,
- this.sdk,
- this.sdkSummary,
- this.packagePath,
- ApplicationRoot applicationRoot,
- Map<Uri, Uri> customUriMappings,
- Map<String, String> declaredVariables})
- : this.customUriMappings = customUriMappings ?? <Uri, Uri>{},
- this.declaredVariables = declaredVariables ?? <String, String>{},
- this.strongMode = strongMode,
- this.strongModeSdk = strongModeSdk ?? strongMode,
- this.applicationRoot = applicationRoot ?? new ApplicationRoot.none();
-}
-
-abstract class ReferenceLevelLoader {
- ast.Library getLibraryReference(LibraryElement element);
- ast.Class getClassReference(ClassElement element);
- ast.Member getMemberReference(Element element);
- ast.Class getRootClassReference();
- ast.Constructor getRootClassConstructorReference();
- ast.Class getCoreClassReference(String className);
- ast.Constructor getCoreClassConstructorReference(String className,
- {String constructorName, String library});
- ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element);
- ast.Class getSharedMixinApplicationClass(
- ast.Library library, ast.Class supertype, ast.Class mixin);
- bool get strongMode;
-
- /// Whether or not to include redirecting factories in the output.
- bool get ignoreRedirectingFactories;
-}
-
-class DartLoader implements ReferenceLevelLoader {
- final ast.Component component;
- final ApplicationRoot applicationRoot;
- final Bimap<ClassElement, ast.Class> _classes =
- new Bimap<ClassElement, ast.Class>();
- final Bimap<Element, ast.Member> _members = new Bimap<Element, ast.Member>();
- final Map<TypeParameterElement, ast.TypeParameter> _classTypeParameters =
- <TypeParameterElement, ast.TypeParameter>{};
- final Map<ast.Library, Map<String, ast.Class>> _mixinApplications =
- <ast.Library, Map<String, ast.Class>>{};
- final Map<LibraryElement, ast.Library> _libraries =
- <LibraryElement, ast.Library>{};
- final AnalysisContext context;
- LibraryElement _dartCoreLibrary;
- final List errors = [];
- final List libraryElements = [];
-
- /// Classes that have been referenced, and must be promoted to type level
- /// so as not to expose partially initialized classes.
- final List<ast.Class> temporaryClassWorklist = [];
-
- final Map<LibraryElement, List<ClassElement>> mixinLibraryWorklist = {};
-
- final bool ignoreRedirectingFactories;
-
- LibraryElement _libraryBeingLoaded = null;
- ClassElement _classBeingPromotedToMixin = null;
-
- bool get strongMode => context.analysisOptions.strongMode;
-
- DartLoader(this.component, DartOptions options, Packages packages,
- {DartSdk dartSdk,
- AnalysisContext context,
- this.ignoreRedirectingFactories: true})
- : this.context =
- context ?? createContext(options, packages, dartSdk: dartSdk),
- this.applicationRoot = options.applicationRoot;
-
- String getLibraryName(LibraryElement element) {
- return element.name.isEmpty ? null : element.name;
- }
-
- LibraryElement getLibraryElementFromUri(Uri uri) {
- var source = context.sourceFactory.forUri2(uri);
- if (source == null) return null;
- return context.computeLibraryElement(source);
- }
-
- ast.Library getLibraryReference(LibraryElement element) {
- var uri = applicationRoot.relativeUri(element.source.uri);
- var library = _libraries[element];
- if (library == null) {
- library = new ast.Library(uri)
- ..isExternal = true
- ..name = getLibraryName(element)
- ..fileUri = element.source.uri;
- component.libraries.add(library..parent = component);
- _libraries[element] = library;
- }
- return library;
- }
-
- ast.Library getLibraryReferenceFromUri(Uri uri) {
- return getLibraryReference(getLibraryElementFromUri(uri));
- }
-
- void _buildTopLevelMember(
- ast.Member member, Element element, Declaration astNode) {
- assert(member.parent != null);
- new MemberBodyBuilder(this, member, element).build(astNode);
- }
-
- /// True if [element] is in the process of being loaded by
- /// [_buildLibraryBody].
- ///
- /// If this is the case, we should avoid adding new members to the classes
- /// in the library, since the AST builder will rebuild the member lists.
- bool isLibraryBeingLoaded(LibraryElement element) {
- return _libraryBeingLoaded == element;
- }
-
- bool isClassBeingPromotedToMixin(ClassElement element) {
- return _classBeingPromotedToMixin == element;
- }
-
- void _buildLibraryBody(LibraryElement element, ast.Library library,
- List<CompilationUnit> units) {
- assert(_libraryBeingLoaded == null);
- _libraryBeingLoaded = element;
- var classes = <ast.Class>[];
- var procedures = <ast.Procedure>[];
- var fields = <ast.Field>[];
-
- void loadClass(NamedCompilationUnitMember declaration) {
- // [declaration] can be a ClassDeclaration, EnumDeclaration, or a
- // ClassTypeAlias.
- ClassElement element = declaration.element;
- var node = getClassReference(element);
- promoteToBodyLevel(node, element, declaration);
- classes.add(node);
- }
-
- void loadProcedure(FunctionDeclaration declaration) {
- var element = declaration.element;
- var node = getMemberReference(element);
- _buildTopLevelMember(node, element, declaration);
- procedures.add(node);
- }
-
- void loadField(TopLevelVariableDeclaration declaration) {
- for (var field in declaration.variables.variables) {
- var element = field.element;
- // Ignore fields inserted through error recovery.
- if (element.name == '') continue;
- var node = getMemberReference(element);
- _buildTopLevelMember(node, element, field);
- fields.add(node);
- }
- }
-
- for (var unit in units) {
- for (CompilationUnitMember declaration in unit.declarations) {
- if (declaration is ClassDeclaration ||
- declaration is EnumDeclaration ||
- declaration is ClassTypeAlias) {
- loadClass(declaration);
- } else if (declaration is FunctionDeclaration) {
- loadProcedure(declaration);
- } else if (declaration is TopLevelVariableDeclaration) {
- loadField(declaration);
- } else if (declaration is FunctionTypeAlias) {
- // Nothing to do. Typedefs are handled lazily while constructing type
- // references.
- } else {
- throw "unexpected node: ${declaration.runtimeType} $declaration";
- }
- }
- }
- libraryElements.add(element);
- _iterateTemporaryClassWorklist();
- // Ensure everything is stored in the original declaration order.
- library.classes
- ..clear()
- ..addAll(classes)
- ..addAll(_mixinApplications[library]?.values ?? const []);
- library.fields
- ..clear()
- ..addAll(fields);
- library.procedures
- ..clear()
- ..addAll(procedures);
- _libraryBeingLoaded = null;
- }
-
- LibraryElement getDartCoreLibrary() {
- return _dartCoreLibrary ??= _findLibraryElement('dart:core');
- }
-
- LibraryElement _findLibraryElement(String uri) {
- var source = context.sourceFactory.forUri(uri);
- if (source == null) return null;
- return context.computeLibraryElement(source);
- }
-
- ast.Class getRootClassReference() {
- return getCoreClassReference('Object');
- }
-
- ast.Constructor getRootClassConstructorReference() {
- var element = getDartCoreLibrary().getType('Object').constructors[0];
- return getMemberReference(element);
- }
-
- ast.Class getCoreClassReference(String className) {
- return getClassReference(getDartCoreLibrary().getType(className));
- }
-
- ast.Constructor getCoreClassConstructorReference(String className,
- {String constructorName, String library}) {
- LibraryElement libraryElement =
- library != null ? _findLibraryElement(library) : getDartCoreLibrary();
- ClassElement element = libraryElement.getType(className);
- if (element == null) {
- throw 'Missing core class $className from ${libraryElement.name}';
- }
- var constructor = element.constructors.firstWhere((constructor) {
- return (constructorName == null)
- ? (constructor.nameLength == 0)
- : (constructor.name == constructorName);
- });
- return getMemberReference(constructor);
- }
-
- ClassElement getClassElement(ast.Class node) {
- return _classes.inverse[node];
- }
-
- void addMixinClassToLibrary(ast.Class class_, ast.Library library) {
- assert(class_.parent == null);
- library.addClass(class_);
- var map =
- _mixinApplications.putIfAbsent(library, () => <String, ast.Class>{});
- map[class_.name] = class_;
- }
-
- /// Returns the IR for a class, at a temporary loading level.
- ///
- /// The returned class has the correct name, flags, type parameter arity,
- /// and enclosing library.
- ast.Class getClassReference(ClassElement element) {
- var classNode = _classes[element];
- if (classNode != null) return classNode;
- _classes[element] = classNode = new ast.Class(
- name: element.name,
- isAbstract: element.isAbstract,
- fileUri: element.source.uri)
- ..fileOffset = element.nameOffset;
- classNode.level = ast.ClassLevel.Temporary;
- var library = getLibraryReference(element.library);
- library.addClass(classNode);
- // Initialize type parameter list without bounds.
- for (var parameter in element.typeParameters) {
- var parameterNode = new ast.TypeParameter(parameter.name);
- _classTypeParameters[parameter] = parameterNode;
- classNode.typeParameters.add(parameterNode);
- parameterNode.parent = classNode;
- }
- // Ensure the class is at least promoted to type level before exposing it
- // to kernel consumers.
- temporaryClassWorklist.add(classNode);
- return classNode;
- }
-
- /// Ensures the supertypes and type parameter bounds have been generated for
- /// the given class.
- void promoteToTypeLevel(ast.Class classNode) {
- if (classNode.level.index >= ast.ClassLevel.Type.index) return;
- classNode.level = ast.ClassLevel.Type;
- var element = getClassElement(classNode);
- assert(element != null);
- var library = getLibraryReference(element.library);
- var scope = new ClassScope(this, library);
- // Initialize bounds on type parameters.
- for (int i = 0; i < classNode.typeParameters.length; ++i) {
- var parameter = element.typeParameters[i];
- var parameterNode = classNode.typeParameters[i];
- parameterNode.bound = parameter.bound == null
- ? scope.defaultTypeParameterBound
- : scope.buildType(parameter.bound);
- }
- // Initialize supertypes.
- Iterable<InterfaceType> mixins = element.mixins;
- if (element.isMixinApplication && mixins.isNotEmpty) {
- classNode.mixedInType = scope.buildSupertype(mixins.last);
- mixins = mixins.take(mixins.length - 1);
- }
- if (element.supertype != null) {
- ast.Supertype supertype = scope.buildSupertype(element.supertype);
- bool useSharedMixin = true;
- for (var mixin in mixins) {
- var mixinType = scope.buildSupertype(mixin);
- if (useSharedMixin &&
- areDistinctUnboundTypeVariables(supertype, mixinType)) {
- // Use a shared mixin application class for this library.
- var mixinClass = getSharedMixinApplicationClass(
- scope.currentLibrary, supertype.classNode, mixinType.classNode);
- if (mixinClass.fileOffset < 0) {
- mixinClass.fileOffset = element.nameOffset;
- }
- supertype = new ast.Supertype(
- mixinClass,
- supertype.typeArguments.length > mixinType.typeArguments.length
- ? supertype.typeArguments
- : mixinType.typeArguments);
- } else {
- // Generate a new class specific for this mixin application.
- var freshParameters =
- getFreshTypeParameters(classNode.typeParameters);
- var mixinClass = new ast.Class(
- name: '${classNode.name}^${mixinType.classNode.name}',
- isAbstract: true,
- typeParameters: freshParameters.freshTypeParameters,
- supertype: freshParameters.substituteSuper(supertype),
- mixedInType: freshParameters.substituteSuper(mixinType),
- fileUri: classNode.fileUri)
- ..fileOffset = element.nameOffset;
- mixinClass.level = ast.ClassLevel.Type;
- addMixinClassToLibrary(mixinClass, classNode.enclosingLibrary);
- supertype = new ast.Supertype(mixinClass,
- classNode.typeParameters.map(makeTypeParameterType).toList());
- // This class cannot be used from anywhere else, so don't try to
- // generate shared mixin applications using it.
- useSharedMixin = false;
- }
- }
- classNode.supertype = supertype;
- for (var implementedType in element.interfaces) {
- classNode.implementedTypes.add(scope.buildSupertype(implementedType));
- }
- }
- }
-
- void promoteToHierarchyLevel(ast.Class classNode) {
- if (classNode.level.index >= ast.ClassLevel.Hierarchy.index) return;
- promoteToTypeLevel(classNode);
- classNode.level = ast.ClassLevel.Hierarchy;
- var element = getClassElement(classNode);
- if (element != null) {
- // Ensure all instance members are at present.
- for (var field in element.fields) {
- if (!field.isStatic && !field.isSynthetic) {
- getMemberReference(field);
- }
- }
- for (var accessor in element.accessors) {
- if (!accessor.isStatic && !accessor.isSynthetic) {
- getMemberReference(accessor);
- }
- }
- for (var method in element.methods) {
- if (!method.isStatic && !method.isSynthetic) {
- getMemberReference(method);
- }
- }
- }
- for (var supertype in classNode.supers) {
- promoteToHierarchyLevel(supertype.classNode);
- }
- }
-
- void promoteToMixinLevel(ast.Class classNode, ClassElement element,
- NamedCompilationUnitMember astNode) {
- if (classNode.level.index >= ast.ClassLevel.Mixin.index) return;
- _classBeingPromotedToMixin = element;
- promoteToHierarchyLevel(classNode);
- classNode.level = ast.ClassLevel.Mixin;
- // Clear out the member references that were put in the class.
- // The AST builder will load them all put back in the right order.
- classNode..fields.clear()..procedures.clear()..constructors.clear();
- new ClassBodyBuilder(this, classNode, element).build(astNode);
- _classBeingPromotedToMixin = null;
-
- // Ensure mixed-in classes are available.
- for (var mixin in element.mixins) {
- _ensureMixinBecomesLoaded(mixin.element);
- }
- }
-
- /// Ensures that [element] eventually becomes loaded at least at mixin level.
- void _ensureMixinBecomesLoaded(ClassElement element) {
- if (isClassBeingPromotedToMixin(element)) {
- return;
- }
- var class_ = getClassReference(element);
- if (class_.level.index >= ast.ClassLevel.Mixin.index) {
- return;
- }
- var list = mixinLibraryWorklist[element.library] ??= <ClassElement>[];
- list.add(element);
- }
-
- void promoteToBodyLevel(ast.Class classNode, ClassElement element,
- NamedCompilationUnitMember astNode) {
- if (classNode.level == ast.ClassLevel.Body) return;
- promoteToMixinLevel(classNode, element, astNode);
- classNode.level = ast.ClassLevel.Body;
- // This frontend delivers the same contents for classes at body and mixin
- // levels, even though as specified, the mixin level does not require all
- // the static members to be present. So no additional work is needed.
- }
-
- ast.TypeParameter tryGetClassTypeParameter(TypeParameterElement element) {
- return _classTypeParameters[element];
- }
-
- Element getMemberElement(ast.Member node) {
- return _members.inverse[node];
- }
-
- ast.Member getMemberReference(Element element) {
- assert(element != null);
- assert(element is! Member); // Use the "base element".
- return _members[element] ??= _buildMemberReference(element);
- }
-
- ast.Member _buildMemberReference(Element element) {
- assert(element != null);
- var member = _buildOrphanedMemberReference(element);
- // Set the parent pointer and store it in the enclosing class or library.
- // If the enclosing library is being built from the AST, do not add the
- // member, since the AST builder will put it in there.
- var parent = element.enclosingElement;
- if (parent is ClassElement) {
- var class_ = getClassReference(parent);
- member.parent = class_;
- if (!isLibraryBeingLoaded(element.library)) {
- class_.addMember(member);
- }
- } else {
- var library = getLibraryReference(element.library);
- member.parent = library;
- if (!isLibraryBeingLoaded(element.library)) {
- library.addMember(member);
- }
- }
- return member;
- }
-
- ast.Member _buildOrphanedMemberReference(Element element) {
- assert(element != null);
- ClassElement classElement = element.enclosingElement is ClassElement
- ? element.enclosingElement
- : null;
- TypeScope scope = classElement != null
- ? new ClassScope(this, getLibraryReference(element.library))
- : new TypeScope(this);
- if (classElement != null) {
- getClassReference(classElement);
- }
- switch (element.kind) {
- case ElementKind.CONSTRUCTOR:
- ConstructorElement constructor = element;
- if (constructor.isFactory) {
- return new ast.Procedure(
- _nameOfMember(constructor),
- ast.ProcedureKind.Factory,
- scope.buildFunctionInterface(constructor),
- isAbstract: false,
- isStatic: true,
- isExternal: constructor.isExternal,
- isConst: constructor.isConst,
- fileUri: element.source.uri)
- ..fileOffset = element.nameOffset;
- }
- return new ast.Constructor(scope.buildFunctionInterface(constructor),
- name: _nameOfMember(element),
- isConst: constructor.isConst,
- isExternal: constructor.isExternal,
- isSynthetic: constructor.isSynthetic)
- ..fileOffset = element.nameOffset;
-
- case ElementKind.FIELD:
- case ElementKind.TOP_LEVEL_VARIABLE:
- VariableElement variable = element;
- return new ast.Field(_nameOfMember(variable),
- isStatic: variable.isStatic,
- isFinal: variable.isFinal,
- isConst: variable.isConst,
- type: scope.buildType(variable.type),
- fileUri: element.source.uri)
- ..fileOffset = element.nameOffset;
-
- case ElementKind.METHOD:
- case ElementKind.GETTER:
- case ElementKind.SETTER:
- case ElementKind.FUNCTION:
- if (element is FunctionElement &&
- element.enclosingElement is! CompilationUnitElement) {
- throw 'Function $element is nested in ${element.enclosingElement} '
- 'and hence is not a member';
- }
- ExecutableElement executable = element;
- return new ast.Procedure(
- _nameOfMember(element),
- _procedureKindOf(executable),
- scope.buildFunctionInterface(executable),
- isAbstract: executable.isAbstract,
- isStatic: executable.isStatic,
- isExternal: executable.isExternal,
- fileUri: element.source.uri)
- ..fileOffset = element.nameOffset;
-
- default:
- throw 'Unexpected member kind: $element';
- }
- }
-
- ast.ProcedureKind _procedureKindOf(ExecutableElement element) {
- if (element is PropertyAccessorElement) {
- return element.isGetter
- ? ast.ProcedureKind.Getter
- : ast.ProcedureKind.Setter;
- }
- if (element is MethodElement) {
- if (element.isOperator) return ast.ProcedureKind.Operator;
- return ast.ProcedureKind.Method;
- }
- if (element is FunctionElement) {
- return ast.ProcedureKind.Method;
- }
- if (element is ConstructorElement) {
- assert(element.isFactory);
- return ast.ProcedureKind.Factory;
- }
- throw 'Unexpected procedure: $element';
- }
-
- ast.Name _nameOfMember(Element element) {
- // Use 'displayName' to avoid a trailing '=' for setters and 'name' to
- // ensure unary minus is called 'unary-'.
- String name =
- element is PropertyAccessorElement ? element.displayName : element.name;
- return new ast.Name(name, getLibraryReference(element.library));
- }
-
- /// True if the two types have form `C<T1 ... Tm>` and `D<T1 ... Tn>`, and
- /// `T1 ... TN` are distinct type variables with no upper bound, where
- /// `N = max(m,n)`.
- bool areDistinctUnboundTypeVariables(
- ast.Supertype first, ast.Supertype second) {
- var seen = new Set<ast.TypeParameter>();
- if (first.typeArguments.length < second.typeArguments.length) {
- var tmp = first;
- first = second;
- second = tmp;
- }
- for (int i = 0; i < first.typeArguments.length; ++i) {
- var firstArg = first.typeArguments[i];
- if (!(firstArg is ast.TypeParameterType &&
- seen.add(firstArg.parameter) &&
- firstArg.parameter.bound is ast.DynamicType)) {
- return false;
- }
- if (i < second.typeArguments.length &&
- firstArg != second.typeArguments[i]) {
- return false;
- }
- }
- return true;
- }
-
- /// Returns the canonical mixin application of two classes, instantiated with
- /// the same list of unbound type variables.
- ///
- /// Given two classes:
- /// class C<C1 ... Cm>
- /// class D<D1 ... Dn>
- ///
- /// This creates or reuses a mixin application class in the library of form:
- ///
- /// abstract class C&D<T1 ... TN> = C<T1 ... Tm> with D<T1 ... Tn>
- ///
- /// where `N = max(m,n)`.
- ///
- /// Such a class can in general contain type errors due to incompatible
- /// inheritance from `C` and `D`. This method therefore should only be called
- /// if a mixin application `C<S1 ... Sm> with D<S1 ... Sn>` is seen, where
- /// `S1 ... SN` are distinct, unbound type variables.
- ast.Class getSharedMixinApplicationClass(
- ast.Library library, ast.Class superclass, ast.Class mixedInClass) {
- // TODO(asgerf): Avoid potential name clash due to associativity.
- // As it is, these mixins get the same name:
- // (A with B) with C
- // A with (B with C)
- String name = '${superclass.name}&${mixedInClass.name}';
- return _mixinApplications
- .putIfAbsent(library, () => <String, ast.Class>{})
- .putIfAbsent(name, () {
- var fresh =
- superclass.typeParameters.length >= mixedInClass.typeParameters.length
- ? getFreshTypeParameters(superclass.typeParameters)
- : getFreshTypeParameters(mixedInClass.typeParameters);
- var typeArguments =
- fresh.freshTypeParameters.map(makeTypeParameterType).toList();
- var superArgs = typeArguments.length != superclass.typeParameters.length
- ? typeArguments.sublist(0, superclass.typeParameters.length)
- : typeArguments;
- var mixinArgs = typeArguments.length != mixedInClass.typeParameters.length
- ? typeArguments.sublist(0, mixedInClass.typeParameters.length)
- : typeArguments;
- var result = new ast.Class(
- name: name,
- isAbstract: true,
- typeParameters: fresh.freshTypeParameters,
- supertype: new ast.Supertype(superclass, superArgs),
- mixedInType: new ast.Supertype(mixedInClass, mixinArgs),
- fileUri: library.fileUri);
- result.level = ast.ClassLevel.Type;
- library.addClass(result);
- return result;
- });
- }
-
- String formatErrorMessage(
- AnalysisError error, String filename, LineInfo lines) {
- var location = lines.getLocation(error.offset);
- return '[error] ${error.message} ($filename, '
- 'line ${location.lineNumber}, '
- 'col ${location.columnNumber})';
- }
-
- void ensureLibraryIsLoaded(ast.Library node) {
- _ensureLibraryIsLoaded(node);
- _iterateMixinLibraryWorklist();
- }
-
- void _ensureLibraryIsLoaded(ast.Library node) {
- if (!node.isExternal) return;
- node.isExternal = false;
- var source = context.sourceFactory
- .forUri2(applicationRoot.absoluteUri(node.importUri));
- assert(source != null);
- var element = context.computeLibraryElement(source);
- var units = <CompilationUnit>[];
- bool reportErrors = node.importUri.scheme != 'dart';
- var tree = context.resolveCompilationUnit(source, element);
- units.add(tree);
- if (reportErrors) _processErrors(source);
- for (var part in element.parts) {
- var source = part.source;
- units.add(context.resolveCompilationUnit(source, element));
- if (reportErrors) _processErrors(source);
- }
- for (var import in element.imports) {
- if (import.isDeferred && import.prefix != null) {
- node.addDependency(new ast.LibraryDependency.deferredImport(
- getLibraryReference(import.importedLibrary), import.prefix.name));
- } else {
- node.addDependency(new ast.LibraryDependency.import(
- getLibraryReference(import.importedLibrary),
- name: import.prefix?.name));
- }
- }
- for (var export in element.exports) {
- node.addDependency(new ast.LibraryDependency.export(
- getLibraryReference(export.exportedLibrary)));
- }
- _buildLibraryBody(element, node, units);
- }
-
- void _processErrors(Source source) {
- LineInfo lines;
- for (var error in context.computeErrors(source)) {
- if (error.errorCode is CompileTimeErrorCode ||
- error.errorCode is ParserErrorCode ||
- error.errorCode is ScannerErrorCode ||
- error.errorCode is StrongModeCode) {
- lines ??= context.computeLineInfo(source);
- errors.add(formatErrorMessage(error, source.shortName, lines));
- }
- }
- }
-
- void loadSdkInterface(ast.Component component, Target target) {
- var requiredSdkMembers = target.requiredSdkClasses;
- for (var libraryUri in requiredSdkMembers.keys) {
- var source = context.sourceFactory.forUri2(Uri.parse(libraryUri));
- var libraryElement = context.computeLibraryElement(source);
- for (var member in requiredSdkMembers[libraryUri]) {
- var type = libraryElement.getType(member);
- if (type == null) {
- throw 'Could not find $member in $libraryUri';
- }
- promoteToTypeLevel(getClassReference(type));
- }
- }
- _iterateTemporaryClassWorklist();
- _iterateMixinLibraryWorklist();
- }
-
- void loadEverything({Target target, bool compileSdk}) {
- compileSdk ??= true;
- if (compileSdk) {
- ensureLibraryIsLoaded(getLibraryReference(getDartCoreLibrary()));
- if (target != null) {
- for (var uri in target.extraRequiredLibraries) {
- var library = _findLibraryElement(uri);
- if (library == null) {
- errors.add('Could not find required library $uri');
- continue;
- }
- ensureLibraryIsLoaded(getLibraryReference(library));
- }
- }
- }
- for (int i = 0; i < component.libraries.length; ++i) {
- var library = component.libraries[i];
- if (compileSdk || library.importUri.scheme != 'dart') {
- ensureLibraryIsLoaded(library);
- }
- }
- }
-
- /// Builds a list of sources that have been loaded.
- ///
- /// This operation may be expensive and should only be used for diagnostics.
- List<String> getLoadedFileNames() {
- var list = <String>[];
- for (var library in component.libraries) {
- LibraryElement element = context.computeLibraryElement(context
- .sourceFactory
- .forUri2(applicationRoot.absoluteUri(library.importUri)));
- for (var unit in element.units) {
- list.add(unit.source.fullName);
- }
- }
- return list;
- }
-
- void _iterateTemporaryClassWorklist() {
- while (temporaryClassWorklist.isNotEmpty) {
- var element = temporaryClassWorklist.removeLast();
- promoteToTypeLevel(element);
- }
- }
-
- void _iterateMixinLibraryWorklist() {
- // The worklist groups classes in the same library together so that we
- // request resolved ASTs for each library only once.
- while (mixinLibraryWorklist.isNotEmpty) {
- LibraryElement library = mixinLibraryWorklist.keys.first;
- _libraryBeingLoaded = library;
- List<ClassElement> classes = mixinLibraryWorklist.remove(library);
- for (var class_ in classes) {
- var classNode = getClassReference(class_);
- promoteToMixinLevel(classNode, class_, class_.computeNode());
- }
- _libraryBeingLoaded = null;
- }
- _iterateTemporaryClassWorklist();
- }
-
- ast.Procedure _getMainMethod(Uri uri) {
- Source source = context.sourceFactory.forUri2(uri);
- LibraryElement library = context.computeLibraryElement(source);
- var mainElement = library.entryPoint;
- if (mainElement == null) return null;
- var mainMember = getMemberReference(mainElement);
- if (mainMember is ast.Procedure && !mainMember.isAccessor) {
- return mainMember;
- }
- // Top-level 'main' getters are not supported at the moment.
- return null;
- }
-
- ast.Procedure _makeMissingMainMethod(ast.Library library) {
- var main = new ast.Procedure(
- new ast.Name('main'),
- ast.ProcedureKind.Method,
- new ast.FunctionNode(new ast.ExpressionStatement(new ast.Throw(
- new ast.StringLiteral('Component has no main method')))),
- isStatic: true)
- ..fileUri = library.fileUri;
- library.addMember(main);
- return main;
- }
-
- void loadComponent(Uri mainLibrary, {Target target, bool compileSdk}) {
- ast.Library library = getLibraryReferenceFromUri(mainLibrary);
- ensureLibraryIsLoaded(library);
- var mainMethod = _getMainMethod(mainLibrary);
- loadEverything(target: target, compileSdk: compileSdk);
- if (mainMethod == null) {
- mainMethod = _makeMissingMainMethod(library);
- }
- component.mainMethod = mainMethod;
- for (LibraryElement libraryElement in libraryElements) {
- for (CompilationUnitElement compilationUnitElement
- in libraryElement.units) {
- var source = compilationUnitElement.source;
- LineInfo lineInfo = context.computeLineInfo(source);
- List<int> sourceCode;
- try {
- sourceCode =
- const Utf8Encoder().convert(context.getContents(source).data);
- } catch (e) {
- // The source's contents could not be accessed.
- sourceCode = const <int>[];
- }
- component.uriToSource[source.uri] =
- new ast.Source(lineInfo.lineStarts, sourceCode);
- }
- }
- }
-
- ast.Library loadLibrary(Uri uri) {
- ast.Library library = getLibraryReferenceFromUri(uri);
- ensureLibraryIsLoaded(library);
- return library;
- }
-}
-
-class Bimap<K, V> {
- final Map<K, V> nodeMap = <K, V>{};
- final Map<V, K> inverse = <V, K>{};
-
- bool containsKey(K key) => nodeMap.containsKey(key);
-
- V operator [](K key) => nodeMap[key];
-
- void operator []=(K key, V value) {
- assert(!nodeMap.containsKey(key));
- nodeMap[key] = value;
- inverse[value] = key;
- }
-}
-
-/// Creates [DartLoader]s for a given configuration, while reusing the
-/// [DartSdk] and [Packages] object if possible.
-class DartLoaderBatch {
- Packages packages;
- DartSdk dartSdk;
-
- String lastSdk;
- String lastPackagePath;
- bool lastStrongMode;
-
- Future<DartLoader> getLoader(ast.Component component, DartOptions options,
- {String packageDiscoveryPath}) async {
- if (dartSdk == null ||
- lastSdk != options.sdk ||
- lastStrongMode != options.strongMode) {
- lastSdk = options.sdk;
- lastStrongMode = options.strongMode;
- dartSdk = createDartSdk(options.sdk, strongMode: options.strongModeSdk);
- }
- if (packages == null ||
- lastPackagePath != options.packagePath ||
- packageDiscoveryPath != null) {
- lastPackagePath = options.packagePath;
- packages = await createPackages(options.packagePath,
- discoveryPath: packageDiscoveryPath);
- }
- return new DartLoader(component, options, packages, dartSdk: dartSdk);
- }
-}
-
-Future<Packages> createPackages(String packagePath,
- {String discoveryPath}) async {
- if (packagePath != null) {
- var absolutePath = new io.File(packagePath).absolute.path;
- if (await new io.Directory(packagePath).exists()) {
- return getPackagesDirectory(new Uri.file(absolutePath));
- } else if (await new io.File(packagePath).exists()) {
- return loadPackagesFile(new Uri.file(absolutePath));
- } else {
- throw 'Packages not found: $packagePath';
- }
- }
- if (discoveryPath != null) {
- return findPackagesFromFile(Uri.parse(discoveryPath));
- }
- return Packages.noPackages;
-}
-
-AnalysisOptions createAnalysisOptions(bool strongMode) {
- return new AnalysisOptionsImpl()
- ..strongMode = strongMode
- ..generateImplicitErrors = false
- ..generateSdkErrors = false
- ..preserveComments = false
- ..hint = false
- ..enableSuperMixins = true;
-}
-
-DartSdk createDartSdk(String path, {bool strongMode, bool isSummary}) {
- if (isSummary ?? false) {
- return new SummaryBasedDartSdk(path, strongMode);
- }
- var resources = PhysicalResourceProvider.INSTANCE;
- return new FolderBasedDartSdk(resources, resources.getFolder(path))
- ..context
- .analysisOptions
- .setCrossContextOptionsFrom(createAnalysisOptions(strongMode));
-}
-
-class CustomUriResolver extends UriResolver {
- final ResourceUriResolver _resourceUriResolver;
- final Map<Uri, Uri> _customUrlMappings;
-
- CustomUriResolver(this._resourceUriResolver, this._customUrlMappings);
-
- Source resolveAbsolute(Uri uri, [Uri actualUri]) {
- // TODO(kustermann): Once dartk supports configurable imports we should be
- // able to get rid of this.
- if (uri.toString() == 'package:mojo/src/internal_contract.dart') {
- uri = actualUri = Uri.parse('dart:mojo.internal');
- }
-
- Uri baseUri = uri;
- String relative;
- String path = uri.path;
- int index = path.indexOf('/');
- if (index > 0) {
- baseUri = uri.replace(path: path.substring(0, index));
- relative = path.substring(index + 1);
- }
- Uri baseMapped = _customUrlMappings[baseUri];
- if (baseMapped == null) return null;
-
- Uri mapped = relative != null ? baseMapped.resolve(relative) : baseMapped;
- return _resourceUriResolver.resolveAbsolute(mapped, actualUri);
- }
-
- Uri restoreAbsolute(Source source) {
- return _resourceUriResolver.restoreAbsolute(source);
- }
-}
-
-AnalysisContext createContext(DartOptions options, Packages packages,
- {DartSdk dartSdk}) {
- bool fromSummary = options.sdkSummary != null;
- dartSdk ??= createDartSdk(fromSummary ? options.sdkSummary : options.sdk,
- strongMode: options.strongModeSdk, isSummary: fromSummary);
-
- var resourceProvider = PhysicalResourceProvider.INSTANCE;
- var resourceUriResolver = new ResourceUriResolver(resourceProvider);
- List<UriResolver> resolvers = [];
- var customUriMappings = options.customUriMappings;
- if (customUriMappings != null && customUriMappings.length > 0) {
- resolvers
- .add(new CustomUriResolver(resourceUriResolver, customUriMappings));
- }
- resolvers.add(new DartUriResolver(dartSdk));
- resolvers.add(resourceUriResolver);
-
- if (packages != null) {
- var folderMap = <String, List<Folder>>{};
- packages.asMap().forEach((String packagePath, Uri uri) {
- String path = resourceProvider.pathContext.fromUri(uri);
- folderMap[packagePath] = [resourceProvider.getFolder(path)];
- });
- resolvers.add(new PackageMapUriResolver(resourceProvider, folderMap));
- }
-
- AnalysisContext context = AnalysisEngine.instance.createAnalysisContext()
- ..sourceFactory = new SourceFactory(resolvers)
- ..analysisOptions = createAnalysisOptions(options.strongMode);
-
- options.declaredVariables.forEach((String name, String value) {
- context.declaredVariables.define(name, value);
- });
-
- return context;
-}
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index dce18a5..5884ac1 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -49,6 +49,7 @@
AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
analysisOptions.strongMode = options.strongMode;
analysisOptions.hint = false;
+ analysisOptions.previewDart2 = options.previewDart2;
analysisOptions.lint = options.enableLints;
analysisOptions.generateSdkErrors = options.showSdkWarnings;
analysisOptions.enableTiming = options.enableTiming;
@@ -82,6 +83,9 @@
/// Whether to use Dart's Strong Mode analyzer.
bool strongMode = true;
+ /// Whether to use Dart 2.0 features.
+ bool previewDart2 = false;
+
/// The mock SDK (to speed up testing) or `null` to use the actual SDK.
DartSdk mockSdk;
diff --git a/pkg/analyzer/lib/src/lint/config.dart b/pkg/analyzer/lib/src/lint/config.dart
index f33b3f3..6f5268d 100644
--- a/pkg/analyzer/lib/src/lint/config.dart
+++ b/pkg/analyzer/lib/src/lint/config.dart
@@ -2,16 +2,17 @@
// 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/util/yaml.dart';
import 'package:yaml/yaml.dart';
/**
* Parse the given map into a lint config.
*/
-LintConfig parseConfig(Map optionsMap) {
+LintConfig parseConfig(YamlMap optionsMap) {
if (optionsMap != null) {
- var options = optionsMap['linter'];
+ var options = getValue(optionsMap, 'linter');
// Quick check of basic contract.
- if (options is Map) {
+ if (options is YamlMap) {
return new LintConfig.parseMap(options);
}
}
@@ -37,7 +38,8 @@
factory LintConfig.parse(String source, {String sourceUrl}) =>
new _LintConfig().._parse(source, sourceUrl: sourceUrl);
- factory LintConfig.parseMap(Map map) => new _LintConfig().._parseMap(map);
+ factory LintConfig.parseMap(YamlMap map) =>
+ new _LintConfig().._parseYaml(map);
List<String> get fileExcludes;
List<String> get fileIncludes;
@@ -76,14 +78,15 @@
}
bool asBool(scalar) {
- if (scalar is bool) {
- return scalar;
+ Object value = scalar is YamlScalar ? scalar.value : scalar;
+ if (value is bool) {
+ return value;
}
- if (scalar is String) {
- if (scalar == 'true') {
+ if (value is String) {
+ if (value == 'true') {
return true;
}
- if (scalar == 'false') {
+ if (value == 'false') {
return false;
}
}
@@ -91,8 +94,9 @@
}
String asString(scalar) {
- if (scalar is String) {
- return scalar;
+ Object value = scalar is YamlScalar ? scalar.value : scalar;
+ if (value is String) {
+ return value;
}
return null;
}
@@ -112,71 +116,6 @@
}
}
- void _parseMap(Map options) {
- //TODO(pq): unify map parsing.
- if (options is YamlMap) {
- _parseYaml(options);
- } else {
- _parseRawMap(options);
- }
- }
-
- void _parseRawMap(Map options) {
- options.forEach((k, v) {
- if (k is! String) {
- return;
- }
- String key = k;
- switch (key) {
- case 'files':
- if (v is Map) {
- addAsListOrString(v['include'], fileIncludes);
- addAsListOrString(v['exclude'], fileExcludes);
- }
- break;
-
- case 'rules':
- // - unnecessary_getters
- // - camel_case_types
- if (v is List) {
- v.forEach((rule) {
- var config = new _RuleConfig();
- config.name = asString(rule);
- config.args = {'enabled': true};
- ruleConfigs.add(config);
- });
- }
-
- // {unnecessary_getters: false, camel_case_types: true}
- if (v is Map) {
- v.forEach((key, value) {
- // style_guide: {unnecessary_getters: false, camel_case_types: true}
- if (value is Map) {
- value.forEach((rule, args) {
- // unnecessary_getters: false
- var config = new _RuleConfig();
- config.group = key;
- config.name = asString(rule);
- config.args = parseArgs(args);
- ruleConfigs.add(config);
- });
- } else {
- //{unnecessary_getters: false}
- value = asBool(value);
- if (value != null) {
- var config = new _RuleConfig();
- config.name = asString(key);
- config.args = {'enabled': value};
- ruleConfigs.add(config);
- }
- }
- });
- }
- break;
- }
- });
- }
-
void _parseYaml(YamlMap yaml) {
yaml.nodes.forEach((k, v) {
if (k is! YamlScalar) {
@@ -195,8 +134,8 @@
// - unnecessary_getters
// - camel_case_types
- if (v is List) {
- (v as List).forEach((rule) {
+ if (v is YamlList) {
+ v.nodes.forEach((rule) {
var config = new _RuleConfig();
config.name = asString(rule);
config.args = {'enabled': true};
@@ -206,22 +145,22 @@
// style_guide: {unnecessary_getters: false, camel_case_types: true}
if (v is YamlMap) {
- v.forEach((key, value) {
+ v.nodes.forEach((key, value) {
//{unnecessary_getters: false}
- if (value is bool) {
+ if (asBool(value) != null) {
var config = new _RuleConfig();
config.name = asString(key);
- config.args = {'enabled': value};
+ config.args = {'enabled': asBool(value)};
ruleConfigs.add(config);
}
// style_guide: {unnecessary_getters: false, camel_case_types: true}
if (value is YamlMap) {
- value.forEach((rule, args) {
+ value.nodes.forEach((rule, args) {
// TODO: verify format
// unnecessary_getters: false
var config = new _RuleConfig();
- config.group = key;
+ config.group = asString(key);
config.name = asString(rule);
config.args = parseArgs(args);
ruleConfigs.add(config);
diff --git a/pkg/analyzer/lib/src/lint/options_rule_validator.dart b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
index 109cdd2..217778a 100644
--- a/pkg/analyzer/lib/src/lint/options_rule_validator.dart
+++ b/pkg/analyzer/lib/src/lint/options_rule_validator.dart
@@ -5,6 +5,7 @@
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/src/lint/registry.dart';
+import 'package:analyzer/src/util/yaml.dart';
import 'package:yaml/yaml.dart';
/**
@@ -24,18 +25,17 @@
static const linter = 'linter';
static const rulesKey = 'rules';
@override
- List<AnalysisError> validate(
- ErrorReporter reporter, Map<String, YamlNode> options) {
+ List<AnalysisError> validate(ErrorReporter reporter, YamlMap options) {
List<AnalysisError> errors = <AnalysisError>[];
- var node = options[linter];
+ var node = getValue(options, linter);
if (node is YamlMap) {
- var rules = node.nodes[rulesKey];
+ var rules = getValue(node, rulesKey);
validateRules(rules, reporter);
}
return errors;
}
- validateRules(dynamic rules, ErrorReporter reporter) {
+ validateRules(YamlNode rules, ErrorReporter reporter) {
if (rules is YamlList) {
Iterable<String> registeredLints =
Registry.ruleRegistry.map((r) => r.name);
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index e0a25cb..ea14ea6 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -100,7 +100,7 @@
* from the given [contents] using the given [key].
*/
Map<dynamic, YamlNode> _getDeclaredDependencies(
- ErrorReporter reporter, Map<String, YamlNode> contents, String key) {
+ ErrorReporter reporter, Map<dynamic, YamlNode> contents, String key) {
YamlNode field = contents[key];
if (field == null) {
return <String, YamlNode>{};
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 4fae935..c7c83de 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -2,8 +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.
-library analyzer.src.task.options;
-
import 'dart:collection';
import 'package:analyzer/analyzer.dart';
@@ -34,8 +32,7 @@
final _OptionsProcessor _processor = new _OptionsProcessor();
-void applyToAnalysisOptions(
- AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+void applyToAnalysisOptions(AnalysisOptionsImpl options, YamlMap optionMap) {
_processor.applyToAnalysisOptions(options, optionMap);
}
@@ -110,7 +107,7 @@
CompositeValidator(this.validators);
@override
- void validate(ErrorReporter reporter, Map<String, YamlNode> options) =>
+ void validate(ErrorReporter reporter, YamlMap options) =>
validators.forEach((v) => v.validate(reporter, options));
}
@@ -170,10 +167,10 @@
}
@override
- void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
- var analyzer = options[AnalyzerOptions.analyzer];
+ void validate(ErrorReporter reporter, YamlMap options) {
+ var analyzer = getValue(options, AnalyzerOptions.analyzer);
if (analyzer is YamlMap) {
- var filters = analyzer[AnalyzerOptions.errors];
+ var filters = getValue(analyzer, AnalyzerOptions.errors);
if (filters is YamlMap) {
String value;
filters.nodes.forEach((k, v) {
@@ -251,7 +248,7 @@
new AnalysisOptionsProvider(sourceFactory);
// Validate the specified options and any included option files
- void validate(Source source, Map<String, YamlNode> options) {
+ void validate(Source source, YamlMap options) {
List<AnalysisError> validationErrors =
new OptionsFileValidator(source).validate(options);
if (initialIncludeSpan != null && validationErrors.isNotEmpty) {
@@ -273,7 +270,7 @@
errors.addAll(validationErrors);
}
- YamlNode node = options[AnalyzerOptions.include];
+ YamlNode node = getValue(options, AnalyzerOptions.include);
if (node == null) {
return;
}
@@ -291,7 +288,7 @@
return;
}
try {
- Map<String, YamlNode> options =
+ YamlMap options =
optionsProvider.getOptionsFromString(includedSource.contents.data);
validate(includedSource, options);
} on OptionsFormatException catch (e) {
@@ -313,8 +310,7 @@
}
try {
- Map<String, YamlNode> options =
- optionsProvider.getOptionsFromString(content);
+ YamlMap options = optionsProvider.getOptionsFromString(content);
validate(source, options);
} on OptionsFormatException catch (e) {
SourceSpan span = e.span;
@@ -360,10 +356,10 @@
ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder();
@override
- void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
- var analyzer = options[AnalyzerOptions.analyzer];
+ void validate(ErrorReporter reporter, YamlMap options) {
+ var analyzer = getValue(options, AnalyzerOptions.analyzer);
if (analyzer is YamlMap) {
- var language = analyzer[AnalyzerOptions.language];
+ var language = getValue(analyzer, AnalyzerOptions.language);
if (language is YamlMap) {
language.nodes.forEach((k, v) {
String key, value;
@@ -408,7 +404,7 @@
OptionsFileValidator(this.source);
- List<AnalysisError> validate(Map<String, YamlNode> options) {
+ List<AnalysisError> validate(YamlMap options) {
RecordingErrorListener recorder = new RecordingErrorListener();
ErrorReporter reporter = new ErrorReporter(recorder, source);
if (AnalysisEngine.ANALYSIS_OPTIONS_FILE == source.shortName) {
@@ -429,10 +425,10 @@
ErrorBuilder trueOrFalseBuilder = new TrueOrFalseValueErrorBuilder();
@override
- void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
- var analyzer = options[AnalyzerOptions.analyzer];
+ void validate(ErrorReporter reporter, YamlMap options) {
+ var analyzer = getValue(options, AnalyzerOptions.analyzer);
if (analyzer is YamlMap) {
- var v = analyzer.nodes[AnalyzerOptions.strong_mode];
+ var v = getValue(analyzer, AnalyzerOptions.strong_mode);
if (v is YamlScalar) {
var value = toLowerCase(v.value);
if (!AnalyzerOptions.trueOrFalse.contains(value)) {
@@ -476,8 +472,8 @@
}
@override
- void validate(ErrorReporter reporter, Map<String, YamlNode> options) {
- YamlNode node = options[pluginName];
+ void validate(ErrorReporter reporter, YamlMap options) {
+ YamlNode node = getValue(options, pluginName);
if (node is YamlMap) {
node.nodes.forEach((k, v) {
if (k is YamlScalar) {
@@ -507,44 +503,46 @@
/**
* Apply the options in the given [optionMap] to the given analysis [options].
*/
- void applyToAnalysisOptions(
- AnalysisOptionsImpl options, Map<String, Object> optionMap) {
+ void applyToAnalysisOptions(AnalysisOptionsImpl options, YamlMap optionMap) {
if (optionMap == null) {
return;
}
- var analyzer = optionMap[AnalyzerOptions.analyzer];
- if (analyzer is Map) {
+ var analyzer = getValue(optionMap, AnalyzerOptions.analyzer);
+ if (analyzer is YamlMap) {
// Process strong mode option.
- var strongMode = analyzer[AnalyzerOptions.strong_mode];
+ var strongMode = getValue(analyzer, AnalyzerOptions.strong_mode);
_applyStrongOptions(options, strongMode);
// Set filters.
- var filters = analyzer[AnalyzerOptions.errors];
+ var filters = getValue(analyzer, AnalyzerOptions.errors);
_applyProcessors(options, filters);
// Process language options.
- var language = analyzer[AnalyzerOptions.language];
+ var language = getValue(analyzer, AnalyzerOptions.language);
_applyLanguageOptions(options, language);
// Process excludes.
- var excludes = analyzer[AnalyzerOptions.exclude];
+ var excludes = getValue(analyzer, AnalyzerOptions.exclude);
_applyExcludes(options, excludes);
// Process plugins.
- var names = analyzer[AnalyzerOptions.plugins];
+ var names = getValue(analyzer, AnalyzerOptions.plugins);
List<String> pluginNames = <String>[];
- if (names is String) {
- pluginNames.add(names);
- } else if (names is List) {
- for (var element in names) {
- if (element is String) {
- pluginNames.add(element);
+ String pluginName = _toString(names);
+ if (pluginName != null) {
+ pluginNames.add(pluginName);
+ } else if (names is YamlList) {
+ for (var element in names.nodes) {
+ String pluginName = _toString(element);
+ if (pluginName != null) {
+ pluginNames.add(pluginName);
}
}
- } else if (names is Map) {
- for (var key in names.keys) {
- if (key is String) {
- pluginNames.add(key);
+ } else if (names is YamlMap) {
+ for (var key in names.nodes.keys) {
+ String pluginName = _toString(key);
+ if (pluginName != null) {
+ pluginNames.add(pluginName);
}
}
}
@@ -561,8 +559,8 @@
}
}
- void _applyExcludes(AnalysisOptionsImpl options, Object excludes) {
- if (excludes is List) {
+ void _applyExcludes(AnalysisOptionsImpl options, YamlNode excludes) {
+ if (excludes is YamlList) {
List<String> excludeList = toStringList(excludes);
if (excludeList != null) {
options.excludePatterns = excludeList;
@@ -582,7 +580,7 @@
}
}
- void _applyLanguageOptions(AnalysisOptionsImpl options, Object configs) {
+ void _applyLanguageOptions(AnalysisOptionsImpl options, YamlNode configs) {
if (configs is YamlMap) {
configs.nodes.forEach((key, value) {
if (key is YamlScalar && value is YamlScalar) {
@@ -590,19 +588,16 @@
_applyLanguageOption(options, feature, value.value);
}
});
- } else if (configs is Map) {
- configs
- .forEach((key, value) => _applyLanguageOption(options, key, value));
}
}
- void _applyProcessors(AnalysisOptionsImpl options, Object codes) {
+ void _applyProcessors(AnalysisOptionsImpl options, YamlNode codes) {
ErrorConfig config = new ErrorConfig(codes);
options.errorProcessors = config.processors;
}
void _applyStrongModeOption(
- AnalysisOptionsImpl options, Object feature, Object value) {
+ AnalysisOptionsImpl options, String feature, Object value) {
bool boolValue = toBool(value);
if (boolValue != null) {
if (feature == AnalyzerOptions.declarationCasts) {
@@ -617,7 +612,7 @@
}
}
- void _applyStrongOptions(AnalysisOptionsImpl options, Object config) {
+ void _applyStrongOptions(AnalysisOptionsImpl options, YamlNode config) {
if (config is YamlMap) {
options.strongMode = true;
config.nodes.forEach((k, v) {
@@ -625,11 +620,21 @@
_applyStrongModeOption(options, k.value?.toString(), v.value);
}
});
- } else if (config is Map) {
- options.strongMode = true;
- config.forEach((k, v) => _applyStrongModeOption(options, k, v));
} else {
- options.strongMode = config is bool ? config : false;
+ bool value = toBool(config);
+ if (value != null) {
+ options.strongMode = value;
+ }
}
}
+
+ String _toString(YamlNode node) {
+ if (node is YamlScalar) {
+ var value = node.value;
+ if (value is String) {
+ return value;
+ }
+ }
+ return null;
+ }
}
diff --git a/pkg/analyzer/lib/src/util/yaml.dart b/pkg/analyzer/lib/src/util/yaml.dart
index 89b6156..cb0175b 100644
--- a/pkg/analyzer/lib/src/util/yaml.dart
+++ b/pkg/analyzer/lib/src/util/yaml.dart
@@ -4,6 +4,20 @@
import 'dart:collection';
+import 'package:yaml/src/event.dart';
+import 'package:yaml/yaml.dart';
+
+/// Given a [map], return the value associated with the key whose value matches
+/// the given [key], or `null` if there is no matching key.
+YamlNode getValue(YamlMap map, String key) {
+ for (var k in map.nodes.keys) {
+ if (k is YamlScalar && k.value == key) {
+ return map.nodes[k];
+ }
+ }
+ return null;
+}
+
/// If all of the elements of [list] are strings, return a list of strings
/// containing the same elements. Otherwise, return `null`.
List<String> toStringList(List list) {
@@ -21,6 +35,15 @@
return stringList;
}
+bool _contains(YamlList l1, YamlNode n2) {
+ for (YamlNode n1 in l1.nodes) {
+ if (n1.value == n2.value) {
+ return true;
+ }
+ }
+ return false;
+}
+
/// Merges two maps (of yaml) with simple override semantics, suitable for
/// merging two maps where one map defines default values that are added to
/// (and possibly overridden) by an overriding map.
@@ -34,40 +57,66 @@
/// * maps are merged recursively.
/// * if map values cannot be merged, the overriding value is taken.
///
- Object merge(Object o1, Object o2) {
+ YamlNode merge(YamlNode o1, YamlNode o2) {
// Handle promotion first.
- if (o1 is List && isMapToBools(o2)) {
- o1 = new Map.fromIterable(o1, key: (item) => item, value: (item) => true);
- } else if (isMapToBools(o1) && o2 is List) {
- o2 = new Map.fromIterable(o2, key: (item) => item, value: (item) => true);
+ YamlMap listToMap(YamlList list) {
+ Map<YamlNode, YamlNode> map = new HashMap<YamlNode,
+ YamlNode>(); // equals: _equals, hashCode: _hashCode
+ ScalarEvent event = new ScalarEvent(null, 'true', ScalarStyle.PLAIN);
+ for (var element in list.nodes) {
+ map[element] = new YamlScalar.internal(true, event);
+ }
+ return new YamlMap.internal(map, null, CollectionStyle.BLOCK);
}
- if (o1 is Map && o2 is Map) {
+ if (isListOfString(o1) && isMapToBools(o2)) {
+ o1 = listToMap(o1 as YamlList);
+ } else if (isMapToBools(o1) && isListOfString(o2)) {
+ o2 = listToMap(o2 as YamlList);
+ }
+
+ if (o1 is YamlMap && o2 is YamlMap) {
return mergeMap(o1, o2);
}
- if (o1 is List && o2 is List) {
+ if (o1 is YamlList && o2 is YamlList) {
return mergeList(o1, o2);
}
- // Default to override.
- return o2;
+ // Default to override, unless the overriding value is `null`.
+ return o2 ?? o1;
}
/// Merge lists, avoiding duplicates.
- List<E> mergeList<E>(List<E> l1, List<E> l2) =>
- new List<E>()..addAll(l1)..addAll(l2.where((item) => !l1.contains(item)));
-
- /// Merge maps (recursively).
- Map<K, V> mergeMap<K, V>(Map<K, V> m1, Map<K, V> m2) {
- Map<K, V> merged = new HashMap<K, V>()..addAll(m1);
- m2.forEach((k, v) {
- // TODO(brianwilkerson) This fails when merging two Map<String, YamlNode>
- // objects and the result of `merge` is a HashMap (because the YamlNodes
- // were YamlMaps.
- merged[k] = merge(merged[k], v);
- });
- return merged;
+ YamlList mergeList(YamlList l1, YamlList l2) {
+ List<YamlNode> list = <YamlNode>[];
+ list.addAll(l1.nodes);
+ for (YamlNode n2 in l2.nodes) {
+ if (!_contains(l1, n2)) {
+ list.add(n2);
+ }
+ }
+ return new YamlList.internal(list, null, CollectionStyle.BLOCK);
}
+ /// Merge maps (recursively).
+ YamlMap mergeMap(YamlMap m1, YamlMap m2) {
+ Map<YamlNode, YamlNode> merged = new HashMap<YamlNode,
+ YamlNode>(); // equals: _equals, hashCode: _hashCode
+ m1.nodes.forEach((k, v) {
+ merged[k] = v;
+ });
+ m2.nodes.forEach((k, v) {
+ YamlScalar mergedKey = merged.keys
+ .firstWhere((key) => key.value == k.value, orElse: () => k);
+ merged[mergedKey] = merge(merged[mergedKey], v);
+ });
+ return new YamlMap.internal(merged, null, CollectionStyle.BLOCK);
+ }
+
+ static bool isListOfString(Object o) =>
+ o is YamlList &&
+ o.nodes.every((e) => e is YamlScalar && e.value is String);
+
static bool isMapToBools(Object o) =>
- o is Map && o.values.every((v) => v is bool);
+ o is YamlMap &&
+ o.nodes.values.every((v) => v is YamlScalar && v.value is bool);
}
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 0385dba..03c52e1 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -2,8 +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.
-library analyzer.test.generated.hint_code_test;
-
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/codes.dart';
@@ -14,6 +12,7 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../src/util/yaml_test.dart';
import 'resolver_test_case.dart';
main() {
@@ -3053,13 +3052,15 @@
test_strongMode_downCastCompositeWarn() async {
AnalysisOptionsImpl options = new AnalysisOptionsImpl();
- applyToAnalysisOptions(options, {
- AnalyzerOptions.analyzer: {
- AnalyzerOptions.errors: {
- StrongModeCode.DOWN_CAST_COMPOSITE.name: 'warning'
- },
- }
- });
+ applyToAnalysisOptions(
+ options,
+ wrap({
+ AnalyzerOptions.analyzer: {
+ AnalyzerOptions.errors: {
+ StrongModeCode.DOWN_CAST_COMPOSITE.name: 'warning'
+ },
+ }
+ }));
options.strongMode = true;
options.strongModeHints = false;
resetWith(options: options);
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index cf19032..7ffd79f 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -114,8 +114,9 @@
}
@override
- void beginClassDeclaration(Token beginToken, Token name) {
- super.beginClassDeclaration(beginToken, name);
+ void beginClassDeclaration(
+ Token beginToken, Token abstractToken, Token name) {
+ super.beginClassDeclaration(beginToken, abstractToken, name);
begin('ClassDeclaration');
}
@@ -397,8 +398,9 @@
}
@override
- void beginNamedMixinApplication(Token beginToken, Token name) {
- super.beginNamedMixinApplication(beginToken, name);
+ void beginNamedMixinApplication(
+ Token beginToken, Token abstractToken, Token name) {
+ super.beginNamedMixinApplication(beginToken, abstractToken, name);
begin('NamedMixinApplication');
}
@@ -704,10 +706,12 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
// beginMember --> endFields, endMember
expectIn('Member');
- super.endFields(count, beginToken, endToken);
+ super.endFields(staticToken, covariantToken, varFinalOrConst, count,
+ beginToken, endToken);
}
@override
@@ -999,9 +1003,11 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
end('TopLevelMember');
- super.endTopLevelFields(count, beginToken, endToken);
+ super.endTopLevelFields(staticToken, covariantToken, varFinalOrConst, count,
+ beginToken, endToken);
}
@override
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index b3465ea..fb9d1c0 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -112,44 +112,6 @@
with ErrorParserTestMixin {
@override
@failingTest
- void test_expectedInterpolationIdentifier() {
- // TODO(brianwilkerson) Does not recover.
- // RangeError: Value not in range: -1
- // dart:core _StringBase.substring
- // package:front_end/src/fasta/quote.dart 130:12 unescapeLastStringPart
- // package:analyzer/src/fasta/ast_builder.dart 187:17 AstBuilder.endLiteralString
- // test/generated/parser_fasta_listener.dart 896:14 ForwardingTestListener.endLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3497:14 Parser.parseSingleLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3434:13 Parser.parseLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3133:14 Parser.parsePrimary
- // package:front_end/src/fasta/parser/parser.dart 3097:14 Parser.parseUnaryExpression
- // package:front_end/src/fasta/parser/parser.dart 2968:13 Parser.parsePrecedenceExpression
- // package:front_end/src/fasta/parser/parser.dart 2942:11 Parser.parseExpression
- // test/generated/parser_fasta_test.dart 2929:39 ParserProxy._run
- super.test_expectedInterpolationIdentifier();
- }
-
- @override
- @failingTest
- void test_expectedInterpolationIdentifier_emptyString() {
- // TODO(brianwilkerson) Does not recover.
- // RangeError: Value not in range: -1
- // dart:core _StringBase.substring
- // package:front_end/src/fasta/quote.dart 130:12 unescapeLastStringPart
- // package:analyzer/src/fasta/ast_builder.dart 187:17 AstBuilder.endLiteralString
- // test/generated/parser_fasta_listener.dart 896:14 ForwardingTestListener.endLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3497:14 Parser.parseSingleLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3434:13 Parser.parseLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3133:14 Parser.parsePrimary
- // package:front_end/src/fasta/parser/parser.dart 3097:14 Parser.parseUnaryExpression
- // package:front_end/src/fasta/parser/parser.dart 2968:13 Parser.parsePrecedenceExpression
- // package:front_end/src/fasta/parser/parser.dart 2942:11 Parser.parseExpression
- // test/generated/parser_fasta_test.dart 2929:39 ParserProxy._run
- super.test_expectedInterpolationIdentifier_emptyString();
- }
-
- @override
- @failingTest
void test_expectedListOrMapLiteral() {
// TODO(brianwilkerson) Does not recover.
// type 'IntegerLiteralImpl' is not a subtype of type 'TypedLiteral' in type cast where
@@ -175,22 +137,6 @@
@override
@failingTest
- void test_expectedToken_whileMissingInDoStatement() {
- // TODO(brianwilkerson) Does not recover.
- // NoSuchMethodError: Class 'SimpleToken' has no instance getter 'endGroup'.
- // Receiver: Instance of 'SimpleToken'
- // Tried calling: endGroup
- // dart:core Object.noSuchMethod
- // package:front_end/src/fasta/parser/parser.dart 3212:26 Parser.parseParenthesizedExpression
- // package:front_end/src/fasta/parser/parser.dart 3781:13 Parser.parseDoWhileStatement
- // package:front_end/src/fasta/parser/parser.dart 2756:14 Parser.parseStatementX
- // package:front_end/src/fasta/parser/parser.dart 2722:20 Parser.parseStatement
- // test/generated/parser_fasta_test.dart 2973:39 ParserProxy._run
- super.test_expectedToken_whileMissingInDoStatement();
- }
-
- @override
- @failingTest
void test_getterInFunction_block_noReturnType() {
// TODO(brianwilkerson) Does not recover.
// type 'ExpressionStatementImpl' is not a subtype of type 'FunctionDeclarationStatement' of 'statement' where
@@ -345,25 +291,6 @@
@override
@failingTest
- void test_invalidInterpolationIdentifier_startWithDigit() {
- // TODO(brianwilkerson) Does not recover.
- // RangeError: Value not in range: -1
- // dart:core _StringBase.substring
- // package:front_end/src/fasta/quote.dart 130:12 unescapeLastStringPart
- // package:analyzer/src/fasta/ast_builder.dart 181:17 AstBuilder.endLiteralString
- // test/generated/parser_fasta_listener.dart 896:14 ForwardingTestListener.endLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3497:14 Parser.parseSingleLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3434:13 Parser.parseLiteralString
- // package:front_end/src/fasta/parser/parser.dart 3133:14 Parser.parsePrimary
- // package:front_end/src/fasta/parser/parser.dart 3097:14 Parser.parseUnaryExpression
- // package:front_end/src/fasta/parser/parser.dart 2968:13 Parser.parsePrecedenceExpression
- // package:front_end/src/fasta/parser/parser.dart 2942:11 Parser.parseExpression
- // test/generated/parser_fasta_test.dart 3196:39 ParserProxy._run
- super.test_invalidInterpolationIdentifier_startWithDigit();
- }
-
- @override
- @failingTest
void test_invalidOperatorAfterSuper_primaryExpression() {
// TODO(brianwilkerson) Does not recover.
// Expected: true
@@ -681,38 +608,6 @@
@override
@failingTest
- void test_missingFunctionParameters_local_nonVoid_block() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
- super.test_missingFunctionParameters_local_nonVoid_block();
- }
-
- @override
- @failingTest
- void test_missingFunctionParameters_local_nonVoid_expression() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
- super.test_missingFunctionParameters_local_nonVoid_expression();
- }
-
- @override
- @failingTest
- void test_missingFunctionParameters_local_void_block() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
- super.test_missingFunctionParameters_local_void_block();
- }
-
- @override
- @failingTest
- void test_missingFunctionParameters_local_void_expression() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
- super.test_missingFunctionParameters_local_void_expression();
- }
-
- @override
- @failingTest
void test_missingFunctionParameters_topLevel_void_block() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.MISSING_FUNCTION_PARAMETERS, found 0
@@ -831,14 +726,6 @@
@override
@failingTest
- void test_nonIdentifierLibraryName_library() {
- // TODO(brianwilkerson) Wrong errors:
- // Expected 1 errors of type ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, found 0
- super.test_nonIdentifierLibraryName_library();
- }
-
- @override
- @failingTest
void test_setterInFunction_block() {
// TODO(brianwilkerson) Wrong errors:
// Expected 1 errors of type ParserErrorCode.SETTER_IN_FUNCTION, found 0
@@ -1792,20 +1679,6 @@
@override
@failingTest
- void test_incompleteLocalVariable_beforeIdentifier() {
- // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
- super.test_incompleteLocalVariable_beforeIdentifier();
- }
-
- @override
- @failingTest
- void test_incompleteLocalVariable_beforeKeyword() {
- // TODO(brianwilkerson) reportUnrecoverableErrorWithToken
- super.test_incompleteLocalVariable_beforeKeyword();
- }
-
- @override
- @failingTest
void test_incompleteTypeArguments_field() {
// TODO(brianwilkerson) reportUnrecoverableErrorWithToken
super.test_incompleteTypeArguments_field();
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 353465d..1154211 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -3076,7 +3076,7 @@
void test_expectedInterpolationIdentifier() {
StringLiteral literal = parseExpression("'\$x\$'", errors: [
fe.Scanner.useFasta
- ? expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 3, 1)
+ ? expectedError(ScannerErrorCode.MISSING_IDENTIFIER, 4, 1)
: expectedError(ParserErrorCode.MISSING_IDENTIFIER, 3, 1)
]);
expectNotNullIfNoErrors(literal);
@@ -3130,15 +3130,10 @@
void test_expectedToken_parseStatement_afterVoid() {
parseStatement("void}", expectedEndOffset: 4);
- listener.assertErrors(usingFastaParser
- ? [
- expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1)
- ]
- : [
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
- expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
- ]);
+ listener.assertErrors([
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 4, 1),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)
+ ]);
}
void test_expectedToken_semicolonMissingAfterExport() {
@@ -3197,7 +3192,7 @@
void test_expectedToken_whileMissingInDoStatement() {
parseStatement("do {} (x);");
listener
- .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 9, 1)]);
+ .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
}
void test_expectedTypeName_as() {
@@ -3795,14 +3790,6 @@
]);
}
- void test_initializedVariableInForEach_var() {
- Statement statement = parseStatement('for (var a = 0 in foo) {}');
- expectNotNullIfNoErrors(statement);
- listener.assertErrors([
- expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
- ]);
- }
-
void test_initializedVariableInForEach_annotation() {
Statement statement = parseStatement('for (@Foo var a = 0 in foo) {}');
expectNotNullIfNoErrors(statement);
@@ -3832,7 +3819,8 @@
expectNotNullIfNoErrors(statement);
listener.assertErrors(usingFastaParser
? [
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1),
+ expectedError(ParserErrorCode.EXPECTED_TOKEN, 8, 1),
+ expectedError(ParserErrorCode.MISSING_IDENTIFIER, 9, 1),
expectedError(ParserErrorCode.EXPECTED_TOKEN, 10, 1)
]
: [
@@ -3841,6 +3829,14 @@
]);
}
+ void test_initializedVariableInForEach_var() {
+ Statement statement = parseStatement('for (var a = 0 in foo) {}');
+ expectNotNullIfNoErrors(statement);
+ listener.assertErrors([
+ expectedError(ParserErrorCode.INITIALIZED_VARIABLE_IN_FOR_EACH, 11, 1)
+ ]);
+ }
+
void test_invalidAwaitInFor() {
Statement statement = parseStatement('await for (; ;) {}');
expectNotNullIfNoErrors(statement);
@@ -4103,16 +4099,27 @@
expect(unit, isNotNull);
}
+ void test_localFunction_annotation() {
+ CompilationUnit unit =
+ parseCompilationUnit("class C { m() { @Foo f() {} } }");
+ expect(unit.declarations, hasLength(1));
+ ClassDeclaration declaration = unit.declarations[0];
+ expect(declaration.members, hasLength(1));
+ MethodDeclaration member = declaration.members[0];
+ BlockFunctionBody body = member.body;
+ expect(body.block.statements, hasLength(1));
+ FunctionDeclarationStatement statement = body.block.statements[0];
+ if (usingFastaParser) {
+ expect(statement.functionDeclaration.metadata, hasLength(1));
+ Annotation metadata = statement.functionDeclaration.metadata[0];
+ expect(metadata.name.name, 'Foo');
+ }
+ }
+
void test_localFunctionDeclarationModifier_abstract() {
parseCompilationUnit("class C { m() { abstract f() {} } }",
errors: usingFastaParser
- ? [
- expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8),
- expectedError(
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 25, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 1),
- ]
+ ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
: [
expectedError(
ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
@@ -4122,13 +4129,7 @@
void test_localFunctionDeclarationModifier_external() {
parseCompilationUnit("class C { m() { external f() {} } }",
errors: usingFastaParser
- ? [
- expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8),
- expectedError(
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 25, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 26, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 32, 1),
- ]
+ ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 8)]
: [
expectedError(
ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 8)
@@ -4148,13 +4149,7 @@
void test_localFunctionDeclarationModifier_static() {
parseCompilationUnit("class C { m() { static f() {} } }",
errors: usingFastaParser
- ? [
- expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6),
- expectedError(
- ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE, 23, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 24, 1),
- expectedError(ParserErrorCode.EXPECTED_TOKEN, 30, 1),
- ]
+ ? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 16, 6)]
: [
expectedError(
ParserErrorCode.LOCAL_FUNCTION_DECLARATION_MODIFIER, 16, 6)
@@ -4388,36 +4383,36 @@
[expectedError(ParserErrorCode.MISSING_FUNCTION_BODY, 0, 6)]);
}
- @failingTest
void test_missingFunctionParameters_local_nonVoid_block() {
// The parser does not recognize this as a function declaration, so it tries
// to parse it as an expression statement. It isn't clear what the best
// error message is in this case.
- parseStatement("int f { return x;}");
- listener.assertErrors(
- [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
+ parseStatement("int f { return x;}", expectedEndOffset: 6);
+ listener
+ .assertErrors([expectedError(ParserErrorCode.EXPECTED_TOKEN, 6, 1)]);
}
- @failingTest
void test_missingFunctionParameters_local_nonVoid_expression() {
// The parser does not recognize this as a function declaration, so it tries
// to parse it as an expression statement. It isn't clear what the best
// error message is in this case.
parseStatement("int f => x;");
- listener.assertErrors(
- [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 4, 1)]);
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 6, 2)]
+ : [expectedError(ParserErrorCode.EXPECTED_TOKEN, 0, 3)]);
}
void test_missingFunctionParameters_local_void_block() {
- parseStatement("void f { return x;}");
- listener.assertErrors(
- [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
+ parseStatement("void f { return x;}", expectedEndOffset: 7);
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.EXPECTED_TOKEN, 7, 1)]
+ : [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
}
void test_missingFunctionParameters_local_void_expression() {
parseStatement("void f => x;");
listener.assertErrors(
- [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 5, 1)]);
+ [expectedError(ParserErrorCode.MISSING_FUNCTION_PARAMETERS, 7, 2)]);
}
void test_missingFunctionParameters_topLevel_nonVoid_block() {
@@ -4675,8 +4670,9 @@
void test_missingStatement_afterVoid() {
parseStatement("void;");
- listener
- .assertErrors([expectedError(ParserErrorCode.MISSING_STATEMENT, 0, 4)]);
+ listener.assertErrors(usingFastaParser
+ ? [expectedError(ParserErrorCode.MISSING_IDENTIFIER, 4, 1)]
+ : [expectedError(ParserErrorCode.MISSING_STATEMENT, 4, 1)]);
}
void test_missingTerminatorForParameterGroup_named() {
@@ -4849,7 +4845,9 @@
void test_nonIdentifierLibraryName_library() {
CompilationUnit unit = parseCompilationUnit("library 'lib';", errors: [
- expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
+ usingFastaParser
+ ? expectedError(ParserErrorCode.MISSING_IDENTIFIER, 8, 5)
+ : expectedError(ParserErrorCode.NON_IDENTIFIER_LIBRARY_NAME, 8, 5)
]);
expect(unit, isNotNull);
}
@@ -5547,7 +5545,7 @@
// this would be a better error message.
parseStatement("var int x;");
listener.assertErrors(usingFastaParser
- ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 4, 3)]
+ ? [expectedError(ParserErrorCode.VAR_AND_TYPE, 0, 3)]
: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 8, 1)]);
}
@@ -13779,6 +13777,24 @@
expect(identifier.name, name);
}
+ void test_parseLibraryIdentifier_builtin() {
+ String name = "deferred";
+ LibraryIdentifier identifier = parseLibraryIdentifier(name);
+ expectNotNullIfNoErrors(identifier);
+ listener.assertNoErrors();
+ expect(identifier.name, name);
+ expect(identifier.beginToken.type.isBuiltIn, isTrue);
+ }
+
+ void test_parseLibraryIdentifier_pseudo() {
+ String name = "await";
+ LibraryIdentifier identifier = parseLibraryIdentifier(name);
+ expectNotNullIfNoErrors(identifier);
+ listener.assertNoErrors();
+ expect(identifier.name, name);
+ expect(identifier.beginToken.type.isPseudo, isTrue);
+ }
+
void test_parseOptionalReturnType() {
// TODO(brianwilkerson) Implement tests for this method.
}
@@ -15257,8 +15273,17 @@
expect(statement.finallyBlock, isNotNull);
}
+ void test_parseVariableDeclaration_equals_builtIn() {
+ VariableDeclarationStatement statement = parseStatement('int set = 0;');
+ assertNoErrors();
+ expect(statement.semicolon, isNotNull);
+ VariableDeclarationList variableList = statement.variables;
+ expect(variableList, isNotNull);
+ expect(variableList.variables, hasLength(1));
+ }
+
void test_parseVariableDeclarationListAfterMetadata_const_noType() {
- var declarationList = parseVariableDeclarationList('const a');
+ var declarationList = parseVariableDeclarationList('const a = 0');
assertNoErrors();
expect(declarationList.keyword.lexeme, 'const');
expect(declarationList.type, isNull);
@@ -16924,9 +16949,8 @@
expect(declaration.propertyKeyword, isNotNull);
}
- @failingTest
void test_parseGenericTypeAlias_noTypeParameters() {
- createParser('F = int Function(int);');
+ createParser('typedef F = int Function(int);');
GenericTypeAlias alias = parseFullCompilationUnitMember();
expect(alias, isNotNull);
assertNoErrors();
@@ -16938,9 +16962,8 @@
expect(alias.semicolon, isNotNull);
}
- @failingTest
void test_parseGenericTypeAlias_typeParameters() {
- createParser('F<T> = T Function(T);');
+ createParser('typedef F<T> = T Function(T);');
GenericTypeAlias alias = parseFullCompilationUnitMember();
expect(alias, isNotNull);
assertNoErrors();
diff --git a/pkg/analyzer/test/generated/utilities_test.dart b/pkg/analyzer/test/generated/utilities_test.dart
index b43805a..c184019 100644
--- a/pkg/analyzer/test/generated/utilities_test.dart
+++ b/pkg/analyzer/test/generated/utilities_test.dart
@@ -2903,7 +2903,7 @@
void test_singleMap_empty() {
Map<String, String> map = new HashMap<String, String>();
- MultipleMapIterator<String, String> iterator = _iterator(<Map>[map]);
+ MultipleMapIterator<String, String> iterator = _iterator([map]);
expect(iterator.moveNext(), isFalse);
expect(() => iterator.key, throwsStateError);
expect(() => iterator.value, throwsStateError);
@@ -2939,7 +2939,8 @@
expect(iterator.moveNext(), isFalse);
}
- MultipleMapIterator<String, String> _iterator(List<Map> maps) {
+ MultipleMapIterator<String, String> _iterator(
+ List<Map<String, String>> maps) {
return new MultipleMapIterator<String, String>(maps);
}
}
diff --git a/pkg/analyzer/test/source/analysis_options_provider_test.dart b/pkg/analyzer/test/source/analysis_options_provider_test.dart
index 222afd5..1b53283 100644
--- a/pkg/analyzer/test/source/analysis_options_provider_test.dart
+++ b/pkg/analyzer/test/source/analysis_options_provider_test.dart
@@ -2,8 +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.
-library analyzer.test.source.analysis_options_provider_test;
-
import 'dart:core';
import 'package:analyzer/file_system/file_system.dart';
@@ -11,11 +9,13 @@
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/yaml.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:yaml/yaml.dart';
import '../resource_utils.dart';
+import '../src/util/yaml_test.dart';
main() {
defineReflectiveSuite(() {
@@ -28,7 +28,7 @@
var defaultOptions = optionsProvider.getOptionsFromString(defaults);
var overrideOptions = optionsProvider.getOptionsFromString(overrides);
var merged = optionsProvider.merge(defaultOptions, overrideOptions);
- expect(merged, optionsProvider.getOptionsFromString(expected));
+ expectEquals(merged, optionsProvider.getOptionsFromString(expected));
}
group('merging', () {
@@ -138,12 +138,12 @@
ignore:
- bar
''');
- Map<String, YamlNode> options = _getOptions('/foo/bar', crawlUp: true);
+ YamlMap options = _getOptions('/foo/bar', crawlUp: true);
expect(options, hasLength(1));
{
- YamlMap analyzer = options['analyzer'];
+ YamlMap analyzer = getValue(options, 'analyzer');
expect(analyzer, isNotNull);
- expect(analyzer['ignore'], unorderedEquals(['bar']));
+ expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
}
}
@@ -159,24 +159,24 @@
ignore:
- bar
''');
- Map<String, YamlNode> options = _getOptions('/foo/bar/baz', crawlUp: true);
+ YamlMap options = _getOptions('/foo/bar/baz', crawlUp: true);
expect(options, hasLength(1));
{
- YamlMap analyzer = options['analyzer'];
+ YamlMap analyzer = getValue(options, 'analyzer');
expect(analyzer, isNotNull);
- expect(analyzer['ignore'], unorderedEquals(['bar']));
+ expect(getValue(analyzer, 'ignore'), unorderedEquals(['bar']));
}
}
void test_getOptions_doesNotExist() {
pathTranslator.newFolder('/notFile');
- Map<String, YamlNode> options = _getOptions('/notFile');
+ YamlMap options = _getOptions('/notFile');
expect(options, isEmpty);
}
void test_getOptions_empty() {
pathTranslator.newFile('/$optionsFileName', r'''#empty''');
- Map<String, YamlNode> options = _getOptions('/');
+ YamlMap options = _getOptions('/');
expect(options, isNotNull);
expect(options, isEmpty);
}
@@ -191,13 +191,13 @@
pathTranslator.newFile('/$optionsFileName', r'''
include: foo.include
''');
- Map<String, YamlNode> options = _getOptions('/');
- expect(options, hasLength(1));
+ YamlMap options = _getOptions('/');
+ expect(options, hasLength(2));
{
- YamlMap analyzer = options['analyzer'];
+ YamlMap analyzer = getValue(options, 'analyzer');
expect(analyzer, hasLength(1));
{
- YamlList ignore = analyzer['ignore'];
+ YamlList ignore = getValue(analyzer, 'ignore');
expect(ignore, hasLength(2));
expect(ignore[0], 'ignoreme.dart');
expect(ignore[1], 'sdk_ext/**');
@@ -209,15 +209,14 @@
pathTranslator.newFile('/$optionsFileName', r'''
include: /foo.include
''');
- Map<String, YamlNode> options = _getOptions('/');
- expect(options, hasLength(0));
+ YamlMap options = _getOptions('/');
+ expect(options, hasLength(1));
}
void test_getOptions_invalid() {
pathTranslator.newFile('/$optionsFileName', r''':''');
- expect(() {
- _getOptions('/');
- }, throwsException);
+ YamlMap options = _getOptions('/');
+ expect(options, hasLength(1));
}
void test_getOptions_simple() {
@@ -227,13 +226,13 @@
- ignoreme.dart
- 'sdk_ext/**'
''');
- Map<String, YamlNode> options = _getOptions('/');
+ YamlMap options = _getOptions('/');
expect(options, hasLength(1));
{
- YamlMap analyzer = options['analyzer'];
+ YamlMap analyzer = getValue(options, 'analyzer');
expect(analyzer, hasLength(1));
{
- YamlList ignore = analyzer['ignore'];
+ YamlList ignore = getValue(analyzer, 'ignore');
expect(ignore, hasLength(2));
expect(ignore[0], 'ignoreme.dart');
expect(ignore[1], 'sdk_ext/**');
@@ -241,7 +240,7 @@
}
}
- Map<String, YamlNode> _getOptions(String posixPath, {bool crawlUp: false}) {
+ YamlMap _getOptions(String posixPath, {bool crawlUp: false}) {
Resource resource = pathTranslator.getResource(posixPath);
return provider.getOptions(resource, crawlUp: crawlUp);
}
diff --git a/pkg/analyzer/test/source/error_processor_test.dart b/pkg/analyzer/test/source/error_processor_test.dart
index 5f632f4..7cf74fc 100644
--- a/pkg/analyzer/test/source/error_processor_test.dart
+++ b/pkg/analyzer/test/source/error_processor_test.dart
@@ -2,8 +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.
-library analyzer.test.source.error_processor;
-
import 'package:analyzer/error/error.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
import 'package:analyzer/source/error_processor.dart';
@@ -14,9 +12,10 @@
import 'package:plugin/manager.dart';
import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
-import 'package:yaml/src/yaml_node.dart';
+import 'package:yaml/yaml.dart';
import '../generated/test_support.dart';
+import '../src/util/yaml_test.dart';
main() {
AnalysisError invalid_assignment =
@@ -124,11 +123,11 @@
});
test('string map', () {
- var options = {
+ var options = wrap({
'invalid_assignment': 'unsupported_action', // should be skipped
'missing_return': 'false',
'unused_local_variable': 'error'
- };
+ });
var errorConfig = new ErrorConfig(options);
expect(errorConfig.processors, hasLength(2));
@@ -170,8 +169,7 @@
ErrorProcessor processor;
void configureOptions(String options) {
- Map<String, YamlNode> optionMap =
- optionsProvider.getOptionsFromString(options);
+ YamlMap optionMap = optionsProvider.getOptionsFromString(options);
applyToAnalysisOptions(context.analysisOptions, optionMap);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 32df76a..6d12d04 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -6725,26 +6725,6 @@
expect(x.constantValue.toIntValue(), 1);
}
- test_currentSession() async {
- var a = _p('/a.dart');
-
- provider.newFile(a, 'var V = 1;');
- await driver.getResult(a);
-
- var session1 = driver.currentSession;
- expect(session1, isNotNull);
-
- provider.updateFile(a, 'var V = 2;');
- driver.changeFile(a);
- await driver.getResult(a);
-
- var session2 = driver.currentSession;
- expect(session2, isNotNull);
-
- // We get a new session.
- expect(session2, isNot(session1));
- }
-
test_errors_uriDoesNotExist_export() async {
addTestFile(r'''
export 'foo.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
new file mode 100644
index 0000000..47c5338
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/session_helper_test.dart
@@ -0,0 +1,84 @@
+// 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.
+
+import 'package:analyzer/src/dart/analysis/session_helper.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'base.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(AnalysisSessionHelperTest);
+ });
+}
+
+@reflectiveTest
+class AnalysisSessionHelperTest extends BaseAnalysisDriverTest {
+ AnalysisSessionHelper sessionHelper;
+
+ @override
+ void setUp() {
+ super.setUp();
+ sessionHelper = new AnalysisSessionHelper(driver.currentSession);
+ }
+
+ test_getClass_defined() async {
+ var path = _p('/c.dart');
+ var file = provider.newFile(path, r'''
+class C {}
+int v = 0;
+''');
+ String uri = file.toUri().toString();
+
+ var element = await sessionHelper.getClass(uri, 'C');
+ expect(element, isNotNull);
+ expect(element.displayName, 'C');
+ }
+
+ test_getClass_defined_notClass() async {
+ var path = _p('/c.dart');
+ var file = provider.newFile(path, r'''
+int v = 0;
+''');
+ String uri = file.toUri().toString();
+
+ var element = await sessionHelper.getClass(uri, 'v');
+ expect(element, isNull);
+ }
+
+ test_getClass_exported() async {
+ var a = _p('/a.dart');
+ var b = _p('/b.dart');
+ provider.newFile(a, r'''
+class A {}
+''');
+ var bFile = provider.newFile(b, r'''
+export 'a.dart';
+''');
+ String bUri = bFile.toUri().toString();
+
+ var element = await sessionHelper.getClass(bUri, 'A');
+ expect(element, isNotNull);
+ expect(element.displayName, 'A');
+ }
+
+ test_getClass_imported() async {
+ var a = _p('/a.dart');
+ var b = _p('/b.dart');
+ provider.newFile(a, r'''
+class A {}
+''');
+ var bFile = provider.newFile(b, r'''
+import 'a.dart';
+''');
+ String bUri = bFile.toUri().toString();
+
+ var element = await sessionHelper.getClass(bUri, 'A');
+ expect(element, isNull);
+ }
+
+ /// Return the [provider] specific path for the given Posix [path].
+ String _p(String path) => provider.convertPath(path);
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index 4563972..0654881 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -12,6 +12,7 @@
import 'mutex_test.dart' as mutex;
import 'referenced_names_test.dart' as referenced_names;
import 'search_test.dart' as search_test;
+import 'session_helper_test.dart' as session_helper_test;
import 'session_test.dart' as session_test;
main() {
@@ -24,6 +25,7 @@
mutex.main();
referenced_names.main();
search_test.main();
+ session_helper_test.main();
session_test.main();
}, name: 'analysis');
}
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
index 599953c..b8eb3ff 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/do_statement_test.dart
@@ -55,7 +55,7 @@
ParserErrorCode.EXPECTED_TOKEN
],
"do {} while (_s_);",
- allFailing: true),
+ failing: ['while']),
new TestDescriptor(
'while',
'do {} while',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
index cebc90d..9aac678 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/for_statement_test.dart
@@ -12,32 +12,40 @@
class ForStatementTest extends PartialCodeTest {
buildAll() {
+ List<String> allExceptEof =
+ PartialCodeTest.statementSuffixes.map((t) => t.name).toList();
buildTests(
'for_statement',
[
+ new TestDescriptor('keyword', 'for', [ParserErrorCode.EXPECTED_TOKEN],
+ 'for (;;) {}'),
new TestDescriptor(
- 'keyword',
- 'for',
+ 'emptyParen',
+ 'for ()',
[
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- 'for (;;) {}',
- allFailing: true),
+ "for (_s_;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'leftParen',
'for (',
[
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (;;) {}",
- allFailing: true),
+ "for (_s_;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'var',
'for (var',
@@ -48,61 +56,79 @@
ParserErrorCode.EXPECTED_TOKEN,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (var _s_;;) {}",
+ "for (var _s_;;) _s_;",
allFailing: true),
new TestDescriptor(
'varAndIdentifier',
'for (var i',
[
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (var i;;) {}",
- allFailing: true),
+ "for (var i;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'equals',
'for (var i =',
[
ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (var i = _s_;;) {}",
- allFailing: true),
+ "for (var i = _s_;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'initializer',
'for (var i = 0',
[
ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (var i = 0;;) {}",
- allFailing: true),
+ "for (var i = 0;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'firstSemicolon',
'for (var i = 0;',
[
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN,
- ParserErrorCode.EXPECTED_TOKEN,
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
ParserErrorCode.EXPECTED_TOKEN
],
- "for (var i = 0;;) {}",
- allFailing: true),
+ "for (var i = 0;_s_;) _s_;",
+ failing: allExceptEof),
new TestDescriptor(
'secondSemicolon',
'for (var i = 0;;',
- [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.EXPECTED_TOKEN],
- "for (var i = 0;;) {}",
- allFailing: true),
- new TestDescriptor('rightParen', 'for (var i = 0;;)',
- [ParserErrorCode.EXPECTED_TOKEN], "for (var i = 0;;) {}",
- allFailing: true),
+ [
+ ScannerErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "for (var i = 0;;) _s_;",
+ failing: allExceptEof),
+ new TestDescriptor(
+ 'rightParen',
+ 'for (var i = 0;;)',
+ [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN
+ ],
+ "for (var i = 0;;) _s_;",
+ failing: allExceptEof),
],
PartialCodeTest.statementSuffixes,
head: 'f() { ',
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
index cf68d9c..ba1d480 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/library_directive_test.dart
@@ -12,20 +12,6 @@
class LibraryDirectivesTest extends PartialCodeTest {
buildAll() {
- List<String> allExceptEof = <String>[
- 'import',
- 'export',
- 'part',
- 'class',
- 'typedef',
- 'functionVoid',
- 'functionNonVoid',
- 'var',
- 'const',
- 'final',
- 'getter',
- 'setter'
- ];
buildTests(
'library_directive',
[
@@ -37,7 +23,7 @@
ParserErrorCode.EXPECTED_TOKEN
],
'library _s_;',
- failing: allExceptEof),
+ failing: ['functionNonVoid', 'getter']),
new TestDescriptor('name', 'library lib',
[ParserErrorCode.EXPECTED_TOKEN], 'library lib;'),
new TestDescriptor(
@@ -48,7 +34,7 @@
ParserErrorCode.EXPECTED_TOKEN
],
'library lib._s_;',
- failing: allExceptEof),
+ failing: ['functionNonVoid', 'getter']),
new TestDescriptor('nameDotName', 'library lib.a',
[ParserErrorCode.EXPECTED_TOKEN], 'library lib.a;'),
],
diff --git a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
index 4c2f010..7a54709 100644
--- a/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/partial_code/local_variable_test.dart
@@ -44,39 +44,12 @@
new TestDescriptor('constName', 'const a',
[ParserErrorCode.EXPECTED_TOKEN], "const a;",
failing: <String>[
- 'assert',
- 'break',
- 'continue',
- 'do',
- 'if',
- 'for',
+ 'eof',
'labeled',
'localFunctionNonVoid',
- 'localFunctionVoid',
- 'localVariable',
- 'switch',
- 'try',
- 'return',
- 'while'
]),
new TestDescriptor('constTypeName', 'const int a',
- [ParserErrorCode.EXPECTED_TOKEN], "const int a;",
- failing: <String>[
- 'assert',
- 'break',
- 'continue',
- 'do',
- 'if',
- 'for',
- 'labeled',
- 'localFunctionNonVoid',
- 'localFunctionVoid',
- 'localVariable',
- 'switch',
- 'try',
- 'return',
- 'while'
- ]),
+ [ParserErrorCode.EXPECTED_TOKEN], "const int a;"),
new TestDescriptor(
'constNameComma',
'const a,',
@@ -157,23 +130,7 @@
"int _s_;",
allFailing: true),
new TestDescriptor(
- 'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;",
- failing: [
- 'assert',
- 'break',
- 'continue',
- 'do',
- 'if',
- 'for',
- 'labeled',
- 'localFunctionNonVoid',
- 'localFunctionVoid',
- 'localVariable',
- 'switch',
- 'try',
- 'return',
- 'while'
- ]),
+ 'typeName', 'int a', [ParserErrorCode.EXPECTED_TOKEN], "int a;"),
new TestDescriptor(
'var',
'var',
diff --git a/pkg/analyzer/test/src/lint/config_test.dart b/pkg/analyzer/test/src/lint/config_test.dart
index 44f385d..2b44f9b 100644
--- a/pkg/analyzer/test/src/lint/config_test.dart
+++ b/pkg/analyzer/test/src/lint/config_test.dart
@@ -5,6 +5,8 @@
import 'package:analyzer/src/lint/config.dart';
import 'package:test/test.dart';
+import '../util/yaml_test.dart';
+
main() {
defineTests();
}
@@ -145,7 +147,7 @@
};
options['linter'] = lintOptions;
- var config = parseConfig(options);
+ var config = parseConfig(wrap(options));
expect(config, isNotNull);
expect(config.ruleConfigs, hasLength(1));
});
@@ -157,7 +159,7 @@
};
options['linter'] = lintOptions;
- var config = parseConfig(options);
+ var config = parseConfig(wrap(options));
expect(config, isNotNull);
expect(config.ruleConfigs, hasLength(1));
});
@@ -169,7 +171,7 @@
};
options['linter'] = lintOptions;
- var config = parseConfig(options);
+ var config = parseConfig(wrap(options));
expect(config, isNotNull);
expect(config.ruleConfigs, hasLength(1));
});
@@ -183,7 +185,7 @@
};
options['linter'] = lintOptions;
- var config = parseConfig(options);
+ var config = parseConfig(wrap(options));
expect(config, isNotNull);
expect(config.ruleConfigs, hasLength(1));
});
@@ -197,7 +199,7 @@
};
options['linter'] = lintOptions;
- var config = parseConfig(options);
+ var config = parseConfig(wrap(options));
expect(config, isNotNull);
expect(config.ruleConfigs, hasLength(1));
});
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 4d5bb5e..6bec4ec 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -2,8 +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.
-library analyzer.test.src.task.options_test;
-
import 'dart:mirrors';
import 'package:analyzer/analyzer.dart';
@@ -49,7 +47,7 @@
void configureContext(String optionsSource) =>
applyToAnalysisOptions(analysisOptions, parseOptions(optionsSource));
- Map<String, YamlNode> parseOptions(String source) =>
+ YamlMap parseOptions(String source) =>
optionsProvider.getOptionsFromString(source);
test_configure_bad_options_contents() {
@@ -361,7 +359,9 @@
expect(descriptor, isNotNull);
}
+ @failingTest
test_perform_bad_yaml() {
+ // We have lost the ability to detect this kind of error.
String code = r'''
:
''';
@@ -410,7 +410,9 @@
expect(error.message, contains('other_options.yaml(47..49)'));
}
+ @failingTest
test_perform_include_bad_yaml() {
+ // We have lost the ability to detect this kind of error.
newSource('/other_options.yaml', ':');
String code = r'''
include: other_options.yaml
@@ -703,7 +705,7 @@
]));
}
- Map<String, YamlNode> _getOptions(String posixPath, {bool crawlUp: false}) {
+ YamlMap _getOptions(String posixPath, {bool crawlUp: false}) {
Resource resource = pathTranslator.getResource(posixPath);
return provider.getOptions(resource, crawlUp: crawlUp);
}
diff --git a/pkg/analyzer/test/src/util/yaml_test.dart b/pkg/analyzer/test/src/util/yaml_test.dart
index 4e109ac..ca6054f 100644
--- a/pkg/analyzer/test/src/util/yaml_test.dart
+++ b/pkg/analyzer/test/src/util/yaml_test.dart
@@ -2,10 +2,10 @@
// 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 analyzer.src.test.util.yaml_test;
-
import 'package:analyzer/src/util/yaml.dart';
import 'package:test/test.dart';
+import 'package:yaml/src/event.dart';
+import 'package:yaml/yaml.dart';
main() {
group('yaml', () {
@@ -25,7 +25,7 @@
},
'seven': true
}),
- equals({
+ equals(wrap({
'one': true,
'two': false,
'three': {
@@ -33,18 +33,20 @@
'five': true
},
'seven': true
- }));
+ })));
});
test('list', () {
- expect(merge([1, 2, 3], [2, 3, 4, 5]), equals([1, 2, 3, 4, 5]));
+ expect(merge([1, 2, 3], [2, 3, 4, 5]), equals(wrap([1, 2, 3, 4, 5])));
});
test('list w/ promotion', () {
- expect(merge(['one', 'two', 'three'], {'three': false, 'four': true}),
- equals({'one': true, 'two': true, 'three': false, 'four': true}));
+ expect(
+ merge(['one', 'two', 'three'], {'three': false, 'four': true}),
+ equals(wrap(
+ {'one': true, 'two': true, 'three': false, 'four': true})));
expect(merge({'one': false, 'two': false}, ['one', 'three']),
- equals({'one': true, 'two': false, 'three': true}));
+ equals(wrap({'one': true, 'two': false, 'three': true})));
});
test('map w/ list promotion', () {
@@ -57,7 +59,7 @@
var map3 = {
'one': {'a': true, 'b': false, 'c': true}
};
- expect(merge(map1, map2), map3);
+ expect(merge(map1, map2), wrap(map3));
});
test('map w/ no promotion', () {
@@ -70,7 +72,7 @@
var map3 = {
'one': {'a': 'foo', 'b': 'bar'}
};
- expect(merge(map1, map2), map3);
+ expect(merge(map1, map2), wrap(map3));
});
test('map w/ no promotion (2)', () {
@@ -83,7 +85,7 @@
var map3 = {
'one': ['a', 'b', 'c']
};
- expect(merge(map1, map2), map3);
+ expect(merge(map1, map2), wrap(map3));
});
test('object', () {
@@ -97,4 +99,77 @@
final Merger merger = new Merger();
-Object merge(Object o1, Object o2) => merger.merge(o1, o2);
+bool containsKey(Map<dynamic, YamlNode> map, dynamic key) =>
+ _getValue(map, key) != null;
+
+void expectEquals(YamlNode actual, YamlNode expected) {
+ if (expected is YamlScalar) {
+ expect(actual, new isInstanceOf<YamlScalar>());
+ expect(expected.value, actual.value);
+ } else if (expected is YamlList) {
+ if (actual is YamlList) {
+ expect(actual.length, expected.length);
+ List<YamlNode> expectedNodes = expected.nodes;
+ List<YamlNode> actualNodes = actual.nodes;
+ for (int i = 0; i < expectedNodes.length; i++) {
+ expectEquals(actualNodes[i], expectedNodes[i]);
+ }
+ } else {
+ fail('Expected a YamlList, found ${actual.runtimeType}');
+ }
+ } else if (expected is YamlMap) {
+ if (actual is YamlMap) {
+ expect(actual.length, expected.length);
+ Map<dynamic, YamlNode> expectedNodes = expected.nodes;
+ Map<dynamic, YamlNode> actualNodes = actual.nodes;
+ for (var expectedKey in expectedNodes.keys) {
+ if (!containsKey(actualNodes, expectedKey)) {
+ fail('Missing key $expectedKey');
+ }
+ }
+ for (var actualKey in actualNodes.keys) {
+ if (!containsKey(expectedNodes, actualKey)) {
+ fail('Extra key $actualKey');
+ }
+ }
+ for (var expectedKey in expectedNodes.keys) {
+ expectEquals(_getValue(actualNodes, expectedKey),
+ _getValue(expectedNodes, expectedKey));
+ }
+ } else {
+ fail('Expected a YamlMap, found ${actual.runtimeType}');
+ }
+ } else {
+ fail('Unknown type of node: ${expected.runtimeType}');
+ }
+}
+
+Object merge(Object o1, Object o2) => merger.merge(wrap(o1), wrap(o2)).value;
+
+Object valueOf(Object object) => object is YamlNode ? object.value : object;
+
+YamlNode wrap(Object value) {
+ if (value is List) {
+ List wrappedElements = value.map((e) => wrap(e)).toList();
+ return new YamlList.internal(wrappedElements, null, CollectionStyle.BLOCK);
+ } else if (value is Map) {
+ Map<dynamic, YamlNode> wrappedEntries = <dynamic, YamlNode>{};
+ value.forEach((k, v) {
+ wrappedEntries[wrap(k)] = wrap(v);
+ });
+ return new YamlMap.internal(wrappedEntries, null, CollectionStyle.BLOCK);
+ } else {
+ return new YamlScalar.internal(
+ value, new ScalarEvent(null, '', ScalarStyle.PLAIN));
+ }
+}
+
+YamlNode _getValue(Map map, Object key) {
+ Object keyValue = valueOf(key);
+ for (var existingKey in map.keys) {
+ if (valueOf(existingKey) == keyValue) {
+ return map[existingKey];
+ }
+ }
+ return null;
+}
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index 6e3b75d..f2bbd10 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -379,7 +379,8 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
// We ignore top level variable declarations; they are present just to make
// the IDL analyze without warnings.
debugEvent("TopLevelFields");
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 59ad0f0..c306703 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -34,6 +34,7 @@
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/yaml.dart';
import 'package:analyzer_cli/src/analyzer_impl.dart';
import 'package:analyzer_cli/src/batch_mode.dart';
import 'package:analyzer_cli/src/build_mode.dart';
@@ -76,9 +77,9 @@
telemetry.createAnalyticsInstance(_analyticsID, 'analyzer-cli'));
/// Test this option map to see if it specifies lint rules.
-bool containsLintRuleEntry(Map<String, YamlNode> options) {
- var linterNode = options['linter'];
- return linterNode is YamlMap && linterNode.containsKey('rules');
+bool containsLintRuleEntry(YamlMap options) {
+ YamlNode linterNode = getValue(options, 'linter');
+ return linterNode is YamlMap && getValue(linterNode, 'rules') != null;
}
/// Make sure that we create an analytics instance that doesn't send for this
diff --git a/pkg/analyzer_cli/pubspec.yaml b/pkg/analyzer_cli/pubspec.yaml
index 0db8c4a..f0e587d 100644
--- a/pkg/analyzer_cli/pubspec.yaml
+++ b/pkg/analyzer_cli/pubspec.yaml
@@ -19,6 +19,5 @@
yaml: ^2.1.2
dev_dependencies:
test_reflective_loader: ^0.1.0
- mockito: ^2.0.2
test: ^0.12.0
usage: ^3.2.0+1
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index f638da8..3a51631 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -2,8 +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.
-library analyzer_cli.test.driver;
-
import 'dart:async';
import 'dart:io';
@@ -36,7 +34,8 @@
// defineReflectiveTests(ExitCodesTest_UseCFE);
defineReflectiveTests(LinterTest);
defineReflectiveTests(LinterTest_PreviewDart2);
- defineReflectiveTests(LinterTest_UseCFE);
+ // Disabled until integration with the CFE has been restarted.
+// defineReflectiveTests(LinterTest_UseCFE);
defineReflectiveTests(NonDartFilesTest);
defineReflectiveTests(OptionsTest);
defineReflectiveTests(OptionsTest_PreviewDart2);
@@ -699,8 +698,7 @@
String get optionsFileName => AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE;
test_containsLintRuleEntry() async {
- Map<String, YamlNode> options;
- options = _parseOptions('''
+ YamlMap options = _parseOptions('''
linter:
rules:
- foo
@@ -772,7 +770,7 @@
expect(getLints(driver.context), isEmpty);
}
- Map<String, YamlNode> _parseOptions(String src) =>
+ YamlMap _parseOptions(String src) =>
new AnalysisOptionsProvider().getOptionsFromString(src);
Future<Null> _runLinter_defaultLints() async {
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index 3cc6ebbd..4231d3c 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -2,26 +2,179 @@
// 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 analyzer_cli.test.mocks;
-
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_cli/src/options.dart';
-import 'package:mockito/mockito.dart';
-class MockAnalysisError extends Mock implements AnalysisError {}
+class MockAnalysisError implements AnalysisError {
+ @override
+ MockSource source;
-class MockAnalysisErrorInfo extends Mock implements AnalysisErrorInfo {}
+ @override
+ MockErrorCode errorCode;
-class MockCommandLineOptions extends Mock implements CommandLineOptions {}
+ @override
+ int offset;
-class MockErrorCode extends Mock implements ErrorCode {}
+ @override
+ String message;
-class MockErrorType extends Mock implements ErrorType {}
+ @override
+ bool isStaticOnly;
-class MockLineInfo extends Mock implements LineInfo {}
+ @override
+ int length;
-class MockLineInfo_Location extends Mock implements LineInfo_Location {}
+ MockAnalysisError(this.source, this.errorCode, this.offset, this.message);
-class MockSource extends Mock implements Source {}
+ @override
+ String get correction => null;
+}
+
+class MockAnalysisErrorInfo implements AnalysisErrorInfo {
+ @override
+ LineInfo lineInfo;
+
+ @override
+ List<AnalysisError> errors;
+
+ MockAnalysisErrorInfo(this.lineInfo, this.errors);
+}
+
+class MockCommandLineOptions implements CommandLineOptions {
+ bool enableTypeChecks = false;
+ bool infosAreFatal = false;
+ bool machineFormat = false;
+ bool verbose = false;
+ bool color = false;
+
+ noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
+
+class MockErrorCode implements ErrorCode {
+ @override
+ ErrorType type;
+
+ @override
+ ErrorSeverity errorSeverity;
+
+ @override
+ String name;
+
+ MockErrorCode(this.type, this.errorSeverity, this.name);
+
+ @override
+ String get correction {
+ throw new StateError('Unexpected invocation of correction');
+ }
+
+ @override
+ String get message {
+ throw new StateError('Unexpected invocation of message');
+ }
+
+ @override
+ String get uniqueName {
+ throw new StateError('Unexpected invocation of uniqueName');
+ }
+}
+
+class MockLineInfo implements LineInfo {
+ MockLineInfo_Location defaultLocation;
+
+ MockLineInfo({this.defaultLocation});
+
+ @override
+ int get lineCount {
+ throw new StateError('Unexpected invocation of lineCount');
+ }
+
+ @override
+ List<int> get lineStarts {
+ throw new StateError('Unexpected invocation of lineStarts');
+ }
+
+ @override
+ LineInfo_Location getLocation(int offset) {
+ if (defaultLocation != null) {
+ return defaultLocation;
+ }
+ throw new StateError('Unexpected invocation of getLocation');
+ }
+
+ @override
+ int getOffsetOfLine(int lineNumber) {
+ throw new StateError('Unexpected invocation of getOffsetOfLine');
+ }
+
+ @override
+ int getOffsetOfLineAfter(int offset) {
+ throw new StateError('Unexpected invocation of getOffsetOfLineAfter');
+ }
+}
+
+class MockLineInfo_Location implements LineInfo_Location {
+ @override
+ int lineNumber;
+
+ @override
+ int columnNumber;
+
+ MockLineInfo_Location(this.lineNumber, this.columnNumber);
+}
+
+class MockSource implements Source {
+ @override
+ String fullName;
+
+ MockSource(this.fullName);
+
+ @override
+ TimestampedData<String> get contents {
+ throw new StateError('Unexpected invocation of contents');
+ }
+
+ @override
+ String get encoding {
+ throw new StateError('Unexpected invocation of encoding');
+ }
+
+ @override
+ bool get isInSystemLibrary {
+ throw new StateError('Unexpected invocation of isInSystemLibrary');
+ }
+
+ @override
+ Source get librarySource {
+ throw new StateError('Unexpected invocation of librarySource');
+ }
+
+ @override
+ int get modificationStamp {
+ throw new StateError('Unexpected invocation of modificationStamp');
+ }
+
+ @override
+ String get shortName {
+ throw new StateError('Unexpected invocation of shortName');
+ }
+
+ @override
+ Source get source {
+ throw new StateError('Unexpected invocation of source');
+ }
+
+ @override
+ Uri get uri {
+ throw new StateError('Unexpected invocation of uri');
+ }
+
+ @override
+ UriKind get uriKind => null; //UriKind.FILE_URI;
+
+ @override
+ bool exists() {
+ throw new StateError('Unexpected invocation of exists');
+ }
+}
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index d5de24c..4f4bc85 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -2,14 +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.
-library analyzer_cli.test.formatter;
-
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer_cli/src/ansi.dart' as ansi;
import 'package:analyzer_cli/src/error_formatter.dart';
import 'package:test/test.dart' hide ErrorFormatter;
-import 'package:mockito/mockito.dart';
import 'mocks.dart';
@@ -27,11 +24,11 @@
stats = new AnalysisStats();
options = new MockCommandLineOptions();
- when(options.enableTypeChecks).thenReturn(false);
- when(options.infosAreFatal).thenReturn(false);
- when(options.machineFormat).thenReturn(false);
- when(options.verbose).thenReturn(false);
- when(options.color).thenReturn(false);
+ options.enableTypeChecks = false;
+ options.infosAreFatal = false;
+ options.machineFormat = false;
+ options.verbose = false;
+ options.color = false;
reporter = new HumanErrorFormatter(out, options, stats);
});
@@ -74,27 +71,13 @@
MockAnalysisErrorInfo mockError(ErrorType type, ErrorSeverity severity) {
// ErrorInfo
- var info = new MockAnalysisErrorInfo();
- var error = new MockAnalysisError();
- var lineInfo = new MockLineInfo();
- var location = new MockLineInfo_Location();
- when(location.columnNumber).thenReturn(3);
- when(location.lineNumber).thenReturn(3);
- when(lineInfo.getLocation(any)).thenReturn(location);
- when(info.lineInfo).thenReturn(lineInfo);
+ var location = new MockLineInfo_Location(3, 3);
+ var lineInfo = new MockLineInfo(defaultLocation: location);
// Details
- var code = new MockErrorCode();
- when(code.type).thenReturn(type);
- when(code.errorSeverity).thenReturn(severity);
- when(code.name).thenReturn('mock_code');
- when(error.errorCode).thenReturn(code);
- when(error.message).thenReturn('MSG');
- when(error.offset).thenReturn(20);
- var source = new MockSource();
- when(source.fullName).thenReturn('/foo/bar/baz.dart');
- when(error.source).thenReturn(source);
- when(info.errors).thenReturn([error]);
+ var code = new MockErrorCode(type, severity, 'mock_code');
+ var source = new MockSource('/foo/bar/baz.dart');
+ var error = new MockAnalysisError(source, code, 20, 'MSG');
- return info;
+ return new MockAnalysisErrorInfo(lineInfo, [error]);
}
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index a87463f..3fa21ce 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1782,7 +1782,7 @@
An enumeration of the kinds of refactorings that can be created.
</p>
- <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
+ <dl><dt class="value">CONVERT_GETTER_TO_METHOD</dt><dt class="value">CONVERT_METHOD_TO_GETTER</dt><dt class="value">EXTRACT_LOCAL_VARIABLE</dt><dt class="value">EXTRACT_METHOD</dt><dt class="value">EXTRACT_WIDGET</dt><dt class="value">INLINE_LOCAL_VARIABLE</dt><dt class="value">INLINE_METHOD</dt><dt class="value">MOVE_FILE</dt><dt class="value">RENAME</dt><dt class="value">SORT_MEMBERS</dt></dl></dd><dt class="typeDefinition"><a name="type_RefactoringMethodParameter">RefactoringMethodParameter: object</a></dt><dd>
<p>
A description of a parameter in a method refactoring.
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index fa6e4fc..ca795ae 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -4667,6 +4667,7 @@
* CONVERT_METHOD_TO_GETTER
* EXTRACT_LOCAL_VARIABLE
* EXTRACT_METHOD
+ * EXTRACT_WIDGET
* INLINE_LOCAL_VARIABLE
* INLINE_METHOD
* MOVE_FILE
@@ -4689,6 +4690,9 @@
static const RefactoringKind EXTRACT_METHOD =
const RefactoringKind._("EXTRACT_METHOD");
+ static const RefactoringKind EXTRACT_WIDGET =
+ const RefactoringKind._("EXTRACT_WIDGET");
+
static const RefactoringKind INLINE_LOCAL_VARIABLE =
const RefactoringKind._("INLINE_LOCAL_VARIABLE");
@@ -4710,6 +4714,7 @@
CONVERT_METHOD_TO_GETTER,
EXTRACT_LOCAL_VARIABLE,
EXTRACT_METHOD,
+ EXTRACT_WIDGET,
INLINE_LOCAL_VARIABLE,
INLINE_METHOD,
MOVE_FILE,
@@ -4732,6 +4737,8 @@
return EXTRACT_LOCAL_VARIABLE;
case "EXTRACT_METHOD":
return EXTRACT_METHOD;
+ case "EXTRACT_WIDGET":
+ return EXTRACT_WIDGET;
case "INLINE_LOCAL_VARIABLE":
return INLINE_LOCAL_VARIABLE;
case "INLINE_METHOD":
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 1f1320c..e0728a5 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -44,7 +44,7 @@
@override
Future<Null> addFileEdit(
String path, void buildFileEdit(DartFileEditBuilder builder)) =>
- super.addFileEdit(path, buildFileEdit);
+ super.addFileEdit(path, (builder) => buildFileEdit(builder));
@override
Future<DartFileEditBuilderImpl> createFileEditBuilder(String path) async {
@@ -76,7 +76,7 @@
@override
void addLinkedEdit(String groupName,
void buildLinkedEdit(DartLinkedEditBuilder builder)) =>
- super.addLinkedEdit(groupName, buildLinkedEdit);
+ super.addLinkedEdit(groupName, (builder) => buildLinkedEdit(builder));
@override
LinkedEditBuilderImpl createLinkedEditBuilder() {
@@ -182,17 +182,20 @@
bool typeRequired = true;
if (isConst) {
write(Keyword.CONST.lexeme);
+ write(' ');
typeRequired = false;
} else if (isFinal) {
write(Keyword.FINAL.lexeme);
+ write(' ');
typeRequired = false;
}
if (type != null) {
writeType(type, groupName: typeGroupName, required: true);
+ write(' ');
} else if (typeRequired) {
write(Keyword.VAR.lexeme);
+ write(' ');
}
- write(' ');
if (nameGroupName != null) {
addSimpleLinkedEdit(nameGroupName, name);
} else {
@@ -447,6 +450,24 @@
}
@override
+ void writeParameter(String name,
+ {StringBuffer displayTextBuffer,
+ ExecutableElement methodBeingCopied,
+ DartType type}) {
+ String parameterSource;
+ if (type != null) {
+ _EnclosingElementFinder finder = new _EnclosingElementFinder();
+ finder.find(dartFileEditBuilder.unit, offset);
+ parameterSource = _getTypeSource(
+ type, finder.enclosingClass, finder.enclosingExecutable,
+ parameterName: name, methodBeingCopied: methodBeingCopied);
+ } else {
+ parameterSource = name;
+ }
+ write(parameterSource, displayTextBuffer: displayTextBuffer);
+ }
+
+ @override
void writeParameterMatchingArgument(
Expression argument, int index, Set<String> usedNames) {
// append type name
@@ -494,9 +515,10 @@
}
}
// parameter
- writeParameterSource(parameter.type, parameter.name,
+ writeParameter(parameter.name,
+ displayTextBuffer: displayTextBuffer,
methodBeingCopied: methodBeingCopied,
- displayTextBuffer: displayTextBuffer);
+ type: parameter.type);
// default value
String defaultCode = parameter.defaultValueCode;
if (defaultCode != null) {
@@ -542,17 +564,6 @@
}
@override
- void writeParameterSource(DartType type, String name,
- {StringBuffer displayTextBuffer, ExecutableElement methodBeingCopied}) {
- _EnclosingElementFinder finder = new _EnclosingElementFinder();
- finder.find(dartFileEditBuilder.unit, offset);
- String parameterSource = _getTypeSource(
- type, finder.enclosingClass, finder.enclosingExecutable,
- parameterName: name, methodBeingCopied: methodBeingCopied);
- write(parameterSource, displayTextBuffer: displayTextBuffer);
- }
-
- @override
bool writeType(DartType type,
{bool addSupertypeProposals: false,
String groupName,
@@ -1149,12 +1160,12 @@
@override
void addInsertion(int offset, void buildEdit(DartEditBuilder builder)) =>
- super.addInsertion(offset, buildEdit);
+ super.addInsertion(offset, (builder) => buildEdit(builder));
@override
void addReplacement(
SourceRange range, void buildEdit(DartEditBuilder builder)) =>
- super.addReplacement(range, buildEdit);
+ super.addReplacement(range, (builder) => buildEdit(builder));
@override
void convertFunctionFromSyncToAsync(
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index a14dffc..c1165a1 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -176,6 +176,18 @@
{StringBuffer displayTextBuffer});
/**
+ * Write the code for a single parameter with the given [name].
+ *
+ * If a [methodBeingCopied] is provided, then type parameters defined by that
+ * method are assumed to be part of what is being written and hence valid
+ * types.
+ *
+ * If a [type] is provided, then it will be used as the type of the parameter.
+ */
+ void writeParameter(String name,
+ {ExecutableElement methodBeingCopied, DartType type});
+
+ /**
* Write the code for a parameter that would match the given [argument]. The
* name of the parameter will be generated based on the type of the argument,
* but if the argument type is not known the [index] will be used to compose
@@ -203,17 +215,6 @@
void writeParametersMatchingArguments(ArgumentList arguments);
/**
- * Write the code for a single parameter with the given [type] and [name].
- * The [type] can be `null` if no type is to be specified for the parameter.
- *
- * If a [methodBeingCopied] is provided, then type parameters defined by that
- * method are assumed to be part of what is being written and hence valid
- * types.
- */
- void writeParameterSource(DartType type, String name,
- {ExecutableElement methodBeingCopied});
-
- /**
* Write the code for a type annotation for the given [type]. If the [type] is
* either `null` or represents the type 'dynamic', then the behavior depends
* on whether a type is [required]. If [required] is `true`, then 'var' will
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 960bce1..31c0e6793 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -726,6 +726,7 @@
* CONVERT_METHOD_TO_GETTER
* EXTRACT_LOCAL_VARIABLE
* EXTRACT_METHOD
+ * EXTRACT_WIDGET
* INLINE_LOCAL_VARIABLE
* INLINE_METHOD
* MOVE_FILE
@@ -738,6 +739,7 @@
"CONVERT_METHOD_TO_GETTER",
"EXTRACT_LOCAL_VARIABLE",
"EXTRACT_METHOD",
+ "EXTRACT_WIDGET",
"INLINE_LOCAL_VARIABLE",
"INLINE_METHOD",
"MOVE_FILE",
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index e7ab4ef..4cc4c03 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -519,6 +519,23 @@
expect(edit.replacement, equalsIgnoringWhitespace('const f;'));
}
+ test_writeFieldDeclaration_isConst_type() async {
+ String path = provider.convertPath('/test.dart');
+ String content = 'class A {}';
+ addSource(path, content);
+ DartType typeA = await _getType(path, 'A');
+
+ DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+ await builder.addFileEdit(path, (FileEditBuilder builder) {
+ builder.addInsertion(content.length - 1, (EditBuilder builder) {
+ (builder as DartEditBuilder)
+ .writeFieldDeclaration('f', isConst: true, type: typeA);
+ });
+ });
+ SourceEdit edit = getEdit(builder);
+ expect(edit.replacement, equalsIgnoringWhitespace('const A f;'));
+ }
+
test_writeFieldDeclaration_isFinal() async {
String path = provider.convertPath('/test.dart');
String content = 'class A {}';
@@ -534,6 +551,23 @@
expect(edit.replacement, equalsIgnoringWhitespace('final f;'));
}
+ test_writeFieldDeclaration_isFinal_type() async {
+ String path = provider.convertPath('/test.dart');
+ String content = 'class A {}';
+ addSource(path, content);
+ DartType typeA = await _getType(path, 'A');
+
+ DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+ await builder.addFileEdit(path, (FileEditBuilder builder) {
+ builder.addInsertion(content.length - 1, (EditBuilder builder) {
+ (builder as DartEditBuilder)
+ .writeFieldDeclaration('f', isFinal: true, type: typeA);
+ });
+ });
+ SourceEdit edit = getEdit(builder);
+ expect(edit.replacement, equalsIgnoringWhitespace('final A f;'));
+ }
+
test_writeFieldDeclaration_isStatic() async {
String path = provider.convertPath('/test.dart');
String content = 'class A {}';
@@ -1308,6 +1342,37 @@
}
}
+ test_writeParameter() async {
+ String path = provider.convertPath('/test.dart');
+ String content = 'class A {}';
+ addSource(path, content);
+
+ DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+ await builder.addFileEdit(path, (FileEditBuilder builder) {
+ builder.addInsertion(content.length - 1, (EditBuilder builder) {
+ (builder as DartEditBuilder).writeParameter('a');
+ });
+ });
+ SourceEdit edit = getEdit(builder);
+ expect(edit.replacement, equalsIgnoringWhitespace('a'));
+ }
+
+ test_writeParameter_type() async {
+ String path = provider.convertPath('/test.dart');
+ String content = 'class A {}';
+ addSource(path, content);
+ DartType typeA = await _getType(path, 'A');
+
+ DartChangeBuilderImpl builder = new DartChangeBuilder(session);
+ await builder.addFileEdit(path, (FileEditBuilder builder) {
+ builder.addInsertion(content.length - 1, (EditBuilder builder) {
+ (builder as DartEditBuilder).writeParameter('a', type: typeA);
+ });
+ });
+ SourceEdit edit = getEdit(builder);
+ expect(edit.replacement, equalsIgnoringWhitespace('A a'));
+ }
+
test_writeParameterMatchingArgument() async {
String path = provider.convertPath('/test.dart');
String content = r'''
@@ -1445,22 +1510,6 @@
expect(edit.replacement, equalsIgnoringWhitespace('String s, int i'));
}
- test_writeParameterSource() async {
- String path = provider.convertPath('/test.dart');
- String content = 'class A {}';
- addSource(path, content);
- DartType typeA = await _getType(path, 'A');
-
- DartChangeBuilderImpl builder = new DartChangeBuilder(session);
- await builder.addFileEdit(path, (FileEditBuilder builder) {
- builder.addInsertion(content.length - 1, (EditBuilder builder) {
- (builder as DartEditBuilder).writeParameterSource(typeA, 'a');
- });
- });
- SourceEdit edit = getEdit(builder);
- expect(edit.replacement, equalsIgnoringWhitespace('A a'));
- }
-
test_writeType_dynamic() async {
String path = provider.convertPath('/test.dart');
String content = 'class A {}';
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 76f0995..3749755 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -1193,6 +1193,7 @@
<value><code>CONVERT_METHOD_TO_GETTER</code></value>
<value><code>EXTRACT_LOCAL_VARIABLE</code></value>
<value><code>EXTRACT_METHOD</code></value>
+ <value><code>EXTRACT_WIDGET</code></value>
<value><code>INLINE_LOCAL_VARIABLE</code></value>
<value><code>INLINE_METHOD</code></value>
<value><code>MOVE_FILE</code></value>
diff --git a/pkg/browser/LICENSE b/pkg/browser/LICENSE
deleted file mode 100644
index 5c60afe..0000000
--- a/pkg/browser/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright 2014, the Dart project authors. All rights reserved.
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the following
- disclaimer in the documentation and/or other materials provided
- with the distribution.
- * Neither the name of Google Inc. nor the names of its
- contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/browser/README.md b/pkg/browser/README.md
deleted file mode 100644
index fa96851..0000000
--- a/pkg/browser/README.md
+++ /dev/null
@@ -1,39 +0,0 @@
-This package contains dart.js, and previously contained interop.js
-
-dart.js
-=======
-
-The dart.js file is used in Dart browser apps to check for native Dart support
-and either (a) bootstrap Dartium or (b) load compiled JS instead. Previously,
-we've recommended that you add a script tag pointing the version of dart.js in
-our repository. This doesn't work offline and also results in slower startup
-(see [dartbug.com/6723](http://dartbug.com/6723)).
-
-Instead, we now recommend that you install dart.js via the following steps:
-
-1. Add the following to your pubspec.yaml:
- dependencies:
- browser: any
-
-2. Run pub install.
-
-3. Use a relative script tag in your html to the installed version:
-
- `<script src="packages/browser/dart.js"></script>`
-
-If you do not wish to use pub, you may host a copy of this file locally instead.
-In this case, you will need to update it yourself as necessary. We reserve the
-right to move the old file in the repository, so we no longer recommend linking
-to it directly.
-
-interop.js
-==========
-
-This script was required for dart:js interop to work, but it is no longer
-needed. The functionality is now supported by dart:js directly.
-
-If you previously had a script such as this, please remove it:
-
-```html
-<script src="packages/browser/interop.js"></script>
-```
diff --git a/pkg/browser/lib/dart.js b/pkg/browser/lib/dart.js
deleted file mode 100644
index b1f97b1..0000000
--- a/pkg/browser/lib/dart.js
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2013, 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.
-
-(function() {
-// Bootstrap support for Dart scripts on the page as this script.
-// TODO(18463): Remove user agent check. We will remove 'Dart' from there.
-if (!navigator.dartEnabled && (navigator.userAgent.indexOf('(Dart)') === -1)) {
- // TODO:
- // - Support in-browser compilation.
- // - Handle inline Dart scripts.
-
- // Fall back to compiled JS. Run through all the scripts and
- // replace them if they have a type that indicate that they source
- // in Dart code (type="application/dart").
- var scripts = document.getElementsByTagName("script");
- var length = scripts.length;
- for (var i = 0; i < length; ++i) {
- if (scripts[i].type == "application/dart") {
- // Remap foo.dart to foo.dart.js.
- if (scripts[i].src && scripts[i].src != '') {
- var script = document.createElement('script');
- script.src = scripts[i].src.replace(/\.dart(?=\?|$)/, '.dart.js');
- var parent = scripts[i].parentNode;
- // TODO(vsm): Find a solution for issue 8455 that works with more
- // than one script.
- document.currentScript = script;
- parent.replaceChild(script, scripts[i]);
-
- // Support for incremental compilation.
- script.onload = function (event) {
- var script = event.target;
- if (self.$dart_unsafe_incremental_support) {
- new WebSocket(script.src.replace(/^http/, 'ws')).onmessage =
- function (event) {
- var patch = String(event.data);
- self.$dart_unsafe_incremental_support.patch(patch);
- script.dispatchEvent(
- new CustomEvent(
- "dart_program_updated",
- { bubbles: true, detail: { patch: patch } }));
- };
- }
- };
- }
- }
- }
-}
-})();
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js
deleted file mode 100644
index ec02e58..0000000
--- a/pkg/browser/lib/interop.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2013, 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.
-
-// TODO(jmesserly): remove this script after a deprecation period.
-if (typeof console == "object" && typeof console.warn == "function") {
- console.warn('<script src="packages/browser/interop.js"> is no longer ' +
- 'needed for dart:js. See http://pub.dartlang.org/packages/browser.');
-}
diff --git a/pkg/browser/pubspec.yaml b/pkg/browser/pubspec.yaml
deleted file mode 100644
index af9396f..0000000
--- a/pkg/browser/pubspec.yaml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: browser
-version: 0.10.1
-author: "Dart Team <misc@dartlang.org>"
-homepage: http://www.dartlang.org
-description: >
- The bootstrap dart.js script for Dart apps running in the browser.
-environment:
- sdk: ">=1.3.0-dev.4.1 <2.0.0"
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index 99f7f7f..51ffa6b 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -3108,29 +3108,7 @@
MessageKind.MALFORMED_STRING_LITERAL,
r"A '$' has special meaning inside a string, and must be followed by "
"an identifier or an expression in curly braces ({}).",
- howToFix: r"Try adding a backslash (\) to escape the '$'.",
- examples: const [
- r"""
-main() {
- return '$';
-}
-""",
- r'''
-main() {
- return "$";
-}
-''',
- r"""
-main() {
- return '''$''';
-}
-""",
- r'''
-main() {
- return """$""";
-}
-'''
- ]),
+ howToFix: r"Try adding a backslash (\) to escape the '$'."),
MessageKind.UNTERMINATED_COMMENT: const MessageTemplate(
MessageKind.UNTERMINATED_COMMENT,
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index ae22161..0297bc2 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -279,6 +279,8 @@
/// Compute the source map name for [element]. If [callStructure] is non-null
/// it is used to name the parameter stub for [element].
+// TODO(johnniwinther): Merge this with `computeKernelElementNameForSourceMaps`
+// when the old frontend is removed.
String computeElementNameForSourceMaps(Entity element,
[CallStructure callStructure]) {
if (element is AstElement) {
diff --git a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
index 6670249..e2d67ea 100644
--- a/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
+++ b/pkg/compiler/lib/src/js_backend/field_naming_mixin.dart
@@ -207,10 +207,10 @@
@override
Map<Entity, jsAst.Name> get names => registry.globalNames;
- _MixinFieldNamingScope.mixin(ClassElement cls, _FieldNamingRegistry registry)
+ _MixinFieldNamingScope.mixin(ClassEntity cls, _FieldNamingRegistry registry)
: super.rootScope(cls, registry);
- _MixinFieldNamingScope.mixedIn(MixinApplicationElement container,
+ _MixinFieldNamingScope.mixedIn(ClassEntity container,
_FieldNamingScope superScope, _FieldNamingRegistry registry)
: super.inherit(container, superScope, registry);
diff --git a/pkg/compiler/lib/src/js_backend/minify_namer.dart b/pkg/compiler/lib/src/js_backend/minify_namer.dart
index 0554923..723bca7 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -316,37 +316,42 @@
/// constructors declared along the inheritance chain.
class _ConstructorBodyNamingScope {
final int _startIndex;
- final List _constructors;
-
+ final List<ConstructorEntity> _constructors;
int get numberOfConstructors => _constructors.length;
- _ConstructorBodyNamingScope.rootScope(ClassElement cls)
+ _ConstructorBodyNamingScope.rootScope(
+ ClassEntity cls, ElementEnvironment environment)
: _startIndex = 0,
- _constructors = cls.constructors.toList(growable: false);
+ _constructors = _getConstructorList(cls, environment);
- _ConstructorBodyNamingScope.forClass(
- ClassElement cls, _ConstructorBodyNamingScope superScope)
+ _ConstructorBodyNamingScope.forClass(ClassEntity cls,
+ _ConstructorBodyNamingScope superScope, ElementEnvironment environment)
: _startIndex = superScope._startIndex + superScope.numberOfConstructors,
- _constructors = cls.constructors.toList(growable: false);
+ _constructors = _getConstructorList(cls, environment);
// Mixin Applications have constructors but we never generate code for them,
// so they do not count in the inheritance chain.
_ConstructorBodyNamingScope.forMixinApplication(
- ClassElement cls, _ConstructorBodyNamingScope superScope)
+ ClassEntity cls, _ConstructorBodyNamingScope superScope)
: _startIndex = superScope._startIndex + superScope.numberOfConstructors,
_constructors = const [];
- factory _ConstructorBodyNamingScope(ClassElement cls,
- Map<ClassElement, _ConstructorBodyNamingScope> registry) {
+ factory _ConstructorBodyNamingScope(
+ ClassEntity cls,
+ Map<ClassEntity, _ConstructorBodyNamingScope> registry,
+ ElementEnvironment environment) {
return registry.putIfAbsent(cls, () {
- if (cls.superclass == null) {
- return new _ConstructorBodyNamingScope.rootScope(cls);
- } else if (cls.isMixinApplication) {
- return new _ConstructorBodyNamingScope.forMixinApplication(
- cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
+ ClassEntity superclass = environment.getSuperClass(cls);
+ if (superclass == null) {
+ return new _ConstructorBodyNamingScope.rootScope(cls, environment);
+ } else if (environment.isMixinApplication(cls)) {
+ return new _ConstructorBodyNamingScope.forMixinApplication(cls,
+ new _ConstructorBodyNamingScope(superclass, registry, environment));
} else {
return new _ConstructorBodyNamingScope.forClass(
- cls, new _ConstructorBodyNamingScope(cls.superclass, registry));
+ cls,
+ new _ConstructorBodyNamingScope(superclass, registry, environment),
+ environment);
}
});
}
@@ -356,16 +361,23 @@
assert(position >= 0, failedAt(body, "constructor body missing"));
return "@constructorBody@${_startIndex + position}";
}
+
+ static List<ConstructorEntity> _getConstructorList(
+ ClassEntity cls, ElementEnvironment environment) {
+ var result = <ConstructorEntity>[];
+ environment.forEachConstructor(cls, result.add);
+ return result;
+ }
}
abstract class _MinifyConstructorBodyNamer implements Namer {
- Map<ClassElement, _ConstructorBodyNamingScope> _constructorBodyScopes =
- new Map<ClassElement, _ConstructorBodyNamingScope>();
+ Map<ClassEntity, _ConstructorBodyNamingScope> _constructorBodyScopes =
+ new Map<ClassEntity, _ConstructorBodyNamingScope>();
@override
jsAst.Name constructorBodyName(ConstructorBodyEntity method) {
_ConstructorBodyNamingScope scope = new _ConstructorBodyNamingScope(
- method.enclosingClass, _constructorBodyScopes);
+ method.enclosingClass, _constructorBodyScopes, elementEnvironment);
String key = scope.constructorBodyKeyFor(method);
return _disambiguateMemberByKey(
key, () => _proposeNameForConstructorBody(method));
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0dab60a..3a02f42 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -15,13 +15,7 @@
import '../constants/values.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../diagnostics/invariant.dart' show DEBUG_MODE;
-import '../elements/elements.dart'
- show
- ClassElement,
- Element,
- Elements,
- MemberElement,
- MixinApplicationElement;
+import '../elements/elements.dart' show Element, Elements, MemberElement;
import '../elements/entities.dart';
import '../elements/entity_utils.dart' as utils;
import '../elements/jumps.dart';
@@ -578,7 +572,7 @@
_literalLazyGetterPrefix = new StringBackedName(lazyGetterPrefix);
}
- ElementEnvironment get _elementEnvironment => _closedWorld.elementEnvironment;
+ ElementEnvironment get elementEnvironment => _closedWorld.elementEnvironment;
CommonElements get _commonElements => _closedWorld.commonElements;
@@ -983,10 +977,10 @@
bool isPrivate = Name.isPrivateName(fieldName);
LibraryEntity memberLibrary = element.library;
ClassEntity lookupClass =
- _elementEnvironment.getSuperClass(element.enclosingClass);
+ elementEnvironment.getSuperClass(element.enclosingClass);
while (lookupClass != null) {
MemberEntity foundMember =
- _elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
+ elementEnvironment.lookupLocalClassMember(lookupClass, fieldName);
if (foundMember != null) {
if (foundMember.isField) {
if (!isPrivate || memberLibrary == foundMember.library) {
@@ -996,7 +990,7 @@
}
}
}
- lookupClass = _elementEnvironment.getSuperClass(lookupClass);
+ lookupClass = elementEnvironment.getSuperClass(lookupClass);
}
return false;
}
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index 9b357d1..b655b94 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -1684,13 +1684,26 @@
ClassFunctionType _computeFunctionType(
ElementEnvironment _elementEnvironment, ClassEntity cls,
{bool strongMode}) {
- if (strongMode && !cls.isClosure) return null;
+ FunctionEntity signatureFunction;
+ if (cls.isClosure) {
+ // Use signature function if available.
+ signatureFunction =
+ _elementEnvironment.lookupLocalClassMember(cls, Identifiers.signature);
+ if (signatureFunction == null && strongMode) {
+ // In Dart 2, a closure only needs its function type if it has a
+ // signature function.
+ return null;
+ }
+ } else if (strongMode) {
+ // Only closures have function type in Dart 2.
+ return null;
+ }
MemberEntity call =
_elementEnvironment.lookupLocalClassMember(cls, Identifiers.call);
if (call != null && call.isFunction) {
FunctionEntity callFunction = call;
FunctionType callType = _elementEnvironment.getFunctionType(callFunction);
- return new ClassFunctionType(callFunction, callType);
+ return new ClassFunctionType(callFunction, callType, signatureFunction);
}
return null;
}
@@ -2340,12 +2353,17 @@
/// a class.
class ClassFunctionType {
/// The `call` function that defines the function type.
- final MemberEntity callFunction;
+ final FunctionEntity callFunction;
/// The type of the `call` function.
final FunctionType callType;
- ClassFunctionType(this.callFunction, this.callType);
+ /// The signature function for the function type.
+ ///
+ /// This is used for Dart 2.
+ final FunctionEntity signatureFunction;
+
+ ClassFunctionType(this.callFunction, this.callType, this.signatureFunction);
}
/// Runtime type usage for a class.
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 7bc40d2..525d31b 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
@@ -678,7 +678,6 @@
_task.emitter, _commonElements, _namer, _worldBuilder, _closedWorld,
enableMinification: _options.enableMinification);
RuntimeTypeGenerator runtimeTypeGenerator = new RuntimeTypeGenerator(
- _elementEnvironment,
_commonElements,
_closureDataLookup,
_outputUnitData,
@@ -688,8 +687,7 @@
_rtiEncoder,
_jsInteropAnalysis,
_options.useKernel,
- _options.strongMode,
- _options.disableRtiOptimization);
+ _options.strongMode);
void visitMember(MemberEntity member) {
if (member.isInstanceMember && !member.isAbstract && !member.isField) {
diff --git a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
index e856ec6..a277091 100644
--- a/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart
@@ -11,8 +11,7 @@
ClosureConversionTask,
ScopeInfo;
import '../common.dart';
-import '../common/names.dart' show Identifiers;
-import '../common_elements.dart' show CommonElements, ElementEnvironment;
+import '../common_elements.dart' show CommonElements;
import '../deferred_load.dart' show OutputUnit, OutputUnitData;
import '../elements/elements.dart' show ClassElement, MethodElement;
import '../elements/entities.dart';
@@ -24,6 +23,7 @@
import '../js_backend/runtime_types.dart'
show
ClassChecks,
+ ClassFunctionType,
RuntimeTypesChecks,
RuntimeTypesEncoder,
Substitution,
@@ -35,8 +35,7 @@
import 'code_emitter_task.dart' show CodeEmitterTask;
// Function signatures used in the generation of runtime type information.
-typedef void FunctionTypeSignatureEmitter(
- FunctionEntity method, FunctionType methodType);
+typedef void FunctionTypeSignatureEmitter(ClassFunctionType classFunctionType);
class TypeTest {
final jsAst.Name name;
@@ -99,7 +98,6 @@
}
class RuntimeTypeGenerator {
- final ElementEnvironment _elementEnvironment;
final CommonElements _commonElements;
final ClosureConversionTask _closureDataLookup;
final OutputUnitData _outputUnitData;
@@ -109,15 +107,9 @@
final RuntimeTypesEncoder _rtiEncoder;
final JsInteropAnalysis _jsInteropAnalysis;
final bool _useKernel;
-
- /// ignore: UNUSED_FIELD
final bool _strongMode;
- /// ignore: UNUSED_FIELD
- final bool _disableRtiOptimization;
-
RuntimeTypeGenerator(
- this._elementEnvironment,
this._commonElements,
this._closureDataLookup,
this._outputUnitData,
@@ -127,8 +119,15 @@
this._rtiEncoder,
this._jsInteropAnalysis,
this._useKernel,
- this._strongMode,
- this._disableRtiOptimization);
+ this._strongMode);
+
+ /**
+ * Generate "is tests" for [cls] itself, and the "is tests" for the
+ * classes it implements and type argument substitution functions for these
+ * tests. We don't need to add the "is tests" of the super class because
+ * they will be inherited at runtime, but we may need to generate the
+ * substitutions, because they may have changed.
+ */
/// Generates all properties necessary for is-checks on the [classElement].
///
@@ -149,49 +148,54 @@
failedAt(classElement));
// TODO(johnniwinther): Include function signatures in [ClassChecks].
- void generateFunctionTypeSignature(
- FunctionEntity method, FunctionType type) {
+ void generateFunctionTypeSignature(ClassFunctionType classFunctionType) {
+ FunctionEntity method = classFunctionType.callFunction;
+ FunctionType type = classFunctionType.callType;
assert(!(method is MethodElement && !method.isImplementation));
- jsAst.Expression thisAccess = new jsAst.This();
- if (method.enclosingClass.isClosure) {
- ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(method);
- if (scopeInfo is ClosureRepresentationInfo) {
- FieldEntity thisLocal = scopeInfo.thisFieldEntity;
- if (thisLocal != null) {
- assert(
- thisLocal is ClosureFieldElement || thisLocal is JClosureField);
- jsAst.Name thisName = _namer.instanceFieldPropertyName(thisLocal);
- thisAccess = js('this.#', thisName);
- }
- }
- }
// TODO(johnniwinther): Avoid unneeded function type indices or
// signatures. We either need them for mirrors or because [type] is
// potentially a subtype of a checked function. Currently we eagerly
// generate a function type index or signature for all callable classes.
if (storeFunctionTypeInMetadata && !type.containsTypeVariables) {
+ // TODO(johnniwinther,efortuna): Should we use the scheme for Dart 2?
// TODO(sigmund): use output unit of `method` (Issue #31032)
OutputUnit outputUnit = _outputUnitData.mainOutputUnit;
result.functionTypeIndex =
emitterTask.metadataCollector.reifyType(type, outputUnit);
} else {
- jsAst.Expression encoding;
- MemberEntity signature = _elementEnvironment.lookupLocalClassMember(
- method.enclosingClass, Identifiers.signature);
- if (_useKernel &&
- signature != null &&
- generatedCode[signature] != null) {
- // Use precomputed signature function.
- encoding = generatedCode[signature];
+ jsAst.Expression encoding =
+ generatedCode[classFunctionType.signatureFunction];
+ if (classFunctionType.signatureFunction != null) {
+ // Use precomputed signature function if live.
} else {
- // TODO(efortuna): Reinsert assertion.
- // Generate the signature on the fly.
+ assert(!_useKernel || !_strongMode);
+ // Generate the signature on the fly. This is only supported for
+ // Dart 1.
+
+ jsAst.Expression thisAccess = new jsAst.This();
+ if (method.enclosingClass.isClosure) {
+ ScopeInfo scopeInfo = _closureDataLookup.getScopeInfo(method);
+ if (scopeInfo is ClosureRepresentationInfo) {
+ FieldEntity thisLocal = scopeInfo.thisFieldEntity;
+ if (thisLocal != null) {
+ assert(thisLocal is ClosureFieldElement ||
+ thisLocal is JClosureField);
+ jsAst.Name thisName =
+ _namer.instanceFieldPropertyName(thisLocal);
+ thisAccess = js('this.#', thisName);
+ }
+ }
+ }
+
encoding = _rtiEncoder.getSignatureEncoding(
emitterTask.emitter, type, thisAccess);
}
- jsAst.Name operatorSignature = _namer.asName(_namer.operatorSignature);
- result.addSignature(classElement, operatorSignature, encoding);
+ if (encoding != null) {
+ jsAst.Name operatorSignature =
+ _namer.asName(_namer.operatorSignature);
+ result.addSignature(classElement, operatorSignature, encoding);
+ }
}
}
@@ -226,13 +230,6 @@
return result;
}
- /**
- * Generate "is tests" for [cls] itself, and the "is tests" for the
- * classes it implements and type argument substitution functions for these
- * tests. We don't need to add the "is tests" of the super class because
- * they will be inherited at runtime, but we may need to generate the
- * substitutions, because they may have changed.
- */
void _generateIsTestsOn(
ClassEntity cls,
FunctionTypeSignatureEmitter generateFunctionTypeSignature,
@@ -252,8 +249,7 @@
}
if (classChecks.functionType != null) {
- generateFunctionTypeSignature(classChecks.functionType.callFunction,
- classChecks.functionType.callType);
+ generateFunctionTypeSignature(classChecks.functionType);
}
}
}
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index ba98796..f7ab997a 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -14,38 +14,13 @@
/// A kernel [Target] to configure the Dart Front End for dart2js.
class Dart2jsTarget extends Target {
final TargetFlags flags;
+ final String name;
- Dart2jsTarget(this.flags);
+ Dart2jsTarget(this.name, this.flags);
bool get strongMode => flags.strongMode;
- String get name => 'dart2js';
-
- List<String> get extraRequiredLibraries => const <String>[
- 'dart:_chrome',
- 'dart:_foreign_helper',
- 'dart:_interceptors',
- 'dart:_internal',
- 'dart:_isolate_helper',
- 'dart:_js_embedded_names',
- 'dart:_js_helper',
- 'dart:_js_mirrors',
- 'dart:_js_names',
- 'dart:_native_typed_data',
- 'dart:async',
- 'dart:collection',
- 'dart:html',
- 'dart:html_common',
- 'dart:indexed_db',
- 'dart:io',
- 'dart:js',
- 'dart:js_util',
- 'dart:mirrors',
- 'dart:svg',
- 'dart:web_audio',
- 'dart:web_gl',
- 'dart:web_sql',
- ];
+ List<String> get extraRequiredLibraries => _requiredLibraries[name];
@override
bool mayDefineRestrictedType(Uri uri) =>
@@ -96,3 +71,50 @@
return new InvalidExpression(null);
}
}
+
+// TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
+// compile-platform should just specify which libraries to compile instead.
+const _requiredLibraries = const <String, List<String>>{
+ 'dart2js': const <String>[
+ 'dart:_chrome',
+ 'dart:_foreign_helper',
+ 'dart:_interceptors',
+ 'dart:_internal',
+ 'dart:_isolate_helper',
+ 'dart:_js_embedded_names',
+ 'dart:_js_helper',
+ 'dart:_js_mirrors',
+ 'dart:_js_names',
+ 'dart:_native_typed_data',
+ 'dart:async',
+ 'dart:collection',
+ 'dart:html',
+ 'dart:html_common',
+ 'dart:indexed_db',
+ 'dart:io',
+ 'dart:js',
+ 'dart:js_util',
+ 'dart:mirrors',
+ 'dart:svg',
+ 'dart:web_audio',
+ 'dart:web_gl',
+ 'dart:web_sql',
+ ],
+ 'dart2js_server': const <String>[
+ 'dart:_foreign_helper',
+ 'dart:_interceptors',
+ 'dart:_internal',
+ 'dart:_isolate_helper',
+ 'dart:_js_embedded_names',
+ 'dart:_js_helper',
+ 'dart:_js_mirrors',
+ 'dart:_js_names',
+ 'dart:_native_typed_data',
+ 'dart:async',
+ 'dart:collection',
+ 'dart:io',
+ 'dart:js',
+ 'dart:js_util',
+ 'dart:mirrors',
+ ]
+};
diff --git a/pkg/compiler/lib/src/kernel/kernel_strategy.dart b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
index f58417e..8106841 100644
--- a/pkg/compiler/lib/src/kernel/kernel_strategy.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_strategy.dart
@@ -83,8 +83,14 @@
env.Environment environment,
DiagnosticReporter reporter,
Measurer measurer) {
- return new KernelLibraryLoaderTask(_options.platformBinaries,
- _options.packageConfig, _elementMap, compilerInput, reporter, measurer,
+ return new KernelLibraryLoaderTask(
+ _options.librariesSpecificationUri,
+ _options.platformBinaries,
+ _options.packageConfig,
+ _elementMap,
+ compilerInput,
+ reporter,
+ measurer,
verbose: _options.verbose,
initializedCompilerState: initializedCompilerState);
}
diff --git a/pkg/compiler/lib/src/library_loader.dart b/pkg/compiler/lib/src/library_loader.dart
index e6e2ea8..33ca393 100644
--- a/pkg/compiler/lib/src/library_loader.dart
+++ b/pkg/compiler/lib/src/library_loader.dart
@@ -202,7 +202,8 @@
"math": "_internal/js_runtime/lib/math_patch.dart",
"mirrors": "_internal/js_runtime/lib/mirrors_patch.dart",
"typed_data": "_internal/js_runtime/lib/typed_data_patch.dart",
- "_internal": "_internal/js_runtime/lib/internal_patch.dart"
+ "_internal": "_internal/js_runtime/lib/internal_patch.dart",
+ "_js": "js/_js_client.dart",
};
/// Returns the location of the patch-file associated with [libraryName]
@@ -823,6 +824,7 @@
// TODO(sigmund): move this class to a new file under src/kernel/.
class KernelLibraryLoaderTask extends CompilerTask
implements LibraryLoaderTask {
+ final Uri librariesSpecification;
final Uri platformBinaries;
final Uri _packageConfig;
@@ -840,9 +842,16 @@
fe.InitializedCompilerState initializedCompilerState;
- KernelLibraryLoaderTask(this.platformBinaries, this._packageConfig,
- this._elementMap, this.compilerInput, this.reporter, Measurer measurer,
- {this.verbose: false, this.initializedCompilerState})
+ KernelLibraryLoaderTask(
+ this.librariesSpecification,
+ this.platformBinaries,
+ this._packageConfig,
+ this._elementMap,
+ this.compilerInput,
+ this.reporter,
+ Measurer measurer,
+ {this.verbose: false,
+ this.initializedCompilerState})
: _allLoadedLibraries = new List<LibraryEntity>(),
super(measurer);
@@ -862,12 +871,16 @@
new BinaryBuilder(input.data).readComponent(component);
} else {
bool strongMode = _elementMap.options.strongMode;
+ String targetName =
+ _elementMap.options.compileForServer ? "dart2js_server" : "dart2js";
String platform = strongMode
- ? 'dart2js_platform_strong.dill'
- : 'dart2js_platform.dill';
+ ? '${targetName}_platform_strong.dill'
+ : '${targetName}_platform.dill';
initializedCompilerState = fe.initializeCompiler(
initializedCompilerState,
- new Dart2jsTarget(new TargetFlags(strongMode: strongMode)),
+ new Dart2jsTarget(
+ targetName, new TargetFlags(strongMode: strongMode)),
+ librariesSpecification,
platformBinaries.resolve(platform),
_packageConfig);
component = await fe.compile(
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index ec4b54c..c42e066 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -100,6 +100,10 @@
/// and in the emitted output of the compiler.
bool get hasBuildId => buildId != _UNDETERMINED_BUILD_ID;
+ /// Whether to compile for the server category. This is used to compile to JS
+ /// that is intended to be run on server-side VMs like nodejs.
+ final bool compileForServer;
+
/// Location where to generate a map containing details of how deferred
/// libraries are subdivided.
final Uri deferredMapUri;
@@ -177,8 +181,12 @@
final Uri outputUri;
/// Location of the platform configuration file.
+ // TODO(sigmund): deprecate and remove, use only [librariesSpecificationUri]
final Uri platformConfigUri;
+ /// Location of the libraries specification file.
+ final Uri librariesSpecificationUri;
+
/// Location of the kernel platform `.dill` files.
final Uri platformBinaries;
@@ -305,6 +313,7 @@
analyzeSignaturesOnly: _hasOption(options, Flags.analyzeSignaturesOnly),
buildId: _extractStringOption(
options, '--build-id=', _UNDETERMINED_BUILD_ID),
+ compileForServer: _resolveCompileForServerFromOptions(options),
deferredMapUri: _extractUriOption(options, '--deferred-map='),
fatalWarnings: _hasOption(options, Flags.fatalWarnings),
terseDiagnostics: _hasOption(options, Flags.terse),
@@ -336,6 +345,7 @@
outputUri: _extractUriOption(options, '--out='),
platformConfigUri:
_resolvePlatformConfigFromOptions(libraryRoot, options),
+ librariesSpecificationUri: _resolveLibrariesSpecification(libraryRoot),
platformBinaries: platformBinaries ??
_extractUriOption(options, '--platform-binaries='),
preserveComments: _hasOption(options, Flags.preserveComments),
@@ -382,6 +392,7 @@
bool analyzeOnly: false,
bool analyzeSignaturesOnly: false,
String buildId: _UNDETERMINED_BUILD_ID,
+ bool compileForServer: false,
Uri deferredMapUri: null,
bool fatalWarnings: false,
bool terseDiagnostics: false,
@@ -406,6 +417,7 @@
bool kernelGlobalInference: false,
Uri outputUri: null,
Uri platformConfigUri: null,
+ Uri librariesSpecificationUri: null,
Uri platformBinaries: null,
bool preserveComments: false,
bool preserveUris: false,
@@ -463,6 +475,7 @@
analyzeOnly || analyzeSignaturesOnly || analyzeAll || resolveOnly,
analyzeSignaturesOnly: analyzeSignaturesOnly,
buildId: buildId,
+ compileForServer: compileForServer,
deferredMapUri: deferredMapUri,
fatalWarnings: fatalWarnings,
terseDiagnostics: terseDiagnostics,
@@ -488,6 +501,7 @@
outputUri: outputUri,
platformConfigUri: platformConfigUri ??
_resolvePlatformConfig(libraryRoot, null, const []),
+ librariesSpecificationUri: _resolveLibrariesSpecification(libraryRoot),
platformBinaries: platformBinaries,
preserveComments: preserveComments,
preserveUris: preserveUris,
@@ -520,6 +534,7 @@
this.analyzeOnly: false,
this.analyzeSignaturesOnly: false,
this.buildId: _UNDETERMINED_BUILD_ID,
+ this.compileForServer: false,
this.deferredMapUri: null,
this.fatalWarnings: false,
this.terseDiagnostics: false,
@@ -543,6 +558,7 @@
this.generateSourceMap: true,
this.outputUri: null,
this.platformConfigUri: null,
+ this.librariesSpecificationUri: null,
this.platformBinaries: null,
this.preserveComments: false,
this.preserveUris: false,
@@ -583,6 +599,7 @@
analyzeOnly,
analyzeSignaturesOnly,
buildId,
+ compileForServer,
deferredMapUri,
fatalWarnings,
terseDiagnostics,
@@ -607,6 +624,7 @@
kernelGlobalInference,
outputUri,
platformConfigUri,
+ librariesSpecificationUri,
platformBinaries,
preserveComments,
preserveUris,
@@ -645,6 +663,7 @@
analyzeSignaturesOnly:
analyzeSignaturesOnly ?? options.analyzeSignaturesOnly,
buildId: buildId ?? options.buildId,
+ compileForServer: compileForServer ?? options.compileForServer,
deferredMapUri: deferredMapUri ?? options.deferredMapUri,
fatalWarnings: fatalWarnings ?? options.fatalWarnings,
terseDiagnostics: terseDiagnostics ?? options.terseDiagnostics,
@@ -678,6 +697,8 @@
generateSourceMap: generateSourceMap ?? options.generateSourceMap,
outputUri: outputUri ?? options.outputUri,
platformConfigUri: platformConfigUri ?? options.platformConfigUri,
+ librariesSpecificationUri:
+ librariesSpecificationUri ?? options.librariesSpecificationUri,
platformBinaries: platformBinaries ?? options.platformBinaries,
preserveComments: preserveComments ?? options.preserveComments,
preserveUris: preserveUris ?? options.preserveUris,
@@ -790,6 +811,11 @@
}
}
+bool _resolveCompileForServerFromOptions(List<String> options) {
+ var categories = _extractCsvOption(options, '--categories=');
+ return categories.length == 1 && categories.single == 'Server';
+}
+
Uri _resolvePlatformConfigFromOptions(Uri libraryRoot, List<String> options) {
return _resolvePlatformConfig(
libraryRoot,
@@ -797,6 +823,9 @@
_extractCsvOption(options, '--categories='));
}
+Uri _resolveLibrariesSpecification(Uri libraryRoot) =>
+ libraryRoot.resolve('lib/libraries.json');
+
/// Locations of the platform descriptor files relative to the library root.
const String _clientPlatform = "lib/dart_client.platform";
const String _serverPlatform = "lib/dart_server.platform";
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
index 0658333..3f77774 100644
--- a/pkg/compiler/lib/src/parser/element_listener.dart
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -350,13 +350,26 @@
}
@override
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {
+ if (abstractToken == null) {
+ pushNode(Modifiers.EMPTY);
+ } else {
+ Link<Node> poppedNodes = const Link<Node>();
+ poppedNodes = poppedNodes.prepend(new Identifier(abstractToken));
+ NodeList modifierNodes = new NodeList(null, poppedNodes, null, ' ');
+ pushNode(new Modifiers(modifierNodes));
+ }
+ }
+
+ @override
void endNamedMixinApplication(Token beginToken, Token classKeyword,
Token equals, Token implementsKeyword, Token endToken) {
NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
MixinApplication mixinApplication = popNode();
+ Modifiers modifiers = popNode();
NodeList typeParameters = popNode();
Identifier name = popNode();
- Modifiers modifiers = popNode();
NamedMixinApplication namedMixinApplication = new NamedMixinApplication(
name,
typeParameters,
@@ -412,7 +425,8 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
bool hasParseError = currentMemberHasParseError;
memberErrors = memberErrors.tail;
void buildFieldElement(Identifier name, VariableList fields) {
@@ -421,11 +435,30 @@
NodeList variables = makeNodeList(count, null, null, ",");
popNode(); // type
- Modifiers modifiers = popNode();
+ Modifiers modifiers =
+ newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
buildFieldElements(modifiers, variables, compilationUnitElement,
buildFieldElement, beginToken, endToken, hasParseError);
}
+ Modifiers newFieldModifiers(
+ Token staticToken, Token covariantToken, Token varFinalOrConst) {
+ Link<Node> modifierNodes = const Link<Node>();
+ if (varFinalOrConst != null) {
+ modifierNodes = modifierNodes.prepend(new Identifier(varFinalOrConst));
+ }
+ if (covariantToken != null) {
+ modifierNodes = modifierNodes.prepend(new Identifier(covariantToken));
+ }
+ if (staticToken != null) {
+ modifierNodes = modifierNodes.prepend(new Identifier(staticToken));
+ }
+ if (!modifierNodes.isNotEmpty) {
+ return Modifiers.EMPTY;
+ }
+ return new Modifiers(new NodeList(null, modifierNodes, null, ' '));
+ }
+
@override
void handleInvalidTopLevelDeclaration(Token endToken) {
memberErrors = memberErrors.tail;
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
index 7846f70..3d1ed39 100644
--- a/pkg/compiler/lib/src/parser/member_listener.dart
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -117,9 +117,11 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
bool hasParseError = memberErrors.head;
- super.endFields(count, beginToken, endToken);
+ super.endFields(staticToken, covariantToken, varFinalOrConst, count,
+ beginToken, endToken);
VariableDefinitions variableDefinitions = popNode();
Modifiers modifiers = variableDefinitions.modifiers;
pushNode(null);
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 54d308e..bb0925d 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -122,14 +122,26 @@
}
@override
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+ if (abstractToken == null) {
+ pushNode(Modifiers.EMPTY);
+ } else {
+ Link<Node> poppedNodes = const Link<Node>();
+ poppedNodes = poppedNodes.prepend(new Identifier(abstractToken));
+ NodeList modifierNodes = new NodeList(null, poppedNodes, null, ' ');
+ pushNode(new Modifiers(modifierNodes));
+ }
+ }
+
+ @override
void endClassDeclaration(Token beginToken, Token endToken) {
NodeList body = popNode();
NodeList interfaces = popNode();
TokenNode extendsNode = popNode();
Node supertype = popNode();
+ Modifiers modifiers = popNode();
NodeList typeParameters = popNode();
Identifier name = popNode();
- Modifiers modifiers = popNode();
// TODO(danrubel): can we remove the extends keyword from ClassNode ?
pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
interfaces, beginToken, extendsNode.token, body, endToken));
@@ -216,9 +228,9 @@
Token equals, Token implementsKeyword, Token endToken) {
NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
Node mixinApplication = popNode();
+ Modifiers modifiers = popNode();
NodeList typeParameters = popNode();
Identifier name = popNode();
- Modifiers modifiers = popNode();
pushNode(new NamedMixinApplication(name, typeParameters, modifiers,
mixinApplication, interfaces, beginToken, endToken));
}
@@ -238,10 +250,12 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
NodeList variables = makeNodeList(count, null, endToken, ",");
TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
+ Modifiers modifiers =
+ newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
pushNode(new VariableDefinitions(type, modifiers, variables));
}
@@ -567,6 +581,7 @@
TypeAnnotation type = popNode();
Modifiers modifiers = new Modifiers(new NodeList.empty());
NodeList typeVariables = popNode();
+ popNode(); // Metadata.
pushNode(new FunctionDeclaration(new FunctionExpression(name, typeVariables,
formals, body, type, modifiers, initializers, null, asyncModifier)));
}
@@ -751,10 +766,12 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
NodeList variables = makeNodeList(count, null, endToken, ",");
TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
+ Modifiers modifiers =
+ newFieldModifiers(staticToken, covariantToken, varFinalOrConst);
pushNode(new VariableDefinitions(type, modifiers, variables));
}
diff --git a/pkg/compiler/tool/generate_kernel.dart b/pkg/compiler/tool/generate_kernel.dart
index a649997..1ccdd8b 100644
--- a/pkg/compiler/tool/generate_kernel.dart
+++ b/pkg/compiler/tool/generate_kernel.dart
@@ -23,7 +23,7 @@
main(List<String> args) async {
ArgResults flags = _argParser.parse(args);
var options = new CompilerOptions()
- ..target = new Dart2jsTarget(new TargetFlags())
+ ..target = new Dart2jsTarget("dart2js", new TargetFlags())
..packagesFileUri = Uri.base.resolve('.packages')
..setExitCodeOnProblem = true
..linkedDependencies = [
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 3e7dd29..048f13f 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -1219,6 +1219,7 @@
/// Does *not* clear digits below ds.
static void _lsh(
Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+ assert(xUsed > 0);
final digitShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -1248,6 +1249,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -1283,6 +1285,7 @@
// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
static void _rsh(
Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+ assert(xUsed > 0);
final digitsShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -1310,6 +1313,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -1552,6 +1556,7 @@
*/
_BigIntImpl operator &(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -1591,6 +1596,8 @@
*/
_BigIntImpl operator |(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -1631,6 +1638,8 @@
*/
_BigIntImpl operator ^(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1665,6 +1674,7 @@
* This maps any integer `x` to `-x - 1`.
*/
_BigIntImpl operator ~() {
+ if (_isZero) return _minusOne;
if (_isNegative) {
// ~(-this) == ~(~(this-1)) == this-1
return _absSubSetSign(one, false);
@@ -1677,6 +1687,8 @@
/// Addition operator.
_BigIntImpl operator +(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative == other._isNegative) {
// this + other == this + other
@@ -1694,6 +1706,8 @@
/// Subtraction operator.
_BigIntImpl operator -(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return -other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative != other._isNegative) {
// this - (-other) == this + other
diff --git a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
index 460e203..c60a782 100644
--- a/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
+++ b/pkg/front_end/lib/src/api_prototype/incremental_kernel_generator.dart
@@ -22,8 +22,9 @@
bootstrapDill);
}
- /// Returns a component whose libraries are the recompiled libraries.
- Future<Component> computeDelta({Uri entryPoint});
+ /// Returns a component whose libraries are the recompiled libraries,
+ /// or - in the case of [fullComponent] - a full Component.
+ Future<Component> computeDelta({Uri entryPoint, bool fullComponent});
/// Remove the file associated with the given file [uri] from the set of
/// valid files. This guarantees that those files will be re-read on the
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index c8151c0..666f32d 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -27,18 +27,24 @@
export 'compiler_state.dart' show InitializedCompilerState;
-InitializedCompilerState initializeCompiler(InitializedCompilerState oldState,
- Target target, Uri sdkUri, Uri packagesFileUri) {
+InitializedCompilerState initializeCompiler(
+ InitializedCompilerState oldState,
+ Target target,
+ Uri librariesSpecificationUri,
+ Uri sdkPlatformUri,
+ Uri packagesFileUri) {
if (oldState != null &&
oldState.options.packagesFileUri == packagesFileUri &&
- oldState.options.linkedDependencies[0] == sdkUri) {
+ oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
+ oldState.options.linkedDependencies[0] == sdkPlatformUri) {
return oldState;
}
CompilerOptions options = new CompilerOptions()
..target = target
..strongMode = target.strongMode
- ..linkedDependencies = [sdkUri]
+ ..linkedDependencies = [sdkPlatformUri]
+ ..librariesSpecificationUri = librariesSpecificationUri
..packagesFileUri = packagesFileUri;
ProcessedOptions processedOpts = new ProcessedOptions(options, false, []);
diff --git a/pkg/front_end/lib/src/base/libraries_specification.dart b/pkg/front_end/lib/src/base/libraries_specification.dart
index 3c1dcfb..28c95fe 100644
--- a/pkg/front_end/lib/src/base/libraries_specification.dart
+++ b/pkg/front_end/lib/src/base/libraries_specification.dart
@@ -30,6 +30,12 @@
/// "convert": {
/// "uri": "convert/convert.dart",
/// }
+/// "mirrors": {
+/// "uri": "mirrors/mirrors.dart",
+/// }
+/// }
+/// "environment_overrides": {
+/// "mirrors": false
/// }
/// }
/// }
@@ -38,9 +44,8 @@
/// - a top level entry for each target. Keys are target names (e.g. "vm"
/// above), and values contain the entire specification of a target.
///
-/// - each target specification is a map. Today only one key ("libraries") is
-/// supported, but this may be extended in the future to add more
-/// information on each target.
+/// - each target specification is a map. Today two keys are supported:
+/// "libraries" and "environment_overrides".
///
/// - The "libraries" entry contains details for how each platform library is
/// implemented. The entry is a map, where keys are the name of the platform
@@ -58,6 +63,20 @@
/// which will be resolved relative to the location of the library
/// specification file.
///
+/// - The "environment_overrides" entry contains rules to override the value
+/// of environment variables that are derived from the platform libraries.
+///
+/// By default every platform library that is available in the "libraries"
+/// section implicitly defines an environment variable `dart.library.name`
+/// as `"true"`, to indicate that the library is supported. Some backends
+/// override this to allow imports to a platform library, but still report
+/// that the library is not supported in conditional imports and const
+/// `fromEnvironment` expressions.
+///
+/// A name key listed in the "environment_overrides" section must match the
+/// name of a library in the "libraries" section. The value is a bool,
+/// however, since the libraries are assumed to be supported by default, we
+/// only expect users to use `false`.
///
/// Note: we currently have several different files that need to be updated
/// when changing libraries, sources, and patch files:
@@ -69,6 +88,9 @@
/// https://github.com/dart-lang/sdk/issues/28836), but for now we need to pay
/// close attention to change them consistently.
+// TODO(sigmund): consider moving the overrides directly into the libraries
+// section (e.g. add a "supported: false" entry).
+
// TODO(sigmund): move this file to a shared package.
import 'dart:convert' show JSON;
@@ -84,10 +106,16 @@
const LibrariesSpecification(
[this._targets = const <String, TargetLibrariesSpecification>{}]);
- /// The library specification for a given [target], or null if none is
+ /// The library specification for a given [target], or throws if none is
/// available.
- TargetLibrariesSpecification specificationFor(String target) =>
- _targets[target];
+ TargetLibrariesSpecification specificationFor(String target) {
+ var targetSpec = _targets[target];
+ if (targetSpec == null) {
+ throw new LibrariesSpecificationException(
+ 'No library specification for target "$target"');
+ }
+ return targetSpec;
+ }
/// Parse the given [json] as a library specification, resolving any relative
/// paths from [baseUri].
@@ -153,8 +181,28 @@
}
libraries[name] = new LibraryInfo(name, uri, patches);
});
- targets[targetName] =
- new TargetLibrariesSpecification(targetName, libraries);
+ Map<String, bool> environmentOverrides = <String, bool>{};
+ if (targetData.containsKey("environment_overrides")) {
+ var overridesData = targetData["environment_overrides"];
+ if (overridesData is! Map) {
+ return _reportError(
+ "environment_overrides entry for '$targetName' is not a map");
+ }
+ overridesData.forEach((String name, value) {
+ if (!libraries.containsKey(name)) {
+ return _reportError(
+ "entry '$name' does not correspond to an existing library "
+ "in '$targetName'");
+ }
+ if (value is bool) {
+ environmentOverrides[name] = value;
+ } else {
+ return _reportError("entry '$name' is not a bool");
+ }
+ });
+ }
+ targets[targetName] = new TargetLibrariesSpecification(
+ targetName, libraries, environmentOverrides);
});
return new LibrariesSpecification(targets);
}
@@ -180,6 +228,10 @@
};
});
result[targetName] = {'libraries': libraries};
+ if (target._environmentOverrides.isNotEmpty) {
+ result[targetName]['environment_overrides'] =
+ target._environmentOverrides;
+ }
});
return result;
}
@@ -192,11 +244,21 @@
final Map<String, LibraryInfo> _libraries;
+ final Map<String, bool> _environmentOverrides;
+
const TargetLibrariesSpecification(this.targetName,
- [this._libraries = const <String, LibraryInfo>{}]);
+ [this._libraries = const <String, LibraryInfo>{},
+ this._environmentOverrides = const <String, bool>{}]);
/// Details about a library whose import is `dart:$name`.
LibraryInfo libraryInfoFor(String name) => _libraries[name];
+
+ /// Environment override for a library whose import is `dart:$name`. The value
+ /// can be "true", "false", or null if no override was given.
+ String environmentOverrideFor(String name) {
+ var override = _environmentOverrides[name];
+ return override == null ? null : "$override";
+ }
}
/// Information about a `dart:` library in a specific target platform.
diff --git a/pkg/front_end/lib/src/fasta/builder_graph.dart b/pkg/front_end/lib/src/fasta/builder_graph.dart
index b78d5f9..b4350b1 100644
--- a/pkg/front_end/lib/src/fasta/builder_graph.dart
+++ b/pkg/front_end/lib/src/fasta/builder_graph.dart
@@ -4,6 +4,8 @@
library fasta.builder_graph;
+import 'package:kernel/kernel.dart' show LibraryDependency, LibraryPart;
+
import 'package:kernel/util/graph.dart' show Graph;
import 'builder/builder.dart' show LibraryBuilder;
@@ -49,22 +51,15 @@
}
} else if (library is DillLibraryBuilder) {
// Imports and exports
- for (var dependency in library.library.dependencies) {
- var uriString;
- if (dependency.importedLibraryReference.node != null) {
- uriString = '${dependency.targetLibrary.importUri}';
- } else {
- uriString =
- '${dependency.importedLibraryReference.canonicalName.name}';
- }
- Uri uri = Uri.parse(uriString);
+ for (LibraryDependency dependency in library.library.dependencies) {
+ Uri uri = dependency.targetLibrary.importUri;
if (builders.containsKey(uri)) {
yield uri;
}
}
// Parts
- for (var part in library.library.parts) {
+ for (LibraryPart part in library.library.parts) {
Uri uri = part.fileUri;
if (builders.containsKey(uri)) {
yield uri;
diff --git a/pkg/front_end/lib/src/fasta/compiler_context.dart b/pkg/front_end/lib/src/fasta/compiler_context.dart
index 77ab869..54d8af3 100644
--- a/pkg/front_end/lib/src/fasta/compiler_context.dart
+++ b/pkg/front_end/lib/src/fasta/compiler_context.dart
@@ -125,7 +125,8 @@
return current.enableColorsCached ??= computeEnableColors(current);
}
- static void clear() {
+ void clear() {
StringToken.canonicalizer.clear();
+ errors.clear();
}
}
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index b3039b5..3d7d04b 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -8,13 +8,14 @@
import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder;
-import 'package:kernel/kernel.dart' show Library, Procedure, Component, Source;
+import 'package:kernel/kernel.dart'
+ show Component, Library, LibraryPart, Procedure, Source;
+
+import '../api_prototype/file_system.dart' show FileSystemEntity;
import '../api_prototype/incremental_kernel_generator.dart'
show IncrementalKernelGenerator;
-import '../api_prototype/file_system.dart' show FileSystemEntity;
-
import 'builder/builder.dart' show LibraryBuilder;
import 'builder_graph.dart' show BuilderGraph;
@@ -25,7 +26,10 @@
import 'dill/dill_target.dart' show DillTarget;
-import 'kernel/kernel_target.dart' show KernelTarget;
+import 'kernel/kernel_incremental_target.dart'
+ show KernelIncrementalTarget, KernelIncrementalTargetErroneousComponent;
+
+import 'library_graph.dart' show LibraryGraph;
import 'source/source_library_builder.dart' show SourceLibraryBuilder;
@@ -46,13 +50,14 @@
final Uri initializeFromDillUri;
bool initializedFromDill = false;
- KernelTarget userCode;
+ KernelIncrementalTarget userCode;
IncrementalCompiler(this.context, [this.initializeFromDillUri])
: ticker = context.options.ticker;
@override
- Future<Component> computeDelta({Uri entryPoint}) async {
+ Future<Component> computeDelta(
+ {Uri entryPoint, bool fullComponent: false}) async {
ticker.reset();
entryPoint ??= context.options.inputs.single;
return context.runInContext<Future<Component>>((CompilerContext c) async {
@@ -72,7 +77,7 @@
bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
}
}
- appendLibraries(data, bytesLength);
+ appendLibraries(data, bytesLength, uriTranslator);
try {
await dillLoadedData.buildOutlines();
@@ -83,7 +88,7 @@
initializedFromDill = false;
data.reset();
bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
- appendLibraries(data, bytesLength);
+ appendLibraries(data, bytesLength, uriTranslator);
await dillLoadedData.buildOutlines();
}
summaryBytes = null;
@@ -115,11 +120,13 @@
ticker.logMs("Decided to reuse ${reusedLibraries.length}"
" of ${userCode.loader.builders.length} libraries");
}
-
reusedLibraries.addAll(platformBuilders);
- userCode = new KernelTarget(
+
+ KernelIncrementalTarget userCodeOld = userCode;
+ userCode = new KernelIncrementalTarget(
c.fileSystem, false, dillLoadedData, dillLoadedData.uriTranslator,
uriToSource: c.uriToSource);
+
for (LibraryBuilder library in reusedLibraries) {
userCode.loader.builders[library.uri] = library;
if (library.uri.scheme == "dart" && library.uri.path == "core") {
@@ -127,47 +134,97 @@
}
}
- userCode.read(entryPoint);
+ Component componentWithDill;
+ try {
+ userCode.read(entryPoint);
+ await userCode.buildOutlines();
- await userCode.buildOutlines();
-
- // This is not the full program. It is the component including all
- // libraries loaded from .dill files.
- Component componentWithDill =
- await userCode.buildComponent(verify: c.options.verify);
+ // This is not the full component. It is the component including all
+ // libraries loaded from .dill files.
+ componentWithDill =
+ await userCode.buildComponent(verify: c.options.verify);
+ } on KernelIncrementalTargetErroneousComponent {
+ List<Library> librariesWithSdk = userCode.component.libraries;
+ List<Library> libraries = <Library>[];
+ for (Library lib in librariesWithSdk) {
+ if (lib.fileUri.scheme == "dart") continue;
+ libraries.add(lib);
+ break;
+ }
+ userCode.loader.builders.clear();
+ userCode = userCodeOld;
+ return new Component(
+ libraries: libraries, uriToSource: data.uriToSource);
+ }
+ userCodeOld?.loader?.builders?.clear();
+ userCodeOld = null;
List<Library> libraries =
new List<Library>.from(userCode.loader.libraries);
data.uriToSource.addAll(userCode.uriToSource);
- if (data.includeUserLoadedLibraries) {
- for (LibraryBuilder library in reusedLibraries) {
- if (library.fileUri.scheme == "dart") continue;
- assert(library is DillLibraryBuilder);
- libraries.add((library as DillLibraryBuilder).library);
- }
-
- // For now ensure original order of libraries to produce bit-perfect
- // output.
- libraries.sort((a, b) {
- int aOrder = data.importUriToOrder[a.importUri];
- int bOrder = data.importUriToOrder[b.importUri];
- if (aOrder != null && bOrder != null) return aOrder - bOrder;
- if (aOrder != null) return -1;
- if (bOrder != null) return 1;
- return 0;
- });
- }
-
- // This component represents the parts of the program that were
- // recompiled.
Procedure mainMethod = componentWithDill == null
? data.userLoadedUriMain
: componentWithDill.mainMethod;
+ if (data.includeUserLoadedLibraries || fullComponent) {
+ addReusedLibraries(libraries, mainMethod, reusedLibraries, data);
+ }
+
+ // Clean up.
+ userCode.loader.releaseAncillaryResources();
+
+ // This is the incremental component.
return new Component(libraries: libraries, uriToSource: data.uriToSource)
..mainMethod = mainMethod;
});
}
+ void addReusedLibraries(List<Library> libraries, Procedure mainMethod,
+ List<LibraryBuilder> reusedLibraries, IncrementalCompilerData data) {
+ Map<Uri, Library> libraryMap = <Uri, Library>{};
+ for (Library library in libraries) {
+ libraryMap[library.fileUri] = library;
+ }
+ List<Uri> worklist = new List<Uri>.from(libraryMap.keys);
+ worklist.add(mainMethod?.enclosingLibrary?.fileUri);
+
+ Map<Uri, Library> potentiallyReferencedLibraries = <Uri, Library>{};
+ for (LibraryBuilder library in reusedLibraries) {
+ if (library.fileUri.scheme == "dart") continue;
+ Library lib = library.target;
+ potentiallyReferencedLibraries[library.fileUri] = lib;
+ libraryMap[library.fileUri] = lib;
+ }
+
+ LibraryGraph graph = new LibraryGraph(libraryMap);
+ while (worklist.isNotEmpty && potentiallyReferencedLibraries.isNotEmpty) {
+ Uri uri = worklist.removeLast();
+ if (libraryMap.containsKey(uri)) {
+ for (Uri neighbor in graph.neighborsOf(uri)) {
+ worklist.add(neighbor);
+ }
+ libraryMap.remove(uri);
+ Library library = potentiallyReferencedLibraries.remove(uri);
+ if (library != null) {
+ libraries.add(library);
+ }
+ }
+ }
+ for (Uri uri in potentiallyReferencedLibraries.keys) {
+ userCode.loader.builders.remove(uri);
+ }
+
+ // For now ensure original order of libraries to produce bit-perfect
+ // output.
+ libraries.sort((a, b) {
+ int aOrder = data.importUriToOrder[a.importUri];
+ int bOrder = data.importUriToOrder[b.importUri];
+ if (aOrder != null && bOrder != null) return aOrder - bOrder;
+ if (aOrder != null) return -1;
+ if (bOrder != null) return 1;
+ return 0;
+ });
+ }
+
int prepareSummary(List<int> summaryBytes, UriTranslator uriTranslator,
CompilerContext c, IncrementalCompilerData data) {
dillLoadedData = new DillTarget(ticker, uriTranslator, c.options.target);
@@ -198,6 +255,8 @@
data.component.libraries.map((Library lib) => lib.importUri));
ticker.logMs("Read $initializeFromDillUri");
+ Set<Uri> sdkUris = data.component.uriToSource.keys.toSet();
+
// We're going to output all we read here so lazy loading it
// doesn't make sense.
new BinaryBuilder(initializationBytes, disableLazyReading: true)
@@ -211,14 +270,29 @@
}
data.userLoadedUriMain = data.component.mainMethod;
data.includeUserLoadedLibraries = true;
- data.uriToSource.addAll(data.component.uriToSource);
+ for (Uri uri in data.component.uriToSource.keys) {
+ if (sdkUris.contains(uri)) continue;
+ data.uriToSource[uri] = data.component.uriToSource[uri];
+ }
}
}
return bytesLength;
}
- void appendLibraries(IncrementalCompilerData data, int bytesLength) {
+ void appendLibraries(IncrementalCompilerData data, int bytesLength,
+ UriTranslator uriTranslator) {
if (data.component != null) {
+ List<Library> keepLibraries = <Library>[];
+ for (Library lib in data.component.libraries) {
+ if (lib.importUri.scheme != "package" ||
+ uriTranslator.translate(lib.importUri, false) != null) {
+ keepLibraries.add(lib);
+ }
+ }
+ data.component.libraries
+ ..clear()
+ ..addAll(keepLibraries);
+
dillLoadedData.loader
.appendLibraries(data.component, byteCount: bytesLength);
}
@@ -254,11 +328,11 @@
}
if (!recursive) return;
if (library is SourceLibraryBuilder) {
- for (var part in library.parts) {
+ for (LibraryBuilder part in library.parts) {
addBuilderAndInvalidateUris(part.uri, part, false);
}
} else if (library is DillLibraryBuilder) {
- for (var part in library.library.parts) {
+ for (LibraryPart part in library.library.parts) {
addBuilderAndInvalidateUris(part.fileUri, library, false);
}
}
@@ -269,6 +343,8 @@
userCode.loader.builders.forEach(addBuilderAndInvalidateUris);
}
+ recordInvalidatedImportUrisForTesting(invalidatedImportUris);
+
BuilderGraph graph = new BuilderGraph(builders);
// Compute direct dependencies for each import URI (the reverse of the
@@ -309,7 +385,7 @@
// builder can exist multiple times in the values list.
Set<Uri> seenUris = new Set<Uri>();
List<LibraryBuilder> result = <LibraryBuilder>[];
- for (var builder in builders.values) {
+ for (LibraryBuilder builder in builders.values) {
if (builder.isPart) continue;
if (!seenUris.add(builder.fileUri)) continue;
result.add(builder);
@@ -321,6 +397,8 @@
void invalidate(Uri uri) {
invalidatedUris.add(uri);
}
+
+ void recordInvalidatedImportUrisForTesting(List<Uri> uris) {}
}
class IncrementalCompilerData {
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 bdf106f..542a791 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -429,13 +429,15 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
debugEvent("TopLevelFields");
push(count);
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
debugEvent("Fields");
push(count);
}
@@ -471,7 +473,6 @@
}
}
pop(); // Type.
- pop(); // Modifiers.
List annotations = pop();
if (annotations != null) {
_typeInferrer.inferMetadata(this, annotations);
@@ -2861,6 +2862,9 @@
returnType ??= const DynamicType();
exitFunction();
List<TypeParameter> typeParameters = typeVariableBuildersToKernel(pop());
+ if (!isFunctionExpression) {
+ pop(); // Metadata.
+ }
FunctionNode function = formals.addToFunction(new FunctionNode(body,
typeParameters: typeParameters,
asyncMarker: asyncModifier,
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 b4e425e..5ead269 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
@@ -27,7 +27,9 @@
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
-import 'package:kernel/type_algebra.dart' show Substitution;
+import 'package:kernel/clone.dart' show CloneWithoutBody;
+
+import 'package:kernel/type_algebra.dart' show Substitution, getSubstitutionMap;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
@@ -51,6 +53,8 @@
templateOverrideTypeVariablesMismatch,
templateRedirectionTargetNotFound;
+import '../names.dart' show noSuchMethodName;
+
import '../problems.dart' show unexpected, unhandled, unimplemented;
import '../type_inference/type_schema.dart' show UnknownType;
@@ -284,6 +288,73 @@
});
}
+ // TODO(dmitryas): Find a better place for this routine.
+ static bool hasUserDefinedNoSuchMethod(
+ Class klass, ClassHierarchy hierarchy) {
+ Member noSuchMethod = hierarchy.getDispatchTarget(klass, noSuchMethodName);
+ // `Object` doesn't have a superclass reference.
+ return noSuchMethod != null &&
+ noSuchMethod.enclosingClass.superclass != null;
+ }
+
+ void addNoSuchMethodForwarderForProcedure(
+ Procedure procedure, ClassHierarchy hierarchy) {
+ CloneWithoutBody cloner = new CloneWithoutBody(
+ typeSubstitution: getSubstitutionMap(
+ hierarchy.getClassAsInstanceOf(cls, procedure.enclosingClass)));
+ Procedure cloned = cloner.clone(procedure);
+ cloned.isAbstract = true;
+ cloned.isNoSuchMethodForwarder = true;
+
+ String name = cloned.name.name;
+ cls.procedures.add(cloned);
+ cloned.parent = cls;
+ DillMemberBuilder memberBuilder = new DillMemberBuilder(cloned, this);
+ memberBuilder.next = scopeBuilder[name];
+ scopeBuilder.addMember(name, memberBuilder);
+ }
+
+ void addNoSuchMethodForwarders(ClassHierarchy hierarchy) {
+ if (!hasUserDefinedNoSuchMethod(cls, hierarchy)) {
+ return;
+ }
+
+ Set<Name> existingForwardersNames = new Set<Name>();
+ if (cls.superclass != null &&
+ hasUserDefinedNoSuchMethod(cls.superclass, hierarchy)) {
+ List<Member> concrete = hierarchy.getDispatchTargets(cls.superclass);
+ for (Member member in hierarchy.getInterfaceMembers(cls.superclass)) {
+ if (ClassHierarchy.findMemberByName(concrete, member.name) == null) {
+ existingForwardersNames.add(member.name);
+ }
+ }
+ }
+ if (cls.mixedInClass != null &&
+ hasUserDefinedNoSuchMethod(cls.mixedInClass, hierarchy)) {
+ List<Member> concrete = hierarchy.getDispatchTargets(cls.mixedInClass);
+ for (Member member in hierarchy.getInterfaceMembers(cls.mixedInClass)) {
+ if (ClassHierarchy.findMemberByName(concrete, member.name) == null) {
+ existingForwardersNames.add(member.name);
+ }
+ }
+ }
+
+ List<Member> concrete = hierarchy.getDispatchTargets(cls);
+ List<Member> declared = hierarchy.getDeclaredMembers(cls);
+ for (Member member in hierarchy.getInterfaceMembers(cls)) {
+ if ((member is Procedure) &&
+ ClassHierarchy.findMemberByName(concrete, member.name) == null &&
+ !existingForwardersNames.contains(member.name)) {
+ if (ClassHierarchy.findMemberByName(declared, member.name) != null) {
+ member.isNoSuchMethodForwarder = true;
+ } else {
+ addNoSuchMethodForwarderForProcedure(member, hierarchy);
+ }
+ existingForwardersNames.add(member.name);
+ }
+ }
+ }
+
Uri _getMemberUri(Member member) {
if (member is Field) return member.fileUri;
if (member is Procedure) return member.fileUri;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart
new file mode 100644
index 0000000..d83c9ae
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_incremental_target.dart
@@ -0,0 +1,35 @@
+// 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.
+
+library fasta.kernel_incremental_target;
+
+import 'package:kernel/ast.dart' show Component, Source;
+
+import '../../api_prototype/file_system.dart' show FileSystem;
+
+import '../dill/dill_target.dart' show DillTarget;
+
+import '../uri_translator.dart' show UriTranslator;
+
+import 'kernel_target.dart' show KernelTarget;
+
+class KernelIncrementalTarget extends KernelTarget {
+ Component component;
+
+ KernelIncrementalTarget(FileSystem fileSystem, bool includeComments,
+ DillTarget dillTarget, UriTranslator uriTranslator,
+ {Map<Uri, Source> uriToSource})
+ : super(fileSystem, includeComments, dillTarget, uriTranslator,
+ uriToSource: uriToSource);
+
+ @override
+ Component erroneousComponent(bool isFullComponent) {
+ component = super.erroneousComponent(isFullComponent);
+ throw const KernelIncrementalTargetErroneousComponent();
+ }
+}
+
+class KernelIncrementalTargetErroneousComponent {
+ const KernelIncrementalTargetErroneousComponent();
+}
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 9550057..778e898 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -264,6 +264,9 @@
loader.performTopLevelInference(myClasses);
}
loader.checkOverrides(myClasses);
+ if (backendTarget.enableNoSuchMethodForwarders) {
+ loader.addNoSuchMethodForwarders(myClasses);
+ }
} on deprecated_InputError catch (e) {
ticker.logMs("Got deprecated_InputError");
handleInputError(e, isFullComponent: false);
@@ -355,6 +358,13 @@
(LocatedMessage message) => new ExpressionStatement(new Throw(
new StringLiteral(context.format(message, Severity.error)))))));
}
+
+ // Clear libraries to avoid having 'the same' library added in both outline
+ // and body building. As loader.libraries is used in the incremental
+ // compiler that will causes problems (i.e. it cannot serialize because 2
+ // libraries has the same URI).
+ loader.libraries.clear();
+
loader.libraries.add(library.library);
library.build(loader.coreLibrary);
return link(<Library>[library.library]);
diff --git a/pkg/front_end/lib/src/fasta/library_graph.dart b/pkg/front_end/lib/src/fasta/library_graph.dart
new file mode 100644
index 0000000..0d7ab6f
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/library_graph.dart
@@ -0,0 +1,37 @@
+// 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.
+
+library fasta.library_graph;
+
+import 'package:kernel/kernel.dart' show Library, LibraryDependency;
+
+import 'package:kernel/util/graph.dart' show Graph;
+
+class LibraryGraph implements Graph<Uri> {
+ final Map<Uri, Library> libraries;
+
+ LibraryGraph(this.libraries);
+
+ Iterable<Uri> get vertices => libraries.keys;
+
+ Iterable<Uri> neighborsOf(Uri vertex) sync* {
+ Library library = libraries[vertex];
+ if (library == null) {
+ throw "Library not found: $vertex";
+ }
+
+ // Imports and exports
+ for (LibraryDependency dependency in library.dependencies) {
+ Uri uri1 = dependency.targetLibrary.importUri;
+ Uri uri2 = dependency.targetLibrary.fileUri;
+ if (libraries.containsKey(uri1)) {
+ yield uri1;
+ } else if (uri2 != null) {
+ if (libraries.containsKey(uri2)) {
+ yield uri2;
+ }
+ }
+ }
+ }
+}
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 c5c0802..17fb305 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -66,8 +66,8 @@
}
@override
- void beginClassDeclaration(Token beginToken, Token name) {
- listener?.beginClassDeclaration(beginToken, name);
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
+ listener?.beginClassDeclaration(begin, abstractToken, name);
}
@override
@@ -299,8 +299,9 @@
}
@override
- void beginNamedMixinApplication(Token beginToken, Token name) {
- listener?.beginNamedMixinApplication(beginToken, name);
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {
+ listener?.beginNamedMixinApplication(begin, abstractToken, name);
}
@override
@@ -564,8 +565,10 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
- listener?.endFields(count, beginToken, endToken);
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
+ listener?.endFields(staticToken, covariantToken, varFinalOrConst, count,
+ beginToken, endToken);
}
@override
@@ -810,8 +813,10 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
- listener?.endTopLevelFields(count, beginToken, endToken);
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
+ listener?.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
+ count, beginToken, endToken);
}
@override
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 af0a4e2..d53576c 100644
--- a/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context.dart
@@ -2,8 +2,16 @@
// 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:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/scanner/token.dart';
+import '../../scanner/token.dart' show Token;
+
+import '../fasta_codes.dart'
+ show Message, Template, templateExpectedIdentifier, templateExpectedType;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'identifier_context_impl.dart';
+
+import 'parser.dart' show Parser;
/// Information about the parser state that is passed to the listener at the
/// time an identifier is encountered. It is also used by the parser for error
@@ -15,42 +23,42 @@
class IdentifierContext {
/// Identifier is being declared as the name of an import prefix (i.e. `Foo`
/// in `import "..." as Foo;`)
- static const importPrefixDeclaration = const IdentifierContext._(
+ static const importPrefixDeclaration = const IdentifierContext(
'importPrefixDeclaration',
inDeclaration: true,
isBuiltInIdentifierAllowed: false);
/// Identifier is the start of a dotted name in a conditional import or
/// export.
- static const dottedName = const IdentifierContext._('dottedName');
+ static const dottedName = const IdentifierContext('dottedName');
/// Identifier is part of a dotted name in a conditional import or export, but
/// it's not the first identifier of the dotted name.
static const dottedNameContinuation =
- const IdentifierContext._('dottedNameContinuation', isContinuation: true);
+ const IdentifierContext('dottedNameContinuation', isContinuation: true);
/// Identifier is one of the shown/hidden names in an import/export
/// combinator.
- static const combinator = const IdentifierContext._('combinator');
+ static const combinator = const IdentifierContext('combinator');
/// Identifier is the start of a name in an annotation that precedes a
/// declaration (i.e. it appears directly after an `@`).
static const metadataReference =
- const IdentifierContext._('metadataReference', isScopeReference: true);
+ const IdentifierContext('metadataReference', isScopeReference: true);
/// Identifier is part of a name in an annotation that precedes a declaration,
/// but it's not the first identifier in the name.
static const metadataContinuation =
- const IdentifierContext._('metadataContinuation', isContinuation: true);
+ const IdentifierContext('metadataContinuation', isContinuation: true);
/// Identifier is part of a name in an annotation that precedes a declaration,
/// but it appears after type parameters (e.g. `foo` in `@X<Y>.foo()`).
- static const metadataContinuationAfterTypeArguments =
- const IdentifierContext._('metadataContinuationAfterTypeArguments',
- isContinuation: true);
+ static const metadataContinuationAfterTypeArguments = const IdentifierContext(
+ 'metadataContinuationAfterTypeArguments',
+ isContinuation: true);
/// Identifier is the name being declared by a typedef declaration.
- static const typedefDeclaration = const IdentifierContext._(
+ static const typedefDeclaration = const IdentifierContext(
'typedefDeclaration',
inDeclaration: true,
isBuiltInIdentifierAllowed: false);
@@ -58,99 +66,96 @@
/// Identifier is a field initializer in a formal parameter list (i.e. it
/// appears directly after `this.`).
static const fieldInitializer =
- const IdentifierContext._('fieldInitializer', isContinuation: true);
+ const IdentifierContext('fieldInitializer', isContinuation: true);
/// Identifier is a formal parameter being declared as part of a function,
/// method, or typedef declaration.
- static const formalParameterDeclaration = const IdentifierContext._(
+ static const formalParameterDeclaration = const IdentifierContext(
'formalParameterDeclaration',
inDeclaration: true);
/// Identifier is the start of a library name (e.g. `foo` in the directive
/// 'library foo;`).
- static const libraryName = const IdentifierContext._('libraryName',
- inLibraryOrPartOfDeclaration: true);
+ static const libraryName = const LibraryIdentifierContext();
/// Identifier is part of a library name, but it's not the first identifier in
/// the name.
- static const libraryNameContinuation = const IdentifierContext._(
- 'libraryNameContinuation',
- inLibraryOrPartOfDeclaration: true,
- isContinuation: true);
+ static const libraryNameContinuation =
+ const LibraryIdentifierContext.continuation();
/// Identifier is the start of a library name referenced by a `part of`
/// directive (e.g. `foo` in the directive `part of foo;`).
static const partName =
- const IdentifierContext._('partName', inLibraryOrPartOfDeclaration: true);
+ const IdentifierContext('partName', inLibraryOrPartOfDeclaration: true);
/// Identifier is part of a library name referenced by a `part of` directive,
/// but it's not the first identifier in the name.
- static const partNameContinuation = const IdentifierContext._(
+ static const partNameContinuation = const IdentifierContext(
'partNameContinuation',
inLibraryOrPartOfDeclaration: true,
isContinuation: true);
/// Identifier is the type name being declared by an enum declaration.
- static const enumDeclaration = const IdentifierContext._('enumDeclaration',
+ static const enumDeclaration = const IdentifierContext('enumDeclaration',
inDeclaration: true, isBuiltInIdentifierAllowed: false);
/// Identifier is an enumerated value name being declared by an enum
/// declaration.
static const enumValueDeclaration =
- const IdentifierContext._('enumValueDeclaration', inDeclaration: true);
+ const IdentifierContext('enumValueDeclaration', inDeclaration: true);
/// Identifier is the name being declared by a class declaration or a named
/// mixin application, for example, `Foo` in `class Foo = X with Y;`.
- static const classOrNamedMixinDeclaration = const IdentifierContext._(
+ static const classOrNamedMixinDeclaration = const IdentifierContext(
'classOrNamedMixinDeclaration',
inDeclaration: true,
isBuiltInIdentifierAllowed: false);
/// Identifier is the name of a type variable being declared (e.g. `Foo` in
/// `class C<Foo extends num> {}`).
- static const typeVariableDeclaration = const IdentifierContext._(
+ static const typeVariableDeclaration = const IdentifierContext(
'typeVariableDeclaration',
inDeclaration: true,
isBuiltInIdentifierAllowed: false);
/// Identifier is the start of a reference to a type that starts with prefix.
- static const prefixedTypeReference = const IdentifierContext._(
+ static const prefixedTypeReference = const IdentifierContext(
'prefixedTypeReference',
isScopeReference: true,
isBuiltInIdentifierAllowed: true,
recoveryTemplate: templateExpectedType);
/// Identifier is the start of a reference to a type declared elsewhere.
- static const typeReference = const IdentifierContext._('typeReference',
+ static const typeReference = const IdentifierContext('typeReference',
isScopeReference: true,
isBuiltInIdentifierAllowed: false,
recoveryTemplate: templateExpectedType);
/// Identifier is part of a reference to a type declared elsewhere, but it's
/// not the first identifier of the reference.
- static const typeReferenceContinuation = const IdentifierContext._(
+ static const typeReferenceContinuation = const IdentifierContext(
'typeReferenceContinuation',
isContinuation: true,
isBuiltInIdentifierAllowed: false);
/// Identifier is a name being declared by a top level variable declaration.
- static const topLevelVariableDeclaration = const IdentifierContext._(
+ static const topLevelVariableDeclaration = const IdentifierContext(
'topLevelVariableDeclaration',
inDeclaration: true);
/// Identifier is a name being declared by a field declaration.
static const fieldDeclaration =
- const IdentifierContext._('fieldDeclaration', inDeclaration: true);
+ const IdentifierContext('fieldDeclaration', inDeclaration: true);
/// Identifier is the name being declared by a top level function declaration.
- static const topLevelFunctionDeclaration = const IdentifierContext._(
+ static const topLevelFunctionDeclaration = const IdentifierContext(
'topLevelFunctionDeclaration',
inDeclaration: true);
/// Identifier is the start of the name being declared by a method
/// declaration.
static const methodDeclaration =
- const IdentifierContext._('methodDeclaration', inDeclaration: true);
+ const IdentifierContext('methodDeclaration', inDeclaration: true);
/// Identifier is part of the name being declared by a method declaration,
/// but it's not the first identifier of the name.
@@ -158,7 +163,7 @@
/// In valid Dart, this can only happen if the identifier is the name of a
/// named constructor which is being declared, e.g. `foo` in
/// `class C { C.foo(); }`.
- static const methodDeclarationContinuation = const IdentifierContext._(
+ static const methodDeclarationContinuation = const IdentifierContext(
'methodDeclarationContinuation',
inDeclaration: true,
isContinuation: true);
@@ -168,7 +173,7 @@
/// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
/// occur as part of error recovery? If it's only as part of error recovery,
/// perhaps we should just re-use methodDeclaration.
- static const operatorName = const IdentifierContext._('operatorName');
+ static const operatorName = const IdentifierContext('operatorName');
/// Identifier is the name being declared by a local function declaration that
/// uses a "get" or "set" keyword.
@@ -176,22 +181,20 @@
/// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
/// occur as part of error recovery? If it's only as part of error recovery,
/// perhaps we should just re-use localFunctionDeclaration.
- static const localAccessorDeclaration = const IdentifierContext._(
- 'localAccessorDeclaration',
- inDeclaration: true);
+ static const localAccessorDeclaration =
+ const IdentifierContext('localAccessorDeclaration', inDeclaration: true);
/// Identifier is the start of the name being declared by a local function
/// declaration.
- static const localFunctionDeclaration = const IdentifierContext._(
- 'localFunctionDeclaration',
- inDeclaration: true);
+ static const localFunctionDeclaration =
+ const IdentifierContext('localFunctionDeclaration', inDeclaration: true);
/// Identifier is part of the name being declared by a local function
/// declaration, but it's not the first identifier of the name.
///
/// TODO(paulberry,ahe): Does this ever occur in valid Dart, or does it only
/// occur as part of error recovery?
- static const localFunctionDeclarationContinuation = const IdentifierContext._(
+ static const localFunctionDeclarationContinuation = const IdentifierContext(
'localFunctionDeclarationContinuation',
inDeclaration: true,
isContinuation: true);
@@ -201,39 +204,39 @@
/// TODO(paulberry,ahe): What is an example of valid Dart code where this
/// would occur?
static const functionExpressionName =
- const IdentifierContext._('functionExpressionName');
+ const IdentifierContext('functionExpressionName');
/// Identifier is the start of a reference to a constructor declared
/// elsewhere.
static const constructorReference =
- const IdentifierContext._('constructorReference', isScopeReference: true);
+ const IdentifierContext('constructorReference', isScopeReference: true);
/// Identifier is part of a reference to a constructor declared elsewhere, but
/// it's not the first identifier of the reference.
- static const constructorReferenceContinuation = const IdentifierContext._(
+ static const constructorReferenceContinuation = const IdentifierContext(
'constructorReferenceContinuation',
isContinuation: true);
/// Identifier is part of a reference to a constructor declared elsewhere, but
/// it appears after type parameters (e.g. `foo` in `X<Y>.foo`).
static const constructorReferenceContinuationAfterTypeArguments =
- const IdentifierContext._(
+ const IdentifierContext(
'constructorReferenceContinuationAfterTypeArguments',
isContinuation: true);
/// Identifier is the declaration of a label (i.e. it is followed by `:` and
/// then a statement).
static const labelDeclaration =
- const IdentifierContext._('labelDeclaration', inDeclaration: true);
+ const IdentifierContext('labelDeclaration', inDeclaration: true);
/// Identifier is the start of a reference occurring in a literal symbol (e.g.
/// `foo` in `#foo`).
static const literalSymbol =
- const IdentifierContext._('literalSymbol', inSymbol: true);
+ const IdentifierContext('literalSymbol', inSymbol: true);
/// Identifier is part of a reference occurring in a literal symbol, but it's
/// not the first identifier of the reference (e.g. `foo` in `#prefix.foo`).
- static const literalSymbolContinuation = const IdentifierContext._(
+ static const literalSymbolContinuation = const IdentifierContext(
'literalSymbolContinuation',
inSymbol: true,
isContinuation: true);
@@ -241,26 +244,25 @@
/// Identifier appears in an expression, and it does not immediately follow a
/// `.`.
static const expression =
- const IdentifierContext._('expression', isScopeReference: true);
+ const IdentifierContext('expression', isScopeReference: true);
/// Identifier appears in an expression, and it immediately follows a `.`.
static const expressionContinuation =
- const IdentifierContext._('expressionContinuation', isContinuation: true);
+ const IdentifierContext('expressionContinuation', isContinuation: true);
/// Identifier is a reference to a named argument of a function or method
/// invocation (e.g. `foo` in `f(foo: 0);`.
- static const namedArgumentReference = const IdentifierContext._(
+ static const namedArgumentReference = const IdentifierContext(
'namedArgumentReference',
allowedInConstantExpression: true);
/// Identifier is a name being declared by a local variable declaration.
- static const localVariableDeclaration = const IdentifierContext._(
- 'localVariableDeclaration',
- inDeclaration: true);
+ static const localVariableDeclaration =
+ const IdentifierContext('localVariableDeclaration', inDeclaration: true);
/// Identifier is a reference to a label (e.g. `foo` in `break foo;`).
/// Labels have their own scope.
- static const labelReference = const IdentifierContext._('labelReference');
+ static const labelReference = const IdentifierContext('labelReference');
final String _name;
@@ -290,7 +292,7 @@
final Template<_MessageWithArgument<Token>> recoveryTemplate;
- const IdentifierContext._(this._name,
+ const IdentifierContext(this._name,
{this.inDeclaration: false,
this.inLibraryOrPartOfDeclaration: false,
this.inSymbol: false,
@@ -307,6 +309,16 @@
(inDeclaration || isContinuation || inSymbol);
String toString() => _name;
+
+ /// Ensure that the next token is an identifier (or keyword which should be
+ /// treated as an identifier) and return that identifier.
+ /// Report errors as necessary via [parser].
+ Token ensureIdentifier(Token token, Parser parser) {
+ assert(token.next.kind != IDENTIFIER_TOKEN);
+ // TODO(danrubel): Implement this method for each identifier context
+ // such that they return a non-null value.
+ return null;
+ }
}
// TODO(ahe): Remove when analyzer supports generalized function syntax.
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
new file mode 100644
index 0000000..54aeabe
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/parser/identifier_context_impl.dart
@@ -0,0 +1,73 @@
+// 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.
+
+import '../../scanner/token.dart' show SyntheticStringToken, Token, TokenType;
+
+import '../fasta_codes.dart' as fasta;
+
+import '../scanner/token_constants.dart' show IDENTIFIER_TOKEN;
+
+import 'identifier_context.dart';
+
+import 'parser.dart' show Parser;
+
+import 'util.dart' show optional;
+
+/// See [IdentifierContext].libraryName
+class LibraryIdentifierContext extends IdentifierContext {
+ const LibraryIdentifierContext()
+ : super('libraryName', inLibraryOrPartOfDeclaration: true);
+
+ const LibraryIdentifierContext.continuation()
+ : super('libraryNameContinuation',
+ inLibraryOrPartOfDeclaration: true, isContinuation: true);
+
+ @override
+ Token ensureIdentifier(Token token, Parser parser) {
+ Token identifier = token.next;
+ assert(identifier.kind != IDENTIFIER_TOKEN);
+ if (identifier.isIdentifier) {
+ Token next = identifier.next;
+ if (optional('.', next) ||
+ optional(';', next) ||
+ !looksLikeStartOfNextDeclaration(identifier)) {
+ return identifier;
+ }
+ // Although this is a valid library name, the library declaration
+ // is invalid and this looks like the start of the next declaration.
+ // In this situation, fall through to insert a synthetic library name.
+ }
+ if (optional('.', identifier) ||
+ optional(';', identifier) ||
+ looksLikeStartOfNextDeclaration(identifier)) {
+ identifier = parser.insertSyntheticIdentifier(token, this,
+ message: fasta.templateExpectedIdentifier.withArguments(identifier));
+ } else {
+ parser.reportRecoverableErrorWithToken(
+ identifier, fasta.templateExpectedIdentifier);
+ if (!identifier.isKeywordOrIdentifier) {
+ // When in doubt, consume the token to ensure we make progress
+ // but insert a synthetic identifier to satisfy listeners.
+ identifier = insertSyntheticIdentifierAfter(identifier, parser);
+ }
+ }
+ return identifier;
+ }
+
+ bool looksLikeStartOfNextDeclaration(Token token) =>
+ token.isTopLevelKeyword ||
+ optional('const', token) ||
+ optional('get', token) ||
+ optional('final', token) ||
+ optional('set', token) ||
+ optional('var', token) ||
+ optional('void', token);
+}
+
+Token insertSyntheticIdentifierAfter(Token token, Parser parser) {
+ Token identifier =
+ new SyntheticStringToken(TokenType.IDENTIFIER, '', token.charOffset, 0);
+ parser.rewriter.insertTokenAfter(token, identifier);
+ return identifier;
+}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 167775d..2b4d876 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -93,7 +93,7 @@
/// Handle the beginning of a class declaration.
/// [beginToken] may be the same as [name], or may point to modifiers
/// (or extraneous modifiers in the case of recovery) preceding [name].
- void beginClassDeclaration(Token beginToken, Token name) {}
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {}
/// Handle an extends clause in a class declaration. Substructures:
/// - supertype (may be a mixin application)
@@ -257,7 +257,8 @@
/// - Variable declarations (count times)
///
/// Doesn't have a corresponding begin event, use [beginMember] instead.
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
logEvent("Fields");
}
@@ -322,12 +323,15 @@
}
/// Handle the beginning of a local function declaration. Substructures:
+ /// - Metadata
/// - Type variables
void beginLocalFunctionDeclaration(Token token) {}
/// A function declaration.
///
/// Substructures:
+ /// - Metadata
+ /// - Type variables
/// - Return type
/// - Name
/// - Type variables
@@ -405,7 +409,8 @@
/// Handle the beginning of a named mixin application.
/// [beginToken] may be the same as [name], or may point to modifiers
/// (or extraneous modifiers in the case of recovery) preceding [name].
- void beginNamedMixinApplication(Token beginToken, Token name) {}
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {}
/// Handle the end of a named mixin declaration. Substructures:
/// - metadata
@@ -806,14 +811,14 @@
/// Handle the end of a top level variable declaration. Substructures:
/// - Metadata
- /// - Modifiers
/// - Type
/// - Repeated [count] times:
/// - Variable name (identifier)
/// - Field initializer
/// Doesn't have a corresponding begin event.
/// Use [beginTopLevelMember] instead.
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
logEvent("TopLevelFields");
}
@@ -915,6 +920,9 @@
logEvent("FunctionExpression");
}
+ /// Handle the start of a variables declaration. Substructures:
+ /// - Metadata
+ /// - Type
void beginVariablesDeclaration(Token token, Token varFinalOrConst) {}
void endVariablesDeclaration(int count, Token endToken) {
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index d48c0a3..8ede4a9 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -29,7 +29,6 @@
import '../scanner/token_constants.dart'
show
- CLOSE_CURLY_BRACKET_TOKEN,
COMMA_TOKEN,
DOUBLE_TOKEN,
EOF_TOKEN,
@@ -1645,23 +1644,18 @@
Token token, Token beforeAbstractToken) {
token = token.next;
listener.beginClassOrNamedMixinApplication(token);
- Token begin = beforeAbstractToken?.next ?? token;
- if (beforeAbstractToken != null) {
- token = parseModifier(beforeAbstractToken).next;
- listener.handleModifiers(1);
- } else {
- listener.handleModifiers(0);
- }
+ Token abstractToken = beforeAbstractToken?.next;
+ Token begin = abstractToken ?? token;
Token classKeyword = token;
expect("class", token);
Token name =
ensureIdentifier(token, IdentifierContext.classOrNamedMixinDeclaration);
token = parseTypeVariablesOpt(name);
if (optional('=', token.next)) {
- listener.beginNamedMixinApplication(begin, name);
+ listener.beginNamedMixinApplication(begin, abstractToken, name);
return parseNamedMixinApplication(token, begin, classKeyword);
} else {
- listener.beginClassDeclaration(begin, name);
+ listener.beginClassDeclaration(begin, abstractToken, name);
return parseClass(token, begin, classKeyword);
}
}
@@ -1857,10 +1851,14 @@
Token parseStringPart(Token token) {
token = token.next;
- if (token.kind != STRING_TOKEN) {
- token =
- reportUnrecoverableErrorWithToken(token, fasta.templateExpectedString)
- .next;
+ while (token.kind != STRING_TOKEN) {
+ if (token is ErrorToken) {
+ reportErrorToken(token, true);
+ } else {
+ token = reportUnrecoverableErrorWithToken(
+ token, fasta.templateExpectedString);
+ }
+ token = token.next;
}
listener.handleStringPart(token);
return token;
@@ -1894,7 +1892,24 @@
/// identifier in the given [context], create a synthetic identifier, report
/// an error, and return the synthetic identifier.
Token ensureIdentifier(Token token, IdentifierContext context) {
+ assert(context != null);
Token next = token.next;
+ if (next.kind == IDENTIFIER_TOKEN) {
+ listener.handleIdentifier(next, context);
+ return next;
+ }
+ Token identifier = context.ensureIdentifier(token, this);
+ // TODO(danrubel): Once refactoring is complete,
+ // context.ensureIdentifier should never return null.
+ if (identifier != null) {
+ assert(identifier.isKeywordOrIdentifier);
+ listener.handleIdentifier(identifier, context);
+ return identifier;
+ }
+
+ // TODO(danrubel): Roll everything beyond this point into the
+ // ensureIdentifier methods in the various IdentifierContext subclasses.
+
if (!next.isIdentifier) {
if (optional("void", next)) {
reportRecoverableError(next, fasta.messageInvalidVoid);
@@ -2050,9 +2065,6 @@
followingValues = [';', 'hide', 'show', 'deferred', 'as'];
} else if (context == IdentifierContext.labelDeclaration) {
followingValues = [':'];
- } else if (context == IdentifierContext.libraryName ||
- context == IdentifierContext.libraryNameContinuation) {
- followingValues = ['.', ';'];
} else if (context == IdentifierContext.literalSymbol ||
context == IdentifierContext.literalSymbolContinuation) {
followingValues = ['.', ';'];
@@ -2285,18 +2297,8 @@
{
// Analyse the next tokens to see if they could be a type.
- if (continuation ==
- TypeContinuation.ExpressionStatementOrConstDeclaration) {
- // This is a special case. The first token is `const` and we need to
- // analyze the tokens following the const keyword.
- assert(optional("const", token.next));
- beforeBegin = token;
- begin = beforeToken = token.next;
- token = beforeToken.next;
- } else {
- beforeToken = beforeBegin = token;
- token = begin = token.next;
- }
+ beforeToken = beforeBegin = token;
+ token = begin = token.next;
if (optional("void", token)) {
// `void` is a type.
@@ -2412,17 +2414,6 @@
return token;
}
- /// Returns true if [kind] could be the end of a variable declaration.
- bool looksLikeVariableDeclarationEnd(int kind) {
- return EQ_TOKEN == kind ||
- SEMICOLON_TOKEN == kind ||
- COMMA_TOKEN == kind ||
- // Recovery: Return true for these additional invalid situations
- // in which we assume a missing semicolon.
- OPEN_CURLY_BRACKET_TOKEN == kind ||
- CLOSE_CURLY_BRACKET_TOKEN == kind;
- }
-
/// Returns true if [token] could be the start of a function body.
bool looksLikeFunctionBody(Token token) {
return optional('{', token) ||
@@ -2494,119 +2485,6 @@
}
continue optional;
- case TypeContinuation.ExpressionStatementOrDeclaration:
- assert(begin.isIdentifier || identical(begin.stringValue, 'void'));
- if (!inPlainSync && optional("await", begin)) {
- return parseExpressionStatement(beforeBegin);
- }
-
- if (looksLikeType && token.isIdentifier) {
- Token afterId = token.next;
-
- int afterIdKind = afterId.kind;
- if (looksLikeVariableDeclarationEnd(afterIdKind)) {
- // We are looking at `type identifier` followed by
- // `(',' | '=' | ';')`.
-
- // TODO(ahe): Generate type events and call
- // parseVariablesDeclarationRest instead.
- return parseVariablesDeclaration(beforeBegin);
- } else if (OPEN_PAREN_TOKEN == afterIdKind) {
- // We are looking at `type identifier '('`.
- if (looksLikeFunctionBody(afterId.endGroup.next)) {
- // We are looking at `type identifier '(' ... ')'` followed
- // `( '{' | '=>' | 'async' | 'sync' )`.
-
- // Although it looks like there are no type variables here, they
- // may get injected from a comment.
- Token beforeFormals = parseTypeVariablesOpt(token);
-
- listener.beginLocalFunctionDeclaration(begin);
- if (voidToken != null) {
- listener.handleVoidKeyword(voidToken);
- } else {
- commitType();
- }
- return parseNamedFunctionRest(
- beforeToken, begin, beforeFormals, false);
- }
- } else if (identical(afterIdKind, LT_TOKEN)) {
- // We are looking at `type identifier '<'`.
- Token beforeFormals = afterId.endGroup;
- if (beforeFormals?.next != null &&
- optional("(", beforeFormals.next)) {
- if (looksLikeFunctionBody(beforeFormals.next.endGroup.next)) {
- // We are looking at "type identifier '<' ... '>' '(' ... ')'"
- // followed by '{', '=>', 'async', or 'sync'.
- parseTypeVariablesOpt(token);
- listener.beginLocalFunctionDeclaration(begin);
- if (voidToken != null) {
- listener.handleVoidKeyword(voidToken);
- } else {
- commitType();
- }
- return parseNamedFunctionRest(
- beforeToken, begin, beforeFormals, false);
- }
- }
- }
- // Fall-through to expression statement.
- } else {
- beforeToken = beforeBegin;
- token = begin;
- if (optional(':', token.next)) {
- return parseLabeledStatement(beforeToken);
- } else if (optional('(', token.next)) {
- if (looksLikeFunctionBody(token.next.endGroup.next)) {
- // We are looking at `identifier '(' ... ')'` followed by `'{'`,
- // `'=>'`, `'async'`, or `'sync'`.
-
- // Although it looks like there are no type variables here, they
- // may get injected from a comment.
- Token formals = parseTypeVariablesOpt(token);
-
- listener.beginLocalFunctionDeclaration(token);
- listener.handleNoType(token);
- return parseNamedFunctionRest(beforeToken, begin, formals, false);
- }
- } else if (optional('<', token.next)) {
- Token gt = token.next.endGroup;
- if (gt?.next != null && optional("(", gt.next)) {
- if (looksLikeFunctionBody(gt.next.endGroup.next)) {
- // We are looking at `identifier '<' ... '>' '(' ... ')'`
- // followed by `'{'`, `'=>'`, `'async'`, or `'sync'`.
- parseTypeVariablesOpt(token);
- listener.beginLocalFunctionDeclaration(token);
- listener.handleNoType(token);
- return parseNamedFunctionRest(beforeToken, begin, gt, false);
- }
- }
- // Fall through to expression statement.
- }
- }
- return parseExpressionStatement(beforeBegin);
-
- case TypeContinuation.ExpressionStatementOrConstDeclaration:
- Token identifier;
- if (looksLikeType && token.isIdentifier) {
- identifier = token;
- } else if (begin.next.isIdentifier) {
- identifier = begin.next;
- }
- if (identifier != null) {
- if (looksLikeVariableDeclarationEnd(identifier.next.kind)) {
- // We are looking at "const type identifier" followed by '=', ';',
- // or ','.
-
- // TODO(ahe): Generate type events and call
- // parseVariablesDeclarationRest instead.
- return parseVariablesDeclaration(beforeBegin);
- }
- // Fall-through to expression statement.
- }
-
- return parseExpressionStatement(beforeBegin);
-
case TypeContinuation.SendOrFunctionLiteral:
Token beforeName;
Token name;
@@ -3068,29 +2946,15 @@
Token beforeName,
MemberKind memberKind,
TypeContinuation typeContinuation) {
- // TODO(danrubel): Consider passing modifiers via endTopLevelField
- // rather than using handleModifier and handleModifiers.
- int modifierCount = 0;
if (externalToken != null) {
reportRecoverableError(externalToken, fasta.messageExternalField);
}
- if (staticToken != null) {
- listener.handleModifier(staticToken);
- ++modifierCount;
- } else if (covariantToken != null) {
+ if (covariantToken != null) {
if (varFinalOrConst != null && optional('final', varFinalOrConst)) {
reportRecoverableError(covariantToken, fasta.messageFinalAndCovariant);
covariantToken = null;
- } else {
- listener.handleModifier(covariantToken);
- ++modifierCount;
}
}
- if (varFinalOrConst != null) {
- listener.handleModifier(varFinalOrConst);
- ++modifierCount;
- }
- listener.handleModifiers(modifierCount);
bool isTopLevel = memberKind == MemberKind.TopLevelField;
@@ -3120,9 +2984,11 @@
}
token = ensureSemicolon(token);
if (isTopLevel) {
- listener.endTopLevelFields(fieldCount, beforeStart.next, token);
+ listener.endTopLevelFields(staticToken, covariantToken, varFinalOrConst,
+ fieldCount, beforeStart.next, token);
} else {
- listener.endFields(fieldCount, beforeStart.next, token);
+ listener.endFields(staticToken, covariantToken, varFinalOrConst,
+ fieldCount, beforeStart.next, token);
}
return token;
}
@@ -3346,6 +3212,11 @@
? fasta.templateExpectedButGot.withArguments('{')
: template.withArguments(token);
reportRecoverableError(next, message);
+ return insertBlock(token);
+ }
+
+ Token insertBlock(Token token) {
+ Token next = token.next;
Token replacement = link(
new SyntheticBeginToken(TokenType.OPEN_CURLY_BRACKET, next.offset),
new SyntheticToken(TokenType.CLOSE_CURLY_BRACKET, next.offset));
@@ -3990,7 +3861,7 @@
beforeName.next, fasta.messageNamedFunctionExpression);
}
listener.endFunctionName(begin, token);
- token = parseFormalParametersOpt(formals, MemberKind.Local);
+ token = parseFormalParametersRequiredOpt(formals, MemberKind.Local);
token = parseInitializersOpt(token);
token = parseAsyncOptBody(token, isFunctionExpression, false);
if (isFunctionExpression) {
@@ -4278,15 +4149,25 @@
}
Token parseStatementX(Token token) {
- final value = token.next.stringValue;
if (identical(token.next.kind, IDENTIFIER_TOKEN)) {
- return parseExpressionStatementOrDeclaration(token);
- } else if (identical(value, '{')) {
+ if (optional(':', token.next.next)) {
+ return parseLabeledStatement(token);
+ }
+ return parseExpressionStatementOrDeclarationAfterModifiers(token, token);
+ }
+ final value = token.next.stringValue;
+ if (identical(value, '{')) {
return parseBlock(token);
} else if (identical(value, 'return')) {
return parseReturnStatement(token);
} else if (identical(value, 'var') || identical(value, 'final')) {
- return parseVariablesDeclaration(token);
+ Token varOrFinal = token.next;
+ if (isModifier(varOrFinal.next)) {
+ return parseExpressionStatementOrDeclaration(token);
+ } else {
+ return parseExpressionStatementOrDeclarationAfterModifiers(
+ varOrFinal, token, varOrFinal);
+ }
} else if (identical(value, 'if')) {
return parseIfStatement(token);
} else if (identical(value, 'await') && optional('for', token.next.next)) {
@@ -4298,8 +4179,6 @@
} else if (identical(value, 'throw') && optional(';', token.next.next)) {
// TODO(kasperl): Stop dealing with throw here.
return parseRethrowStatement(token);
- } else if (identical(value, 'void')) {
- return parseExpressionStatementOrDeclaration(token);
} else if (identical(value, 'while')) {
return parseWhileStatement(token);
} else if (identical(value, 'do')) {
@@ -4332,14 +4211,15 @@
throw "Internal error: Unknown asyncState: '$asyncState'.";
} else if (identical(value, 'const')) {
return parseExpressionStatementOrConstDeclaration(token);
- } else if (isModifier(token.next)) {
- return parseVariablesDeclaration(token);
- } else if (token.next.isIdentifier) {
- return parseExpressionStatementOrDeclaration(token);
- } else if (identical(value, '@')) {
- return parseVariablesDeclaration(token);
- } else {
+ } else if (!inPlainSync && identical(value, 'await')) {
return parseExpressionStatement(token);
+ } else if (token.next.isIdentifier) {
+ if (optional(':', token.next.next)) {
+ return parseLabeledStatement(token);
+ }
+ return parseExpressionStatementOrDeclaration(token);
+ } else {
+ return parseExpressionStatementOrDeclaration(token);
}
}
@@ -4386,21 +4266,6 @@
return token;
}
- Token parseExpressionStatementOrDeclaration(Token token) {
- return parseType(token, TypeContinuation.ExpressionStatementOrDeclaration);
- }
-
- Token parseExpressionStatementOrConstDeclaration(Token token) {
- Token next = token.next;
- assert(optional('const', next));
- if (next.next.isModifier) {
- return parseVariablesDeclaration(token);
- } else {
- return parseType(
- token, TypeContinuation.ExpressionStatementOrConstDeclaration);
- }
- }
-
/// ```
/// label:
/// identifier ':'
@@ -4424,9 +4289,7 @@
/// ```
Token parseLabeledStatement(Token token) {
Token next = token.next;
- // TODO(brianwilkerson): Enable this assert.
- // `parseType` is allowing `void` to be a label.
-// assert(next.isIdentifier);
+ assert(next.isIdentifier);
assert(optional(':', next.next));
int labelCount = 0;
do {
@@ -5487,10 +5350,72 @@
return token;
}
- /// Parse the metadata, modifiers, and type of a local declaration and return
- /// the last token consumed. If a local variable declaration or local
- /// function declaration is not found, then return the starting token.
- Token parseLocalDeclarationStartOpt(final Token start) {
+ /// Returns true if [token] could be the start of a function declaration
+ /// without a return type.
+ bool looksLikeLocalFunction(Token token) {
+ if (token.isIdentifier) {
+ token = token.next;
+ if (optional('<', token)) {
+ Token closeBrace = token.endGroup;
+ if (closeBrace == null) {
+ return false;
+ }
+ token = closeBrace.next;
+ }
+ if (optional('(', token)) {
+ token = token.endGroup.next;
+ return optional('{', token) ||
+ optional('=>', token) ||
+ optional('async', token) ||
+ optional('sync', token);
+ } else if (optional('=>', token)) {
+ // Recovery: Looks like a local function that is missing parenthesis.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Token parseExpressionStatementOrConstDeclaration(final Token start) {
+ Token constToken = start.next;
+ assert(optional('const', constToken));
+ if (!isModifier(constToken.next)) {
+ TypeInfo typeInfo = computeType(constToken, false);
+ if (typeInfo == noTypeInfo) {
+ Token next = constToken.next;
+ if (!next.isIdentifier) {
+ return parseExpressionStatement(start);
+ }
+ next = next.next;
+ if (!(optional('=', next) ||
+ // Recovery
+ next.isKeywordOrIdentifier ||
+ optional(';', next) ||
+ optional(',', next) ||
+ optional('{', next))) {
+ return parseExpressionStatement(start);
+ }
+ }
+ return parseExpressionStatementOrDeclarationAfterModifiers(
+ constToken, start, constToken, typeInfo);
+ }
+ return parseExpressionStatementOrDeclaration(start);
+ }
+
+ /// This method has two modes based upon [onlyParseVariableDeclarationStart].
+ ///
+ /// If [onlyParseVariableDeclarationStart] is `false` (the default) then this
+ /// method will parse a local variable declaration, a local function,
+ /// or an expression statement, and then return the last consumed token.
+ ///
+ /// If [onlyParseVariableDeclarationStart] is `true` then this method
+ /// will only parse the metadata, modifiers, and type of a local variable
+ /// declaration if it exists. It is the responsibility of the caller to
+ /// call [parseVariablesDeclarationRest] to finish parsing the local variable
+ /// declaration. If a local variable declaration is not found then this
+ /// method will return [start].
+ Token parseExpressionStatementOrDeclaration(final Token start,
+ [bool onlyParseVariableDeclarationStart = false]) {
Token token = start;
Token next = token.next;
if (optional('@', next)) {
@@ -5521,36 +5446,67 @@
}
}
- Token beforeType = token;
- TypeInfo typeInfo = computeType(beforeType, false);
- token = typeInfo.skipType(beforeType);
- next = token.next;
+ return parseExpressionStatementOrDeclarationAfterModifiers(
+ token, start, varFinalOrConst, null, onlyParseVariableDeclarationStart);
+ }
- if (next.isIdentifier) {
- if (optional('<', next.next) || optional('(', next.next)) {
- // Found an expression or local function declaration.
- // TODO(danrubel): Process local function declarations.
- return start;
+ /// See [parseExpressionStatementOrDeclaration]
+ Token parseExpressionStatementOrDeclarationAfterModifiers(
+ final Token beforeType, final Token start,
+ [Token varFinalOrConst = null,
+ TypeInfo typeInfo,
+ bool onlyParseVariableDeclarationStart = false]) {
+ typeInfo ??= computeType(beforeType, false);
+ Token token = typeInfo.skipType(beforeType);
+ Token next = token.next;
+
+ if (!onlyParseVariableDeclarationStart && looksLikeLocalFunction(next)) {
+ // Parse a local function declaration.
+ if (varFinalOrConst != null) {
+ reportRecoverableErrorWithToken(
+ varFinalOrConst, fasta.templateExtraneousModifier);
}
+ if (!optional('@', start.next)) {
+ listener.beginMetadataStar(start.next);
+ listener.endMetadataStar(0);
+ }
+ Token beforeFormals = parseTypeVariablesOpt(next);
+ listener.beginLocalFunctionDeclaration(start.next);
+ token = typeInfo.parseType(beforeType, this);
+ next = token.next;
+ return parseNamedFunctionRest(token, start.next, beforeFormals, false);
}
if (token == start) {
// If no annotation, modifier, or type, and this is not a local function
- // then return without consuming any tokens because this is not
- // a local declaration.
- return start;
+ // then this must be an expression statement.
+ if (onlyParseVariableDeclarationStart) {
+ return start;
+ } else {
+ return parseExpressionStatement(start);
+ }
+ }
+ if (next.type.isBuiltIn &&
+ beforeType == start &&
+ typeInfo.couldBeExpression) {
+ // Detect expressions such as identifier `as` identifier
+ // and treat those as expressions.
+ int kind = next.next.kind;
+ if (EQ_TOKEN != kind && SEMICOLON_TOKEN != kind && COMMA_TOKEN != kind) {
+ if (onlyParseVariableDeclarationStart) {
+ if (!optional('in', next.next)) {
+ return start;
+ }
+ } else {
+ return parseExpressionStatement(start);
+ }
+ }
}
- if (!optional('@', start.next)) {
- listener.beginMetadataStar(start.next);
- listener.endMetadataStar(0);
- }
- token = typeInfo.parseType(beforeType, this);
- next = token.next;
-
- // If there is not an identifier, then allow ensureIdentifier to report an
- // error and don't report errors here.
if (next.isIdentifier) {
+ // Only report these errors if there is an identifier. If there is not an
+ // identifier, then allow ensureIdentifier to report an error
+ // and don't report errors here.
if (varFinalOrConst == null) {
if (typeInfo == noTypeInfo) {
reportRecoverableError(next, fasta.messageMissingConstFinalVarOrType);
@@ -5562,58 +5518,19 @@
}
}
+ if (!optional('@', start.next)) {
+ listener.beginMetadataStar(start.next);
+ listener.endMetadataStar(0);
+ }
+ token = typeInfo.parseType(beforeType, this);
+ next = token.next;
listener.beginVariablesDeclaration(next, varFinalOrConst);
+ if (!onlyParseVariableDeclarationStart) {
+ token = parseVariablesDeclarationRest(token, true);
+ }
return token;
}
- Token parseVariablesDeclaration(Token token) {
- token = parseMetadataStar(token);
- Token next = token.next;
-
- Token varFinalOrConst;
- if (isModifier(next)) {
- if (optional('var', next)) {
- varFinalOrConst = token = token.next;
- next = token.next;
- } else if (optional('final', next) || optional('const', next)) {
- varFinalOrConst = token = token.next;
- next = token.next;
- }
-
- if (isModifier(next)) {
- // Recovery
- ModifierRecoveryContext2 modifierContext =
- new ModifierRecoveryContext2(this);
- token = modifierContext.parseVariableDeclarationModifiers(token,
- varFinalOrConst: varFinalOrConst);
-
- varFinalOrConst = modifierContext.varFinalOrConst;
- modifierContext = null;
- }
- }
-
- TypeInfo typeInfo = computeType(token, false);
- if (varFinalOrConst == null) {
- if (typeInfo == noTypeInfo) {
- // If there is no modifer, no type, and no identifier
- // then let parseVariablesDeclarationMaybeSemicolonRest
- // report a missing identifier rather than reporting two errors.
- if (token.next.isIdentifier) {
- reportRecoverableError(
- token.next, fasta.messageMissingConstFinalVarOrType);
- }
- }
- } else if (optional('var', varFinalOrConst)) {
- if (typeInfo != noTypeInfo) {
- reportRecoverableError(token.next, fasta.messageTypeAfterVar);
- }
- }
- token = typeInfo.parseType(token, this);
-
- listener.beginVariablesDeclaration(token.next, varFinalOrConst);
- return parseVariablesDeclarationRest(token, true);
- }
-
Token parseVariablesDeclarationRest(Token token, bool endWithSemicolon) {
int count = 1;
token = parseOptionallyInitializedIdentifier(token);
@@ -5702,14 +5619,22 @@
Token closeParen =
semicolon.setNext(new SyntheticToken(TokenType.CLOSE_PAREN, offset));
openParen.endGroup = closeParen;
-
closeParen.setNext(leftParenthesis);
+ insertBlock(closeParen);
+
leftParenthesis = openParen;
}
token = leftParenthesis;
- token = parseLocalDeclarationStartOpt(token);
+ // Pass `true` so that the [parseExpressionStatementOrDeclaration] only
+ // parses the metadata, modifiers, and type of a local variable
+ // declaration if it exists. This enables capturing [beforeIdentifier]
+ // for later error reporting.
+ token = parseExpressionStatementOrDeclaration(token, true);
Token beforeIdentifier = token;
+
+ // Parse the remainder of the local variable declaration
+ // or an expression if no local variable declaration was found.
if (token != leftParenthesis) {
token = parseVariablesDeclarationRest(token, false);
} else if (optional(';', token.next)) {
@@ -5721,6 +5646,7 @@
Token next = token.next;
if (!optional('in', next)) {
if (optional(':', next)) {
+ // Recovery
reportRecoverableError(next, fasta.messageColonInPlaceOfIn);
// Fall through to process `for ( ... in ... )`
} else {
@@ -5858,12 +5784,19 @@
listener.beginDoWhileStatementBody(doToken.next);
LoopState savedLoopState = loopState;
loopState = LoopState.InsideLoop;
- token = parseStatement(doToken).next;
+ token = parseStatement(doToken);
loopState = savedLoopState;
listener.endDoWhileStatementBody(token);
- Token whileToken = token;
- expect('while', token);
- token = parseParenthesizedExpression(token);
+ Token whileToken = token.next;
+ if (!optional('while', whileToken)) {
+ reportRecoverableError(
+ whileToken, fasta.templateExpectedButGot.withArguments('while'));
+ whileToken = rewriter
+ .insertTokenAfter(token,
+ new SyntheticKeywordToken(Keyword.WHILE, whileToken.charOffset))
+ .next;
+ }
+ token = parseParenthesizedExpression(whileToken);
token = ensureSemicolon(token);
listener.endDoWhileStatement(doToken, whileToken, token);
return token;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
index 165353e..a825ae5 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_continuation.dart
@@ -31,14 +31,6 @@
/// should parse the following as a type unless it is followed by `=`.
Typedef,
- /// Indicates that what follows is either a local declaration or an
- /// expression.
- ExpressionStatementOrDeclaration,
-
- /// Indicates that the keyword `const` has just been seen, and what follows
- /// may be a local variable declaration or an expression.
- ExpressionStatementOrConstDeclaration,
-
/// Indicates that the parser is parsing an expression and has just seen an
/// identifier.
SendOrFunctionLiteral,
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index d282fcb..704ca9b9 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -33,6 +33,12 @@
/// [TypeInfo] provides information that has collected by [computeType]
/// about a particular type reference.
abstract class TypeInfo {
+ /// Return `true` if the tokens comprising the type represented by the
+ /// receiver could be interpreted as a valid standalone expression.
+ /// For example, `A` or `A.b` could be interpreted as a type references
+ /// or as expressions, while `A<T>` only looks like a type reference.
+ bool get couldBeExpression;
+
/// Call this function when it's known that the token after [token] is a type.
/// This function will call the appropriate event methods on the [Parser]'s
/// listener to handle the type. This may modify the token stream
@@ -197,6 +203,9 @@
ComplexTypeInfo(Token beforeStart) : this.start = beforeStart.next;
@override
+ bool get couldBeExpression => false;
+
+ @override
Token parseType(Token token, Parser parser) {
assert(identical(token.next, start));
Listener listener = parser.listener;
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 58b67bc..811672b 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -21,6 +21,9 @@
const NoTypeInfo();
@override
+ bool get couldBeExpression => false;
+
+ @override
Token parseType(Token token, Parser parser) {
parser.listener.handleNoType(token);
return token;
@@ -37,6 +40,9 @@
const PrefixedTypeInfo();
@override
+ bool get couldBeExpression => true;
+
+ @override
Token parseType(Token token, Parser parser) {
Token start = token = token.next;
assert(token.isKeywordOrIdentifier);
@@ -68,6 +74,9 @@
const SimpleTypeArgumentsInfo();
@override
+ bool get couldBeExpression => false;
+
+ @override
Token parseType(Token token, Parser parser) {
Token start = token = token.next;
assert(token.isKeywordOrIdentifier);
@@ -100,6 +109,9 @@
const SimpleTypeInfo();
@override
+ bool get couldBeExpression => true;
+
+ @override
Token parseType(Token token, Parser parser) {
token = token.next;
assert(token.isKeywordOrIdentifier);
@@ -121,6 +133,9 @@
const VoidTypeInfo();
@override
+ bool get couldBeExpression => false;
+
+ @override
Token parseType(Token token, Parser parser) {
token = token.next;
parser.listener.handleVoidKeyword(token);
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 3b901fb..445b4a5 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -219,7 +219,8 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
debugEvent("Fields");
buildFields(count, beginToken, false);
}
@@ -246,7 +247,8 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
debugEvent("TopLevelFields");
buildFields(count, beginToken, true);
}
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 95f7e87..1637a9f 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -42,7 +42,9 @@
Var,
abstractMask,
constMask,
- externalMask;
+ covariantMask,
+ externalMask,
+ staticMask;
import '../operator.dart'
show
@@ -362,23 +364,26 @@
}
@override
- void beginClassDeclaration(Token begin, Token name) {
+ void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
debugEvent("beginNamedMixinApplication");
List<TypeVariableBuilder> typeVariables = pop();
push(typeVariables ?? NullValue.TypeVariables);
library.currentDeclaration
..name = name.lexeme
..typeVariables = typeVariables;
+ push(abstractToken != null ? abstractMask : 0);
}
@override
- void beginNamedMixinApplication(Token beginToken, Token name) {
+ void beginNamedMixinApplication(
+ Token begin, Token abstractToken, Token name) {
debugEvent("beginNamedMixinApplication");
List<TypeVariableBuilder> typeVariables = pop();
push(typeVariables ?? NullValue.TypeVariables);
library.currentDeclaration
..name = name.lexeme
..typeVariables = typeVariables;
+ push(abstractToken != null ? abstractMask : 0);
}
@override
@@ -408,13 +413,13 @@
List<TypeBuilder> interfaces = pop(NullValue.TypeBuilderList);
int supertypeOffset = pop();
TypeBuilder supertype = pop();
+ int modifiers = pop();
List<TypeVariableBuilder> typeVariables = pop();
int charOffset = pop();
String name = pop();
if (typeVariables != null && supertype is MixinApplicationBuilder) {
supertype.typeVariables = typeVariables;
}
- int modifiers = Modifier.validate(pop());
List<MetadataBuilder> metadata = pop();
library.addClass(
@@ -713,10 +718,10 @@
String documentationComment = getDocumentationComment(beginToken);
List<TypeBuilder> interfaces = popIfNotNull(implementsKeyword);
TypeBuilder mixinApplication = pop();
+ int modifiers = pop();
List<TypeVariableBuilder> typeVariables = pop();
int charOffset = pop();
String name = pop();
- int modifiers = Modifier.validate(pop());
List<MetadataBuilder> metadata = pop();
library.addNamedMixinApplication(documentationComment, metadata, name,
typeVariables, modifiers, mixinApplication, interfaces, charOffset);
@@ -971,11 +976,14 @@
}
@override
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ void endTopLevelFields(Token staticToken, Token covariantToken,
+ Token varFinalOrConst, int count, Token beginToken, Token endToken) {
debugEvent("endTopLevelFields");
List fieldsInfo = popList(count * 4);
TypeBuilder type = pop();
- int modifiers = Modifier.validate(pop());
+ int modifiers = (staticToken != null ? staticMask : 0) |
+ (covariantToken != null ? covariantMask : 0) |
+ Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
List<MetadataBuilder> metadata = pop();
String documentationComment = getDocumentationComment(beginToken);
library.addFields(
@@ -984,11 +992,14 @@
}
@override
- void endFields(int count, Token beginToken, Token endToken) {
+ void endFields(Token staticToken, Token covariantToken, Token varFinalOrConst,
+ int count, Token beginToken, Token endToken) {
debugEvent("Fields");
List fieldsInfo = popList(count * 4);
TypeBuilder type = pop();
- int modifiers = Modifier.validate(pop());
+ int modifiers = (staticToken != null ? staticMask : 0) |
+ (covariantToken != null ? covariantMask : 0) |
+ Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
List<MetadataBuilder> metadata = pop();
String documentationComment = getDocumentationComment(beginToken);
library.addFields(
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 2980d2f..79e0664 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
@@ -244,6 +244,9 @@
const String prefix = "dart.library.";
if (!dottedName.startsWith(prefix)) return "";
dottedName = dottedName.substring(prefix.length);
+ String override =
+ loader.target.uriTranslator.environmentOverrideFor(dottedName);
+ if (override != null) return override;
LibraryBuilder imported =
loader.builders[new Uri(scheme: "dart", path: dottedName)];
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 79c88ae..e15d994 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -561,7 +561,9 @@
Set<Library> libraries = new Set<Library>();
List<Library> workList = <Library>[];
builders.forEach((Uri uri, LibraryBuilder library) {
- if (!library.isPart && !library.isPatch) {
+ if (!library.isPart &&
+ !library.isPatch &&
+ (library.loader == this || library.fileUri.scheme == "dart")) {
if (libraries.add(library.target)) {
workList.add(library.target);
}
@@ -630,6 +632,15 @@
ticker.logMs("Checked overrides");
}
+ void addNoSuchMethodForwarders(List<SourceClassBuilder> sourceClasses) {
+ for (SourceClassBuilder builder in sourceClasses) {
+ if (builder.library.loader == this) {
+ builder.addNoSuchMethodForwarders(hierarchy);
+ }
+ }
+ ticker.logMs("Added noSuchMethod forwarders");
+ }
+
void createTypeInferenceEngine() {
typeInferenceEngine =
new ShadowTypeInferenceEngine(instrumentation, target.strongMode);
@@ -800,4 +811,9 @@
new InstrumentationValueLiteral(context.code.name));
}
}
+
+ void releaseAncillaryResources() {
+ hierarchy = null;
+ typeInferenceEngine = null;
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index b43d976..b2e71fc 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -497,7 +497,7 @@
actualType = getCalleeType(callMember, actualType);
var conditional = new ConditionalExpression(nullCheck,
new NullLiteral()..fileOffset = fileOffset, tearOff, actualType);
- var let = new Let(t, conditional);
+ var let = new Let(t, conditional)..fileOffset = fileOffset;
parent?.replaceChild(expression, let);
expression = let;
}
diff --git a/pkg/front_end/lib/src/fasta/uri_translator.dart b/pkg/front_end/lib/src/fasta/uri_translator.dart
index d2f32ff..135ad73 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator.dart
@@ -24,5 +24,12 @@
///
/// Note: this only translates the URI, there is no guarantee that the
/// corresponding file exists in the file system.
- Uri translate(Uri uri);
+ ///
+ /// If [reportMessage] is true a message will be reported via
+ /// [CompilerContext.current].
+ Uri translate(Uri uri, [bool reportMessage = true]);
+
+ /// Return the value of `dart.library.name`, if it was overriden in the
+ /// library specification file, otherwise return null.
+ String environmentOverrideFor(String libraryName);
}
diff --git a/pkg/front_end/lib/src/fasta/uri_translator_impl.dart b/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
index 9d31710..5c52e50 100644
--- a/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/uri_translator_impl.dart
@@ -37,12 +37,18 @@
// TODO(sigmund, ahe): consider expanding this API to include an error
// callback, so we can provide an error location when one is available. For
// example, if the error occurs in an `import`.
- Uri translate(Uri uri) {
+ Uri translate(Uri uri, [bool reportMessage = true]) {
if (uri.scheme == "dart") return _translateDartUri(uri);
- if (uri.scheme == "package") return _translatePackageUri(uri);
+ if (uri.scheme == "package") {
+ return _translatePackageUri(uri, reportMessage);
+ }
return null;
}
+ @override
+ String environmentOverrideFor(String libraryName) =>
+ dartLibraries.environmentOverrideFor(libraryName);
+
/// Return the file URI that corresponds to the given `dart` URI, or `null`
/// if there is no corresponding Dart library registered.
Uri _translateDartUri(Uri uri) {
@@ -53,16 +59,21 @@
/// Return the file URI that corresponds to the given `package` URI, or
/// `null` if the `package` [uri] format is invalid, or there is no
/// corresponding package registered.
- Uri _translatePackageUri(Uri uri) {
+ Uri _translatePackageUri(Uri uri, bool reportMessage) {
try {
// TODO(sigmund): once we remove the `parse` API, we can ensure that
// packages will never be null and get rid of `?` below.
- return packages?.resolve(uri, notFound: _packageUriNotFound);
+ return packages?.resolve(uri,
+ notFound: reportMessage
+ ? _packageUriNotFound
+ : _packageUriNotFoundNoReport);
} on ArgumentError catch (e) {
// TODO(sigmund): catch a more precise error when
// https://github.com/dart-lang/package_config/issues/40 is fixed.
- CompilerContext.current.reportWithoutLocation(
- templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error);
+ if (reportMessage) {
+ CompilerContext.current.reportWithoutLocation(
+ templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error);
+ }
return null;
}
}
@@ -76,4 +87,8 @@
// compiler.
return null;
}
+
+ static Uri _packageUriNotFoundNoReport(Uri uri) {
+ return null;
+ }
}
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index c5970959..e4a0be5 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -9,7 +9,7 @@
charcode: '^1.1.1'
convert: '^2.0.1'
crypto: '^2.0.2'
- kernel: 0.3.0-alpha.10
+ kernel: 0.3.0-alpha.11
meta: '^1.1.1'
package_config: '^1.0.1'
path: '^1.3.9'
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 9486a3f..4bbac1c 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -22,6 +22,7 @@
TypeInfo typeInfo = noTypeInfo;
Token start = scanString('before ;').tokens;
Token expectedEnd = start;
+ expect(typeInfo.couldBeExpression, isFalse);
expect(typeInfo.skipType(start), expectedEnd);
TypeInfoListener listener = new TypeInfoListener();
@@ -34,6 +35,7 @@
Token start = scanString('before void ;').tokens;
Token expectedEnd = start.next;
expect(typeInfo.skipType(start), expectedEnd);
+ expect(typeInfo.couldBeExpression, isFalse);
TypeInfoListener listener = new TypeInfoListener();
expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -45,6 +47,7 @@
Token start = scanString('before C.a ;').tokens;
Token expectedEnd = start.next.next.next;
expect(typeInfo.skipType(start), expectedEnd);
+ expect(typeInfo.couldBeExpression, isTrue);
TypeInfoListener listener = new TypeInfoListener();
expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -62,6 +65,7 @@
Token start = scanString('before C ;').tokens;
Token expectedEnd = start.next;
expect(typeInfo.skipType(start), expectedEnd);
+ expect(typeInfo.couldBeExpression, isTrue);
TypeInfoListener listener = new TypeInfoListener();
expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -77,6 +81,7 @@
Token start = scanString('before C<T> ;').tokens;
Token expectedEnd = start.next.next.next.next;
expect(typeInfo.skipType(start), expectedEnd);
+ expect(typeInfo.couldBeExpression, isFalse);
TypeInfoListener listener = new TypeInfoListener();
expect(typeInfo.parseType(start, new Parser(listener)), expectedEnd);
@@ -590,6 +595,7 @@
TypeInfoListener listener = new TypeInfoListener();
Parser parser = new Parser(listener);
expect(typeInfo.start, start.next, reason: source);
+ expect(typeInfo.couldBeExpression, isFalse);
expectEnd(expectedAfter, typeInfo.skipType(start));
expectEnd(expectedAfter, typeInfo.parseType(start, parser));
if (expectedCalls != null) {
diff --git a/pkg/front_end/test/incremental_bulk_compiler_full.dart b/pkg/front_end/test/incremental_bulk_compiler_full.dart
new file mode 100644
index 0000000..6f4e489
--- /dev/null
+++ b/pkg/front_end/test/incremental_bulk_compiler_full.dart
@@ -0,0 +1,155 @@
+// 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.
+
+import 'dart:async' show Future;
+
+import 'package:expect/expect.dart' show Expect;
+
+import 'package:front_end/src/api_prototype/compiler_options.dart'
+ show CompilerOptions;
+
+import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
+ show IncrementalKernelGenerator;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+ show computePlatformBinariesLocation;
+
+import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+ show IncrementalCompiler;
+
+import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+import 'package:kernel/kernel.dart' show Component, Library, Reference;
+
+import 'package:kernel/text/ast_to_text.dart'
+ show globalDebuggingNames, NameSystem;
+
+import 'package:testing/testing.dart'
+ show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+main([List<String> arguments = const []]) =>
+ runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new Context();
+}
+
+class Context extends ChainContext {
+ final List<Step> steps = const <Step>[
+ const RunTest(),
+ ];
+
+ // Override special handling of negative tests.
+ @override
+ Result processTestResult(
+ TestDescription description, Result result, bool last) {
+ return result;
+ }
+
+ IncrementalCompiler compiler;
+}
+
+CompilerOptions getOptions(bool strong) {
+ final Uri sdkRoot = computePlatformBinariesLocation();
+ var options = new CompilerOptions()
+ ..sdkRoot = sdkRoot
+ ..librariesSpecificationUri = Uri.base.resolve("sdk/lib/libraries.json")
+ ..onProblem = (LocatedMessage message, Severity severity, String formatted,
+ int line, int column) {
+ // ignore
+ }
+ ..strongMode = strong;
+ if (strong) {
+ options.sdkSummary =
+ computePlatformBinariesLocation().resolve("vm_platform_strong.dill");
+ } else {
+ options.sdkSummary =
+ computePlatformBinariesLocation().resolve("vm_platform.dill");
+ }
+ return options;
+}
+
+class RunTest extends Step<TestDescription, TestDescription, Context> {
+ const RunTest();
+
+ String get name => "run test";
+
+ Future<Result<TestDescription>> run(
+ TestDescription description, Context context) async {
+ Uri uri = description.uri;
+
+ // "One shot compile"
+ bool oneShotFailed = false;
+ List<int> oneShotSerialized;
+ try {
+ IncrementalCompiler compiler =
+ new IncrementalKernelGenerator(getOptions(true), uri);
+ oneShotSerialized = postProcess(await compiler.computeDelta());
+ } catch (e) {
+ oneShotFailed = true;
+ }
+
+ // Bulk
+ bool bulkFailed = false;
+ List<int> bulkSerialized;
+ try {
+ globalDebuggingNames = new NameSystem();
+ if (context.compiler == null) {
+ context.compiler =
+ new IncrementalKernelGenerator(getOptions(true), uri);
+ }
+ Component bulkCompiledComponent = await context.compiler
+ .computeDelta(entryPoint: uri, fullComponent: true);
+ bulkSerialized = postProcess(bulkCompiledComponent);
+ } catch (e) {
+ bulkFailed = true;
+ }
+
+ if (bulkFailed || oneShotFailed) {
+ if (bulkFailed != oneShotFailed) {
+ throw "Bulk-compiler failed: $bulkFailed; "
+ "one-shot failed: $oneShotFailed";
+ }
+ } else {
+ checkIsEqual(oneShotSerialized, bulkSerialized);
+ }
+
+ return pass(description);
+ }
+
+ List<int> postProcess(Component c) {
+ c.libraries.sort((l1, l2) {
+ return l1.fileUri.toString().compareTo(l2.fileUri.toString());
+ });
+
+ c.computeCanonicalNames();
+ for (Library library in c.libraries) {
+ library.additionalExports.sort((Reference r1, Reference r2) {
+ return r1.canonicalName
+ .toString()
+ .compareTo(r2.canonicalName.toString());
+ });
+ }
+
+ return serializeComponent(c);
+ }
+
+ void checkIsEqual(List<int> a, List<int> b) {
+ int length = a.length;
+ if (b.length < length) {
+ length = b.length;
+ }
+ for (int i = 0; i < length; ++i) {
+ if (a[i] != b[i]) {
+ Expect.fail("Data differs at byte ${i+1}.");
+ }
+ }
+ Expect.equals(a.length, b.length);
+ }
+}
diff --git a/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart b/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart
new file mode 100644
index 0000000..5399635
--- /dev/null
+++ b/pkg/front_end/test/incremental_bulk_compiler_smoke_test.dart
@@ -0,0 +1,17 @@
+// 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.
+
+import 'dart:async' show Future;
+
+import 'package:testing/testing.dart' show Chain, runMe;
+
+import 'incremental_bulk_compiler_full.dart' show Context;
+
+main([List<String> arguments = const []]) =>
+ runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new Context();
+}
diff --git a/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
new file mode 100644
index 0000000..50cedd6
--- /dev/null
+++ b/pkg/front_end/test/incremental_dart2js_load_from_dill_test.dart
@@ -0,0 +1,70 @@
+// 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.
+
+import 'dart:io' show Directory, File;
+
+import 'package:expect/expect.dart' show Expect;
+
+import 'incremental_load_from_dill_test.dart'
+ show normalCompile, initializedCompile, checkIsEqual;
+
+Directory outDir;
+
+main() async {
+ outDir =
+ Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
+ try {
+ await testDart2jsCompile();
+ print("----");
+ } finally {
+ outDir.deleteSync(recursive: true);
+ }
+}
+
+void testDart2jsCompile() async {
+ final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
+ final Uri invalidateUri = Uri.parse("package:compiler/src/filenames.dart");
+ Uri normalDill = outDir.uri.resolve("dart2js.full.dill");
+ Uri fullDillFromInitialized =
+ outDir.uri.resolve("dart2js.full_from_initialized.dill");
+ Uri nonexisting = outDir.uri.resolve("dart2js.nonexisting.dill");
+ Uri nonLoadable = outDir.uri.resolve("dart2js.nonloadable.dill");
+
+ // Compile dart2js without initializing from dill.
+ Stopwatch stopwatch = new Stopwatch()..start();
+ await normalCompile(dart2jsUrl, normalDill);
+ print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
+
+ // Create a file that cannot be (fully) loaded as a dill file.
+ List<int> corruptData = new File.fromUri(normalDill).readAsBytesSync();
+ for (int i = 10 * (corruptData.length ~/ 16);
+ i < 15 * (corruptData.length ~/ 16);
+ ++i) {
+ corruptData[i] = 42;
+ }
+ new File.fromUri(nonLoadable).writeAsBytesSync(corruptData);
+
+ // Compile dart2js, initializing from the just-compiled dill,
+ // a nonexisting file and a dill file that isn't valid.
+ for (List<Object> initializationData in [
+ [normalDill, true],
+ [nonexisting, false],
+ // [nonLoadable, false] // disabled for now
+ ]) {
+ Uri initializeWith = initializationData[0];
+ bool initializeExpect = initializationData[1];
+ stopwatch.reset();
+ bool initializeResult = await initializedCompile(
+ dart2jsUrl, fullDillFromInitialized, initializeWith, [invalidateUri]);
+ Expect.equals(initializeExpect, initializeResult);
+ print("Initialized compile(s) from ${initializeWith.pathSegments.last} "
+ "took ${stopwatch.elapsedMilliseconds} ms");
+
+ // Compare the two files.
+ List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
+ List<int> initializedDillData =
+ new File.fromUri(fullDillFromInitialized).readAsBytesSync();
+ checkIsEqual(normalDillData, initializedDillData);
+ }
+}
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 5ba4f3b..93bd46b 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -3,411 +3,294 @@
// BSD-style license that can be found in the LICENSE file.
import 'dart:async' show Future;
+
import 'dart:io' show Directory, File;
import 'package:expect/expect.dart' show Expect;
+
+import 'package:front_end/src/base/processed_options.dart'
+ show ProcessedOptions;
+
+import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;
+
import 'package:front_end/src/api_prototype/compiler_options.dart'
show CompilerOptions;
-import 'package:front_end/src/api_prototype/incremental_kernel_generator.dart'
- show IncrementalKernelGenerator;
-import 'package:front_end/src/compute_platform_binaries_location.dart'
- show computePlatformBinariesLocation;
-import 'package:front_end/src/fasta/incremental_compiler.dart'
- show IncrementalCompiler;
-import 'package:front_end/src/fasta/kernel/utils.dart'
- show writeComponentToFile, serializeComponent;
+
import "package:front_end/src/api_prototype/memory_file_system.dart"
show MemoryFileSystem;
-import 'package:kernel/kernel.dart'
- show Class, EmptyStatement, Library, Procedure, Component;
+
+import 'package:front_end/src/compute_platform_binaries_location.dart'
+ show computePlatformBinariesLocation;
import 'package:front_end/src/fasta/fasta_codes.dart' show LocatedMessage;
+import 'package:front_end/src/fasta/incremental_compiler.dart'
+ show IncrementalCompiler;
+
+import 'package:front_end/src/fasta/kernel/utils.dart'
+ show writeComponentToFile, serializeComponent;
+
import 'package:front_end/src/fasta/severity.dart' show Severity;
-Directory outDir;
+import 'package:kernel/kernel.dart'
+ show Class, EmptyStatement, Library, Procedure, Component;
-main() async {
- await runPassingTest(testDart2jsCompile);
- await runPassingTest(testDisappearingLibrary);
- await runPassingTest(testDeferredLibrary);
- await runPassingTest(testStrongModeMixins);
- await runFailingTest(
- testStrongModeMixins2,
- "testStrongModeMixins2_a.dart: Error: "
- "The parameter 'value' of the method 'A::child' has type");
- await runPassingTest(testInvalidateExportOfMain);
- await runPassingTest(testInvalidatePart);
+import "package:testing/testing.dart"
+ show Chain, ChainContext, Result, Step, TestDescription, runMe;
+
+import "package:yaml/yaml.dart" show YamlMap, loadYamlNode;
+
+main([List<String> arguments = const []]) =>
+ runMe(arguments, createContext, "../testing.json");
+
+Future<Context> createContext(
+ Chain suite, Map<String, String> environment) async {
+ return new Context();
}
-void runFailingTest(dynamic test, String expectContains) async {
- try {
- await runPassingTest(test);
- throw "Expected this to fail.";
- } catch (e) {
- if (e.toString().contains(expectContains)) {
- print("got expected error as this test is currently failing");
- } else {
- rethrow;
+class Context extends ChainContext {
+ final List<Step> steps = const <Step>[
+ const ReadTest(),
+ const RunCompilations(),
+ ];
+
+ @override
+ void cleanUp(TestDescription description, Result result) {
+ cleanupHelper?.outDir?.deleteSync(recursive: true);
+ }
+
+ TestData cleanupHelper;
+}
+
+class TestData {
+ YamlMap map;
+ Directory outDir;
+}
+
+class ReadTest extends Step<TestDescription, TestData, Context> {
+ const ReadTest();
+
+ String get name => "read test";
+
+ Future<Result<TestData>> run(
+ TestDescription description, Context context) async {
+ Uri uri = description.uri;
+ String contents = await new File.fromUri(uri).readAsString();
+ TestData data = new TestData();
+ data.map = loadYamlNode(contents, sourceUrl: uri);
+ data.outDir =
+ Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
+ context.cleanupHelper = data;
+ return pass(data);
+ }
+}
+
+class RunCompilations extends Step<TestData, TestData, Context> {
+ const RunCompilations();
+
+ String get name => "run compilations";
+
+ Future<Result<TestData>> run(TestData data, Context context) async {
+ YamlMap map = data.map;
+ switch (map["type"]) {
+ case "simple":
+ await simpleTest(
+ map["sources"],
+ map["name"],
+ map["entry"],
+ map["strong"],
+ map["invalidate"],
+ data.outDir,
+ );
+ break;
+ case "newworld":
+ await newWorldTest(
+ map["strong"],
+ map["worlds"],
+ );
+ break;
+ default:
+ throw "Unexpected type: ${map['type']}";
}
+ return pass(data);
}
}
-void runPassingTest(dynamic test) async {
- outDir =
- Directory.systemTemp.createTempSync("incremental_load_from_dill_test");
- try {
- await test();
- print("----");
- } finally {
- outDir.deleteSync(recursive: true);
- }
-}
-
-/// Invalidate a part file.
-void testInvalidatePart() async {
- final Uri a = outDir.uri.resolve("testInvalidatePart_a.dart");
- final Uri b = outDir.uri.resolve("testInvalidatePart_b.dart");
- final Uri c = outDir.uri.resolve("testInvalidatePart_c.dart");
- final Uri d = outDir.uri.resolve("testInvalidatePart_d.dart");
-
- Uri output = outDir.uri.resolve("testInvalidatePart_full.dill");
- Uri bootstrappedOutput =
- outDir.uri.resolve("testInvalidatePart_full_from_bootstrap.dill");
-
- new File.fromUri(a).writeAsStringSync("""
- library a;
- import 'testInvalidatePart_c.dart';
- part 'testInvalidatePart_b.dart';
- """);
- new File.fromUri(b).writeAsStringSync("""
- part of a;
- b() { print("b"); }
- """);
- new File.fromUri(c).writeAsStringSync("""
- library c;
- part 'testInvalidatePart_d.dart';
- """);
- new File.fromUri(d).writeAsStringSync("""
- part of c;
- d() { print("d"); }
- """);
-
- Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(a, output, options: getOptions(true));
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
- stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- a, bootstrappedOutput, output, [b],
- performSizeTests: true, options: getOptions(true));
- print("Bootstrapped compile(s) from ${output.pathSegments.last} "
- "took ${stopwatch.elapsedMilliseconds} ms");
- Expect.isTrue(bootstrapResult);
-
- // Compare the two files.
- List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedOutput).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Invalidate the entrypoint which just exports another file (which has main).
-void testInvalidateExportOfMain() async {
- final Uri a = outDir.uri.resolve("testInvalidateExportOfMain_a.dart");
- final Uri b = outDir.uri.resolve("testInvalidateExportOfMain_b.dart");
-
- Uri output = outDir.uri.resolve("testInvalidateExportOfMain_full.dill");
- Uri bootstrappedOutput =
- outDir.uri.resolve("testInvalidateExportOfMain_full_from_bootstrap.dill");
-
- new File.fromUri(a).writeAsStringSync("""
- export 'testInvalidateExportOfMain_b.dart';
- """);
- new File.fromUri(b).writeAsStringSync("""
- main() { print("hello"); }
- """);
-
- Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(a, output, options: getOptions(true));
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
- stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- a, bootstrappedOutput, output, [a],
- performSizeTests: true, options: getOptions(true));
- print("Bootstrapped compile(s) from ${output.pathSegments.last} "
- "took ${stopwatch.elapsedMilliseconds} ms");
- Expect.isTrue(bootstrapResult);
-
- // Compare the two files.
- List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedOutput).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Compile in strong mode. Use mixins.
-void testStrongModeMixins2() async {
- final Uri a = outDir.uri.resolve("testStrongModeMixins2_a.dart");
- final Uri b = outDir.uri.resolve("testStrongModeMixins2_b.dart");
-
- Uri output = outDir.uri.resolve("testStrongModeMixins2_full.dill");
- Uri bootstrappedOutput =
- outDir.uri.resolve("testStrongModeMixins2_full_from_bootstrap.dill");
-
- new File.fromUri(a).writeAsStringSync("""
- import 'testStrongModeMixins2_b.dart';
- class A extends Object with B<C>, D<Object> {}
- """);
- new File.fromUri(b).writeAsStringSync("""
- abstract class B<ChildType extends Object> extends Object {
- ChildType get child => null;
- set child(ChildType value) {}
+void simpleTest(
+ Map<String, String> sourceFiles,
+ String testName,
+ String entryPoint,
+ bool strong,
+ List<String> invalidate,
+ Directory outDir) async {
+ Uri entryPointUri;
+ Set<String> invalidateFilenames = invalidate?.toSet() ?? new Set<String>();
+ List<Uri> invalidateUris = <Uri>[];
+ Uri packagesUri;
+ for (String filename in sourceFiles.keys) {
+ Uri uri = outDir.uri.resolve(filename);
+ if (filename == entryPoint) entryPointUri = uri;
+ if (invalidateFilenames.contains(filename)) invalidateUris.add(uri);
+ String source = sourceFiles[filename];
+ if (filename == ".packages") {
+ source = substituteVariables(source, outDir.uri);
+ packagesUri = uri;
}
+ new File.fromUri(uri).writeAsStringSync(source);
+ }
- class C extends Object {}
-
- abstract class D<T extends Object> extends Object with B<T> {}
- """);
+ Uri output = outDir.uri.resolve("${testName}_full.dill");
+ Uri initializedOutput =
+ outDir.uri.resolve("${testName}_full_from_initialized.dill");
Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(a, output, options: getOptions(true));
+ CompilerOptions options = getOptions(strong);
+ if (packagesUri != null) {
+ options.packagesFileUri = packagesUri;
+ }
+ await normalCompile(entryPointUri, output, options: options);
print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- a, bootstrappedOutput, output, [a],
- performSizeTests: true, options: getOptions(true));
- print("Bootstrapped compile(s) from ${output.pathSegments.last} "
+ bool initializedResult = await initializedCompile(
+ entryPointUri, initializedOutput, output, invalidateUris,
+ options: getOptions(strong));
+ print("Initialized compile(s) from ${output.pathSegments.last} "
"took ${stopwatch.elapsedMilliseconds} ms");
- Expect.isTrue(bootstrapResult);
+ Expect.isTrue(initializedResult);
// Compare the two files.
List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedOutput).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
+ List<int> initializedDillData =
+ new File.fromUri(initializedOutput).readAsBytesSync();
+ checkIsEqual(normalDillData, initializedDillData);
}
-/// Compile in strong mode. Invalidate a file so type inferrer starts
-/// on something compiled from source and (potentially) goes into
-/// something loaded from dill.
-void testStrongModeMixins() async {
- final Uri a = outDir.uri.resolve("testStrongModeMixins_a.dart");
- final Uri b = outDir.uri.resolve("testStrongModeMixins_b.dart");
-
- Uri output = outDir.uri.resolve("testStrongModeMixins_full.dill");
- Uri bootstrappedOutput =
- outDir.uri.resolve("testStrongModeMixins_full_from_bootstrap.dill");
-
- new File.fromUri(a).writeAsStringSync("""
- import 'testStrongModeMixins_b.dart';
- class A extends Object with B<Object>, C {}
- """);
- new File.fromUri(b).writeAsStringSync("""
- abstract class C<T extends Object> extends Object with B<T> {}
- abstract class B<ChildType extends Object> extends Object {}
- """);
-
- Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(a, output, options: getOptions(true));
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
- stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- a, bootstrappedOutput, output, [a],
- performSizeTests: true, options: getOptions(true));
- print("Bootstrapped compile(s) from ${output.pathSegments.last} "
- "took ${stopwatch.elapsedMilliseconds} ms");
- Expect.isTrue(bootstrapResult);
-
- // Compare the two files.
- List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedOutput).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-/// Test loading from a dill file with a deferred library.
-/// This is done by bootstrapping with no changes.
-void testDeferredLibrary() async {
- final Uri input = outDir.uri.resolve("testDeferredLibrary_main.dart");
- final Uri b = outDir.uri.resolve("testDeferredLibrary_b.dart");
- Uri output = outDir.uri.resolve("testDeferredLibrary_full.dill");
- Uri bootstrappedOutput =
- outDir.uri.resolve("testDeferredLibrary_full_from_bootstrap.dill");
- new File.fromUri(input).writeAsStringSync("""
- import 'testDeferredLibrary_b.dart' deferred as b;
-
- void main() {
- print(b.foo());
- }
- """);
- new File.fromUri(b).writeAsStringSync("""
- String foo() => "hello from foo in b";
- """);
-
- Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(input, output);
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
- stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- input, bootstrappedOutput, output, [],
- performSizeTests: false);
- print("Bootstrapped compile(s) from ${output.pathSegments.last} "
- "took ${stopwatch.elapsedMilliseconds} ms");
- Expect.isTrue(bootstrapResult);
-
- // Compare the two files.
- List<int> normalDillData = new File.fromUri(output).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedOutput).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
-}
-
-void testDart2jsCompile() async {
- final Uri dart2jsUrl = Uri.base.resolve("pkg/compiler/bin/dart2js.dart");
- final Uri invalidateUri = Uri.parse("package:compiler/src/filenames.dart");
- Uri normalDill = outDir.uri.resolve("dart2js.full.dill");
- Uri bootstrappedDill = outDir.uri.resolve("dart2js.bootstrap.dill");
- Uri nonexisting = outDir.uri.resolve("dart2js.nonexisting.dill");
- Uri nonLoadable = outDir.uri.resolve("dart2js.nonloadable.dill");
-
- // Compile dart2js without bootstrapping.
- Stopwatch stopwatch = new Stopwatch()..start();
- await normalCompile(dart2jsUrl, normalDill);
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
-
- // Create a file that cannot be (fully) loaded as a dill file.
- List<int> corruptData = new File.fromUri(normalDill).readAsBytesSync();
- for (int i = 10 * (corruptData.length ~/ 16);
- i < 15 * (corruptData.length ~/ 16);
- ++i) {
- corruptData[i] = 42;
- }
- new File.fromUri(nonLoadable).writeAsBytesSync(corruptData);
-
- // Compile dart2js, bootstrapping from the just-compiled dill,
- // a nonexisting file and a dill file that isn't valid.
- for (List<Object> bootstrapData in [
- [normalDill, true],
- [nonexisting, false],
- // [nonLoadable, false] // disabled for now
- ]) {
- Uri bootstrapWith = bootstrapData[0];
- bool bootstrapExpect = bootstrapData[1];
- stopwatch.reset();
- bool bootstrapResult = await bootstrapCompile(
- dart2jsUrl, bootstrappedDill, bootstrapWith, [invalidateUri]);
- Expect.equals(bootstrapExpect, bootstrapResult);
- print("Bootstrapped compile(s) from ${bootstrapWith.pathSegments.last} "
- "took ${stopwatch.elapsedMilliseconds} ms");
-
- // Compare the two files.
- List<int> normalDillData = new File.fromUri(normalDill).readAsBytesSync();
- List<int> bootstrappedDillData =
- new File.fromUri(bootstrappedDill).readAsBytesSync();
- checkBootstrappedIsEqual(normalDillData, bootstrappedDillData);
- }
-}
-
-void checkBootstrappedIsEqual(
- List<int> normalDillData, List<int> bootstrappedDillData) {
- Expect.equals(normalDillData.length, bootstrappedDillData.length);
- for (int i = 0; i < normalDillData.length; ++i) {
- if (normalDillData[i] != bootstrappedDillData[i]) {
- Expect.fail("Normally compiled and bootstrapped compile differs.");
- }
- }
-}
-
-/// Compile an application with n libraries, then
-/// compile "the same" application, but with m < n libraries,
-/// where (at least one) of the missing libraries are "in the middle"
-/// of the library list --- bootstrapping from the dill with n libarries.
-void testDisappearingLibrary() async {
+void newWorldTest(bool strong, List worlds) async {
+ final Uri sdkRoot = computePlatformBinariesLocation();
final Uri base = Uri.parse("org-dartlang-test:///");
final Uri sdkSummary = base.resolve("vm_platform.dill");
- final Uri main = base.resolve("main.dart");
- final Uri b = base.resolve("b.dart");
- final Uri bootstrap = base.resolve("bootstrapFrom.dill");
- final List<int> sdkSummaryData = await new File.fromUri(
- computePlatformBinariesLocation().resolve("vm_platform.dill"))
- .readAsBytes();
+ final Uri initializeFrom = base.resolve("initializeFrom.dill");
+ Uri platformUri;
+ if (strong) {
+ platformUri = sdkRoot.resolve("vm_platform_strong.dill");
+ } else {
+ platformUri = sdkRoot.resolve("vm_platform.dill");
+ }
+ final List<int> sdkSummaryData =
+ await new File.fromUri(platformUri).readAsBytes();
- List<int> libCount2;
- {
+ List<int> newestWholeComponent;
+ for (var world in worlds) {
MemoryFileSystem fs = new MemoryFileSystem(base);
fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
-
- fs.entityForUri(main).writeAsStringSync("""
- library mainLibrary;
- import "b.dart" as b;
-
- main() {
- b.foo();
+ bool expectInitializeFromDill = false;
+ if (newestWholeComponent != null && newestWholeComponent.isNotEmpty) {
+ fs.entityForUri(initializeFrom).writeAsBytesSync(newestWholeComponent);
+ expectInitializeFromDill = true;
+ }
+ Map<String, String> sourceFiles = world["sources"];
+ Uri packagesUri;
+ for (String filename in sourceFiles.keys) {
+ String data = sourceFiles[filename] ?? "";
+ Uri uri = base.resolve(filename);
+ if (filename == ".packages") {
+ data = substituteVariables(data, base);
+ packagesUri = uri;
}
- """);
+ fs.entityForUri(uri).writeAsStringSync(data);
+ }
- fs.entityForUri(b).writeAsStringSync("""
- library bLibrary;
-
- foo() {
- print("hello from b.dart foo!");
- }
- """);
-
- CompilerOptions options = getOptions(false);
+ CompilerOptions options = getOptions(strong);
options.fileSystem = fs;
options.sdkRoot = null;
options.sdkSummary = sdkSummary;
- IncrementalCompiler compiler =
- new IncrementalKernelGenerator(options, main);
- Stopwatch stopwatch = new Stopwatch()..start();
- var component = await compiler.computeDelta();
- throwOnEmptyMixinBodies(component);
- print("Normal compile took ${stopwatch.elapsedMilliseconds} ms");
- libCount2 = serializeComponent(component);
- if (component.libraries.length != 2) {
- throw "Expected 2 libraries, got ${component.libraries.length}";
+ if (packagesUri != null) {
+ options.packagesFileUri = packagesUri;
}
- if (component.libraries[0].fileUri != main) {
- throw "Expected the first library to have uri $main but was "
- "${component.libraries[0].fileUri}";
- }
- }
+ bool gotError = false;
+ List<String> formattedErrors = <String>[];
+ bool gotWarning = false;
+ List<String> formattedWarnings = <String>[];
- {
- MemoryFileSystem fs = new MemoryFileSystem(base);
- fs.entityForUri(sdkSummary).writeAsBytesSync(sdkSummaryData);
- fs.entityForUri(bootstrap).writeAsBytesSync(libCount2);
- fs.entityForUri(b).writeAsStringSync("""
- library bLibrary;
-
- main() {
- print("hello from b!");
+ options.onProblem = (LocatedMessage message, Severity severity,
+ String formatted, int line, int column) {
+ if (severity == Severity.error) {
+ gotError = true;
+ formattedErrors.add(formatted);
+ } else if (severity == Severity.warning) {
+ gotWarning = true;
+ formattedWarnings.add(formatted);
}
- """);
- CompilerOptions options = getOptions(false);
- options.fileSystem = fs;
- options.sdkRoot = null;
- options.sdkSummary = sdkSummary;
- IncrementalCompiler compiler =
- new IncrementalKernelGenerator(options, b, bootstrap);
- compiler.invalidate(main);
- compiler.invalidate(b);
+ };
+
+ Uri entry = base.resolve(world["entry"]);
+ TestIncrementalCompiler compiler =
+ new TestIncrementalCompiler(options, entry, initializeFrom);
+
+ if (world["invalidate"] != null) {
+ for (var filename in world["invalidate"]) {
+ compiler.invalidate(base.resolve(filename));
+ }
+ }
+
Stopwatch stopwatch = new Stopwatch()..start();
- var component = await compiler.computeDelta();
+ Component component = await compiler.computeDelta();
+ if (world["errors"] == true && !gotError) {
+ throw "Expected error, but didn't get any.";
+ } else if (world["errors"] != true && gotError) {
+ throw "Got unexpected error(s): $formattedErrors.";
+ }
+ if (world["warnings"] == true && !gotWarning) {
+ throw "Expected warning, but didn't get any.";
+ } else if (world["warnings"] != true && gotWarning) {
+ throw "Got unexpected warnings(s): $formattedWarnings.";
+ }
throwOnEmptyMixinBodies(component);
- print("Bootstrapped compile took ${stopwatch.elapsedMilliseconds} ms");
- if (component.libraries.length != 1) {
- throw "Expected 1 library, got ${component.libraries.length}";
+ print("Compile took ${stopwatch.elapsedMilliseconds} ms");
+ newestWholeComponent = serializeComponent(component);
+ if (component.libraries.length != world["expectedLibraryCount"]) {
+ throw "Expected ${world["expectedLibraryCount"]} libraries, "
+ "got ${component.libraries.length}";
+ }
+ if (component.libraries[0].importUri != entry) {
+ throw "Expected the first library to have uri $entry but was "
+ "${component.libraries[0].importUri}";
+ }
+ if (compiler.initializedFromDill != expectInitializeFromDill) {
+ throw "Expected that initializedFromDill would be "
+ "$expectInitializeFromDill but was ${compiler.initializedFromDill}";
+ }
+ if (world["invalidate"] != null) {
+ Expect.equals(world["invalidate"].length,
+ compiler.invalidatedImportUrisForTesting.length);
+ List expectedInvalidatedUri = world["expectedInvalidatedUri"];
+ if (expectedInvalidatedUri != null) {
+ Expect.setEquals(
+ expectedInvalidatedUri
+ .map((s) => Uri.parse(substituteVariables(s, base))),
+ compiler.invalidatedImportUrisForTesting);
+ }
+ } else {
+ Expect.isNull(compiler.invalidatedImportUrisForTesting);
+ Expect.isNull(world["expectedInvalidatedUri"]);
}
}
}
+void checkIsEqual(List<int> a, List<int> b) {
+ int length = a.length;
+ if (b.length < length) {
+ length = b.length;
+ }
+ for (int i = 0; i < length; ++i) {
+ if (a[i] != b[i]) {
+ Expect.fail("Data differs at byte ${i+1}.");
+ }
+ }
+ Expect.equals(a.length, b.length);
+}
+
CompilerOptions getOptions(bool strong) {
final Uri sdkRoot = computePlatformBinariesLocation();
var options = new CompilerOptions()
@@ -421,11 +304,9 @@
}
..strongMode = strong;
if (strong) {
- options.sdkSummary =
- computePlatformBinariesLocation().resolve("vm_platform_strong.dill");
+ options.sdkSummary = sdkRoot.resolve("vm_platform_strong.dill");
} else {
- options.sdkSummary =
- computePlatformBinariesLocation().resolve("vm_platform.dill");
+ options.sdkSummary = sdkRoot.resolve("vm_platform.dill");
}
return options;
}
@@ -433,13 +314,51 @@
Future<bool> normalCompile(Uri input, Uri output,
{CompilerOptions options}) async {
options ??= getOptions(false);
- IncrementalCompiler compiler = new IncrementalKernelGenerator(options, input);
- var component = await compiler.computeDelta();
+ TestIncrementalCompiler compiler =
+ new TestIncrementalCompiler(options, input);
+ Component component = await compiler.computeDelta();
throwOnEmptyMixinBodies(component);
await writeComponentToFile(component, output);
return compiler.initializedFromDill;
}
+Future<bool> initializedCompile(
+ Uri input, Uri output, Uri initializeWith, List<Uri> invalidateUris,
+ {CompilerOptions options}) async {
+ options ??= getOptions(false);
+ TestIncrementalCompiler compiler =
+ new TestIncrementalCompiler(options, input, initializeWith);
+ for (Uri invalidateUri in invalidateUris) {
+ compiler.invalidate(invalidateUri);
+ }
+ var initializedComponent = await compiler.computeDelta();
+ throwOnEmptyMixinBodies(initializedComponent);
+ bool result = compiler.initializedFromDill;
+ await writeComponentToFile(initializedComponent, output);
+ for (Uri invalidateUri in invalidateUris) {
+ compiler.invalidate(invalidateUri);
+ }
+
+ var partialComponent = await compiler.computeDelta();
+ throwOnEmptyMixinBodies(partialComponent);
+ var emptyComponent = await compiler.computeDelta();
+ throwOnEmptyMixinBodies(emptyComponent);
+
+ var fullLibUris =
+ initializedComponent.libraries.map((lib) => lib.importUri).toList();
+ var partialLibUris =
+ partialComponent.libraries.map((lib) => lib.importUri).toList();
+ var emptyLibUris =
+ emptyComponent.libraries.map((lib) => lib.importUri).toList();
+
+ Expect.isTrue(fullLibUris.length > partialLibUris.length ||
+ partialLibUris.length == invalidateUris.length);
+ Expect.isTrue(partialLibUris.isNotEmpty || invalidateUris.isEmpty);
+ Expect.isTrue(emptyLibUris.isEmpty);
+
+ return result;
+}
+
void throwOnEmptyMixinBodies(Component component) {
int empty = countEmptyMixinBodies(component);
if (empty != 0) {
@@ -452,7 +371,6 @@
for (Library lib in component.libraries) {
for (Class c in lib.classes) {
if (c.isSyntheticMixinImplementation) {
- // Assume mixin
for (Procedure p in c.procedures) {
if (p.function.body is EmptyStatement) {
empty++;
@@ -464,40 +382,22 @@
return empty;
}
-Future<bool> bootstrapCompile(
- Uri input, Uri output, Uri bootstrapWith, List<Uri> invalidateUris,
- {bool performSizeTests: true, CompilerOptions options}) async {
- options ??= getOptions(false);
- IncrementalCompiler compiler =
- new IncrementalKernelGenerator(options, input, bootstrapWith);
- for (Uri invalidateUri in invalidateUris) {
- compiler.invalidate(invalidateUri);
+String substituteVariables(String source, Uri base) {
+ return source.replaceAll(r"${outDirUri}", "${base}");
+}
+
+class TestIncrementalCompiler extends IncrementalCompiler {
+ List<Uri> invalidatedImportUrisForTesting;
+
+ TestIncrementalCompiler(CompilerOptions options, Uri entryPoint,
+ [Uri initializeFrom])
+ : super(
+ new CompilerContext(
+ new ProcessedOptions(options, false, [entryPoint])),
+ initializeFrom);
+
+ @override
+ void recordInvalidatedImportUrisForTesting(List<Uri> uris) {
+ invalidatedImportUrisForTesting = uris.isEmpty ? null : uris.toList();
}
- var bootstrappedComponent = await compiler.computeDelta();
- throwOnEmptyMixinBodies(bootstrappedComponent);
- bool result = compiler.initializedFromDill;
- await writeComponentToFile(bootstrappedComponent, output);
- for (Uri invalidateUri in invalidateUris) {
- compiler.invalidate(invalidateUri);
- }
-
- var partialComponent = await compiler.computeDelta();
- throwOnEmptyMixinBodies(partialComponent);
- var emptyComponent = await compiler.computeDelta();
- throwOnEmptyMixinBodies(emptyComponent);
-
- var fullLibUris =
- bootstrappedComponent.libraries.map((lib) => lib.importUri).toList();
- var partialLibUris =
- partialComponent.libraries.map((lib) => lib.importUri).toList();
- var emptyLibUris =
- emptyComponent.libraries.map((lib) => lib.importUri).toList();
-
- if (performSizeTests) {
- Expect.isTrue(fullLibUris.length > partialLibUris.length);
- Expect.isTrue(partialLibUris.isNotEmpty);
- Expect.isTrue(emptyLibUris.isEmpty);
- }
-
- return result;
}
diff --git a/pkg/front_end/test/src/base/libraries_specification_test.dart b/pkg/front_end/test/src/base/libraries_specification_test.dart
index 4f9c8ed..60315e2 100644
--- a/pkg/front_end/test/src/base/libraries_specification_test.dart
+++ b/pkg/front_end/test/src/base/libraries_specification_test.dart
@@ -197,6 +197,43 @@
expect(spec.specificationFor('none').libraryInfoFor('c').uri,
Uri.parse('org-dartlang-test:///one/two/c/main.dart'));
});
+
+ test('environment_overrides entry must be a map', () async {
+ var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+ '"environment_overrides": []}}';
+ expect(
+ () => LibrariesSpecification.parse(
+ Uri.parse('org-dartlang-test:///f.json'), jsonString),
+ throwsA((e) => e is LibrariesSpecificationException));
+ });
+
+ test('environment_overrides values must be bool', () async {
+ var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+ '"environment_overrides": {"core": 3}}}';
+ expect(
+ () => LibrariesSpecification.parse(
+ Uri.parse('org-dartlang-test:///f.json'), jsonString),
+ throwsA((e) => e is LibrariesSpecificationException));
+ });
+
+ test('environment_overrides correspond to existing libraries', () async {
+ var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+ '"environment_overrides": {"ui": false}}}';
+ expect(
+ () => LibrariesSpecification.parse(
+ Uri.parse('org-dartlang-test:///f.json'), jsonString),
+ throwsA((e) => e is LibrariesSpecificationException));
+ });
+
+ test('environment_overrides can be read from the public API', () async {
+ var jsonString = '{"vm" : {"libraries": {"core": {"uri": "main.dart"}},'
+ '"environment_overrides": {"core": false}}}';
+ var spec = LibrariesSpecification.parse(
+ Uri.parse('org-dartlang-test:///one/two/f.json'), jsonString);
+ expect(
+ spec.specificationFor('vm').environmentOverrideFor('core'), "false");
+ expect(spec.specificationFor('vm').environmentOverrideFor('ui'), null);
+ });
});
group('toJson', () {
@@ -226,6 +263,9 @@
"uri": "c/main.dart",
"patches": []
}
+ },
+ "environment_overrides": {
+ "c" : false
}
}
}
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index dc8b1a2..71b880f 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -6,6 +6,7 @@
# generating analyzer ASTs and connecting up type inference information.
annotation_top: Crash
argument_mismatch: Fail
+bug32629: Fail
dynamic_and_void: Fail
illegal_named_function_expression: Crash
illegal_named_function_expression_scope: Crash
diff --git a/pkg/front_end/testcases/bug32629.dart b/pkg/front_end/testcases/bug32629.dart
new file mode 100644
index 0000000..88610e0
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart
@@ -0,0 +1,19 @@
+// 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.
+
+/*@testedFeatures=error*/
+
+class A {
+ dynamic call(dynamic a, dynamic b) {
+ return a;
+ }
+}
+
+typedef S Reducer<S>(S a, dynamic b);
+
+void foo<S>(Reducer<S> v) {}
+
+void main() {
+ foo<String>(new /*@error=InvalidAssignment*/ A());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.expect b/pkg/front_end/testcases/bug32629.dart.direct.expect
new file mode 100644
index 0000000..1f4307c
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.direct.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method call(dynamic a, dynamic b) → dynamic {
+ return a;
+ }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+ self::foo<core::String>(new self::A::•());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect b/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect
new file mode 100644
index 0000000..1f4307c
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.direct.transformed.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method call(dynamic a, dynamic b) → dynamic {
+ return a;
+ }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+ self::foo<core::String>(new self::A::•());
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.outline.expect b/pkg/front_end/testcases/bug32629.dart.outline.expect
new file mode 100644
index 0000000..d37f8be
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.outline.expect
@@ -0,0 +1,15 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method call(dynamic a, dynamic b) → dynamic
+ ;
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void
+ ;
+static method main() → void
+ ;
diff --git a/pkg/front_end/testcases/bug32629.dart.strong.expect b/pkg/front_end/testcases/bug32629.dart.strong.expect
new file mode 100644
index 0000000..0258b41
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.strong.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method call(dynamic a, dynamic b) → dynamic {
+ return a;
+ }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+ self::foo<core::String>(let final dynamic #t1 = let final self::A #t2 = new self::A::•() in #t2.==(null) ?{(dynamic, dynamic) → dynamic} null : #t2.{self::A::call} in let dynamic _ = null in invalid-expression "pkg/front_end/testcases/bug32629.dart:18:47: Error: A value of type '(dynamic, dynamic) \u8594 dynamic' can't be assigned to a variable of type '(dart.core::String, dynamic) \u8594 dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to '(dart.core::String, dynamic) \u8594 dart.core::String'.
+ foo<String>(new /*@error=InvalidAssignment*/A());
+ ^");
+}
diff --git a/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect b/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect
new file mode 100644
index 0000000..b6f7b796
--- /dev/null
+++ b/pkg/front_end/testcases/bug32629.dart.strong.transformed.expect
@@ -0,0 +1,20 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+typedef Reducer<S extends core::Object> = (S, dynamic) → S;
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method call(dynamic a, dynamic b) → dynamic {
+ return a;
+ }
+}
+static method foo<S extends core::Object>((self::foo::S, dynamic) → self::foo::S v) → void {}
+static method main() → void {
+ self::foo<core::String>(let final (dynamic, dynamic) → dynamic #t1 = let final self::A #t2 = new self::A::•() in #t2.==(null) ?{(dynamic, dynamic) → dynamic} null : #t2.{self::A::call} in let<BottomType> _ = null in invalid-expression "pkg/front_end/testcases/bug32629.dart:18:47: Error: A value of type '(dynamic, dynamic) \u8594 dynamic' can't be assigned to a variable of type '(dart.core::String, dynamic) \u8594 dart.core::String'.
+Try changing the type of the left hand side, or casting the right hand side to '(dart.core::String, dynamic) \u8594 dart.core::String'.
+ foo<String>(new /*@error=InvalidAssignment*/A());
+ ^");
+}
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_full.status b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
new file mode 100644
index 0000000..acb1629
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_full.status
@@ -0,0 +1,3 @@
+# 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.md file.
diff --git a/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
new file mode 100644
index 0000000..acb1629
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_bulk_compiler_smoke.status
@@ -0,0 +1,3 @@
+# 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.md file.
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml
new file mode 100644
index 0000000..c6eb17a
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/calculated_bounds_no_strongmode.yaml
@@ -0,0 +1,22 @@
+# 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.md file.
+
+# Test compiling in non-strong-mode from source and initializing from dill.
+# Make sure that any inference if done in the same way.
+
+type: simple
+name: testCalculatedBounds
+entry: testCalculatedBounds_a.dart
+strong: false
+invalidate:
+ - testCalculatedBounds_a.dart
+sources:
+ testCalculatedBounds_a.dart: |
+ import 'testCalculatedBounds_b.dart';
+
+ class A {
+ void foo(B cls) {}
+ }
+ testCalculatedBounds_b.dart: |
+ abstract class B<T extends String> {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml
new file mode 100644
index 0000000..7ffc3f1
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/deferred_library.yaml
@@ -0,0 +1,21 @@
+# 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.md file.
+
+# Test loading from a dill file with a deferred library.
+# This is done by initializing from dill and making no changes/invalidations.
+
+type: simple
+name: testDeferredLibrary
+entry: testDeferredLibrary_main.dart
+strong: false
+invalidate:
+sources:
+ testDeferredLibrary_main.dart: |
+ import 'testDeferredLibrary_b.dart' deferred as b;
+
+ void main() {
+ print(b.foo());
+ }
+ testDeferredLibrary_b.dart: |
+ String foo() => "hello from foo in b";
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml
new file mode 100644
index 0000000..a00341b
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_library.yaml
@@ -0,0 +1,40 @@
+# 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.md file.
+
+# Compile an application with n libraries, then
+# compile "the same" application, but with m < n libraries,
+# where (at least one) of the missing libraries are "in the middle"
+# of the library list --- initializing from the dill with n libraries.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ library mainLibrary;
+ import "b.dart" as b;
+
+ main() {
+ b.foo();
+ }
+ b.dart: |
+ library bLibrary;
+
+ foo() {
+ print("hello from b.dart foo!");
+ }
+ expectedLibraryCount: 2
+ - entry: b.dart
+ invalidate:
+ - main.dart
+ - b.dart
+ sources:
+ b.dart: |
+ library bLibrary;
+
+ main() {
+ print("hello from b!");
+ }
+ expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
new file mode 100644
index 0000000..78c978d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/disappearing_package.yaml
@@ -0,0 +1,36 @@
+# 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.md file.
+
+# Compile an application with a package and use it.
+# Then remove the package from .packages and remove any use of it.
+# The package is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "package:dummy/b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ b() {
+ print("b");
+ }
+ .packages: dummy:${outDirUri}
+ expectedLibraryCount: 2
+ - entry: main.dart
+ invalidate:
+ - main.dart
+ sources:
+ main.dart: |
+ main() {
+ print("hello");
+ }
+ .packages:
+ expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml
new file mode 100644
index 0000000..5a11db2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_export_of_main.yaml
@@ -0,0 +1,17 @@
+# 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.md file.
+
+# Invalidate the entrypoint which just exports another file (which has main).
+
+type: simple
+name: testInvalidateExportOfMain
+entry: testInvalidateExportOfMain_a.dart
+strong: true
+invalidate:
+ - testInvalidateExportOfMain_a.dart
+sources:
+ testInvalidateExportOfMain_a.dart: |
+ export 'testInvalidateExportOfMain_b.dart';
+ testInvalidateExportOfMain_b.dart: |
+ main() { print("hello"); }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml
new file mode 100644
index 0000000..e7811bd
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part.yaml
@@ -0,0 +1,63 @@
+# 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.md file.
+
+# Test that invalidating a part of a package works with both file and package
+# URI.
+
+type: newworld
+strong: false
+worlds:
+ - entry: "package:dummy/main.dart"
+ sources:
+ main.dart: |
+ part "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ part of "main.dart";
+ b() {
+ print("b1");
+ }
+ .packages: dummy:${outDirUri}
+ expectedLibraryCount: 1
+ - entry: "package:dummy/main.dart"
+ invalidate:
+ - b.dart
+ expectedInvalidatedUri:
+ - "package:dummy/b.dart"
+ sources:
+ main.dart: |
+ part "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ part of "main.dart";
+ b() {
+ print("b2");
+ }
+ .packages: dummy:${outDirUri}
+ expectedLibraryCount: 1
+ - entry: "package:dummy/main.dart"
+ invalidate:
+ - "package:dummy/b.dart"
+ expectedInvalidatedUri:
+ - "package:dummy/b.dart"
+ sources:
+ main.dart: |
+ part "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ part of "main.dart";
+ b() {
+ print("b3");
+ }
+ .packages: dummy:${outDirUri}
+ expectedLibraryCount: 1
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml
new file mode 100644
index 0000000..759ae72
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_file.yaml
@@ -0,0 +1,24 @@
+# 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.md file.
+
+# Test that invalidating a part of a package works with file URI.
+
+type: simple
+name: testDeferredLibrary
+entry: "package:dummy/main.dart"
+strong: false
+invalidate:
+sources:
+ main.dart: |
+ part "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ part of "main.dart";
+ b() {
+ print("b1");
+ }
+ .packages: dummy:${outDirUri}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml
new file mode 100644
index 0000000..759ae72
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_package_part_as_package.yaml
@@ -0,0 +1,24 @@
+# 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.md file.
+
+# Test that invalidating a part of a package works with file URI.
+
+type: simple
+name: testDeferredLibrary
+entry: "package:dummy/main.dart"
+strong: false
+invalidate:
+sources:
+ main.dart: |
+ part "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ part of "main.dart";
+ b() {
+ print("b1");
+ }
+ .packages: dummy:${outDirUri}
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml
new file mode 100644
index 0000000..e3828ea
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/invalidate_part.yaml
@@ -0,0 +1,26 @@
+# 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.md file.
+
+# Invalidate a part file.
+
+type: simple
+name: testInvalidatePart
+entry: testInvalidatePart_a.dart
+strong: true
+invalidate:
+ - testInvalidatePart_b.dart
+sources:
+ testInvalidatePart_a.dart: |
+ library a;
+ import 'testInvalidatePart_c.dart';
+ part 'testInvalidatePart_b.dart';
+ testInvalidatePart_b.dart: |
+ part of a;
+ b() { print("b"); }
+ testInvalidatePart_c.dart: |
+ library c;
+ part 'testInvalidatePart_d.dart';
+ testInvalidatePart_d.dart: |
+ part of c;
+ d() { print("d"); }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml
new file mode 100644
index 0000000..b86dbc7
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_from_sdk.yaml
@@ -0,0 +1,26 @@
+# 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.md file.
+
+# Test using a mixin from the sdk and invalidationg it.
+# Make sure compiling from source and compiling where we initialize from dill
+# ends up including the same source code.
+
+type: simple
+name: testMixinFromSdk
+entry: testMixinFromSdk_a.dart
+strong: true
+invalidate:
+ - testMixinFromSdk_a.dart
+sources:
+ testMixinFromSdk_a.dart: |
+ import 'dart:collection';
+
+ class Foo extends Object with ListMixin<int> {
+ int length = 0;
+ int operator [](int index) {
+ return 42;
+ }
+
+ void operator []=(int index, int value) {}
+ }
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml
new file mode 100644
index 0000000..fb8b511
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/remove_import_with_error.yaml
@@ -0,0 +1,67 @@
+# 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.md file.
+
+# First compile a file (a) that imports a file (b) with errors in it.
+# Then change a to not import b, but leave b as-is, thus rightfully only
+# invalidating a. Compiling this should not result in any errors.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ errors: true
+ warnings: false
+ sources:
+ main.dart: |
+ library mainLibrary;
+ import "b.dart" as b;
+
+ main() {
+ b.foo();
+ }
+ b.dart: |
+ library bLibrary;
+
+ foo() {
+ print("hello from b.dart foo!");
+ print(new C());
+ }
+
+ class I<T> {}
+
+ class A implements I<int> {}
+
+ class B implements I<String> {}
+
+ class C extends A implements B {}
+
+ expectedLibraryCount: 2
+ - entry: main.dart
+ invalidate:
+ - main.dart
+ errors: false
+ warnings: false
+ sources:
+ main.dart: |
+ library mainLibrary;
+
+ main() {
+ print("hello");
+ }
+ b.dart: |
+ library bLibrary;
+
+ foo() {
+ print("hello from b.dart foo!");
+ print(new C());
+ }
+
+ class I<T> {}
+
+ class A implements I<int> {}
+
+ class B implements I<String> {}
+
+ class C extends A implements B {}
+ expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/status.status b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
new file mode 100644
index 0000000..2dcebd2
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/status.status
@@ -0,0 +1,11 @@
+# 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.md file.
+
+# Status file for the test suite ../test/incremental_load_from_dill_yaml_test.dart.
+
+calculated_bounds_no_strongmode: Crash
+invalidate_package_part: Crash
+invalidate_package_part_as_file: Crash
+invalidate_package_part_as_package: Crash
+strongmode_mixins_2: Crash
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml
new file mode 100644
index 0000000..dbabbd3
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins.yaml
@@ -0,0 +1,21 @@
+# 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.md file.
+
+# Compile in strong mode. Invalidate a file so type inferrer starts
+# on something compiled from source and (potentially) goes into
+# something loaded from dill.
+
+type: simple
+name: testStrongModeMixins
+entry: testStrongModeMixins_a.dart
+strong: true
+invalidate:
+ - testStrongModeMixins_a.dart
+sources:
+ testStrongModeMixins_a.dart: |
+ import 'testStrongModeMixins_b.dart';
+ class A extends Object with B<Object>, C {}
+ testStrongModeMixins_b.dart: |
+ abstract class C<T extends Object> extends Object with B<T> {}
+ abstract class B<ChildType extends Object> extends Object {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml
new file mode 100644
index 0000000..4907a06
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/strongmode_mixins_2.yaml
@@ -0,0 +1,25 @@
+# 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.md file.
+
+# Compile in strong mode. Use mixins.
+
+type: simple
+name: testStrongModeMixins2
+entry: testStrongModeMixins2_a.dart
+strong: true
+invalidate:
+ - testStrongModeMixins2_a.dart
+sources:
+ testStrongModeMixins2_a.dart: |
+ import 'testStrongModeMixins2_b.dart';
+ class A extends Object with B<C>, D<Object> {}
+ testStrongModeMixins2_b.dart: |
+ abstract class B<ChildType extends Object> extends Object {
+ ChildType get child => null;
+ set child(ChildType value) {}
+ }
+
+ class C extends Object {}
+
+ abstract class D<T extends Object> extends Object with B<T> {}
\ No newline at end of file
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml
new file mode 100644
index 0000000..a2c5739
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/unused_file.yaml
@@ -0,0 +1,38 @@
+# 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.md file.
+
+# Compile an application where we use an import, then recomile without changing
+# the import but where we no longer use it.
+# The imported file is still included in the dill file we initialize from,
+# but shouldn't cause trouble, nor be included in the output.
+
+type: newworld
+strong: false
+worlds:
+ - entry: main.dart
+ sources:
+ main.dart: |
+ import "b.dart";
+ main() {
+ print("hello");
+ b();
+ }
+ b.dart: |
+ b() {
+ print("b");
+ }
+ expectedLibraryCount: 2
+ - entry: main.dart
+ invalidate:
+ - main.dart
+ sources:
+ main.dart: |
+ main() {
+ print("hello");
+ }
+ b.dart: |
+ b() {
+ print("b");
+ }
+ expectedLibraryCount: 1
\ No newline at end of file
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart
new file mode 100644
index 0000000..e5d16a8
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// This test checks that a noSuchMethod forwarder is generated in classes that
+// inherit a user-defined noSuchMethod from their superclass and have not
+// implemented abstract methods from their interfaces.
+
+class A {
+ dynamic noSuchMethod(Invocation i) {
+ return null;
+ }
+}
+
+abstract class I {
+ void foo();
+}
+
+class B extends A implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.direct.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
new file mode 100644
index 0000000..f5898c4
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.outline.expect
@@ -0,0 +1,22 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+}
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ ;
+ abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
new file mode 100644
index 0000000..77108c2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/abstract_interface_nsm_inherited.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart
new file mode 100644
index 0000000..a23c474
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// This method checks that the noSuchMethod forwarder is generated in cases when
+// the class of the implemented interface has concrete methods.
+
+class A {
+ dynamic noSuchMethod(Invocation i) {
+ return null;
+ }
+}
+
+class I {
+ // This method is concrete.
+ void foo() {}
+}
+
+class B extends A implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.direct.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
new file mode 100644
index 0000000..a299436
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.outline.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+}
+class I extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method foo() → void
+ ;
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
new file mode 100644
index 0000000..6de0ac2
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_concrete.dart.strong.transformed.expect
@@ -0,0 +1,25 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method foo() → void {}
+}
+class B extends self::A implements self::I {
+ synthetic constructor •() → void
+ : super self::A::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart
new file mode 100644
index 0000000..af56a39
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart
@@ -0,0 +1,26 @@
+// 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.
+
+// This test checks that if an interface have a user-defined noSuchMethod, its
+// implementations that have their own user-defined noSuchMethods still receive
+// the noSuchMethod forwarders for each not implemented method from the
+// interface.
+
+class I {
+ dynamic noSuchMethod(Invocation i) => null;
+
+ // This should be a noSuchMethod forwarder, because [I] has a user-defined
+ // [noSuchMethod].
+ void foo();
+}
+
+class M {
+ dynamic noSuchMethod(Invocation i) => null;
+}
+
+class A extends Object with M implements I {}
+
+class B extends Object with M implements I {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect
new file mode 100644
index 0000000..7463788
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect
new file mode 100644
index 0000000..49caf94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.direct.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+class A extends self::_A&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+class B extends self::_B&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
new file mode 100644
index 0000000..f61d498
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.outline.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
new file mode 100644
index 0000000..7463788
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.expect
@@ -0,0 +1,36 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M = core::Object with self::M {
+}
+class B extends self::_B&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
new file mode 100644
index 0000000..49caf94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/interface_with_nsm.dart.strong.transformed.expect
@@ -0,0 +1,46 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+class A extends self::_A&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+}
+class B extends self::_B&Object&M implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart
new file mode 100644
index 0000000..fcbc2e3
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// This test checks that the noSuchMethod forwarder is not duplicated in classes
+// that mix in the classes that already have the forwarder.
+
+abstract class I {
+ void foo();
+}
+
+class A implements I {
+ dynamic noSuchMethod(Invocation i) => null;
+}
+
+class B extends Object with A {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect
new file mode 100644
index 0000000..aeadca5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect
new file mode 100644
index 0000000..f43923a
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.direct.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect
new file mode 100644
index 0000000..71c513d
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ ;
+ abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ ;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect
new file mode 100644
index 0000000..aeadca5
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.expect
@@ -0,0 +1,26 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect
new file mode 100644
index 0000000..f43923a
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/no_dup_from_mixin.dart.strong.transformed.expect
@@ -0,0 +1,32 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+abstract class I extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → void;
+}
+class A extends core::Object implements self::I {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ return null;
+ abstract no-such-method-forwarder method foo() → void;
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart
new file mode 100644
index 0000000..ecd60f1
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart
@@ -0,0 +1,16 @@
+// 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.
+
+// This test checks that the noSuchMethod forwarder is generated in cases when
+// the user-defined noSuchMethod is inherited by classes with abstract methods.
+
+class M {
+ dynamic noSuchMethod(Invocation invocation) => null;
+}
+
+class A extends M {
+ void call(String s);
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation invocation) → dynamic
+ return null;
+}
+class A extends self::M {
+ synthetic constructor •() → void
+ : super self::M::•()
+ ;
+ abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.direct.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation invocation) → dynamic
+ return null;
+}
+class A extends self::M {
+ synthetic constructor •() → void
+ : super self::M::•()
+ ;
+ abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
new file mode 100644
index 0000000..6fdc38e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.outline.expect
@@ -0,0 +1,17 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation invocation) → dynamic
+ ;
+}
+class A extends self::M {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation invocation) → dynamic
+ return null;
+}
+class A extends self::M {
+ synthetic constructor •() → void
+ : super self::M::•()
+ ;
+ abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
new file mode 100644
index 0000000..5b3dcdd
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_inherited.dart.strong.transformed.expect
@@ -0,0 +1,18 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation invocation) → dynamic
+ return null;
+}
+class A extends self::M {
+ synthetic constructor •() → void
+ : super self::M::•()
+ ;
+ abstract no-such-method-forwarder method call(core::String s) → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart
new file mode 100644
index 0000000..284d817
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart
@@ -0,0 +1,18 @@
+// 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.
+
+// This test checks that the noSuchMethod forwarder is generated in cases when
+// the user-defined noSuchMethod is mixed in to a class with abstract methods.
+
+class A {
+ dynamic noSuchMethod(Invocation i) {
+ return null;
+ }
+}
+
+class B extends Object with A {
+ void foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect
new file mode 100644
index 0000000..82b4b89
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect
new file mode 100644
index 0000000..224585c
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.direct.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
new file mode 100644
index 0000000..6e0c11e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.outline.expect
@@ -0,0 +1,19 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
new file mode 100644
index 0000000..82b4b89
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.expect
@@ -0,0 +1,21 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _B&Object&A = core::Object with self::A {
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
new file mode 100644
index 0000000..224585c
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/nsm_mixed_in.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _B&Object&A extends core::Object implements self::A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class B extends self::_B&Object&A {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart b/pkg/front_end/testcases/no_such_method_forwarders/same.dart
new file mode 100644
index 0000000..40d7c26
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart
@@ -0,0 +1,17 @@
+// 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.
+
+// This test checks that a noSuchMethod forwarder is generated in the case when
+// the user-defined noSuchMethod and the abstract method are both defined in the
+// same class.
+
+class A {
+ dynamic noSuchMethod(Invocation i) {
+ return null;
+ }
+
+ void foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.direct.transformed.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
new file mode 100644
index 0000000..ef9c2e6
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.outline.expect
@@ -0,0 +1,13 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect
new file mode 100644
index 0000000..a8c2894
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/same.dart.strong.transformed.expect
@@ -0,0 +1,14 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+ abstract no-such-method-forwarder method foo() → void;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
new file mode 100644
index 0000000..f461405
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart
@@ -0,0 +1,21 @@
+// 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.
+
+// This test checks that the generated noSuchMethod forwarder for a
+// non-implemented abstract method has all the references to the type variables
+// in its signature replaced with the appropriate types.
+
+class I<T> {
+ T foo();
+}
+
+class M {
+ dynamic noSuchMethod(Invocation i) {
+ return null;
+ }
+}
+
+class A extends Object with M implements I<int> {}
+
+main() {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
new file mode 100644
index 0000000..ffa2406
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
new file mode 100644
index 0000000..41aef5e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.direct.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
new file mode 100644
index 0000000..6a7ca94
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.outline.expect
@@ -0,0 +1,24 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+ synthetic constructor •() → void
+ ;
+ abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic
+ ;
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+ synthetic constructor •() → void
+ ;
+ abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic
+ ;
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
new file mode 100644
index 0000000..ffa2406
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _A&Object&M = core::Object with self::M {
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
new file mode 100644
index 0000000..41aef5e
--- /dev/null
+++ b/pkg/front_end/testcases/no_such_method_forwarders/subst_on_forwarder.dart.strong.transformed.expect
@@ -0,0 +1,33 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class I<T extends core::Object> extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract method foo() → self::I::T;
+}
+class M extends core::Object {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+abstract class _A&Object&M extends core::Object implements self::M {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ method noSuchMethod(core::Invocation i) → dynamic {
+ return null;
+ }
+}
+class A extends self::_A&Object&M implements self::I<core::int> {
+ synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+ abstract no-such-method-forwarder method foo() → core::int;
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 91b818e..bdc3645 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -14,6 +14,7 @@
bug21938: TypeCheckError
bug30695: TypeCheckError
bug31124: RuntimeError # Test has an intentional error
+bug32629: Fail # Test has an intentional error
call: Fail
cascade: Fail
casts: Fail
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index b1fadda..af4b8b4 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -148,6 +148,48 @@
},
{
+ "name": "incremental_load_from_dill",
+ "kind": "Chain",
+ "source": "test/incremental_load_from_dill_test.dart",
+ "path": "testcases/incremental_initialize_from_dill/",
+ "status": "testcases/incremental_initialize_from_dill/status.status",
+ "pattern": [
+ "\\.yaml$"
+ ],
+ "exclude": [
+ ]
+ },
+
+ {
+ "name": "incremental_bulk_compiler_smoke",
+ "kind": "Chain",
+ "source": "test/incremental_bulk_compiler_smoke_test.dart",
+ "path": "../../tests/",
+ "status": "testcases/incremental_bulk_compiler_smoke.status",
+ "pattern": [
+ "/language_2/accessor_conflict_export2_test\\.dart$",
+ "/language_2/accessor_conflict_export_test\\.dart$",
+ "/language_2/regress_14348_test\\.dart$",
+ "/language_2/regress_18535_test\\.dart$"
+ ],
+ "exclude": [
+ ]
+ },
+
+ {
+ "name": "incremental_bulk_compiler_full",
+ "kind": "Chain",
+ "source": "test/incremental_bulk_compiler_full.dart",
+ "path": "../../tests/",
+ "status": "testcases/incremental_bulk_compiler_full.status",
+ "pattern": [
+ "language_2/.*_test\\.dart$"
+ ],
+ "exclude": [
+ ]
+ },
+
+ {
"name": "sdk",
"kind": "Chain",
"source": "test/fasta/sdk_test.dart",
diff --git a/pkg/front_end/tool/_fasta/compile_platform.dart b/pkg/front_end/tool/_fasta/compile_platform.dart
index 5629776..b2bf572 100644
--- a/pkg/front_end/tool/_fasta/compile_platform.dart
+++ b/pkg/front_end/tool/_fasta/compile_platform.dart
@@ -9,7 +9,10 @@
import 'dart:io' show File, Platform, exitCode;
import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
-import 'package:vm/target/runner.dart' show RunnerTarget;
+
+import 'package:vm/target/dart_runner.dart' show DartRunnerTarget;
+
+import 'package:vm/target/flutter_runner.dart' show FlutterRunnerTarget;
import 'package:kernel/target/targets.dart' show TargetFlags, targets;
@@ -35,8 +38,13 @@
const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
Future main(List<String> arguments) async {
- targets["dart2js"] = (TargetFlags flags) => new Dart2jsTarget(flags);
- targets["runner"] = (TargetFlags flags) => new RunnerTarget(flags);
+ targets["dart2js"] =
+ (TargetFlags flags) => new Dart2jsTarget("dart2js", flags);
+ targets["dart2js_server"] =
+ (TargetFlags flags) => new Dart2jsTarget("dart2js_server", flags);
+ targets["dart_runner"] = (TargetFlags flags) => new DartRunnerTarget(flags);
+ targets["flutter_runner"] =
+ (TargetFlags flags) => new FlutterRunnerTarget(flags);
for (int i = 0; i < iterations; i++) {
if (i > 0) {
print("\n");
diff --git a/pkg/front_end/tool/_fasta/entry_points.dart b/pkg/front_end/tool/_fasta/entry_points.dart
index 67cbe59..c69bb9b 100644
--- a/pkg/front_end/tool/_fasta/entry_points.dart
+++ b/pkg/front_end/tool/_fasta/entry_points.dart
@@ -49,7 +49,10 @@
const int iterations = const int.fromEnvironment("iterations", defaultValue: 1);
compileEntryPoint(List<String> arguments) async {
- targets["dart2js"] = (TargetFlags flags) => new Dart2jsTarget(flags);
+ targets["dart2js"] =
+ (TargetFlags flags) => new Dart2jsTarget("dart2js", flags);
+ targets["dart2js_server"] =
+ (TargetFlags flags) => new Dart2jsTarget("dart2js_server", flags);
// Timing results for each iteration
List<double> elapsedTimes = <double>[];
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 9305d16..6179db3 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -353,6 +353,7 @@
Byte flags (isStatic, isAbstract, isExternal, isConst, isForwardingStub,
isGenericContravariant, isForwardingSemiStub,
isRedirectingFactoryConstructor);
+ Byte flags2 (isNoSuchMethodForwarder);
Name name;
List<Expression> annotations;
// Only present if the 'isForwardingStub' flag is set.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 2152cd9..099307e 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -1451,6 +1451,7 @@
class Procedure extends Member {
ProcedureKind kind;
int flags = 0;
+ int flags2 = 0;
// function is null if and only if abstract, external.
FunctionNode function;
@@ -1539,6 +1540,7 @@
static const int FlagForwardingSemiStub = 1 << 6;
// TODO(29841): Remove this flag after the issue is resolved.
static const int FlagRedirectingFactoryConstructor = 1 << 7;
+ static const int Flag2NoSuchMethodForwarder = 1 << 0;
bool get isStatic => flags & FlagStatic != 0;
bool get isAbstract => flags & FlagAbstract != 0;
@@ -1581,6 +1583,8 @@
/// and forwarding to [forwardingStubSuperTarget].
bool get isSyntheticForwarder => isForwardingStub && !isForwardingSemiStub;
+ bool get isNoSuchMethodForwarder => flags2 & Flag2NoSuchMethodForwarder != 0;
+
void set isStatic(bool value) {
flags = value ? (flags | FlagStatic) : (flags & ~FlagStatic);
}
@@ -1620,6 +1624,13 @@
: (flags & ~FlagRedirectingFactoryConstructor);
}
+ void set isNoSuchMethodForwarder(bool value) {
+ assert(isAbstract);
+ flags2 = value
+ ? (flags2 | Flag2NoSuchMethodForwarder)
+ : (flags2 & ~Flag2NoSuchMethodForwarder);
+ }
+
bool get isInstanceMember => !isStatic;
bool get isGetter => kind == ProcedureKind.Getter;
bool get isSetter => kind == ProcedureKind.Setter;
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index ce35260..4869901 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -933,6 +933,7 @@
int kindIndex = readByte();
var kind = ProcedureKind.values[kindIndex];
var flags = readByte();
+ var flags2 = readByte();
var name = readName();
var annotations = readAnnotationList(node);
assert(() {
@@ -956,6 +957,7 @@
node.fileEndOffset = fileEndOffset;
node.kind = kind;
node.flags = flags;
+ node.flags2 = flags2;
node.name = name;
node.fileUri = fileUri;
node.annotations = annotations;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 7bec298..a71ec32 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -808,6 +808,7 @@
writeOffset(node.fileEndOffset);
writeByte(node.kind.index);
writeByte(node.flags);
+ writeByte(node.flags2);
writeName(node.name ?? '');
writeAnnotationList(node.annotations);
writeOptionalReference(node.forwardingStubSuperTargetReference);
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 20eadbe..be0c79a 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -724,7 +724,9 @@
// Run a downward traversal from the root, compute preorder numbers for
// each class, and build their subtype sets as interval lists.
- _topDownSortVisit(_infoFor[classes[0]]);
+ if (classes.isNotEmpty) {
+ _topDownSortVisit(_infoFor[classes[0]]);
+ }
// Now that the intervals for subclass, mixer, and implementer queries are
// built, we may infer and record supertypes for the classes.
diff --git a/pkg/kernel/lib/clone.dart b/pkg/kernel/lib/clone.dart
index 3eb51ac..3901902 100644
--- a/pkg/kernel/lib/clone.dart
+++ b/pkg/kernel/lib/clone.dart
@@ -423,19 +423,15 @@
visitProcedure(Procedure node) {
return new Procedure(node.name, node.kind, clone(node.function),
- isAbstract: node.isAbstract,
- isStatic: node.isStatic,
- isExternal: node.isExternal,
- isConst: node.isConst,
- isForwardingStub: node.isForwardingStub,
- isForwardingSemiStub: node.isForwardingSemiStub,
transformerFlags: node.transformerFlags,
fileUri: _activeFileUri,
forwardingStubSuperTarget: node.forwardingStubSuperTarget,
forwardingStubInterfaceTarget: node.forwardingStubInterfaceTarget)
..fileOffset = _cloneFileOffset(node.fileOffset)
..fileEndOffset = _cloneFileOffset(node.fileEndOffset)
- ..isGenericContravariant = node.isGenericContravariant;
+ ..isGenericContravariant = node.isGenericContravariant
+ ..flags = node.flags
+ ..flags2 = node.flags2;
}
visitField(Field node) {
@@ -590,3 +586,11 @@
return defaultTreeNode(node);
}
}
+
+class CloneWithoutBody extends CloneVisitor {
+ CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
+ : super(typeSubstitution: typeSubstitution);
+
+ @override
+ TreeNode cloneFunctionNodeBody(FunctionNode node) => null;
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index 22672fd..ec9a8aa 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -76,6 +76,15 @@
/// promotion do not slow down compilation too much.
bool get disableTypeInference => false;
+ /// A derived class may change this to `true` to enable forwarders to
+ /// user-defined `noSuchMethod` that are generated for each abstract member
+ /// if such `noSuchMethod` is present.
+ ///
+ /// The forwarders are abstract [Procedure]s with [isNoSuchMethodForwarder]
+ /// bit set. The implementation of the behavior of such forwarders is up
+ /// for the target backend.
+ bool get enableNoSuchMethodForwarders => false;
+
/// A derived class may change this to `true` to enable Flutter specific
/// "super-mixins" semantics.
///
diff --git a/pkg/kernel/lib/target/vm.dart b/pkg/kernel/lib/target/vm.dart
index 5fd891e..322d2c5 100644
--- a/pkg/kernel/lib/target/vm.dart
+++ b/pkg/kernel/lib/target/vm.dart
@@ -26,6 +26,9 @@
bool get strongMode => flags.strongMode;
@override
+ bool get enableNoSuchMethodForwarders => true;
+
+ @override
String get name => 'vm';
// This is the order that bootstrap libraries are loaded according to
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index fcf52cf..ade2e8e 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -929,6 +929,7 @@
writeModifier(node.isForwardingStub, 'forwarding-stub');
writeModifier(node.isForwardingSemiStub, 'forwarding-semi-stub');
writeModifier(node.isGenericContravariant, 'generic-contravariant');
+ writeModifier(node.isNoSuchMethodForwarder, 'no-such-method-forwarder');
writeWord(procedureKindToString(node.kind));
if ((node.enclosingClass == null &&
node.enclosingLibrary.fileUri != node.fileUri) ||
diff --git a/pkg/kernel/lib/transformations/closure/clone_without_body.dart b/pkg/kernel/lib/transformations/closure/clone_without_body.dart
index 1f13b54..1e4b344 100644
--- a/pkg/kernel/lib/transformations/closure/clone_without_body.dart
+++ b/pkg/kernel/lib/transformations/closure/clone_without_body.dart
@@ -4,14 +4,4 @@
library kernel.transformations.closure.converter;
-import '../../ast.dart' show DartType, FunctionNode, TreeNode, TypeParameter;
-
-import '../../clone.dart' show CloneVisitor;
-
-class CloneWithoutBody extends CloneVisitor {
- CloneWithoutBody({Map<TypeParameter, DartType> typeSubstitution})
- : super(typeSubstitution: typeSubstitution);
-
- @override
- TreeNode cloneFunctionNodeBody(FunctionNode node) => null;
-}
+export '../../clone.dart' show CloneWithoutBody;
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index 6e17f7d..a08802c 100644
--- a/pkg/kernel/pubspec.yaml
+++ b/pkg/kernel/pubspec.yaml
@@ -12,7 +12,7 @@
package_config: ^1.0.0
dev_dependencies:
analyzer: '>=0.30.0 <0.32.0'
- front_end: 0.1.0-alpha.10
+ front_end: 0.1.0-alpha.11
test: ^0.12.15+6
stack_trace: ^1.6.6
ansicolor: ^0.0.9
diff --git a/pkg/kernel/test/frontend_bench.dart b/pkg/kernel/test/frontend_bench.dart
deleted file mode 100644
index 78d01c2..0000000
--- a/pkg/kernel/test/frontend_bench.dart
+++ /dev/null
@@ -1,67 +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 'dart:io';
-import 'package:analyzer/src/context/cache.dart';
-import 'package:analyzer/task/model.dart';
-import 'package:args/args.dart';
-import 'package:analyzer/src/kernel/loader.dart';
-import 'package:kernel/kernel.dart';
-import 'package:package_config/discovery.dart';
-
-ArgParser parser = new ArgParser()
- ..addOption('sdk',
- help: 'Path to Dart SDK', valueHelp: 'path', defaultsTo: '/usr/lib/dart')
- ..addOption('packages',
- abbr: 'p',
- help: 'Path to the packages folder or .packages file',
- valueHelp: 'path')
- ..addFlag('strong', help: 'Use strong mode');
-
-String get usage => '''
-Usage: frontend_bench [options] FILE.dart
-
-Benchmark the analyzer-based frontend.
-
-Options:
-${parser.options}
-''';
-
-main(List<String> args) {
- if (args.length == 0) {
- print(usage);
- exit(1);
- }
- ArgResults options = parser.parse(args);
-
- if (options.rest.length != 1) {
- print('Exactly one file must be given');
- exit(1);
- }
-
- String sdk = options['sdk'];
- String packagePath = options['packages'];
- bool strongMode = options['strong'];
-
- String path = options.rest.single;
- var uri = new Uri(scheme: 'file', path: new File(path).absolute.path);
- var packages =
- getPackagesDirectory(new Uri(scheme: 'file', path: packagePath));
- Component repository = new Component();
-
- new DartLoader(
- repository,
- new DartOptions(
- strongMode: strongMode, sdk: sdk, packagePath: packagePath),
- packages)
- .loadComponent(uri);
-
- CacheEntry.recomputedCounts.forEach((key, value) {
- print('Recomputed $key $value times');
- });
-
- AnalysisTask.stopwatchMap.forEach((key, Stopwatch watch) {
- print('$key took ${watch.elapsedMilliseconds} ms');
- });
-}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index a742edc..a03128c 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -116,7 +116,7 @@
front_end/test/fasta/ast_builder_test: Pass, Slow, Timeout
front_end/test/fasta/bootstrap_test: Skip # Issue 31902
front_end/test/fasta/strong_test: Pass, Slow, Timeout
-front_end/test/incremental_load_from_dill_test: Pass, Slow
+front_end/test/incremental_dart2js_load_from_dill_test: Pass, Slow
front_end/test/src/incremental/hot_reload_e2e_test: Skip # Issue 31901
front_end/test/whole_program_test: Skip # Issue 31902
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 15ee47f..341207f 100644
--- a/pkg/vm/lib/frontend_server.dart
+++ b/pkg/vm/lib/frontend_server.dart
@@ -256,7 +256,6 @@
printer.writeComponentFile(component);
await sink.close();
_outputStream.writeln('$boundaryKey $_kernelBinaryFilename');
-
final String depfile = options['depfile'];
if (depfile != null) {
await _writeDepfile(component, _kernelBinaryFilename, depfile);
@@ -270,6 +269,10 @@
Future<Null> invalidateIfBootstrapping() async {
if (_kernelBinaryFilename != _kernelBinaryFilenameFull) return null;
+ // If the generator is initialized bootstrapping is not in effect anyway,
+ // so there's no reason to spend time invalidating what should be
+ // invalidated by the normal approach anyway.
+ if (_generator.initialized) return null;
try {
final File f = new File(_kernelBinaryFilenameFull);
@@ -342,7 +345,7 @@
@override
void resetIncrementalCompiler() {
- _generator = _createGenerator(new Uri.file(_kernelBinaryFilenameFull));
+ _generator.resetDeltaState();
_kernelBinaryFilename = _kernelBinaryFilenameFull;
}
diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart
index bfe5919..91d9426 100644
--- a/pkg/vm/lib/incremental_compiler.dart
+++ b/pkg/vm/lib/incremental_compiler.dart
@@ -17,6 +17,8 @@
IncrementalKernelGenerator _generator;
List<Component> _pendingDeltas;
CompilerOptions _compilerOptions;
+ bool initialized = false;
+ bool fullComponent = false;
IncrementalCompiler(this._compilerOptions, Uri entryPoint,
{Uri bootstrapDill}) {
@@ -30,7 +32,10 @@
/// If [entryPoint] is specified, that points to new entry point for the
/// compilation. Otherwise, previously set entryPoint is used.
Future<Component> compile({Uri entryPoint}) async {
- Component component = await _generator.computeDelta(entryPoint: entryPoint);
+ Component component = await _generator.computeDelta(
+ entryPoint: entryPoint, fullComponent: fullComponent);
+ initialized = true;
+ fullComponent = false;
final bool firstDelta = _pendingDeltas.isEmpty;
_pendingDeltas.add(component);
if (firstDelta) {
@@ -64,4 +69,9 @@
invalidate(Uri uri) {
_generator.invalidate(uri);
}
+
+ resetDeltaState() {
+ _pendingDeltas.clear();
+ fullComponent = true;
+ }
}
diff --git a/pkg/vm/lib/target/runner.dart b/pkg/vm/lib/target/dart_runner.dart
similarity index 83%
rename from pkg/vm/lib/target/runner.dart
rename to pkg/vm/lib/target/dart_runner.dart
index 3b7ce0c..fe75c94 100644
--- a/pkg/vm/lib/target/runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -1,16 +1,19 @@
// 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.
-library kernel.target.runner;
+library kernel.target.dart_runner;
import 'package:kernel/target/targets.dart';
import 'package:kernel/target/vm.dart' show VmTarget;
-class RunnerTarget extends VmTarget {
- RunnerTarget(TargetFlags flags) : super(flags);
+class DartRunnerTarget extends VmTarget {
+ DartRunnerTarget(TargetFlags flags) : super(flags);
@override
- String get name => 'runner';
+ String get name => 'dart_runner';
+
+ @override
+ bool get enableSuperMixins => true;
// This is the order that bootstrap libraries are loaded according to
// `runtime/vm/object_store.h`.
diff --git a/pkg/vm/lib/target/runner.dart b/pkg/vm/lib/target/flutter_runner.dart
similarity index 76%
copy from pkg/vm/lib/target/runner.dart
copy to pkg/vm/lib/target/flutter_runner.dart
index 3b7ce0c..8878c01 100644
--- a/pkg/vm/lib/target/runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -1,16 +1,19 @@
// 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.
-library kernel.target.runner;
+library kernel.target.flutter_runner;
import 'package:kernel/target/targets.dart';
import 'package:kernel/target/vm.dart' show VmTarget;
-class RunnerTarget extends VmTarget {
- RunnerTarget(TargetFlags flags) : super(flags);
+class FlutterRunnerTarget extends VmTarget {
+ FlutterRunnerTarget(TargetFlags flags) : super(flags);
@override
- String get name => 'runner';
+ String get name => 'flutter_runner';
+
+ @override
+ bool get enableSuperMixins => true;
// This is the order that bootstrap libraries are loaded according to
// `runtime/vm/object_store.h`.
@@ -33,10 +36,12 @@
'dart:nativewrappers',
'dart:io',
- // Required for dart_runner.
+ // Required for flutter_runner.
'dart:fuchsia.builtin',
'dart:zircon',
'dart:fuchsia',
'dart:vmservice_io',
+ 'dart:ui',
+ 'dart:mozart.internal',
];
}
diff --git a/pkg/vm/test/frontend_server_test.dart b/pkg/vm/test/frontend_server_test.dart
index 3279881..bc18e95 100644
--- a/pkg/vm/test/frontend_server_test.dart
+++ b/pkg/vm/test/frontend_server_test.dart
@@ -377,6 +377,7 @@
final _MockedIncrementalCompiler generator =
new _MockedIncrementalCompiler();
+ when(generator.initialized).thenAnswer((_) => false);
when(generator.compile())
.thenAnswer((_) => new Future<Component>.value(new Component()));
final _MockedBinaryPrinterFactory printerFactory =
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
index f15ef86..9971701 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/no_such_method.dart.expect
@@ -52,6 +52,9 @@
method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T1::•();
}
+ abstract no-such-method-forwarder get bar() → dynamic;
+ abstract no-such-method-forwarder method foo() → dynamic;
+ abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
}
class C extends core::Object {
synthetic constructor •() → void
@@ -65,6 +68,9 @@
synthetic constructor •() → void
: super self::C::•()
;
+ abstract no-such-method-forwarder get bar() → dynamic;
+ abstract no-such-method-forwarder method foo() → dynamic;
+ abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
}
class E extends core::Object implements self::A {
synthetic constructor •() → void
@@ -75,6 +81,8 @@
method noSuchMethod(core::Invocation invocation) → dynamic {
return new self::T4::•();
}
+ abstract no-such-method-forwarder get bar() → dynamic;
+ abstract no-such-method-forwarder method bazz(dynamic a1, dynamic a2, dynamic a3, [dynamic a4, dynamic a5]) → dynamic;
}
class F extends core::Object {
synthetic constructor •() → void
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index e23ba23..8043ec0 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -368,6 +368,7 @@
if (File::GetType(NULL, filename, true) == File::kIsFile) {
File* file = File::Open(NULL, filename, File::kRead);
if (file != NULL) {
+ RefCntReleaseScope<File> rs(file);
intptr_t max_magic_length = 0;
max_magic_length =
Utils::Maximum(max_magic_length, snapshot_magic_number.length);
@@ -382,7 +383,6 @@
if (file->ReadFully(&header, max_magic_length)) {
magic_number = DartUtils::SniffForMagicNumber(header, sizeof(header));
}
- file->Close();
}
}
return magic_number;
diff --git a/runtime/bin/extensions_fuchsia.cc b/runtime/bin/extensions_fuchsia.cc
index 540963f..34aa8d0 100644
--- a/runtime/bin/extensions_fuchsia.cc
+++ b/runtime/bin/extensions_fuchsia.cc
@@ -30,7 +30,7 @@
return NULL;
}
zx_handle_t vmo;
- zx_status_t status = fdio_get_vmo(fd, &vmo);
+ zx_status_t status = fdio_get_vmo_clone(fd, &vmo);
close(fd);
if (status != ZX_OK) {
return NULL;
diff --git a/runtime/bin/run_vm_tests.cc b/runtime/bin/run_vm_tests.cc
index 31ecf76..d5d6ff0 100644
--- a/runtime/bin/run_vm_tests.cc
+++ b/runtime/bin/run_vm_tests.cc
@@ -165,7 +165,6 @@
DART_KERNEL_ISOLATE_NAME, main, isolate_snapshot_data,
isolate_snapshot_instructions, flags, isolate_data, error);
if (isolate == NULL) {
- *error = strdup("Failed to create isolate");
delete isolate_data;
return NULL;
}
diff --git a/runtime/lib/bigint_patch.dart b/runtime/lib/bigint_patch.dart
index 08bcf47..331dd25 100644
--- a/runtime/lib/bigint_patch.dart
+++ b/runtime/lib/bigint_patch.dart
@@ -540,6 +540,7 @@
/// Note: This function may be intrinsified.
static void _lsh(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+ assert(xUsed > 0);
final digitShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -569,6 +570,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be positive $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -611,6 +613,7 @@
/// Note: This function may be intrinsified.
static void _rsh(
Uint32List xDigits, int xUsed, int n, Uint32List resultDigits) {
+ assert(xUsed > 0);
final digitsShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -638,6 +641,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be positive $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -902,6 +906,7 @@
*/
_BigIntImpl operator &(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -941,6 +946,8 @@
*/
_BigIntImpl operator |(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -981,6 +988,8 @@
*/
_BigIntImpl operator ^(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1015,6 +1024,7 @@
* This maps any integer `x` to `-x - 1`.
*/
_BigIntImpl operator ~() {
+ if (_isZero) return _minusOne;
if (_isNegative) {
// ~(-this) == ~(~(this-1)) == this-1
return _absSubSetSign(one, false);
@@ -1027,6 +1037,8 @@
/// Addition operator.
_BigIntImpl operator +(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative == other._isNegative) {
// this + other == this + other
@@ -1044,6 +1056,8 @@
/// Subtraction operator.
_BigIntImpl operator -(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return -other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative != other._isNegative) {
// this - (-other) == this + other
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index bd8e1ab..2917008 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -286,6 +286,12 @@
static uint32_t HostToLittleEndian32(uint32_t host_value);
static uint64_t HostToLittleEndian64(uint64_t host_value);
+ static uint32_t BigEndianToHost32(uint32_t be_value) {
+ // Going between Host <-> BE is the same operation for all practical
+ // purposes.
+ return HostToBigEndian32(be_value);
+ }
+
static bool DoublesBitEqual(const double a, const double b) {
return bit_cast<int64_t, double>(a) == bit_cast<int64_t, double>(b);
}
diff --git a/runtime/tests/vm/dart/regress32597_test.dart b/runtime/tests/vm/dart/regress32597_test.dart
new file mode 100644
index 0000000..969af09
--- /dev/null
+++ b/runtime/tests/vm/dart/regress32597_test.dart
@@ -0,0 +1,40 @@
+// 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.
+
+// Regression test for dartbug.com/32597: incorrect type was assigned to phi
+// in strong mode.
+
+// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
+
+class Token {
+ Token next;
+}
+
+class StringToken extends Token {}
+
+class ErrorToken extends Token {}
+
+void foo(Token tokens) {
+ Token current = tokens;
+ for (int i = 0; i < 1; i++) {
+ while (current is ErrorToken) {
+ ErrorToken first = current;
+ // Loading phi (created for local variable 'current') from another local
+ // variable ('first') with more specific type should not change the type
+ // assigned to phi.
+ print(first);
+ }
+ current = current.next;
+ }
+}
+
+void main() {
+ Token token = new StringToken();
+ token.next = token;
+
+ for (int i = 0; i < 100; i++) {
+ foo(token);
+ }
+ print('ok');
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 983023c..0d9f1cd 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -64,9 +64,9 @@
dart/redirection_type_shuffling_test/none: RuntimeError
[ $compiler != dartk ]
-cc/IsolateReload_KernelIncrementalCompile: Skip
-cc/IsolateReload_KernelIncrementalCompileAppAndLib: Skip
-cc/IsolateReload_KernelIncrementalCompileGenerics: Skip
+cc/IsolateReload_KernelIncrementalCompile: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileAppAndLib: SkipByDesign
+cc/IsolateReload_KernelIncrementalCompileGenerics: SkipByDesign
cc/Mixin_PrivateSuperResolution: Skip
cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Skip
@@ -77,7 +77,7 @@
dart/byte_array_test: Skip # Incompatible flag --disable_alloc_stubs_after_gc
[ $mode == debug ]
-cc/CorelibIsolateStartup: Skip # This is a benchmark that is not informative in debug mode.
+cc/CorelibIsolateStartup: SkipByDesign # This is a benchmark that is not informative in debug mode.
cc/VerifyExplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
cc/VerifyImplicit_Crash: Crash # Negative tests of VerifiedMemory should crash iff in DEBUG mode. TODO(koda): Improve support for negative tests.
dart/spawn_shutdown_test: Pass, Slow # VM Shutdown test, It can take some time for all the isolates to shutdown in a Debug build.
@@ -88,8 +88,8 @@
[ $runtime != vm ]
dart/hello_fuchsia_test: SkipByDesign # This is a test for fuchsia OS
dart/snapshot_version_test: SkipByDesign # Spawns processes
-dart/spawn_infinite_loop_test: Skip # VM shutdown test
-dart/spawn_shutdown_test: Skip # VM Shutdown test
+dart/spawn_infinite_loop_test: SkipByDesign # VM shutdown test
+dart/spawn_shutdown_test: SkipByDesign # VM Shutdown test
[ $system == fuchsia ]
cc/CorelibIsolateStartup: Skip # OOM crash can bring down the OS.
@@ -142,7 +142,6 @@
*: Skip # Issue 28649
[ $compiler == dartk && $mode == debug && $runtime == vm ]
-cc/InjectNativeFields1: Crash
cc/PrintJSON: Crash
cc/Service_TokenStream: Crash
@@ -154,16 +153,12 @@
[ $compiler == dartk && $mode == release && $runtime == vm ]
cc/CorelibIsolateStartup: Timeout, Pass
-cc/InjectNativeFields1: Fail
cc/Service_TokenStream: Fail
[ $compiler == dartk && $runtime == vm ]
cc/CanonicalizationInScriptSnapshots: Fail
cc/Class_ComputeEndTokenPos: Crash
-cc/DartAPI_CurrentStackTraceInfo: Fail
-cc/DartAPI_InjectNativeFields1: Skip
cc/DartAPI_InvokeNoSuchMethod: Fail
-cc/DartAPI_Invoke_CrossLibrary: Crash
cc/DartAPI_IsolateSetCheckedMode: Skip # Checked mode is not relevant for dart 2?
cc/DartAPI_IsolateShutdownRunDartCode: Skip # Flaky
cc/DartAPI_LazyLoadDeoptimizes: Fail
@@ -175,10 +170,7 @@
cc/DartAPI_LoadPatchSignatureMismatch: Crash
cc/DartAPI_LoadSource: Crash
cc/DartAPI_LoadSource_LateLoad: Crash
-cc/DartAPI_LookupLibrary: Crash
-cc/DartAPI_NativeFieldAccess: Fail
cc/DartAPI_ParsePatchLibrary: Crash
-cc/DartAPI_PropagateError: Fail
cc/DartAPI_StackOverflowStackTraceInfoArrowFunction: Fail
cc/DartAPI_StackOverflowStackTraceInfoBraceFunction1: Fail
cc/DartAPI_StackOverflowStackTraceInfoBraceFunction2: Fail
@@ -195,12 +187,6 @@
cc/GenerateSource: Skip # Cannot generate source from a kernel binary.
cc/IsolateReload_NotTypedefToTypedef: Fail
cc/IsolateReload_TypedefToNotTypedef: Fail
-cc/Parser_AllocateVariables_CaptureLoopVar: Fail
-cc/Parser_AllocateVariables_CapturedVar: Fail
-cc/Parser_AllocateVariables_Issue7681: Fail
-cc/Parser_AllocateVariables_MiddleChain: Fail
-cc/Parser_AllocateVariables_NestedCapturedVar: Fail
-cc/Parser_AllocateVariables_TwoChains: Fail
cc/Profiler_BasicSourcePositionOptimized: Skip
cc/Profiler_BinaryOperatorSourcePositionOptimized: Skip
cc/Profiler_GetSourceReport: Fail
@@ -245,11 +231,6 @@
cc/IsolateReload_TearOff_AddArguments: Fail
cc/IsolateReload_TearOff_Instance_Equality: Fail
cc/IsolateReload_TearOff_List_Set: Fail
-cc/Parser_AllocateVariables_CaptureLoopVar: Crash
-cc/Parser_AllocateVariables_Issue7681: Crash
-cc/Parser_AllocateVariables_MiddleChain: Crash
-cc/Parser_AllocateVariables_NestedCapturedVar: Crash
-cc/Parser_AllocateVariables_TwoChains: Crash
[ $compiler == dartk && $runtime == vm && $strong ]
cc/IsolateReload_LibraryHide: Crash
@@ -279,14 +260,13 @@
cc/DartAPI_NativePortPostInteger: Crash # Issue 32190
cc/DartAPI_NativePortReceiveInteger: Timeout # Issue 32190
cc/DartAPI_NativePortReceiveNull: Timeout # Issue 32190
-cc/DartAPI_NewNativePort: Crash,Timeout # Issue 32190
+cc/DartAPI_NewNativePort: Crash, Timeout # Issue 32190
cc/DartGeneratedArrayLiteralMessages: Crash # Issue 32190
cc/FullSnapshot1: Crash # Issue 32190
cc/IsolateReload_LibraryImportAdded: Crash # Issue 32190
cc/IsolateReload_LibraryImportRemoved: Fail # Issue 32190
cc/IsolateReload_LibraryLookup: Fail, Crash # Issue 32190
cc/Mixin_PrivateSuperResolutionCrossLibraryShouldFail: Fail, Crash # Issue 32190
-cc/StackMapGC: Crash # Issue 32190
# Enabling of dartk for sim{arm,arm64,dbc64} revelaed these test failures, which
# are to be triaged. Isolate tests are skipped on purpose due to the usage of
@@ -363,6 +343,15 @@
[ $compiler == dart2analyzer || $compiler == dart2js ]
dart/data_uri*test: Skip # Data uri's not supported by dart2js or the analyzer.
+# Tests for VM parser aren't valid for Dart 2.
+[ $compiler == dartk || $compiler == dartkp ]
+cc/Parser_AllocateVariables_CaptureLoopVar: SkipByDesign
+cc/Parser_AllocateVariables_CapturedVar: SkipByDesign
+cc/Parser_AllocateVariables_Issue7681: SkipByDesign
+cc/Parser_AllocateVariables_MiddleChain: SkipByDesign
+cc/Parser_AllocateVariables_NestedCapturedVar: SkipByDesign
+cc/Parser_AllocateVariables_TwoChains: SkipByDesign
+
[ $compiler == precompiler || $mode == product ]
cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
diff --git a/runtime/vm/allocation.cc b/runtime/vm/allocation.cc
index 93ee9d0..b1a7e93 100644
--- a/runtime/vm/allocation.cc
+++ b/runtime/vm/allocation.cc
@@ -69,7 +69,9 @@
}
#if defined(DEBUG)
-NoSafepointScope::NoSafepointScope() : StackResource(Thread::Current()) {
+NoSafepointScope::NoSafepointScope(Thread* current_thread)
+ : StackResource(current_thread != nullptr ? current_thread
+ : Thread::Current()) {
thread()->IncrementNoSafepointScopeDepth();
}
diff --git a/runtime/vm/allocation.h b/runtime/vm/allocation.h
index 3442acf..b9af2f9 100644
--- a/runtime/vm/allocation.h
+++ b/runtime/vm/allocation.h
@@ -82,7 +82,7 @@
#if defined(DEBUG)
class NoSafepointScope : public StackResource {
public:
- NoSafepointScope();
+ explicit NoSafepointScope(Thread* thread = nullptr);
~NoSafepointScope();
private:
@@ -91,7 +91,7 @@
#else // defined(DEBUG)
class NoSafepointScope : public ValueObject {
public:
- NoSafepointScope() {}
+ explicit NoSafepointScope(Thread* thread = nullptr) {}
private:
DISALLOW_COPY_AND_ASSIGN(NoSafepointScope);
diff --git a/runtime/vm/code_descriptors_test.cc b/runtime/vm/code_descriptors_test.cc
index aaa7fc1..b67e93d 100644
--- a/runtime/vm/code_descriptors_test.cc
+++ b/runtime/vm/code_descriptors_test.cc
@@ -202,7 +202,7 @@
" return i + k; }"
" static int moo() {"
" var i = A.foo();"
- " Expect.equals(30, i);"
+ " if (i != 30) throw '$i != 30';"
" }\n"
"}\n";
// First setup the script and compile the script.
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index febb84c..77ca3cb 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -1191,8 +1191,12 @@
if ((phi != NULL) && isolate()->strong() &&
FLAG_use_strong_mode_types) {
- phi->UpdateType(
- CompileType::FromAbstractType(load->local().type()));
+ // Assign type to phi only if phi was not copied from another local.
+ const auto* phis = phi->block()->phis();
+ if ((index < phis->length()) && ((*phis)[index] == phi)) {
+ phi->UpdateType(
+ CompileType::FromAbstractType(load->local().type()));
+ }
}
} else if (drop != NULL) {
// Drop temps from the environment.
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 22f92eb..3a7ad08 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -8,6 +8,8 @@
#include "vm/compiler/jit/compiler.h"
#include "vm/longjump.h"
#include "vm/object_store.h"
+#include "vm/resolver.h"
+#include "vm/stack_frame.h"
#if !defined(DART_PRECOMPILED_RUNTIME)
@@ -18,6 +20,7 @@
#define H (translation_helper_)
#define T (type_translator_)
#define I Isolate::Current()
+#define B (flow_graph_builder_)
static bool IsFieldInitializer(const Function& function, Zone* zone) {
return (function.kind() == RawFunction::kImplicitStaticFinalGetter) &&
@@ -217,6 +220,7 @@
if (++next_read_ == field) return;
case kFlags:
flags_ = builder_->ReadFlags();
+ flags2_ = builder_->ReadFlags();
if (++next_read_ == field) return;
case kName:
builder_->SkipName(); // read name.
@@ -1084,7 +1088,7 @@
case RawFunction::kIrregexpFunction:
UNREACHABLE();
}
- if (needs_expr_temp_) {
+ if (needs_expr_temp_ || parsed_function_->is_no_such_method_forwarder()) {
scope_->AddVariable(parsed_function_->EnsureExpressionTemp());
}
parsed_function_->AllocateVariables();
@@ -3747,8 +3751,8 @@
}
}
-void StreamingFlowGraphBuilder::ReadUntilFunctionNode(
- ParsedFunction* set_forwarding_stub) {
+bool StreamingFlowGraphBuilder::ReadUntilFunctionNode(
+ ParsedFunction* parsed_function) {
const Tag tag = PeekTag();
if (tag == kProcedure) {
ProcedureHelper procedure_helper(this);
@@ -3757,17 +3761,22 @@
// Running a procedure without a function node doesn't make sense.
UNREACHABLE();
}
- if (set_forwarding_stub != NULL && flow_graph_builder_ &&
+ if (parsed_function != NULL && flow_graph_builder_ != nullptr &&
procedure_helper.IsForwardingStub() && !procedure_helper.IsAbstract()) {
ASSERT(procedure_helper.forwarding_stub_super_target_ != -1);
- set_forwarding_stub->MarkForwardingStub(
+ parsed_function->MarkForwardingStub(
procedure_helper.forwarding_stub_super_target_);
}
+ if (parsed_function != NULL && flow_graph_builder_ != nullptr &&
+ procedure_helper.IsNoSuchMethodForwarder()) {
+ parsed_function->set_is_no_such_method_forwarder(true);
+ }
+ return procedure_helper.IsNoSuchMethodForwarder();
// Now at start of FunctionNode.
} else if (tag == kConstructor) {
ConstructorHelper constructor_helper(this);
constructor_helper.ReadUntilExcluding(ConstructorHelper::kFunction);
- return;
+ return false;
// Now at start of FunctionNode.
// Notice that we also have a list of initializers after that!
} else if (tag == kFunctionNode) {
@@ -3776,6 +3785,7 @@
ReportUnexpectedTag("a procedure, a constructor or a function node", tag);
UNREACHABLE();
}
+ return false;
}
StringIndex StreamingFlowGraphBuilder::GetNameFromVariableDeclaration(
@@ -4322,6 +4332,219 @@
flow_graph_builder_->last_used_block_id_, prologue_info);
}
+FlowGraph* StreamingFlowGraphBuilder::BuildGraphOfNoSuchMethodForwarder(
+ const Function& function,
+ bool is_implicit_closure_function) {
+ // The prologue builder needs the default parameter values.
+ SetupDefaultParameterValues();
+
+ TargetEntryInstr* normal_entry = B->BuildTargetEntry();
+ PrologueInfo prologue_info(-1, -1);
+ BlockEntryInstr* instruction_cursor =
+ B->BuildPrologue(normal_entry, &prologue_info);
+
+ B->graph_entry_ = new (Z) GraphEntryInstr(*parsed_function(), normal_entry,
+ Compiler::kNoOSRDeoptId);
+
+ Fragment body(instruction_cursor);
+ body += B->CheckStackOverflowInPrologue();
+
+ // If we are inside the tearoff wrapper function (implicit closure), we need
+ // to extract the receiver from the context. We just replace it directly on
+ // the stack to simplify the rest of the code.
+ if (is_implicit_closure_function) {
+ if (parsed_function()->has_arg_desc_var()) {
+ body += B->LoadArgDescriptor();
+ body += LoadField(ArgumentsDescriptor::count_offset());
+ body += LoadLocal(parsed_function()->current_context_var());
+ body += B->LoadField(Context::variable_offset(0));
+ body += B->StoreFpRelativeSlot(kWordSize * kParamEndSlotFromFp);
+ body += Drop();
+ } else {
+ body += LoadLocal(parsed_function()->current_context_var());
+ body += B->LoadField(Context::variable_offset(0));
+ body += B->StoreFpRelativeSlot(
+ kWordSize * (kParamEndSlotFromFp + function.NumParameters()));
+ body += Drop();
+ }
+ }
+
+ FunctionNodeHelper function_node_helper(this);
+ function_node_helper.ReadUntilExcluding(FunctionNodeHelper::kTypeParameters);
+
+ if (function.NeedsArgumentTypeChecks(I)) {
+ AlternativeReadingScope _(reader_);
+ body += BuildArgumentTypeChecks();
+ }
+
+ function_node_helper.ReadUntilExcluding(
+ FunctionNodeHelper::kPositionalParameters);
+
+ body += NullConstant();
+ LocalVariable* result = MakeTemporary();
+
+ // Do "++argument_count" if any type arguments were passed.
+ LocalVariable* argument_count_var = parsed_function()->expression_temp_var();
+ body += IntConstant(0);
+ body += StoreLocal(TokenPosition::kNoSource, argument_count_var);
+ body += Drop();
+ if (function.IsGeneric() && Isolate::Current()->reify_generic_functions()) {
+ Fragment test_generic;
+ JoinEntryInstr* join = BuildJoinEntry();
+
+ TargetEntryInstr *passed_type_args, *not_passed_type_args;
+ test_generic += B->LoadArgDescriptor();
+ test_generic += LoadField(ArgumentsDescriptor::type_args_len_offset());
+ test_generic += IntConstant(0);
+ test_generic += BranchIfEqual(¬_passed_type_args, &passed_type_args,
+ /*negate=*/false);
+
+ Fragment passed_type_args_frag(passed_type_args);
+ passed_type_args_frag += IntConstant(1);
+ passed_type_args_frag +=
+ StoreLocal(TokenPosition::kNoSource, argument_count_var);
+ passed_type_args_frag += Drop();
+ passed_type_args_frag += Goto(join);
+
+ Fragment not_passed_type_args_frag(not_passed_type_args);
+ not_passed_type_args_frag += Goto(join);
+
+ body += Fragment(test_generic.entry, join);
+ }
+
+ if (function.HasOptionalParameters()) {
+ body += B->LoadArgDescriptor();
+ body += LoadField(ArgumentsDescriptor::count_offset());
+ } else {
+ body += IntConstant(function.NumParameters());
+ }
+ body += LoadLocal(argument_count_var);
+ body += B->SmiBinaryOp(Token::kADD, /* truncate= */ true);
+ LocalVariable* argument_count = MakeTemporary();
+
+ // We are generating code like the following:
+ //
+ // var arguments = new Array<dynamic>(argument_count);
+ //
+ // for (int i = 0; i < argument_count; ++i) {
+ // arguments[i] = LoadFpRelativeSlot(
+ // kWordSize * (kParamEndSlotFromFp + argument_count - i));
+ // }
+ body += Constant(TypeArguments::ZoneHandle(Z, TypeArguments::null()));
+ body += LoadLocal(argument_count);
+ body += CreateArray();
+ LocalVariable* arguments = MakeTemporary();
+
+ {
+ // int i = 0
+ LocalVariable* index = parsed_function()->expression_temp_var();
+ body += IntConstant(0);
+ body += StoreLocal(TokenPosition::kNoSource, index);
+ body += Drop();
+
+ TargetEntryInstr* body_entry;
+ TargetEntryInstr* loop_exit;
+
+ Fragment condition;
+ // i < argument_count
+ condition += LoadLocal(index);
+ condition += LoadLocal(argument_count);
+ condition += B->SmiRelationalOp(Token::kLT);
+ condition += BranchIfTrue(&body_entry, &loop_exit, /*negate=*/false);
+
+ Fragment loop_body(body_entry);
+
+ // arguments[i] = LoadFpRelativeSlot(
+ // kWordSize * (kParamEndSlotFromFp + argument_count - i));
+ loop_body += LoadLocal(arguments);
+ loop_body += LoadLocal(index);
+ loop_body += LoadLocal(argument_count);
+ loop_body += LoadLocal(index);
+ loop_body += B->SmiBinaryOp(Token::kSUB, /*truncate=*/true);
+ loop_body += B->LoadFpRelativeSlot(kWordSize * kParamEndSlotFromFp);
+ loop_body += StoreIndexed(kArrayCid);
+ loop_body += Drop();
+
+ // ++i
+ loop_body += LoadLocal(index);
+ loop_body += IntConstant(1);
+ loop_body += B->SmiBinaryOp(Token::kADD, /*truncate=*/true);
+ loop_body += StoreLocal(TokenPosition::kNoSource, index);
+ loop_body += Drop();
+
+ JoinEntryInstr* join = BuildJoinEntry();
+ loop_body += Goto(join);
+
+ Fragment loop(join);
+ loop += condition;
+
+ Instruction* entry =
+ new (Z) GotoInstr(join, Thread::Current()->GetNextDeoptId());
+ body += Fragment(entry, loop_exit);
+ }
+
+ // Load receiver.
+ if (is_implicit_closure_function) {
+ body += LoadLocal(parsed_function()->current_context_var());
+ body += B->LoadField(Context::variable_offset(0));
+ } else {
+ LocalScope* scope = parsed_function()->node_sequence()->scope();
+ body += LoadLocal(scope->VariableAt(0));
+ }
+ body += PushArgument();
+
+ body += Constant(String::ZoneHandle(Z, function.name()));
+ body += PushArgument();
+
+ if (!parsed_function()->has_arg_desc_var()) {
+ // If there is no variable for the arguments descriptor (this function's
+ // signature doesn't require it), then we need to create one.
+ Array& args_desc = Array::ZoneHandle(
+ Z, ArgumentsDescriptor::New(0, function.NumParameters()));
+ body += Constant(args_desc);
+ } else {
+ body += B->LoadArgDescriptor();
+ }
+ body += PushArgument();
+
+ body += LoadLocal(arguments);
+ body += PushArgument();
+
+ // false -> this is not super NSM
+ body += Constant(Bool::False());
+ body += PushArgument();
+
+ const Class& mirror_class =
+ Class::Handle(Z, Library::LookupCoreClass(Symbols::InvocationMirror()));
+ ASSERT(!mirror_class.IsNull());
+ const Function& allocation_function = Function::ZoneHandle(
+ Z, mirror_class.LookupStaticFunction(
+ Library::PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
+ ASSERT(!allocation_function.IsNull());
+ body += StaticCall(TokenPosition::kMinSource, allocation_function,
+ /* argument_count = */ 4, ICData::kStatic);
+ body += PushArgument(); // For the call to noSuchMethod.
+
+ body += InstanceCall(TokenPosition::kNoSource, Symbols::NoSuchMethod(),
+ Token::kILLEGAL, 2, 1);
+ body += StoreLocal(TokenPosition::kNoSource, result);
+ body += Drop();
+
+ body += Drop(); // arguments
+ body += Drop(); // argument count
+
+ AbstractType& return_type = AbstractType::Handle(function.result_type());
+ if (!return_type.IsDynamicType() && !return_type.IsVoidType() &&
+ !return_type.IsObjectType()) {
+ body += flow_graph_builder_->AssertAssignable(
+ TokenPosition::kNoSource, return_type, Symbols::Empty());
+ }
+ body += Return(TokenPosition::kNoSource);
+
+ return new (Z) FlowGraph(*parsed_function(), B->graph_entry_,
+ B->last_used_block_id_, prologue_info);
+}
+
Fragment StreamingFlowGraphBuilder::BuildArgumentTypeChecks(
TypeChecksToBuild mode /*= kDefaultTypeChecks*/) {
FunctionNodeHelper function_node_helper(this);
@@ -4783,6 +5006,18 @@
ActiveMemberScope active_member(active_class(), &outermost_function);
ActiveTypeParametersScope active_type_params(active_class(), function, Z);
+ SetOffset(kernel_offset);
+
+ // We need to read out the NSM-forwarder bit before we can build scopes.
+ switch (function.kind()) {
+ case RawFunction::kImplicitClosureFunction:
+ case RawFunction::kRegularFunction: {
+ AlternativeReadingScope alt(reader_);
+ ReadUntilFunctionNode(parsed_function()); // read until function node.
+ }
+ default: {}
+ }
+
// The IR builder will create its own local variables and scopes, and it
// will not need an AST. The code generator will assume that there is a
// local variable stack slot allocated for the current context and (I
@@ -4790,19 +5025,21 @@
// requires allocating an unused expression temporary variable.
set_scopes(parsed_function()->EnsureKernelScopes());
- SetOffset(kernel_offset);
-
switch (function.kind()) {
- case RawFunction::kClosureFunction:
- case RawFunction::kImplicitClosureFunction:
- case RawFunction::kConvertedClosureFunction:
case RawFunction::kRegularFunction:
+ case RawFunction::kImplicitClosureFunction:
+ if (ReadUntilFunctionNode(parsed_function())) {
+ return BuildGraphOfNoSuchMethodForwarder(
+ function, function.IsImplicitClosureFunction());
+ } else if (function.IsImplicitClosureFunction()) {
+ return BuildGraphOfImplicitClosureFunction(function);
+ }
+ // fallthrough intended
+ case RawFunction::kClosureFunction:
+ case RawFunction::kConvertedClosureFunction:
case RawFunction::kGetterFunction:
case RawFunction::kSetterFunction: {
ReadUntilFunctionNode(parsed_function()); // read until function node.
- if (function.IsImplicitClosureFunction()) {
- return BuildGraphOfImplicitClosureFunction(function);
- }
return BuildGraphOfFunction(false);
}
case RawFunction::kConstructor: {
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index 40d1d89..7db1719 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -276,6 +276,10 @@
kRedirectingFactoryConstructor = 1 << 7,
};
+ enum Flag2 {
+ kNoSuchMethodForwarder = 1 << 0,
+ };
+
explicit ProcedureHelper(StreamingFlowGraphBuilder* builder) {
builder_ = builder;
next_read_ = kStart;
@@ -298,12 +302,16 @@
bool IsRedirectingFactoryConstructor() {
return (flags_ & kRedirectingFactoryConstructor) != 0;
}
+ bool IsNoSuchMethodForwarder() {
+ return (flags2_ & kNoSuchMethodForwarder) != 0;
+ }
NameIndex canonical_name_;
TokenPosition position_;
TokenPosition end_position_;
Kind kind_;
uint8_t flags_;
+ uint8_t flags2_;
intptr_t source_uri_index_;
intptr_t annotation_count_;
@@ -1042,7 +1050,9 @@
// If a 'ParsedFunction' is provided for 'set_forwarding_stub', this method
// will attach the forwarding stub target reference to the parsed function if
// it crosses a procedure node for a concrete forwarding stub.
- void ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
+ //
+ // Returns 'true' if discovered a no-such-method forwarder.
+ bool ReadUntilFunctionNode(ParsedFunction* set_forwarding_stub = NULL);
intptr_t ReadListLength();
enum DispatchCategory { Interface, ViaThis, Closure, DynamicDispatch };
@@ -1071,7 +1081,9 @@
Fragment BuildInitializers(const Class& parent_class);
FlowGraph* BuildGraphOfImplicitClosureFunction(const Function& function);
FlowGraph* BuildGraphOfFunction(bool constructor);
- FlowGraph* BuildGraphOfForwardingStub(const Function& function);
+ FlowGraph* BuildGraphOfNoSuchMethodForwarder(
+ const Function& function,
+ bool is_implicit_closure_function);
intptr_t GetOffsetForSourceInfo(intptr_t index);
@@ -1156,8 +1168,10 @@
const TypeArguments& PeekArgumentsInstantiatedType(const Class& klass);
intptr_t PeekArgumentsCount();
- LocalVariable* LookupVariable(intptr_t kernel_offset);
+ // See BaseFlowGraphBuilder::MakeTemporary.
LocalVariable* MakeTemporary();
+
+ LocalVariable* LookupVariable(intptr_t kernel_offset);
RawFunction* LookupMethodByMember(NameIndex target,
const String& method_name);
Function& FindMatchingFunctionAnyArgs(const Class& klass, const String& name);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 2e5356c..a354661 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1457,7 +1457,7 @@
ArgumentArray arguments = GetArguments(num_args);
NativeCallInstr* call =
new (Z) NativeCallInstr(name, function, FLAG_link_natives_lazily,
- TokenPosition::kNoSource, arguments);
+ function->end_token_pos(), arguments);
Push(call);
return Fragment(call);
}
@@ -2724,7 +2724,7 @@
}
static void ProcessTokenPositionsEntry(
- const TypedData& data,
+ const TypedData& kernel_data,
const Script& script,
const Script& entry_script,
intptr_t kernel_offset,
@@ -2733,24 +2733,22 @@
TranslationHelper* helper,
GrowableArray<intptr_t>* token_positions,
GrowableArray<intptr_t>* yield_positions) {
- if (data.IsNull() ||
- script.kernel_string_offsets() != entry_script.kernel_string_offsets()) {
+ if (kernel_data.IsNull()) {
return;
}
StreamingFlowGraphBuilder streaming_flow_graph_builder(
- helper, script, zone_, data, data_kernel_offset);
+ helper, script, zone_, kernel_data, data_kernel_offset);
streaming_flow_graph_builder.CollectTokenPositionsFor(
script.kernel_script_index(), entry_script.kernel_script_index(),
kernel_offset, token_positions, yield_positions);
}
-void CollectTokenPositionsFor(const Script& const_script) {
+void CollectTokenPositionsFor(const Script& interesting_script) {
Thread* thread = Thread::Current();
Zone* zone_ = thread->zone();
- Script& script = Script::Handle(Z, const_script.raw());
TranslationHelper helper(thread);
- helper.InitFromScript(script);
+ helper.InitFromScript(interesting_script);
GrowableArray<intptr_t> token_positions(10);
GrowableArray<intptr_t> yield_positions(1);
@@ -2759,9 +2757,13 @@
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(Z, isolate->object_store()->libraries());
Library& lib = Library::Handle(Z);
- Object& entry = Object::Handle();
+ Object& entry = Object::Handle(Z);
Script& entry_script = Script::Handle(Z);
TypedData& data = TypedData::Handle(Z);
+
+ auto& temp_array = Array::Handle(Z);
+ auto& temp_field = Field::Handle(Z);
+ auto& temp_function = Function::Handle(Z);
for (intptr_t i = 0; i < libs.Length(); i++) {
lib ^= libs.At(i);
DictionaryIterator it(lib);
@@ -2770,40 +2772,41 @@
data = TypedData::null();
if (entry.IsClass()) {
const Class& klass = Class::Cast(entry);
- entry_script = klass.script();
- if (!entry_script.IsNull() &&
- (script.kernel_script_index() ==
- entry_script.kernel_script_index()) &&
- (script.kernel_string_offsets() ==
- entry_script.kernel_string_offsets())) {
+ if (klass.script() == interesting_script.raw()) {
token_positions.Add(klass.token_pos().value());
}
if (klass.is_finalized()) {
- Array& array = Array::Handle(Z, klass.fields());
- Field& field = Field::Handle(Z);
- for (intptr_t i = 0; i < array.Length(); ++i) {
- field ^= array.At(i);
- if (field.kernel_offset() <= 0) {
+ temp_array = klass.fields();
+ for (intptr_t i = 0; i < temp_array.Length(); ++i) {
+ temp_field ^= temp_array.At(i);
+ if (temp_field.kernel_offset() <= 0) {
// Skip artificially injected fields.
continue;
}
- data = field.KernelData();
- entry_script = field.Script();
- ProcessTokenPositionsEntry(
- data, script, entry_script, field.kernel_offset(),
- field.KernelDataProgramOffset(), Z, &helper, &token_positions,
- &yield_positions);
+ entry_script = temp_field.Script();
+ if (entry_script.raw() != interesting_script.raw()) {
+ continue;
+ }
+ data = temp_field.KernelData();
+ ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+ temp_field.kernel_offset(),
+ temp_field.KernelDataProgramOffset(), Z,
+ &helper, &token_positions,
+ &yield_positions);
}
- array = klass.functions();
- Function& function = Function::Handle(Z);
- for (intptr_t i = 0; i < array.Length(); ++i) {
- function ^= array.At(i);
- data = function.KernelData();
- entry_script = function.script();
- ProcessTokenPositionsEntry(
- data, script, entry_script, function.kernel_offset(),
- function.KernelDataProgramOffset(), Z, &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();
+ 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(),
+ Z, &helper, &token_positions,
+ &yield_positions);
}
} else {
// Class isn't finalized yet: read the data attached to it.
@@ -2815,17 +2818,24 @@
const intptr_t class_offset = klass.kernel_offset();
entry_script = klass.script();
- ProcessTokenPositionsEntry(data, script, entry_script, class_offset,
- library_kernel_offset, Z, &helper,
- &token_positions, &yield_positions);
+ if (entry_script.raw() != interesting_script.raw()) {
+ continue;
+ }
+ ProcessTokenPositionsEntry(data, interesting_script, entry_script,
+ class_offset, library_kernel_offset, Z,
+ &helper, &token_positions,
+ &yield_positions);
}
} else if (entry.IsFunction()) {
- const Function& function = Function::Cast(entry);
- data = function.KernelData();
- entry_script = function.script();
- ProcessTokenPositionsEntry(data, script, entry_script,
- function.kernel_offset(),
- function.KernelDataProgramOffset(), Z,
+ temp_function ^= entry.raw();
+ 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(), Z,
&helper, &token_positions, &yield_positions);
} else if (entry.IsField()) {
const Field& field = Field::Cast(entry);
@@ -2833,9 +2843,12 @@
// Skip artificially injected fields.
continue;
}
- data = field.KernelData();
entry_script = field.Script();
- ProcessTokenPositionsEntry(data, script, entry_script,
+ if (entry_script.raw() != interesting_script.raw()) {
+ continue;
+ }
+ data = field.KernelData();
+ ProcessTokenPositionsEntry(data, interesting_script, entry_script,
field.kernel_offset(),
field.KernelDataProgramOffset(), Z, &helper,
&token_positions, &yield_positions);
@@ -2843,6 +2856,7 @@
}
}
+ Script& script = Script::Handle(Z, interesting_script.raw());
Array& array_object = Array::Handle(Z);
array_object = AsSortedDuplicateFreeArray(&token_positions);
script.set_debug_positions(array_object);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index cd5ffd4..50c607c 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -562,6 +562,25 @@
// Drop given number of temps from the stack but preserve top of the stack.
Fragment DropTempsPreserveTop(intptr_t num_temps_to_drop);
+ // Create a pseudo-local variable for a location on the expression stack.
+ // Note: SSA construction currently does not support inserting Phi functions
+ // for expression stack locations - only real local variables are supported.
+ // This means that you can't use MakeTemporary in a way that would require
+ // a Phi in SSA form. For example example below will be miscompiled or
+ // will crash debug VM with assertion when building SSA for optimizing
+ // compiler:
+ //
+ // t = MakeTemporary()
+ // Branch B1 or B2
+ // B1:
+ // StoreLocal(t, v0)
+ // goto B3
+ // B2:
+ // StoreLocal(t, v1)
+ // goto B3
+ // B3:
+ // LoadLocal(t)
+ //
LocalVariable* MakeTemporary();
Fragment PushArgument();
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 67ae5b3..1203498 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -146,14 +146,15 @@
V(_Smi, ~, Smi_bitNegate, Smi, 0x67299f4f) \
V(_Smi, get:bitLength, Smi_bitLength, Smi, 0x25b3cb0a) \
V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, Smi, 0x562d5047) \
- V(_Bigint, _lsh, Bigint_lsh, Dynamic, 0x7b99f80e) \
- V(_Bigint, _rsh, Bigint_rsh, Dynamic, 0x5262b3a1) \
- V(_Bigint, _absAdd, Bigint_absAdd, Dynamic, 0x07cad968) \
- V(_Bigint, _absSub, Bigint_absSub, Dynamic, 0x1bf1bb4c) \
- V(_Bigint, _mulAdd, Bigint_mulAdd, Dynamic, 0x229759b7) \
- V(_Bigint, _sqrAdd, Bigint_sqrAdd, Dynamic, 0x5212b81f) \
- V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, Dynamic, 0x4dd342fe) \
- V(_Montgomery, _mulMod, Montgomery_mulMod, Dynamic, 0x17a515ac) \
+ V(_BigIntImpl, _lsh, Bigint_lsh, Dynamic, 0x5b6cfc8b) \
+ V(_BigIntImpl, _rsh, Bigint_rsh, Dynamic, 0x6ff14a49) \
+ V(_BigIntImpl, _absAdd, Bigint_absAdd, Dynamic, 0x5bf14238) \
+ V(_BigIntImpl, _absSub, Bigint_absSub, Dynamic, 0x1de5bd32) \
+ V(_BigIntImpl, _mulAdd, Bigint_mulAdd, Smi, 0x6f277966) \
+ V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, Smi, 0x68e4c8ea) \
+ V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, Smi, \
+ 0x35456d91) \
+ V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, Smi, 0x0f7b0375) \
V(_Double, >, Double_greaterThan, Bool, 0x4f1375a3) \
V(_Double, >=, Double_greaterEqualThan, Bool, 0x4260c184) \
V(_Double, <, Double_lessThan, Bool, 0x365d1eba) \
@@ -460,14 +461,14 @@
V(::, sin, MathSin, 0x6b7bd98c) \
V(::, sqrt, MathSqrt, 0x70482cf3) \
V(::, tan, MathTan, 0x3bcd772a) \
- V(_Bigint, _lsh, Bigint_lsh, 0x7b99f80e) \
- V(_Bigint, _rsh, Bigint_rsh, 0x5262b3a1) \
- V(_Bigint, _absAdd, Bigint_absAdd, 0x07cad968) \
- V(_Bigint, _absSub, Bigint_absSub, 0x1bf1bb4c) \
- V(_Bigint, _mulAdd, Bigint_mulAdd, 0x229759b7) \
- V(_Bigint, _sqrAdd, Bigint_sqrAdd, 0x5212b81f) \
- V(_Bigint, _estQuotientDigit, Bigint_estQuotientDigit, 0x4dd342fe) \
- V(_Montgomery, _mulMod, Montgomery_mulMod, 0x17a515ac) \
+ V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b) \
+ V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49) \
+ V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238) \
+ V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32) \
+ V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966) \
+ V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea) \
+ V(_BigIntImpl, _estimateQuotientDigit, Bigint_estQuotientDigit, 0x35456d91) \
+ V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375) \
V(_Double, >, Double_greaterThan, 0x4f1375a3) \
V(_Double, >=, Double_greaterEqualThan, 0x4260c184) \
V(_Double, <, Double_lessThan, 0x365d1eba) \
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 2c6f781..728a7db 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -324,6 +324,8 @@
intptr_t line_number = 0;
intptr_t column_number = 0;
const char* cstr = "";
+ const char* test_lib =
+ FLAG_use_dart_frontend ? "file:///test-lib" : "test-lib";
// Top frame is inspectStack().
Dart_ActivationFrame frame;
@@ -335,7 +337,7 @@
Dart_StringToCString(function_name, &cstr);
EXPECT_STREQ("inspectStack", cstr);
Dart_StringToCString(script_url, &cstr);
- EXPECT_STREQ("test-lib", cstr);
+ EXPECT_STREQ(test_lib, cstr);
EXPECT_EQ(1, line_number);
EXPECT_EQ(47, column_number);
@@ -348,7 +350,7 @@
Dart_StringToCString(function_name, &cstr);
EXPECT_STREQ("foo", cstr);
Dart_StringToCString(script_url, &cstr);
- EXPECT_STREQ("test-lib", cstr);
+ EXPECT_STREQ(test_lib, cstr);
EXPECT_EQ(2, line_number);
EXPECT_EQ(20, column_number);
@@ -363,7 +365,7 @@
Dart_StringToCString(function_name, &cstr);
EXPECT_STREQ("foo", cstr);
Dart_StringToCString(script_url, &cstr);
- EXPECT_STREQ("test-lib", cstr);
+ EXPECT_STREQ(test_lib, cstr);
EXPECT_EQ(2, line_number);
EXPECT_EQ(37, column_number);
}
@@ -377,7 +379,7 @@
Dart_StringToCString(function_name, &cstr);
EXPECT_STREQ("testMain", cstr);
Dart_StringToCString(script_url, &cstr);
- EXPECT_STREQ("test-lib", cstr);
+ EXPECT_STREQ(test_lib, cstr);
EXPECT_EQ(3, line_number);
EXPECT_EQ(15, column_number);
@@ -551,22 +553,67 @@
return reinterpret_cast<Dart_NativeFunction>(&PropagateErrorNative);
}
-TEST_CASE(DartAPI_PropagateError) {
+TEST_CASE(DartAPI_PropagateCompileTimeError) {
const char* kScriptChars =
"raiseCompileError() {\n"
" return missing_semicolon\n"
"}\n"
"\n"
- "void throwException() {\n"
- " throw new Exception('myException');\n"
- "}\n"
- "\n"
"void nativeFunc(closure) native 'Test_nativeFunc';\n"
"\n"
"void Func1() {\n"
" nativeFunc(() => raiseCompileError());\n"
+ "}\n";
+ Dart_Handle lib =
+ TestCase::LoadTestScript(kScriptChars, &PropagateError_native_lookup);
+ Dart_Handle result;
+
+ // Use Dart_PropagateError to propagate the error.
+ use_throw_exception = false;
+ use_set_return = false;
+
+ result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+ EXPECT(Dart_IsError(result));
+
+ if (FLAG_use_dart_frontend) {
+ EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+ } else {
+ EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+ }
+
+ // Use Dart_SetReturnValue to propagate the error.
+ use_throw_exception = false;
+ use_set_return = true;
+
+ result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+ EXPECT(Dart_IsError(result));
+ if (FLAG_use_dart_frontend) {
+ EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+ } else {
+ EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+ }
+
+ // Use Dart_ThrowException to propagate the error.
+ use_throw_exception = true;
+ use_set_return = false;
+
+ result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
+ EXPECT(Dart_IsError(result));
+ if (FLAG_use_dart_frontend) {
+ EXPECT_SUBSTRING("Expected ';' before this.", Dart_GetError(result));
+ } else {
+ EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
+ }
+}
+
+TEST_CASE(DartAPI_PropagateError) {
+ const char* kScriptChars =
+ "void throwException() {\n"
+ " throw new Exception('myException');\n"
"}\n"
"\n"
+ "void nativeFunc(closure) native 'Test_nativeFunc';\n"
+ "\n"
"void Func2() {\n"
" nativeFunc(() => throwException());\n"
"}\n";
@@ -578,10 +625,6 @@
use_throw_exception = false;
use_set_return = false;
- result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
- EXPECT(Dart_IsError(result));
- EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
EXPECT(Dart_IsError(result));
EXPECT(Dart_ErrorHasException(result));
@@ -591,10 +634,6 @@
use_throw_exception = false;
use_set_return = true;
- result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
- EXPECT(Dart_IsError(result));
- EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
EXPECT(Dart_IsError(result));
EXPECT(Dart_ErrorHasException(result));
@@ -604,10 +643,6 @@
use_throw_exception = true;
use_set_return = false;
- result = Dart_Invoke(lib, NewString("Func1"), 0, NULL);
- EXPECT(Dart_IsError(result));
- EXPECT_SUBSTRING("semicolon expected", Dart_GetError(result));
-
result = Dart_Invoke(lib, NewString("Func2"), 0, NULL);
EXPECT(Dart_IsError(result));
EXPECT(Dart_ErrorHasException(result));
@@ -3931,57 +3966,6 @@
return reinterpret_cast<Dart_NativeFunction>(&NativeFieldLookup);
}
-TEST_CASE(DartAPI_InjectNativeFields1) {
- const char* kScriptChars =
- "class NativeFields extends NativeFieldsWrapper {\n"
- " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
- " int fld1;\n"
- " final int fld2;\n"
- " static int fld3;\n"
- " static const int fld4 = 10;\n"
- "}\n"
- "NativeFields testMain() {\n"
- " NativeFields obj = new NativeFields(10, 20);\n"
- " return obj;\n"
- "}\n";
- Dart_Handle result;
-
- const int kNumNativeFields = 4;
-
- // Create a test library.
- Dart_Handle lib =
- TestCase::LoadTestScript(kScriptChars, NULL, USER_TEST_URI, false);
-
- // Create a native wrapper class with native fields.
- result = Dart_CreateNativeWrapperClass(lib, NewString("NativeFieldsWrapper"),
- kNumNativeFields);
- EXPECT_VALID(result);
- result = Dart_FinalizeLoading(false);
- EXPECT_VALID(result);
-
- // Load up a test script in the test library.
-
- // Invoke a function which returns an object of type NativeFields.
- result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
- EXPECT_VALID(result);
- CHECK_API_SCOPE(thread);
- HANDLESCOPE(thread);
- Instance& obj = Instance::Handle();
- obj ^= Api::UnwrapHandle(result);
- const Class& cls = Class::Handle(obj.clazz());
- // We expect the newly created "NativeFields" object to have
- // 2 dart instance fields (fld1, fld2) and a reference to the native fields.
- // Hence the size of an instance of "NativeFields" should be
- // (1 + 2) * kWordSize + size of object header.
- // We check to make sure the instance size computed by the VM matches
- // our expectations.
- intptr_t header_size = sizeof(RawObject);
- EXPECT_EQ(
- Utils::RoundUp(((1 + 2) * kWordSize) + header_size, kObjectAlignment),
- cls.instance_size());
- EXPECT_EQ(kNumNativeFields, cls.num_native_fields());
-}
-
TEST_CASE(DartAPI_InjectNativeFields2) {
const char* kScriptChars =
"class NativeFields extends NativeFieldsWrapper {\n"
@@ -4262,55 +4246,6 @@
EXPECT_EQ(20, value);
}
-TEST_CASE(DartAPI_NativeFieldAccess) {
- const char* kScriptChars =
- "class NativeFields extends NativeFieldsWrapper {\n"
- " NativeFields(int i, int j) : fld1 = i, fld2 = j {}\n"
- " int fld0;\n"
- " int fld1;\n"
- " final int fld2;\n"
- " static int fld3;\n"
- " static const int fld4 = 10;\n"
- "}\n"
- "NativeFields testMain() {\n"
- " NativeFields obj = new NativeFields(10, 20);\n"
- " return obj;\n"
- "}\n";
- const int kNumNativeFields = 4;
-
- // Create a test library.
- Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, native_field_lookup,
- USER_TEST_URI, false);
-
- // Create a native wrapper class with native fields.
- Dart_Handle result = Dart_CreateNativeWrapperClass(
- lib, NewString("NativeFieldsWrapper"), kNumNativeFields);
- EXPECT_VALID(result);
- result = Dart_FinalizeLoading(false);
- EXPECT_VALID(result);
-
- // Load up a test script in it.
-
- // Invoke a function which returns an object of type NativeFields.
- Dart_Handle retobj = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
- EXPECT_VALID(retobj);
-
- // Now access and set various instance fields of the returned object.
- TestNativeFields(retobj);
-
- // Test that accessing an error handle propagates the error.
- Dart_Handle error = Api::NewError("myerror");
- intptr_t field_value = 0;
-
- result = Dart_GetNativeInstanceField(error, 0, &field_value);
- EXPECT(Dart_IsError(result));
- EXPECT_STREQ("myerror", Dart_GetError(result));
-
- result = Dart_SetNativeInstanceField(error, 0, 1);
- EXPECT(Dart_IsError(result));
- EXPECT_STREQ("myerror", Dart_GetError(result));
-}
-
TEST_CASE(DartAPI_ImplicitNativeFieldAccess) {
const char* kScriptChars =
"import 'dart:nativewrappers';"
@@ -5127,15 +5062,11 @@
"void _imported() {}\n";
// Load lib1
- Dart_Handle url = NewString("library1_url");
- Dart_Handle source = NewString(kLibrary1Chars);
- Dart_Handle lib1 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+ Dart_Handle lib1 = TestCase::LoadTestLibrary("library1_url", kLibrary1Chars);
EXPECT_VALID(lib1);
// Load lib2
- url = NewString("library2_url");
- source = NewString(kLibrary2Chars);
- Dart_Handle lib2 = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+ Dart_Handle lib2 = TestCase::LoadTestLibrary("library2_url", kLibrary2Chars);
EXPECT_VALID(lib2);
// Import lib2 from lib1
@@ -5785,23 +5716,38 @@
const char* kScriptChars =
"import 'library1_dart';"
"main() {}";
+ const char* kLibrary1 = "file:///library1_dart";
const char* kLibrary1Chars =
- "library library1_dart;"
- "import 'library2_dart';";
+ "library library1;"
+ "final x = 0;";
- // Create a test library and Load up a test script in it.
- Dart_Handle url = NewString(TestCase::url());
- Dart_Handle source = NewString(kScriptChars);
- Dart_Handle result = Dart_SetLibraryTagHandler(library_handler);
- EXPECT_VALID(result);
- result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
- EXPECT_VALID(result);
+ Dart_Handle url;
+ Dart_Handle result;
- url = NewString("library1_dart");
- source = NewString(kLibrary1Chars);
- result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
- EXPECT_VALID(result);
+ // Create a test library and load up a test script in it.
+ if (FLAG_use_dart_frontend) {
+ TestCase::AddTestLib("file:///library1_dart", kLibrary1Chars);
+ // LoadTestScript resets the LibraryTagHandler, which we don't want when
+ // using the VM compiler, so we only use it with the Dart frontend for this
+ // test.
+ result = TestCase::LoadTestScript(kScriptChars, NULL, TestCase::url());
+ EXPECT_VALID(result);
+ } else {
+ Dart_Handle source = NewString(kScriptChars);
+ url = NewString(TestCase::url());
+ result = Dart_SetLibraryTagHandler(library_handler);
+ EXPECT_VALID(result);
+
+ result = Dart_LoadScript(url, Dart_Null(), source, 0, 0);
+ EXPECT_VALID(result);
+
+ url = NewString(kLibrary1);
+ source = NewString(kLibrary1Chars);
+ result = Dart_LoadLibrary(url, Dart_Null(), source, 0, 0);
+ }
+
+ url = NewString(kLibrary1);
result = Dart_LookupLibrary(url);
EXPECT_VALID(result);
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 8f67d03..559d178 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -163,10 +163,15 @@
class Reader {
public:
Reader(const uint8_t* buffer, intptr_t size)
- : raw_buffer_(buffer), typed_data_(NULL), size_(size), offset_(0) {}
+ : thread_(NULL),
+ raw_buffer_(buffer),
+ typed_data_(NULL),
+ size_(size),
+ offset_(0) {}
explicit Reader(const TypedData& typed_data)
- : raw_buffer_(NULL),
+ : thread_(Thread::Current()),
+ raw_buffer_(NULL),
typed_data_(&typed_data),
size_(typed_data.IsNull() ? 0 : typed_data.Length()),
offset_(0) {}
@@ -184,11 +189,13 @@
uint32_t ReadUInt32At(intptr_t offset) const {
ASSERT((size_ >= 4) && (offset >= 0) && (offset <= size_ - 4));
-
- const uint8_t* buffer = this->buffer();
- uint32_t value = (buffer[offset + 0] << 24) | (buffer[offset + 1] << 16) |
- (buffer[offset + 2] << 8) | (buffer[offset + 3] << 0);
- return value;
+ uint32_t value;
+ if (raw_buffer_ != NULL) {
+ value = *reinterpret_cast<const uint32_t*>(raw_buffer_ + offset);
+ } else {
+ value = typed_data_->GetUint32(offset);
+ }
+ return Utils::BigEndianToHost32(value);
}
uint32_t ReadFromIndexNoReset(intptr_t end_offset,
@@ -323,14 +330,14 @@
void CopyDataToVMHeap(const TypedData& typed_data,
intptr_t offset,
intptr_t size) {
- NoSafepointScope no_safepoint;
+ NoSafepointScope no_safepoint(thread_);
memmove(typed_data.DataAddr(0), buffer() + offset, size);
}
uint8_t* CopyDataIntoZone(Zone* zone, intptr_t offset, intptr_t length) {
uint8_t* buffer_ = zone->Alloc<uint8_t>(length);
{
- NoSafepointScope no_safepoint;
+ NoSafepointScope no_safepoint(thread_);
memmove(buffer_, buffer() + offset, length);
}
return buffer_;
@@ -341,10 +348,11 @@
if (raw_buffer_ != NULL) {
return raw_buffer_;
}
- NoSafepointScope no_safepoint;
+ NoSafepointScope no_safepoint(thread_);
return reinterpret_cast<uint8_t*>(typed_data_->DataAddr(0));
}
+ Thread* thread_;
const uint8_t* raw_buffer_;
const TypedData* typed_data_;
intptr_t size_;
diff --git a/runtime/vm/kernel_isolate.cc b/runtime/vm/kernel_isolate.cc
index 829c764..5d2a12c 100644
--- a/runtime/vm/kernel_isolate.cc
+++ b/runtime/vm/kernel_isolate.cc
@@ -101,6 +101,8 @@
OS::PrintErr(DART_KERNEL_ISOLATE_NAME ": Isolate creation error: %s\n",
error);
}
+ free(error);
+ error = NULL;
KernelIsolate::SetKernelIsolate(NULL);
KernelIsolate::FinishedInitializing();
return;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b2b6b26..490d3cd 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1304,6 +1304,8 @@
const String& name = H.DartProcedureName(procedure_helper.canonical_name_);
bool is_method = in_class && !procedure_helper.IsStatic();
bool is_abstract = procedure_helper.IsAbstract();
+ bool is_no_such_method_forwarder = procedure_helper.IsNoSuchMethodForwarder();
+
bool is_external = procedure_helper.IsExternal();
String* native_name = NULL;
intptr_t annotation_count;
@@ -1377,13 +1379,20 @@
}
const Object& script_class =
ClassForScriptAt(owner, procedure_helper.source_uri_index_);
+ RawFunction::Kind kind = GetFunctionType(procedure_helper.kind_);
+ is_no_such_method_forwarder &= kind == RawFunction::kRegularFunction;
Function& function = Function::ZoneHandle(
- Z, Function::New(name, GetFunctionType(procedure_helper.kind_),
+ Z, Function::New(name, kind,
!is_method, // is_static
false, // is_const
- is_abstract, is_external,
+ is_abstract && !is_no_such_method_forwarder, is_external,
native_name != NULL, // is_native
script_class, procedure_helper.position_));
+ if (is_no_such_method_forwarder) {
+ // Not inlinable yet because its implementation is generic against the call
+ // site in a way that makes assumptions about the stack frame layout.
+ function.set_is_inlinable(false);
+ }
function.set_end_token_pos(procedure_helper.end_position_);
functions_.Add(&function);
function.set_kernel_offset(procedure_offset);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ad7d534..ea5328d 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -7191,7 +7191,9 @@
// In strong mode, change covariant parameter types to Object in the implicit
// closure of a method compiled by kernel.
// The VM's parser erases covariant types immediately in strong mode.
- if (thread->isolate()->strong() && !is_static() && (kernel_offset() > 0)) {
+ do {
+ if (is_static() || kernel_offset() == 0) break;
+
const Script& function_script = Script::Handle(zone, script());
kernel::TranslationHelper translation_helper(thread);
kernel::StreamingFlowGraphBuilder builder(
@@ -7200,7 +7202,10 @@
translation_helper.InitFromScript(function_script);
builder.SetOffset(kernel_offset());
- builder.ReadUntilFunctionNode();
+ closure_function.set_is_inlinable(!builder.ReadUntilFunctionNode(NULL));
+
+ if (!thread->isolate()->strong()) break;
+
kernel::FunctionNodeHelper fn_helper(&builder);
// Check the positional parameters, including the optional positional ones.
@@ -7231,7 +7236,7 @@
object_type);
}
}
- }
+ } while (false);
const Type& signature_type =
Type::Handle(zone, closure_function.SignatureType());
if (!signature_type.IsFinalized()) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 8946317..3581349 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -8168,8 +8168,10 @@
#define TYPED_GETTER_SETTER(name, type) \
type Get##name(intptr_t byte_offset) const { \
- NoSafepointScope no_safepoint; \
- return ReadUnaligned(reinterpret_cast<type*>(DataAddr(byte_offset))); \
+ ASSERT((byte_offset >= 0) && \
+ (byte_offset + static_cast<intptr_t>(sizeof(type)) - 1) < \
+ LengthInBytes()); \
+ return ReadUnaligned(ReadOnlyDataAddr<type>(byte_offset)); \
} \
void Set##name(intptr_t byte_offset, type value) const { \
NoSafepointScope no_safepoint; \
@@ -8295,6 +8297,18 @@
}
private:
+ // Provides const access to non-pointer, non-aligned data within the object.
+ // Such access does not need a write barrier, but it is *not* GC-safe, since
+ // the object might move.
+ //
+ // Therefore this method is private and the call-sites in this class need to
+ // ensure the returned pointer does not escape.
+ template <typename FieldType>
+ const FieldType* ReadOnlyDataAddr(intptr_t byte_offset) const {
+ return reinterpret_cast<const FieldType*>((raw_ptr()->data()) +
+ byte_offset);
+ }
+
static intptr_t element_size(intptr_t index) {
ASSERT(0 <= index && index < kNumElementSizes);
intptr_t size = element_size_table[index];
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 7568b96..576a194 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -168,7 +168,8 @@
}
ParsedFunction::ParsedFunction(Thread* thread, const Function& function)
- : thread_(thread),
+ : is_no_such_method_forwarder_(false),
+ thread_(thread),
function_(function),
code_(Code::Handle(zone(), function.unoptimized_code())),
node_sequence_(NULL),
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index 12d0557..75baa8d 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -220,7 +220,17 @@
return raw_parameters_[i];
}
+ bool is_no_such_method_forwarder() const {
+ return is_no_such_method_forwarder_;
+ }
+
+ void set_is_no_such_method_forwarder(bool value) {
+ is_no_such_method_forwarder_ = value;
+ }
+
private:
+ bool is_no_such_method_forwarder_;
+
Thread* thread_;
const Function& function_;
Code& code_;
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index ed685d8..b3e25e2 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -57,6 +57,7 @@
# ......dart_native_api.h
# ......dart_tools_api.h
# ....lib/
+# ......libraries.json
# ......dart_client.platform
# ......dart_server.platform
# ......dart_shared.platform
@@ -64,7 +65,9 @@
#.........spec.sum
#.........strong.sum
#.........dart2js_platform.dill
+#.........dart2js_server_platform.dill
#.........dart2js_platform_strong.dill
+#.........dart2js_server_platform_strong.dill
#.........vm_outline.dill
#.........vm_outline_strong.dill
#.........vm_platform.dill
@@ -548,11 +551,15 @@
deps = [
":copy_libraries",
"../utils/compiler:compile_dart2js_platform",
+ "../utils/compiler:compile_dart2js_server_platform",
"../utils/compiler:compile_dart2js_platform_strong",
+ "../utils/compiler:compile_dart2js_server_platform_strong",
]
sources = [
"$root_out_dir/dart2js_platform.dill",
+ "$root_out_dir/dart2js_server_platform.dill",
"$root_out_dir/dart2js_platform_strong.dill",
+ "$root_out_dir/dart2js_server_platform_strong.dill",
]
outputs = [
"$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}",
@@ -779,6 +786,20 @@
]
}
+# This rule copies libraries.json files to lib/
+copy("copy_libraries_specification") {
+ visibility = [ ":create_common_sdk" ]
+ sources = [
+ "lib/libraries.json",
+ ]
+ deps = [
+ ":copy_libraries",
+ ]
+ outputs = [
+ "$root_out_dir/dart-sdk/lib/{{source_file_part}}",
+ ]
+}
+
# This rule copies .platform files to lib/
copy("copy_platform_files") {
visibility = [ ":create_common_sdk" ]
@@ -924,6 +945,7 @@
":copy_headers",
":copy_libraries_dart",
":copy_license",
+ ":copy_libraries_specification",
":copy_platform_files",
":copy_pub_assets",
":copy_readme",
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index df3bf16..d0f53c3 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -1299,6 +1299,7 @@
/// Does *not* clear digits below ds.
static void _lsh(
Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+ assert(xUsed > 0);
final digitShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -1328,6 +1329,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -1363,6 +1365,7 @@
// resultDigits[0..resultUsed-1] = xDigits[0..xUsed-1] >> n.
static void _rsh(
Uint16List xDigits, int xUsed, int n, Uint16List resultDigits) {
+ assert(xUsed > 0);
final digitsShift = n ~/ _digitBits;
final bitShift = n % _digitBits;
final carryBitShift = _digitBits - bitShift;
@@ -1390,6 +1393,7 @@
if (shiftAmount < 0) {
throw new ArgumentError("shift-amount must be posititve $shiftAmount");
}
+ if (_isZero) return this;
final digitShift = shiftAmount ~/ _digitBits;
final bitShift = shiftAmount % _digitBits;
if (bitShift == 0) {
@@ -1632,6 +1636,7 @@
*/
_BigIntImpl operator &(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero || other._isZero) return zero;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) & (-other) == ~(this-1) & ~(other-1)
@@ -1671,6 +1676,8 @@
*/
_BigIntImpl operator |(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) | (-other) == ~(this-1) | ~(other-1)
@@ -1711,6 +1718,8 @@
*/
_BigIntImpl operator ^(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
if (_isNegative == other._isNegative) {
if (_isNegative) {
// (-this) ^ (-other) == ~(this-1) ^ ~(other-1) == (this-1) ^ (other-1)
@@ -1745,6 +1754,7 @@
* This maps any integer `x` to `-x - 1`.
*/
_BigIntImpl operator ~() {
+ if (_isZero) return _minusOne;
if (_isNegative) {
// ~(-this) == ~(~(this-1)) == this-1
return _absSubSetSign(one, false);
@@ -1757,6 +1767,8 @@
/// Addition operator.
_BigIntImpl operator +(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative == other._isNegative) {
// this + other == this + other
@@ -1774,6 +1786,8 @@
/// Subtraction operator.
_BigIntImpl operator -(BigInt bigInt) {
_BigIntImpl other = bigInt;
+ if (_isZero) return -other;
+ if (other._isZero) return this;
var isNegative = _isNegative;
if (isNegative != other._isNegative) {
// this - (-other) == this + other
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 5f3a40c..c2ba34e 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -90,6 +90,11 @@
categories: "Client",
maturity: Maturity.STABLE,
platforms: DART2JS_PLATFORM),
+ "_js": const LibraryInfo("js/_js.dart",
+ categories: "Client",
+ dart2jsPatchPath: "js/_js_client.dart",
+ documented: false,
+ platforms: DART2JS_PLATFORM),
"js_util": const LibraryInfo("js_util/dart2js/js_util_dart2js.dart",
categories: "Client",
maturity: Maturity.STABLE,
diff --git a/sdk/lib/dart_client.platform b/sdk/lib/dart_client.platform
index 3813dc0..0228d99 100644
--- a/sdk/lib/dart_client.platform
+++ b/sdk/lib/dart_client.platform
@@ -32,6 +32,7 @@
cli: unsupported:cli/cli.dart
isolate: isolate/isolate.dart
js: js/dart2js/js_dart2js.dart
+_js: js/_js.dart
js_util: js_util/dart2js/js_util_dart2js.dart
math: math/math.dart
mirrors: mirrors/mirrors.dart
diff --git a/sdk/lib/dart_server.platform b/sdk/lib/dart_server.platform
index de57d4c..414a30c 100644
--- a/sdk/lib/dart_server.platform
+++ b/sdk/lib/dart_server.platform
@@ -37,6 +37,7 @@
web_sql: unsupported:
_chrome: unsupported:
js: unsupported:
+_js: unsupported:
js_util: unsupported:
_mirror_helper: unsupported:
_internal: internal/internal.dart
diff --git a/sdk/lib/dart_shared.platform b/sdk/lib/dart_shared.platform
index be8ed61..922fb98 100644
--- a/sdk/lib/dart_shared.platform
+++ b/sdk/lib/dart_shared.platform
@@ -26,6 +26,7 @@
cli: cli/cli.dart
isolate: isolate/isolate.dart
js: js/dart2js/js_dart2js.dart
+_js: js/_js.dart
js_util: js_util/dart2js/js_util_dart2js.dart
math: math/math.dart
mirrors: mirrors/mirrors.dart
diff --git a/sdk/lib/js/_js.dart b/sdk/lib/js/_js.dart
new file mode 100644
index 0000000..aef7ef9
--- /dev/null
+++ b/sdk/lib/js/_js.dart
@@ -0,0 +1,21 @@
+// 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.
+
+/// Helper library used by `dart:js`.
+///
+/// This library hides any logic that is specific to the web, and allows us to
+/// support `dart:js` for compiling to javascript on the server (e.g. to target
+/// nodejs).
+library dart._js;
+
+/// Whether `o` is a browser object such as `Blob`, `Event`, `KeyRange`,
+/// `ImageData`, `Node`, and `Window`.
+///
+/// On non-web targets, this function always returns false.
+external bool isBrowserObject(dynamic o);
+
+/// Convert a browser object to it's Dart counterpart. None of these types are
+/// wrapped, but this function is needed to inform dart2js about the possible
+/// types that are used and that therefore cannot be tree-shaken.
+external Object convertFromBrowserObject(dynamic o);
diff --git a/sdk/lib/js/_js_client.dart b/sdk/lib/js/_js_client.dart
new file mode 100644
index 0000000..74df24d
--- /dev/null
+++ b/sdk/lib/js/_js_client.dart
@@ -0,0 +1,21 @@
+// 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.
+
+import 'dart:html' show Blob, Event, ImageData, Node, Window;
+import 'dart:indexed_db' show KeyRange;
+import 'dart:_js_helper' show patch;
+import 'dart:_foreign_helper' show JS;
+
+@patch
+bool isBrowserObject(dynamic o) =>
+ o is Blob ||
+ o is Event ||
+ o is KeyRange ||
+ o is ImageData ||
+ o is Node ||
+ o is Window;
+
+@patch
+Object convertFromBrowserObject(dynamic o) =>
+ JS('Blob|Event|KeyRange|ImageData|Node|Window', '#', o);
diff --git a/sdk/lib/js/_js_server.dart b/sdk/lib/js/_js_server.dart
new file mode 100644
index 0000000..b941d77
--- /dev/null
+++ b/sdk/lib/js/_js_server.dart
@@ -0,0 +1,11 @@
+// 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.
+
+import 'dart:_js_helper' show patch;
+
+@patch
+bool isBrowserObject(dynamic o) => false;
+
+@patch
+Object convertFromBrowserObject(dynamic o) => o;
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 5d1e2d3..74c55b8 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -58,17 +58,11 @@
*
* The following types are transferred directly and not proxied:
*
- * * "Basic" types: `null`, `bool`, `num`, `String`, `DateTime`
- * * `Blob`
- * * `Event`
- * * `HtmlCollection`
- * * `ImageData`
- * * `KeyRange`
- * * `Node`
- * * `NodeList`
- * * `TypedData`, including its subclasses like `Int32List`, but _not_
- * `ByteBuffer`
- * * `Window`
+ * * Basic types: `null`, `bool`, `num`, `String`, `DateTime`
+ * * `TypedData`, including its subclasses like `Int32List`, but _not_
+ * `ByteBuffer`
+ * * When compiling for the web, also: `Blob`, `Event`, `ImageData`,
+ * `KeyRange`, `Node`, and `Window`.
*
* ## Converting collections with JsObject.jsify()
*
@@ -87,9 +81,7 @@
*/
library dart.js;
-import 'dart:html' show Blob, Event, ImageData, Node, Window;
import 'dart:collection' show HashMap, ListMixin;
-import 'dart:indexed_db' show KeyRange;
import 'dart:typed_data' show TypedData;
import 'dart:_foreign_helper' show JS, JS_CONST, DART_CLOSURE_TO_JS;
@@ -97,6 +89,7 @@
show JavaScriptObject, UnknownJavaScriptObject, DART_CLOSURE_PROPERTY_NAME;
import 'dart:_js_helper'
show Primitives, convertDartClosureToJS, getIsolateAffinityTag;
+import 'dart:_js' show isBrowserObject, convertFromBrowserObject;
export 'dart:_interceptors' show JavaScriptObject;
@@ -568,13 +561,10 @@
if (o is JsObject) {
return o._jsObject;
}
- if (o is Blob ||
- o is Event ||
- o is KeyRange ||
- o is ImageData ||
- o is Node ||
- o is TypedData ||
- o is Window) {
+ if (isBrowserObject(o)) {
+ return o;
+ }
+ if (o is TypedData) {
return o;
}
if (o is DateTime) {
@@ -610,16 +600,10 @@
JS('bool', 'typeof # == "number"', o) ||
JS('bool', 'typeof # == "boolean"', o)) {
return o;
- } else if (_isLocalObject(o) &&
- (o is Blob ||
- o is Event ||
- o is KeyRange ||
- o is ImageData ||
- o is Node ||
- o is TypedData ||
- o is Window)) {
- // long line: dart2js doesn't allow string concatenation in the JS() form
- return JS('Blob|Event|KeyRange|ImageData|Node|TypedData|Window', '#', o);
+ } else if (_isLocalObject(o) && isBrowserObject(o)) {
+ return convertFromBrowserObject(o);
+ } else if (_isLocalObject(o) && o is TypedData) {
+ return JS('TypedData', '#', o);
} else if (JS('bool', '# instanceof Date', o)) {
var ms = JS('num', '#.getTime()', o);
return new DateTime.fromMillisecondsSinceEpoch(ms);
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index c2b21b0..633ae36 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -146,18 +146,22 @@
}
},
"dart2js": {
+ "environment_overrides": {
+ "mirrors": false,
+ "io": false
+ },
"libraries": {
"async": {
"patches": "_internal/js_runtime/lib/async_patch.dart",
"uri": "async/async.dart"
},
+ "_interceptors": {
+ "uri": "_internal/js_runtime/lib/interceptors.dart"
+ },
"mirrors": {
"patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
"uri": "mirrors/mirrors.dart"
},
- "_interceptors": {
- "uri": "_internal/js_runtime/lib/interceptors.dart"
- },
"_js_embedded_names": {
"uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
},
@@ -237,6 +241,10 @@
"indexed_db": {
"uri": "indexed_db/dart2js/indexed_db_dart2js.dart"
},
+ "_js": {
+ "patches": "js/_js_client.dart",
+ "uri": "js/_js.dart"
+ },
"convert": {
"patches": "_internal/js_runtime/lib/convert_patch.dart",
"uri": "convert/convert.dart"
@@ -258,5 +266,100 @@
"uri": "svg/dart2js/svg_dart2js.dart"
}
}
+ },
+ "dart2js_server": {
+ "environment_overrides": {
+ "mirrors": false,
+ "io": false
+ },
+ "libraries": {
+ "async": {
+ "patches": "_internal/js_runtime/lib/async_patch.dart",
+ "uri": "async/async.dart"
+ },
+ "mirrors": {
+ "patches": "_internal/js_runtime/lib/mirrors_patch_cfe.dart",
+ "uri": "mirrors/mirrors.dart"
+ },
+ "_interceptors": {
+ "uri": "_internal/js_runtime/lib/interceptors.dart"
+ },
+ "_js_embedded_names": {
+ "uri": "_internal/js_runtime/lib/shared/embedded_names.dart"
+ },
+ "io": {
+ "patches": "_internal/js_runtime/lib/io_patch.dart",
+ "uri": "io/io.dart"
+ },
+ "_internal": {
+ "patches": "_internal/js_runtime/lib/internal_patch.dart",
+ "uri": "internal/internal.dart"
+ },
+ "_async_await_error_codes": {
+ "uri": "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+ },
+ "_http": {
+ "uri": "_http/http.dart"
+ },
+ "_js_helper": {
+ "uri": "_internal/js_runtime/lib/js_helper.dart"
+ },
+ "_js_primitives": {
+ "uri": "_internal/js_runtime/lib/js_primitives.dart"
+ },
+ "js": {
+ "uri": "js/dart2js/js_dart2js.dart"
+ },
+ "_js_mirrors": {
+ "uri": "_internal/js_runtime/lib/js_mirrors.dart"
+ },
+ "_native_typed_data": {
+ "uri": "_internal/js_runtime/lib/native_typed_data.dart"
+ },
+ "core": {
+ "patches": "_internal/js_runtime/lib/core_patch.dart",
+ "uri": "core/core.dart"
+ },
+ "_js_names": {
+ "uri": "_internal/js_runtime/lib/js_names.dart"
+ },
+ "js_util": {
+ "uri": "js_util/dart2js/js_util_dart2js.dart"
+ },
+ "collection": {
+ "patches": "_internal/js_runtime/lib/collection_patch.dart",
+ "uri": "collection/collection.dart"
+ },
+ "typed_data": {
+ "patches": "_internal/js_runtime/lib/typed_data_patch.dart",
+ "uri": "typed_data/typed_data.dart"
+ },
+ "isolate": {
+ "patches": "_internal/js_runtime/lib/isolate_patch.dart",
+ "uri": "isolate/isolate.dart"
+ },
+ "developer": {
+ "patches": "_internal/js_runtime/lib/developer_patch.dart",
+ "uri": "developer/developer.dart"
+ },
+ "_js": {
+ "patches": "js/_js_server.dart",
+ "uri": "js/_js.dart"
+ },
+ "convert": {
+ "patches": "_internal/js_runtime/lib/convert_patch.dart",
+ "uri": "convert/convert.dart"
+ },
+ "_isolate_helper": {
+ "uri": "_internal/js_runtime/lib/isolate_helper.dart"
+ },
+ "math": {
+ "patches": "_internal/js_runtime/lib/math_patch.dart",
+ "uri": "math/math.dart"
+ },
+ "_foreign_helper": {
+ "uri": "_internal/js_runtime/lib/foreign_helper.dart"
+ }
+ }
}
-}
+}
\ No newline at end of file
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index c959674..2bb6e8c 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -192,6 +192,10 @@
js:
uri: "js/dart2js/js_dart2js.dart"
+ _js:
+ uri: "js/_js.dart"
+ patches: "js/_js_client.dart"
+
js_util:
uri: "js_util/dart2js/js_util_dart2js.dart"
@@ -201,7 +205,7 @@
mirrors:
uri: "mirrors/mirrors.dart"
- patches: "_internal/js_runtime/lib/mirrors_patch.dart"
+ patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
typed_data:
uri: "typed_data/typed_data.dart"
@@ -255,3 +259,100 @@
_metadata:
uri: "html/html_common/metadata.dart"
+
+ environment_overrides:
+ io: false
+ mirrors: false
+
+dart2js_server:
+ libraries:
+ async:
+ uri: "async/async.dart"
+ patches: "_internal/js_runtime/lib/async_patch.dart"
+
+ collection:
+ uri: "collection/collection.dart"
+ patches: "_internal/js_runtime/lib/collection_patch.dart"
+
+ convert:
+ uri: "convert/convert.dart"
+ patches: "_internal/js_runtime/lib/convert_patch.dart"
+
+ core:
+ uri: "core/core.dart"
+ patches: "_internal/js_runtime/lib/core_patch.dart"
+
+ developer:
+ uri: "developer/developer.dart"
+ patches: "_internal/js_runtime/lib/developer_patch.dart"
+
+ _http:
+ uri: "_http/http.dart"
+
+ io:
+ uri: "io/io.dart"
+ patches: "_internal/js_runtime/lib/io_patch.dart"
+
+ isolate:
+ uri: "isolate/isolate.dart"
+ patches: "_internal/js_runtime/lib/isolate_patch.dart"
+
+ js:
+ uri: "js/dart2js/js_dart2js.dart"
+
+ _js:
+ uri: "js/_js.dart"
+ patches: "js/_js_server.dart"
+
+ js_util:
+ uri: "js_util/dart2js/js_util_dart2js.dart"
+
+ math:
+ uri: "math/math.dart"
+ patches: "_internal/js_runtime/lib/math_patch.dart"
+
+ mirrors:
+ uri: "mirrors/mirrors.dart"
+ patches: "_internal/js_runtime/lib/mirrors_patch_cfe.dart"
+
+ typed_data:
+ uri: "typed_data/typed_data.dart"
+ patches: "_internal/js_runtime/lib/typed_data_patch.dart"
+
+ _native_typed_data:
+ uri: "_internal/js_runtime/lib/native_typed_data.dart"
+
+ _internal:
+ uri: "internal/internal.dart"
+ patches: "_internal/js_runtime/lib/internal_patch.dart"
+
+ _js_helper:
+ uri: "_internal/js_runtime/lib/js_helper.dart"
+
+ _interceptors:
+ uri: "_internal/js_runtime/lib/interceptors.dart"
+
+ _foreign_helper:
+ uri: "_internal/js_runtime/lib/foreign_helper.dart"
+
+ _isolate_helper:
+ uri: "_internal/js_runtime/lib/isolate_helper.dart"
+
+ _js_mirrors:
+ uri: "_internal/js_runtime/lib/js_mirrors.dart"
+
+ _js_names:
+ uri: "_internal/js_runtime/lib/js_names.dart"
+
+ _js_primitives:
+ uri: "_internal/js_runtime/lib/js_primitives.dart"
+
+ _js_embedded_names:
+ uri: "_internal/js_runtime/lib/shared/embedded_names.dart"
+
+ _async_await_error_codes:
+ uri: "_internal/js_runtime/lib/shared/async_await_error_codes.dart"
+
+ environment_overrides:
+ io: false
+ mirrors: false
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index deb724c..707b1e7 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -206,10 +206,9 @@
@DocsEditable()
final AudioParam playbackRate;
- @JSName('start')
@DomName('AudioBufferSourceNode.start')
@DocsEditable()
- void start2([num when, num grainOffset, num grainDuration]) native;
+ void start([num when, num grainOffset, num grainDuration]) native;
}
// 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
@@ -599,10 +598,11 @@
static const EventStreamProvider<Event> endedEvent =
const EventStreamProvider<Event>('ended');
+ @JSName('start')
@DomName('AudioScheduledSourceNode.start')
@DocsEditable()
@Experimental() // untriaged
- void start([num when]) native;
+ void start2([num when]) native;
@DomName('AudioScheduledSourceNode.stop')
@DocsEditable()
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 9ef5fea..c05773a 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -468,6 +468,7 @@
LayoutTests/fast/css/max-device-aspect-ratio_t01: RuntimeError, Pass # Issue 28998
LayoutTests/fast/css/media-query-recovery_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/modify-ua-rules-from-javascript_t01: RuntimeError
+LayoutTests/fast/css/padding-no-renderer_t01: Pass, RuntimeError
LayoutTests/fast/css/parsing-at-rule-recovery_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/parsing-css-allowed-string-characters_t01: RuntimeError # Please triage this failure
LayoutTests/fast/css/parsing-page-rule_t01: RuntimeError # Please triage this failure
diff --git a/tests/compiler/dart2js/closure/show.dart b/tests/compiler/dart2js/closure/show.dart
new file mode 100644
index 0000000..ae6eb5e
--- /dev/null
+++ b/tests/compiler/dart2js/closure/show.dart
@@ -0,0 +1,22 @@
+// 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.
+
+/// Helper program that shows the closure data on a dart program.
+
+import 'package:args/args.dart';
+import '../equivalence/id_equivalence_helper.dart';
+import '../equivalence/show_helper.dart';
+import 'closure_test.dart';
+
+main(List<String> args) async {
+ ArgParser argParser = createArgParser();
+ argParser.addFlag('inference', defaultsTo: true);
+ argParser.addFlag('side-effects', defaultsTo: false);
+ argParser.addFlag('callers', defaultsTo: false);
+ ArgResults results = argParser.parse(args);
+
+ ComputeMemberDataFunction astFunction = computeClosureData;
+ ComputeMemberDataFunction kernelFunction = computeKernelClosureData;
+ await show(results, astFunction, kernelFunction);
+}
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 31320ad..f4b558f 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -10,7 +10,8 @@
codegen/logical_expression_test: Fail # Issue 17027
codegen/simple_function_subtype_test: Fail # simple_function_subtype_test is temporarily(?) disabled due to new method for building function type tests.
deferred_loading/deferred_loading_test: Slow, Pass
-equivalence/id_equivalence_test: Pass, Slow
+equivalence/id_equivalence1_test: Pass, Slow
+equivalence/id_equivalence2_test: Pass, Slow
generate_code_with_compile_time_errors_test: RuntimeError # not supported yet with the new FE.
in_user_code_test: RuntimeError # analyze-only with CFE is not complete (Issues 32512, 32513)
inference/inference0_test: Slow, Pass
@@ -78,8 +79,6 @@
mirrors/import_mirrors_test: Pass, Slow
mirrors/mirror_final_field_inferrer2_test: Crash, Pass, Slow # Issue 15581
old_frontend/analyze_api_test: Pass, Slow # DON'T CHANGE THIS LINE -- Don't mark these tests as failing. Instead, fix the errors/warnings that they report or update the whitelist in the test-files to temporarily allow digression.
-old_frontend/analyze_dart2js_test: Pass, Slow # DON'T CHANGE THIS LINE -- Don't mark these tests as failing. Instead, fix the errors/warnings that they report or update the whitelist in the test-files to temporarily allow digression.
-old_frontend/analyze_unused_dart2js_test: Pass, Slow
old_frontend/check_elements_invariants_test: Skip # Slow and only needs to be run in one configuration
old_frontend/check_members_test: Pass, Slow
old_frontend/duplicate_library_test: Pass, Slow
@@ -103,8 +102,6 @@
mirrors/mirror_final_field_inferrer2_test: Pass, Slow
mirrors/preserve_uris_test: Pass, Slow
old_frontend/analyze_dart2js_helpers_test: Pass, Slow
-old_frontend/analyze_dart2js_test: Pass, Slow
-old_frontend/analyze_unused_dart2js_test: Pass, Slow
old_frontend/duplicate_library_test: Pass, Slow
output_type_test: Pass, Slow
serialization*: Slow, Pass
diff --git a/tests/compiler/dart2js/dill_loader_test.dart b/tests/compiler/dart2js/dill_loader_test.dart
index 1963d3b..4192756 100644
--- a/tests/compiler/dart2js/dill_loader_test.dart
+++ b/tests/compiler/dart2js/dill_loader_test.dart
@@ -43,7 +43,7 @@
Uri entryPoint = Uri.parse('memory:main.dill');
var options = new CompilerOptions()
- ..target = new Dart2jsTarget(new TargetFlags())
+ ..target = new Dart2jsTarget("dart2js", new TargetFlags())
..packagesFileUri = Uri.base.resolve('.packages')
..linkedDependencies = <Uri>[
computePlatformBinariesLocation().resolve("dart2js_platform.dill"),
diff --git a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
index 8349c81..9cfb6cb 100644
--- a/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
+++ b/tests/compiler/dart2js/end_to_end/async_compiler_input_provider_test.dart
@@ -2,8 +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.
-// TODO(johnniwinther): Port this test to use '--use-kernel'.
-
import "dart:async";
import "dart:io";
@@ -11,6 +9,7 @@
import "package:async_helper/async_helper.dart";
import 'package:compiler/compiler.dart' as compiler;
+import 'package:compiler/src/filenames.dart';
const SOURCES = const {
"/main.dart": """
@@ -49,7 +48,8 @@
// Find the path to sdk/ in the repo relative to this script.
Uri libraryRoot = Uri.base.resolve('sdk/');
Uri packageRoot = Uri.base.resolve('packages/');
- var platformDir = Uri.parse(Platform.resolvedExecutable).resolve('.');
+ var platformDir =
+ Uri.parse(nativeToUriPath(Platform.resolvedExecutable)).resolve('.');
asyncTest(() => compiler.compile(
entrypoint,
libraryRoot,
diff --git a/tests/compiler/dart2js/equivalence/check_functions.dart b/tests/compiler/dart2js/equivalence/check_functions.dart
index 01e83cc..945803a 100644
--- a/tests/compiler/dart2js/equivalence/check_functions.dart
+++ b/tests/compiler/dart2js/equivalence/check_functions.dart
@@ -520,6 +520,7 @@
Uri.parse('dart:mirrors'),
Uri.parse('dart:_js_mirrors'),
Uri.parse('dart:js'),
+ Uri.parse('dart:_js'),
Uri.parse('dart:js_util'),
Uri.parse('dart:_chrome'),
Uri.parse('dart:io'),
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence.dart b/tests/compiler/dart2js/equivalence/id_equivalence.dart
index 0794c05..93500b0 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence.dart
@@ -28,6 +28,9 @@
abstract class Id {
IdKind get kind;
bool get isGlobal;
+
+ /// Display name for this id.
+ String get descriptor;
}
class IdValue {
@@ -155,6 +158,8 @@
String get name => className != null ? '$className.$memberName' : memberName;
+ String get descriptor => 'member $name';
+
String toString() => 'element:$name';
}
@@ -177,6 +182,8 @@
String get name => className;
+ String get descriptor => 'class $name';
+
String toString() => 'class:$name';
}
@@ -198,6 +205,8 @@
return value == other.value && kind == other.kind;
}
+ String get descriptor => 'offset $value ($kind)';
+
String toString() => '$kind:$value';
}
@@ -217,8 +226,12 @@
}
}
+ String get objectText {
+ return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
+ }
+
String toString() =>
- 'ActualData(value=$value,sourceSpan=$sourceSpan,object=$object)';
+ 'ActualData(value=$value,sourceSpan=$sourceSpan,object=$objectText)';
}
abstract class DataRegistry {
@@ -432,14 +445,16 @@
case SendStructureKind.INCOMPATIBLE_INVOKE:
switch (sendStructure.semantics.kind) {
case AccessKind.EXPRESSION:
- computeForNode(node, createInvokeId(node.argumentsNode));
+ computeForNode(node,
+ createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
break;
case AccessKind.LOCAL_VARIABLE:
case AccessKind.FINAL_LOCAL_VARIABLE:
case AccessKind.PARAMETER:
case AccessKind.FINAL_PARAMETER:
computeForNode(node, createAccessId(node));
- computeForNode(node, createInvokeId(node.argumentsNode));
+ computeForNode(node,
+ createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
break;
case AccessKind.STATIC_FIELD:
case AccessKind.FINAL_STATIC_FIELD:
@@ -449,13 +464,17 @@
case AccessKind.SUPER_FIELD:
case AccessKind.SUPER_FINAL_FIELD:
case AccessKind.SUPER_GETTER:
- computeForNode(node, createInvokeId(node.argumentsNode));
+ computeForNode(node,
+ createInvokeId(node.typeArgumentsNode ?? node.argumentsNode));
break;
case AccessKind.TOPLEVEL_GETTER:
if (elements[node].isDeferredLoaderGetter) {
computeForNode(node, createInvokeId(node.selector));
} else {
- computeForNode(node, createInvokeId(node.argumentsNode));
+ computeForNode(
+ node,
+ createInvokeId(
+ node.typeArgumentsNode ?? node.argumentsNode));
}
break;
default:
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart
new file mode 100644
index 0000000..553ae8f
--- /dev/null
+++ b/tests/compiler/dart2js/equivalence/id_equivalence1_test.dart
@@ -0,0 +1,9 @@
+// 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.
+
+import 'id_equivalence_tester.dart';
+
+main(List<String> args) {
+ mainInternal(args, dataDirectories1);
+}
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart
new file mode 100644
index 0000000..c7c81cf
--- /dev/null
+++ b/tests/compiler/dart2js/equivalence/id_equivalence2_test.dart
@@ -0,0 +1,9 @@
+// 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.
+
+import 'id_equivalence_tester.dart';
+
+main(List<String> args) {
+ mainInternal(args, dataDirectories2);
+}
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index 09b47fa..80ec57a 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -82,6 +82,19 @@
const String stopAfterTypeInference = 'stopAfterTypeInference';
+/// Reports [message] as an error using [spannable] as error location.
+void reportError(
+ DiagnosticReporter reporter, Spannable spannable, String message) {
+ reporter
+ .reportErrorMessage(spannable, MessageKind.GENERIC, {'text': message});
+}
+
+/// Display name used for compilation using the old dart2js frontend.
+const String astName = 'dart2js old frontend';
+
+/// Display name used for compilation using the new common frontend.
+const String kernelName = 'kernel';
+
/// Compute actual data for all members defined in the program with the
/// [entryPoint] and [memorySourceFiles].
///
@@ -468,7 +481,7 @@
}
print('----------------------------------------------------------------');
- print('Test: $name');
+ print('Test file: ${entity.uri}');
// Pretend this is a dart2js_native test to allow use of 'native' keyword
// and import of private libraries.
String commonTestPath = 'sdk/tests/compiler';
@@ -523,7 +536,7 @@
verbose: verbose,
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys);
- if (await checkCode(code, annotations, compiledData1,
+ if (await checkCode(astName, entity.uri, code, annotations, compiledData1,
fatalErrors: !testAfterFailures)) {
hasFailures = true;
}
@@ -540,7 +553,8 @@
verbose: verbose,
forUserLibrariesOnly: forUserLibrariesOnly,
globalIds: annotations.globalData.keys);
- if (await checkCode(code, annotations, compiledData2,
+ if (await checkCode(
+ kernelName, entity.uri, code, annotations, compiledData2,
filterActualData: filterActualData,
fatalErrors: !testAfterFailures)) {
hasFailures = true;
@@ -554,12 +568,17 @@
/// Checks [compiledData] against the expected data in [expectedMap] derived
/// from [code].
-Future<bool> checkCode(Map<Uri, AnnotatedCode> code,
- MemberAnnotations<IdValue> expectedMaps, CompiledData compiledData,
+Future<bool> checkCode(
+ String mode,
+ Uri mainFileUri,
+ Map<Uri, AnnotatedCode> code,
+ MemberAnnotations<IdValue> expectedMaps,
+ CompiledData compiledData,
{bool filterActualData(IdValue expected, ActualData actualData),
bool fatalErrors: true}) async {
IdData data = new IdData(code, expectedMaps, compiledData);
bool hasFailure = false;
+ Set<Uri> neededDiffs = new Set<Uri>();
void checkActualMap(
Map<Id, ActualData> actualMap, Map<Id, IdValue> expectedMap,
@@ -567,14 +586,15 @@
bool hasLocalFailure = false;
actualMap.forEach((Id id, ActualData actualData) {
IdValue actual = actualData.value;
+
if (!expectedMap.containsKey(id)) {
if (actual.value != '') {
- reportHere(
+ reportError(
data.compiler.reporter,
actualData.sourceSpan,
- 'Id $id = ${colors.red('$actual')} for ${actualData.object} '
- '(${actualData.object.runtimeType}) '
- 'not expected in ${expectedMap.keys}');
+ 'EXTRA $mode DATA for ${id.descriptor} = '
+ '${colors.red('$actual')} for ${actualData.objectText}. '
+ 'Data was expected for these ids: ${expectedMap.keys}');
if (filterActualData == null || filterActualData(null, actualData)) {
hasLocalFailure = true;
}
@@ -582,11 +602,11 @@
} else {
IdValue expected = expectedMap[id];
if (actual != expected) {
- reportHere(
+ reportError(
data.compiler.reporter,
actualData.sourceSpan,
- 'Object: ${actualData.object} '
- '(${actualData.object.runtimeType})\n '
+ 'UNEXPECTED $mode DATA for ${id.descriptor}: '
+ 'Object: ${actualData.objectText}\n '
'expected: ${colors.green('$expected')}\n '
'actual: ${colors.red('$actual')}');
if (filterActualData == null ||
@@ -599,9 +619,7 @@
if (hasLocalFailure) {
hasFailure = true;
if (uri != null) {
- print('--annotations diff [${uri.pathSegments.last}]-------------');
- print(data.diffCode(uri));
- print('----------------------------------------------------------');
+ neededDiffs.add(uri);
}
}
}
@@ -612,29 +630,23 @@
checkActualMap(data.actualMaps.globalData, data.expectedMaps.globalData);
Set<Id> missingIds = new Set<Id>();
- StringBuffer combinedAnnotationsDiff = new StringBuffer();
void checkMissing(Map<Id, IdValue> expectedMap, Map<Id, ActualData> actualMap,
[Uri uri]) {
expectedMap.forEach((Id id, IdValue expected) {
if (!actualMap.containsKey(id)) {
missingIds.add(id);
- StringBuffer sb = new StringBuffer();
- for (Id id in actualMap.keys.where((d) => d.kind == id.kind)) {
- sb.write('\n $id');
- }
+ String message = 'MISSING $mode DATA for ${id.descriptor}: '
+ 'Expected ${colors.green('$expected')}';
if (uri != null) {
- reportHere(
- data.compiler.reporter,
- computeSpannable(data.elementEnvironment, uri, id),
- 'Expected $expected for id $id missing in${sb}');
+ reportError(data.compiler.reporter,
+ computeSpannable(data.elementEnvironment, uri, id), message);
} else {
- print('Expected $expected for id $id missing in${sb}');
+ print(message);
}
}
});
if (missingIds.isNotEmpty && uri != null) {
- combinedAnnotationsDiff.write('Missing in $uri:\n');
- combinedAnnotationsDiff.write('${data.diffCode(uri)}\n');
+ neededDiffs.add(uri);
}
}
@@ -642,13 +654,13 @@
checkMissing(expectedMap, data.actualMaps[uri], uri);
});
checkMissing(data.expectedMaps.globalData, data.actualMaps.globalData);
- if (combinedAnnotationsDiff.isNotEmpty) {
- print('--annotations diff--------------------------------------------');
- print(combinedAnnotationsDiff.toString());
- print('--------------------------------------------------------------');
+ for (Uri uri in neededDiffs) {
+ print('--annotations diff [${uri.pathSegments.last}]-------------');
+ print(data.diffCode(uri));
+ print('----------------------------------------------------------');
}
if (missingIds.isNotEmpty) {
- print("Ids not found: ${missingIds}.");
+ print("MISSING ids: ${missingIds}.");
hasFailure = true;
}
if (hasFailure && fatalErrors) {
@@ -749,6 +761,7 @@
}
Future<bool> compareData(
+ Uri mainFileUri,
Uri entryPoint,
Map<String, String> memorySourceFiles,
ComputeMemberDataFunction computeAstData,
@@ -775,14 +788,15 @@
skipUnprocessedMembers: skipUnprocessedMembers,
skipFailedCompilations: skipFailedCompilations);
if (data2 == null) return false;
- await compareCompiledData(data1, data2,
+ await compareCompiledData(mainFileUri, data1, data2,
whiteList: whiteList,
skipMissingUris: !forUserLibrariesOnly,
verbose: verbose);
return true;
}
-Future compareCompiledData(CompiledData data1, CompiledData data2,
+Future compareCompiledData(
+ Uri mainFileUri, CompiledData data1, CompiledData data2,
{bool skipMissingUris: false,
bool verbose: false,
bool whiteList(Uri uri, Id id)}) async {
@@ -831,9 +845,20 @@
actualMap1.forEach((Id id, ActualData actualData1) {
IdValue value1 = actualData1.value;
IdValue value2 = actualMap2[id]?.value;
+
if (value1 != value2) {
- reportHere(data1.compiler.reporter, actualData1.sourceSpan,
- '$id: from source:${value1},from dill:${value2}');
+ String message;
+ if (value2 != null) {
+ String prefix = 'DATA MISMATCH for ${id.descriptor}';
+ message = '$prefix: Data from $astName: ${value1}, '
+ 'data from $kernelName: ${value2}';
+ } else {
+ String prefix = 'MISSING $kernelName DATA for ${id.descriptor}, '
+ 'object = ${actualData1.objectText}';
+ message = '$prefix: Data from $astName: ${value1}, '
+ 'no data from $kernelName';
+ }
+ reportError(data1.compiler.reporter, actualData1.sourceSpan, message);
if (!whiteList(uri1, id)) {
hasErrors = hasErrorsInUri = true;
}
@@ -843,15 +868,24 @@
IdValue value2 = actualData2.value;
IdValue value1 = actualMap1[id]?.value;
if (value1 != value2) {
- reportHere(data2.compiler.reporter, actualData2.sourceSpan,
- '$id: from source:${value1},from dill:${value2}');
+ String prefix = 'EXTRA $kernelName DATA for ${id.descriptor}, '
+ 'object = ${actualData2.objectText}';
+ String message =
+ '$prefix: Data from $kernelName: ${value2}, no data from $astName';
+ reportError(data1.compiler.reporter, actualData2.sourceSpan, message);
if (!whiteList(uri1, id)) {
hasErrors = hasErrorsInUri = true;
}
}
});
if (hasErrorsInUri) {
- print('--annotations diff $uri1---------------------------------------');
+ Uri fileUri;
+ if (data1.compiler.mainLibraryUri == uri1) {
+ fileUri = mainFileUri;
+ } else {
+ fileUri = uri1;
+ }
+ print('--annotations diff for: $fileUri -------------------------------');
print(withAnnotations(
sourceCode1,
data1.computeDiffAnnotationsAgainst(actualMap1, actualMap2, uri1,
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart b/tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
similarity index 91%
rename from tests/compiler/dart2js/equivalence/id_equivalence_test.dart
rename to tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
index b4441ed..3592578 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_test.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_tester.dart
@@ -15,24 +15,27 @@
import 'package:compiler/src/resolution/access_semantics.dart';
import 'package:compiler/src/resolution/send_structure.dart';
import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:sourcemap_testing/src/annotated_code_helper.dart';
-import '../equivalence/id_equivalence.dart';
-import '../equivalence/id_equivalence_helper.dart';
+import 'id_equivalence.dart';
+import 'id_equivalence_helper.dart';
-const List<String> dataDirectories = const <String>[
+const List<String> dataDirectories1 = const <String>[
'../closure/data',
'../inference/data',
+ '../inlining/data',
+];
+
+const List<String> dataDirectories2 = const <String>[
'../jumps/data',
+ '../rti/data',
+ '../rti/emission',
];
const List<String> skipList = const <String>[
- // TODO(johnniwinther): Fix these when kernel provides a unique offset for
- // `()` in `foo[0]()`.
- 'closure_tracer.dart',
- 'closure_tracer_28919.dart',
- 'index_call.dart',
- 'map_tracer_const.dart',
+ // Unpatched external functions are not supported in the legacy frontend.
+ 'external.dart',
// Id equivalence doesn't support libraries.
'mixin_constructor_default_parameter_values.dart',
// Id equivalence doesn't support unused constructors.
@@ -42,14 +45,22 @@
];
main(List<String> args) {
+ mainInternal(args, []..addAll(dataDirectories1)..addAll(dataDirectories2));
+}
+
+mainInternal(List<String> args, Iterable<String> dataDirectories) {
+ args = args.toList();
+ bool shouldContinue = args.remove('-c');
+ bool continued = false;
asyncTest(() async {
+ bool hasFailures = false;
for (String path in dataDirectories) {
Directory dataDir = new Directory.fromUri(Platform.script.resolve(path));
await for (FileSystemEntity entity in dataDir.list()) {
- if (args.isNotEmpty && !args.contains(entity.uri.pathSegments.last)) {
- continue;
- }
- if (skipList.contains(entity.uri.pathSegments.last)) {
+ String name = entity.uri.pathSegments.last;
+ if (args.isNotEmpty && !args.contains(name) && !continued) continue;
+ if (shouldContinue) continued = true;
+ if (skipList.contains(name)) {
print('Skipping ${entity.uri}');
continue;
}
@@ -65,11 +76,14 @@
Map<String, String> memorySourceFiles = {
entryPoint.path: code.sourceCode
};
- await compareData(entryPoint, memorySourceFiles, computeAstMemberData,
- computeIrMemberData,
- options: [Flags.disableTypeInference, stopAfterTypeInference]);
+ if (!await compareData(entity.uri, entryPoint, memorySourceFiles,
+ computeAstMemberData, computeIrMemberData,
+ options: [Flags.disableTypeInference, stopAfterTypeInference])) {
+ hasFailures = true;
+ }
}
}
+ Expect.isFalse(hasFailures, 'Errors found.');
});
}
diff --git a/tests/compiler/dart2js/inference/inference_equivalence.dart b/tests/compiler/dart2js/inference/inference_equivalence.dart
index cdd9a9e..638eab5 100644
--- a/tests/compiler/dart2js/inference/inference_equivalence.dart
+++ b/tests/compiler/dart2js/inference/inference_equivalence.dart
@@ -72,7 +72,7 @@
Future<bool> testUri(Uri uri,
{bool verbose: false, bool whiteList(Uri uri, Id id)}) {
return compareData(
- uri, const {}, computeMemberAstTypeMasks, computeMemberIrTypeMasks,
+ uri, uri, const {}, computeMemberAstTypeMasks, computeMemberIrTypeMasks,
options: [stopAfterTypeInference],
forUserLibrariesOnly: false,
skipUnprocessedMembers: true,
diff --git a/tests/compiler/dart2js/kernel/compiler_helper.dart b/tests/compiler/dart2js/kernel/compiler_helper.dart
index e32bb06..d59c303 100644
--- a/tests/compiler/dart2js/kernel/compiler_helper.dart
+++ b/tests/compiler/dart2js/kernel/compiler_helper.dart
@@ -65,7 +65,7 @@
MemoryKernelLibraryLoaderTask(KernelToElementMapForImpact elementMap,
DiagnosticReporter reporter, Measurer measurer, this.component)
- : super(null, null, elementMap, null, reporter, measurer);
+ : super(null, null, null, elementMap, null, reporter, measurer);
Future<LoadedLibraries> loadLibrary(Uri resolvedUri,
{bool skipFileWithPartOfTag: false}) async {
diff --git a/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart b/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart
deleted file mode 100644
index e10862d..0000000
--- a/tests/compiler/dart2js/old_frontend/analyze_dart2js_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2013, 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 analyze_dart2js;
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/compiler.dart';
-import 'analyze_helper.dart';
-import 'related_types.dart';
-
-/**
- * Map of whitelisted warnings and errors.
- *
- * Only add a whitelisting together with a bug report to dartbug.com and add
- * the bug issue number as a comment on the whitelisting.
- *
- * Use an identifiable suffix of the file uri as key. Use a fixed substring of
- * the error/warning message in the list of whitelistings for each file.
- */
-// TODO(johnniwinther): Support canonical URIs as keys and message kinds as
-// values.
-const Map<String, List<String>> WHITE_LIST = const {
- "pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart": const [
- "The getter 'iterator' is not defined for the class 'Object'.",
- ],
- "pkg/front_end/lib/src/fasta/type_inference/type_schema.dart": const [
- "The class 'UnknownType' overrides 'operator==', but not 'get hashCode'."
- ],
- "pkg/kernel/lib/transformations/closure/": const [
- "Duplicated library name 'kernel.transformations.closure.converter'",
- ],
- "pkg/kernel/lib/transformations/closure/info.dart": const [
- "Types 'FunctionNode' and 'FunctionDeclaration' have no common subtypes."
- ],
- "third_party/pkg/collection/lib/src/functions.dart": const [
- "Method type variables are treated as `dynamic` in `as` expressions."
- ],
- "sdk/lib/_internal/js_runtime/lib/js_array.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/collection/iterable.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/collection/list.dart": const [
- "Method type variables do not have a runtime value.",
- "Method type variables are treated as `dynamic` in `as` expressions.",
- ],
- "sdk/lib/collection/set.dart": const [
- "Method type variables do not have a runtime value.",
- ],
- "sdk/lib/core/iterable.dart": const [
- "Method type variables do not have a runtime value.",
- "Method type variables are treated as `dynamic` in `as` expressions.",
- ],
-};
-
-void main() {
- var uri = currentDirectory.resolve('pkg/compiler/lib/src/dart2js.dart');
- asyncTest(() => analyze([uri], WHITE_LIST, checkResults: checkResults));
-}
-
-bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
- checkRelatedTypes(compiler);
- return !handler.hasHint;
-}
diff --git a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart b/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
deleted file mode 100644
index dd803ab..0000000
--- a/tests/compiler/dart2js/old_frontend/analyze_unused_dart2js_test.dart
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2013, 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 analyze_unused_dart2js;
-
-import 'package:async_helper/async_helper.dart';
-
-import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/diagnostics/messages.dart';
-import 'package:compiler/src/elements/elements.dart' show LibraryElement;
-import 'package:compiler/src/filenames.dart';
-
-import 'analyze_helper.dart';
-
-// Do not remove WHITE_LIST even if it's empty. The error message for
-// unused members refers to WHITE_LIST by name.
-const Map<String, List<String>> WHITE_LIST = const {
- // TODO(johnniwinther): uncomment when [Compiler.reportUnusedCode] is
- // reenabled.
- // // Helper methods for debugging should never be called from production code:
- // "lib/src/helpers/": const [" is never "],
-
- // // Node.asAssert, Node.asLiteralBool is never used.
- // "lib/src/tree/nodes.dart": const [
- // "The method 'asAssert' is never called.",
- // "The method 'asLiteralBool' is never called."
- // ],
-
- // // Uncalled methods in SemanticSendVisitor and subclasses.
- // "lib/src/resolution/semantic_visitor.dart": const ["The method 'error"],
- // "lib/src/resolution/semantic_visitor_mixins.dart": const [
- // "The class 'SuperBulkMixin'",
- // "The class 'Base",
- // "The method 'error",
- // "The method 'visit"
- // ],
-
- // // Uncalled type predicate. Keep while related predicates are used.
- // "lib/src/ssa/nodes.dart": const ["The method 'isArray' is never called"],
-
- // // Serialization code is only used in test.
- // "lib/src/serialization/": const ["is never"],
-
- // "lib/src/universe/world_builder.dart": const [
- // "The method 'getterInvocationsByName' is never called.",
- // "The method 'setterInvocationsByName' is never called."
- // ],
-
- "pkg/front_end/lib/src/fasta/type_inference/type_schema.dart": const [
- "The class 'UnknownType' overrides 'operator==', but not 'get hashCode'."
- ],
-
- "pkg/kernel/lib/transformations/closure/": const [
- "Duplicated library name 'kernel.transformations.closure.converter'",
- ],
-
- "pkg/kernel/lib/binary/ast_to_binary.dart": const [
- "'void' is not a subtype of bound 'Object' for type variable",
- ],
-
- "pkg/compiler/lib/src/js_backend/runtime_types.dart": const [
- "'void' is not a subtype of bound 'Object' for type variable",
- ],
-
- "sdk/lib/io/file.dart": const [
- "'void' is not a subtype of bound 'Object' for type variable",
- ],
-
- "sdk/lib/io/file_impl.dart": const [
- "'void' is not a subtype of bound 'Object' for type variable",
- ],
-};
-
-void main() {
- var uri =
- currentDirectory.resolve('pkg/compiler/lib/src/use_unused_api.dart');
- asyncTest(() => analyze([uri], WHITE_LIST,
- mode: AnalysisMode.TREE_SHAKING, checkResults: checkResults));
-}
-
-bool checkResults(Compiler compiler, CollectingDiagnosticHandler handler) {
- var helperUri =
- currentDirectory.resolve('pkg/compiler/lib/src/helpers/helpers.dart');
- void checkLive(member) {
- if (member.isFunction) {
- if (compiler.resolutionWorldBuilder.isMemberUsed(member)) {
- compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
- {'text': "Helper function in production code '$member'."});
- }
- } else if (member.isClass) {
- if (member.isResolved) {
- compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
- {'text': "Helper class in production code '$member'."});
- } else {
- member.forEachLocalMember(checkLive);
- }
- } else if (member.isTypedef) {
- if (member.isResolved) {
- compiler.reporter.reportHintMessage(member, MessageKind.GENERIC,
- {'text': "Helper typedef in production code '$member'."});
- }
- }
- }
-
- (compiler.libraryLoader.lookupLibrary(helperUri) as LibraryElement)
- .forEachLocalMember(checkLive);
- return handler.checkResults();
-}
diff --git a/tests/compiler/dart2js/sourcemaps/name_test.dart b/tests/compiler/dart2js/sourcemaps/name_test.dart
index 4855843..f540c8b 100644
--- a/tests/compiler/dart2js/sourcemaps/name_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/name_test.dart
@@ -6,9 +6,11 @@
import 'package:async_helper/async_helper.dart';
import 'package:expect/expect.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/elements/entities.dart';
-import 'package:compiler/src/io/source_information.dart';
+import 'package:compiler/src/io/kernel_source_information.dart';
+import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
import '../memory_compiler.dart';
const String SOURCE = '''
@@ -71,22 +73,25 @@
}
''';
-check(Entity element, String expectedName) {
- String name = computeElementNameForSourceMaps(element);
- Expect.equals(expectedName, name,
- "Unexpected name '$name' for $element, expected '$expectedName'.");
-}
-
main() {
asyncTest(() async {
- CompilationResult result =
- await runCompiler(memorySourceFiles: {'main.dart': SOURCE});
+ CompilationResult result = await runCompiler(
+ memorySourceFiles: {'main.dart': SOURCE},
+ options: [Flags.disableInlining]);
Compiler compiler = result.compiler;
+ KernelBackendStrategy backendStrategy = compiler.backendStrategy;
var env = compiler.backendClosedWorldForTesting.elementEnvironment;
LibraryEntity mainApp = env.mainLibrary;
- Entity lookup(String name) {
- Entity element;
+ check(MemberEntity element, String expectedName) {
+ String name = computeKernelElementNameForSourceMaps(
+ backendStrategy.elementMap, element);
+ Expect.equals(expectedName, name,
+ "Unexpected name '$name' for $element, expected '$expectedName'.");
+ }
+
+ MemberEntity lookup(String name) {
+ MemberEntity element;
int dotPosition = name.indexOf('.');
if (dotPosition != -1) {
String clsName = name.substring(0, dotPosition);
@@ -95,8 +100,6 @@
var subname = name.substring(dotPosition + 1);
element = env.lookupLocalClassMember(cls, subname) ??
env.lookupConstructor(cls, subname);
- } else if (name.substring(0, 1) == name.substring(0, 1).toUpperCase()) {
- element = env.lookupClass(mainApp, name);
} else {
element = env.lookupLibraryMember(mainApp, name);
}
@@ -125,7 +128,6 @@
env.forEachNestedClosure(element, (closure) {
String expectedName = expectedClosureNames[index];
check(closure, expectedName);
- check(closure.enclosingClass, expectedName);
index++;
});
}
@@ -133,28 +135,28 @@
checkName('toplevelField');
checkName('toplevelMethod');
- // TODO(johnniwinther): improve closure names.
- checkName('toplevelAnonymous', ['toplevelAnonymous_closure']);
- checkName('toplevelLocal', ['toplevelLocal_localMethod']);
- checkName('Class');
+ checkName('toplevelAnonymous', ['toplevelAnonymous.<anonymous function>']);
+ checkName('toplevelLocal', ['toplevelLocal.localMethod']);
checkName('main');
checkName('Class.staticField');
checkName('Class.staticMethod');
- checkName('Class.staticAnonymous', ['Class_staticAnonymous_closure']);
- checkName('Class.staticLocal', ['Class_staticLocal_localMethod']);
+ checkName('Class.staticAnonymous',
+ ['Class.staticAnonymous.<anonymous function>']);
+ checkName('Class.staticLocal', ['Class.staticLocal.localMethod']);
- checkName('Class', ['Class_closure'], 'Class.');
- checkName('Class.named', ['Class\$named_localMethod']);
+ checkName('Class', ['Class.<anonymous function>'], 'Class.');
+ checkName('Class.named', ['Class.named.localMethod']);
checkName('Class.instanceField');
checkName('Class.instanceMethod');
- checkName('Class.instanceAnonymous', ['Class_instanceAnonymous_closure']);
- checkName('Class.instanceLocal', ['Class_instanceLocal_localMethod']);
+ checkName('Class.instanceAnonymous',
+ ['Class.instanceAnonymous.<anonymous function>']);
+ checkName('Class.instanceLocal', ['Class.instanceLocal.localMethod']);
checkName('Class.instanceNestedLocal', [
- 'Class_instanceNestedLocal_localMethod',
- 'Class_instanceNestedLocal_localMethod_closure',
- 'Class_instanceNestedLocal_localMethod_nestedLocalMethod'
+ 'Class.instanceNestedLocal.localMethod',
+ 'Class.instanceNestedLocal.localMethod.<anonymous function>',
+ 'Class.instanceNestedLocal.localMethod.nestedLocalMethod'
]);
});
}
diff --git a/tests/corelib_2/bigint_test.dart b/tests/corelib_2/bigint_test.dart
index 0401e12..ed526b4 100644
--- a/tests/corelib_2/bigint_test.dart
+++ b/tests/corelib_2/bigint_test.dart
@@ -280,6 +280,33 @@
Expect.equals(-BigInt.parse("1000000001000000000"), a * b);
}
+testBigintAnd() {
+ var a = BigInt.parse("0x55555555555555555555");
+ var b = BigInt.parse("0x33333333333333333333");
+ var c = BigInt.parse("0x11111111111111111111");
+ Expect.equals(BigInt.zero, BigInt.zero & a);
+ Expect.equals(BigInt.zero, a & BigInt.zero);
+ Expect.equals(c, a & b);
+}
+
+testBigintOr() {
+ var a = BigInt.parse("0x33333333333333333333");
+ var b = BigInt.parse("0x55555555555555555555");
+ var c = BigInt.parse("0x77777777777777777777");
+ Expect.equals(a, BigInt.zero | a);
+ Expect.equals(a, a | BigInt.zero);
+ Expect.equals(c, a | b);
+}
+
+testBigintXor() {
+ var a = BigInt.parse("0x33333333333333333333");
+ var b = BigInt.parse("0x55555555555555555555");
+ var c = BigInt.parse("0x66666666666666666666");
+ Expect.equals(a, BigInt.zero ^ a);
+ Expect.equals(a, a ^ BigInt.zero);
+ Expect.equals(c, a ^ b);
+}
+
testBigintAdd() {
// Bigint and Smi.
var a = BigInt.parse("12345678901234567890");
@@ -289,6 +316,8 @@
// Bigint and Bigint.
a = BigInt.parse("10000000000000000001");
Expect.equals(BigInt.parse("20000000000000000002"), a + a);
+ Expect.equals(a, BigInt.zero + a);
+ Expect.equals(a, a + BigInt.zero);
}
testBigintSub() {
@@ -300,6 +329,8 @@
// Bigint and Bigint.
a = BigInt.parse("10000000000000000001");
Expect.equals(BigInt.parse("20000000000000000002"), a + a);
+ Expect.equals(-a, BigInt.zero - a);
+ Expect.equals(a, a - BigInt.zero);
}
testBigintMul() {
@@ -634,6 +665,12 @@
}
testShiftAmount() {
+ Expect.equals(BigInt.zero, BigInt.zero << 0);
+ Expect.equals(BigInt.zero, BigInt.zero >> 0);
+ Expect.equals(BigInt.zero, BigInt.zero << 1234567890);
+ Expect.equals(BigInt.zero, BigInt.zero >> 1234567890);
+ Expect.equals(BigInt.two.pow(999), BigInt.one << 999);
+ Expect.equals(BigInt.one, BigInt.two.pow(999) >> 999);
Expect.equals(BigInt.zero, new BigInt.from(12) >> 0x7FFFFFFFFFFFFFFF);
Expect.equals(-BigInt.one, -new BigInt.from(12) >> 0x7FFFFFFFFFFFFFFF);
bool exceptionCaught = false;
@@ -910,6 +947,9 @@
testModInverse();
testGcd();
testSmiOverflow();
+ testBigintAnd();
+ testBigintOr();
+ testBigintXor();
testBigintAdd();
testBigintSub();
testBigintMul();
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 4083750a..2890a4f 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -87,6 +87,9 @@
[ !$strong ]
cast_test: SkipByDesign # Uses generic method parameters.
+[ $arch == ia32 && $builder_tag == optimization_counter_threshold ]
+bigint_from_test: RuntimeError # Issue 32619
+
[ $arch == simarmv5te && ($runtime == dart_precompiled || $runtime == vm) ]
int_parse_radix_test/*: Pass, Slow
integer_parsed_mul_div_vm_test: Pass, Slow
@@ -213,10 +216,8 @@
[ $compiler == dart2js && $fasta && $host_checked && $strong ]
apply3_test: RuntimeError
-apply_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
bigint_test: RuntimeError
cast_test: RuntimeError
-date_time11_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
dynamic_nosuchmethod_test: RuntimeError
error_stack_trace1_test: RuntimeError # Issue 12399
growable_list_test: RuntimeError # Concurrent modifications test always runs
@@ -232,7 +233,6 @@
iterable_return_type_test/01: RuntimeError # Issue 20085
iterable_return_type_test/02: RuntimeError # Dart2js does not support Uint64*.
iterable_to_list_test/01: RuntimeError # Issue 26501
-iterable_where_type_test: Crash # 'file:*/pkg/compiler/lib/src/js_emitter/runtime_type_generator.dart': Failed assertion: line 208 pos 18: '!(_useKernel && _strongMode && !_disableRtiOptimization) ||
list_concurrent_modify_test: RuntimeError # dart2js does not fully implement these
list_test/01: RuntimeError
list_test/none: RuntimeError
diff --git a/tests/html/audiobuffersourcenode_test.dart b/tests/html/audiobuffersourcenode_test.dart
index 34dc221..7da731f 100644
--- a/tests/html/audiobuffersourcenode_test.dart
+++ b/tests/html/audiobuffersourcenode_test.dart
@@ -19,7 +19,7 @@
var ctx = new AudioContext();
AudioBufferSourceNode node = ctx.createBufferSource();
expect(node is AudioBufferSourceNode, isTrue);
- node.start2(ctx.currentTime, 0, 2);
+ node.start(ctx.currentTime, 0, 2);
expect(node is AudioBufferSourceNode, isTrue);
}
});
diff --git a/tests/html/html.status b/tests/html/html.status
index bd4fae9..2b26a61 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -125,6 +125,7 @@
audiobuffersourcenode_test/functional: RuntimeError
canvasrenderingcontext2d_test/drawImage_video_element: Fail # Safari does not support drawImage w/ video element
canvasrenderingcontext2d_test/drawImage_video_element_dataUrl: Fail # Safari does not support drawImage w/ video element
+css_test/functional: RuntimeError # Issue 32576
element_animate_test: Fail # Element.animate not supported on these browsers.
element_test: Pass, Fail # Issue 21434
element_types_test/supported_content: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
@@ -150,6 +151,7 @@
rtc_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
shadow_dom_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
speechrecognition_test/supported: Fail # Safari Feature support statuses - All changes should be accompanied by platform support annotation changes.
+svgelement_test/getBoundingClientRect: RuntimeError # Issue 32572
touchevent_test/supported: Fail # Safari does not support TouchEvents
webgl_1_test: Pass, Fail # Issue 8219
worker_api_test: Skip # Issue 13221
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 5161156..9cc7e0e 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -10,6 +10,7 @@
full_stacktrace1_test: Pass, RuntimeError # Issue 12698
full_stacktrace2_test: Pass, RuntimeError # Issue 12698
full_stacktrace3_test: Pass, RuntimeError # Issue 12698
+library_env_test/has_no_html_support: RuntimeError, OK
local_function_test: RuntimeError # Issue 31879
vm/*: Skip # Issue 12699
@@ -29,7 +30,6 @@
override_field_test/02: Pass, Slow # TODO(kasperl): Please triage.
[ $compiler == dart2js && $runtime == d8 && $fasta ]
-library_env_test/has_no_io_support: RuntimeError
regress_23408_test: RuntimeError
[ $compiler == dart2js && $runtime != drt ]
@@ -66,20 +66,19 @@
[ $compiler == dart2js && $system == windows && !$fasta && ($runtime == chrome || $runtime == ff) ]
string_literals_test: RuntimeError # Issue 27533
+[ $compiler == dart2js && $browser ]
+config_import_test: RuntimeError # Test flag is not passed to the compiler.
+library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when using '--categories=Client'.
+
[ $compiler == dart2js && $browser && $csp && !$fast_startup ]
conditional_import_string_test: Fail # Issue 30615
conditional_import_test: Fail # Issue 30615
-[ $compiler == dart2js && $browser && $fasta ]
-conditional_import_string_test: RuntimeError
-conditional_import_test: RuntimeError
-config_import_corelib_test: RuntimeError
-library_env_test/has_io_support: RuntimeError
+[ $compiler == dart2js && !$browser ]
+library_env_test/has_no_io_support: RuntimeError, OK # dart2js supports io when using '--categories=all'.
-[ $compiler == dart2js && $browser && !$fasta ]
-config_import_test: Fail # Test flag is not passed to the compiler.
-library_env_test/has_io_support: RuntimeError # Issue 27398
-library_env_test/has_no_io_support: Pass # Issue 27398
+[ $compiler == dart2js && !$browser && $fasta ]
+config_import_corelib_test: RuntimeError, OK # all dart:* are supported when using '--categories=all'.
[ $compiler == dart2js && $checked && $fasta ]
assertion_initializer_const_function_test/01: RuntimeError
@@ -332,7 +331,7 @@
class_literal_test/01: RuntimeError
class_literal_test/03: RuntimeError
class_literal_test/07: RuntimeError
-config_import_test: RuntimeError
+config_import_test: RuntimeError # not supported by fasta
const_error_multiply_initialized_test/02: MissingCompileTimeError
const_error_multiply_initialized_test/04: MissingCompileTimeError
const_evaluation_test/01: RuntimeError
@@ -408,8 +407,7 @@
invocation_mirror_test: RuntimeError # mirrors not supported
issue21079_test: RuntimeError
left_shift_test: RuntimeError
-library_env_test/has_mirror_support: RuntimeError
-library_env_test/has_no_html_support: RuntimeError
+library_env_test/has_mirror_support: RuntimeError, OK
list_literal4_test: RuntimeError
main_not_a_function_test/01: CompileTimeError
many_overridden_no_such_method_test: RuntimeError
@@ -688,9 +686,7 @@
invocation_mirror2_test: RuntimeError # Issue 6490 (wrong retval).
invocation_mirror_empty_arguments_test: Fail # Issue 24331
left_shift_test: RuntimeError # Issue 1533
-library_env_test/has_no_html_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
-library_env_test/has_no_io_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
-library_env_test/has_no_mirror_support: RuntimeError, OK # The following tests are supposed to fail. In testing-mode, dart2js supports all dart:X libraries (because it uses '--categories=all').
+library_env_test/has_no_mirror_support: RuntimeError, OK
list_literal4_test: RuntimeError # Issue 12890
malformed_test/none: Fail # Expect failure in lib/_internal/js_runtime/lib/preambles/d8.js
method_override5_test: RuntimeError # Issue 12809
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index f42f191..acf2b12 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -6,9 +6,12 @@
[ $compiler == dart2js ]
async_star_cancel_while_paused_test: RuntimeError # Issue 22853
bit_operations_test: RuntimeError, OK # non JS number semantics
+config_import_corelib_test: CompileTimeError # we need a special platform.dill file for categories=all. Once we fix that, all dart:* are supported when using '--categories=all' so this will become a RuntimeError, OK.
config_import_test: RuntimeError # Test flag is not passed to the compiler.
double_identical_test: RuntimeError # Negative and positive zero are distinct, but not in dart2js; bug #11551.
issue23244_test: RuntimeError # Isolates - enum canonicalization - Issue 23244
+library_env_test/has_mirror_support: RuntimeError, OK
+library_env_test/has_no_html_support: RuntimeError, OK
null_test/mirrors: SkipByDesign # Uses mirrors.
vm/*: SkipByDesign # Tests for the VM.
@@ -176,13 +179,15 @@
string_literals_test: Pass, RuntimeError # Failures on dart2js-win7-chrome-4-4-be and dart2js-win7-ie11ff-4-4-be
[ $compiler == dart2js && $browser ]
-library_env_test/has_io_support: RuntimeError # Issue 27398
-library_env_test/has_no_io_support: Pass # Issue 27398
+library_env_test/has_io_support: RuntimeError, OK # dart2js doesn't support io when compiling on --categories=Client
[ $compiler == dart2js && $browser && $csp && !$fast_startup ]
conditional_import_string_test: Fail # Issue 30615
conditional_import_test: Fail # Issue 30615
+[ $compiler == dart2js && !$browser ]
+library_env_test/has_no_io_support: RuntimeError, OK # dart2js supports io when using '--categories=all'.
+
[ $compiler == dart2js && $checked ]
covariant_subtyping_test: CompileTimeError
@@ -584,24 +589,23 @@
assertion_test: RuntimeError, OK
[ $compiler == dart2js && !$checked && $fasta ]
+cascaded_forwarding_stubs_generic_test: RuntimeError
+cascaded_forwarding_stubs_test: RuntimeError
+checked_setter3_test: RuntimeError # Issue 31128
constructor_call_as_function_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_const_context_prefix_constructor_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_new_constructor_named_test: CompileTimeError # Issue 32517
+forwarding_semi_stub_test: RuntimeError
+forwarding_stub_tearoff_generic_test: RuntimeError
+forwarding_stub_tearoff_test: RuntimeError
implicit_creation/implicit_const_context_constructor_generic_test: CompileTimeError # Issue 32517
-implicit_creation/implicit_const_context_prefix_constructor_named_test: CompileTimeError # Issue 32517
implicit_creation/implicit_const_context_constructor_named_test: CompileTimeError # Issue 32517
implicit_creation/implicit_const_context_constructor_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_const_context_prefix_constructor_named_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_const_context_prefix_constructor_test: CompileTimeError # Issue 32517
+implicit_creation/implicit_new_constructor_named_test: CompileTimeError # Issue 32517
implicit_creation/implicit_new_constructor_test: CompileTimeError # Issue 32517
implicit_creation/implicit_new_or_const_composite_test: CompileTimeError # Issue 32517
implicit_creation/implicit_new_or_const_test: CompileTimeError # Issue 32517
implicit_creation/implicit_new_prefix_constructor_named_test: CompileTimeError # Issue 32517
-
-cascaded_forwarding_stubs_generic_test: RuntimeError
-cascaded_forwarding_stubs_test: RuntimeError
-checked_setter3_test: RuntimeError # Issue 31128
-forwarding_semi_stub_test: RuntimeError
-forwarding_stub_tearoff_generic_test: RuntimeError
-forwarding_stub_tearoff_test: RuntimeError
implicit_downcast_during_assignment_test: RuntimeError
implicit_downcast_during_combiner_test: RuntimeError
implicit_downcast_during_compound_assignment_test: RuntimeError
@@ -1231,8 +1235,6 @@
compile_time_constant_static5_test/16: CompileTimeError
compile_time_constant_static5_test/21: CompileTimeError
compile_time_constant_static5_test/23: CompileTimeError
-conditional_import_string_test: CompileTimeError
-conditional_import_test: CompileTimeError
conditional_rewrite_test: RuntimeError
config_import_corelib_test: CompileTimeError
config_import_test: RuntimeError
@@ -1418,7 +1420,6 @@
generic_no_such_method_dispatcher_simple_test: CompileTimeError
generic_no_such_method_dispatcher_test: CompileTimeError
generic_tearoff_test: CompileTimeError
-generic_test: RuntimeError
getter_override2_test/02: MissingCompileTimeError
getter_override_test/00: MissingCompileTimeError
getter_override_test/01: MissingCompileTimeError
@@ -1626,6 +1627,7 @@
no_such_method_test: RuntimeError
nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
null_no_such_method_test: CompileTimeError
null_test/mirrors: RuntimeError
null_test/none: RuntimeError
@@ -1854,8 +1856,8 @@
void_type_usage_test/conditional2_dynamic_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_for: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_literal_list_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
-void_type_usage_test/conditional2_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_literal_map_value_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
+void_type_usage_test/conditional2_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_null_equals2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_parens: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional2_return: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
@@ -1871,8 +1873,8 @@
void_type_usage_test/conditional3_dynamic_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_for: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_literal_list_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
-void_type_usage_test/conditional3_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_literal_map_value_init: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
+void_type_usage_test/conditional3_literal_map_value_init2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_null_equals2: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_parens: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
void_type_usage_test/conditional3_return: Crash # 'package:front_end/src/fasta/type_inference/type_schema_environment.dart': Failed assertion: line 214 pos 12: 'false': is not true.
@@ -1990,8 +1992,6 @@
compile_time_constant_static5_test/16: CompileTimeError
compile_time_constant_static5_test/21: CompileTimeError
compile_time_constant_static5_test/23: CompileTimeError
-conditional_import_string_test: CompileTimeError
-conditional_import_test: CompileTimeError
conditional_rewrite_test: RuntimeError
config_import_corelib_test: CompileTimeError
config_import_test: RuntimeError
@@ -2387,6 +2387,7 @@
no_such_method_test: RuntimeError
nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
null_no_such_method_test: CompileTimeError
null_test/mirrors: RuntimeError
null_test/none: RuntimeError
@@ -2610,4 +2611,3 @@
mixin_mixin_bound2_test: RuntimeError # Issue 31054
mixin_mixin_bound_test: RuntimeError # Issue 31054
mixin_mixin_type_arguments_test: RuntimeError # Issue 31054
-
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index e94da20..2dfeef7 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -167,6 +167,7 @@
multiline_newline_test/none: RuntimeError
multiple_interface_inheritance_test: CompileTimeError # Issue 30552
nested_generic_closure_test: CompileTimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError # Issue 31425
override_inheritance_field_test/04: CompileTimeError
override_inheritance_field_test/06: CompileTimeError
override_inheritance_field_test/26: CompileTimeError
@@ -612,6 +613,7 @@
named_parameters_default_eq_test/02: MissingCompileTimeError
no_such_method_mock_test: RuntimeError # Issue 31425
nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31425
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError # Issue 31425
nsm5_test: MissingCompileTimeError
null2_test: RuntimeError # Issue 32194
null_method_test: RuntimeError # Issue 32194
@@ -885,4 +887,3 @@
switch_try_catch_test: RuntimeError # Issue 29920; Expect.throws: Unexpected 'UnimplementedError: node <ShadowContinueSwitchStatement> see https://github.com/dart-lang/sdk/issues/29352 `continue #L1;
truncdiv_test: RuntimeError # Issue 29920; Expect.throws fails: Did not throw
vm/*: SkipByDesign # VM only tests.; VM only tests.
-
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index cea3c5c..776be24 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -717,8 +717,6 @@
no_main_test/01: Skip
no_main_test/01: DartkCrash
no_such_method_mock_test: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
null_no_such_method_test: CompileTimeError # Issue 31533
override_inheritance_field_test/04: CompileTimeError # Issue 31616
override_inheritance_field_test/06: CompileTimeError # Issue 31616
@@ -1075,8 +1073,6 @@
no_main_test/01: Skip
no_such_method_mock_test: RuntimeError
no_such_method_test: SkipByDesign
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError # Issue 31426
-nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError # Issue 31426
null_no_such_method_test: CompileTimeError # Issue 31533
null_test/mirrors: Skip # Uses mirrors.
null_test/none: SkipByDesign
@@ -2209,4 +2205,3 @@
[ $compiler == dartk || $compiler == dartkp ]
generic_function_bounds_test: RuntimeError # Issue 32076
generic_test/01: MissingCompileTimeError
-
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index a6dedf1..dfc7a3b 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -1328,6 +1328,7 @@
generic_methods_test: Pass # Issue 25869
nosuchmethod_forwarding/nosuchmethod_forwarding_test/05: RuntimeError
nosuchmethod_forwarding/nosuchmethod_forwarding_test/06: RuntimeError
+nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test: RuntimeError
nsm5_test: MissingCompileTimeError
override_inheritance_no_such_method_test/05: MissingCompileTimeError
@@ -1346,4 +1347,3 @@
invalid_type_argument_count_test/03: MissingCompileTimeError # Error only in strong mode
invalid_type_argument_count_test/04: MissingCompileTimeError # Error only in strong mode
partial_tearoff_instantiation_test/none: CompileTimeError
-
diff --git a/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart b/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart
new file mode 100644
index 0000000..cf5b1be
--- /dev/null
+++ b/tests/language_2/nosuchmethod_forwarding/nosuchmethod_forwarding_arguments_test.dart
@@ -0,0 +1,84 @@
+// 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.
+
+// Testing that `noSuchMethod` forwarding properly handles optional, named and
+// type parameters, and result type checking.
+
+import 'package:expect/expect.dart';
+
+class A {
+ dynamic noSuchMethod(Invocation invoke) {
+ if (invoke.memberName == #test0) {
+ Expect.equals(invoke.positionalArguments[0], 1);
+ Expect.equals(invoke.positionalArguments[1], 2);
+ return null;
+ } else if (invoke.memberName == #test1) {
+ Expect.isTrue(invoke.namedArguments.isEmpty);
+ return null;
+ } else if (invoke.memberName == #test2) {
+ Expect.isTrue(invoke.namedArguments.isEmpty);
+ return null;
+ } else if (invoke.memberName == #test3) {
+ Expect.equals(invoke.namedArguments[#x], "ok");
+ return null;
+ } else if (invoke.memberName == #test4) {
+ Expect.equals(invoke.positionalArguments[0], "ok");
+ return null;
+ } else if (invoke.memberName == #test5) {
+ Expect.equals(invoke.typeArguments[0].toString(), "int");
+ return null;
+ } else if (invoke.memberName == #test6) {
+ return 1;
+ } else if (invoke.memberName == #allTogetherNow) {
+ Expect.equals(invoke.typeArguments.length, 2);
+ Expect.equals(invoke.typeArguments[0].toString(), "num");
+ Expect.equals(invoke.typeArguments[1].toString(), "double");
+
+ Expect.equals(invoke.positionalArguments.length, 1);
+ Expect.equals(invoke.positionalArguments[0], 2.0);
+
+ Expect.equals(invoke.namedArguments.length, 1);
+ Expect.equals(invoke.namedArguments[#foo], const <num>[3, 4]);
+ }
+ }
+
+ void test0(int x, int y);
+ void test1({String x});
+ void test2({String x: "w/e"});
+ void test3({String x: "w/e"});
+ void test4([String x]);
+ void test5<T extends num>(T x);
+ String test6();
+
+ T allTogetherNow<T, S extends T>(S x1, {List<T> foo: const <Null>[]});
+}
+
+main() {
+ var a = new A();
+
+ a.test0(1, 2);
+ (a.test0 as dynamic)(1, 2);
+
+ a.test1();
+ (a.test1 as dynamic)();
+
+ a.test2();
+ (a.test2 as dynamic)();
+
+ a.test3(x: "ok");
+ (a.test3 as dynamic)(x: "ok");
+
+ a.test4("ok");
+ (a.test4 as dynamic)("ok");
+
+ a.test5<int>(1);
+ (a.test5 as dynamic)<int>(1);
+ Expect.throwsTypeError(() => (a.test5 as dynamic)<String>("foo"));
+ Expect.throwsTypeError(() => (a.test5 as dynamic)<int>(3.0));
+
+ Expect.throwsTypeError(() => a.test6());
+ Expect.throwsTypeError(() => (a.test6 as dynamic)());
+
+ a.allTogetherNow<num, double>(2.0, foo: const <num>[3, 4]);
+}
diff --git a/tests/lib_2/async/future_or_type_test.dart b/tests/lib_2/async/future_or_type_test.dart
new file mode 100644
index 0000000..df5a014
--- /dev/null
+++ b/tests/lib_2/async/future_or_type_test.dart
@@ -0,0 +1,254 @@
+// 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.
+
+// In strong mode, `FutureOr` should be a valid type in most locations.
+
+import 'dart:async';
+import 'package:expect/expect.dart';
+
+typedef void FunTakes<T>(T x);
+typedef T FunReturns<T>();
+
+main() {
+ // Some useful values.
+ dynamic n = null;
+ dynamic i = 0;
+ dynamic d = 1.5;
+ dynamic fni = new Future<num>.value(i);
+ dynamic fnd = new Future<num>.value(d);
+ dynamic fi = new Future<int>.value(i);
+ dynamic fd = new Future<double>.value(d);
+ dynamic fn = new Future<Null>.value(null);
+
+ dynamic o = new Object();
+ dynamic fo = new Future<Object>.value(o);
+ dynamic foi = new Future<Object>.value(i);
+
+ if (typeAssertionsEnabled) {
+ // Type annotation allows correct values.
+ FutureOr<num> v;
+ v = n;
+ v = i;
+ v = d;
+ v = fni;
+ v = fnd;
+ v = fi;
+ v = fd;
+ v = fn;
+ // Disallows invalid values.
+ // These are all valid down-casts that fail at runtime.
+ Expect.throws(() => v = o);
+ Expect.throws(() => v = fo);
+ Expect.throws(() => v = foi);
+
+ void fun(FutureOr<num> v) {}
+ fun(n);
+ fun(i);
+ fun(d);
+ fun(fni);
+ fun(fnd);
+ fun(fi);
+ fun(fd);
+ fun(fn);
+ // Disallows invalid values.
+ // These are all valid down-casts that fail at runtime.
+ Expect.throws(() => fun(o));
+ Expect.throws(() => fun(fo));
+ Expect.throws(() => fun(foi));
+
+ FutureOr<num> fun2(Object o) => o; // implicit down-cast to return type.
+ fun2(n);
+ fun2(i);
+ fun2(d);
+ fun2(fni);
+ fun2(fnd);
+ fun2(fi);
+ fun2(fd);
+ fun2(fn);
+ // Disallows invalid values.
+ Expect.throws(() => fun2(o));
+ Expect.throws(() => fun2(fo));
+ Expect.throws(() => fun2(foi));
+
+ List<Object> list = new List<FutureOr<num>>();
+ list.add(n);
+ list.add(i);
+ list.add(d);
+ list.add(fni);
+ list.add(fnd);
+ list.add(fi);
+ list.add(fd);
+ list.add(fn);
+ Expect.throws(() => list.add(o));
+ Expect.throws(() => list.add(fo));
+ Expect.throws(() => list.add(foi));
+ }
+
+ {
+ // Casts.
+ FutureOr<num> v;
+ v = n as FutureOr<num>;
+ v = i as FutureOr<num>;
+ v = d as FutureOr<num>;
+ v = fni as FutureOr<num>;
+ v = fnd as FutureOr<num>;
+ v = fi as FutureOr<num>;
+ v = fd as FutureOr<num>;
+ v = fn as FutureOr<num>;
+ // Disallows invalid values.
+ // These are all valid down-casts that fail at runtime.
+ Expect.throws(() => v = o as FutureOr<num>);
+ Expect.throws(() => v = fo as FutureOr<num>);
+ Expect.throws(() => v = foi as FutureOr<num>);
+ }
+
+ {
+ // on-catch
+ String check(Object o) {
+ try {
+ throw o;
+ } on FutureOr<num> {
+ return "caught";
+ } on Object {
+ return "uncaught";
+ }
+ }
+
+ // Can't throw null, so no `n` case here.
+ Expect.equals("caught", check(i));
+ Expect.equals("caught", check(d));
+ Expect.equals("caught", check(fni));
+ Expect.equals("caught", check(fnd));
+ Expect.equals("caught", check(fi));
+ Expect.equals("caught", check(fd));
+ Expect.equals("caught", check(fn));
+
+ Expect.equals("uncaught", check(o));
+ Expect.equals("uncaught", check(fo));
+ Expect.equals("uncaught", check(foi));
+ }
+
+ {
+ // Type variable bound.
+ var valids = <C<FutureOr<num>>>[
+ new C<Null>(),
+ new C<int>(),
+ new C<double>(),
+ new C<num>(),
+ new C<Future<Null>>(),
+ new C<Future<int>>(),
+ new C<Future<double>>(),
+ new C<Future<num>>(),
+ new C<FutureOr<Null>>(),
+ new C<FutureOr<int>>(),
+ new C<FutureOr<double>>(),
+ new C<FutureOr<num>>(),
+ ];
+ Expect.equals(12, valids.length);
+ }
+
+ {
+ // Dynamic checks.
+ Expect.isFalse(new C<FutureOr<num>>().isCheck(n));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(i));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(d));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(fni));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(fnd));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(fi));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(fd));
+ Expect.isTrue(new C<FutureOr<num>>().isCheck(fn));
+ Expect.isFalse(new C<FutureOr<num>>().isCheck(o));
+ Expect.isFalse(new C<FutureOr<num>>().isCheck(fo));
+ Expect.isFalse(new C<FutureOr<num>>().isCheck(foi));
+
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(n));
+ Expect.isTrue(new C<FutureOr<int>>().isCheck(i));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(d));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(fni));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(fnd));
+ Expect.isTrue(new C<FutureOr<int>>().isCheck(fi));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(fd));
+ Expect.isTrue(new C<FutureOr<int>>().isCheck(fn));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(o));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(fo));
+ Expect.isFalse(new C<FutureOr<int>>().isCheck(foi));
+
+ Expect.isTrue(new C<FutureOr<Null>>().isCheck(n));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(i));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(d));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(fni));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(fnd));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(fi));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(fd));
+ Expect.isTrue(new C<FutureOr<Null>>().isCheck(fn));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(o));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(fo));
+ Expect.isFalse(new C<FutureOr<Null>>().isCheck(foi));
+
+ Expect.isFalse(new C<Future<num>>().isCheck(n));
+ Expect.isFalse(new C<Future<num>>().isCheck(i));
+ Expect.isFalse(new C<Future<num>>().isCheck(d));
+ Expect.isTrue(new C<Future<num>>().isCheck(fni));
+ Expect.isTrue(new C<Future<num>>().isCheck(fnd));
+ Expect.isTrue(new C<Future<num>>().isCheck(fi));
+ Expect.isTrue(new C<Future<num>>().isCheck(fd));
+ Expect.isTrue(new C<Future<num>>().isCheck(fn));
+ Expect.isFalse(new C<Future<num>>().isCheck(o));
+ Expect.isFalse(new C<Future<num>>().isCheck(fo));
+ Expect.isFalse(new C<Future<num>>().isCheck(foi));
+
+ Expect.isFalse(new C<Future<int>>().isCheck(n));
+ Expect.isFalse(new C<Future<int>>().isCheck(i));
+ Expect.isFalse(new C<Future<int>>().isCheck(d));
+ Expect.isFalse(new C<Future<int>>().isCheck(fni));
+ Expect.isFalse(new C<Future<int>>().isCheck(fnd));
+ Expect.isTrue(new C<Future<int>>().isCheck(fi));
+ Expect.isFalse(new C<Future<int>>().isCheck(fd));
+ Expect.isTrue(new C<Future<int>>().isCheck(fn));
+ Expect.isFalse(new C<Future<int>>().isCheck(o));
+ Expect.isFalse(new C<Future<int>>().isCheck(fo));
+ Expect.isFalse(new C<Future<int>>().isCheck(foi));
+
+ Expect.isFalse(new C<num>().isCheck(n));
+ Expect.isTrue(new C<num>().isCheck(i));
+ Expect.isTrue(new C<num>().isCheck(d));
+ Expect.isFalse(new C<num>().isCheck(fni));
+ Expect.isFalse(new C<num>().isCheck(fnd));
+ Expect.isFalse(new C<num>().isCheck(fi));
+ Expect.isFalse(new C<num>().isCheck(fd));
+ Expect.isFalse(new C<num>().isCheck(fn));
+ Expect.isFalse(new C<num>().isCheck(o));
+ Expect.isFalse(new C<num>().isCheck(fo));
+ Expect.isFalse(new C<num>().isCheck(foi));
+
+ Expect.isFalse(new C<int>().isCheck(n));
+ Expect.isTrue(new C<int>().isCheck(i));
+ Expect.isFalse(new C<int>().isCheck(d));
+ Expect.isFalse(new C<int>().isCheck(fni));
+ Expect.isFalse(new C<int>().isCheck(fnd));
+ Expect.isFalse(new C<int>().isCheck(fi));
+ Expect.isFalse(new C<int>().isCheck(fd));
+ Expect.isFalse(new C<int>().isCheck(fn));
+ Expect.isFalse(new C<int>().isCheck(o));
+ Expect.isFalse(new C<int>().isCheck(fo));
+ Expect.isFalse(new C<int>().isCheck(foi));
+
+ Expect.isTrue(new C<Null>().isCheck(n));
+ Expect.isFalse(new C<Null>().isCheck(i));
+ Expect.isFalse(new C<Null>().isCheck(d));
+ Expect.isFalse(new C<Null>().isCheck(fni));
+ Expect.isFalse(new C<Null>().isCheck(fnd));
+ Expect.isFalse(new C<Null>().isCheck(fi));
+ Expect.isFalse(new C<Null>().isCheck(fd));
+ Expect.isFalse(new C<Null>().isCheck(fn));
+ Expect.isFalse(new C<Null>().isCheck(o));
+ Expect.isFalse(new C<Null>().isCheck(fo));
+ Expect.isFalse(new C<Null>().isCheck(foi));
+ }
+}
+
+// FutureOr used as type parameter bound.
+class C<T extends FutureOr<num>> {
+ bool isCheck(Object o) => o is T;
+}
diff --git a/tests/lib_2/html/audiobuffersourcenode_test.dart b/tests/lib_2/html/audiobuffersourcenode_test.dart
index ddfb55c..9c98cf0 100644
--- a/tests/lib_2/html/audiobuffersourcenode_test.dart
+++ b/tests/lib_2/html/audiobuffersourcenode_test.dart
@@ -15,7 +15,7 @@
var ctx = new AudioContext();
AudioBufferSourceNode node = ctx.createBufferSource();
expect(node is AudioBufferSourceNode, isTrue);
- node.start2(ctx.currentTime, 0, 2);
+ node.start(ctx.currentTime, 0, 2);
expect(node is AudioBufferSourceNode, isTrue);
}
});
diff --git a/tests/lib_2/html/websql_test.dart b/tests/lib_2/html/websql_test.dart
index 728b0fd..1d52d5d 100644
--- a/tests/lib_2/html/websql_test.dart
+++ b/tests/lib_2/html/websql_test.dart
@@ -57,12 +57,6 @@
await setup();
group('Database', () {
- test('supported', () {
- expect(SqlDatabase.supported, true);
- });
- });
-
- group('Database', () {
test('Open/Transaction', () async {
if (!SqlDatabase.supported) return;
diff --git a/tests/lib_2/lib_2.status b/tests/lib_2/lib_2.status
index 322ea0f..a5c29d5 100644
--- a/tests/lib_2/lib_2.status
+++ b/tests/lib_2/lib_2.status
@@ -124,6 +124,9 @@
async/stream_last_where_test/badType: MissingCompileTimeError
mirrors/redirecting_factory_different_type_test/02: MissingCompileTimeError
+[ !$strong && $compiler != fasta && $compiler != dart2analyzer ]
+async/future_or_type_test: Fail # Strong mode implements FutureOr, non-strong treats it as dynamic.
+
[ $builder_tag == mac10_7 && $runtime == safari ]
typed_data/setRange_2_test: Fail # Safari doesn't fully implement spec for TypedArray.set
typed_data/setRange_3_test: Fail # Safari doesn't fully implement spec for TypedArray.set
diff --git a/tests/lib_2/lib_2_dart2js.status b/tests/lib_2/lib_2_dart2js.status
index 85c39cc..a7913ac 100644
--- a/tests/lib_2/lib_2_dart2js.status
+++ b/tests/lib_2/lib_2_dart2js.status
@@ -407,7 +407,6 @@
html/speechrecognition_test: RuntimeError # Please triage.
html/text_event_test: Fail # Issue 17893
html/webgl_1_test: Pass, Fail # Issue 8219
-html/websql_test: Fail
isolate/kill_self_synchronously_test: RuntimeError
[ $compiler == dart2js && $runtime == ie11 ]
diff --git a/tools/VERSION b/tools/VERSION
index bdaeec8..2e2e188 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 0
PATCH 0
-PRERELEASE 40
+PRERELEASE 41
PRERELEASE_PATCH 0
diff --git a/tools/apps/update_homebrew/lib/update_homebrew.dart b/tools/apps/update_homebrew/lib/update_homebrew.dart
index 350c779..5628c41 100644
--- a/tools/apps/update_homebrew/lib/update_homebrew.dart
+++ b/tools/apps/update_homebrew/lib/update_homebrew.dart
@@ -157,12 +157,18 @@
bin.write_exec_script Dir["#{libexec}/bin/{pub,dart?*}"]
if build.with? "dartium"
+ if build.devel?
+ odie "dartium is no longer supported with --devel builds. Remove --with-dartium and try again."
+ end
dartium_binary = "Chromium.app/Contents/MacOS/Chromium"
prefix.install resource("dartium")
(bin+"dartium").write shim_script dartium_binary
end
if build.with? "content-shell"
+ if build.devel?
+ odie "content-shell is no longer supported with --devel builds. Remove --with-content-shell and try again."
+ end
content_shell_binary = "Content Shell.app/Contents/MacOS/Content Shell"
prefix.install resource("content_shell")
(bin+"content_shell").write shim_script content_shell_binary
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 21094fc..9b22618 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -11,12 +11,21 @@
".packages"
],
"dart2js": [
- "out/ReleaseX64/",
- "xcodebuild/ReleaseX64/",
- "tools/",
- "tests/",
+ ".packages",
+ "out/ReleaseIA32/dart-sdk/",
+ "out/ReleaseX64/dart-sdk/",
"pkg/",
- ".packages"
+ "runtime/tests/",
+ "samples-dev/",
+ "samples/",
+ "tests/",
+ "third_party/d8/",
+ "third_party/observatory_pub_packages/packages/web_components/",
+ "third_party/pkg/",
+ "third_party/pkg_tested/",
+ "tools/",
+ "xcodebuild/ReleaseIA32/dart-sdk/",
+ "xcodebuild/ReleaseX64/dart-sdk/"
],
"vm_debug": [
"out/DebugIA32/",
@@ -615,13 +624,17 @@
},
{
"name": "vm tests",
- "arguments": ["--vm-options=--optimization-counter-threshold=5"]
+ "arguments": [
+ "--vm-options=--optimization-counter-threshold=5",
+ "--builder-tag=optimization_counter_threshold"
+ ]
},
{
"name": "checked vm tests",
"arguments": [
"--checked",
- "--vm-options=--optimization-counter-threshold=5"
+ "--vm-options=--optimization-counter-threshold=5",
+ "--builder-tag=optimization_counter_threshold"
]
}
]
@@ -880,32 +893,6 @@
"fileset": "dart2js"
},
{
- "name": "dart2js fast-startup tests",
- "arguments": [
- "--use-sdk",
- "--compiler=dart2js",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "--fast-startup"
- ],
- "exclude_tests": ["observatory_ui", "co19"],
- "shards": 4,
- "fileset": "dart2js"
- },
- {
- "name": "dart2js fast-startup co19 tests",
- "arguments": [
- "--use-sdk",
- "--compiler=dart2js",
- "--dart2js-batch",
- "--reset-browser-configuration",
- "--fast-startup"
- ],
- "tests": ["co19"],
- "shards": 4,
- "fileset": "dart2js"
- },
- {
"name": "dart2js package tests",
"arguments": [
"--use-sdk",
@@ -934,9 +921,51 @@
"--reset-browser-configuration"
],
"tests": ["dart2js_extra","dart2js_native"]
+ }
+ ]
+ },
+ {
+ "builders": [
+ "dart2js-faststartup-linux-x64-chrome"
+ ],
+ "meta": {
+ "description":
+ "These builders run dart2js tests with the --fast-startup option."
+ },
+ "steps": [
+ {
+ "name": "build dart",
+ "script": "tools/build.py",
+ "arguments": ["create_sdk"]
},
{
- "name": "dart2js fast-startup pkg tests",
+ "name": "dart2js fast-startup tests",
+ "arguments": [
+ "--use-sdk",
+ "--compiler=dart2js",
+ "--dart2js-batch",
+ "--reset-browser-configuration",
+ "--fast-startup"
+ ],
+ "exclude_tests": ["observatory_ui", "co19"],
+ "shards": 4,
+ "fileset": "dart2js"
+ },
+ {
+ "name": "dart2js fast-startup co19 tests",
+ "arguments": [
+ "--use-sdk",
+ "--compiler=dart2js",
+ "--dart2js-batch",
+ "--reset-browser-configuration",
+ "--fast-startup"
+ ],
+ "tests": ["co19"],
+ "shards": 4,
+ "fileset": "dart2js"
+ },
+ {
+ "name": "dart2js fast-startup package tests",
"arguments": [
"--use-sdk",
"--compiler=dart2js",
diff --git a/tools/copy_tree.py b/tools/copy_tree.py
index a9925b4..5d72750 100755
--- a/tools/copy_tree.py
+++ b/tools/copy_tree.py
@@ -82,7 +82,7 @@
errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive CopyTree so that we can
# continue with other files
- except Error as err:
+ except Exception as err:
errors.extend(err.args[0])
try:
shutil.copystat(src, dst)
diff --git a/tools/dart2js/sourceMapViewer/web/display.dart b/tools/dart2js/sourceMapViewer/web/display.dart
index fa21a25..824f6aa 100644
--- a/tools/dart2js/sourceMapViewer/web/display.dart
+++ b/tools/dart2js/sourceMapViewer/web/display.dart
@@ -51,8 +51,6 @@
displaySource(String filename, List<String> source, TargetEntry entry) {
int line = entry.sourceLine;
int column = entry.sourceColumn;
- int nameId = entry.sourceNameId;
- String id = nameId == null ? null : sourceMap.names[nameId];
selectedSource.children.clear();
SpanElement marker = new SpanElement()
..className = "marker"
@@ -308,7 +306,7 @@
getMap().then((mapFileName) {
load(mapFileName).then((mapFileContent) {
- sourceMap = new SingleMapping.fromJson(JSON.decode(mapFileContent));
+ sourceMap = new SingleMapping.fromJson(jsonDecode(mapFileContent));
displayMap(mapFileContent);
targetFileName.text = sourceMap.targetUrl;
load(targetFileName.text).then((targetFileContent) {
diff --git a/tools/dart2js/sourceMapViewer/web/display.html b/tools/dart2js/sourceMapViewer/web/display.html
index 834cf64..54bfefc 100644
--- a/tools/dart2js/sourceMapViewer/web/display.html
+++ b/tools/dart2js/sourceMapViewer/web/display.html
@@ -57,7 +57,6 @@
</td>
</tr>
</table></div>
- <script type="application/dart" src="display.dart"></script>
- <script src="packages/browser/dart.js"></script>
+ <script defer src="display.dart.js"></script>
</body>
</html>
\ No newline at end of file
diff --git a/tools/dom/idl/dart/dart.idl b/tools/dom/idl/dart/dart.idl
index 570ccc5..b9acad3 100644
--- a/tools/dom/idl/dart/dart.idl
+++ b/tools/dom/idl/dart/dart.idl
@@ -493,8 +493,8 @@
};
[DartSupplemental]
-interface AudioBufferSourceNode {
- [DartName=start2] void start(optional double when = 0, optional double grainOffset, optional double grainDuration);
+interface AudioScheduledSourceNode {
+ [DartName=start2] void start(optional double when);
};
// Remove operations webkitRequestFullscreen replaced w/ requestFullscreen.
diff --git a/tools/patch_sdk.dart b/tools/patch_sdk.dart
index 9dac1deb..f8dd6fc 100644
--- a/tools/patch_sdk.dart
+++ b/tools/patch_sdk.dart
@@ -29,7 +29,6 @@
import 'package:kernel/target/targets.dart';
import 'package:kernel/target/vm.dart' show VmTarget;
import 'package:kernel/target/flutter.dart' show FlutterTarget;
-import 'package:vm/target/runner.dart' show RunnerTarget;
import 'package:compiler/src/kernel/dart2js_target.dart' show Dart2jsTarget;
/// Set of input files that were read by this script to generate patched SDK.
@@ -134,17 +133,13 @@
target = new VmTarget(flags);
break;
- case 'runner':
- target = new RunnerTarget(flags);
- break;
-
case 'flutter':
case 'flutter_release':
target = new FlutterTarget(flags);
break;
case 'dart2js':
- target = new Dart2jsTarget(flags);
+ target = new Dart2jsTarget("dart2js", flags);
break;
default:
diff --git a/utils/compiler/BUILD.gn b/utils/compiler/BUILD.gn
index bcea398..a279e9e 100644
--- a/utils/compiler/BUILD.gn
+++ b/utils/compiler/BUILD.gn
@@ -110,3 +110,36 @@
"dart:core",
]
}
+
+compile_platform("compile_dart2js_server_platform") {
+ sources = [
+ "../../sdk/lib/libraries.json",
+ ]
+
+ outputs = [
+ "$root_out_dir/dart2js_server_platform.dill",
+ "$root_out_dir/dart2js_server_outline.dill",
+ ]
+
+ args = [
+ "--target=dart2js_server",
+ "dart:core",
+ ]
+}
+
+compile_platform("compile_dart2js_server_platform_strong") {
+ sources = [
+ "../../sdk/lib/libraries.json",
+ ]
+
+ outputs = [
+ "$root_out_dir/dart2js_server_platform_strong.dill",
+ "$root_out_dir/dart2js_server_outline_strong.dill",
+ ]
+
+ args = [
+ "--target=dart2js_server",
+ "--strong",
+ "dart:core",
+ ]
+}