Version 1.21.0-dev.8.0
Merge dbf8d06eab8140bcc49b2b8eed3b149fb215c3dc into dev
diff --git a/.travis.yml b/.travis.yml
index 2f868f8..f458e35 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -81,8 +81,8 @@
- TEST=package
matrix:
allow_failures:
- - env: TEST=node
- env: ANALYZER=master CXX=g++
+ - env: ANALYZER=master DDC_BROWSERS=ChromeCanaryTravis
notifications:
email:
recipients:
diff --git a/DEPS b/DEPS
index bfad3e5..9aef0a8 100644
--- a/DEPS
+++ b/DEPS
@@ -64,7 +64,7 @@
"glob_tag": "@1.1.3",
"html_tag" : "@0.13.1",
"http_multi_server_tag" : "@2.0.2",
- "http_parser_tag" : "@3.0.2",
+ "http_parser_tag" : "@3.0.3",
"http_tag" : "@0.11.3+9",
"http_throttle_rev" : "@284344cd357e435c6c8ff9a4a21f02b9e384a541",
"idl_parser_rev": "@7fbe68cab90c38147dee4f48c30ad0d496c17915",
diff --git a/pkg/analysis_server/.gitignore b/pkg/analysis_server/.gitignore
new file mode 100644
index 0000000..16a1724
--- /dev/null
+++ b/pkg/analysis_server/.gitignore
@@ -0,0 +1 @@
+.packages
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 9855905..0f5bcc7 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -95,9 +95,6 @@
/* Styles for index */
-.subindex {
-}
-
.subindex ul {
padding-left: 0;
margin-left: 0;
@@ -233,11 +230,12 @@
<ul>
<li><a href="#domain_server">Server</a></li>
<li><a href="#domain_analysis">Analysis</a></li>
- <li><a href="#domain_completion">Code Completion</a></li>
+ <li><a href="#domain_completion">Completion</a></li>
<li><a href="#domain_search">Search</a></li>
<li><a href="#domain_edit">Edit</a></li>
<li><a href="#domain_execution">Execution</a></li>
- </ul>
+ <li><a href="#domain_diagnostic">Diagnostic</a></li>
+</ul>
<p>
The specifications of the API’s refer to data structures beyond
the standard JSON primitives. These data structures are
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 083874b..47293f7 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/plugin/options.dart';
import 'package:analyzer/plugin/resolver_provider.dart';
import 'package:analyzer/source/analysis_options_provider.dart';
-import 'package:analyzer/source/config.dart';
import 'package:analyzer/source/package_map_provider.dart';
import 'package:analyzer/source/package_map_resolver.dart';
import 'package:analyzer/source/path_filter.dart';
@@ -477,10 +476,6 @@
*/
final PubPackageMapProvider _packageMapProvider;
- /// Provider of analysis options.
- AnalysisOptionsProvider analysisOptionsProvider =
- new AnalysisOptionsProvider();
-
/**
* A list of the globs used to determine which files should be analyzed.
*/
@@ -685,9 +680,19 @@
* if exists, or in one of the parent folders, or `null` if no analysis
* options file is found or if the contents of the file are not valid YAML.
*/
- Map<String, Object> readOptions(Folder folder) {
+ Map<String, Object> readOptions(Folder folder, Packages packages) {
try {
- return analysisOptionsProvider.getOptions(folder, crawlUp: true);
+ Map<String, List<Folder>> packageMap =
+ new ContextBuilder(resourceProvider, null, null)
+ .convertPackagesToMap(packages);
+ List<UriResolver> resolvers = <UriResolver>[
+ new ResourceUriResolver(resourceProvider),
+ new PackageMapUriResolver(resourceProvider, packageMap),
+ ];
+ SourceFactory sourceFactory =
+ new SourceFactory(resolvers, packages, resourceProvider);
+ return new AnalysisOptionsProvider(sourceFactory)
+ .getOptions(folder, crawlUp: true);
} catch (_) {
// Parse errors are reported by GenerateOptionsErrorsTask.
}
@@ -916,7 +921,8 @@
if (AnalysisEngine.isAnalysisOptionsFileName(path, pathContext)) {
var analysisContext = info.context;
if (analysisContext is context.AnalysisContextImpl) {
- Map<String, Object> options = readOptions(info.folder);
+ Map<String, Object> options =
+ readOptions(info.folder, info.disposition.packages);
processOptionsForContext(info, options,
optionsRemoved: changeType == ChangeType.REMOVE);
analysisContext.sourceFactory = _createSourceFactory(
@@ -1069,7 +1075,8 @@
ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
normalizedPackageRoots[folder.path], disposition);
- Map<String, Object> optionMap = readOptions(info.folder);
+ Map<String, Object> optionMap =
+ readOptions(info.folder, disposition.packages);
AnalysisOptions options =
new AnalysisOptionsImpl.from(defaultContextOptions);
applyToAnalysisOptions(options, optionMap);
@@ -1096,17 +1103,6 @@
pubspec = child;
}
}
- if (pubspec != null) {
- File pubSource = resourceProvider.getFile(pubspec.path);
- if (enableNewAnalysisDriver) {
- // TODO(scheglov) implement for the new analysis driver
- } else {
- setConfiguration(
- info.context,
- new AnalysisConfiguration.fromPubspec(
- pubSource, resourceProvider, disposition.packages));
- }
- }
if (enableNewAnalysisDriver) {
// TODO(scheglov) implement for the new analysis driver
@@ -1264,18 +1260,6 @@
if (maps.length == 1) {
embeddedOptions = maps.first;
}
-
- AnalysisConfiguration configuration = getConfiguration(info.context);
- if (configuration != null) {
- Map configMap = configuration.options;
- if (configMap != null) {
- if (embeddedOptions != null) {
- embeddedOptions = new Merger().merge(embeddedOptions, configMap);
- } else {
- embeddedOptions = configMap;
- }
- }
- }
return embeddedOptions;
}
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 9621afb..eda11af 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -133,6 +133,10 @@
* Implement the `analysis.getNavigation` request.
*/
Response getNavigation(Request request) {
+ if (server.options.enableNewAnalysisDriver) {
+ // TODO(scheglov) implement for the new analysis driver
+ return new Response.getNavigationInvalidFile(request);
+ }
var params = new AnalysisGetNavigationParams.fromRequest(request);
String file = params.file;
Future<AnalysisDoneReason> analysisFuture =
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index cdd39a3..b77f2df 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -49,6 +49,15 @@
searchEngine = server.searchEngine;
Future findElementReferences(protocol.Request request) async {
+ if (server.options.enableNewAnalysisDriver) {
+ // TODO(scheglov) implement for the new analysis driver
+ String searchId = (_nextSearchId++).toString();
+ var result = new protocol.SearchFindElementReferencesResult();
+ result.id = searchId;
+ _sendSearchResult(request, result);
+ _sendSearchNotification(searchId, true, <protocol.SearchResult>[]);
+ return;
+ }
var params =
new protocol.SearchFindElementReferencesParams.fromRequest(request);
await server.onAnalysisComplete;
@@ -145,6 +154,14 @@
* Implement the `search.getTypeHierarchy` request.
*/
Future getTypeHierarchy(protocol.Request request) async {
+ if (server.options.enableNewAnalysisDriver) {
+ // TODO(scheglov) implement for the new analysis driver
+ protocol.Response response =
+ new protocol.SearchGetTypeHierarchyResult(hierarchyItems: [])
+ .toResponse(request.id);
+ server.sendResponse(response);
+ return;
+ }
var params = new protocol.SearchGetTypeHierarchyParams.fromRequest(request);
String file = params.file;
// wait for analysis
diff --git a/pkg/analysis_server/lib/src/server/driver.dart b/pkg/analysis_server/lib/src/server/driver.dart
index df6df7b..051ae23 100644
--- a/pkg/analysis_server/lib/src/server/driver.dart
+++ b/pkg/analysis_server/lib/src/server/driver.dart
@@ -389,7 +389,7 @@
analysisServerOptions.enableIncrementalResolutionValidation =
results[INCREMENTAL_RESOLUTION_VALIDATION];
analysisServerOptions.enableNewAnalysisDriver =
- results[ENABLE_NEW_ANALYSIS_DRIVER];
+ results[ENABLE_NEW_ANALYSIS_DRIVER];
analysisServerOptions.enablePubSummaryManager =
results[ENABLE_PUB_SUMMARY_MANAGER];
analysisServerOptions.finerGrainedInvalidation =
@@ -428,7 +428,8 @@
.defaultSdkDirectory(PhysicalResourceProvider.INSTANCE)
.path;
}
- bool useSummaries = analysisServerOptions.fileReadMode == 'as-is';
+ bool useSummaries = analysisServerOptions.fileReadMode == 'as-is' ||
+ analysisServerOptions.enableNewAnalysisDriver;
// TODO(brianwilkerson) It would be nice to avoid creating an SDK that
// cannot be re-used, but the SDK is needed to create a package map provider
// in the case where we need to run `pub` in order to get the package map.
diff --git a/pkg/analysis_server/test/context_manager_test.dart b/pkg/analysis_server/test/context_manager_test.dart
index ce0bf7d..1039788 100644
--- a/pkg/analysis_server/test/context_manager_test.dart
+++ b/pkg/analysis_server/test/context_manager_test.dart
@@ -25,7 +25,7 @@
import 'package:analyzer/src/util/glob.dart';
import 'package:linter/src/plugin/linter_plugin.dart';
import 'package:linter/src/rules/avoid_as.dart';
-import 'package:path/path.dart';
+import 'package:path/path.dart' as path;
import 'package:plugin/manager.dart';
import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
@@ -45,11 +45,11 @@
@reflectiveTest
class AbstractContextManagerTest extends ContextManagerTest {
void test_contextsInAnalysisRoot_nestedContext() {
- String subProjPath = posix.join(projPath, 'subproj');
+ String subProjPath = path.posix.join(projPath, 'subproj');
Folder subProjFolder = resourceProvider.newFolder(subProjPath);
resourceProvider.newFile(
- posix.join(subProjPath, 'pubspec.yaml'), 'contents');
- String subProjFilePath = posix.join(subProjPath, 'file.dart');
+ path.posix.join(subProjPath, 'pubspec.yaml'), 'contents');
+ String subProjFilePath = path.posix.join(subProjPath, 'file.dart');
resourceProvider.newFile(subProjFilePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// Make sure that there really are contexts for both the main project and
@@ -167,16 +167,16 @@
test_ignoreFilesInPackagesFolder() {
// create a context with a pubspec.yaml file
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec');
// create a file in the "packages" folder
- String filePath1 = posix.join(projPath, 'packages', 'file1.dart');
+ String filePath1 = path.posix.join(projPath, 'packages', 'file1.dart');
resourceProvider.newFile(filePath1, 'contents');
// "packages" files are ignored initially
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
expect(callbacks.currentContextFilePaths[projPath], isEmpty);
// "packages" files are ignored during watch
- String filePath2 = posix.join(projPath, 'packages', 'file2.dart');
+ String filePath2 = path.posix.join(projPath, 'packages', 'file2.dart');
resourceProvider.newFile(filePath2, 'contents');
return pumpEventQueue().then((_) {
expect(callbacks.currentContextFilePaths[projPath], isEmpty);
@@ -197,11 +197,11 @@
}
void test_isInAnalysisRoot_inNestedContext() {
- String subProjPath = posix.join(projPath, 'subproj');
+ String subProjPath = path.posix.join(projPath, 'subproj');
Folder subProjFolder = resourceProvider.newFolder(subProjPath);
resourceProvider.newFile(
- posix.join(subProjPath, 'pubspec.yaml'), 'contents');
- String subProjFilePath = posix.join(subProjPath, 'file.dart');
+ path.posix.join(subProjPath, 'pubspec.yaml'), 'contents');
+ String subProjFilePath = path.posix.join(subProjPath, 'file.dart');
resourceProvider.newFile(subProjFilePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// Make sure that there really is a context for the subproject.
@@ -253,7 +253,7 @@
test_refresh_folder_with_packagespec() {
// create a context with a .packages file
- String packagespecFile = posix.join(projPath, '.packages');
+ String packagespecFile = path.posix.join(projPath, '.packages');
resourceProvider.newFile(packagespecFile, '');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
return pumpEventQueue().then((_) {
@@ -273,10 +273,10 @@
test_refresh_folder_with_packagespec_subfolders() {
// Create a folder with no .packages file, containing two subfolders with
// .packages files.
- String subdir1Path = posix.join(projPath, 'subdir1');
- String subdir2Path = posix.join(projPath, 'subdir2');
- String packagespec1Path = posix.join(subdir1Path, '.packages');
- String packagespec2Path = posix.join(subdir2Path, '.packages');
+ String subdir1Path = path.posix.join(projPath, 'subdir1');
+ String subdir2Path = path.posix.join(projPath, 'subdir2');
+ String packagespec1Path = path.posix.join(subdir1Path, '.packages');
+ String packagespec2Path = path.posix.join(subdir2Path, '.packages');
resourceProvider.newFile(packagespec1Path, '');
resourceProvider.newFile(packagespec2Path, '');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -297,7 +297,7 @@
test_refresh_folder_with_pubspec() {
// create a context with a pubspec.yaml file
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
return pumpEventQueue().then((_) {
@@ -314,10 +314,10 @@
test_refresh_folder_with_pubspec_subfolders() {
// Create a folder with no pubspec.yaml, containing two subfolders with
// pubspec.yaml files.
- String subdir1Path = posix.join(projPath, 'subdir1');
- String subdir2Path = posix.join(projPath, 'subdir2');
- String pubspec1Path = posix.join(subdir1Path, 'pubspec.yaml');
- String pubspec2Path = posix.join(subdir2Path, 'pubspec.yaml');
+ String subdir1Path = path.posix.join(projPath, 'subdir1');
+ String subdir2Path = path.posix.join(projPath, 'subdir2');
+ String pubspec1Path = path.posix.join(subdir1Path, 'pubspec.yaml');
+ String pubspec2Path = path.posix.join(subdir2Path, 'pubspec.yaml');
resourceProvider.newFile(pubspec1Path, 'pubspec');
resourceProvider.newFile(pubspec2Path, 'pubspec');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -338,12 +338,12 @@
test_refresh_oneContext() {
// create two contexts with pubspec.yaml files
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec1');
String proj2Path = '/my/proj2';
resourceProvider.newFolder(proj2Path);
- String pubspec2Path = posix.join(proj2Path, 'pubspec.yaml');
+ String pubspec2Path = path.posix.join(proj2Path, 'pubspec.yaml');
resourceProvider.newFile(pubspec2Path, 'pubspec2');
List<String> roots = <String>[projPath, proj2Path];
@@ -396,7 +396,7 @@
}
void test_setRoots_addFolderWithDartFile() {
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -414,7 +414,7 @@
}
void test_setRoots_addFolderWithDartFileInSubfolder() {
- String filePath = posix.join(projPath, 'foo', 'bar.dart');
+ String filePath = path.posix.join(projPath, 'foo', 'bar.dart');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -424,7 +424,7 @@
}
void test_setRoots_addFolderWithDummyLink() {
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
resourceProvider.newDummyLink(filePath);
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -497,12 +497,12 @@
}
void test_setRoots_addFolderWithPackagespec() {
- String packagespecPath = posix.join(projPath, '.packages');
+ String packagespecPath = path.posix.join(projPath, '.packages');
resourceProvider.newFile(packagespecPath,
'unittest:file:///home/somebody/.pub/cache/unittest-0.9.9/lib/');
String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
File mainFile =
- resourceProvider.newFile(posix.join(libPath, 'main.dart'), '');
+ resourceProvider.newFile(path.posix.join(libPath, 'main.dart'), '');
Source source = mainFile.createSource();
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -523,7 +523,7 @@
void test_setRoots_addFolderWithPackagespecAndPackageRoot() {
// The package root should take priority.
- String packagespecPath = posix.join(projPath, '.packages');
+ String packagespecPath = path.posix.join(projPath, '.packages');
resourceProvider.newFile(packagespecPath,
'unittest:file:///home/somebody/.pub/cache/unittest-0.9.9/lib/');
String packageRootPath = '/package/root/';
@@ -535,7 +535,7 @@
}
void test_setRoots_addFolderWithPubspec() {
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -545,8 +545,8 @@
}
void test_setRoots_addFolderWithPubspec_andPackagespec() {
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
- String packagespecPath = posix.join(projPath, '.packages');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
+ String packagespecPath = path.posix.join(projPath, '.packages');
resourceProvider.newFile(pubspecPath, 'pubspec');
resourceProvider.newFile(packagespecPath, '');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -931,7 +931,7 @@
}
void test_setRoots_noContext_inDotFolder() {
- String pubspecPath = posix.join(projPath, '.pub', 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, '.pub', 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'name: test');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -941,7 +941,7 @@
}
void test_setRoots_noContext_inPackagesFolder() {
- String pubspecPath = posix.join(projPath, 'packages', 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'packages', 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'name: test');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
// verify
@@ -951,7 +951,7 @@
}
void test_setRoots_packageResolver() {
- String filePath = posix.join(projPath, 'lib', 'foo.dart');
+ String filePath = path.posix.join(projPath, 'lib', 'foo.dart');
newFile([projPath, ContextManagerImpl.PACKAGE_SPEC_NAME], 'foo:lib/');
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -991,7 +991,7 @@
void test_setRoots_removeFolderWithPackagespec() {
// create a pubspec
- String pubspecPath = posix.join(projPath, '.packages');
+ String pubspecPath = path.posix.join(projPath, '.packages');
resourceProvider.newFile(pubspecPath, '');
// add one root - there is a context
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -1041,7 +1041,7 @@
void test_setRoots_removeFolderWithPubspec() {
// create a pubspec
- String pubspecPath = posix.join(projPath, 'pubspec.yaml');
+ String pubspecPath = path.posix.join(projPath, 'pubspec.yaml');
resourceProvider.newFile(pubspecPath, 'pubspec');
// add one root - there is a context
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -1124,7 +1124,7 @@
Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
expect(filePaths, isEmpty);
// add link
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
resourceProvider.newDummyLink(filePath);
// the link was ignored
return pumpEventQueue().then((_) {
@@ -1138,7 +1138,7 @@
Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
expect(filePaths, hasLength(0));
// add file
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
resourceProvider.newFile(filePath, 'contents');
// the file was added
return pumpEventQueue().then((_) {
@@ -1244,7 +1244,7 @@
Map<String, int> filePaths = callbacks.currentContextFilePaths[projPath];
expect(filePaths, hasLength(0));
// add file in subfolder
- String filePath = posix.join(projPath, 'foo', 'bar.dart');
+ String filePath = path.posix.join(projPath, 'foo', 'bar.dart');
resourceProvider.newFile(filePath, 'contents');
// the file was added
return pumpEventQueue().then((_) {
@@ -1425,7 +1425,7 @@
}
test_watch_deleteFile() {
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
// add root with a file
File file = resourceProvider.newFile(filePath, 'contents');
Folder projFolder = file.parent;
@@ -1446,7 +1446,7 @@
}
test_watch_deleteFolder() {
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
// add root with a file
File file = resourceProvider.newFile(filePath, 'contents');
Folder projFolder = file.parent;
@@ -1595,7 +1595,7 @@
}
test_watch_modifyFile() {
- String filePath = posix.join(projPath, 'foo.dart');
+ String filePath = path.posix.join(projPath, 'foo.dart');
// add root with a file
resourceProvider.newFile(filePath, 'contents');
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -1614,11 +1614,11 @@
test_watch_modifyPackageMapDependency_fail() async {
// create a dependency file
- String dependencyPath = posix.join(projPath, 'dep');
+ String dependencyPath = path.posix.join(projPath, 'dep');
resourceProvider.newFile(dependencyPath, 'contents');
packageMapProvider.dependencies.add(dependencyPath);
// create a Dart file
- String dartFilePath = posix.join(projPath, 'main.dart');
+ String dartFilePath = path.posix.join(projPath, 'main.dart');
resourceProvider.newFile(dartFilePath, 'contents');
// the created context has the expected empty package map
manager.setRoots(<String>[projPath], <String>[], <String, String>{});
@@ -1743,7 +1743,7 @@
'**/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}'
];
return patterns
- .map((pattern) => new Glob(posix.separator, pattern))
+ .map((pattern) => new Glob(path.posix.separator, pattern))
.toList();
}
@@ -1757,7 +1757,7 @@
Map<String, List<Folder>> get _currentPackageMap => _packageMap(projPath);
void deleteFile(List<String> pathComponents) {
- String filePath = posix.joinAll(pathComponents);
+ String filePath = path.posix.joinAll(pathComponents);
resourceProvider.deleteFile(filePath);
}
@@ -1765,13 +1765,13 @@
ErrorProcessor.getProcessor(callbacks.currentContext, error);
String newFile(List<String> pathComponents, [String content = '']) {
- String filePath = posix.joinAll(pathComponents);
+ String filePath = path.posix.joinAll(pathComponents);
resourceProvider.newFile(filePath, content);
return filePath;
}
String newFolder(List<String> pathComponents) {
- String folderPath = posix.joinAll(pathComponents);
+ String folderPath = path.posix.joinAll(pathComponents);
resourceProvider.newFolder(folderPath);
return folderPath;
}
@@ -1935,6 +1935,43 @@
expect(getProcessor(missing_return).severity, isNull);
}
+ test_analysis_options_include() async {
+ // Create files.
+ String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
+ newFile([libPath, 'main.dart']);
+ String sdkExtPath = newFolder([projPath, 'sdk_ext']);
+ newFile([sdkExtPath, 'entry.dart']);
+ String sdkExtSrcPath = newFolder([projPath, 'sdk_ext', 'src']);
+ newFile([sdkExtSrcPath, 'part.dart']);
+ // Setup analysis options file which includes another options file.
+ newFile(
+ [projPath, optionsFileName],
+ r'''
+include: other_options.yaml
+''');
+ newFile(
+ [projPath, 'other_options.yaml'],
+ r'''
+analyzer:
+ language:
+ enableGenericMethods: true
+ errors:
+ unused_local_variable: false
+linter:
+ rules:
+ - camel_case_types
+''');
+ // Setup context.
+ manager.setRoots(<String>[projPath], <String>[], <String, String>{});
+ await pumpEventQueue();
+
+ // Verify options were set.
+ expect(options.enableGenericMethods, isTrue);
+ expect(errorProcessors, hasLength(1));
+ expect(lints, hasLength(1));
+ expect(lints[0].name, 'camel_case_types');
+ }
+
test_analysis_options_parse_failure() async {
// Create files.
String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
@@ -1955,217 +1992,6 @@
// No error means success.
}
- test_configed_options() async {
- // Create files.
- String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
- newFile([projPath, 'test', 'test.dart']);
- newFile(
- [projPath, 'pubspec.yaml'],
- r'''
-dependencies:
- test_pack: any
-analyzer:
- configuration: test_pack/config
-''');
-
- // Setup .packages file
- newFile(
- [projPath, '.packages'],
- r'''
-test_pack:lib/''');
-
- // Setup config.yaml.
- newFile(
- [libPath, 'config', 'config.yaml'],
- r'''
-analyzer:
- strong-mode: true
- language:
- enableSuperMixins: true
- errors:
- missing_return: false
-linter:
- rules:
- - avoid_as
-''');
-
- // Setup analysis options
- newFile(
- [projPath, optionsFileName],
- r'''
-analyzer:
- exclude:
- - 'test/**'
- language:
- enableGenericMethods: true
- errors:
- unused_local_variable: false
-linter:
- rules:
- - camel_case_types
-''');
-
- // Setup context.
- manager.setRoots(<String>[projPath], <String>[], <String, String>{});
- await pumpEventQueue();
-
- // Confirm that one context was created.
- var contexts =
- manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
- expect(contexts, isNotNull);
- expect(contexts, hasLength(1));
-
- var context = contexts.first;
-
- // Verify options.
- // * from `config.yaml`:
- expect(context.analysisOptions.strongMode, isTrue);
- expect(context.analysisOptions.enableSuperMixins, isTrue);
- // * from analysis options:
- expect(context.analysisOptions.enableGenericMethods, isTrue);
-
- // * verify tests are excluded
- expect(callbacks.currentContextFilePaths[projPath].keys,
- unorderedEquals(['/my/proj/$optionsFileName']));
-
- // Verify filter setup.
- expect(errorProcessors, hasLength(2));
-
- // * (config.)
- expect(getProcessor(missing_return).severity, isNull);
-
- // * (options.)
- expect(getProcessor(unused_local_variable).severity, isNull);
-
- // Verify lints.
- var lintNames = lints.map((lint) => lint.name);
- expect(
- lintNames,
- unorderedEquals(
- ['avoid_as' /* config */, 'camel_case_types' /* options */]));
- }
-
- test_embedder_and_configed_options() async {
- // Create files.
- String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
- String sdkExtPath = newFolder([projPath, 'sdk_ext']);
- newFile([projPath, 'test', 'test.dart']);
- newFile([sdkExtPath, 'entry.dart']);
-
- // Setup pubspec with configuration.
- newFile(
- [projPath, 'pubspec.yaml'],
- r'''
-dependencies:
- test_pack: any
-analyzer:
- configuration: test_pack/config
-''');
-
- // Setup _embedder.yaml.
- newFile(
- [libPath, '_embedder.yaml'],
- r'''
-embedded_libs:
- "dart:foobar": "../sdk_ext/entry.dart"
-analyzer:
- strong-mode: true
- language:
- enableSuperMixins: true
- errors:
- missing_return: false
-linter:
- rules:
- - avoid_as
-''');
-
- // Setup .packages file
- newFile(
- [projPath, '.packages'],
- r'''
-test_pack:lib/''');
-
- // Setup analysis options
- newFile(
- [projPath, optionsFileName],
- r'''
-analyzer:
- exclude:
- - 'test/**'
- language:
- enableGenericMethods: true
- errors:
- unused_local_variable: false
-linter:
- rules:
- - camel_case_types
-''');
-
- // Setup config.yaml.
- newFile(
- [libPath, 'config', 'config.yaml'],
- r'''
-analyzer:
- errors:
- missing_required_param: error
-linter:
- rules:
- - always_specify_types
-''');
-
- // Setup context.
- manager.setRoots(<String>[projPath], <String>[], <String, String>{});
- await pumpEventQueue();
-
- // Confirm that one context was created.
- var contexts =
- manager.contextsInAnalysisRoot(resourceProvider.newFolder(projPath));
- expect(contexts, isNotNull);
- expect(contexts, hasLength(1));
- var context = contexts[0];
-
- // Verify options.
- // * from `_embedder.yaml`:
- expect(context.analysisOptions.strongMode, isTrue);
- expect(context.analysisOptions.enableSuperMixins, isTrue);
- // * from analysis options:
- expect(context.analysisOptions.enableGenericMethods, isTrue);
-
- // * verify tests are excluded
- expect(
- callbacks.currentContextFilePaths[projPath].keys,
- unorderedEquals(
- ['/my/proj/sdk_ext/entry.dart', '/my/proj/$optionsFileName']));
-
- // Verify filter setup.
- expect(errorProcessors, hasLength(3));
-
- // * (embedder.)
- expect(getProcessor(missing_return).severity, isNull);
-
- // * (config.)
- expect(getProcessor(missing_required_param).severity, ErrorSeverity.ERROR);
-
- // * (options.)
- expect(getProcessor(unused_local_variable).severity, isNull);
-
- // Verify lints.
- var lintNames = lints.map((lint) => lint.name);
-
- expect(
- lintNames,
- unorderedEquals([
- 'avoid_as' /* embedder */,
- 'always_specify_types' /* config*/,
- 'camel_case_types' /* options */
- ]));
-
- // Sanity check embedder libs.
- var source = context.sourceFactory.forUri('dart:foobar');
- expect(source, isNotNull);
- expect(source.fullName, '/my/proj/sdk_ext/entry.dart');
- }
-
test_embedder_options() async {
// Create files.
String libPath = newFolder([projPath, ContextManagerTest.LIB_NAME]);
diff --git a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
index 921a266..7c6a742 100644
--- a/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_hover_test.dart
@@ -7,7 +7,7 @@
import 'dart:async';
import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:path/path.dart';
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -78,7 +78,7 @@
expect(info.offset, equals(offset));
expect(info.length, equals(length));
if (isCore) {
- expect(basename(info.containingLibraryPath), equals('core.dart'));
+ expect(path.basename(info.containingLibraryPath), equals('core.dart'));
expect(info.containingLibraryName, equals('dart.core'));
} else if (isLocal || isLiteral) {
expect(info.containingLibraryPath, isNull);
diff --git a/pkg/analysis_server/test/integration/analysis/package_root_test.dart b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
index 4febe5ad..5ad9c38 100644
--- a/pkg/analysis_server/test/integration/analysis/package_root_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/package_root_test.dart
@@ -5,7 +5,7 @@
library test.integration.analysis.packageRoot;
import 'package:analysis_server/plugin/protocol/protocol.dart';
-import 'package:path/path.dart';
+import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -21,9 +21,9 @@
class Test extends AbstractAnalysisServerIntegrationTest {
test_package_root() {
String projPath = sourcePath('project');
- String mainPath = join(projPath, 'main.dart');
+ String mainPath = path.join(projPath, 'main.dart');
String packagesPath = sourcePath('packages');
- String fooBarPath = join(packagesPath, 'foo', 'bar.dart');
+ String fooBarPath = path.join(packagesPath, 'foo', 'bar.dart');
String mainText = """
library main;
diff --git a/pkg/analysis_server/test/integration/analysis/update_content_test.dart b/pkg/analysis_server/test/integration/analysis/update_content_test.dart
index c9d5400..1d275ce2 100644
--- a/pkg/analysis_server/test/integration/analysis/update_content_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/update_content_test.dart
@@ -37,7 +37,7 @@
.then((result) => analysisFinished)
.then((_) {
// There should be no errors now because the contents on disk have been
- // overriden with goodText.
+ // overridden with goodText.
expect(currentAnalysisErrors[pathname], isEmpty);
return sendAnalysisUpdateContent({
pathname: new ChangeContentOverlay(
diff --git a/pkg/analysis_server/test/single_context_manager_test.dart b/pkg/analysis_server/test/single_context_manager_test.dart
index 97b4ec6..eafa488 100644
--- a/pkg/analysis_server/test/single_context_manager_test.dart
+++ b/pkg/analysis_server/test/single_context_manager_test.dart
@@ -14,7 +14,7 @@
import 'package:analyzer/src/generated/source_io.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:linter/src/plugin/linter_plugin.dart';
-import 'package:path/path.dart';
+import 'package:path/path.dart' as path;
import 'package:plugin/manager.dart';
import 'package:plugin/plugin.dart';
import 'package:test/test.dart';
@@ -43,18 +43,18 @@
'**/*.${AnalysisEngine.SUFFIX_HTML}',
];
return patterns
- .map((pattern) => new Glob(posix.separator, pattern))
+ .map((pattern) => new Glob(path.posix.separator, pattern))
.toList();
}
String newFile(List<String> pathComponents, [String content = '']) {
- String filePath = posix.joinAll(pathComponents);
+ String filePath = path.posix.joinAll(pathComponents);
resourceProvider.newFile(filePath, content);
return filePath;
}
String newFolder(List<String> pathComponents) {
- String folderPath = posix.joinAll(pathComponents);
+ String folderPath = path.posix.joinAll(pathComponents);
resourceProvider.newFolder(folderPath);
return folderPath;
}
@@ -99,7 +99,7 @@
resourceProvider.newFolder(root1);
resourceProvider.newFolder(root2);
manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
- expect(manager.isIgnored('$context/root3/file.dart'), isTrue);
+ expect(manager.isIgnored('/context/root3/file.dart'), isTrue);
}
void test_isInAnalysisRoot_false_inExcludedPath() {
@@ -117,7 +117,7 @@
resourceProvider.newFolder(root1);
resourceProvider.newFolder(root2);
manager.setRoots(<String>[root1, root2], <String>[], <String, String>{});
- expect(manager.isInAnalysisRoot('$context/root3/file.dart'), isFalse);
+ expect(manager.isInAnalysisRoot('/context/root3/file.dart'), isFalse);
}
void test_isInAnalysisRoot_true() {
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 07a0577..44e480f 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -125,14 +125,7 @@
For convenience, the API is divided into domains. Each domain is
specified in a separate section below:
</p>
- <ul>
- <li><a href="#domain_server">Server</a></li>
- <li><a href="#domain_analysis">Analysis</a></li>
- <li><a href="#domain_completion">Code Completion</a></li>
- <li><a href="#domain_search">Search</a></li>
- <li><a href="#domain_edit">Edit</a></li>
- <li><a href="#domain_execution">Execution</a></li>
- </ul>
+ <toc></toc>
<p>
The specifications of the API’s refer to data structures beyond
the standard JSON primitives. These data structures are
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index b17cdfe..d71fa64 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -116,9 +116,6 @@
/* Styles for index */
-.subindex {
-}
-
.subindex ul {
padding-left: 0;
margin-left: 0;
@@ -196,6 +193,7 @@
void head(void callback()) => element('head', {}, callback);
void html(void callback()) => element('html', {}, callback);
void i(void callback()) => element('i', {}, callback);
+ void li(void callback()) => element('li', {}, callback);
void link(String id, void callback()) {
element('a', {'href': '#$id'}, callback);
}
@@ -204,6 +202,7 @@
void pre(void callback()) => element('pre', {}, callback);
void title(void callback()) => element('title', {}, callback);
void tt(void callback()) => element('tt', {}, callback);
+ void ul(void callback()) => element('ul', {}, callback);
}
/**
@@ -270,6 +269,22 @@
}
}
+ void generateTableOfContents() {
+ ul(() {
+ writeln();
+
+ for (var domain in api.domains.where((domain) => !domain.experimental)) {
+ write(' ');
+ li(() {
+ link('domain_${domain.name}', () {
+ write(_toTitleCase(domain.name));
+ });
+ });
+ writeln();
+ }
+ });
+ }
+
void generateIndex() {
h3(() => write('Domains'));
for (var domain in api.domains) {
@@ -425,6 +440,9 @@
case 'version':
translateHtml(node, squashParagraphs: squashParagraphs);
break;
+ case 'toc':
+ generateTableOfContents();
+ break;
case 'index':
generateIndex();
break;
@@ -769,3 +787,8 @@
}
}
}
+
+String _toTitleCase(String str) {
+ if (str.isEmpty) return str;
+ return str.substring(0, 1).toUpperCase() + str.substring(1);
+}
diff --git a/pkg/analyzer/lib/source/analysis_options_provider.dart b/pkg/analyzer/lib/source/analysis_options_provider.dart
index 808c835..90cf8a1 100644
--- a/pkg/analyzer/lib/source/analysis_options_provider.dart
+++ b/pkg/analyzer/lib/source/analysis_options_provider.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/source/source_resource.dart';
+import 'package:analyzer/src/task/options.dart';
import 'package:analyzer/src/util/yaml.dart';
import 'package:source_span/source_span.dart';
import 'package:yaml/yaml.dart';
@@ -25,6 +26,8 @@
/// Provide the options found in either
/// [root]/[AnalysisEngine.ANALYSIS_OPTIONS_FILE] or
/// [root]/[AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE].
+ /// 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}) {
Resource resource;
@@ -42,17 +45,21 @@
}
/// Provide the options found in [file].
+ /// 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) {
return getOptionsFromSource(new FileSource(file));
}
/// Provide the options found in [source].
+ /// 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('include');
+ YamlNode node = options.remove(AnalyzerOptions.include);
if (sourceFactory != null && node is YamlScalar) {
var path = node.value;
if (path is String) {
@@ -64,6 +71,8 @@
}
/// Provide the options found in [optionsSource].
+ /// 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>{};
diff --git a/pkg/analyzer/lib/source/config.dart b/pkg/analyzer/lib/source/config.dart
deleted file mode 100644
index db44b4e..0000000
--- a/pkg/analyzer/lib/source/config.dart
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/source/analysis_options_provider.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/task/model.dart';
-import 'package:analyzer/task/model.dart';
-import 'package:package_config/packages.dart';
-import 'package:yaml/src/yaml_node.dart';
-import 'package:yaml/yaml.dart';
-
-/// The descriptor used to associate analysis configuration with analysis
-/// contexts in configuration data.
-final ResultDescriptor<AnalysisConfiguration> ANALYSIS_CONFIGURATION =
- new ResultDescriptorImpl('analysis.config', null);
-
-/// Return configuration associated with this [context], or `null` if there is
-/// none.
-AnalysisConfiguration getConfiguration(AnalysisContext context) =>
- context.getConfigurationData(ANALYSIS_CONFIGURATION);
-
-/// Associate this [config] with the given [context].
-void setConfiguration(AnalysisContext context, AnalysisConfiguration config) {
- context.setConfigurationData(ANALYSIS_CONFIGURATION, config);
-}
-
-/// Analysis configuration.
-abstract class AnalysisConfiguration {
- final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
- final Packages packages;
- final ResourceProvider resourceProvider;
- AnalysisConfiguration(this.resourceProvider, this.packages);
-
- factory AnalysisConfiguration.fromPubspec(
- File pubspec, ResourceProvider resourceProvider, Packages packages) =>
- new PubspecConfiguration(pubspec, resourceProvider, packages);
-
- /// Get a map of options defined by this configuration (or `null` if none
- /// are specified).
- Map get options;
-}
-
-/// Describes an analysis configuration.
-class AnalysisConfigurationDescriptor {
- /// The name of the package hosting the configuration.
- String package;
-
- /// The name of the configuration "pragma".
- String pragma;
-
- AnalysisConfigurationDescriptor.fromAnalyzerOptions(Map analyzerOptions) {
- Object config = analyzerOptions['configuration'];
- if (config is String) {
- List<String> items = config.split('/');
- if (items.length == 2) {
- package = items[0].trim();
- pragma = items[1].trim();
- }
- }
- }
-
- /// Return true if this descriptor is valid.
- bool get isValid => package != null && pragma != null;
-}
-
-/// Pubspec-specified analysis configuration.
-class PubspecConfiguration extends AnalysisConfiguration {
- final File pubspec;
- PubspecConfiguration(
- this.pubspec, ResourceProvider resourceProvider, Packages packages)
- : super(resourceProvider, packages);
-
- @override
- Map get options {
- //Safest not to cache (requested infrequently).
- if (pubspec.exists) {
- try {
- String contents = pubspec.readAsStringSync();
- YamlNode map = loadYamlNode(contents);
- if (map is YamlMap) {
- YamlNode config = map['analyzer'];
- if (config is YamlMap) {
- AnalysisConfigurationDescriptor descriptor =
- new AnalysisConfigurationDescriptor.fromAnalyzerOptions(config);
-
- if (descriptor.isValid) {
- //Create a path, given descriptor and packagemap
- Uri uri = packages.asMap()[descriptor.package];
- Uri pragma = new Uri.file('config/${descriptor.pragma}.yaml',
- windows: false);
- Uri optionsUri = uri.resolveUri(pragma);
- String path = resourceProvider.pathContext.fromUri(optionsUri);
- File file = resourceProvider.getFile(path);
- if (file.exists) {
- return optionsProvider.getOptionsFromFile(file);
- }
- }
- }
- }
- } catch (_) {
- // Skip exceptional configurations.
- }
- }
- return null;
- }
-}
diff --git a/pkg/analyzer/lib/src/analysis_options/error/option_codes.dart b/pkg/analyzer/lib/src/analysis_options/error/option_codes.dart
index 4b39a45..768ec94 100644
--- a/pkg/analyzer/lib/src/analysis_options/error/option_codes.dart
+++ b/pkg/analyzer/lib/src/analysis_options/error/option_codes.dart
@@ -23,6 +23,19 @@
const AnalysisOptionsErrorCode('PARSE_ERROR', '{0}');
/**
+ * An error code indicating that there is a syntactic error
+ * in the included file.
+ *
+ * Parameters:
+ * 0: the path of the file containing the error
+ * 1: the starting offset of the text in the file that contains the error
+ * 2: the ending offset of the text in the file that contains the error
+ * 3: the error message
+ */
+ static const INCLUDED_FILE_PARSE_ERROR = const AnalysisOptionsErrorCode(
+ 'INCLUDED_FILE_PARSE_ERROR', '{3} in {0}({1}..{2})');
+
+ /**
* Initialize a newly created error code to have the given [name].
*/
const AnalysisOptionsErrorCode(String name, String message,
@@ -44,6 +57,30 @@
*/
class AnalysisOptionsWarningCode extends ErrorCode {
/**
+ * An error code indicating a specified include file could not be found.
+ *
+ * Parameters:
+ * 0: the uri of the file to be included
+ * 1: the path of the file containing the include directive
+ */
+ static const AnalysisOptionsWarningCode INCLUDE_FILE_NOT_FOUND =
+ const AnalysisOptionsWarningCode('INCLUDE_FILE_NOT_FOUND',
+ "The include file {0} in {1} cannot be found.");
+
+ /**
+ * An error code indicating a specified include file has a warning.
+ *
+ * Parameters:
+ * 0: the path of the file containing the warnings
+ * 1: the starting offset of the text in the file that contains the warning
+ * 2: the ending offset of the text in the file that contains the warning
+ * 3: the warning message
+ */
+ static const AnalysisOptionsWarningCode INCLUDED_FILE_WARNING =
+ const AnalysisOptionsWarningCode('INCLUDED_FILE_WARNING',
+ "Warning in the included options file {0}({1}..{2}): {3}");
+
+ /**
* An error code indicating that a plugin is being configured with an
* unsupported option and legal options are provided.
*
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 75875f7..5037995 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -77,14 +77,12 @@
* The resolver provider used to create a package: URI resolver, or `null` if
* the normal (Package Specification DEP) lookup mechanism is to be used.
*/
- @deprecated
ResolverProvider packageResolverProvider;
/**
* The resolver provider used to create a file: URI resolver, or `null` if
* the normal file URI resolver is to be used.
*/
- @deprecated
ResolverProvider fileResolverProvider;
/**
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 543e382..7486496b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -1139,7 +1139,6 @@
final FileState file;
final Uri uri;
- Set<FileState> transitiveDependencies;
String _dependencySignature;
_LibraryNode(this.driver, this.file, this.uri);
@@ -1152,8 +1151,7 @@
signature.addString(driver._sdkBundle.apiSignature);
// Add all unlinked API signatures.
- computeTransitiveDependencies();
- transitiveDependencies
+ file.transitiveFiles
.map((file) => file.apiSignature)
.forEach(signature.addBytes);
@@ -1170,20 +1168,6 @@
return other is _LibraryNode && other.uri == uri;
}
- void computeTransitiveDependencies() {
- if (transitiveDependencies == null) {
- transitiveDependencies = new Set<FileState>();
-
- void appendDependencies(FileState file) {
- if (transitiveDependencies.add(file)) {
- file.dependencies.forEach(appendDependencies);
- }
- }
-
- appendDependencies(file);
- }
- }
-
@override
String toString() => uri.toString();
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
index 46f4648..3e18290 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_byte_store.dart
@@ -10,6 +10,17 @@
import 'package:path/path.dart';
/**
+ * The request that is sent from the main isolate to the clean-up isolate.
+ */
+class CacheCleanUpRequest {
+ final String cachePath;
+ final int maxSizeBytes;
+ final SendPort replyTo;
+
+ CacheCleanUpRequest(this.cachePath, this.maxSizeBytes, this.replyTo);
+}
+
+/**
* [ByteStore] that stores values as files.
*/
class FileByteStore implements ByteStore {
@@ -17,7 +28,7 @@
static SendPort _cleanUpSendPort;
final String _cachePath;
- final String _tempName = 'temp_${pid}';
+ final String _tempName = 'temp_$pid';
final int _maxSizeBytes;
int _bytesWrittenSinceCleanup = 0;
@@ -74,7 +85,8 @@
_evictionIsolateIsRunning = true;
try {
ReceivePort response = new ReceivePort();
- _cleanUpSendPort.send([_cachePath, _maxSizeBytes, response.sendPort]);
+ _cleanUpSendPort.send(new CacheCleanUpRequest(
+ _cachePath, _maxSizeBytes, response.sendPort));
await response.first;
} finally {
_evictionIsolateIsRunning = false;
@@ -90,18 +102,11 @@
static void _cacheCleanUpFunction(SendPort initialReplyTo) {
ReceivePort port = new ReceivePort();
initialReplyTo.send(port.sendPort);
- port.listen((args) async {
- if (args is List &&
- args.length == 3 &&
- args[0] is String &&
- args[1] is int &&
- args[2] is SendPort) {
- String cachePath = args[0] as String;
- int maxSizeBytes = args[1] as int;
- await _cleanUpFolder(cachePath, maxSizeBytes);
- // Let that client know that we're done.
- SendPort replyTo = args[2] as SendPort;
- replyTo.send(true);
+ port.listen((request) async {
+ if (request is CacheCleanUpRequest) {
+ await _cleanUpFolder(request.cachePath, request.maxSizeBytes);
+ // Let the client know that we're done.
+ request.replyTo.send(true);
}
});
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 89a3d7b..da38aca 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -25,6 +25,7 @@
import 'package:analyzer/src/util/fast_uri.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
+import 'package:meta/meta.dart';
/**
* [FileContentOverlay] is used to temporary override content of files.
@@ -90,7 +91,8 @@
List<FileState> _importedFiles;
List<FileState> _exportedFiles;
List<FileState> _partedFiles;
- List<FileState> _dependencies;
+ Set<FileState> _directReferencedFiles = new Set<FileState>();
+ Set<FileState> _transitiveFiles;
FileState._(this._fsState, this.path, this.uri, this.source);
@@ -110,9 +112,10 @@
String get contentHash => _contentHash;
/**
- * Return the list of all direct dependencies.
+ * Return the set of all directly referenced files - imported, exported or
+ * parted.
*/
- List<FileState> get dependencies => _dependencies;
+ Set<FileState> get directReferencedFiles => _directReferencedFiles;
/**
* The list of files this file exports.
@@ -157,6 +160,25 @@
List<FileState> get partedFiles => _partedFiles;
/**
+ * Return the set of transitive files - the file itself and all of the
+ * directly or indirectly referenced files.
+ */
+ Set<FileState> get transitiveFiles {
+ if (_transitiveFiles == null) {
+ _transitiveFiles = new Set<FileState>();
+
+ void appendReferenced(FileState file) {
+ if (_transitiveFiles.add(file)) {
+ file._directReferencedFiles.forEach(appendReferenced);
+ }
+ }
+
+ appendReferenced(this);
+ }
+ return _transitiveFiles;
+ }
+
+ /**
* The [UnlinkedUnit] of the file.
*/
UnlinkedUnit get unlinked => _unlinked;
@@ -289,12 +311,25 @@
}
}
- // Compute direct dependencies.
- _dependencies = (new Set<FileState>()
- ..addAll(_importedFiles)
- ..addAll(_exportedFiles)
- ..addAll(_partedFiles))
- .toList();
+ // Compute referenced files.
+ Set<FileState> oldDirectReferencedFiles = _directReferencedFiles;
+ _directReferencedFiles = new Set<FileState>()
+ ..addAll(_importedFiles)
+ ..addAll(_exportedFiles)
+ ..addAll(_partedFiles);
+
+ // If the set of directly referenced files of this file is changed,
+ // then the transitive sets of files that include this file are also
+ // changed. Reset these transitive sets.
+ if (_directReferencedFiles.length != oldDirectReferencedFiles.length ||
+ !_directReferencedFiles.containsAll(oldDirectReferencedFiles)) {
+ for (FileState file in _fsState._uriToFile.values) {
+ if (file._transitiveFiles != null &&
+ file._transitiveFiles.contains(this)) {
+ file._transitiveFiles = null;
+ }
+ }
+ }
// Return whether the API signature changed.
return apiSignatureChanged;
@@ -368,6 +403,8 @@
*/
final Map<FileState, List<FileState>> _partToLibraries = {};
+ FileSystemStateTestView _testView;
+
FileSystemState(
this._logger,
this._byteStore,
@@ -375,13 +412,18 @@
this._resourceProvider,
this._sourceFactory,
this._analysisOptions,
- this._salt);
+ this._salt) {
+ _testView = new FileSystemStateTestView(this);
+ }
/**
* Return the set of known files.
*/
Set<String> get knownFiles => _pathToFiles.keys.toSet();
+ @visibleForTesting
+ FileSystemStateTestView get test => _testView;
+
/**
* Return the canonical [FileState] for the given absolute [path]. The
* returned file has the last known state since if was last refreshed.
@@ -453,3 +495,16 @@
..insert(0, canonicalFile);
}
}
+
+@visibleForTesting
+class FileSystemStateTestView {
+ final FileSystemState state;
+
+ FileSystemStateTestView(this.state);
+
+ Set<FileState> get filesWithoutTransitive {
+ return state._uriToFile.values
+ .where((f) => f._transitiveFiles == null)
+ .toSet();
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
new file mode 100644
index 0000000..811aa92
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
@@ -0,0 +1,250 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+
+/**
+ * Compute the set of external names referenced in the [unit].
+ */
+Set<String> computeReferencedNames(CompilationUnit unit) {
+ _ReferencedNamesComputer computer = new _ReferencedNamesComputer();
+ unit.accept(computer);
+ return computer.names;
+}
+
+/**
+ * Chained set of local names, that hide corresponding external names.
+ */
+class _LocalNameScope {
+ final _LocalNameScope enclosing;
+ Set<String> names;
+
+ _LocalNameScope(this.enclosing);
+
+ factory _LocalNameScope.forBlock(_LocalNameScope enclosing, Block node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ for (Statement statement in node.statements) {
+ if (statement is FunctionDeclarationStatement) {
+ scope.add(statement.functionDeclaration.name);
+ } else if (statement is VariableDeclarationStatement) {
+ scope.addVariableNames(statement.variables);
+ }
+ }
+ return scope;
+ }
+
+ factory _LocalNameScope.forClass(
+ _LocalNameScope enclosing, ClassDeclaration node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ scope.addTypeParameters(node.typeParameters);
+ for (ClassMember member in node.members) {
+ if (member is FieldDeclaration) {
+ scope.addVariableNames(member.fields);
+ } else if (member is MethodDeclaration) {
+ scope.add(member.name);
+ }
+ }
+ return scope;
+ }
+
+ factory _LocalNameScope.forClassTypeAlias(
+ _LocalNameScope enclosing, ClassTypeAlias node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ scope.addTypeParameters(node.typeParameters);
+ return scope;
+ }
+
+ factory _LocalNameScope.forFunction(
+ _LocalNameScope enclosing, FunctionDeclaration node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ scope.addTypeParameters(node.functionExpression.typeParameters);
+ scope.addFormalParameters(node.functionExpression.parameters);
+ return scope;
+ }
+
+ factory _LocalNameScope.forFunctionTypeAlias(
+ _LocalNameScope enclosing, FunctionTypeAlias node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ scope.addTypeParameters(node.typeParameters);
+ return scope;
+ }
+
+ factory _LocalNameScope.forMethod(
+ _LocalNameScope enclosing, MethodDeclaration node) {
+ _LocalNameScope scope = new _LocalNameScope(enclosing);
+ scope.addTypeParameters(node.typeParameters);
+ scope.addFormalParameters(node.parameters);
+ return scope;
+ }
+
+ factory _LocalNameScope.forUnit(CompilationUnit node) {
+ _LocalNameScope scope = new _LocalNameScope(null);
+ for (CompilationUnitMember declaration in node.declarations) {
+ if (declaration is NamedCompilationUnitMember) {
+ scope.add(declaration.name);
+ } else if (declaration is TopLevelVariableDeclaration) {
+ scope.addVariableNames(declaration.variables);
+ }
+ }
+ return scope;
+ }
+
+ void add(SimpleIdentifier identifier) {
+ if (identifier != null) {
+ names ??= new Set<String>();
+ names.add(identifier.name);
+ }
+ }
+
+ void addFormalParameters(FormalParameterList parameterList) {
+ if (parameterList != null) {
+ parameterList.parameters
+ .map((p) => p is NormalFormalParameter ? p.identifier : null)
+ .forEach(add);
+ }
+ }
+
+ void addTypeParameters(TypeParameterList typeParameterList) {
+ if (typeParameterList != null) {
+ typeParameterList.typeParameters.map((p) => p.name).forEach(add);
+ }
+ }
+
+ void addVariableNames(VariableDeclarationList variableList) {
+ for (VariableDeclaration variable in variableList.variables) {
+ add(variable.name);
+ }
+ }
+
+ bool contains(String name) {
+ if (names != null && names.contains(name)) {
+ return true;
+ }
+ if (enclosing != null) {
+ return enclosing.contains(name);
+ }
+ return false;
+ }
+}
+
+class _ReferencedNamesComputer extends GeneralizingAstVisitor {
+ final Set<String> names = new Set<String>();
+ final Set<String> importPrefixNames = new Set<String>();
+
+ _LocalNameScope localScope = new _LocalNameScope(null);
+
+ @override
+ visitBlock(Block node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forBlock(localScope, node);
+ super.visitBlock(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitClassDeclaration(ClassDeclaration node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forClass(localScope, node);
+ super.visitClassDeclaration(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitClassTypeAlias(ClassTypeAlias node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forClassTypeAlias(localScope, node);
+ super.visitClassTypeAlias(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitCompilationUnit(CompilationUnit node) {
+ localScope = new _LocalNameScope.forUnit(node);
+ super.visitCompilationUnit(node);
+ }
+
+ @override
+ visitConstructorName(ConstructorName node) {
+ if (node.parent is! ConstructorDeclaration) {
+ super.visitConstructorName(node);
+ }
+ }
+
+ @override
+ visitFunctionDeclaration(FunctionDeclaration node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forFunction(localScope, node);
+ super.visitFunctionDeclaration(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitFunctionTypeAlias(FunctionTypeAlias node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forFunctionTypeAlias(localScope, node);
+ super.visitFunctionTypeAlias(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitImportDirective(ImportDirective node) {
+ if (node.prefix != null) {
+ importPrefixNames.add(node.prefix.name);
+ }
+ super.visitImportDirective(node);
+ }
+
+ @override
+ visitMethodDeclaration(MethodDeclaration node) {
+ _LocalNameScope outerScope = localScope;
+ try {
+ localScope = new _LocalNameScope.forMethod(localScope, node);
+ super.visitMethodDeclaration(node);
+ } finally {
+ localScope = outerScope;
+ }
+ }
+
+ @override
+ visitSimpleIdentifier(SimpleIdentifier node) {
+ // Ignore all declarations.
+ if (node.inDeclarationContext()) {
+ return;
+ }
+ // Ignore class names references from constructors.
+ AstNode parent = node.parent;
+ if (parent is ConstructorDeclaration && parent.returnType == node) {
+ return;
+ }
+ // Prepare name.
+ String name = node.name;
+ // Ignore unqualified names shadowed by local elements.
+ if (!node.isQualified) {
+ if (localScope.contains(name)) {
+ return;
+ }
+ if (importPrefixNames.contains(name)) {
+ return;
+ }
+ }
+ // Do add the name.
+ names.add(name);
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index dbb50df..3ec4819 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2336,7 +2336,7 @@
* If this element is resynthesized from the summary, return the unlinked
* initializer, otherwise return `null`.
*/
- UnlinkedConst get _unlinkedConst;
+ UnlinkedExpr get _unlinkedConst;
/**
* Return a representation of the value of this variable, forcing the value
@@ -3129,7 +3129,7 @@
* Return annotations for the given [unlinkedConsts] in the [unit].
*/
List<ElementAnnotation> _buildAnnotations(
- CompilationUnitElementImpl unit, List<UnlinkedConst> unlinkedConsts) {
+ CompilationUnitElementImpl unit, List<UnlinkedExpr> unlinkedConsts) {
int length = unlinkedConsts.length;
if (length != 0) {
List<ElementAnnotation> annotations = new List<ElementAnnotation>(length);
@@ -3143,7 +3143,7 @@
}
}
- static int _findElementIndexUsingIdentical(List items, Object item) {
+ static int findElementIndexUsingIdentical(List items, Object item) {
int length = items.length;
for (int i = 0; i < length; i++) {
if (identical(items[i], item)) {
@@ -4387,8 +4387,8 @@
String identifier = super.identifier;
Element enclosing = this.enclosingElement;
if (enclosing is ExecutableElement) {
- int id = ElementImpl._findElementIndexUsingIdentical(
- enclosing.functions, this);
+ int id =
+ ElementImpl.findElementIndexUsingIdentical(enclosing.functions, this);
identifier += "@$id";
}
return identifier;
@@ -6046,7 +6046,7 @@
String identifier = super.identifier;
Element enclosing = this.enclosingElement;
if (enclosing is ExecutableElement) {
- int id = ElementImpl._findElementIndexUsingIdentical(
+ int id = ElementImpl.findElementIndexUsingIdentical(
enclosing.localVariables, this);
identifier += "@$id";
}
@@ -6811,7 +6811,7 @@
/**
* Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
*/
- UnlinkedConst get _unlinkedConst => _unlinkedVariable?.initializer?.bodyExpr;
+ UnlinkedExpr get _unlinkedConst => _unlinkedVariable?.initializer?.bodyExpr;
}
/**
@@ -7178,7 +7178,7 @@
/**
* Subclasses need this getter, see [ConstVariableElement._unlinkedConst].
*/
- UnlinkedConst get _unlinkedConst => _unlinkedParam?.initializer?.bodyExpr;
+ UnlinkedExpr get _unlinkedConst => _unlinkedParam?.initializer?.bodyExpr;
@override
accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
@@ -7760,14 +7760,14 @@
*/
abstract class ResynthesizerContext {
/**
- * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
+ * Build [ElementAnnotationImpl] for the given [UnlinkedExpr].
*/
- ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc);
+ ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc);
/**
- * Build [Expression] for the given [UnlinkedConst].
+ * Build [Expression] for the given [UnlinkedExpr].
*/
- Expression buildExpression(ElementImpl context, UnlinkedConst uc);
+ Expression buildExpression(ElementImpl context, UnlinkedExpr uc);
/**
* Build explicit top-level property accessors.
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index d9914a2..a81585b 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -326,12 +326,12 @@
* that do not invoke the overridden super method.
*
* Parameters:
- * 0: the name of the class declaring the overriden method
+ * 0: the name of the class declaring the overridden method
*/
static const HintCode MUST_CALL_SUPER = const HintCode(
'MUST_CALL_SUPER',
- "This method overrides a method annotated as @mustCall super in '{0}', "
- "but does invoke the overriden method.");
+ "This method overrides a method annotated as @mustCallSuper in '{0}', "
+ "but does invoke the overridden method.");
/**
* A condition in a control flow statement could evaluate to `null` because it
diff --git a/pkg/analyzer/lib/src/generated/constant.dart b/pkg/analyzer/lib/src/generated/constant.dart
index 6dd6c16..db0eb79 100644
--- a/pkg/analyzer/lib/src/generated/constant.dart
+++ b/pkg/analyzer/lib/src/generated/constant.dart
@@ -97,7 +97,6 @@
/// In addition, this class defines several values that can be returned to
/// indicate various conditions encountered during evaluation. These are
/// documented with the static fields that define those values.
-@deprecated
class ConstantEvaluator {
/**
* The source containing the expression(s) that will be evaluated.
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 595acb9..90f3483 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -154,8 +154,17 @@
@override
Object visitExportDirective(ExportDirective node) {
super.visitExportDirective(node);
- _resolveAnnotations(
- node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ List<ElementAnnotation> annotations =
+ _enclosingUnit.getAnnotations(node.offset);
+ if (annotations.isEmpty && node.metadata.isNotEmpty) {
+ int index = (node.parent as CompilationUnit)
+ .directives
+ .where((directive) => directive is ExportDirective)
+ .toList()
+ .indexOf(node);
+ annotations = _walker.element.library.exports[index].metadata;
+ }
+ _resolveAnnotations(node, node.metadata, annotations);
return null;
}
@@ -263,8 +272,17 @@
@override
Object visitImportDirective(ImportDirective node) {
super.visitImportDirective(node);
- _resolveAnnotations(
- node, node.metadata, _enclosingUnit.getAnnotations(node.offset));
+ List<ElementAnnotation> annotations =
+ _enclosingUnit.getAnnotations(node.offset);
+ if (annotations.isEmpty && node.metadata.isNotEmpty) {
+ int index = (node.parent as CompilationUnit)
+ .directives
+ .where((directive) => directive is ImportDirective)
+ .toList()
+ .indexOf(node);
+ annotations = _walker.element.library.imports[index].metadata;
+ }
+ _resolveAnnotations(node, node.metadata, annotations);
return null;
}
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 6a78ba5..9576b15 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -1290,7 +1290,7 @@
@override
@deprecated
- int cacheSize = DEFAULT_CACHE_SIZE;
+ int cacheSize = 64;
@override
bool dart2jsHint = false;
diff --git a/pkg/analyzer/lib/src/generated/parser.dart b/pkg/analyzer/lib/src/generated/parser.dart
index a608bad..0291fde 100644
--- a/pkg/analyzer/lib/src/generated/parser.dart
+++ b/pkg/analyzer/lib/src/generated/parser.dart
@@ -298,8 +298,9 @@
* parameters, followed by a left-parenthesis. This is used by
* [parseTypeAlias] to determine whether or not to parse a return type.
*/
- @deprecated
bool get hasReturnTypeInTypeAlias {
+ // TODO(brianwilkerson) This is too expensive as implemented and needs to be
+ // re-implemented or removed.
Token next = skipReturnType(_currentToken);
if (next == null) {
return false;
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8208abb..b345876 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -8669,7 +8669,7 @@
/**
* A table mapping elements to the overridden type of that element.
*/
- Map<VariableElement, DartType> _overridenTypes =
+ Map<VariableElement, DartType> _overriddenTypes =
new HashMap<VariableElement, DartType>();
/**
@@ -8685,7 +8685,7 @@
* @param overrides the overrides to be applied
*/
void applyOverrides(Map<VariableElement, DartType> overrides) {
- _overridenTypes.addAll(overrides);
+ _overriddenTypes.addAll(overrides);
}
/**
@@ -8694,7 +8694,7 @@
*
* @return the overrides in the current scope
*/
- Map<VariableElement, DartType> captureLocalOverrides() => _overridenTypes;
+ Map<VariableElement, DartType> captureLocalOverrides() => _overriddenTypes;
/**
* Return a map from the elements for the variables in the given list that have their types
@@ -8711,7 +8711,7 @@
for (VariableDeclaration variable in variableList.variables) {
VariableElement element = variable.element;
if (element != null) {
- DartType type = _overridenTypes[element];
+ DartType type = _overriddenTypes[element];
if (type != null) {
overrides[element] = type;
}
@@ -8731,8 +8731,8 @@
DartType getType(Element element) {
Element nonAccessor =
element is PropertyAccessorElement ? element.variable : element;
- DartType type = _overridenTypes[nonAccessor];
- if (_overridenTypes.containsKey(nonAccessor)) {
+ DartType type = _overriddenTypes[nonAccessor];
+ if (_overriddenTypes.containsKey(nonAccessor)) {
return type;
}
return type ?? _outerScope?.getType(element);
@@ -8742,7 +8742,7 @@
* Clears the overridden type of the given [element].
*/
void resetType(VariableElement element) {
- _overridenTypes[element] = null;
+ _overriddenTypes[element] = null;
}
/**
@@ -8752,7 +8752,7 @@
* @param type the overridden type of the given element
*/
void setType(VariableElement element, DartType type) {
- _overridenTypes[element] = type;
+ _overriddenTypes[element] = type;
}
}
diff --git a/pkg/analyzer/lib/src/generated/sdk.dart b/pkg/analyzer/lib/src/generated/sdk.dart
index a03afbe..397fb9d 100644
--- a/pkg/analyzer/lib/src/generated/sdk.dart
+++ b/pkg/analyzer/lib/src/generated/sdk.dart
@@ -120,7 +120,8 @@
/**
* Initialize a newly created manager.
*/
- DartSdkManager(this.defaultSdkDirectory, this.canUseSummaries);
+ DartSdkManager(this.defaultSdkDirectory, this.canUseSummaries,
+ [dynamic ignored]);
/**
* Return any SDK that has been created, or `null` if no SDKs have been
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 3cbfe97..1d91db3 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -64,19 +64,6 @@
}
}
-class _UnlinkedConstOperationReader extends fb.Reader<idl.UnlinkedConstOperation> {
- const _UnlinkedConstOperationReader() : super();
-
- @override
- int get size => 1;
-
- @override
- idl.UnlinkedConstOperation read(fb.BufferContext bc, int offset) {
- int index = const fb.Uint8Reader().read(bc, offset);
- return index < idl.UnlinkedConstOperation.values.length ? idl.UnlinkedConstOperation.values[index] : idl.UnlinkedConstOperation.pushInt;
- }
-}
-
class _UnlinkedConstructorInitializerKindReader extends fb.Reader<idl.UnlinkedConstructorInitializerKind> {
const _UnlinkedConstructorInitializerKindReader() : super();
@@ -116,6 +103,19 @@
}
}
+class _UnlinkedExprOperationReader extends fb.Reader<idl.UnlinkedExprOperation> {
+ const _UnlinkedExprOperationReader() : super();
+
+ @override
+ int get size => 1;
+
+ @override
+ idl.UnlinkedExprOperation read(fb.BufferContext bc, int offset) {
+ int index = const fb.Uint8Reader().read(bc, offset);
+ return index < idl.UnlinkedExprOperation.values.length ? idl.UnlinkedExprOperation.values[index] : idl.UnlinkedExprOperation.pushInt;
+ }
+}
+
class _UnlinkedParamKindReader extends fb.Reader<idl.UnlinkedParamKind> {
const _UnlinkedParamKindReader() : super();
@@ -3425,7 +3425,7 @@
}
class UnlinkedClassBuilder extends Object with _UnlinkedClassMixin implements idl.UnlinkedClass {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
CodeRangeBuilder _codeRange;
UnlinkedDocumentationCommentBuilder _documentationComment;
List<UnlinkedExecutableBuilder> _executables;
@@ -3441,12 +3441,12 @@
List<UnlinkedTypeParamBuilder> _typeParameters;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this class.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -3585,7 +3585,7 @@
this._typeParameters = value;
}
- UnlinkedClassBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedExecutableBuilder> executables, List<UnlinkedVariableBuilder> fields, bool hasNoSupertype, List<EntityRefBuilder> interfaces, bool isAbstract, bool isMixinApplication, List<EntityRefBuilder> mixins, String name, int nameOffset, EntityRefBuilder supertype, List<UnlinkedTypeParamBuilder> typeParameters})
+ UnlinkedClassBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, List<UnlinkedExecutableBuilder> executables, List<UnlinkedVariableBuilder> fields, bool hasNoSupertype, List<EntityRefBuilder> interfaces, bool isAbstract, bool isMixinApplication, List<EntityRefBuilder> mixins, String name, int nameOffset, EntityRefBuilder supertype, List<UnlinkedTypeParamBuilder> typeParameters})
: _annotations = annotations,
_codeRange = codeRange,
_documentationComment = documentationComment,
@@ -3778,7 +3778,7 @@
_UnlinkedClassImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.CodeRange _codeRange;
idl.UnlinkedDocumentationComment _documentationComment;
List<idl.UnlinkedExecutable> _executables;
@@ -3794,8 +3794,8 @@
List<idl.UnlinkedTypeParam> _typeParameters;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 5, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 5, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -4240,313 +4240,10 @@
String toString() => convert.JSON.encode(toJson());
}
-class UnlinkedConstBuilder extends Object with _UnlinkedConstMixin implements idl.UnlinkedConst {
- List<idl.UnlinkedExprAssignOperator> _assignmentOperators;
- List<double> _doubles;
- List<int> _ints;
- bool _isValidConst;
- List<idl.UnlinkedConstOperation> _operations;
- List<EntityRefBuilder> _references;
- List<String> _strings;
-
- @override
- List<idl.UnlinkedExprAssignOperator> get assignmentOperators => _assignmentOperators ??= <idl.UnlinkedExprAssignOperator>[];
-
- /**
- * Sequence of operators used by assignment operations.
- */
- void set assignmentOperators(List<idl.UnlinkedExprAssignOperator> value) {
- this._assignmentOperators = value;
- }
-
- @override
- List<double> get doubles => _doubles ??= <double>[];
-
- /**
- * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
- */
- void set doubles(List<double> value) {
- this._doubles = value;
- }
-
- @override
- List<int> get ints => _ints ??= <int>[];
-
- /**
- * Sequence of unsigned 32-bit integers consumed by the operations
- * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
- * `makeList`, and `makeMap`.
- */
- void set ints(List<int> value) {
- assert(value == null || value.every((e) => e >= 0));
- this._ints = value;
- }
-
- @override
- bool get isValidConst => _isValidConst ??= false;
-
- /**
- * Indicates whether the expression is a valid potentially constant
- * expression.
- */
- void set isValidConst(bool value) {
- this._isValidConst = value;
- }
-
- @override
- List<idl.UnlinkedConstOperation> get operations => _operations ??= <idl.UnlinkedConstOperation>[];
-
- /**
- * Sequence of operations to execute (starting with an empty stack) to form
- * the constant value.
- */
- void set operations(List<idl.UnlinkedConstOperation> value) {
- this._operations = value;
- }
-
- @override
- List<EntityRefBuilder> get references => _references ??= <EntityRefBuilder>[];
-
- /**
- * Sequence of language constructs consumed by the operations
- * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
- * that in the case of `pushReference` (and sometimes `invokeConstructor` the
- * actual entity being referred to may be something other than a type.
- */
- void set references(List<EntityRefBuilder> value) {
- this._references = value;
- }
-
- @override
- List<String> get strings => _strings ??= <String>[];
-
- /**
- * Sequence of strings consumed by the operations `pushString` and
- * `invokeConstructor`.
- */
- void set strings(List<String> value) {
- this._strings = value;
- }
-
- UnlinkedConstBuilder({List<idl.UnlinkedExprAssignOperator> assignmentOperators, List<double> doubles, List<int> ints, bool isValidConst, List<idl.UnlinkedConstOperation> operations, List<EntityRefBuilder> references, List<String> strings})
- : _assignmentOperators = assignmentOperators,
- _doubles = doubles,
- _ints = ints,
- _isValidConst = isValidConst,
- _operations = operations,
- _references = references,
- _strings = strings;
-
- /**
- * Flush [informative] data recursively.
- */
- void flushInformative() {
- _references?.forEach((b) => b.flushInformative());
- }
-
- /**
- * Accumulate non-[informative] data into [signature].
- */
- void collectApiSignature(api_sig.ApiSignature signature) {
- if (this._operations == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._operations.length);
- for (var x in this._operations) {
- signature.addInt(x.index);
- }
- }
- if (this._ints == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._ints.length);
- for (var x in this._ints) {
- signature.addInt(x);
- }
- }
- if (this._references == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._references.length);
- for (var x in this._references) {
- x?.collectApiSignature(signature);
- }
- }
- if (this._strings == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._strings.length);
- for (var x in this._strings) {
- signature.addString(x);
- }
- }
- if (this._doubles == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._doubles.length);
- for (var x in this._doubles) {
- signature.addDouble(x);
- }
- }
- signature.addBool(this._isValidConst == true);
- if (this._assignmentOperators == null) {
- signature.addInt(0);
- } else {
- signature.addInt(this._assignmentOperators.length);
- for (var x in this._assignmentOperators) {
- signature.addInt(x.index);
- }
- }
- }
-
- fb.Offset finish(fb.Builder fbBuilder) {
- fb.Offset offset_assignmentOperators;
- fb.Offset offset_doubles;
- fb.Offset offset_ints;
- fb.Offset offset_operations;
- fb.Offset offset_references;
- fb.Offset offset_strings;
- if (!(_assignmentOperators == null || _assignmentOperators.isEmpty)) {
- offset_assignmentOperators = fbBuilder.writeListUint8(_assignmentOperators.map((b) => b.index).toList());
- }
- if (!(_doubles == null || _doubles.isEmpty)) {
- offset_doubles = fbBuilder.writeListFloat64(_doubles);
- }
- if (!(_ints == null || _ints.isEmpty)) {
- offset_ints = fbBuilder.writeListUint32(_ints);
- }
- if (!(_operations == null || _operations.isEmpty)) {
- offset_operations = fbBuilder.writeListUint8(_operations.map((b) => b.index).toList());
- }
- if (!(_references == null || _references.isEmpty)) {
- offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
- }
- if (!(_strings == null || _strings.isEmpty)) {
- offset_strings = fbBuilder.writeList(_strings.map((b) => fbBuilder.writeString(b)).toList());
- }
- fbBuilder.startTable();
- if (offset_assignmentOperators != null) {
- fbBuilder.addOffset(6, offset_assignmentOperators);
- }
- if (offset_doubles != null) {
- fbBuilder.addOffset(4, offset_doubles);
- }
- if (offset_ints != null) {
- fbBuilder.addOffset(1, offset_ints);
- }
- if (_isValidConst == true) {
- fbBuilder.addBool(5, true);
- }
- if (offset_operations != null) {
- fbBuilder.addOffset(0, offset_operations);
- }
- if (offset_references != null) {
- fbBuilder.addOffset(2, offset_references);
- }
- if (offset_strings != null) {
- fbBuilder.addOffset(3, offset_strings);
- }
- return fbBuilder.endTable();
- }
-}
-
-class _UnlinkedConstReader extends fb.TableReader<_UnlinkedConstImpl> {
- const _UnlinkedConstReader();
-
- @override
- _UnlinkedConstImpl createObject(fb.BufferContext bc, int offset) => new _UnlinkedConstImpl(bc, offset);
-}
-
-class _UnlinkedConstImpl extends Object with _UnlinkedConstMixin implements idl.UnlinkedConst {
- final fb.BufferContext _bc;
- final int _bcOffset;
-
- _UnlinkedConstImpl(this._bc, this._bcOffset);
-
- List<idl.UnlinkedExprAssignOperator> _assignmentOperators;
- List<double> _doubles;
- List<int> _ints;
- bool _isValidConst;
- List<idl.UnlinkedConstOperation> _operations;
- List<idl.EntityRef> _references;
- List<String> _strings;
-
- @override
- List<idl.UnlinkedExprAssignOperator> get assignmentOperators {
- _assignmentOperators ??= const fb.ListReader<idl.UnlinkedExprAssignOperator>(const _UnlinkedExprAssignOperatorReader()).vTableGet(_bc, _bcOffset, 6, const <idl.UnlinkedExprAssignOperator>[]);
- return _assignmentOperators;
- }
-
- @override
- List<double> get doubles {
- _doubles ??= const fb.Float64ListReader().vTableGet(_bc, _bcOffset, 4, const <double>[]);
- return _doubles;
- }
-
- @override
- List<int> get ints {
- _ints ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 1, const <int>[]);
- return _ints;
- }
-
- @override
- bool get isValidConst {
- _isValidConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 5, false);
- return _isValidConst;
- }
-
- @override
- List<idl.UnlinkedConstOperation> get operations {
- _operations ??= const fb.ListReader<idl.UnlinkedConstOperation>(const _UnlinkedConstOperationReader()).vTableGet(_bc, _bcOffset, 0, const <idl.UnlinkedConstOperation>[]);
- return _operations;
- }
-
- @override
- List<idl.EntityRef> get references {
- _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bc, _bcOffset, 2, const <idl.EntityRef>[]);
- return _references;
- }
-
- @override
- List<String> get strings {
- _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 3, const <String>[]);
- return _strings;
- }
-}
-
-abstract class _UnlinkedConstMixin implements idl.UnlinkedConst {
- @override
- Map<String, Object> toJson() {
- Map<String, Object> _result = <String, Object>{};
- if (assignmentOperators.isNotEmpty) _result["assignmentOperators"] = assignmentOperators.map((_value) => _value.toString().split('.')[1]).toList();
- if (doubles.isNotEmpty) _result["doubles"] = doubles.map((_value) => _value.isFinite ? _value : _value.toString()).toList();
- if (ints.isNotEmpty) _result["ints"] = ints;
- if (isValidConst != false) _result["isValidConst"] = isValidConst;
- if (operations.isNotEmpty) _result["operations"] = operations.map((_value) => _value.toString().split('.')[1]).toList();
- if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
- if (strings.isNotEmpty) _result["strings"] = strings;
- return _result;
- }
-
- @override
- Map<String, Object> toMap() => {
- "assignmentOperators": assignmentOperators,
- "doubles": doubles,
- "ints": ints,
- "isValidConst": isValidConst,
- "operations": operations,
- "references": references,
- "strings": strings,
- };
-
- @override
- String toString() => convert.JSON.encode(toJson());
-}
-
class UnlinkedConstructorInitializerBuilder extends Object with _UnlinkedConstructorInitializerMixin implements idl.UnlinkedConstructorInitializer {
List<String> _argumentNames;
- List<UnlinkedConstBuilder> _arguments;
- UnlinkedConstBuilder _expression;
+ List<UnlinkedExprBuilder> _arguments;
+ UnlinkedExprBuilder _expression;
idl.UnlinkedConstructorInitializerKind _kind;
String _name;
@@ -4563,24 +4260,24 @@
}
@override
- List<UnlinkedConstBuilder> get arguments => _arguments ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get arguments => _arguments ??= <UnlinkedExprBuilder>[];
/**
* If [kind] is `thisInvocation` or `superInvocation`, the arguments of the
* invocation. Otherwise empty.
*/
- void set arguments(List<UnlinkedConstBuilder> value) {
+ void set arguments(List<UnlinkedExprBuilder> value) {
this._arguments = value;
}
@override
- UnlinkedConstBuilder get expression => _expression;
+ UnlinkedExprBuilder get expression => _expression;
/**
* If [kind] is `field`, the expression of the field initializer.
* Otherwise `null`.
*/
- void set expression(UnlinkedConstBuilder value) {
+ void set expression(UnlinkedExprBuilder value) {
this._expression = value;
}
@@ -4607,7 +4304,7 @@
this._name = value;
}
- UnlinkedConstructorInitializerBuilder({List<String> argumentNames, List<UnlinkedConstBuilder> arguments, UnlinkedConstBuilder expression, idl.UnlinkedConstructorInitializerKind kind, String name})
+ UnlinkedConstructorInitializerBuilder({List<String> argumentNames, List<UnlinkedExprBuilder> arguments, UnlinkedExprBuilder expression, idl.UnlinkedConstructorInitializerKind kind, String name})
: _argumentNames = argumentNames,
_arguments = arguments,
_expression = expression,
@@ -4699,8 +4396,8 @@
_UnlinkedConstructorInitializerImpl(this._bc, this._bcOffset);
List<String> _argumentNames;
- List<idl.UnlinkedConst> _arguments;
- idl.UnlinkedConst _expression;
+ List<idl.UnlinkedExpr> _arguments;
+ idl.UnlinkedExpr _expression;
idl.UnlinkedConstructorInitializerKind _kind;
String _name;
@@ -4711,14 +4408,14 @@
}
@override
- List<idl.UnlinkedConst> get arguments {
- _arguments ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get arguments {
+ _arguments ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedExpr>[]);
return _arguments;
}
@override
- idl.UnlinkedConst get expression {
- _expression ??= const _UnlinkedConstReader().vTableGet(_bc, _bcOffset, 1, null);
+ idl.UnlinkedExpr get expression {
+ _expression ??= const _UnlinkedExprReader().vTableGet(_bc, _bcOffset, 1, null);
return _expression;
}
@@ -4857,7 +4554,7 @@
}
class UnlinkedEnumBuilder extends Object with _UnlinkedEnumMixin implements idl.UnlinkedEnum {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
CodeRangeBuilder _codeRange;
UnlinkedDocumentationCommentBuilder _documentationComment;
String _name;
@@ -4865,12 +4562,12 @@
List<UnlinkedEnumValueBuilder> _values;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this enum.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -4926,7 +4623,7 @@
this._values = value;
}
- UnlinkedEnumBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedEnumValueBuilder> values})
+ UnlinkedEnumBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedEnumValueBuilder> values})
: _annotations = annotations,
_codeRange = codeRange,
_documentationComment = documentationComment,
@@ -5025,7 +4722,7 @@
_UnlinkedEnumImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.CodeRange _codeRange;
idl.UnlinkedDocumentationComment _documentationComment;
String _name;
@@ -5033,8 +4730,8 @@
List<idl.UnlinkedEnumValue> _values;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 4, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 4, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -5234,8 +4931,8 @@
}
class UnlinkedExecutableBuilder extends Object with _UnlinkedExecutableMixin implements idl.UnlinkedExecutable {
- List<UnlinkedConstBuilder> _annotations;
- UnlinkedConstBuilder _bodyExpr;
+ List<UnlinkedExprBuilder> _annotations;
+ UnlinkedExprBuilder _bodyExpr;
CodeRangeBuilder _codeRange;
List<UnlinkedConstructorInitializerBuilder> _constantInitializers;
int _constCycleSlot;
@@ -5266,24 +4963,24 @@
int _visibleOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this executable.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@override
- UnlinkedConstBuilder get bodyExpr => _bodyExpr;
+ UnlinkedExprBuilder get bodyExpr => _bodyExpr;
/**
* If this executable's function body is declared using `=>`, the expression
* to the right of the `=>`. May be omitted if neither type inference nor
* constant evaluation depends on the function body.
*/
- void set bodyExpr(UnlinkedConstBuilder value) {
+ void set bodyExpr(UnlinkedExprBuilder value) {
this._bodyExpr = value;
}
@@ -5607,7 +5304,7 @@
this._visibleOffset = value;
}
- UnlinkedExecutableBuilder({List<UnlinkedConstBuilder> annotations, UnlinkedConstBuilder bodyExpr, CodeRangeBuilder codeRange, List<UnlinkedConstructorInitializerBuilder> constantInitializers, int constCycleSlot, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isAsynchronous, bool isConst, bool isExternal, bool isFactory, bool isGenerator, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedLabelBuilder> localLabels, List<UnlinkedVariableBuilder> localVariables, String name, int nameEnd, int nameOffset, List<UnlinkedParamBuilder> parameters, int periodOffset, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
+ UnlinkedExecutableBuilder({List<UnlinkedExprBuilder> annotations, UnlinkedExprBuilder bodyExpr, CodeRangeBuilder codeRange, List<UnlinkedConstructorInitializerBuilder> constantInitializers, int constCycleSlot, UnlinkedDocumentationCommentBuilder documentationComment, int inferredReturnTypeSlot, bool isAbstract, bool isAsynchronous, bool isConst, bool isExternal, bool isFactory, bool isGenerator, bool isRedirectedConstructor, bool isStatic, idl.UnlinkedExecutableKind kind, List<UnlinkedExecutableBuilder> localFunctions, List<UnlinkedLabelBuilder> localLabels, List<UnlinkedVariableBuilder> localVariables, String name, int nameEnd, int nameOffset, List<UnlinkedParamBuilder> parameters, int periodOffset, EntityRefBuilder redirectedConstructor, String redirectedConstructorName, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters, int visibleLength, int visibleOffset})
: _annotations = annotations,
_bodyExpr = bodyExpr,
_codeRange = codeRange,
@@ -5892,8 +5589,8 @@
_UnlinkedExecutableImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
- idl.UnlinkedConst _bodyExpr;
+ List<idl.UnlinkedExpr> _annotations;
+ idl.UnlinkedExpr _bodyExpr;
idl.CodeRange _codeRange;
List<idl.UnlinkedConstructorInitializer> _constantInitializers;
int _constCycleSlot;
@@ -5924,14 +5621,14 @@
int _visibleOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 6, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 6, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@override
- idl.UnlinkedConst get bodyExpr {
- _bodyExpr ??= const _UnlinkedConstReader().vTableGet(_bc, _bcOffset, 29, null);
+ idl.UnlinkedExpr get bodyExpr {
+ _bodyExpr ??= const _UnlinkedExprReader().vTableGet(_bc, _bcOffset, 29, null);
return _bodyExpr;
}
@@ -6180,18 +5877,18 @@
}
class UnlinkedExportNonPublicBuilder extends Object with _UnlinkedExportNonPublicMixin implements idl.UnlinkedExportNonPublic {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
int _offset;
int _uriEnd;
int _uriOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this export directive.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -6230,7 +5927,7 @@
this._uriOffset = value;
}
- UnlinkedExportNonPublicBuilder({List<UnlinkedConstBuilder> annotations, int offset, int uriEnd, int uriOffset})
+ UnlinkedExportNonPublicBuilder({List<UnlinkedExprBuilder> annotations, int offset, int uriEnd, int uriOffset})
: _annotations = annotations,
_offset = offset,
_uriEnd = uriEnd,
@@ -6295,14 +5992,14 @@
_UnlinkedExportNonPublicImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
int _offset;
int _uriEnd;
int _uriOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -6504,8 +6201,311 @@
String toString() => convert.JSON.encode(toJson());
}
+class UnlinkedExprBuilder extends Object with _UnlinkedExprMixin implements idl.UnlinkedExpr {
+ List<idl.UnlinkedExprAssignOperator> _assignmentOperators;
+ List<double> _doubles;
+ List<int> _ints;
+ bool _isValidConst;
+ List<idl.UnlinkedExprOperation> _operations;
+ List<EntityRefBuilder> _references;
+ List<String> _strings;
+
+ @override
+ List<idl.UnlinkedExprAssignOperator> get assignmentOperators => _assignmentOperators ??= <idl.UnlinkedExprAssignOperator>[];
+
+ /**
+ * Sequence of operators used by assignment operations.
+ */
+ void set assignmentOperators(List<idl.UnlinkedExprAssignOperator> value) {
+ this._assignmentOperators = value;
+ }
+
+ @override
+ List<double> get doubles => _doubles ??= <double>[];
+
+ /**
+ * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+ */
+ void set doubles(List<double> value) {
+ this._doubles = value;
+ }
+
+ @override
+ List<int> get ints => _ints ??= <int>[];
+
+ /**
+ * Sequence of unsigned 32-bit integers consumed by the operations
+ * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+ * `makeList`, and `makeMap`.
+ */
+ void set ints(List<int> value) {
+ assert(value == null || value.every((e) => e >= 0));
+ this._ints = value;
+ }
+
+ @override
+ bool get isValidConst => _isValidConst ??= false;
+
+ /**
+ * Indicates whether the expression is a valid potentially constant
+ * expression.
+ */
+ void set isValidConst(bool value) {
+ this._isValidConst = value;
+ }
+
+ @override
+ List<idl.UnlinkedExprOperation> get operations => _operations ??= <idl.UnlinkedExprOperation>[];
+
+ /**
+ * Sequence of operations to execute (starting with an empty stack) to form
+ * the constant value.
+ */
+ void set operations(List<idl.UnlinkedExprOperation> value) {
+ this._operations = value;
+ }
+
+ @override
+ List<EntityRefBuilder> get references => _references ??= <EntityRefBuilder>[];
+
+ /**
+ * Sequence of language constructs consumed by the operations
+ * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
+ * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+ * actual entity being referred to may be something other than a type.
+ */
+ void set references(List<EntityRefBuilder> value) {
+ this._references = value;
+ }
+
+ @override
+ List<String> get strings => _strings ??= <String>[];
+
+ /**
+ * Sequence of strings consumed by the operations `pushString` and
+ * `invokeConstructor`.
+ */
+ void set strings(List<String> value) {
+ this._strings = value;
+ }
+
+ UnlinkedExprBuilder({List<idl.UnlinkedExprAssignOperator> assignmentOperators, List<double> doubles, List<int> ints, bool isValidConst, List<idl.UnlinkedExprOperation> operations, List<EntityRefBuilder> references, List<String> strings})
+ : _assignmentOperators = assignmentOperators,
+ _doubles = doubles,
+ _ints = ints,
+ _isValidConst = isValidConst,
+ _operations = operations,
+ _references = references,
+ _strings = strings;
+
+ /**
+ * Flush [informative] data recursively.
+ */
+ void flushInformative() {
+ _references?.forEach((b) => b.flushInformative());
+ }
+
+ /**
+ * Accumulate non-[informative] data into [signature].
+ */
+ void collectApiSignature(api_sig.ApiSignature signature) {
+ if (this._operations == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._operations.length);
+ for (var x in this._operations) {
+ signature.addInt(x.index);
+ }
+ }
+ if (this._ints == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._ints.length);
+ for (var x in this._ints) {
+ signature.addInt(x);
+ }
+ }
+ if (this._references == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._references.length);
+ for (var x in this._references) {
+ x?.collectApiSignature(signature);
+ }
+ }
+ if (this._strings == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._strings.length);
+ for (var x in this._strings) {
+ signature.addString(x);
+ }
+ }
+ if (this._doubles == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._doubles.length);
+ for (var x in this._doubles) {
+ signature.addDouble(x);
+ }
+ }
+ signature.addBool(this._isValidConst == true);
+ if (this._assignmentOperators == null) {
+ signature.addInt(0);
+ } else {
+ signature.addInt(this._assignmentOperators.length);
+ for (var x in this._assignmentOperators) {
+ signature.addInt(x.index);
+ }
+ }
+ }
+
+ fb.Offset finish(fb.Builder fbBuilder) {
+ fb.Offset offset_assignmentOperators;
+ fb.Offset offset_doubles;
+ fb.Offset offset_ints;
+ fb.Offset offset_operations;
+ fb.Offset offset_references;
+ fb.Offset offset_strings;
+ if (!(_assignmentOperators == null || _assignmentOperators.isEmpty)) {
+ offset_assignmentOperators = fbBuilder.writeListUint8(_assignmentOperators.map((b) => b.index).toList());
+ }
+ if (!(_doubles == null || _doubles.isEmpty)) {
+ offset_doubles = fbBuilder.writeListFloat64(_doubles);
+ }
+ if (!(_ints == null || _ints.isEmpty)) {
+ offset_ints = fbBuilder.writeListUint32(_ints);
+ }
+ if (!(_operations == null || _operations.isEmpty)) {
+ offset_operations = fbBuilder.writeListUint8(_operations.map((b) => b.index).toList());
+ }
+ if (!(_references == null || _references.isEmpty)) {
+ offset_references = fbBuilder.writeList(_references.map((b) => b.finish(fbBuilder)).toList());
+ }
+ if (!(_strings == null || _strings.isEmpty)) {
+ offset_strings = fbBuilder.writeList(_strings.map((b) => fbBuilder.writeString(b)).toList());
+ }
+ fbBuilder.startTable();
+ if (offset_assignmentOperators != null) {
+ fbBuilder.addOffset(6, offset_assignmentOperators);
+ }
+ if (offset_doubles != null) {
+ fbBuilder.addOffset(4, offset_doubles);
+ }
+ if (offset_ints != null) {
+ fbBuilder.addOffset(1, offset_ints);
+ }
+ if (_isValidConst == true) {
+ fbBuilder.addBool(5, true);
+ }
+ if (offset_operations != null) {
+ fbBuilder.addOffset(0, offset_operations);
+ }
+ if (offset_references != null) {
+ fbBuilder.addOffset(2, offset_references);
+ }
+ if (offset_strings != null) {
+ fbBuilder.addOffset(3, offset_strings);
+ }
+ return fbBuilder.endTable();
+ }
+}
+
+class _UnlinkedExprReader extends fb.TableReader<_UnlinkedExprImpl> {
+ const _UnlinkedExprReader();
+
+ @override
+ _UnlinkedExprImpl createObject(fb.BufferContext bc, int offset) => new _UnlinkedExprImpl(bc, offset);
+}
+
+class _UnlinkedExprImpl extends Object with _UnlinkedExprMixin implements idl.UnlinkedExpr {
+ final fb.BufferContext _bc;
+ final int _bcOffset;
+
+ _UnlinkedExprImpl(this._bc, this._bcOffset);
+
+ List<idl.UnlinkedExprAssignOperator> _assignmentOperators;
+ List<double> _doubles;
+ List<int> _ints;
+ bool _isValidConst;
+ List<idl.UnlinkedExprOperation> _operations;
+ List<idl.EntityRef> _references;
+ List<String> _strings;
+
+ @override
+ List<idl.UnlinkedExprAssignOperator> get assignmentOperators {
+ _assignmentOperators ??= const fb.ListReader<idl.UnlinkedExprAssignOperator>(const _UnlinkedExprAssignOperatorReader()).vTableGet(_bc, _bcOffset, 6, const <idl.UnlinkedExprAssignOperator>[]);
+ return _assignmentOperators;
+ }
+
+ @override
+ List<double> get doubles {
+ _doubles ??= const fb.Float64ListReader().vTableGet(_bc, _bcOffset, 4, const <double>[]);
+ return _doubles;
+ }
+
+ @override
+ List<int> get ints {
+ _ints ??= const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 1, const <int>[]);
+ return _ints;
+ }
+
+ @override
+ bool get isValidConst {
+ _isValidConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 5, false);
+ return _isValidConst;
+ }
+
+ @override
+ List<idl.UnlinkedExprOperation> get operations {
+ _operations ??= const fb.ListReader<idl.UnlinkedExprOperation>(const _UnlinkedExprOperationReader()).vTableGet(_bc, _bcOffset, 0, const <idl.UnlinkedExprOperation>[]);
+ return _operations;
+ }
+
+ @override
+ List<idl.EntityRef> get references {
+ _references ??= const fb.ListReader<idl.EntityRef>(const _EntityRefReader()).vTableGet(_bc, _bcOffset, 2, const <idl.EntityRef>[]);
+ return _references;
+ }
+
+ @override
+ List<String> get strings {
+ _strings ??= const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 3, const <String>[]);
+ return _strings;
+ }
+}
+
+abstract class _UnlinkedExprMixin implements idl.UnlinkedExpr {
+ @override
+ Map<String, Object> toJson() {
+ Map<String, Object> _result = <String, Object>{};
+ if (assignmentOperators.isNotEmpty) _result["assignmentOperators"] = assignmentOperators.map((_value) => _value.toString().split('.')[1]).toList();
+ if (doubles.isNotEmpty) _result["doubles"] = doubles.map((_value) => _value.isFinite ? _value : _value.toString()).toList();
+ if (ints.isNotEmpty) _result["ints"] = ints;
+ if (isValidConst != false) _result["isValidConst"] = isValidConst;
+ if (operations.isNotEmpty) _result["operations"] = operations.map((_value) => _value.toString().split('.')[1]).toList();
+ if (references.isNotEmpty) _result["references"] = references.map((_value) => _value.toJson()).toList();
+ if (strings.isNotEmpty) _result["strings"] = strings;
+ return _result;
+ }
+
+ @override
+ Map<String, Object> toMap() => {
+ "assignmentOperators": assignmentOperators,
+ "doubles": doubles,
+ "ints": ints,
+ "isValidConst": isValidConst,
+ "operations": operations,
+ "references": references,
+ "strings": strings,
+ };
+
+ @override
+ String toString() => convert.JSON.encode(toJson());
+}
+
class UnlinkedImportBuilder extends Object with _UnlinkedImportMixin implements idl.UnlinkedImport {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
List<UnlinkedCombinatorBuilder> _combinators;
List<UnlinkedConfigurationBuilder> _configurations;
bool _isDeferred;
@@ -6518,12 +6518,12 @@
int _uriOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this import declaration.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -6640,7 +6640,7 @@
this._uriOffset = value;
}
- UnlinkedImportBuilder({List<UnlinkedConstBuilder> annotations, List<UnlinkedCombinatorBuilder> combinators, List<UnlinkedConfigurationBuilder> configurations, bool isDeferred, bool isImplicit, int offset, int prefixOffset, int prefixReference, String uri, int uriEnd, int uriOffset})
+ UnlinkedImportBuilder({List<UnlinkedExprBuilder> annotations, List<UnlinkedCombinatorBuilder> combinators, List<UnlinkedConfigurationBuilder> configurations, bool isDeferred, bool isImplicit, int offset, int prefixOffset, int prefixReference, String uri, int uriEnd, int uriOffset})
: _annotations = annotations,
_combinators = combinators,
_configurations = configurations,
@@ -6768,7 +6768,7 @@
_UnlinkedImportImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
List<idl.UnlinkedCombinator> _combinators;
List<idl.UnlinkedConfiguration> _configurations;
bool _isDeferred;
@@ -6781,8 +6781,8 @@
int _uriOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 8, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 8, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -7043,7 +7043,7 @@
}
class UnlinkedParamBuilder extends Object with _UnlinkedParamMixin implements idl.UnlinkedParam {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
CodeRangeBuilder _codeRange;
String _defaultValueCode;
int _inferredTypeSlot;
@@ -7060,12 +7060,12 @@
int _visibleOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this parameter.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -7232,7 +7232,7 @@
this._visibleOffset = value;
}
- UnlinkedParamBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, String defaultValueCode, int inferredTypeSlot, int inheritsCovariantSlot, UnlinkedExecutableBuilder initializer, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
+ UnlinkedParamBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, String defaultValueCode, int inferredTypeSlot, int inheritsCovariantSlot, UnlinkedExecutableBuilder initializer, bool isFunctionTyped, bool isInitializingFormal, idl.UnlinkedParamKind kind, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder type, int visibleLength, int visibleOffset})
: _annotations = annotations,
_codeRange = codeRange,
_defaultValueCode = defaultValueCode,
@@ -7388,7 +7388,7 @@
_UnlinkedParamImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.CodeRange _codeRange;
String _defaultValueCode;
int _inferredTypeSlot;
@@ -7405,8 +7405,8 @@
int _visibleOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 9, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 9, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -7541,17 +7541,17 @@
}
class UnlinkedPartBuilder extends Object with _UnlinkedPartMixin implements idl.UnlinkedPart {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
int _uriEnd;
int _uriOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this part declaration.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -7579,7 +7579,7 @@
this._uriOffset = value;
}
- UnlinkedPartBuilder({List<UnlinkedConstBuilder> annotations, int uriEnd, int uriOffset})
+ UnlinkedPartBuilder({List<UnlinkedExprBuilder> annotations, int uriEnd, int uriOffset})
: _annotations = annotations,
_uriEnd = uriEnd,
_uriOffset = uriOffset;
@@ -7639,13 +7639,13 @@
_UnlinkedPartImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
int _uriEnd;
int _uriOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 2, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 2, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -8148,7 +8148,7 @@
}
class UnlinkedTypedefBuilder extends Object with _UnlinkedTypedefMixin implements idl.UnlinkedTypedef {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
CodeRangeBuilder _codeRange;
UnlinkedDocumentationCommentBuilder _documentationComment;
String _name;
@@ -8158,12 +8158,12 @@
List<UnlinkedTypeParamBuilder> _typeParameters;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this typedef.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -8239,7 +8239,7 @@
this._typeParameters = value;
}
- UnlinkedTypedefBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters})
+ UnlinkedTypedefBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, String name, int nameOffset, List<UnlinkedParamBuilder> parameters, EntityRefBuilder returnType, List<UnlinkedTypeParamBuilder> typeParameters})
: _annotations = annotations,
_codeRange = codeRange,
_documentationComment = documentationComment,
@@ -8366,7 +8366,7 @@
_UnlinkedTypedefImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.CodeRange _codeRange;
idl.UnlinkedDocumentationComment _documentationComment;
String _name;
@@ -8376,8 +8376,8 @@
List<idl.UnlinkedTypeParam> _typeParameters;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 4, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 4, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -8456,19 +8456,19 @@
}
class UnlinkedTypeParamBuilder extends Object with _UnlinkedTypeParamMixin implements idl.UnlinkedTypeParam {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
EntityRefBuilder _bound;
CodeRangeBuilder _codeRange;
String _name;
int _nameOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this type parameter.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -8514,7 +8514,7 @@
this._nameOffset = value;
}
- UnlinkedTypeParamBuilder({List<UnlinkedConstBuilder> annotations, EntityRefBuilder bound, CodeRangeBuilder codeRange, String name, int nameOffset})
+ UnlinkedTypeParamBuilder({List<UnlinkedExprBuilder> annotations, EntityRefBuilder bound, CodeRangeBuilder codeRange, String name, int nameOffset})
: _annotations = annotations,
_bound = bound,
_codeRange = codeRange,
@@ -8598,15 +8598,15 @@
_UnlinkedTypeParamImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.EntityRef _bound;
idl.CodeRange _codeRange;
String _name;
int _nameOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 3, const <idl.UnlinkedExpr>[]);
return _annotations;
}
@@ -8670,7 +8670,7 @@
String _fallbackModePath;
List<UnlinkedImportBuilder> _imports;
bool _isPartOf;
- List<UnlinkedConstBuilder> _libraryAnnotations;
+ List<UnlinkedExprBuilder> _libraryAnnotations;
UnlinkedDocumentationCommentBuilder _libraryDocumentationComment;
String _libraryName;
int _libraryNameLength;
@@ -8781,13 +8781,13 @@
}
@override
- List<UnlinkedConstBuilder> get libraryAnnotations => _libraryAnnotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get libraryAnnotations => _libraryAnnotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for the library declaration, or the empty list if there is no
* library declaration.
*/
- void set libraryAnnotations(List<UnlinkedConstBuilder> value) {
+ void set libraryAnnotations(List<UnlinkedExprBuilder> value) {
this._libraryAnnotations = value;
}
@@ -8901,7 +8901,7 @@
this._variables = value;
}
- UnlinkedUnitBuilder({List<int> apiSignature, List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, bool isPartOf, List<UnlinkedConstBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<int> lineStarts, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
+ UnlinkedUnitBuilder({List<int> apiSignature, List<UnlinkedClassBuilder> classes, CodeRangeBuilder codeRange, List<UnlinkedEnumBuilder> enums, List<UnlinkedExecutableBuilder> executables, List<UnlinkedExportNonPublicBuilder> exports, String fallbackModePath, List<UnlinkedImportBuilder> imports, bool isPartOf, List<UnlinkedExprBuilder> libraryAnnotations, UnlinkedDocumentationCommentBuilder libraryDocumentationComment, String libraryName, int libraryNameLength, int libraryNameOffset, List<int> lineStarts, List<UnlinkedPartBuilder> parts, UnlinkedPublicNamespaceBuilder publicNamespace, List<UnlinkedReferenceBuilder> references, List<UnlinkedTypedefBuilder> typedefs, List<UnlinkedVariableBuilder> variables})
: _apiSignature = apiSignature,
_classes = classes,
_codeRange = codeRange,
@@ -9210,7 +9210,7 @@
String _fallbackModePath;
List<idl.UnlinkedImport> _imports;
bool _isPartOf;
- List<idl.UnlinkedConst> _libraryAnnotations;
+ List<idl.UnlinkedExpr> _libraryAnnotations;
idl.UnlinkedDocumentationComment _libraryDocumentationComment;
String _libraryName;
int _libraryNameLength;
@@ -9277,8 +9277,8 @@
}
@override
- List<idl.UnlinkedConst> get libraryAnnotations {
- _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 14, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get libraryAnnotations {
+ _libraryAnnotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 14, const <idl.UnlinkedExpr>[]);
return _libraryAnnotations;
}
@@ -9399,7 +9399,7 @@
}
class UnlinkedVariableBuilder extends Object with _UnlinkedVariableMixin implements idl.UnlinkedVariable {
- List<UnlinkedConstBuilder> _annotations;
+ List<UnlinkedExprBuilder> _annotations;
CodeRangeBuilder _codeRange;
UnlinkedDocumentationCommentBuilder _documentationComment;
int _inferredTypeSlot;
@@ -9415,12 +9415,12 @@
int _visibleOffset;
@override
- List<UnlinkedConstBuilder> get annotations => _annotations ??= <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> get annotations => _annotations ??= <UnlinkedExprBuilder>[];
/**
* Annotations for this variable.
*/
- void set annotations(List<UnlinkedConstBuilder> value) {
+ void set annotations(List<UnlinkedExprBuilder> value) {
this._annotations = value;
}
@@ -9573,7 +9573,7 @@
this._visibleOffset = value;
}
- UnlinkedVariableBuilder({List<UnlinkedConstBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, UnlinkedExecutableBuilder initializer, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
+ UnlinkedVariableBuilder({List<UnlinkedExprBuilder> annotations, CodeRangeBuilder codeRange, UnlinkedDocumentationCommentBuilder documentationComment, int inferredTypeSlot, UnlinkedExecutableBuilder initializer, bool isConst, bool isFinal, bool isStatic, String name, int nameOffset, int propagatedTypeSlot, EntityRefBuilder type, int visibleLength, int visibleOffset})
: _annotations = annotations,
_codeRange = codeRange,
_documentationComment = documentationComment,
@@ -9712,7 +9712,7 @@
_UnlinkedVariableImpl(this._bc, this._bcOffset);
- List<idl.UnlinkedConst> _annotations;
+ List<idl.UnlinkedExpr> _annotations;
idl.CodeRange _codeRange;
idl.UnlinkedDocumentationComment _documentationComment;
int _inferredTypeSlot;
@@ -9728,8 +9728,8 @@
int _visibleOffset;
@override
- List<idl.UnlinkedConst> get annotations {
- _annotations ??= const fb.ListReader<idl.UnlinkedConst>(const _UnlinkedConstReader()).vTableGet(_bc, _bcOffset, 8, const <idl.UnlinkedConst>[]);
+ List<idl.UnlinkedExpr> get annotations {
+ _annotations ??= const fb.ListReader<idl.UnlinkedExpr>(const _UnlinkedExprReader()).vTableGet(_bc, _bcOffset, 8, const <idl.UnlinkedExpr>[]);
return _annotations;
}
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 023c370..09fbfe4 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -210,13 +210,152 @@
}
/**
+ * Enum used to indicate the kind of an constructor initializer.
+ */
+enum UnlinkedConstructorInitializerKind : byte {
+ /**
+ * Initialization of a field.
+ */
+ field,
+
+ /**
+ * Invocation of a constructor in the same class.
+ */
+ thisInvocation,
+
+ /**
+ * Invocation of a superclass' constructor.
+ */
+ superInvocation
+}
+
+/**
+ * Enum used to indicate the kind of an executable.
+ */
+enum UnlinkedExecutableKind : byte {
+ /**
+ * Executable is a function or method.
+ */
+ functionOrMethod,
+
+ /**
+ * Executable is a getter.
+ */
+ getter,
+
+ /**
+ * Executable is a setter.
+ */
+ setter,
+
+ /**
+ * Executable is a constructor.
+ */
+ constructor
+}
+
+/**
+ * Enum representing the various kinds of assignment operations combined
+ * with:
+ * [UnlinkedExprOperation.assignToRef],
+ * [UnlinkedExprOperation.assignToProperty],
+ * [UnlinkedExprOperation.assignToIndex].
+ */
+enum UnlinkedExprAssignOperator : byte {
+ /**
+ * Perform simple assignment `target = operand`.
+ */
+ assign,
+
+ /**
+ * Perform `target ??= operand`.
+ */
+ ifNull,
+
+ /**
+ * Perform `target *= operand`.
+ */
+ multiply,
+
+ /**
+ * Perform `target /= operand`.
+ */
+ divide,
+
+ /**
+ * Perform `target ~/= operand`.
+ */
+ floorDivide,
+
+ /**
+ * Perform `target %= operand`.
+ */
+ modulo,
+
+ /**
+ * Perform `target += operand`.
+ */
+ plus,
+
+ /**
+ * Perform `target -= operand`.
+ */
+ minus,
+
+ /**
+ * Perform `target <<= operand`.
+ */
+ shiftLeft,
+
+ /**
+ * Perform `target >>= operand`.
+ */
+ shiftRight,
+
+ /**
+ * Perform `target &= operand`.
+ */
+ bitAnd,
+
+ /**
+ * Perform `target ^= operand`.
+ */
+ bitXor,
+
+ /**
+ * Perform `target |= operand`.
+ */
+ bitOr,
+
+ /**
+ * Perform `++target`.
+ */
+ prefixIncrement,
+
+ /**
+ * Perform `--target`.
+ */
+ prefixDecrement,
+
+ /**
+ * Perform `target++`.
+ */
+ postfixIncrement,
+
+ /**
+ * Perform `target++`.
+ */
+ postfixDecrement
+}
+
+/**
* Enum representing the various kinds of operations which may be performed to
- * produce a constant value. These options are assumed to execute in the
+ * in an expression. These options are assumed to execute in the
* context of a stack which is initially empty.
*/
-enum UnlinkedConstOperation : byte {
+enum UnlinkedExprOperation : byte {
/**
- * Push the next value from [UnlinkedConst.ints] (a 32-bit unsigned integer)
+ * Push the next value from [UnlinkedExpr.ints] (a 32-bit unsigned integer)
* onto the stack.
*
* Note that Dart supports integers larger than 32 bits; these are
@@ -225,15 +364,15 @@
pushInt,
/**
- * Get the number of components from [UnlinkedConst.ints], then do this number
+ * Get the number of components from [UnlinkedExpr.ints], then do this number
* of times the following operations: multiple the current value by 2^32, "or"
- * it with the next value in [UnlinkedConst.ints]. The initial value is zero.
+ * it with the next value in [UnlinkedExpr.ints]. The initial value is zero.
* Push the result into the stack.
*/
pushLongInt,
/**
- * Push the next value from [UnlinkedConst.doubles] (a double precision
+ * Push the next value from [UnlinkedExpr.doubles] (a double precision
* floating point value) onto the stack.
*/
pushDouble,
@@ -249,13 +388,13 @@
pushFalse,
/**
- * Push the next value from [UnlinkedConst.strings] onto the stack.
+ * Push the next value from [UnlinkedExpr.strings] onto the stack.
*/
pushString,
/**
* Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), convert them to strings (if they aren't already),
+ * [UnlinkedExpr.ints]), convert them to strings (if they aren't already),
* concatenate them into a single string, and push it back onto the stack.
*
* This operation is used to represent constants whose value is a literal
@@ -264,7 +403,7 @@
concatenate,
/**
- * Get the next value from [UnlinkedConst.strings], convert it to a symbol,
+ * Get the next value from [UnlinkedExpr.strings], convert it to a symbol,
* and push it onto the stack.
*/
makeSymbol,
@@ -276,14 +415,14 @@
/**
* Push the value of the function parameter with the name obtained from
- * [UnlinkedConst.strings].
+ * [UnlinkedExpr.strings].
*/
pushParameter,
/**
* Evaluate a (potentially qualified) identifier expression and push the
* resulting value onto the stack. The identifier to be evaluated is
- * obtained from [UnlinkedConst.references].
+ * obtained from [UnlinkedExpr.references].
*
* This operation is used to represent the following kinds of constants
* (which are indistinguishable from an unresolved AST alone):
@@ -299,20 +438,20 @@
/**
* Pop the top value from the stack, extract the value of the property with
- * the name obtained from [UnlinkedConst.strings], and push the result back
+ * the name obtained from [UnlinkedExpr.strings], and push the result back
* onto the stack.
*/
extractProperty,
/**
* Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
* values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
* from the end) and use them as positional arguments. Use the lists of
* positional and names arguments to invoke a constant constructor obtained
- * from [UnlinkedConst.references], and push the resulting value back onto the
+ * from [UnlinkedExpr.references], and push the resulting value back onto the
* stack.
*
* Note that for an invocation of the form `const a.b(...)` (where no type
@@ -326,14 +465,14 @@
/**
* Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), place them in a [List], and push the result back
+ * [UnlinkedExpr.ints]), place them in a [List], and push the result back
* onto the stack. The type parameter for the [List] is implicitly `dynamic`.
*/
makeUntypedList,
/**
* Pop the top 2*n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+ * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
* [Map], and push the result back onto the stack. The two type parameters
* for the [Map] are implicitly `dynamic`.
*/
@@ -341,17 +480,17 @@
/**
* Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), place them in a [List], and push the result back
+ * [UnlinkedExpr.ints]), place them in a [List], and push the result back
* onto the stack. The type parameter for the [List] is obtained from
- * [UnlinkedConst.references].
+ * [UnlinkedExpr.references].
*/
makeTypedList,
/**
* Pop the top 2*n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
+ * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
* [Map], and push the result back onto the stack. The two type parameters for
- * the [Map] are obtained from [UnlinkedConst.references].
+ * the [Map] are obtained from [UnlinkedExpr.references].
*/
makeTypedMap,
@@ -495,13 +634,13 @@
/**
* Pop from the stack `value` and get the next `target` reference from
- * [UnlinkedConst.references] - a top-level variable (prefixed or not), an
+ * [UnlinkedExpr.references] - a top-level variable (prefixed or not), an
* assignable field of a class (prefixed or not), or a sequence of getters
* ending with an assignable property `a.b.b.c.d.e`. In general `a.b` cannot
* not be distinguished between: `a` is a prefix and `b` is a top-level
* variable; or `a` is an object and `b` is the name of a property. Perform
* `reference op= value` where `op` is the next assignment operator from
- * [UnlinkedConst.assignmentOperators]. Push `value` back into the stack.
+ * [UnlinkedExpr.assignmentOperators]. Push `value` back into the stack.
*
* If the assignment operator is a prefix/postfix increment/decrement, then
* `value` is not present in the stack, so it should not be popped and the
@@ -516,7 +655,7 @@
* `target`. This operation is used when we know that the `target` is an
* object reference expression, e.g. `new Foo().a.b.c` or `a.b[0].c.d`.
* Perform `target.property op= value` where `op` is the next assignment
- * operator from [UnlinkedConst.assignmentOperators]. Push `value` back into
+ * operator from [UnlinkedExpr.assignmentOperators]. Push `value` back into
* the stack.
*
* If the assignment operator is a prefix/postfix increment/decrement, then
@@ -529,7 +668,7 @@
/**
* Pop from the stack `index`, `target` and `value`. Perform
* `target[index] op= value` where `op` is the next assignment operator from
- * [UnlinkedConst.assignmentOperators]. Push `value` back into the stack.
+ * [UnlinkedExpr.assignmentOperators]. Push `value` back into the stack.
*
* If the assignment operator is a prefix/postfix increment/decrement, then
* `value` is not present in the stack, so it should not be popped and the
@@ -546,15 +685,15 @@
/**
* Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
* values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
* from the end) and use them as positional arguments. Use the lists of
* positional and names arguments to invoke a method (or a function) with
- * the reference from [UnlinkedConst.references]. If `k` is nonzero (where
- * `k` is obtained from [UnlinkedConst.ints]), obtain `k` type arguments from
- * [UnlinkedConst.references] and use them as generic type arguments for the
+ * the reference from [UnlinkedExpr.references]. If `k` is nonzero (where
+ * `k` is obtained from [UnlinkedExpr.ints]), obtain `k` type arguments from
+ * [UnlinkedExpr.references] and use them as generic type arguments for the
* aforementioned method or function. Push the result of the invocation onto
* the stack.
*
@@ -567,15 +706,15 @@
/**
* Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
* values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
* from the end) and use them as positional arguments. Use the lists of
* positional and names arguments to invoke the method with the name from
- * [UnlinkedConst.strings] of the target popped from the stack. If `k` is
- * nonzero (where `k` is obtained from [UnlinkedConst.ints]), obtain `k` type
- * arguments from [UnlinkedConst.references] and use them as generic type
+ * [UnlinkedExpr.strings] of the target popped from the stack. If `k` is
+ * nonzero (where `k` is obtained from [UnlinkedExpr.ints]), obtain `k` type
+ * arguments from [UnlinkedExpr.references] and use them as generic type
* arguments for the aforementioned method. Push the result of the
* invocation onto the stack.
*
@@ -597,13 +736,13 @@
/**
* Pop the top value from the stack and cast it to the type with reference
- * from [UnlinkedConst.references], push the result into the stack.
+ * from [UnlinkedExpr.references], push the result into the stack.
*/
typeCast,
/**
* Pop the top value from the stack and check whether it is a subclass of the
- * type with reference from [UnlinkedConst.references], push the result into
+ * type with reference from [UnlinkedExpr.references], push the result into
* the stack.
*/
typeCheck,
@@ -614,7 +753,7 @@
throwException,
/**
- * Obtain two values `n` and `m` from [UnlinkedConst.ints]. Then, starting at
+ * Obtain two values `n` and `m` from [UnlinkedExpr.ints]. Then, starting at
* the executable element for the expression being evaluated, if n > 0, pop to
* the nth enclosing function element. Then, push the mth local function of
* that element onto the stack.
@@ -623,145 +762,6 @@
}
/**
- * Enum used to indicate the kind of an constructor initializer.
- */
-enum UnlinkedConstructorInitializerKind : byte {
- /**
- * Initialization of a field.
- */
- field,
-
- /**
- * Invocation of a constructor in the same class.
- */
- thisInvocation,
-
- /**
- * Invocation of a superclass' constructor.
- */
- superInvocation
-}
-
-/**
- * Enum used to indicate the kind of an executable.
- */
-enum UnlinkedExecutableKind : byte {
- /**
- * Executable is a function or method.
- */
- functionOrMethod,
-
- /**
- * Executable is a getter.
- */
- getter,
-
- /**
- * Executable is a setter.
- */
- setter,
-
- /**
- * Executable is a constructor.
- */
- constructor
-}
-
-/**
- * Enum representing the various kinds of assignment operations combined
- * with:
- * [UnlinkedConstOperation.assignToRef],
- * [UnlinkedConstOperation.assignToProperty],
- * [UnlinkedConstOperation.assignToIndex].
- */
-enum UnlinkedExprAssignOperator : byte {
- /**
- * Perform simple assignment `target = operand`.
- */
- assign,
-
- /**
- * Perform `target ??= operand`.
- */
- ifNull,
-
- /**
- * Perform `target *= operand`.
- */
- multiply,
-
- /**
- * Perform `target /= operand`.
- */
- divide,
-
- /**
- * Perform `target ~/= operand`.
- */
- floorDivide,
-
- /**
- * Perform `target %= operand`.
- */
- modulo,
-
- /**
- * Perform `target += operand`.
- */
- plus,
-
- /**
- * Perform `target -= operand`.
- */
- minus,
-
- /**
- * Perform `target <<= operand`.
- */
- shiftLeft,
-
- /**
- * Perform `target >>= operand`.
- */
- shiftRight,
-
- /**
- * Perform `target &= operand`.
- */
- bitAnd,
-
- /**
- * Perform `target ^= operand`.
- */
- bitXor,
-
- /**
- * Perform `target |= operand`.
- */
- bitOr,
-
- /**
- * Perform `++target`.
- */
- prefixIncrement,
-
- /**
- * Perform `--target`.
- */
- prefixDecrement,
-
- /**
- * Perform `target++`.
- */
- postfixIncrement,
-
- /**
- * Perform `target++`.
- */
- postfixDecrement
-}
-
-/**
* Enum used to indicate the kind of a parameter.
*/
enum UnlinkedParamKind : byte {
@@ -1398,7 +1398,7 @@
/**
* Annotations for this class.
*/
- annotations:[UnlinkedConst] (id: 5);
+ annotations:[UnlinkedExpr] (id: 5);
/**
* Code range of the class.
@@ -1521,61 +1521,6 @@
}
/**
- * Unlinked summary information about a compile-time constant expression, or a
- * potentially constant expression.
- *
- * Constant expressions are represented using a simple stack-based language
- * where [operations] is a sequence of operations to execute starting with an
- * empty stack. Once all operations have been executed, the stack should
- * contain a single value which is the value of the constant. Note that some
- * operations consume additional data from the other fields of this class.
- */
-table UnlinkedConst {
- /**
- * Sequence of operators used by assignment operations.
- */
- assignmentOperators:[UnlinkedExprAssignOperator] (id: 6);
-
- /**
- * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
- */
- doubles:[double] (id: 4);
-
- /**
- * Sequence of unsigned 32-bit integers consumed by the operations
- * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
- * `makeList`, and `makeMap`.
- */
- ints:[uint] (id: 1);
-
- /**
- * Indicates whether the expression is a valid potentially constant
- * expression.
- */
- isValidConst:bool (id: 5);
-
- /**
- * Sequence of operations to execute (starting with an empty stack) to form
- * the constant value.
- */
- operations:[UnlinkedConstOperation] (id: 0);
-
- /**
- * Sequence of language constructs consumed by the operations
- * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
- * that in the case of `pushReference` (and sometimes `invokeConstructor` the
- * actual entity being referred to may be something other than a type.
- */
- references:[EntityRef] (id: 2);
-
- /**
- * Sequence of strings consumed by the operations `pushString` and
- * `invokeConstructor`.
- */
- strings:[string] (id: 3);
-}
-
-/**
* Unlinked summary information about a constructor initializer.
*/
table UnlinkedConstructorInitializer {
@@ -1590,13 +1535,13 @@
* If [kind] is `thisInvocation` or `superInvocation`, the arguments of the
* invocation. Otherwise empty.
*/
- arguments:[UnlinkedConst] (id: 3);
+ arguments:[UnlinkedExpr] (id: 3);
/**
* If [kind] is `field`, the expression of the field initializer.
* Otherwise `null`.
*/
- expression:UnlinkedConst (id: 1);
+ expression:UnlinkedExpr (id: 1);
/**
* The kind of the constructor initializer (field, redirect, super).
@@ -1643,7 +1588,7 @@
/**
* Annotations for this enum.
*/
- annotations:[UnlinkedConst] (id: 4);
+ annotations:[UnlinkedExpr] (id: 4);
/**
* Code range of the enum.
@@ -1702,14 +1647,14 @@
/**
* Annotations for this executable.
*/
- annotations:[UnlinkedConst] (id: 6);
+ annotations:[UnlinkedExpr] (id: 6);
/**
* If this executable's function body is declared using `=>`, the expression
* to the right of the `=>`. May be omitted if neither type inference nor
* constant evaluation depends on the function body.
*/
- bodyExpr:UnlinkedConst (id: 29);
+ bodyExpr:UnlinkedExpr (id: 29);
/**
* Code range of the executable.
@@ -1893,7 +1838,7 @@
/**
* Annotations for this export directive.
*/
- annotations:[UnlinkedConst] (id: 3);
+ annotations:[UnlinkedExpr] (id: 3);
/**
* Offset of the "export" keyword.
@@ -1936,13 +1881,67 @@
}
/**
+ * Unlinked summary information about an expression.
+ *
+ * Expressions are represented using a simple stack-based language
+ * where [operations] is a sequence of operations to execute starting with an
+ * empty stack. Once all operations have been executed, the stack should
+ * contain a single value which is the value of the constant. Note that some
+ * operations consume additional data from the other fields of this class.
+ */
+table UnlinkedExpr {
+ /**
+ * Sequence of operators used by assignment operations.
+ */
+ assignmentOperators:[UnlinkedExprAssignOperator] (id: 6);
+
+ /**
+ * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+ */
+ doubles:[double] (id: 4);
+
+ /**
+ * Sequence of unsigned 32-bit integers consumed by the operations
+ * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+ * `makeList`, and `makeMap`.
+ */
+ ints:[uint] (id: 1);
+
+ /**
+ * Indicates whether the expression is a valid potentially constant
+ * expression.
+ */
+ isValidConst:bool (id: 5);
+
+ /**
+ * Sequence of operations to execute (starting with an empty stack) to form
+ * the constant value.
+ */
+ operations:[UnlinkedExprOperation] (id: 0);
+
+ /**
+ * Sequence of language constructs consumed by the operations
+ * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
+ * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+ * actual entity being referred to may be something other than a type.
+ */
+ references:[EntityRef] (id: 2);
+
+ /**
+ * Sequence of strings consumed by the operations `pushString` and
+ * `invokeConstructor`.
+ */
+ strings:[string] (id: 3);
+}
+
+/**
* Unlinked summary information about an import declaration.
*/
table UnlinkedImport {
/**
* Annotations for this import declaration.
*/
- annotations:[UnlinkedConst] (id: 8);
+ annotations:[UnlinkedExpr] (id: 8);
/**
* Combinators contained in this import declaration.
@@ -2036,7 +2035,7 @@
/**
* Annotations for this parameter.
*/
- annotations:[UnlinkedConst] (id: 9);
+ annotations:[UnlinkedExpr] (id: 9);
/**
* Code range of the parameter.
@@ -2134,7 +2133,7 @@
/**
* Annotations for this part declaration.
*/
- annotations:[UnlinkedConst] (id: 2);
+ annotations:[UnlinkedExpr] (id: 2);
/**
* End of the URI string (including quotes) relative to the beginning of the
@@ -2240,7 +2239,7 @@
/**
* Annotations for this typedef.
*/
- annotations:[UnlinkedConst] (id: 4);
+ annotations:[UnlinkedExpr] (id: 4);
/**
* Code range of the typedef.
@@ -2286,7 +2285,7 @@
/**
* Annotations for this type parameter.
*/
- annotations:[UnlinkedConst] (id: 3);
+ annotations:[UnlinkedExpr] (id: 3);
/**
* Bound of the type parameter, if a bound is explicitly declared. Otherwise
@@ -2370,7 +2369,7 @@
* Annotations for the library declaration, or the empty list if there is no
* library declaration.
*/
- libraryAnnotations:[UnlinkedConst] (id: 14);
+ libraryAnnotations:[UnlinkedExpr] (id: 14);
/**
* Documentation comment for the library, or `null` if there is no
@@ -2438,7 +2437,7 @@
/**
* Annotations for this variable.
*/
- annotations:[UnlinkedConst] (id: 8);
+ annotations:[UnlinkedExpr] (id: 8);
/**
* Code range of the variable.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index 07ce297d8..eeb604a 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -971,7 +971,7 @@
* Annotations for this class.
*/
@Id(5)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Code range of the class.
@@ -1119,481 +1119,6 @@
}
/**
- * Unlinked summary information about a compile-time constant expression, or a
- * potentially constant expression.
- *
- * Constant expressions are represented using a simple stack-based language
- * where [operations] is a sequence of operations to execute starting with an
- * empty stack. Once all operations have been executed, the stack should
- * contain a single value which is the value of the constant. Note that some
- * operations consume additional data from the other fields of this class.
- */
-abstract class UnlinkedConst extends base.SummaryClass {
- /**
- * Sequence of operators used by assignment operations.
- */
- @Id(6)
- List<UnlinkedExprAssignOperator> get assignmentOperators;
-
- /**
- * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
- */
- @Id(4)
- List<double> get doubles;
-
- /**
- * Sequence of unsigned 32-bit integers consumed by the operations
- * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
- * `makeList`, and `makeMap`.
- */
- @Id(1)
- List<int> get ints;
-
- /**
- * Indicates whether the expression is a valid potentially constant
- * expression.
- */
- @Id(5)
- bool get isValidConst;
-
- /**
- * Sequence of operations to execute (starting with an empty stack) to form
- * the constant value.
- */
- @Id(0)
- List<UnlinkedConstOperation> get operations;
-
- /**
- * Sequence of language constructs consumed by the operations
- * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
- * that in the case of `pushReference` (and sometimes `invokeConstructor` the
- * actual entity being referred to may be something other than a type.
- */
- @Id(2)
- List<EntityRef> get references;
-
- /**
- * Sequence of strings consumed by the operations `pushString` and
- * `invokeConstructor`.
- */
- @Id(3)
- List<String> get strings;
-}
-
-/**
- * Enum representing the various kinds of operations which may be performed to
- * produce a constant value. These options are assumed to execute in the
- * context of a stack which is initially empty.
- */
-enum UnlinkedConstOperation {
- /**
- * Push the next value from [UnlinkedConst.ints] (a 32-bit unsigned integer)
- * onto the stack.
- *
- * Note that Dart supports integers larger than 32 bits; these are
- * represented by composing 32-bit values using the [pushLongInt] operation.
- */
- pushInt,
-
- /**
- * Get the number of components from [UnlinkedConst.ints], then do this number
- * of times the following operations: multiple the current value by 2^32, "or"
- * it with the next value in [UnlinkedConst.ints]. The initial value is zero.
- * Push the result into the stack.
- */
- pushLongInt,
-
- /**
- * Push the next value from [UnlinkedConst.doubles] (a double precision
- * floating point value) onto the stack.
- */
- pushDouble,
-
- /**
- * Push the constant `true` onto the stack.
- */
- pushTrue,
-
- /**
- * Push the constant `false` onto the stack.
- */
- pushFalse,
-
- /**
- * Push the next value from [UnlinkedConst.strings] onto the stack.
- */
- pushString,
-
- /**
- * Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), convert them to strings (if they aren't already),
- * concatenate them into a single string, and push it back onto the stack.
- *
- * This operation is used to represent constants whose value is a literal
- * string containing string interpolations.
- */
- concatenate,
-
- /**
- * Get the next value from [UnlinkedConst.strings], convert it to a symbol,
- * and push it onto the stack.
- */
- makeSymbol,
-
- /**
- * Push the constant `null` onto the stack.
- */
- pushNull,
-
- /**
- * Push the value of the function parameter with the name obtained from
- * [UnlinkedConst.strings].
- */
- pushParameter,
-
- /**
- * Evaluate a (potentially qualified) identifier expression and push the
- * resulting value onto the stack. The identifier to be evaluated is
- * obtained from [UnlinkedConst.references].
- *
- * This operation is used to represent the following kinds of constants
- * (which are indistinguishable from an unresolved AST alone):
- *
- * - A qualified reference to a static constant variable (e.g. `C.v`, where
- * C is a class and `v` is a constant static variable in `C`).
- * - An identifier expression referring to a constant variable.
- * - A simple or qualified identifier denoting a class or type alias.
- * - A simple or qualified identifier denoting a top-level function or a
- * static method.
- */
- pushReference,
-
- /**
- * Pop the top value from the stack, extract the value of the property with
- * the name obtained from [UnlinkedConst.strings], and push the result back
- * onto the stack.
- */
- extractProperty,
-
- /**
- * Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
- * values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
- * from the end) and use them as positional arguments. Use the lists of
- * positional and names arguments to invoke a constant constructor obtained
- * from [UnlinkedConst.references], and push the resulting value back onto the
- * stack.
- *
- * Note that for an invocation of the form `const a.b(...)` (where no type
- * arguments are specified), it is impossible to tell from the unresolved AST
- * alone whether `a` is a class name and `b` is a constructor name, or `a` is
- * a prefix name and `b` is a class name. For consistency between AST based
- * and elements based summaries, references to default constructors are always
- * recorded as references to corresponding classes.
- */
- invokeConstructor,
-
- /**
- * Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), place them in a [List], and push the result back
- * onto the stack. The type parameter for the [List] is implicitly `dynamic`.
- */
- makeUntypedList,
-
- /**
- * Pop the top 2*n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
- * [Map], and push the result back onto the stack. The two type parameters
- * for the [Map] are implicitly `dynamic`.
- */
- makeUntypedMap,
-
- /**
- * Pop the top n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), place them in a [List], and push the result back
- * onto the stack. The type parameter for the [List] is obtained from
- * [UnlinkedConst.references].
- */
- makeTypedList,
-
- /**
- * Pop the top 2*n values from the stack (where n is obtained from
- * [UnlinkedConst.ints]), interpret them as key/value pairs, place them in a
- * [Map], and push the result back onto the stack. The two type parameters for
- * the [Map] are obtained from [UnlinkedConst.references].
- */
- makeTypedMap,
-
- /**
- * Pop the top 2 values from the stack, evaluate `v1 == v2`, and push the
- * result back onto the stack.
- */
- equal,
-
- /**
- * Pop the top 2 values from the stack, evaluate `v1 != v2`, and push the
- * result back onto the stack.
- */
- notEqual,
-
- /**
- * Pop the top value from the stack, compute its boolean negation, and push
- * the result back onto the stack.
- */
- not,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 && v2`, and push the
- * result back onto the stack.
- */
- and,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 || v2`, and push the
- * result back onto the stack.
- */
- or,
-
- /**
- * Pop the top value from the stack, compute its integer complement, and push
- * the result back onto the stack.
- */
- complement,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 ^ v2`, and push the
- * result back onto the stack.
- */
- bitXor,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 & v2`, and push the
- * result back onto the stack.
- */
- bitAnd,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 | v2`, and push the
- * result back onto the stack.
- */
- bitOr,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 >> v2`, and push the
- * result back onto the stack.
- */
- bitShiftRight,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 << v2`, and push the
- * result back onto the stack.
- */
- bitShiftLeft,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 + v2`, and push the
- * result back onto the stack.
- */
- add,
-
- /**
- * Pop the top value from the stack, compute its integer negation, and push
- * the result back onto the stack.
- */
- negate,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 - v2`, and push the
- * result back onto the stack.
- */
- subtract,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 * v2`, and push the
- * result back onto the stack.
- */
- multiply,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 / v2`, and push the
- * result back onto the stack.
- */
- divide,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 ~/ v2`, and push the
- * result back onto the stack.
- */
- floorDivide,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 > v2`, and push the
- * result back onto the stack.
- */
- greater,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 < v2`, and push the
- * result back onto the stack.
- */
- less,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 >= v2`, and push the
- * result back onto the stack.
- */
- greaterEqual,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 <= v2`, and push the
- * result back onto the stack.
- */
- lessEqual,
-
- /**
- * Pop the top 2 values from the stack, compute `v1 % v2`, and push the
- * result back onto the stack.
- */
- modulo,
-
- /**
- * Pop the top 3 values from the stack, compute `v1 ? v2 : v3`, and push the
- * result back onto the stack.
- */
- conditional,
-
- /**
- * Pop from the stack `value` and get the next `target` reference from
- * [UnlinkedConst.references] - a top-level variable (prefixed or not), an
- * assignable field of a class (prefixed or not), or a sequence of getters
- * ending with an assignable property `a.b.b.c.d.e`. In general `a.b` cannot
- * not be distinguished between: `a` is a prefix and `b` is a top-level
- * variable; or `a` is an object and `b` is the name of a property. Perform
- * `reference op= value` where `op` is the next assignment operator from
- * [UnlinkedConst.assignmentOperators]. Push `value` back into the stack.
- *
- * If the assignment operator is a prefix/postfix increment/decrement, then
- * `value` is not present in the stack, so it should not be popped and the
- * corresponding value of the `target` after/before update is pushed into the
- * stack instead.
- */
- assignToRef,
-
- /**
- * Pop from the stack `target` and `value`. Get the name of the property from
- * `UnlinkedConst.strings` and assign the `value` to the named property of the
- * `target`. This operation is used when we know that the `target` is an
- * object reference expression, e.g. `new Foo().a.b.c` or `a.b[0].c.d`.
- * Perform `target.property op= value` where `op` is the next assignment
- * operator from [UnlinkedConst.assignmentOperators]. Push `value` back into
- * the stack.
- *
- * If the assignment operator is a prefix/postfix increment/decrement, then
- * `value` is not present in the stack, so it should not be popped and the
- * corresponding value of the `target` after/before update is pushed into the
- * stack instead.
- */
- assignToProperty,
-
- /**
- * Pop from the stack `index`, `target` and `value`. Perform
- * `target[index] op= value` where `op` is the next assignment operator from
- * [UnlinkedConst.assignmentOperators]. Push `value` back into the stack.
- *
- * If the assignment operator is a prefix/postfix increment/decrement, then
- * `value` is not present in the stack, so it should not be popped and the
- * corresponding value of the `target` after/before update is pushed into the
- * stack instead.
- */
- assignToIndex,
-
- /**
- * Pop from the stack `index` and `target`. Push into the stack the result
- * of evaluation of `target[index]`.
- */
- extractIndex,
-
- /**
- * Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
- * values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
- * from the end) and use them as positional arguments. Use the lists of
- * positional and names arguments to invoke a method (or a function) with
- * the reference from [UnlinkedConst.references]. If `k` is nonzero (where
- * `k` is obtained from [UnlinkedConst.ints]), obtain `k` type arguments from
- * [UnlinkedConst.references] and use them as generic type arguments for the
- * aforementioned method or function. Push the result of the invocation onto
- * the stack.
- *
- * In general `a.b` cannot not be distinguished between: `a` is a prefix and
- * `b` is a top-level function; or `a` is an object and `b` is the name of a
- * method. This operation should be used for a sequence of identifiers
- * `a.b.b.c.d.e` ending with an invokable result.
- */
- invokeMethodRef,
-
- /**
- * Pop the top `n` values from the stack (where `n` is obtained from
- * [UnlinkedConst.ints]) into a list (filled from the end) and take the next
- * `n` values from [UnlinkedConst.strings] and use the lists of names and
- * values to create named arguments. Then pop the top `m` values from the
- * stack (where `m` is obtained from [UnlinkedConst.ints]) into a list (filled
- * from the end) and use them as positional arguments. Use the lists of
- * positional and names arguments to invoke the method with the name from
- * [UnlinkedConst.strings] of the target popped from the stack. If `k` is
- * nonzero (where `k` is obtained from [UnlinkedConst.ints]), obtain `k` type
- * arguments from [UnlinkedConst.references] and use them as generic type
- * arguments for the aforementioned method. Push the result of the
- * invocation onto the stack.
- *
- * This operation should be used for invocation of a method invocation
- * where `target` is known to be an object instance.
- */
- invokeMethod,
-
- /**
- * Begin a new cascade section. Duplicate the top value of the stack.
- */
- cascadeSectionBegin,
-
- /**
- * End a new cascade section. Pop the top value from the stack and throw it
- * away.
- */
- cascadeSectionEnd,
-
- /**
- * Pop the top value from the stack and cast it to the type with reference
- * from [UnlinkedConst.references], push the result into the stack.
- */
- typeCast,
-
- /**
- * Pop the top value from the stack and check whether it is a subclass of the
- * type with reference from [UnlinkedConst.references], push the result into
- * the stack.
- */
- typeCheck,
-
- /**
- * Pop the top value from the stack and raise an exception with this value.
- */
- throwException,
-
- /**
- * Obtain two values `n` and `m` from [UnlinkedConst.ints]. Then, starting at
- * the executable element for the expression being evaluated, if n > 0, pop to
- * the nth enclosing function element. Then, push the mth local function of
- * that element onto the stack.
- */
- pushLocalFunctionReference,
-}
-
-/**
* Unlinked summary information about a constructor initializer.
*/
abstract class UnlinkedConstructorInitializer extends base.SummaryClass {
@@ -1610,14 +1135,14 @@
* invocation. Otherwise empty.
*/
@Id(3)
- List<UnlinkedConst> get arguments;
+ List<UnlinkedExpr> get arguments;
/**
* If [kind] is `field`, the expression of the field initializer.
* Otherwise `null`.
*/
@Id(1)
- UnlinkedConst get expression;
+ UnlinkedExpr get expression;
/**
* The kind of the constructor initializer (field, redirect, super).
@@ -1692,7 +1217,7 @@
* Annotations for this enum.
*/
@Id(4)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Code range of the enum.
@@ -1765,7 +1290,7 @@
* Annotations for this executable.
*/
@Id(6)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* If this executable's function body is declared using `=>`, the expression
@@ -1773,7 +1298,7 @@
* constant evaluation depends on the function body.
*/
@Id(29)
- UnlinkedConst get bodyExpr;
+ UnlinkedExpr get bodyExpr;
/**
* Code range of the executable.
@@ -2022,7 +1547,7 @@
* Annotations for this export directive.
*/
@Id(3)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Offset of the "export" keyword.
@@ -2074,11 +1599,72 @@
}
/**
+ * Unlinked summary information about an expression.
+ *
+ * Expressions are represented using a simple stack-based language
+ * where [operations] is a sequence of operations to execute starting with an
+ * empty stack. Once all operations have been executed, the stack should
+ * contain a single value which is the value of the constant. Note that some
+ * operations consume additional data from the other fields of this class.
+ */
+abstract class UnlinkedExpr extends base.SummaryClass {
+ /**
+ * Sequence of operators used by assignment operations.
+ */
+ @Id(6)
+ List<UnlinkedExprAssignOperator> get assignmentOperators;
+
+ /**
+ * Sequence of 64-bit doubles consumed by the operation `pushDouble`.
+ */
+ @Id(4)
+ List<double> get doubles;
+
+ /**
+ * Sequence of unsigned 32-bit integers consumed by the operations
+ * `pushArgument`, `pushInt`, `shiftOr`, `concatenate`, `invokeConstructor`,
+ * `makeList`, and `makeMap`.
+ */
+ @Id(1)
+ List<int> get ints;
+
+ /**
+ * Indicates whether the expression is a valid potentially constant
+ * expression.
+ */
+ @Id(5)
+ bool get isValidConst;
+
+ /**
+ * Sequence of operations to execute (starting with an empty stack) to form
+ * the constant value.
+ */
+ @Id(0)
+ List<UnlinkedExprOperation> get operations;
+
+ /**
+ * Sequence of language constructs consumed by the operations
+ * `pushReference`, `invokeConstructor`, `makeList`, and `makeMap`. Note
+ * that in the case of `pushReference` (and sometimes `invokeConstructor` the
+ * actual entity being referred to may be something other than a type.
+ */
+ @Id(2)
+ List<EntityRef> get references;
+
+ /**
+ * Sequence of strings consumed by the operations `pushString` and
+ * `invokeConstructor`.
+ */
+ @Id(3)
+ List<String> get strings;
+}
+
+/**
* Enum representing the various kinds of assignment operations combined
* with:
- * [UnlinkedConstOperation.assignToRef],
- * [UnlinkedConstOperation.assignToProperty],
- * [UnlinkedConstOperation.assignToIndex].
+ * [UnlinkedExprOperation.assignToRef],
+ * [UnlinkedExprOperation.assignToProperty],
+ * [UnlinkedExprOperation.assignToIndex].
*/
enum UnlinkedExprAssignOperator {
/**
@@ -2168,6 +1754,419 @@
}
/**
+ * Enum representing the various kinds of operations which may be performed to
+ * in an expression. These options are assumed to execute in the
+ * context of a stack which is initially empty.
+ */
+enum UnlinkedExprOperation {
+ /**
+ * Push the next value from [UnlinkedExpr.ints] (a 32-bit unsigned integer)
+ * onto the stack.
+ *
+ * Note that Dart supports integers larger than 32 bits; these are
+ * represented by composing 32-bit values using the [pushLongInt] operation.
+ */
+ pushInt,
+
+ /**
+ * Get the number of components from [UnlinkedExpr.ints], then do this number
+ * of times the following operations: multiple the current value by 2^32, "or"
+ * it with the next value in [UnlinkedExpr.ints]. The initial value is zero.
+ * Push the result into the stack.
+ */
+ pushLongInt,
+
+ /**
+ * Push the next value from [UnlinkedExpr.doubles] (a double precision
+ * floating point value) onto the stack.
+ */
+ pushDouble,
+
+ /**
+ * Push the constant `true` onto the stack.
+ */
+ pushTrue,
+
+ /**
+ * Push the constant `false` onto the stack.
+ */
+ pushFalse,
+
+ /**
+ * Push the next value from [UnlinkedExpr.strings] onto the stack.
+ */
+ pushString,
+
+ /**
+ * Pop the top n values from the stack (where n is obtained from
+ * [UnlinkedExpr.ints]), convert them to strings (if they aren't already),
+ * concatenate them into a single string, and push it back onto the stack.
+ *
+ * This operation is used to represent constants whose value is a literal
+ * string containing string interpolations.
+ */
+ concatenate,
+
+ /**
+ * Get the next value from [UnlinkedExpr.strings], convert it to a symbol,
+ * and push it onto the stack.
+ */
+ makeSymbol,
+
+ /**
+ * Push the constant `null` onto the stack.
+ */
+ pushNull,
+
+ /**
+ * Push the value of the function parameter with the name obtained from
+ * [UnlinkedExpr.strings].
+ */
+ pushParameter,
+
+ /**
+ * Evaluate a (potentially qualified) identifier expression and push the
+ * resulting value onto the stack. The identifier to be evaluated is
+ * obtained from [UnlinkedExpr.references].
+ *
+ * This operation is used to represent the following kinds of constants
+ * (which are indistinguishable from an unresolved AST alone):
+ *
+ * - A qualified reference to a static constant variable (e.g. `C.v`, where
+ * C is a class and `v` is a constant static variable in `C`).
+ * - An identifier expression referring to a constant variable.
+ * - A simple or qualified identifier denoting a class or type alias.
+ * - A simple or qualified identifier denoting a top-level function or a
+ * static method.
+ */
+ pushReference,
+
+ /**
+ * Pop the top value from the stack, extract the value of the property with
+ * the name obtained from [UnlinkedExpr.strings], and push the result back
+ * onto the stack.
+ */
+ extractProperty,
+
+ /**
+ * Pop the top `n` values from the stack (where `n` is obtained from
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
+ * values to create named arguments. Then pop the top `m` values from the
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
+ * from the end) and use them as positional arguments. Use the lists of
+ * positional and names arguments to invoke a constant constructor obtained
+ * from [UnlinkedExpr.references], and push the resulting value back onto the
+ * stack.
+ *
+ * Note that for an invocation of the form `const a.b(...)` (where no type
+ * arguments are specified), it is impossible to tell from the unresolved AST
+ * alone whether `a` is a class name and `b` is a constructor name, or `a` is
+ * a prefix name and `b` is a class name. For consistency between AST based
+ * and elements based summaries, references to default constructors are always
+ * recorded as references to corresponding classes.
+ */
+ invokeConstructor,
+
+ /**
+ * Pop the top n values from the stack (where n is obtained from
+ * [UnlinkedExpr.ints]), place them in a [List], and push the result back
+ * onto the stack. The type parameter for the [List] is implicitly `dynamic`.
+ */
+ makeUntypedList,
+
+ /**
+ * Pop the top 2*n values from the stack (where n is obtained from
+ * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
+ * [Map], and push the result back onto the stack. The two type parameters
+ * for the [Map] are implicitly `dynamic`.
+ */
+ makeUntypedMap,
+
+ /**
+ * Pop the top n values from the stack (where n is obtained from
+ * [UnlinkedExpr.ints]), place them in a [List], and push the result back
+ * onto the stack. The type parameter for the [List] is obtained from
+ * [UnlinkedExpr.references].
+ */
+ makeTypedList,
+
+ /**
+ * Pop the top 2*n values from the stack (where n is obtained from
+ * [UnlinkedExpr.ints]), interpret them as key/value pairs, place them in a
+ * [Map], and push the result back onto the stack. The two type parameters for
+ * the [Map] are obtained from [UnlinkedExpr.references].
+ */
+ makeTypedMap,
+
+ /**
+ * Pop the top 2 values from the stack, evaluate `v1 == v2`, and push the
+ * result back onto the stack.
+ */
+ equal,
+
+ /**
+ * Pop the top 2 values from the stack, evaluate `v1 != v2`, and push the
+ * result back onto the stack.
+ */
+ notEqual,
+
+ /**
+ * Pop the top value from the stack, compute its boolean negation, and push
+ * the result back onto the stack.
+ */
+ not,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 && v2`, and push the
+ * result back onto the stack.
+ */
+ and,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 || v2`, and push the
+ * result back onto the stack.
+ */
+ or,
+
+ /**
+ * Pop the top value from the stack, compute its integer complement, and push
+ * the result back onto the stack.
+ */
+ complement,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 ^ v2`, and push the
+ * result back onto the stack.
+ */
+ bitXor,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 & v2`, and push the
+ * result back onto the stack.
+ */
+ bitAnd,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 | v2`, and push the
+ * result back onto the stack.
+ */
+ bitOr,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 >> v2`, and push the
+ * result back onto the stack.
+ */
+ bitShiftRight,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 << v2`, and push the
+ * result back onto the stack.
+ */
+ bitShiftLeft,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 + v2`, and push the
+ * result back onto the stack.
+ */
+ add,
+
+ /**
+ * Pop the top value from the stack, compute its integer negation, and push
+ * the result back onto the stack.
+ */
+ negate,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 - v2`, and push the
+ * result back onto the stack.
+ */
+ subtract,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 * v2`, and push the
+ * result back onto the stack.
+ */
+ multiply,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 / v2`, and push the
+ * result back onto the stack.
+ */
+ divide,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 ~/ v2`, and push the
+ * result back onto the stack.
+ */
+ floorDivide,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 > v2`, and push the
+ * result back onto the stack.
+ */
+ greater,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 < v2`, and push the
+ * result back onto the stack.
+ */
+ less,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 >= v2`, and push the
+ * result back onto the stack.
+ */
+ greaterEqual,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 <= v2`, and push the
+ * result back onto the stack.
+ */
+ lessEqual,
+
+ /**
+ * Pop the top 2 values from the stack, compute `v1 % v2`, and push the
+ * result back onto the stack.
+ */
+ modulo,
+
+ /**
+ * Pop the top 3 values from the stack, compute `v1 ? v2 : v3`, and push the
+ * result back onto the stack.
+ */
+ conditional,
+
+ /**
+ * Pop from the stack `value` and get the next `target` reference from
+ * [UnlinkedExpr.references] - a top-level variable (prefixed or not), an
+ * assignable field of a class (prefixed or not), or a sequence of getters
+ * ending with an assignable property `a.b.b.c.d.e`. In general `a.b` cannot
+ * not be distinguished between: `a` is a prefix and `b` is a top-level
+ * variable; or `a` is an object and `b` is the name of a property. Perform
+ * `reference op= value` where `op` is the next assignment operator from
+ * [UnlinkedExpr.assignmentOperators]. Push `value` back into the stack.
+ *
+ * If the assignment operator is a prefix/postfix increment/decrement, then
+ * `value` is not present in the stack, so it should not be popped and the
+ * corresponding value of the `target` after/before update is pushed into the
+ * stack instead.
+ */
+ assignToRef,
+
+ /**
+ * Pop from the stack `target` and `value`. Get the name of the property from
+ * `UnlinkedConst.strings` and assign the `value` to the named property of the
+ * `target`. This operation is used when we know that the `target` is an
+ * object reference expression, e.g. `new Foo().a.b.c` or `a.b[0].c.d`.
+ * Perform `target.property op= value` where `op` is the next assignment
+ * operator from [UnlinkedExpr.assignmentOperators]. Push `value` back into
+ * the stack.
+ *
+ * If the assignment operator is a prefix/postfix increment/decrement, then
+ * `value` is not present in the stack, so it should not be popped and the
+ * corresponding value of the `target` after/before update is pushed into the
+ * stack instead.
+ */
+ assignToProperty,
+
+ /**
+ * Pop from the stack `index`, `target` and `value`. Perform
+ * `target[index] op= value` where `op` is the next assignment operator from
+ * [UnlinkedExpr.assignmentOperators]. Push `value` back into the stack.
+ *
+ * If the assignment operator is a prefix/postfix increment/decrement, then
+ * `value` is not present in the stack, so it should not be popped and the
+ * corresponding value of the `target` after/before update is pushed into the
+ * stack instead.
+ */
+ assignToIndex,
+
+ /**
+ * Pop from the stack `index` and `target`. Push into the stack the result
+ * of evaluation of `target[index]`.
+ */
+ extractIndex,
+
+ /**
+ * Pop the top `n` values from the stack (where `n` is obtained from
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
+ * values to create named arguments. Then pop the top `m` values from the
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
+ * from the end) and use them as positional arguments. Use the lists of
+ * positional and names arguments to invoke a method (or a function) with
+ * the reference from [UnlinkedExpr.references]. If `k` is nonzero (where
+ * `k` is obtained from [UnlinkedExpr.ints]), obtain `k` type arguments from
+ * [UnlinkedExpr.references] and use them as generic type arguments for the
+ * aforementioned method or function. Push the result of the invocation onto
+ * the stack.
+ *
+ * In general `a.b` cannot not be distinguished between: `a` is a prefix and
+ * `b` is a top-level function; or `a` is an object and `b` is the name of a
+ * method. This operation should be used for a sequence of identifiers
+ * `a.b.b.c.d.e` ending with an invokable result.
+ */
+ invokeMethodRef,
+
+ /**
+ * Pop the top `n` values from the stack (where `n` is obtained from
+ * [UnlinkedExpr.ints]) into a list (filled from the end) and take the next
+ * `n` values from [UnlinkedExpr.strings] and use the lists of names and
+ * values to create named arguments. Then pop the top `m` values from the
+ * stack (where `m` is obtained from [UnlinkedExpr.ints]) into a list (filled
+ * from the end) and use them as positional arguments. Use the lists of
+ * positional and names arguments to invoke the method with the name from
+ * [UnlinkedExpr.strings] of the target popped from the stack. If `k` is
+ * nonzero (where `k` is obtained from [UnlinkedExpr.ints]), obtain `k` type
+ * arguments from [UnlinkedExpr.references] and use them as generic type
+ * arguments for the aforementioned method. Push the result of the
+ * invocation onto the stack.
+ *
+ * This operation should be used for invocation of a method invocation
+ * where `target` is known to be an object instance.
+ */
+ invokeMethod,
+
+ /**
+ * Begin a new cascade section. Duplicate the top value of the stack.
+ */
+ cascadeSectionBegin,
+
+ /**
+ * End a new cascade section. Pop the top value from the stack and throw it
+ * away.
+ */
+ cascadeSectionEnd,
+
+ /**
+ * Pop the top value from the stack and cast it to the type with reference
+ * from [UnlinkedExpr.references], push the result into the stack.
+ */
+ typeCast,
+
+ /**
+ * Pop the top value from the stack and check whether it is a subclass of the
+ * type with reference from [UnlinkedExpr.references], push the result into
+ * the stack.
+ */
+ typeCheck,
+
+ /**
+ * Pop the top value from the stack and raise an exception with this value.
+ */
+ throwException,
+
+ /**
+ * Obtain two values `n` and `m` from [UnlinkedExpr.ints]. Then, starting at
+ * the executable element for the expression being evaluated, if n > 0, pop to
+ * the nth enclosing function element. Then, push the mth local function of
+ * that element onto the stack.
+ */
+ pushLocalFunctionReference,
+}
+
+/**
* Unlinked summary information about an import declaration.
*/
abstract class UnlinkedImport extends base.SummaryClass {
@@ -2175,7 +2174,7 @@
* Annotations for this import declaration.
*/
@Id(8)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Combinators contained in this import declaration.
@@ -2289,7 +2288,7 @@
* Annotations for this parameter.
*/
@Id(9)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Code range of the parameter.
@@ -2427,7 +2426,7 @@
* Annotations for this part declaration.
*/
@Id(2)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* End of the URI string (including quotes) relative to the beginning of the
@@ -2551,7 +2550,7 @@
* Annotations for this typedef.
*/
@Id(4)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Code range of the typedef.
@@ -2608,7 +2607,7 @@
* Annotations for this type parameter.
*/
@Id(3)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Bound of the type parameter, if a bound is explicitly declared. Otherwise
@@ -2713,7 +2712,7 @@
* library declaration.
*/
@Id(14)
- List<UnlinkedConst> get libraryAnnotations;
+ List<UnlinkedExpr> get libraryAnnotations;
/**
* Documentation comment for the library, or `null` if there is no
@@ -2796,7 +2795,7 @@
* Annotations for this variable.
*/
@Id(8)
- List<UnlinkedConst> get annotations;
+ List<UnlinkedExpr> get annotations;
/**
* Code range of the variable.
diff --git a/pkg/analyzer/lib/src/summary/link.dart b/pkg/analyzer/lib/src/summary/link.dart
index 87828c3..6b2e1d7 100644
--- a/pkg/analyzer/lib/src/summary/link.dart
+++ b/pkg/analyzer/lib/src/summary/link.dart
@@ -1449,7 +1449,7 @@
constructorElement.enclosingElement.enclosingElement;
collectDependencies(
dependencies, constructorInitializer.expression, compilationUnit);
- for (UnlinkedConst unlinkedConst in constructorInitializer.arguments) {
+ for (UnlinkedExpr unlinkedConst in constructorInitializer.arguments) {
collectDependencies(dependencies, unlinkedConst, compilationUnit);
}
}
@@ -1534,26 +1534,26 @@
*/
void collectDependencies(
List<ConstNode> dependencies,
- UnlinkedConst unlinkedConst,
+ UnlinkedExpr unlinkedConst,
CompilationUnitElementForLink compilationUnit) {
if (unlinkedConst == null) {
return;
}
int refPtr = 0;
int intPtr = 0;
- for (UnlinkedConstOperation operation in unlinkedConst.operations) {
+ for (UnlinkedExprOperation operation in unlinkedConst.operations) {
switch (operation) {
- case UnlinkedConstOperation.pushInt:
+ case UnlinkedExprOperation.pushInt:
intPtr++;
break;
- case UnlinkedConstOperation.pushLongInt:
+ case UnlinkedExprOperation.pushLongInt:
int numInts = unlinkedConst.ints[intPtr++];
intPtr += numInts;
break;
- case UnlinkedConstOperation.concatenate:
+ case UnlinkedExprOperation.concatenate:
intPtr++;
break;
- case UnlinkedConstOperation.pushReference:
+ case UnlinkedExprOperation.pushReference:
EntityRef ref = unlinkedConst.references[refPtr++];
ConstVariableNode variable =
compilationUnit.resolveRef(ref.reference).asConstVariable;
@@ -1561,14 +1561,14 @@
dependencies.add(variable);
}
break;
- case UnlinkedConstOperation.makeUntypedList:
- case UnlinkedConstOperation.makeUntypedMap:
+ case UnlinkedExprOperation.makeUntypedList:
+ case UnlinkedExprOperation.makeUntypedMap:
intPtr++;
break;
- case UnlinkedConstOperation.assignToRef:
+ case UnlinkedExprOperation.assignToRef:
refPtr++;
break;
- case UnlinkedConstOperation.invokeMethodRef:
+ case UnlinkedExprOperation.invokeMethodRef:
EntityRef ref = unlinkedConst.references[refPtr++];
ConstVariableNode variable =
compilationUnit.resolveRef(ref.reference).asConstVariable;
@@ -1579,20 +1579,20 @@
int numTypeArguments = unlinkedConst.ints[intPtr++];
refPtr += numTypeArguments;
break;
- case UnlinkedConstOperation.invokeMethod:
+ case UnlinkedExprOperation.invokeMethod:
intPtr += 2;
int numTypeArguments = unlinkedConst.ints[intPtr++];
refPtr += numTypeArguments;
break;
- case UnlinkedConstOperation.makeTypedList:
+ case UnlinkedExprOperation.makeTypedList:
refPtr++;
intPtr++;
break;
- case UnlinkedConstOperation.makeTypedMap:
+ case UnlinkedExprOperation.makeTypedMap:
refPtr += 2;
intPtr++;
break;
- case UnlinkedConstOperation.invokeConstructor:
+ case UnlinkedExprOperation.invokeConstructor:
EntityRef ref = unlinkedConst.references[refPtr++];
ConstructorElementForLink element =
compilationUnit.resolveRef(ref.reference).asConstructor;
@@ -1601,11 +1601,11 @@
}
intPtr += 2;
break;
- case UnlinkedConstOperation.typeCast:
- case UnlinkedConstOperation.typeCheck:
+ case UnlinkedExprOperation.typeCast:
+ case UnlinkedExprOperation.typeCheck:
refPtr++;
break;
- case UnlinkedConstOperation.pushLocalFunctionReference:
+ case UnlinkedExprOperation.pushLocalFunctionReference:
intPtr += 2;
break;
default:
@@ -2072,7 +2072,7 @@
final LibraryElementForLink library;
final Linker linker;
final TypeProvider typeProvider;
- final UnlinkedConst unlinkedConst;
+ final UnlinkedExpr unlinkedConst;
final List<DartType> stack = <DartType>[];
int intPtr = 0;
@@ -2085,7 +2085,7 @@
LibraryElementForLink library = unit.enclosingElement;
Linker linker = library._linker;
TypeProvider typeProvider = linker.typeProvider;
- UnlinkedConst unlinkedConst = functionElement._unlinkedExecutable.bodyExpr;
+ UnlinkedExpr unlinkedConst = functionElement._unlinkedExecutable.bodyExpr;
return new ExprTypeComputer._(
functionElement, unit, library, linker, typeProvider, unlinkedConst);
}
@@ -2100,169 +2100,169 @@
return DynamicTypeImpl.instance;
}
// Perform RPN evaluation of the constant, using a stack of inferred types.
- for (UnlinkedConstOperation operation in unlinkedConst.operations) {
+ for (UnlinkedExprOperation operation in unlinkedConst.operations) {
switch (operation) {
- case UnlinkedConstOperation.pushInt:
+ case UnlinkedExprOperation.pushInt:
intPtr++;
stack.add(typeProvider.intType);
break;
- case UnlinkedConstOperation.pushLongInt:
+ case UnlinkedExprOperation.pushLongInt:
int numInts = _getNextInt();
intPtr += numInts;
stack.add(typeProvider.intType);
break;
- case UnlinkedConstOperation.pushDouble:
+ case UnlinkedExprOperation.pushDouble:
stack.add(typeProvider.doubleType);
break;
- case UnlinkedConstOperation.pushTrue:
- case UnlinkedConstOperation.pushFalse:
+ case UnlinkedExprOperation.pushTrue:
+ case UnlinkedExprOperation.pushFalse:
stack.add(typeProvider.boolType);
break;
- case UnlinkedConstOperation.pushString:
+ case UnlinkedExprOperation.pushString:
strPtr++;
stack.add(typeProvider.stringType);
break;
- case UnlinkedConstOperation.concatenate:
+ case UnlinkedExprOperation.concatenate:
stack.length -= _getNextInt();
stack.add(typeProvider.stringType);
break;
- case UnlinkedConstOperation.makeSymbol:
+ case UnlinkedExprOperation.makeSymbol:
strPtr++;
stack.add(typeProvider.symbolType);
break;
- case UnlinkedConstOperation.pushNull:
+ case UnlinkedExprOperation.pushNull:
stack.add(BottomTypeImpl.instance);
break;
- case UnlinkedConstOperation.pushReference:
+ case UnlinkedExprOperation.pushReference:
_doPushReference();
break;
- case UnlinkedConstOperation.extractProperty:
+ case UnlinkedExprOperation.extractProperty:
_doExtractProperty();
break;
- case UnlinkedConstOperation.invokeConstructor:
+ case UnlinkedExprOperation.invokeConstructor:
_doInvokeConstructor();
break;
- case UnlinkedConstOperation.makeUntypedList:
+ case UnlinkedExprOperation.makeUntypedList:
_doMakeUntypedList();
break;
- case UnlinkedConstOperation.makeUntypedMap:
+ case UnlinkedExprOperation.makeUntypedMap:
_doMakeUntypedMap();
break;
- case UnlinkedConstOperation.makeTypedList:
+ case UnlinkedExprOperation.makeTypedList:
_doMakeTypedList();
break;
- case UnlinkedConstOperation.makeTypedMap:
+ case UnlinkedExprOperation.makeTypedMap:
_doMakeTypeMap();
break;
- case UnlinkedConstOperation.not:
+ case UnlinkedExprOperation.not:
stack.length -= 1;
stack.add(typeProvider.boolType);
break;
- case UnlinkedConstOperation.complement:
+ case UnlinkedExprOperation.complement:
_computePrefixExpressionType('~');
break;
- case UnlinkedConstOperation.negate:
+ case UnlinkedExprOperation.negate:
_computePrefixExpressionType('unary-');
break;
- case UnlinkedConstOperation.and:
- case UnlinkedConstOperation.or:
- case UnlinkedConstOperation.equal:
- case UnlinkedConstOperation.notEqual:
+ case UnlinkedExprOperation.and:
+ case UnlinkedExprOperation.or:
+ case UnlinkedExprOperation.equal:
+ case UnlinkedExprOperation.notEqual:
stack.length -= 2;
stack.add(typeProvider.boolType);
break;
- case UnlinkedConstOperation.bitXor:
+ case UnlinkedExprOperation.bitXor:
_computeBinaryExpressionType(TokenType.CARET);
break;
- case UnlinkedConstOperation.bitAnd:
+ case UnlinkedExprOperation.bitAnd:
_computeBinaryExpressionType(TokenType.AMPERSAND);
break;
- case UnlinkedConstOperation.bitOr:
+ case UnlinkedExprOperation.bitOr:
_computeBinaryExpressionType(TokenType.BAR);
break;
- case UnlinkedConstOperation.bitShiftRight:
+ case UnlinkedExprOperation.bitShiftRight:
_computeBinaryExpressionType(TokenType.GT_GT);
break;
- case UnlinkedConstOperation.bitShiftLeft:
+ case UnlinkedExprOperation.bitShiftLeft:
_computeBinaryExpressionType(TokenType.LT_LT);
break;
- case UnlinkedConstOperation.add:
+ case UnlinkedExprOperation.add:
_computeBinaryExpressionType(TokenType.PLUS);
break;
- case UnlinkedConstOperation.subtract:
+ case UnlinkedExprOperation.subtract:
_computeBinaryExpressionType(TokenType.MINUS);
break;
- case UnlinkedConstOperation.multiply:
+ case UnlinkedExprOperation.multiply:
_computeBinaryExpressionType(TokenType.STAR);
break;
- case UnlinkedConstOperation.divide:
+ case UnlinkedExprOperation.divide:
_computeBinaryExpressionType(TokenType.SLASH);
break;
- case UnlinkedConstOperation.floorDivide:
+ case UnlinkedExprOperation.floorDivide:
_computeBinaryExpressionType(TokenType.TILDE_SLASH);
break;
- case UnlinkedConstOperation.greater:
+ case UnlinkedExprOperation.greater:
_computeBinaryExpressionType(TokenType.GT);
break;
- case UnlinkedConstOperation.less:
+ case UnlinkedExprOperation.less:
_computeBinaryExpressionType(TokenType.LT);
break;
- case UnlinkedConstOperation.greaterEqual:
+ case UnlinkedExprOperation.greaterEqual:
_computeBinaryExpressionType(TokenType.GT_EQ);
break;
- case UnlinkedConstOperation.lessEqual:
+ case UnlinkedExprOperation.lessEqual:
_computeBinaryExpressionType(TokenType.LT_EQ);
break;
- case UnlinkedConstOperation.modulo:
+ case UnlinkedExprOperation.modulo:
_computeBinaryExpressionType(TokenType.PERCENT);
break;
- case UnlinkedConstOperation.conditional:
+ case UnlinkedExprOperation.conditional:
_doConditional();
break;
- case UnlinkedConstOperation.assignToRef:
+ case UnlinkedExprOperation.assignToRef:
_doAssignToRef();
break;
- case UnlinkedConstOperation.assignToProperty:
+ case UnlinkedExprOperation.assignToProperty:
_doAssignToProperty();
break;
- case UnlinkedConstOperation.assignToIndex:
+ case UnlinkedExprOperation.assignToIndex:
_doAssignToIndex();
break;
- case UnlinkedConstOperation.extractIndex:
+ case UnlinkedExprOperation.extractIndex:
_doExtractIndex();
break;
- case UnlinkedConstOperation.invokeMethodRef:
+ case UnlinkedExprOperation.invokeMethodRef:
_doInvokeMethodRef();
break;
- case UnlinkedConstOperation.invokeMethod:
+ case UnlinkedExprOperation.invokeMethod:
_doInvokeMethod();
break;
- case UnlinkedConstOperation.cascadeSectionBegin:
+ case UnlinkedExprOperation.cascadeSectionBegin:
stack.add(stack.last);
break;
- case UnlinkedConstOperation.cascadeSectionEnd:
+ case UnlinkedExprOperation.cascadeSectionEnd:
stack.removeLast();
break;
- case UnlinkedConstOperation.typeCast:
+ case UnlinkedExprOperation.typeCast:
stack.removeLast();
DartType type = _getNextTypeRef();
stack.add(type);
break;
- case UnlinkedConstOperation.typeCheck:
+ case UnlinkedExprOperation.typeCheck:
stack.removeLast();
refPtr++;
stack.add(typeProvider.boolType);
break;
- case UnlinkedConstOperation.throwException:
+ case UnlinkedExprOperation.throwException:
stack.removeLast();
stack.add(BottomTypeImpl.instance);
break;
- case UnlinkedConstOperation.pushLocalFunctionReference:
+ case UnlinkedExprOperation.pushLocalFunctionReference:
int popCount = _getNextInt();
assert(popCount == 0); // TODO(paulberry): handle the nonzero case.
stack.add(function.functions[_getNextInt()].type);
break;
- case UnlinkedConstOperation.pushParameter:
+ case UnlinkedExprOperation.pushParameter:
stack.add(_findParameterType(_getNextString()));
break;
default:
@@ -2962,6 +2962,9 @@
.toList();
@override
+ String get identifier => '';
+
+ @override
DartType get returnType {
// If this is a variable whose type needs inferring, infer it.
if (_variable.hasImplicitType) {
@@ -3085,6 +3088,18 @@
.toList();
@override
+ String get identifier {
+ String identifier = _unlinkedExecutable.name;
+ Element enclosing = this.enclosingElement;
+ if (enclosing is ExecutableElement) {
+ int id =
+ ElementImpl.findElementIndexUsingIdentical(enclosing.functions, this);
+ identifier += "@$id";
+ }
+ return identifier;
+ }
+
+ @override
bool get _hasTypeBeenInferred => _inferredReturnType != null;
@override
@@ -3988,9 +4003,9 @@
if (inheritsCovariant) {
return true;
}
- for (UnlinkedConst annotation in _unlinkedParam.annotations) {
+ for (UnlinkedExpr annotation in _unlinkedParam.annotations) {
if (annotation.operations.length == 1 &&
- annotation.operations[0] == UnlinkedConstOperation.pushReference) {
+ annotation.operations[0] == UnlinkedExprOperation.pushReference) {
ReferenceableElementForLink element =
this.compilationUnit.resolveRef(annotation.references[0].reference);
if (element is PropertyAccessorElementForLink &&
@@ -4663,26 +4678,26 @@
List<TypeInferenceNode> dependencies,
UnlinkedExecutable unlinkedExecutable,
CompilationUnitElementForLink compilationUnit) {
- UnlinkedConst unlinkedConst = unlinkedExecutable?.bodyExpr;
+ UnlinkedExpr unlinkedConst = unlinkedExecutable?.bodyExpr;
if (unlinkedConst == null) {
return;
}
int refPtr = 0;
int intPtr = 0;
- for (UnlinkedConstOperation operation in unlinkedConst.operations) {
+ for (UnlinkedExprOperation operation in unlinkedConst.operations) {
switch (operation) {
- case UnlinkedConstOperation.pushInt:
+ case UnlinkedExprOperation.pushInt:
intPtr++;
break;
- case UnlinkedConstOperation.pushLongInt:
+ case UnlinkedExprOperation.pushLongInt:
int numInts = unlinkedConst.ints[intPtr++];
intPtr += numInts;
break;
- case UnlinkedConstOperation.concatenate:
+ case UnlinkedExprOperation.concatenate:
intPtr++;
break;
- case UnlinkedConstOperation.pushReference:
+ case UnlinkedExprOperation.pushReference:
EntityRef ref = unlinkedConst.references[refPtr++];
// TODO(paulberry): cache these resolved references for
// later use by evaluate().
@@ -4692,28 +4707,28 @@
dependencies.add(dependency);
}
break;
- case UnlinkedConstOperation.invokeConstructor:
+ case UnlinkedExprOperation.invokeConstructor:
refPtr++;
intPtr += 2;
break;
- case UnlinkedConstOperation.makeUntypedList:
- case UnlinkedConstOperation.makeUntypedMap:
+ case UnlinkedExprOperation.makeUntypedList:
+ case UnlinkedExprOperation.makeUntypedMap:
intPtr++;
break;
- case UnlinkedConstOperation.makeTypedList:
+ case UnlinkedExprOperation.makeTypedList:
refPtr++;
intPtr++;
break;
- case UnlinkedConstOperation.makeTypedMap:
+ case UnlinkedExprOperation.makeTypedMap:
refPtr += 2;
intPtr++;
break;
- case UnlinkedConstOperation.assignToRef:
+ case UnlinkedExprOperation.assignToRef:
// TODO(paulberry): if this reference refers to a variable, should it
// be considered a type inference dependency?
refPtr++;
break;
- case UnlinkedConstOperation.invokeMethodRef:
+ case UnlinkedExprOperation.invokeMethodRef:
// TODO(paulberry): if this reference refers to a variable, should it
// be considered a type inference dependency?
refPtr++;
@@ -4721,16 +4736,16 @@
int numTypeArguments = unlinkedConst.ints[intPtr++];
refPtr += numTypeArguments;
break;
- case UnlinkedConstOperation.invokeMethod:
+ case UnlinkedExprOperation.invokeMethod:
intPtr += 2;
int numTypeArguments = unlinkedConst.ints[intPtr++];
refPtr += numTypeArguments;
break;
- case UnlinkedConstOperation.typeCast:
- case UnlinkedConstOperation.typeCheck:
+ case UnlinkedExprOperation.typeCast:
+ case UnlinkedExprOperation.typeCheck:
refPtr++;
break;
- case UnlinkedConstOperation.pushLocalFunctionReference:
+ case UnlinkedExprOperation.pushLocalFunctionReference:
int popCount = unlinkedConst.ints[intPtr++];
assert(popCount == 0); // TODO(paulberry): handle the nonzero case.
dependencies.add(functionElement
@@ -4981,6 +4996,9 @@
@override
bool get hasImplicitType => unlinkedVariable.type == null;
+ @override
+ String get identifier => unlinkedVariable.name;
+
/**
* Return the inferred type of the variable element. Should only be called if
* no type was explicitly declared.
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 0baf656..30f0aec 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -301,12 +301,12 @@
}
/**
- * Builder of [Expression]s from [UnlinkedConst]s.
+ * Builder of [Expression]s from [UnlinkedExpr]s.
*/
class _ConstExprBuilder {
final _UnitResynthesizer resynthesizer;
final ElementImpl context;
- final UnlinkedConst uc;
+ final UnlinkedExpr uc;
int intPtr = 0;
int doublePtr = 0;
@@ -333,24 +333,24 @@
if (!uc.isValidConst) {
return AstFactory.identifier3(r'$$invalidConstExpr$$');
}
- for (UnlinkedConstOperation operation in uc.operations) {
+ for (UnlinkedExprOperation operation in uc.operations) {
switch (operation) {
- case UnlinkedConstOperation.pushNull:
+ case UnlinkedExprOperation.pushNull:
_push(AstFactory.nullLiteral());
break;
// bool
- case UnlinkedConstOperation.pushFalse:
+ case UnlinkedExprOperation.pushFalse:
_push(AstFactory.booleanLiteral(false));
break;
- case UnlinkedConstOperation.pushTrue:
+ case UnlinkedExprOperation.pushTrue:
_push(AstFactory.booleanLiteral(true));
break;
// literals
- case UnlinkedConstOperation.pushInt:
+ case UnlinkedExprOperation.pushInt:
int value = uc.ints[intPtr++];
_push(AstFactory.integer(value));
break;
- case UnlinkedConstOperation.pushLongInt:
+ case UnlinkedExprOperation.pushLongInt:
int value = 0;
int count = uc.ints[intPtr++];
for (int i = 0; i < count; i++) {
@@ -359,20 +359,20 @@
}
_push(AstFactory.integer(value));
break;
- case UnlinkedConstOperation.pushDouble:
+ case UnlinkedExprOperation.pushDouble:
double value = uc.doubles[doublePtr++];
_push(AstFactory.doubleLiteral(value));
break;
- case UnlinkedConstOperation.makeSymbol:
+ case UnlinkedExprOperation.makeSymbol:
String component = uc.strings[stringPtr++];
_push(AstFactory.symbolLiteral([component]));
break;
// String
- case UnlinkedConstOperation.pushString:
+ case UnlinkedExprOperation.pushString:
String value = uc.strings[stringPtr++];
_push(AstFactory.string2(value));
break;
- case UnlinkedConstOperation.concatenate:
+ case UnlinkedExprOperation.concatenate:
int count = uc.ints[intPtr++];
List<InterpolationElement> elements = <InterpolationElement>[];
for (int i = 0; i < count; i++) {
@@ -383,75 +383,75 @@
_push(AstFactory.string(elements));
break;
// binary
- case UnlinkedConstOperation.equal:
+ case UnlinkedExprOperation.equal:
_pushBinary(TokenType.EQ_EQ);
break;
- case UnlinkedConstOperation.notEqual:
+ case UnlinkedExprOperation.notEqual:
_pushBinary(TokenType.BANG_EQ);
break;
- case UnlinkedConstOperation.and:
+ case UnlinkedExprOperation.and:
_pushBinary(TokenType.AMPERSAND_AMPERSAND);
break;
- case UnlinkedConstOperation.or:
+ case UnlinkedExprOperation.or:
_pushBinary(TokenType.BAR_BAR);
break;
- case UnlinkedConstOperation.bitXor:
+ case UnlinkedExprOperation.bitXor:
_pushBinary(TokenType.CARET);
break;
- case UnlinkedConstOperation.bitAnd:
+ case UnlinkedExprOperation.bitAnd:
_pushBinary(TokenType.AMPERSAND);
break;
- case UnlinkedConstOperation.bitOr:
+ case UnlinkedExprOperation.bitOr:
_pushBinary(TokenType.BAR);
break;
- case UnlinkedConstOperation.bitShiftLeft:
+ case UnlinkedExprOperation.bitShiftLeft:
_pushBinary(TokenType.LT_LT);
break;
- case UnlinkedConstOperation.bitShiftRight:
+ case UnlinkedExprOperation.bitShiftRight:
_pushBinary(TokenType.GT_GT);
break;
- case UnlinkedConstOperation.add:
+ case UnlinkedExprOperation.add:
_pushBinary(TokenType.PLUS);
break;
- case UnlinkedConstOperation.subtract:
+ case UnlinkedExprOperation.subtract:
_pushBinary(TokenType.MINUS);
break;
- case UnlinkedConstOperation.multiply:
+ case UnlinkedExprOperation.multiply:
_pushBinary(TokenType.STAR);
break;
- case UnlinkedConstOperation.divide:
+ case UnlinkedExprOperation.divide:
_pushBinary(TokenType.SLASH);
break;
- case UnlinkedConstOperation.floorDivide:
+ case UnlinkedExprOperation.floorDivide:
_pushBinary(TokenType.TILDE_SLASH);
break;
- case UnlinkedConstOperation.modulo:
+ case UnlinkedExprOperation.modulo:
_pushBinary(TokenType.PERCENT);
break;
- case UnlinkedConstOperation.greater:
+ case UnlinkedExprOperation.greater:
_pushBinary(TokenType.GT);
break;
- case UnlinkedConstOperation.greaterEqual:
+ case UnlinkedExprOperation.greaterEqual:
_pushBinary(TokenType.GT_EQ);
break;
- case UnlinkedConstOperation.less:
+ case UnlinkedExprOperation.less:
_pushBinary(TokenType.LT);
break;
- case UnlinkedConstOperation.lessEqual:
+ case UnlinkedExprOperation.lessEqual:
_pushBinary(TokenType.LT_EQ);
break;
// prefix
- case UnlinkedConstOperation.complement:
+ case UnlinkedExprOperation.complement:
_pushPrefix(TokenType.TILDE);
break;
- case UnlinkedConstOperation.negate:
+ case UnlinkedExprOperation.negate:
_pushPrefix(TokenType.MINUS);
break;
- case UnlinkedConstOperation.not:
+ case UnlinkedExprOperation.not:
_pushPrefix(TokenType.BANG);
break;
// conditional
- case UnlinkedConstOperation.conditional:
+ case UnlinkedExprOperation.conditional:
Expression elseExpr = _pop();
Expression thenExpr = _pop();
Expression condition = _pop();
@@ -459,35 +459,35 @@
AstFactory.conditionalExpression(condition, thenExpr, elseExpr));
break;
// invokeMethodRef
- case UnlinkedConstOperation.invokeMethodRef:
+ case UnlinkedExprOperation.invokeMethodRef:
_pushInvokeMethodRef();
break;
// containers
- case UnlinkedConstOperation.makeUntypedList:
+ case UnlinkedExprOperation.makeUntypedList:
_pushList(null);
break;
- case UnlinkedConstOperation.makeTypedList:
+ case UnlinkedExprOperation.makeTypedList:
TypeName itemType = _newTypeName();
_pushList(AstFactory.typeArgumentList(<TypeName>[itemType]));
break;
- case UnlinkedConstOperation.makeUntypedMap:
+ case UnlinkedExprOperation.makeUntypedMap:
_pushMap(null);
break;
- case UnlinkedConstOperation.makeTypedMap:
+ case UnlinkedExprOperation.makeTypedMap:
TypeName keyType = _newTypeName();
TypeName valueType = _newTypeName();
_pushMap(AstFactory.typeArgumentList(<TypeName>[keyType, valueType]));
break;
- case UnlinkedConstOperation.pushReference:
+ case UnlinkedExprOperation.pushReference:
_pushReference();
break;
- case UnlinkedConstOperation.extractProperty:
+ case UnlinkedExprOperation.extractProperty:
_pushExtractProperty();
break;
- case UnlinkedConstOperation.invokeConstructor:
+ case UnlinkedExprOperation.invokeConstructor:
_pushInstanceCreation();
break;
- case UnlinkedConstOperation.pushParameter:
+ case UnlinkedExprOperation.pushParameter:
String name = uc.strings[stringPtr++];
SimpleIdentifier identifier = AstFactory.identifier3(name);
identifier.staticElement = _enclosingConstructor.parameters
@@ -496,17 +496,17 @@
'Unable to resolve constructor parameter: $name'));
_push(identifier);
break;
- case UnlinkedConstOperation.assignToRef:
- case UnlinkedConstOperation.assignToProperty:
- case UnlinkedConstOperation.assignToIndex:
- case UnlinkedConstOperation.extractIndex:
- case UnlinkedConstOperation.invokeMethod:
- case UnlinkedConstOperation.cascadeSectionBegin:
- case UnlinkedConstOperation.cascadeSectionEnd:
- case UnlinkedConstOperation.typeCast:
- case UnlinkedConstOperation.typeCheck:
- case UnlinkedConstOperation.throwException:
- case UnlinkedConstOperation.pushLocalFunctionReference:
+ case UnlinkedExprOperation.assignToRef:
+ case UnlinkedExprOperation.assignToProperty:
+ case UnlinkedExprOperation.assignToIndex:
+ case UnlinkedExprOperation.extractIndex:
+ case UnlinkedExprOperation.invokeMethod:
+ case UnlinkedExprOperation.cascadeSectionBegin:
+ case UnlinkedExprOperation.cascadeSectionEnd:
+ case UnlinkedExprOperation.typeCast:
+ case UnlinkedExprOperation.typeCheck:
+ case UnlinkedExprOperation.throwException:
+ case UnlinkedExprOperation.pushLocalFunctionReference:
throw new UnimplementedError(
'Unexpected $operation in a constant expression.');
}
@@ -1370,12 +1370,12 @@
_ResynthesizerContext(this._unitResynthesizer);
@override
- ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc) {
+ ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
return _unitResynthesizer.buildAnnotation(context, uc);
}
@override
- Expression buildExpression(ElementImpl context, UnlinkedConst uc) {
+ Expression buildExpression(ElementImpl context, UnlinkedExpr uc) {
return _unitResynthesizer._buildConstExpression(context, uc);
}
@@ -1507,9 +1507,9 @@
TypeProvider get typeProvider => summaryResynthesizer.typeProvider;
/**
- * Build [ElementAnnotationImpl] for the given [UnlinkedConst].
+ * Build [ElementAnnotationImpl] for the given [UnlinkedExpr].
*/
- ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedConst uc) {
+ ElementAnnotationImpl buildAnnotation(ElementImpl context, UnlinkedExpr uc) {
ElementAnnotationImpl elementAnnotation = new ElementAnnotationImpl(unit);
Expression constExpr = _buildConstExpression(context, uc);
if (constExpr is Identifier) {
@@ -1804,13 +1804,14 @@
return result;
}
- Expression _buildConstExpression(ElementImpl context, UnlinkedConst uc) {
+ Expression _buildConstExpression(ElementImpl context, UnlinkedExpr uc) {
return new _ConstExprBuilder(this, context, uc).build();
}
/**
* Return the defining type for a [ConstructorElement] by applying
- * [typeArgumentRefs] to the given linked [info].
+ * [typeArgumentRefs] to the given linked [info]. Return [DynamicTypeImpl]
+ * if the [info] is unresolved.
*/
DartType _createConstructorDefiningType(
TypeParameterizedElementMixin typeParameterContext,
@@ -1818,6 +1819,9 @@
List<EntityRef> typeArgumentRefs) {
bool isClass = info.element is ClassElement;
_ReferenceInfo classInfo = isClass ? info : info.enclosing;
+ if (classInfo == null) {
+ return DynamicTypeImpl.instance;
+ }
List<DartType> typeArguments = typeArgumentRefs
.map((t) => buildType(t, typeParameterContext))
.toList();
diff --git a/pkg/analyzer/lib/src/summary/summarize_ast.dart b/pkg/analyzer/lib/src/summary/summarize_ast.dart
index b81fe88..5d35783 100644
--- a/pkg/analyzer/lib/src/summary/summarize_ast.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_ast.dart
@@ -331,7 +331,7 @@
* If the library has a library directive, the annotations for it (if any).
* Otherwise `null`.
*/
- List<UnlinkedConst> libraryAnnotations = const <UnlinkedConstBuilder>[];
+ List<UnlinkedExpr> libraryAnnotations = const <UnlinkedExprBuilder>[];
/**
* The number of slot ids which have been assigned to this compilation unit.
@@ -407,10 +407,10 @@
* Serialize the given list of [annotations]. If there are no annotations,
* the empty list is returned.
*/
- List<UnlinkedConstBuilder> serializeAnnotations(
+ List<UnlinkedExprBuilder> serializeAnnotations(
NodeList<Annotation> annotations) {
if (annotations == null || annotations.isEmpty) {
- return const <UnlinkedConstBuilder>[];
+ return const <UnlinkedExprBuilder>[];
}
return annotations.map((Annotation a) {
// Closures can't appear inside annotations, so we don't need a
@@ -546,9 +546,9 @@
}
/**
- * Serialize the given [expression], creating an [UnlinkedConstBuilder].
+ * Serialize the given [expression], creating an [UnlinkedExprBuilder].
*/
- UnlinkedConstBuilder serializeConstExpr(
+ UnlinkedExprBuilder serializeConstExpr(
Map<int, int> localClosureIndexMap, Expression expression,
[Set<String> parameterNames]) {
_ConstExprSerializer serializer =
diff --git a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
index 18db39f..4662be8 100644
--- a/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
+++ b/pkg/analyzer/lib/src/summary/summarize_const_expr.dart
@@ -15,7 +15,7 @@
*/
UnlinkedConstructorInitializer serializeConstructorInitializer(
ConstructorInitializer node,
- UnlinkedConstBuilder serializeConstExpr(Expression expr)) {
+ UnlinkedExprBuilder serializeConstExpr(Expression expr)) {
if (node is ConstructorFieldInitializer) {
return new UnlinkedConstructorInitializerBuilder(
kind: UnlinkedConstructorInitializerKind.field,
@@ -23,7 +23,7 @@
expression: serializeConstExpr(node.expression));
}
- List<UnlinkedConstBuilder> arguments = <UnlinkedConstBuilder>[];
+ List<UnlinkedExprBuilder> arguments = <UnlinkedExprBuilder>[];
List<String> argumentNames = <String>[];
void serializeArguments(List<Expression> args) {
for (Expression arg in args) {
@@ -61,43 +61,43 @@
*/
abstract class AbstractConstExprSerializer {
/**
- * See [UnlinkedConstBuilder.isValidConst].
+ * See [UnlinkedExprBuilder.isValidConst].
*/
bool isValidConst = true;
/**
- * See [UnlinkedConstBuilder.nmae].
+ * See [UnlinkedExprBuilder.nmae].
*/
String name = null;
/**
- * See [UnlinkedConstBuilder.operations].
+ * See [UnlinkedExprBuilder.operations].
*/
- final List<UnlinkedConstOperation> operations = <UnlinkedConstOperation>[];
+ final List<UnlinkedExprOperation> operations = <UnlinkedExprOperation>[];
/**
- * See [UnlinkedConstBuilder.assignmentOperators].
+ * See [UnlinkedExprBuilder.assignmentOperators].
*/
final List<UnlinkedExprAssignOperator> assignmentOperators =
<UnlinkedExprAssignOperator>[];
/**
- * See [UnlinkedConstBuilder.ints].
+ * See [UnlinkedExprBuilder.ints].
*/
final List<int> ints = <int>[];
/**
- * See [UnlinkedConstBuilder.doubles].
+ * See [UnlinkedExprBuilder.doubles].
*/
final List<double> doubles = <double>[];
/**
- * See [UnlinkedConstBuilder.strings].
+ * See [UnlinkedExprBuilder.strings].
*/
final List<String> strings = <String>[];
/**
- * See [UnlinkedConstBuilder.references].
+ * See [UnlinkedExprBuilder.references].
*/
final List<EntityRefBuilder> references = <EntityRefBuilder>[];
@@ -163,7 +163,7 @@
EntityRefBuilder constructor, ArgumentList argumentList) {
_serializeArguments(argumentList);
references.add(constructor);
- operations.add(UnlinkedConstOperation.invokeConstructor);
+ operations.add(UnlinkedExprOperation.invokeConstructor);
}
/**
@@ -183,11 +183,11 @@
}
/**
- * Return the [UnlinkedConstBuilder] that corresponds to the state of this
+ * Return the [UnlinkedExprBuilder] that corresponds to the state of this
* serializer.
*/
- UnlinkedConstBuilder toBuilder() {
- return new UnlinkedConstBuilder(
+ UnlinkedExprBuilder toBuilder() {
+ return new UnlinkedExprBuilder(
isValidConst: isValidConst,
operations: operations,
assignmentOperators: assignmentOperators,
@@ -232,24 +232,24 @@
if (_isIdentifierSequence(expr)) {
EntityRefBuilder ref = serializeIdentifierSequence(expr);
references.add(ref);
- operations.add(UnlinkedConstOperation.assignToRef);
+ operations.add(UnlinkedExprOperation.assignToRef);
} else if (expr is PropertyAccess) {
if (!expr.isCascaded) {
_serialize(expr.target);
}
strings.add(expr.propertyName.name);
- operations.add(UnlinkedConstOperation.assignToProperty);
+ operations.add(UnlinkedExprOperation.assignToProperty);
} else if (expr is IndexExpression) {
if (!expr.isCascaded) {
_serialize(expr.target);
}
_serialize(expr.index);
- operations.add(UnlinkedConstOperation.assignToIndex);
+ operations.add(UnlinkedExprOperation.assignToIndex);
} else if (expr is PrefixedIdentifier) {
strings.add(expr.prefix.name);
- operations.add(UnlinkedConstOperation.pushParameter);
+ operations.add(UnlinkedExprOperation.pushParameter);
strings.add(expr.identifier.name);
- operations.add(UnlinkedConstOperation.assignToProperty);
+ operations.add(UnlinkedExprOperation.assignToProperty);
} else {
throw new StateError('Unsupported assignable: $expr');
}
@@ -267,11 +267,12 @@
numOfComponents++;
ints.add(value & 0xFFFFFFFF);
}
+
pushComponents(value);
ints[ints.length - 1 - numOfComponents] = numOfComponents;
- operations.add(UnlinkedConstOperation.pushLongInt);
+ operations.add(UnlinkedExprOperation.pushLongInt);
} else {
- operations.add(UnlinkedConstOperation.pushInt);
+ operations.add(UnlinkedExprOperation.pushInt);
ints.add(value);
}
}
@@ -283,34 +284,34 @@
if (expr is IntegerLiteral) {
_pushInt(expr.value);
} else if (expr is DoubleLiteral) {
- operations.add(UnlinkedConstOperation.pushDouble);
+ operations.add(UnlinkedExprOperation.pushDouble);
doubles.add(expr.value);
} else if (expr is BooleanLiteral) {
if (expr.value) {
- operations.add(UnlinkedConstOperation.pushTrue);
+ operations.add(UnlinkedExprOperation.pushTrue);
} else {
- operations.add(UnlinkedConstOperation.pushFalse);
+ operations.add(UnlinkedExprOperation.pushFalse);
}
} else if (expr is StringLiteral) {
_serializeString(expr);
} else if (expr is SymbolLiteral) {
strings.add(expr.components.map((token) => token.lexeme).join('.'));
- operations.add(UnlinkedConstOperation.makeSymbol);
+ operations.add(UnlinkedExprOperation.makeSymbol);
} else if (expr is NullLiteral) {
- operations.add(UnlinkedConstOperation.pushNull);
+ operations.add(UnlinkedExprOperation.pushNull);
} else if (expr is Identifier) {
if (expr is SimpleIdentifier && isParameterName(expr.name)) {
strings.add(expr.name);
- operations.add(UnlinkedConstOperation.pushParameter);
+ operations.add(UnlinkedExprOperation.pushParameter);
} else if (expr is PrefixedIdentifier &&
isParameterName(expr.prefix.name)) {
strings.add(expr.prefix.name);
- operations.add(UnlinkedConstOperation.pushParameter);
+ operations.add(UnlinkedExprOperation.pushParameter);
strings.add(expr.identifier.name);
- operations.add(UnlinkedConstOperation.extractProperty);
+ operations.add(UnlinkedExprOperation.extractProperty);
} else {
references.add(serializeIdentifier(expr));
- operations.add(UnlinkedConstOperation.pushReference);
+ operations.add(UnlinkedExprOperation.pushReference);
}
} else if (expr is InstanceCreationExpression) {
if (!expr.isConst) {
@@ -333,7 +334,7 @@
_serialize(expr.condition);
_serialize(expr.thenExpression);
_serialize(expr.elseExpression);
- operations.add(UnlinkedConstOperation.conditional);
+ operations.add(UnlinkedExprOperation.conditional);
} else if (expr is PrefixExpression) {
_serializePrefixExpression(expr);
} else if (expr is PostfixExpression) {
@@ -346,7 +347,7 @@
isValidConst = false;
_serialize(expr.target);
_serialize(expr.index);
- operations.add(UnlinkedConstOperation.extractIndex);
+ operations.add(UnlinkedExprOperation.extractIndex);
} else if (expr is AssignmentExpression) {
_serializeAssignment(expr);
} else if (expr is CascadeExpression) {
@@ -356,29 +357,29 @@
List<int> indices = serializeFunctionExpression(expr);
if (indices != null) {
ints.addAll(serializeFunctionExpression(expr));
- operations.add(UnlinkedConstOperation.pushLocalFunctionReference);
+ operations.add(UnlinkedExprOperation.pushLocalFunctionReference);
} else {
// Invalid expression; just push null.
- operations.add(UnlinkedConstOperation.pushNull);
+ operations.add(UnlinkedExprOperation.pushNull);
}
} else if (expr is FunctionExpressionInvocation) {
isValidConst = false;
// TODO(scheglov) implement
- operations.add(UnlinkedConstOperation.pushNull);
+ operations.add(UnlinkedExprOperation.pushNull);
} else if (expr is AsExpression) {
isValidConst = false;
_serialize(expr.expression);
references.add(serializeTypeName(expr.type));
- operations.add(UnlinkedConstOperation.typeCast);
+ operations.add(UnlinkedExprOperation.typeCast);
} else if (expr is IsExpression) {
isValidConst = false;
_serialize(expr.expression);
references.add(serializeTypeName(expr.type));
- operations.add(UnlinkedConstOperation.typeCheck);
+ operations.add(UnlinkedExprOperation.typeCheck);
} else if (expr is ThrowExpression) {
isValidConst = false;
_serialize(expr.expression);
- operations.add(UnlinkedConstOperation.throwException);
+ operations.add(UnlinkedExprOperation.throwException);
} else {
throw new StateError('Unknown expression type: $expr');
}
@@ -448,43 +449,43 @@
_serialize(expr.rightOperand);
TokenType operator = expr.operator.type;
if (operator == TokenType.EQ_EQ) {
- operations.add(UnlinkedConstOperation.equal);
+ operations.add(UnlinkedExprOperation.equal);
} else if (operator == TokenType.BANG_EQ) {
- operations.add(UnlinkedConstOperation.notEqual);
+ operations.add(UnlinkedExprOperation.notEqual);
} else if (operator == TokenType.AMPERSAND_AMPERSAND) {
- operations.add(UnlinkedConstOperation.and);
+ operations.add(UnlinkedExprOperation.and);
} else if (operator == TokenType.BAR_BAR) {
- operations.add(UnlinkedConstOperation.or);
+ operations.add(UnlinkedExprOperation.or);
} else if (operator == TokenType.CARET) {
- operations.add(UnlinkedConstOperation.bitXor);
+ operations.add(UnlinkedExprOperation.bitXor);
} else if (operator == TokenType.AMPERSAND) {
- operations.add(UnlinkedConstOperation.bitAnd);
+ operations.add(UnlinkedExprOperation.bitAnd);
} else if (operator == TokenType.BAR) {
- operations.add(UnlinkedConstOperation.bitOr);
+ operations.add(UnlinkedExprOperation.bitOr);
} else if (operator == TokenType.GT_GT) {
- operations.add(UnlinkedConstOperation.bitShiftRight);
+ operations.add(UnlinkedExprOperation.bitShiftRight);
} else if (operator == TokenType.LT_LT) {
- operations.add(UnlinkedConstOperation.bitShiftLeft);
+ operations.add(UnlinkedExprOperation.bitShiftLeft);
} else if (operator == TokenType.PLUS) {
- operations.add(UnlinkedConstOperation.add);
+ operations.add(UnlinkedExprOperation.add);
} else if (operator == TokenType.MINUS) {
- operations.add(UnlinkedConstOperation.subtract);
+ operations.add(UnlinkedExprOperation.subtract);
} else if (operator == TokenType.STAR) {
- operations.add(UnlinkedConstOperation.multiply);
+ operations.add(UnlinkedExprOperation.multiply);
} else if (operator == TokenType.SLASH) {
- operations.add(UnlinkedConstOperation.divide);
+ operations.add(UnlinkedExprOperation.divide);
} else if (operator == TokenType.TILDE_SLASH) {
- operations.add(UnlinkedConstOperation.floorDivide);
+ operations.add(UnlinkedExprOperation.floorDivide);
} else if (operator == TokenType.GT) {
- operations.add(UnlinkedConstOperation.greater);
+ operations.add(UnlinkedExprOperation.greater);
} else if (operator == TokenType.LT) {
- operations.add(UnlinkedConstOperation.less);
+ operations.add(UnlinkedExprOperation.less);
} else if (operator == TokenType.GT_EQ) {
- operations.add(UnlinkedConstOperation.greaterEqual);
+ operations.add(UnlinkedExprOperation.greaterEqual);
} else if (operator == TokenType.LT_EQ) {
- operations.add(UnlinkedConstOperation.lessEqual);
+ operations.add(UnlinkedExprOperation.lessEqual);
} else if (operator == TokenType.PERCENT) {
- operations.add(UnlinkedConstOperation.modulo);
+ operations.add(UnlinkedExprOperation.modulo);
} else {
throw new StateError('Unknown operator: $operator');
}
@@ -493,9 +494,9 @@
void _serializeCascadeExpression(CascadeExpression expr) {
_serialize(expr.target);
for (Expression section in expr.cascadeSections) {
- operations.add(UnlinkedConstOperation.cascadeSectionBegin);
+ operations.add(UnlinkedExprOperation.cascadeSectionBegin);
_serialize(section);
- operations.add(UnlinkedConstOperation.cascadeSectionEnd);
+ operations.add(UnlinkedExprOperation.cascadeSectionEnd);
}
}
@@ -506,9 +507,9 @@
if (expr.typeArguments != null &&
expr.typeArguments.arguments.length == 1) {
references.add(serializeTypeName(expr.typeArguments.arguments[0]));
- operations.add(UnlinkedConstOperation.makeTypedList);
+ operations.add(UnlinkedExprOperation.makeTypedList);
} else {
- operations.add(UnlinkedConstOperation.makeUntypedList);
+ operations.add(UnlinkedExprOperation.makeUntypedList);
}
}
@@ -522,9 +523,9 @@
expr.typeArguments.arguments.length == 2) {
references.add(serializeTypeName(expr.typeArguments.arguments[0]));
references.add(serializeTypeName(expr.typeArguments.arguments[1]));
- operations.add(UnlinkedConstOperation.makeTypedMap);
+ operations.add(UnlinkedExprOperation.makeTypedMap);
} else {
- operations.add(UnlinkedConstOperation.makeUntypedMap);
+ operations.add(UnlinkedExprOperation.makeUntypedMap);
}
}
@@ -541,7 +542,7 @@
_serializeArguments(argumentList);
references.add(ref);
_serializeTypeArguments(invocation.typeArguments);
- operations.add(UnlinkedConstOperation.invokeMethodRef);
+ operations.add(UnlinkedExprOperation.invokeMethodRef);
} else {
if (!invocation.isCascaded) {
_serialize(target);
@@ -549,7 +550,7 @@
_serializeArguments(argumentList);
strings.add(methodName.name);
_serializeTypeArguments(invocation.typeArguments);
- operations.add(UnlinkedConstOperation.invokeMethod);
+ operations.add(UnlinkedExprOperation.invokeMethod);
}
}
@@ -572,13 +573,13 @@
Expression operand = expr.operand;
if (operator == TokenType.BANG) {
_serialize(operand);
- operations.add(UnlinkedConstOperation.not);
+ operations.add(UnlinkedExprOperation.not);
} else if (operator == TokenType.MINUS) {
_serialize(operand);
- operations.add(UnlinkedConstOperation.negate);
+ operations.add(UnlinkedExprOperation.negate);
} else if (operator == TokenType.TILDE) {
_serialize(operand);
- operations.add(UnlinkedConstOperation.complement);
+ operations.add(UnlinkedExprOperation.complement);
} else if (operator == TokenType.PLUS_PLUS) {
_serializePrefixPostfixIncDec(
operand, UnlinkedExprAssignOperator.prefixIncrement);
@@ -601,38 +602,38 @@
if (_isIdentifierSequence(expr)) {
EntityRefBuilder ref = serializeIdentifierSequence(expr);
references.add(ref);
- operations.add(UnlinkedConstOperation.pushReference);
+ operations.add(UnlinkedExprOperation.pushReference);
} else {
_serialize(expr.target);
strings.add(expr.propertyName.name);
- operations.add(UnlinkedConstOperation.extractProperty);
+ operations.add(UnlinkedExprOperation.extractProperty);
}
}
void _serializeString(StringLiteral expr) {
if (expr is AdjacentStrings) {
if (expr.strings.every((string) => string is SimpleStringLiteral)) {
- operations.add(UnlinkedConstOperation.pushString);
+ operations.add(UnlinkedExprOperation.pushString);
strings.add(expr.stringValue);
} else {
expr.strings.forEach(_serializeString);
- operations.add(UnlinkedConstOperation.concatenate);
+ operations.add(UnlinkedExprOperation.concatenate);
ints.add(expr.strings.length);
}
} else if (expr is SimpleStringLiteral) {
- operations.add(UnlinkedConstOperation.pushString);
+ operations.add(UnlinkedExprOperation.pushString);
strings.add(expr.value);
} else {
StringInterpolation interpolation = expr as StringInterpolation;
for (InterpolationElement element in interpolation.elements) {
if (element is InterpolationString) {
- operations.add(UnlinkedConstOperation.pushString);
+ operations.add(UnlinkedExprOperation.pushString);
strings.add(element.value);
} else {
_serialize((element as InterpolationExpression).expression);
}
}
- operations.add(UnlinkedConstOperation.concatenate);
+ operations.add(UnlinkedExprOperation.concatenate);
ints.add(interpolation.elements.length);
}
}
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 60a6dbc..eb7455d 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -63,6 +63,7 @@
static const String errors = 'errors';
static const String exclude = 'exclude';
+ static const String include = 'include';
static const String language = 'language';
static const String plugins = 'plugins';
static const String strong_mode = 'strong-mode';
@@ -228,10 +229,12 @@
<ResultDescriptor>[ANALYSIS_OPTIONS_ERRORS, LINE_INFO],
suitabilityFor: suitabilityFor);
- final AnalysisOptionsProvider optionsProvider = new AnalysisOptionsProvider();
+ AnalysisOptionsProvider optionsProvider;
GenerateOptionsErrorsTask(AnalysisContext context, AnalysisTarget target)
- : super(context, target);
+ : super(context, target) {
+ optionsProvider = new AnalysisOptionsProvider(context?.sourceFactory);
+ }
@override
TaskDescriptor get descriptor => DESCRIPTOR;
@@ -243,16 +246,80 @@
String content = getRequiredInput(CONTENT_INPUT_NAME);
List<AnalysisError> errors = <AnalysisError>[];
+ Source initialSource = source;
+ SourceSpan initialIncludeSpan;
+
+ // Validate the specified options and any included option files
+ void validate(Source source, Map<String, YamlNode> options) {
+ List<AnalysisError> validationErrors =
+ new OptionsFileValidator(source).validate(options);
+ if (initialIncludeSpan != null && validationErrors.isNotEmpty) {
+ for (AnalysisError error in validationErrors) {
+ var args = [
+ source.fullName,
+ error.offset.toString(),
+ (error.offset + error.length - 1).toString(),
+ error.message,
+ ];
+ errors.add(new AnalysisError(
+ initialSource,
+ initialIncludeSpan.start.column + 1,
+ initialIncludeSpan.length,
+ AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING,
+ args));
+ }
+ } else {
+ errors.addAll(validationErrors);
+ }
+
+ YamlNode node = options[AnalyzerOptions.include];
+ if (node == null) {
+ return;
+ }
+ SourceSpan span = node.span;
+ initialIncludeSpan ??= span;
+ String includeUri = span.text;
+ Source includedSource =
+ context.sourceFactory.resolveUri(source, includeUri);
+ if (!includedSource.exists()) {
+ errors.add(new AnalysisError(
+ initialSource,
+ initialIncludeSpan.start.column + 1,
+ initialIncludeSpan.length,
+ AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND,
+ [includeUri, source.fullName]));
+ return;
+ }
+ try {
+ Map<String, YamlNode> options =
+ optionsProvider.getOptionsFromString(includedSource.contents.data);
+ validate(includedSource, options);
+ } on OptionsFormatException catch (e) {
+ var args = [
+ includedSource.fullName,
+ e.span.start.offset.toString(),
+ e.span.end.offset.toString(),
+ e.message,
+ ];
+ // Report errors for included option files
+ // on the include directive located in the initial options file.
+ errors.add(new AnalysisError(
+ initialSource,
+ initialIncludeSpan.start.column + 1,
+ initialIncludeSpan.length,
+ AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR,
+ args));
+ }
+ }
try {
Map<String, YamlNode> options =
optionsProvider.getOptionsFromString(content);
- errors.addAll(_validate(options));
+ validate(source, options);
} on OptionsFormatException catch (e) {
SourceSpan span = e.span;
- var error = new AnalysisError(source, span.start.column + 1, span.length,
- AnalysisOptionsErrorCode.PARSE_ERROR, [e.message]);
- errors.add(error);
+ errors.add(new AnalysisError(source, span.start.column + 1, span.length,
+ AnalysisOptionsErrorCode.PARSE_ERROR, [e.message]));
}
//
@@ -262,9 +329,6 @@
outputs[LINE_INFO] = computeLineInfo(content);
}
- List<AnalysisError> _validate(Map<String, YamlNode> options) =>
- new OptionsFileValidator(source).validate(options);
-
/// Return a map from the names of the inputs of this kind of task to the
/// task input descriptors describing those inputs for a task with the
/// given [target].
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index 869d7e0..eeaf82d 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -101,6 +101,33 @@
checkMetadata('export');
}
+ void test_metadata_exportDirective_resynthesized() {
+ CompilationUnit unit = resolveSource(r'''
+@a
+export "dart:async";
+
+@b
+export "dart:math";
+
+const a = null;
+const b = null;
+''');
+ expect(unit.directives[0].metadata.single.name.name, 'a');
+ expect(unit.directives[1].metadata.single.name.name, 'b');
+ var unitElement = unit.element as CompilationUnitElementImpl;
+ // Damage the unit element - as if "setAnnotations" were not called.
+ // The ExportElement(s) still have the metadata, we should use it.
+ unitElement.setAnnotations(unit.directives[0].offset, []);
+ unitElement.setAnnotations(unit.directives[1].offset, []);
+ expect(unitElement.library.exports[0].metadata, hasLength(1));
+ expect(unitElement.library.exports[1].metadata, hasLength(1));
+ // DeclarationResolver on the clone should succeed.
+ CompilationUnit clonedUnit = AstCloner.clone(unit);
+ new DeclarationResolver().resolve(clonedUnit, unit.element);
+ expect(unit.directives[0].metadata.single.name.name, 'a');
+ expect(unit.directives[1].metadata.single.name.name, 'b');
+ }
+
void test_metadata_fieldDeclaration() {
setupCode('class C { @a int x; }');
checkMetadata('x');
@@ -163,6 +190,33 @@
checkMetadata('import');
}
+ void test_metadata_importDirective_resynthesized() {
+ CompilationUnit unit = resolveSource(r'''
+@a
+import "dart:async";
+
+@b
+import "dart:math";
+
+const a = null;
+const b = null;
+''');
+ expect(unit.directives[0].metadata.single.name.name, 'a');
+ expect(unit.directives[1].metadata.single.name.name, 'b');
+ var unitElement = unit.element as CompilationUnitElementImpl;
+ // Damage the unit element - as if "setAnnotations" were not called.
+ // The ImportElement(s) still have the metadata, we should use it.
+ unitElement.setAnnotations(unit.directives[0].offset, []);
+ unitElement.setAnnotations(unit.directives[1].offset, []);
+ expect(unitElement.library.imports[0].metadata, hasLength(1));
+ expect(unitElement.library.imports[1].metadata, hasLength(1));
+ // DeclarationResolver on the clone should succeed.
+ CompilationUnit clonedUnit = AstCloner.clone(unit);
+ new DeclarationResolver().resolve(clonedUnit, unit.element);
+ expect(unit.directives[0].metadata.single.name.name, 'a');
+ expect(unit.directives[1].metadata.single.name.name, 'b');
+ }
+
void test_metadata_libraryDirective() {
setupCode('@a library L;');
checkMetadata('L');
diff --git a/pkg/analyzer/test/source/config_test.dart b/pkg/analyzer/test/source/config_test.dart
deleted file mode 100644
index 6ce08cd..0000000
--- a/pkg/analyzer/test/source/config_test.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/source/config.dart';
-import 'package:test/test.dart';
-import 'package:yaml/yaml.dart';
-
-main() {
- group('Analysis Config', () {
- test('parseConfigSource', () {
- String source = r'''
-analyzer:
- configuration: google/strict
-''';
- YamlMap options = loadYamlNode(source);
- AnalysisConfigurationDescriptor descriptor =
- new AnalysisConfigurationDescriptor.fromAnalyzerOptions(
- options['analyzer']);
- expect(descriptor.package, 'google');
- expect(descriptor.pragma, 'strict');
- });
- });
-}
diff --git a/pkg/analyzer/test/source/test_all.dart b/pkg/analyzer/test/source/test_all.dart
index 98f3cde..a995c9b 100644
--- a/pkg/analyzer/test/source/test_all.dart
+++ b/pkg/analyzer/test/source/test_all.dart
@@ -7,7 +7,6 @@
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'analysis_options_provider_test.dart' as analysis_options_provider_test;
-import 'config_test.dart' as config_test;
import 'embedder_test.dart' as embedder_test;
import 'error_processor_test.dart' as error_processor_test;
import 'package_map_provider_test.dart' as package_map_provider_test;
@@ -19,7 +18,6 @@
main() {
defineReflectiveSuite(() {
analysis_options_provider_test.main();
- config_test.main();
embedder_test.main();
error_processor_test.main();
package_map_provider_test.main();
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
new file mode 100644
index 0000000..2ef6802
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -0,0 +1,360 @@
+// 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:convert';
+import 'dart:typed_data';
+
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/memory_file_system.dart';
+import 'package:analyzer/source/package_map_resolver.dart';
+import 'package:analyzer/src/dart/analysis/byte_store.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart' show PerformanceLog;
+import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisOptions, AnalysisOptionsImpl;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/fast_uri.dart';
+import 'package:convert/convert.dart';
+import 'package:crypto/crypto.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../context/mock_sdk.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FileSystemStateTest);
+ });
+}
+
+@reflectiveTest
+class FileSystemStateTest {
+ static final MockSdk sdk = new MockSdk();
+
+ final MemoryResourceProvider provider = new MemoryResourceProvider();
+ final ByteStore byteStore = new MemoryByteStore();
+ final FileContentOverlay contentOverlay = new FileContentOverlay();
+
+ final StringBuffer logBuffer = new StringBuffer();
+ PerformanceLog logger;
+
+ FileSystemState fileSystemState;
+
+ void setUp() {
+ logger = new PerformanceLog(logBuffer);
+ SourceFactory sourceFactory = new SourceFactory([
+ new DartUriResolver(sdk),
+ new PackageMapUriResolver(provider, <String, List<Folder>>{
+ 'aaa': [provider.getFolder(_p('/aaa/lib'))],
+ 'bbb': [provider.getFolder(_p('/bbb/lib'))],
+ }),
+ new ResourceUriResolver(provider)
+ ], null, provider);
+ AnalysisOptions analysisOptions = new AnalysisOptionsImpl()
+ ..strongMode = true;
+ fileSystemState = new FileSystemState(logger, byteStore, contentOverlay,
+ provider, sourceFactory, analysisOptions, new Uint32List(0));
+ }
+
+ test_getFileForPath_doesNotExist() {
+ String path = _p('/aaa/lib/a.dart');
+ FileState file = fileSystemState.getFileForPath(path);
+ expect(file.path, path);
+ expect(file.uri, FastUri.parse('package:aaa/a.dart'));
+ expect(file.content, '');
+ expect(file.contentHash, _md5(''));
+ expect(file.importedFiles, isEmpty);
+ expect(file.exportedFiles, isEmpty);
+ expect(file.partedFiles, isEmpty);
+ expect(file.directReferencedFiles, isEmpty);
+ expect(file.isPart, isFalse);
+ expect(file.library, isNull);
+ expect(file.unlinked, isNotNull);
+ expect(file.unlinked.classes, isEmpty);
+ }
+
+ test_getFileForPath_library() {
+ String a1 = _p('/aaa/lib/a1.dart');
+ String a2 = _p('/aaa/lib/a2.dart');
+ String a3 = _p('/aaa/lib/a3.dart');
+ String a4 = _p('/aaa/lib/a4.dart');
+ String b1 = _p('/bbb/lib/b1.dart');
+ String b2 = _p('/bbb/lib/b2.dart');
+ String content_a1 = r'''
+import 'package:aaa/a2.dart';
+import 'package:bbb/b1.dart';
+export 'package:bbb/b2.dart';
+export 'package:aaa/a3.dart';
+part 'a4.dart';
+
+class A1 {}
+''';
+ provider.newFile(a1, content_a1);
+
+ FileState file = fileSystemState.getFileForPath(a1);
+ expect(file.path, a1);
+ expect(file.content, content_a1);
+ expect(file.contentHash, _md5(content_a1));
+
+ expect(file.isPart, isFalse);
+ expect(file.library, isNull);
+ expect(file.unlinked, isNotNull);
+ expect(file.unlinked.classes, hasLength(1));
+ expect(file.unlinked.classes[0].name, 'A1');
+
+ expect(file.importedFiles, hasLength(2));
+ expect(file.importedFiles[0].path, a2);
+ expect(file.importedFiles[0].uri, FastUri.parse('package:aaa/a2.dart'));
+ expect(file.importedFiles[0].source, isNotNull);
+ expect(file.importedFiles[1].path, b1);
+ expect(file.importedFiles[1].uri, FastUri.parse('package:bbb/b1.dart'));
+ expect(file.importedFiles[1].source, isNotNull);
+
+ expect(file.exportedFiles, hasLength(2));
+ expect(file.exportedFiles[0].path, b2);
+ expect(file.exportedFiles[0].uri, FastUri.parse('package:bbb/b2.dart'));
+ expect(file.exportedFiles[0].source, isNotNull);
+ expect(file.exportedFiles[1].path, a3);
+ expect(file.exportedFiles[1].uri, FastUri.parse('package:aaa/a3.dart'));
+ expect(file.exportedFiles[1].source, isNotNull);
+
+ expect(file.partedFiles, hasLength(1));
+ expect(file.partedFiles[0].path, a4);
+ expect(file.partedFiles[0].uri, FastUri.parse('package:aaa/a4.dart'));
+
+ expect(file.directReferencedFiles, hasLength(5));
+
+ expect(fileSystemState.getFilesForPath(a1), [file]);
+ }
+
+ test_getFileForPath_part() {
+ String a1 = _p('/aaa/lib/a1.dart');
+ String a2 = _p('/aaa/lib/a2.dart');
+ provider.newFile(
+ a1,
+ r'''
+library a1;
+part 'a2.dart';
+''');
+ provider.newFile(
+ a2,
+ r'''
+part of a1;
+class A2 {}
+''');
+
+ FileState file_a2 = fileSystemState.getFileForPath(a2);
+ expect(file_a2.path, a2);
+ expect(file_a2.uri, FastUri.parse('package:aaa/a2.dart'));
+
+ expect(file_a2.unlinked, isNotNull);
+ expect(file_a2.unlinked.classes, hasLength(1));
+ expect(file_a2.unlinked.classes[0].name, 'A2');
+
+ expect(file_a2.importedFiles, isEmpty);
+ expect(file_a2.exportedFiles, isEmpty);
+ expect(file_a2.partedFiles, isEmpty);
+ expect(file_a2.directReferencedFiles, isEmpty);
+
+ // The library is not known yet.
+ expect(file_a2.isPart, isTrue);
+ expect(file_a2.library, isNull);
+
+ // Ask for the library.
+ FileState file_a1 = fileSystemState.getFileForPath(a1);
+ expect(file_a1.partedFiles, hasLength(1));
+ expect(file_a1.partedFiles[0], same(file_a2));
+ expect(file_a1.directReferencedFiles, unorderedEquals([file_a2]));
+
+ // Now the part knows its library.
+ expect(file_a2.library, same(file_a1));
+
+ // Now update the library, and refresh its file.
+ // The 'a2.dart' is not referenced anymore.
+ // So the part file does not have the library anymore.
+ provider.newFile(
+ a1,
+ r'''
+library a1;
+part 'not-a2.dart';
+''');
+ file_a1.refresh();
+ expect(file_a2.library, isNull);
+ }
+
+ test_getFileForPath_samePath() {
+ String path = _p('/aaa/lib/a.dart');
+ FileState file1 = fileSystemState.getFileForPath(path);
+ FileState file2 = fileSystemState.getFileForPath(path);
+ expect(file2, same(file1));
+ }
+
+ test_getFileForUri_packageVsFileUri() {
+ String path = _p('/aaa/lib/a.dart');
+ var packageUri = FastUri.parse('package:aaa/a.dart');
+ var fileUri = provider.pathContext.toUri(path);
+
+ // The files with `package:` and `file:` URIs are different.
+ FileState filePackageUri = fileSystemState.getFileForUri(packageUri);
+ FileState fileFileUri = fileSystemState.getFileForUri(fileUri);
+ expect(filePackageUri, isNot(same(fileFileUri)));
+
+ expect(filePackageUri.path, path);
+ expect(filePackageUri.uri, packageUri);
+
+ expect(fileFileUri.path, path);
+ expect(fileFileUri.uri, fileUri);
+
+ // The file with the `package:` style URI is canonical, and is the first.
+ var files = fileSystemState.getFilesForPath(path);
+ expect(files, [filePackageUri, fileFileUri]);
+ }
+
+ test_refresh_differentApiSignature() {
+ String path = _p('/aaa/lib/a.dart');
+ provider.newFile(
+ path,
+ r'''
+class A {}
+''');
+ FileState file = fileSystemState.getFileForPath(path);
+ expect(file.unlinked.classes[0].name, 'A');
+ List<int> signature = file.apiSignature;
+
+ // Update the resource and refresh the file state.
+ provider.newFile(
+ path,
+ r'''
+class B {}
+''');
+ bool apiSignatureChanged = file.refresh();
+ expect(apiSignatureChanged, isTrue);
+
+ expect(file.unlinked.classes[0].name, 'B');
+ expect(file.apiSignature, isNot(signature));
+ }
+
+ test_refresh_sameApiSignature() {
+ String path = _p('/aaa/lib/a.dart');
+ provider.newFile(
+ path,
+ r'''
+class C {
+ foo() {
+ print(111);
+ }
+}
+''');
+ FileState file = fileSystemState.getFileForPath(path);
+ List<int> signature = file.apiSignature;
+
+ // Update the resource and refresh the file state.
+ provider.newFile(
+ path,
+ r'''
+class C {
+ foo() {
+ print(222);
+ }
+}
+''');
+ bool apiSignatureChanged = file.refresh();
+ expect(apiSignatureChanged, isFalse);
+
+ expect(file.apiSignature, signature);
+ }
+
+ test_transitiveFiles() {
+ String pa = _p('/aaa/lib/a.dart');
+ String pb = _p('/aaa/lib/b.dart');
+ String pc = _p('/aaa/lib/c.dart');
+ String pd = _p('/aaa/lib/d.dart');
+
+ FileState fa = fileSystemState.getFileForPath(pa);
+ FileState fb = fileSystemState.getFileForPath(pb);
+ FileState fc = fileSystemState.getFileForPath(pc);
+ FileState fd = fileSystemState.getFileForPath(pd);
+
+ // Compute transitive closures for all files.
+ fa.transitiveFiles;
+ fb.transitiveFiles;
+ fc.transitiveFiles;
+ fd.transitiveFiles;
+ expect(fileSystemState.test.filesWithoutTransitive, isEmpty);
+
+ // No imports, so just a single file.
+ provider.newFile(pa, "");
+ _assertTransitiveFiles(fa, [fa]);
+
+ // Import b.dart into a.dart, two files now.
+ provider.newFile(pa, "import 'b.dart';");
+ fa.refresh();
+ _assertFilesWithoutTransitive([fa]);
+ _assertTransitiveFiles(fa, [fa, fb]);
+
+ // Update b.dart so that it imports c.dart now.
+ provider.newFile(pb, "import 'c.dart';");
+ fb.refresh();
+ _assertFilesWithoutTransitive([fa, fb]);
+ _assertTransitiveFiles(fa, [fa, fb, fc]);
+ _assertTransitiveFiles(fb, [fb, fc]);
+ _assertFilesWithoutTransitive([]);
+
+ // Update b.dart so that it exports d.dart instead.
+ provider.newFile(pb, "export 'd.dart';");
+ fb.refresh();
+ _assertFilesWithoutTransitive([fa, fb]);
+ _assertTransitiveFiles(fa, [fa, fb, fd]);
+ _assertTransitiveFiles(fb, [fb, fd]);
+ _assertFilesWithoutTransitive([]);
+
+ // Update a.dart so that it does not import b.dart anymore.
+ provider.newFile(pa, "");
+ fa.refresh();
+ _assertFilesWithoutTransitive([fa]);
+ _assertTransitiveFiles(fa, [fa]);
+ }
+
+ test_transitiveFiles_cycle() {
+ String pa = _p('/aaa/lib/a.dart');
+ String pb = _p('/aaa/lib/b.dart');
+
+ provider.newFile(pa, "import 'b.dart';");
+ provider.newFile(pb, "import 'a.dart';");
+
+ FileState fa = fileSystemState.getFileForPath(pa);
+ FileState fb = fileSystemState.getFileForPath(pb);
+
+ // Compute transitive closures for all files.
+ fa.transitiveFiles;
+ fb.transitiveFiles;
+ _assertFilesWithoutTransitive([]);
+
+ // It's a cycle.
+ _assertTransitiveFiles(fa, [fa, fb]);
+ _assertTransitiveFiles(fb, [fa, fb]);
+
+ // Update a.dart so that it does not import b.dart anymore.
+ provider.newFile(pa, "");
+ fa.refresh();
+ _assertFilesWithoutTransitive([fa, fb]);
+ _assertTransitiveFiles(fa, [fa]);
+ _assertTransitiveFiles(fb, [fa, fb]);
+ }
+
+ void _assertFilesWithoutTransitive(List<FileState> expected) {
+ var actual = fileSystemState.test.filesWithoutTransitive;
+ expect(actual, unorderedEquals(expected));
+ }
+
+ void _assertTransitiveFiles(FileState file, List<FileState> expected) {
+ expect(file.transitiveFiles, unorderedEquals(expected));
+ }
+
+ String _p(String path) => provider.convertPath(path);
+
+ static String _md5(String content) {
+ return hex.encode(md5.convert(UTF8.encode(content)).bytes);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
new file mode 100644
index 0000000..ee43d8d
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
@@ -0,0 +1,390 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/referenced_names.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../generated/parser_test.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ReferencedNamesBuilderTest);
+ });
+}
+
+@reflectiveTest
+class ReferencedNamesBuilderTest {
+ test_class_constructor() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ U.named(A a, B b) {
+ C c = null;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_class_field() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ A f = new B();
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_class_getter() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ A get a => new B();
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_class_members() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ int a;
+ int get b;
+ set c(_) {}
+ m(D d) {
+ a;
+ b;
+ c = 1;
+ m();
+ }
+}
+''');
+ expect(names, unorderedEquals(['int', 'D']));
+ }
+
+ test_class_members_dontHideQualified() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ int a;
+ int get b;
+ set c(_) {}
+ m(D d) {
+ d.a;
+ d.b;
+ d.c;
+ }
+}
+''');
+ expect(names, unorderedEquals(['int', 'D', 'a', 'b', 'c']));
+ }
+
+ test_class_method() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ A m(B p) {
+ C v = 0;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_class_method_localVariables() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ A m() {
+ B b = null;
+ b;
+ {
+ C c = null;
+ b;
+ c;
+ }
+ d;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'd']));
+ }
+
+ test_class_method_parameters() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ m(A a) {
+ a;
+ b;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'b']));
+ }
+
+ test_class_method_typeParameters() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ A m<T>(B b, T t) {
+ C c = 0;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_class_setter() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ set a(A a) {
+ B b = null;
+ }
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_class_typeParameters() {
+ Set<String> names = _computeReferencedNames('''
+class U<T> {
+ T f = new A<T>();
+}
+''');
+ expect(names, unorderedEquals(['A']));
+ }
+
+ test_instantiatedNames_importPrefix() {
+ Set<String> names = _computeReferencedNames('''
+import 'a.dart' as p1;
+import 'b.dart' as p2;
+main() {
+ new p1.A();
+ new p1.A.c1();
+ new p1.B();
+ new p2.C();
+ new D();
+ new D.c2();
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'D', 'c1', 'c2']));
+ }
+
+ test_localFunction() {
+ Set<String> names = _computeReferencedNames('''
+f(A a) {
+ g(B b) {}
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_superToSubs_importPrefix() {
+ Set<String> names = _computeReferencedNames('''
+import 'a.dart' as p1;
+import 'b.dart' as p2;
+class U extends p1.A with p2.B implements p2.C {}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_topLevelVariable() {
+ Set<String> names = _computeReferencedNames('''
+A v = new B(c);
+''');
+ expect(names, unorderedEquals(['A', 'B', 'c']));
+ }
+
+ test_topLevelVariable_multiple() {
+ Set<String> names = _computeReferencedNames('''
+A v1 = new B(c), v2 = new D<E>(f);
+''');
+ expect(names, unorderedEquals(['A', 'B', 'c', 'D', 'E', 'f']));
+ }
+
+ test_unit_classTypeAlias() {
+ Set<String> names = _computeReferencedNames('''
+class U = A with B implements C;
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_unit_classTypeAlias_typeParameters() {
+ Set<String> names = _computeReferencedNames('''
+class U<T1, T2 extends D> = A<T1> with B<T2> implements C<T1, T2>;
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'D']));
+ }
+
+ test_unit_function() {
+ Set<String> names = _computeReferencedNames('''
+A f(B b) {
+ C c = 0;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_unit_function_doc() {
+ Set<String> names = _computeReferencedNames('''
+/**
+ * Documentation [C.d] reference.
+ */
+A f(B b) {}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'd']));
+ }
+
+ test_unit_function_dontHideQualified() {
+ Set<String> names = _computeReferencedNames('''
+class U {
+ int a;
+ int get b;
+ set c(_) {}
+ m(D d) {
+ d.a;
+ d.b;
+ d.c;
+ }
+}
+''');
+ expect(names, unorderedEquals(['int', 'D', 'a', 'b', 'c']));
+ }
+
+ test_unit_function_localFunction_parameter() {
+ Set<String> names = _computeReferencedNames('''
+A f() {
+ B g(x) {
+ x;
+ return null;
+ }
+ return null;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_unit_function_localFunctions() {
+ Set<String> names = _computeReferencedNames('''
+A f() {
+ B b = null;
+ C g() {}
+ g();
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_unit_function_localsDontHideQualified() {
+ Set<String> names = _computeReferencedNames('''
+f(A a, B b) {
+ var v = 0;
+ a.v;
+ a.b;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'v', 'b']));
+ }
+
+ test_unit_function_localVariables() {
+ Set<String> names = _computeReferencedNames('''
+A f() {
+ B b = null;
+ b;
+ {
+ C c = null;
+ b;
+ c;
+ }
+ d;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'd']));
+ }
+
+ test_unit_function_parameters() {
+ Set<String> names = _computeReferencedNames('''
+A f(B b) {
+ C c = 0;
+ b;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_unit_function_parameters_dontHideQualified() {
+ Set<String> names = _computeReferencedNames('''
+f(x, C g()) {
+ g().x;
+}
+''');
+ expect(names, unorderedEquals(['C', 'x']));
+ }
+
+ test_unit_function_typeParameters() {
+ Set<String> names = _computeReferencedNames('''
+A f<T>(B b, T t) {
+ C c = 0;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ test_unit_functionTypeAlias() {
+ Set<String> names = _computeReferencedNames('''
+typedef A F(B B, C c(D d));
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C', 'D']));
+ }
+
+ test_unit_functionTypeAlias_typeParameters() {
+ Set<String> names = _computeReferencedNames('''
+typedef A F<T>(B b, T t);
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_unit_getter() {
+ Set<String> names = _computeReferencedNames('''
+A get aaa {
+ return new B();
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_unit_setter() {
+ Set<String> names = _computeReferencedNames('''
+set aaa(A a) {
+ B b = null;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B']));
+ }
+
+ test_unit_topLevelDeclarations() {
+ Set<String> names = _computeReferencedNames('''
+class L1 {}
+class L2 = A with B implements C;
+A L3() => null;
+typedef A L4(B b);
+A get L5 => null;
+set L6(_) {}
+A L7, L8;
+main() {
+ L1;
+ L2;
+ L3;
+ L4;
+ L5;
+ L6;
+ L7;
+ L8;
+}
+''');
+ expect(names, unorderedEquals(['A', 'B', 'C']));
+ }
+
+ Set<String> _computeReferencedNames(String code) {
+ CompilationUnit unit =
+ ParserTestCase.parseCompilationUnit2(code, parseGenericMethods: true);
+ return computeReferencedNames(unit);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/analysis/test_all.dart b/pkg/analyzer/test/src/dart/analysis/test_all.dart
index 346ac5a..0ba933e 100644
--- a/pkg/analyzer/test/src/dart/analysis/test_all.dart
+++ b/pkg/analyzer/test/src/dart/analysis/test_all.dart
@@ -8,11 +8,15 @@
import 'byte_store_test.dart' as byte_store;
import 'driver_test.dart' as driver;
+import 'file_state_test.dart' as file_state;
+import 'referenced_names_test.dart' as referenced_names;
/// Utility for manually running all tests.
main() {
defineReflectiveSuite(() {
byte_store.main();
driver.main();
+ file_state.main();
+ referenced_names.main();
}, name: 'analysis');
}
diff --git a/pkg/analyzer/test/src/summary/linker_test.dart b/pkg/analyzer/test/src/summary/linker_test.dart
index 2a0706c..cd70c5d 100644
--- a/pkg/analyzer/test/src/summary/linker_test.dart
+++ b/pkg/analyzer/test/src/summary/linker_test.dart
@@ -351,6 +351,20 @@
'(D) → E');
}
+ void test_inferredType_instanceField_conditional_genericFunctions() {
+ createLinker('''
+class C {
+ final f = true ? <T>(T t) => 0 : <T>(T t) => 1;
+}
+''');
+ LibraryElementForLink library = linker.getLibrary(linkerInputs.testDartUri);
+ library.libraryCycleForLink.ensureLinked();
+ ClassElementForLink_Class cls = library.getContainedName('C');
+ expect(cls.fields, hasLength(1));
+ var field = cls.fields[0];
+ expect(field.type.toString(), '(<bottom>) → dynamic');
+ }
+
void test_inferredType_instanceField_dynamic() {
createLinker('''
var x;
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index bf040c6..664882b 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -2590,6 +2590,27 @@
''');
}
+ test_constructor_redirected_factory_named_unresolved_class() {
+ checkLibrary(
+ '''
+class C<E> {
+ factory C() = D.named<E>;
+}
+''',
+ allowErrors: true);
+ }
+
+ test_constructor_redirected_factory_named_unresolved_constructor() {
+ checkLibrary(
+ '''
+class D {}
+class C<E> {
+ factory C() = D.named<E>;
+}
+''',
+ allowErrors: true);
+ }
+
test_constructor_redirected_factory_unnamed() {
checkLibrary('''
class C {
@@ -2686,6 +2707,16 @@
''');
}
+ test_constructor_redirected_factory_unnamed_unresolved() {
+ checkLibrary(
+ '''
+class C<E> {
+ factory C() = D<E>;
+}
+''',
+ allowErrors: true);
+ }
+
test_constructor_redirected_thisInvocation_named() {
checkLibrary('''
class C {
diff --git a/pkg/analyzer/test/src/summary/summary_common.dart b/pkg/analyzer/test/src/summary/summary_common.dart
index 8b90c3c..018d86d 100644
--- a/pkg/analyzer/test/src/summary/summary_common.dart
+++ b/pkg/analyzer/test/src/summary/summary_common.dart
@@ -179,10 +179,10 @@
* Check that [annotations] contains a single entry which is a reference to
* a top level variable called `a` in the current library.
*/
- void checkAnnotationA(List<UnlinkedConst> annotations) {
+ void checkAnnotationA(List<UnlinkedExpr> annotations) {
expect(annotations, hasLength(1));
_assertUnlinkedConst(annotations[0], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'a',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -1547,9 +1547,9 @@
test_constExpr_binary_add() {
UnlinkedVariable variable = serializeVariableText('const v = 1 + 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add
], ints: [
1,
2
@@ -1560,18 +1560,18 @@
UnlinkedVariable variable =
serializeVariableText('const v = true && false;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushTrue,
- UnlinkedConstOperation.pushFalse,
- UnlinkedConstOperation.and
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushFalse,
+ UnlinkedExprOperation.and
]);
}
test_constExpr_binary_bitAnd() {
UnlinkedVariable variable = serializeVariableText('const v = 1 & 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.bitAnd
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.bitAnd
], ints: [
1,
2
@@ -1581,9 +1581,9 @@
test_constExpr_binary_bitOr() {
UnlinkedVariable variable = serializeVariableText('const v = 1 | 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.bitOr
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.bitOr
], ints: [
1,
2
@@ -1593,9 +1593,9 @@
test_constExpr_binary_bitShiftLeft() {
UnlinkedVariable variable = serializeVariableText('const v = 1 << 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.bitShiftLeft
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.bitShiftLeft
], ints: [
1,
2
@@ -1605,9 +1605,9 @@
test_constExpr_binary_bitShiftRight() {
UnlinkedVariable variable = serializeVariableText('const v = 1 >> 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.bitShiftRight
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.bitShiftRight
], ints: [
1,
2
@@ -1617,9 +1617,9 @@
test_constExpr_binary_bitXor() {
UnlinkedVariable variable = serializeVariableText('const v = 1 ^ 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.bitXor
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.bitXor
], ints: [
1,
2
@@ -1629,9 +1629,9 @@
test_constExpr_binary_divide() {
UnlinkedVariable variable = serializeVariableText('const v = 1 / 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.divide
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.divide
], ints: [
1,
2
@@ -1641,9 +1641,9 @@
test_constExpr_binary_equal() {
UnlinkedVariable variable = serializeVariableText('const v = 1 == 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.equal
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.equal
], ints: [
1,
2
@@ -1653,9 +1653,9 @@
test_constExpr_binary_equal_not() {
UnlinkedVariable variable = serializeVariableText('const v = 1 != 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.notEqual
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.notEqual
], ints: [
1,
2
@@ -1665,9 +1665,9 @@
test_constExpr_binary_floorDivide() {
UnlinkedVariable variable = serializeVariableText('const v = 1 ~/ 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.floorDivide
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.floorDivide
], ints: [
1,
2
@@ -1677,9 +1677,9 @@
test_constExpr_binary_greater() {
UnlinkedVariable variable = serializeVariableText('const v = 1 > 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.greater
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.greater
], ints: [
1,
2
@@ -1689,9 +1689,9 @@
test_constExpr_binary_greaterEqual() {
UnlinkedVariable variable = serializeVariableText('const v = 1 >= 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.greaterEqual
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.greaterEqual
], ints: [
1,
2
@@ -1701,9 +1701,9 @@
test_constExpr_binary_less() {
UnlinkedVariable variable = serializeVariableText('const v = 1 < 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.less
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.less
], ints: [
1,
2
@@ -1713,9 +1713,9 @@
test_constExpr_binary_lessEqual() {
UnlinkedVariable variable = serializeVariableText('const v = 1 <= 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.lessEqual
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.lessEqual
], ints: [
1,
2
@@ -1725,9 +1725,9 @@
test_constExpr_binary_modulo() {
UnlinkedVariable variable = serializeVariableText('const v = 1 % 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.modulo
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.modulo
], ints: [
1,
2
@@ -1737,9 +1737,9 @@
test_constExpr_binary_multiply() {
UnlinkedVariable variable = serializeVariableText('const v = 1 * 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.multiply
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.multiply
], ints: [
1,
2
@@ -1750,18 +1750,18 @@
UnlinkedVariable variable =
serializeVariableText('const v = false || true;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushFalse,
- UnlinkedConstOperation.pushTrue,
- UnlinkedConstOperation.or
+ UnlinkedExprOperation.pushFalse,
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.or
]);
}
test_constExpr_binary_subtract() {
UnlinkedVariable variable = serializeVariableText('const v = 1 - 2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.subtract
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.subtract
], ints: [
1,
2
@@ -1783,7 +1783,7 @@
UnlinkedClass cls = serializeClassText(text, allowErrors: true);
_assertUnlinkedConst(cls.executables[0].constantInitializers[0].expression,
operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
],
referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'T',
@@ -1799,10 +1799,10 @@
UnlinkedVariable variable =
serializeVariableText('const v = true ? 1 : 2;', allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushTrue,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.conditional
+ UnlinkedExprOperation.pushTrue,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.conditional
], ints: [
1,
2
@@ -1818,7 +1818,7 @@
}
''');
_assertUnlinkedConst(cls.executables[0].constantInitializers[0].expression,
- operators: [UnlinkedConstOperation.pushParameter], strings: ['a']);
+ operators: [UnlinkedExprOperation.pushParameter], strings: ['a']);
}
test_constExpr_constructorParam_shadows_typeParam() {
@@ -1829,7 +1829,7 @@
}
''');
_assertUnlinkedConst(cls.executables[0].constantInitializers[0].expression,
- operators: [UnlinkedConstOperation.pushParameter], strings: ['T']);
+ operators: [UnlinkedExprOperation.pushParameter], strings: ['T']);
}
test_constExpr_functionExpression_asArgument() {
@@ -1843,9 +1843,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
5,
@@ -1872,10 +1872,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
5,
@@ -1906,11 +1906,11 @@
expect(executable.localFunctions, hasLength(2));
_assertUnlinkedConst(executable.constantInitializers[0].expression,
isValidConst: false,
- operators: [UnlinkedConstOperation.pushLocalFunctionReference],
+ operators: [UnlinkedExprOperation.pushLocalFunctionReference],
ints: [0, 0]);
_assertUnlinkedConst(executable.constantInitializers[1].expression,
isValidConst: false,
- operators: [UnlinkedConstOperation.pushLocalFunctionReference],
+ operators: [UnlinkedExprOperation.pushLocalFunctionReference],
ints: [0, 1]);
}
@@ -1922,7 +1922,7 @@
const v = const C<int, String>.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -1954,7 +1954,7 @@
const v = const C<int, String>.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -1988,7 +1988,7 @@
const v = const p.C<int, String>.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2018,7 +2018,7 @@
const v = const C<int, String>();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2047,7 +2047,7 @@
const v = const C<int, String>();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2076,7 +2076,7 @@
const v = const p.C<int, String>();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2103,7 +2103,7 @@
const v = const C.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2129,7 +2129,7 @@
const v = const C.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2156,7 +2156,7 @@
const v = const p.C.named();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2183,14 +2183,14 @@
// Doubles: ^pointer
// Strings: ^pointer 'e' 'g' 'f' ''
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushDouble,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushDouble,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
11,
22,
@@ -2225,7 +2225,7 @@
const v = const C();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2248,7 +2248,7 @@
const v = const p.C();
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2269,7 +2269,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2289,7 +2289,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2316,7 +2316,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2340,7 +2340,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2361,7 +2361,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -2375,9 +2375,9 @@
UnlinkedVariable variable =
serializeVariableText('const v = identical(42, null);');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushNull,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushNull,
+ UnlinkedExprOperation.invokeMethodRef
], ints: [
42,
0,
@@ -2399,7 +2399,7 @@
const int v = C.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2422,7 +2422,7 @@
const int v = p.C.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2440,7 +2440,7 @@
const int v = a.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.unresolved,
@@ -2460,7 +2460,7 @@
const int v = C.F.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.unresolved,
@@ -2483,7 +2483,7 @@
const int v = a.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.unresolved,
@@ -2507,7 +2507,7 @@
const int v = p.a.length;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'length',
expectedKind: ReferenceKind.unresolved,
@@ -2525,10 +2525,10 @@
UnlinkedVariable variable =
serializeVariableText('const v = ("abc" + "edf").length;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.add,
- UnlinkedConstOperation.extractProperty
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.add,
+ UnlinkedExprOperation.extractProperty
], strings: [
'abc',
'edf',
@@ -2540,8 +2540,8 @@
UnlinkedVariable variable =
serializeVariableText('const v = ("abc").length;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.extractProperty
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.extractProperty
], strings: [
'abc',
'length'
@@ -2552,8 +2552,8 @@
UnlinkedVariable variable =
serializeVariableText('const v = "abc".length;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.extractProperty
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.extractProperty
], strings: [
'abc',
'length'
@@ -2563,17 +2563,17 @@
test_constExpr_makeSymbol() {
UnlinkedVariable variable = serializeVariableText('const v = #a.bb.ccc;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.makeSymbol], strings: ['a.bb.ccc']);
+ operators: [UnlinkedExprOperation.makeSymbol], strings: ['a.bb.ccc']);
}
test_constExpr_makeTypedList() {
UnlinkedVariable variable =
serializeVariableText('const v = const <int>[11, 22, 33];');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.makeTypedList
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeTypedList
], ints: [
11,
22,
@@ -2589,10 +2589,10 @@
UnlinkedVariable variable =
serializeVariableText('const v = const <dynamic>[11, 22, 33];');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.makeTypedList
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeTypedList
], ints: [
11,
22,
@@ -2607,13 +2607,13 @@
UnlinkedVariable variable = serializeVariableText(
'const v = const <int, String>{11: "aaa", 22: "bbb", 33: "ccc"};');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.makeTypedMap
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeTypedMap
], ints: [
11,
22,
@@ -2635,13 +2635,13 @@
UnlinkedVariable variable = serializeVariableText(
'const v = const <dynamic, dynamic>{11: "aaa", 22: "bbb", 33: "ccc"};');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.makeTypedMap
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeTypedMap
], ints: [
11,
22,
@@ -2661,10 +2661,10 @@
UnlinkedVariable variable =
serializeVariableText('const v = const [11, 22, 33];');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.makeUntypedList
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.makeUntypedList
], ints: [
11,
22,
@@ -2677,13 +2677,13 @@
UnlinkedVariable variable = serializeVariableText(
'const v = const {11: "aaa", 22: "bbb", 33: "ccc"};');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.makeUntypedMap
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.makeUntypedMap
], ints: [
11,
22,
@@ -2699,11 +2699,11 @@
test_constExpr_parenthesized() {
UnlinkedVariable variable = serializeVariableText('const v = (1 + 2) * 3;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.multiply,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.multiply,
], ints: [
1,
2,
@@ -2714,8 +2714,8 @@
test_constExpr_prefix_complement() {
UnlinkedVariable variable = serializeVariableText('const v = ~2;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.complement
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.complement
], ints: [
2
]);
@@ -2724,8 +2724,8 @@
test_constExpr_prefix_negate() {
UnlinkedVariable variable = serializeVariableText('const v = -(2);');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.negate
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.negate
], ints: [
2
]);
@@ -2733,34 +2733,32 @@
test_constExpr_prefix_not() {
UnlinkedVariable variable = serializeVariableText('const v = !true;');
- _assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushTrue,
- UnlinkedConstOperation.not
- ]);
+ _assertUnlinkedConst(variable.initializer.bodyExpr,
+ operators: [UnlinkedExprOperation.pushTrue, UnlinkedExprOperation.not]);
}
test_constExpr_pushDouble() {
UnlinkedVariable variable = serializeVariableText('const v = 123.4567;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushDouble], doubles: [123.4567]);
+ operators: [UnlinkedExprOperation.pushDouble], doubles: [123.4567]);
}
test_constExpr_pushFalse() {
UnlinkedVariable variable = serializeVariableText('const v = false;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushFalse]);
+ operators: [UnlinkedExprOperation.pushFalse]);
}
test_constExpr_pushInt() {
UnlinkedVariable variable = serializeVariableText('const v = 1;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
}
test_constExpr_pushInt_max() {
UnlinkedVariable variable = serializeVariableText('const v = 0xFFFFFFFF;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
], ints: [
0xFFFFFFFF
]);
@@ -2769,8 +2767,8 @@
test_constExpr_pushInt_negative() {
UnlinkedVariable variable = serializeVariableText('const v = -5;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.negate
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.negate
], ints: [
5
]);
@@ -2780,14 +2778,14 @@
UnlinkedVariable variable =
serializeVariableText('const v = 0xA123456789ABCDEF012345678;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushLongInt],
+ operators: [UnlinkedExprOperation.pushLongInt],
ints: [4, 0xA, 0x12345678, 0x9ABCDEF0, 0x12345678]);
}
test_constExpr_pushLongInt_min2() {
UnlinkedVariable variable = serializeVariableText('const v = 0x100000000;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushLongInt
+ UnlinkedExprOperation.pushLongInt
], ints: [
2,
1,
@@ -2799,7 +2797,7 @@
UnlinkedVariable variable =
serializeVariableText('const v = 0x10000000000000000;');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushLongInt
+ UnlinkedExprOperation.pushLongInt
], ints: [
3,
1,
@@ -2811,7 +2809,7 @@
test_constExpr_pushNull() {
UnlinkedVariable variable = serializeVariableText('const v = null;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushNull]);
+ operators: [UnlinkedExprOperation.pushNull]);
}
test_constExpr_pushReference_class() {
@@ -2820,7 +2818,7 @@
const v = C;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'C',
expectedKind: ReferenceKind.classOrEnum)
@@ -2833,7 +2831,7 @@
const v = C;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'C',
expectedKind: ReferenceKind.classOrEnum)
@@ -2846,7 +2844,7 @@
const v = C.V1;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'V1',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2867,7 +2865,7 @@
const v = C.V1;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'V1',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2884,7 +2882,7 @@
const v = C.values;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'values',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2905,7 +2903,7 @@
const v = C.values;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'values',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2924,7 +2922,7 @@
const v = C.F;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'F',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2947,7 +2945,7 @@
const v = C.F;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'F',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2971,7 +2969,7 @@
const v = p.C.F;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'F',
expectedKind: ReferenceKind.propertyAccessor,
@@ -2991,7 +2989,7 @@
}
''').fields[0];
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'b',
expectedKind: ReferenceKind.propertyAccessor,
@@ -3009,7 +3007,7 @@
const v = C.x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'x',
expectedKind: ReferenceKind.propertyAccessor,
@@ -3032,7 +3030,7 @@
const v = C.x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'x',
expectedKind: ReferenceKind.propertyAccessor,
@@ -3056,7 +3054,7 @@
const v = p.C.x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'x',
expectedKind: ReferenceKind.propertyAccessor,
@@ -3076,7 +3074,7 @@
const v = C.m;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'm',
expectedKind: ReferenceKind.method,
@@ -3099,7 +3097,7 @@
const v = C.m;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'm',
expectedKind: ReferenceKind.method,
@@ -3123,7 +3121,7 @@
const v = p.C.m;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'm',
expectedKind: ReferenceKind.method,
@@ -3143,7 +3141,7 @@
}
''').fields[0];
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'm',
expectedKind: ReferenceKind.method,
@@ -3159,7 +3157,7 @@
const v = f;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'f',
expectedKind: ReferenceKind.topLevelFunction)
@@ -3177,7 +3175,7 @@
const v = f;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'f',
expectedKind: ReferenceKind.topLevelFunction)
@@ -3195,7 +3193,7 @@
const v = p.f;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'f',
expectedKind: ReferenceKind.topLevelFunction,
@@ -3211,7 +3209,7 @@
const v = x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'x',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -3225,7 +3223,7 @@
const v = x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'x',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -3239,7 +3237,7 @@
const v = p.x;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'x',
expectedKind: ReferenceKind.topLevelPropertyAccessor,
@@ -3253,7 +3251,7 @@
const v = a;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'a',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -3267,7 +3265,7 @@
const v = a;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'a',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -3281,7 +3279,7 @@
const v = p.a;
''');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) {
return checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'a',
@@ -3300,7 +3298,7 @@
UnlinkedVariable variable =
serializeClassText(text, allowErrors: true).fields[0];
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) {
return checkParamTypeRef(r, 1);
@@ -3315,7 +3313,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'foo',
expectedKind: ReferenceKind.unresolved)
@@ -3330,7 +3328,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'foo',
expectedKind: ReferenceKind.unresolved,
@@ -3353,7 +3351,7 @@
''',
allowErrors: true);
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'foo',
expectedKind: ReferenceKind.unresolved,
@@ -3369,20 +3367,20 @@
UnlinkedVariable variable =
serializeVariableText('const v = "aaa" "b" "ccc";');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushString], strings: ['aaabccc']);
+ operators: [UnlinkedExprOperation.pushString], strings: ['aaabccc']);
}
test_constExpr_pushString_adjacent_interpolation() {
UnlinkedVariable variable =
serializeVariableText(r'const v = "aaa" "bb ${42} bbb" "cccc";');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.concatenate,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.concatenate,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.concatenate,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.concatenate,
], ints: [
42,
3,
@@ -3399,10 +3397,10 @@
UnlinkedVariable variable =
serializeVariableText(r'const v = "aaa ${42} bbb";');
_assertUnlinkedConst(variable.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushString,
- UnlinkedConstOperation.concatenate
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushString,
+ UnlinkedExprOperation.concatenate
], ints: [
42,
3
@@ -3415,13 +3413,13 @@
test_constExpr_pushString_simple() {
UnlinkedVariable variable = serializeVariableText('const v = "abc";');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushString], strings: ['abc']);
+ operators: [UnlinkedExprOperation.pushString], strings: ['abc']);
}
test_constExpr_pushTrue() {
UnlinkedVariable variable = serializeVariableText('const v = true;');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushTrue]);
+ operators: [UnlinkedExprOperation.pushTrue]);
}
test_constructor() {
@@ -3513,7 +3511,7 @@
expect(initializer.kind, UnlinkedConstructorInitializerKind.field);
expect(initializer.name, 'x');
_assertUnlinkedConst(initializer.expression,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
expect(initializer.arguments, isEmpty);
}
@@ -3531,7 +3529,7 @@
expect(initializer.kind, UnlinkedConstructorInitializerKind.field);
expect(initializer.name, 'x');
_assertUnlinkedConst(initializer.expression,
- operators: [UnlinkedConstOperation.pushParameter], strings: ['p']);
+ operators: [UnlinkedExprOperation.pushParameter], strings: ['p']);
expect(initializer.arguments, isEmpty);
}
@@ -3565,7 +3563,7 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(1));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_constructor_initializers_superInvocation_namedExpression() {
@@ -3587,11 +3585,11 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(3));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
_assertUnlinkedConst(initializer.arguments[1],
- operators: [UnlinkedConstOperation.pushInt], ints: [2]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [2]);
_assertUnlinkedConst(initializer.arguments[2],
- operators: [UnlinkedConstOperation.pushInt], ints: [3]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [3]);
expect(initializer.argumentNames, ['b', 'c']);
}
@@ -3614,7 +3612,7 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(1));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_constructor_initializers_thisInvocation_named() {
@@ -3633,9 +3631,9 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(2));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
_assertUnlinkedConst(initializer.arguments[1],
- operators: [UnlinkedConstOperation.pushString], strings: ['bbb']);
+ operators: [UnlinkedExprOperation.pushString], strings: ['bbb']);
}
test_constructor_initializers_thisInvocation_namedExpression() {
@@ -3654,11 +3652,11 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(3));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
_assertUnlinkedConst(initializer.arguments[1],
- operators: [UnlinkedConstOperation.pushInt], ints: [2]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [2]);
_assertUnlinkedConst(initializer.arguments[2],
- operators: [UnlinkedConstOperation.pushInt], ints: [3]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [3]);
expect(initializer.argumentNames, ['b', 'c']);
}
@@ -3678,9 +3676,9 @@
expect(initializer.expression, isNull);
expect(initializer.arguments, hasLength(2));
_assertUnlinkedConst(initializer.arguments[0],
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
_assertUnlinkedConst(initializer.arguments[1],
- operators: [UnlinkedConstOperation.pushString], strings: ['bbb']);
+ operators: [UnlinkedExprOperation.pushString], strings: ['bbb']);
}
test_constructor_initializing_formal() {
@@ -3765,7 +3763,7 @@
expect(param.kind, UnlinkedParamKind.positional);
expect(param.defaultValueCode, 'foo');
_assertUnlinkedConst(param.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'foo',
expectedKind: ReferenceKind.topLevelFunction)
@@ -3810,7 +3808,7 @@
expect(parameter.defaultValueCode, '42');
_assertCodeRange(parameter.codeRange, 13, 10);
_assertUnlinkedConst(parameter.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_constructor_initializing_formal_non_function_typed() {
@@ -3842,7 +3840,7 @@
expect(parameter.defaultValueCode, '42');
_assertCodeRange(parameter.codeRange, 13, 11);
_assertUnlinkedConst(parameter.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_constructor_initializing_formal_required() {
@@ -3874,7 +3872,7 @@
expect(param.kind, UnlinkedParamKind.positional);
expect(param.defaultValueCode, '42');
_assertUnlinkedConst(param.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_constructor_named() {
@@ -5784,7 +5782,7 @@
expect(param.initializer, isNotNull);
expect(param.defaultValueCode, 'foo');
_assertUnlinkedConst(param.initializer.bodyExpr, operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'foo',
expectedKind: ReferenceKind.topLevelFunction)
@@ -5807,7 +5805,7 @@
expect(param.defaultValueCode, '42');
_assertCodeRange(param.codeRange, 3, 5);
_assertUnlinkedConst(param.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_executable_param_kind_positional() {
@@ -5826,7 +5824,7 @@
expect(param.defaultValueCode, '42');
_assertCodeRange(param.codeRange, 3, 6);
_assertUnlinkedConst(param.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [42]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [42]);
}
test_executable_param_kind_required() {
@@ -6390,10 +6388,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushReference,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToIndex,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToIndex,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6436,19 +6434,19 @@
isValidConst: false,
operators: [
// 5
- UnlinkedConstOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
// a.b[1]
- UnlinkedConstOperation.pushReference,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.extractIndex,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.extractIndex,
// c[2]
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.extractIndex,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.extractIndex,
// f[3] = 5
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToIndex,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToIndex,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6484,10 +6482,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushReference,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToIndex,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToIndex,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6516,9 +6514,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeConstructor,
- UnlinkedConstOperation.assignToProperty,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeConstructor,
+ UnlinkedExprOperation.assignToProperty,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6550,8 +6548,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6589,8 +6587,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6642,8 +6640,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6674,8 +6672,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6706,8 +6704,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToRef,
],
assignmentOperators: [
(UnlinkedExprAssignOperator.assign)
@@ -6739,14 +6737,14 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushReference,
+ UnlinkedExprOperation.pushReference,
// ..[1] = 2
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToIndex,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToIndex,
// c
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionEnd,
],
assignmentOperators: [
UnlinkedExprAssignOperator.assign,
@@ -6781,19 +6779,19 @@
isValidConst: false,
operators: [
// new C()
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
// ..f1 = 1
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToProperty,
// C
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionEnd,
// ..f2 += 2
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToProperty,
// C
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionEnd,
],
assignmentOperators: [
UnlinkedExprAssignOperator.assign,
@@ -6836,29 +6834,29 @@
isValidConst: false,
operators: [
// new A()
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
// ..fa1 = 1
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToProperty,
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionEnd,
// ..b
- UnlinkedConstOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.cascadeSectionBegin,
// new B()
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
// ..fb = 2
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToProperty,
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionEnd,
// ..b = <pop value>
- UnlinkedConstOperation.assignToProperty,
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionEnd,
// ..fa2 = 3
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.assignToProperty,
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.assignToProperty,
+ UnlinkedExprOperation.cascadeSectionEnd,
],
assignmentOperators: [
UnlinkedExprAssignOperator.assign,
@@ -6904,21 +6902,21 @@
isValidConst: false,
operators: [
// a
- UnlinkedConstOperation.pushReference,
+ UnlinkedExprOperation.pushReference,
// ..m(5)
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeMethod,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethod,
// ..abs()
- UnlinkedConstOperation.invokeMethod,
+ UnlinkedExprOperation.invokeMethod,
// a
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionEnd,
// ..m(6)
- UnlinkedConstOperation.cascadeSectionBegin,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeMethod,
+ UnlinkedExprOperation.cascadeSectionBegin,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethod,
// a
- UnlinkedConstOperation.cascadeSectionEnd,
+ UnlinkedExprOperation.cascadeSectionEnd,
],
ints: [
5, 0, 1, 0, // m(5)
@@ -6949,10 +6947,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeConstructor,
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.extractIndex,
+ UnlinkedExprOperation.invokeConstructor,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.extractIndex,
],
ints: [
0,
@@ -6981,8 +6979,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeConstructor,
- UnlinkedConstOperation.extractProperty,
+ UnlinkedExprOperation.invokeConstructor,
+ UnlinkedExprOperation.extractProperty,
],
ints: [
0,
@@ -7008,9 +7006,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
5,
@@ -7037,10 +7035,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
5,
@@ -7067,7 +7065,7 @@
''');
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
- operators: [UnlinkedConstOperation.pushLocalFunctionReference],
+ operators: [UnlinkedExprOperation.pushLocalFunctionReference],
ints: [0, 0]);
}
@@ -7080,7 +7078,7 @@
''');
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
- operators: [UnlinkedConstOperation.pushLocalFunctionReference],
+ operators: [UnlinkedExprOperation.pushLocalFunctionReference],
ints: [0, 0]);
}
@@ -7092,7 +7090,7 @@
final v = ((a, b) {return 42;})(1, 2);
''');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false, operators: [UnlinkedConstOperation.pushNull]);
+ isValidConst: false, operators: [UnlinkedExprOperation.pushNull]);
}
test_expr_functionExpressionInvocation_withExpressionBody() {
@@ -7103,7 +7101,7 @@
final v = ((a, b) => 42)(1, 2);
''');
_assertUnlinkedConst(variable.initializer.bodyExpr,
- isValidConst: false, operators: [UnlinkedConstOperation.pushNull]);
+ isValidConst: false, operators: [UnlinkedExprOperation.pushNull]);
}
test_expr_inClosure() {
@@ -7112,7 +7110,7 @@
}
UnlinkedVariable variable = serializeVariableText('var v = () => 1;');
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [1]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [1]);
}
test_expr_inClosure_noTypeInferenceNeeded() {
@@ -7130,7 +7128,7 @@
serializeVariableText('var v = (x) => (y) => x;');
_assertUnlinkedConst(
variable.initializer.localFunctions[0].localFunctions[0].bodyExpr,
- operators: [UnlinkedConstOperation.pushParameter],
+ operators: [UnlinkedExprOperation.pushParameter],
strings: ['x']);
}
@@ -7140,7 +7138,7 @@
}
UnlinkedVariable variable = serializeVariableText('var v = (x) => x;');
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
- operators: [UnlinkedConstOperation.pushParameter], strings: ['x']);
+ operators: [UnlinkedExprOperation.pushParameter], strings: ['x']);
}
test_expr_inClosure_refersToParam_methodCall() {
@@ -7151,8 +7149,8 @@
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.invokeMethod
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.invokeMethod
],
strings: [
'x',
@@ -7174,9 +7172,9 @@
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.invokeMethod
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.invokeMethod
],
strings: [
'x',
@@ -7199,10 +7197,10 @@
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.pushLocalFunctionReference,
- UnlinkedConstOperation.pushReference,
- UnlinkedConstOperation.conditional,
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.pushLocalFunctionReference,
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.conditional,
],
strings: [
'b'
@@ -7224,8 +7222,8 @@
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y;');
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.extractProperty
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.extractProperty
],
strings: [
'x',
@@ -7242,9 +7240,9 @@
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushNull,
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.assignToProperty
+ UnlinkedExprOperation.pushNull,
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.assignToProperty
],
strings: [
'x',
@@ -7262,9 +7260,9 @@
UnlinkedVariable variable = serializeVariableText('var v = (x) => x.y.z;');
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
operators: [
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.extractProperty
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.extractProperty
],
strings: [
'x',
@@ -7282,10 +7280,10 @@
_assertUnlinkedConst(variable.initializer.localFunctions[0].bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushNull,
- UnlinkedConstOperation.pushParameter,
- UnlinkedConstOperation.extractProperty,
- UnlinkedConstOperation.assignToProperty
+ UnlinkedExprOperation.pushNull,
+ UnlinkedExprOperation.pushParameter,
+ UnlinkedExprOperation.extractProperty,
+ UnlinkedExprOperation.assignToProperty
],
strings: [
'x',
@@ -7310,11 +7308,11 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeConstructor,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeMethod,
+ UnlinkedExprOperation.invokeConstructor,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethod,
],
ints: [
0,
@@ -7350,8 +7348,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeConstructor,
- UnlinkedConstOperation.invokeMethod
+ UnlinkedExprOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeMethod
],
ints: [
0,
@@ -7390,9 +7388,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeMethodRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethodRef,
],
ints: [
10,
@@ -7432,7 +7430,7 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeMethodRef,
+ UnlinkedExprOperation.invokeMethodRef,
],
ints: [
0,
@@ -7463,8 +7461,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushReference,
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.pushReference,
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
0,
@@ -7490,7 +7488,7 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.invokeMethodRef
+ UnlinkedExprOperation.invokeMethodRef
],
ints: [
0,
@@ -7516,10 +7514,10 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add,
- UnlinkedConstOperation.throwException,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add,
+ UnlinkedExprOperation.throwException,
],
ints: [
1,
@@ -7537,8 +7535,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.typeCast,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.typeCast,
],
ints: [
42
@@ -7559,8 +7557,8 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.typeCheck,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.typeCheck,
],
ints: [
42
@@ -7591,7 +7589,7 @@
serializeClassText('class C { static const int i = 0; }').fields[0];
expect(variable.isConst, isTrue);
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [0]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [0]);
}
test_field_documented() {
@@ -7612,7 +7610,7 @@
serializeClassText('class C { final int i = 0; }').fields[0];
expect(variable.isFinal, isTrue);
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.pushInt], ints: [0]);
+ operators: [UnlinkedExprOperation.pushInt], ints: [0]);
}
test_field_final_notConstExpr() {
@@ -7625,9 +7623,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.invokeMethodRef,
- UnlinkedConstOperation.add,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.invokeMethodRef,
+ UnlinkedExprOperation.add,
],
ints: [
1,
@@ -7652,7 +7650,7 @@
}''').fields[0];
expect(variable.isFinal, isTrue);
_assertUnlinkedConst(variable.initializer.bodyExpr,
- operators: [UnlinkedConstOperation.makeTypedList],
+ operators: [UnlinkedExprOperation.makeTypedList],
ints: [0],
referenceValidators: [(EntityRef r) => checkParamTypeRef(r, 1)]);
}
@@ -8686,7 +8684,7 @@
'class A { const A.named(); } @A.named() class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8705,7 +8703,7 @@
'import "foo.dart" as foo; @foo.A.named() class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8727,7 +8725,7 @@
allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8748,7 +8746,7 @@
allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8768,7 +8766,7 @@
serializeClassText('@A.named() class C {}', allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8786,7 +8784,7 @@
allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8804,7 +8802,7 @@
serializeClassText('class A { const A(); } @A() class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8820,7 +8818,7 @@
serializeClassText('import "foo.dart" as foo; @foo.A() class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8837,7 +8835,7 @@
allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8852,7 +8850,7 @@
serializeClassText('@A() class C {}', allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
0
@@ -8867,8 +8865,8 @@
serializeClassText('class A { const A(x); } @A(null) class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.pushNull,
- UnlinkedConstOperation.invokeConstructor,
+ UnlinkedExprOperation.pushNull,
+ UnlinkedExprOperation.invokeConstructor,
], ints: [
0,
1
@@ -8994,16 +8992,16 @@
test_metadata_multiple_annotations() {
UnlinkedClass cls =
serializeClassText('const a = null, b = null; @a @b class C {}');
- List<UnlinkedConst> annotations = cls.annotations;
+ List<UnlinkedExpr> annotations = cls.annotations;
expect(annotations, hasLength(2));
_assertUnlinkedConst(annotations[0], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'a',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
]);
_assertUnlinkedConst(annotations[1], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'b',
expectedKind: ReferenceKind.topLevelPropertyAccessor)
@@ -9022,7 +9020,7 @@
serializeClassText('import "a.dart" as a; @a.b class C {}');
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, absUri('/a.dart'), 'a.dart', 'b',
expectedKind: ReferenceKind.topLevelPropertyAccessor,
@@ -9037,7 +9035,7 @@
allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'b',
expectedKind: ReferenceKind.unresolved, expectedPrefix: 'a')
@@ -9092,7 +9090,7 @@
UnlinkedClass cls = serializeClassText('@a class C {}', allowErrors: true);
expect(cls.annotations, hasLength(1));
_assertUnlinkedConst(cls.annotations[0], operators: [
- UnlinkedConstOperation.pushReference
+ UnlinkedExprOperation.pushReference
], referenceValidators: [
(EntityRef r) => checkTypeRef(r, null, null, 'a',
expectedKind: ReferenceKind.unresolved)
@@ -10237,12 +10235,12 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add,
- UnlinkedConstOperation.assignToRef,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add,
],
assignmentOperators: [
expectedAssignOperator
@@ -10304,9 +10302,9 @@
_assertUnlinkedConst(variable.initializer.bodyExpr,
isValidConst: false,
operators: [
- UnlinkedConstOperation.assignToRef,
- UnlinkedConstOperation.pushInt,
- UnlinkedConstOperation.add,
+ UnlinkedExprOperation.assignToRef,
+ UnlinkedExprOperation.pushInt,
+ UnlinkedExprOperation.add,
],
assignmentOperators: [
expectedAssignmentOperator
@@ -10324,9 +10322,9 @@
/**
* TODO(scheglov) rename "Const" to "Expr" everywhere
*/
- void _assertUnlinkedConst(UnlinkedConst constExpr,
+ void _assertUnlinkedConst(UnlinkedExpr constExpr,
{bool isValidConst: true,
- List<UnlinkedConstOperation> operators: const <UnlinkedConstOperation>[],
+ List<UnlinkedExprOperation> operators: const <UnlinkedExprOperation>[],
List<UnlinkedExprAssignOperator> assignmentOperators:
const <UnlinkedExprAssignOperator>[],
List<int> ints: const <int>[],
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index ce4bf2e..be0798c 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -226,6 +226,77 @@
expect(errors[0].errorCode, AnalysisOptionsErrorCode.PARSE_ERROR);
}
+ test_perform_include() {
+ newSource('/other_options.yaml', '');
+ String code = r'''
+include: other_options.yaml
+''';
+ AnalysisTarget target = newSource(optionsFilePath, code);
+ computeResult(target, ANALYSIS_OPTIONS_ERRORS);
+ expect(task, isGenerateOptionsErrorsTask);
+ List<AnalysisError> errors =
+ outputs[ANALYSIS_OPTIONS_ERRORS] as List<AnalysisError>;
+ expect(errors, hasLength(0));
+ }
+
+ test_perform_include_bad_value() {
+ newSource('/other_options.yaml', '''
+analyzer:
+ errors:
+ unused_local_variable: ftw
+''');
+ String code = r'''
+include: other_options.yaml
+''';
+ AnalysisTarget target = newSource(optionsFilePath, code);
+ computeResult(target, ANALYSIS_OPTIONS_ERRORS);
+ expect(task, isGenerateOptionsErrorsTask);
+ List<AnalysisError> errors =
+ outputs[ANALYSIS_OPTIONS_ERRORS] as List<AnalysisError>;
+ expect(errors, hasLength(1));
+ AnalysisError error = errors[0];
+ expect(error.errorCode, AnalysisOptionsWarningCode.INCLUDED_FILE_WARNING);
+ expect(error.source, target.source);
+ expect(error.offset, 10);
+ expect(error.length, 18);
+ expect(error.message, contains('other_options.yaml(47..49)'));
+ }
+
+ test_perform_include_bad_yaml() {
+ newSource('/other_options.yaml', ':');
+ String code = r'''
+include: other_options.yaml
+''';
+ AnalysisTarget target = newSource(optionsFilePath, code);
+ computeResult(target, ANALYSIS_OPTIONS_ERRORS);
+ expect(task, isGenerateOptionsErrorsTask);
+ List<AnalysisError> errors =
+ outputs[ANALYSIS_OPTIONS_ERRORS] as List<AnalysisError>;
+ expect(errors, hasLength(1));
+ AnalysisError error = errors[0];
+ expect(error.errorCode, AnalysisOptionsErrorCode.INCLUDED_FILE_PARSE_ERROR);
+ expect(error.source, target.source);
+ expect(error.offset, 10);
+ expect(error.length, 18);
+ expect(error.message, contains('other_options.yaml(0..0)'));
+ }
+
+ test_perform_include_missing() {
+ String code = r'''
+include: other_options.yaml
+''';
+ AnalysisTarget target = newSource(optionsFilePath, code);
+ computeResult(target, ANALYSIS_OPTIONS_ERRORS);
+ expect(task, isGenerateOptionsErrorsTask);
+ List<AnalysisError> errors =
+ outputs[ANALYSIS_OPTIONS_ERRORS] as List<AnalysisError>;
+ expect(errors, hasLength(1));
+ AnalysisError error = errors[0];
+ expect(error.errorCode, AnalysisOptionsWarningCode.INCLUDE_FILE_NOT_FOUND);
+ expect(error.offset, 10);
+ expect(error.length, 18);
+ }
+
test_perform_OK() {
String code = r'''
analyzer:
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index b613093..2bb7001 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -17,7 +17,7 @@
import '../constants/values.dart' show ConstantValue;
import '../dart_types.dart' show DartType, InterfaceType;
import '../elements/elements.dart'
- show ClassElement, Element, FunctionElement, LibraryElement;
+ show ClassElement, Element, FunctionElement, MethodElement, LibraryElement;
import '../enqueue.dart' show Enqueuer, EnqueueTask, ResolutionEnqueuer;
import '../io/code_output.dart' show CodeBuffer;
import '../io/source_information.dart' show SourceInformationStrategy;
@@ -313,7 +313,8 @@
void forgetElement(Element element) {}
- void registerMainHasArguments(Enqueuer enqueuer) {}
+ /// Computes the [WorldImpact] of calling [mainMethod] as the entry point.
+ WorldImpact computeMainImpact(Enqueuer enqueuer, MethodElement mainMethod) {}
/// Returns the location of the patch-file associated with [libraryName]
/// resolved from [plaformConfigUri].
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index ef0e751..c7bdcdf 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -683,6 +683,10 @@
backend.enqueueHelpers(enqueuer.resolution);
resolveLibraryMetadata();
reporter.log('Resolving...');
+ if (mainFunction != null && !mainFunction.isMalformed) {
+ mainFunction.computeType(resolution);
+ }
+
processQueue(enqueuer.resolution, mainFunction);
enqueuer.resolution.logSummary(reporter.log);
@@ -847,28 +851,15 @@
});
}
- void processQueue(Enqueuer enqueuer, Element main) {
+ void processQueue(Enqueuer enqueuer, MethodElement mainMethod) {
selfTask.measureSubtask("Compiler.processQueue", () {
enqueuer.applyImpact(
impactStrategy,
enqueuer.nativeEnqueuer
.processNativeClasses(libraryLoader.libraries));
- if (main != null && !main.isMalformed) {
- FunctionElement mainMethod = main;
- mainMethod.computeType(resolution);
- if (mainMethod.functionSignature.parameterCount != 0) {
- // The first argument could be a list of strings.
- backend.backendClasses.listImplementation.ensureResolved(resolution);
- enqueuer.registerInstantiatedType(
- backend.backendClasses.listImplementation.rawType);
- backend.backendClasses.stringImplementation
- .ensureResolved(resolution);
- enqueuer.registerInstantiatedType(
- backend.backendClasses.stringImplementation.rawType);
-
- backend.registerMainHasArguments(enqueuer);
- }
- enqueuer.addToWorkList(main);
+ if (mainMethod != null && !mainMethod.isMalformed) {
+ enqueuer.applyImpact(
+ impactStrategy, backend.computeMainImpact(enqueuer, mainMethod));
}
if (options.verbose) {
progress.reset();
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index bb50941..6c7de3f 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -22,6 +22,7 @@
AnalyzableElement,
AstElement,
ClassElement,
+ ConstructorElement,
Element,
Entity,
FunctionElement,
@@ -158,9 +159,9 @@
this.globalDependencies,
Backend backend,
CommonElements commonElements,
- CacheStrategy cacheStrategy)
- : this.name = 'resolution enqueuer',
- this.backend = backend,
+ CacheStrategy cacheStrategy,
+ [this.name = 'resolution enqueuer'])
+ : this.backend = backend,
this.commonElements = commonElements,
this.nativeEnqueuer = backend.nativeResolutionEnqueuer(),
processedElements = new Set<AstElement>(),
@@ -204,16 +205,20 @@
}
void _registerInstantiatedType(InterfaceType type,
- {bool mirrorUsage: false,
+ {ConstructorElement constructor,
+ bool mirrorUsage: false,
bool nativeUsage: false,
- bool globalDependency: false}) {
+ bool globalDependency: false,
+ bool isRedirection: false}) {
task.measure(() {
ClassElement cls = type.element;
cls.ensureResolved(resolution);
bool isNative = backend.isNative(cls);
_universe.registerTypeInstantiation(type,
+ constructor: constructor,
isNative: isNative,
- byMirrors: mirrorUsage, onImplemented: (ClassElement cls) {
+ byMirrors: mirrorUsage,
+ isRedirection: isRedirection, onImplemented: (ClassElement cls) {
backend.registerImplementedClass(cls, this);
});
if (globalDependency && !mirrorUsage) {
@@ -453,7 +458,14 @@
break;
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
- _registerTypeUse(new TypeUse.instantiation(staticUse.type));
+ _registerInstantiatedType(staticUse.type,
+ constructor: staticUse.element, globalDependency: false);
+ break;
+ case StaticUseKind.REDIRECTION:
+ _registerInstantiatedType(staticUse.type,
+ constructor: staticUse.element,
+ globalDependency: false,
+ isRedirection: true);
break;
case StaticUseKind.DIRECT_INVOKE:
invariant(
diff --git a/pkg/compiler/lib/src/js/rewrite_async.dart b/pkg/compiler/lib/src/js/rewrite_async.dart
index 5d37861..bc05656 100644
--- a/pkg/compiler/lib/src/js/rewrite_async.dart
+++ b/pkg/compiler/lib/src/js/rewrite_async.dart
@@ -5,13 +5,14 @@
library rewrite_async;
import 'dart:collection';
-import "dart:math" show max;
+import 'dart:math' show max;
import 'package:js_runtime/shared/async_await_error_codes.dart' as error_codes;
import '../common.dart';
+import '../io/source_information.dart' show SourceInformation;
import '../util/util.dart' show Pair;
-import "js.dart" as js;
+import 'js.dart' as js;
/// Rewrites a [js.Fun] with async/sync*/async* functions and await and yield
/// (with dart-like semantics) to an equivalent function without these.
@@ -519,7 +520,8 @@
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
- js.VariableDeclarationList variableDeclarations);
+ js.VariableDeclarationList variableDeclarations,
+ SourceInformation sourceInformation);
Iterable<js.VariableInitialization> variableInitializations();
@@ -705,7 +707,8 @@
js.VariableDeclarationList variableDeclarations =
new js.VariableDeclarationList(variables);
- return finishFunction(node.params, rewrittenBody, variableDeclarations);
+ return finishFunction(node.params, rewrittenBody, variableDeclarations,
+ node.sourceInformation);
}
@override
@@ -851,7 +854,8 @@
bool storeTarget = node.arguments.any(shouldTransform);
return withCallTargetExpression(node.target, (target) {
return withExpressions(node.arguments, (List<js.Expression> arguments) {
- return new js.Call(target, arguments);
+ return new js.Call(target, arguments)
+ .withSourceInformation(node.sourceInformation);
});
}, store: storeTarget);
}
@@ -1405,7 +1409,8 @@
@override
void visitThrow(js.Throw node) {
withExpression(node.expression, (js.Expression expression) {
- addStatement(new js.Throw(expression));
+ addStatement(new js.Throw(expression)
+ .withSourceInformation(node.sourceInformation));
}, store: false);
}
@@ -1712,14 +1717,13 @@
addStatement(new js.Comment("implicit return"));
}
addStatement(js.js.statement(
- "return #runtimeHelper(#returnValue, #successCode, #completer);",
- {
- "runtimeHelper": asyncHelper,
- "successCode": js.number(error_codes.SUCCESS),
- "returnValue":
- analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(),
- "completer": completer
- }));
+ "return #runtimeHelper(#returnValue, #successCode, #completer);", {
+ "runtimeHelper": asyncHelper,
+ "successCode": js.number(error_codes.SUCCESS),
+ "returnValue":
+ analysis.hasExplicitReturns ? returnValue : new js.LiteralNull(),
+ "completer": completer
+ }));
}
@override
@@ -1759,7 +1763,8 @@
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
- js.VariableDeclarationList variableDeclarations) {
+ js.VariableDeclarationList variableDeclarations,
+ SourceInformation sourceInformation) {
return js.js(
"""
function (#parameters) {
@@ -1787,7 +1792,7 @@
"asyncHelper": asyncHelper,
"completer": completer,
"wrapBody": wrapBody,
- });
+ }).withSourceInformation(sourceInformation);
}
}
@@ -1838,7 +1843,8 @@
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
- js.VariableDeclarationList variableDeclarations) {
+ js.VariableDeclarationList variableDeclarations,
+ SourceInformation sourceInformation) {
// Each iterator invocation on the iterable should work on its own copy of
// the parameters.
// TODO(sigurdm): We only need to do this copying for parameters that are
@@ -1891,7 +1897,7 @@
"handler": handler,
"currentError": currentErrorName,
"ERROR": js.number(error_codes.ERROR),
- });
+ }).withSourceInformation(sourceInformation);
}
void addErrorExit() {
@@ -2030,7 +2036,8 @@
js.Fun finishFunction(
List<js.Parameter> parameters,
js.Statement rewrittenBody,
- js.VariableDeclarationList variableDeclarations) {
+ js.VariableDeclarationList variableDeclarations,
+ SourceInformation sourceInformation) {
return js.js(
"""
function (#parameters) {
@@ -2074,7 +2081,7 @@
"streamOfController": streamOfController,
"controller": controllerName,
"wrapBody": wrapBody,
- });
+ }).withSourceInformation(sourceInformation);
}
@override
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 3aca346..03e5839 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -59,6 +59,7 @@
TransformedWorldImpact,
WorldImpact,
WorldImpactBuilder,
+ WorldImpactBuilderImpl,
WorldImpactVisitor,
StagedWorldImpactBuilder;
import '../util/util.dart';
@@ -2577,12 +2578,23 @@
aliasedSuperMembers.remove(element);
}
- void registerMainHasArguments(Enqueuer enqueuer) {
- // If the main method takes arguments, this compilation could be the target
- // of Isolate.spawnUri. Strictly speaking, that can happen also if main
- // takes no arguments, but in this case the spawned isolate can't
- // communicate with the spawning isolate.
- enqueuer.enableIsolateSupport();
+ @override
+ WorldImpact computeMainImpact(Enqueuer enqueuer, MethodElement mainMethod) {
+ WorldImpactBuilderImpl mainImpact = new WorldImpactBuilderImpl();
+ if (mainMethod.parameters.isNotEmpty) {
+ impactTransformer.registerBackendImpact(
+ mainImpact, impacts.mainWithArguments);
+ mainImpact.registerStaticUse(
+ new StaticUse.staticInvoke(mainMethod, CallStructure.TWO_ARGS));
+ // If the main method takes arguments, this compilation could be the
+ // target of Isolate.spawnUri. Strictly speaking, that can happen also if
+ // main takes no arguments, but in this case the spawned isolate can't
+ // communicate with the spawning isolate.
+ enqueuer.enableIsolateSupport();
+ }
+ mainImpact.registerStaticUse(
+ new StaticUse.staticInvoke(mainMethod, CallStructure.NO_ARGS));
+ return mainImpact;
}
/// Returns the filename for the output-unit named [name].
@@ -3000,7 +3012,7 @@
}
void registerBackendImpact(
- TransformedWorldImpact worldImpact, BackendImpact backendImpact) {
+ WorldImpactBuilder worldImpact, BackendImpact backendImpact) {
for (Element staticUse in backendImpact.staticUses) {
assert(staticUse != null);
backend.registerBackendUse(staticUse);
diff --git a/pkg/compiler/lib/src/js_backend/backend_impact.dart b/pkg/compiler/lib/src/js_backend/backend_impact.dart
index 7726ed0..afbd270 100644
--- a/pkg/compiler/lib/src/js_backend/backend_impact.dart
+++ b/pkg/compiler/lib/src/js_backend/backend_impact.dart
@@ -83,6 +83,18 @@
return _computeSignature;
}
+ BackendImpact _mainWithArguments;
+
+ BackendImpact get mainWithArguments {
+ if (_mainWithArguments == null) {
+ _mainWithArguments = new BackendImpact(
+ instantiatedClasses: [
+ helpers.jsArrayClass,
+ helpers.jsStringClass]);
+ }
+ return _mainWithArguments;
+ }
+
BackendImpact _asyncBody;
BackendImpact get asyncBody {
diff --git a/pkg/compiler/lib/src/js_backend/enqueuer.dart b/pkg/compiler/lib/src/js_backend/enqueuer.dart
index 179a65d..07c1f06 100644
--- a/pkg/compiler/lib/src/js_backend/enqueuer.dart
+++ b/pkg/compiler/lib/src/js_backend/enqueuer.dart
@@ -17,7 +17,6 @@
import '../elements/elements.dart'
show
ClassElement,
- ConstructorElement,
Element,
Elements,
Entity,
@@ -378,6 +377,7 @@
break;
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+ case StaticUseKind.REDIRECTION:
registerTypeUse(new TypeUse.instantiation(staticUse.type));
break;
case StaticUseKind.DIRECT_INVOKE:
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index f93553d..16843b3 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -3681,13 +3681,10 @@
isValidAsConstant = false;
}
- registry.registerStaticUse(
- new StaticUse.constructorRedirect(redirectionTarget));
- // TODO(johnniwinther): Register the effective target type as part of the
- // static use instead.
- registry.registerTypeUse(new TypeUse.instantiation(redirectionTarget
- .enclosingClass.thisType
- .subst(type.typeArguments, targetClass.typeVariables)));
+ registry.registerStaticUse(new StaticUse.constructorRedirect(
+ redirectionTarget,
+ redirectionTarget.enclosingClass.thisType
+ .subst(type.typeArguments, targetClass.typeVariables)));
if (resolution.commonElements.isSymbolConstructor(enclosingElement)) {
registry.registerFeature(Feature.SYMBOL_CONSTRUCTOR);
}
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 3f407ca..1c922e5 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -29,6 +29,7 @@
import 'nodes.dart';
import 'ssa_branch_builder.dart';
import 'type_builder.dart';
+import 'types.dart' show TypeMaskFactory;
class SsaKernelBuilderTask extends CompilerTask {
final JavaScriptBackend backend;
@@ -57,6 +58,14 @@
final ResolvedAst resolvedAst;
final CodegenRegistry registry;
+ /// A stack of [DartType]s that have been seen during inlining of factory
+ /// constructors. These types are preserved in [HInvokeStatic]s and
+ /// [HCreate]s inside the inline code and registered during code generation
+ /// for these nodes.
+ // TODO(karlklose): consider removing this and keeping the (substituted) types
+ // of the type variables in an environment (like the [LocalsHandler]).
+ final List<DartType> currentImplicitInstantiations = <DartType>[];
+
@override
JavaScriptBackend get backend => compiler.backend;
@@ -320,6 +329,18 @@
closeFunction();
}
+ void addImplicitInstantiation(DartType type) {
+ if (type != null) {
+ currentImplicitInstantiations.add(type);
+ }
+ }
+
+ void removeImplicitInstantiation(DartType type) {
+ if (type != null) {
+ currentImplicitInstantiations.removeLast();
+ }
+ }
+
void openFunction() {
HBasicBlock block = graph.addNewBlock();
open(graph.entry);
@@ -715,7 +736,9 @@
stack.add(graph.addConstantNull(compiler));
}
- HInstruction setRtiIfNeeded(HInstruction object, ir.ListLiteral listLiteral) {
+ /// Set the runtime type information if necessary.
+ HInstruction setListRuntimeTypeInfoIfNeeded(
+ HInstruction object, ir.ListLiteral listLiteral) {
InterfaceType type = localsHandler
.substInContext(elements.getType(astAdapter.getNode(listLiteral)));
if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
@@ -744,7 +767,8 @@
}
listInstruction = new HLiteralList(elements, backend.extendableArrayType);
add(listInstruction);
- listInstruction = setRtiIfNeeded(listInstruction, listLiteral);
+ listInstruction =
+ setListRuntimeTypeInfoIfNeeded(listInstruction, listLiteral);
}
TypeMask type = astAdapter.typeOfNewList(targetElement, listLiteral);
@@ -783,8 +807,52 @@
inputs.add(argList);
}
- // TODO(het): Add type information
- _pushStaticInvocation(constructor, inputs, backend.dynamicType);
+ assert(constructor.kind == ir.ProcedureKind.Factory);
+
+ InterfaceType type = localsHandler
+ .substInContext(elements.getType(astAdapter.getNode(mapLiteral)));
+
+ ir.Class cls = constructor.enclosingClass;
+
+ if (backend.classNeedsRti(astAdapter.getElement(cls))) {
+ List<HInstruction> typeInputs = <HInstruction>[];
+ type.typeArguments.forEach((DartType argument) {
+ typeInputs
+ .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
+ });
+
+ // We lift this common call pattern into a helper function to save space
+ // in the output.
+ if (typeInputs.every((HInstruction input) => input.isNull())) {
+ if (constructorArgs.isEmpty) {
+ constructor = astAdapter.mapLiteralUntypedEmptyMaker;
+ } else {
+ constructor = astAdapter.mapLiteralUntypedMaker;
+ }
+ } else {
+ inputs.addAll(typeInputs);
+ }
+ }
+
+ // If runtime type information is needed and the map literal has no type
+ // parameters, 'constructor' is a static function that forwards the call to
+ // the factory constructor without type parameters.
+ assert(constructor.kind == ir.ProcedureKind.Factory);
+
+ // The instruction type will always be a subtype of the mapLiteralClass, but
+ // type inference might discover a more specific type, or find nothing (in
+ // dart2js unit tests).
+ TypeMask mapType = new TypeMask.nonNullSubtype(
+ astAdapter.getElement(astAdapter.mapLiteralClass),
+ compiler.closedWorld);
+ TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement(
+ astAdapter.getElement(constructor), compiler);
+ TypeMask instructionType =
+ mapType.intersection(returnTypeMask, compiler.closedWorld);
+
+ addImplicitInstantiation(type);
+ _pushStaticInvocation(constructor, inputs, instructionType);
+ removeImplicitInstantiation(type);
}
@override
@@ -914,9 +982,13 @@
void _pushStaticInvocation(
ir.Node target, List<HInstruction> arguments, TypeMask typeMask) {
- HInstruction instruction = new HInvokeStatic(
+ HInvokeStatic instruction = new HInvokeStatic(
astAdapter.getMember(target), arguments, typeMask,
targetCanThrow: astAdapter.getCanThrow(target));
+ if (currentImplicitInstantiations.isNotEmpty) {
+ instruction.instantiatedTypes =
+ new List<DartType>.from(currentImplicitInstantiations);
+ }
instruction.sideEffects = astAdapter.getSideEffects(target);
push(instruction);
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index c882259..cd9d7c0 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+import 'dart:math' as math;
import '../common.dart';
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/tasks.dart' show CompilerTask;
@@ -210,8 +211,59 @@
return false;
}
+ // Returns the number of bits occupied by the value computed by [instruction].
+ // Returns `32` if the value is negative or does not fit in a smaller number
+ // of bits.
+ int bitWidth(HInstruction instruction) {
+ const int MAX = 32;
+ int constant(HInstruction insn) {
+ if (insn is HConstant && insn.isConstantInteger()) {
+ IntConstantValue constant = insn.constant;
+ return constant.primitiveValue;
+ }
+ return null;
+ }
+
+ if (instruction.isConstantInteger()) {
+ int value = constant(instruction);
+ if (value < 0) return MAX;
+ if (value > ((1 << 31) - 1)) return MAX;
+ return value.bitLength;
+ }
+ if (instruction is HBitAnd) {
+ return math.min(bitWidth(instruction.left), bitWidth(instruction.right));
+ }
+ if (instruction is HBitOr || instruction is HBitXor) {
+ HBinaryBitOp bitOp = instruction;
+ int leftWidth = bitWidth(bitOp.left);
+ if (leftWidth == MAX) return MAX;
+ return math.max(leftWidth, bitWidth(bitOp.right));
+ }
+ if (instruction is HShiftLeft) {
+ int shiftCount = constant(instruction.right);
+ if (shiftCount == null || shiftCount < 0 || shiftCount > 31) return MAX;
+ int leftWidth = bitWidth(instruction.left);
+ int width = leftWidth + shiftCount;
+ return math.min(width, MAX);
+ }
+ if (instruction is HShiftRight) {
+ int shiftCount = constant(instruction.right);
+ if (shiftCount == null || shiftCount < 0 || shiftCount > 31) return MAX;
+ int leftWidth = bitWidth(instruction.left);
+ if (leftWidth >= MAX) return MAX;
+ return math.max(leftWidth - shiftCount, 0);
+ }
+ if (instruction is HAdd) {
+ return math.min(
+ 1 + math.max(bitWidth(instruction.left), bitWidth(instruction.right)),
+ MAX);
+ }
+ return MAX;
+ }
+
bool requiresUintConversion(instruction) {
if (instruction.isUInt31(compiler)) return false;
+ if (bitWidth(instruction) <= 31) return false;
// If the result of a bit-operation is only used by other bit
// operations, we do not have to convert to an unsigned integer.
return hasNonBitOpUser(instruction, new Set<HPhi>());
diff --git a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
index 4db25e9..cf58dce 100644
--- a/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart
@@ -263,12 +263,21 @@
JumpTarget getTargetDefinition(ir.Node node) =>
elements.getTargetDefinition(getNode(node));
+ ir.Class get mapLiteralClass =>
+ kernel.classes[_backend.helpers.mapLiteralClass];
+
ir.Procedure get mapLiteralConstructor =>
kernel.functions[_backend.helpers.mapLiteralConstructor];
ir.Procedure get mapLiteralConstructorEmpty =>
kernel.functions[_backend.helpers.mapLiteralConstructorEmpty];
+ ir.Procedure get mapLiteralUntypedEmptyMaker =>
+ kernel.functions[_backend.helpers.mapLiteralUntypedEmptyMaker];
+
+ ir.Procedure get mapLiteralUntypedMaker =>
+ kernel.functions[_backend.helpers.mapLiteralUntypedMaker];
+
MemberElement get jsIndexableLength => _backend.helpers.jsIndexableLength;
ir.Procedure get checkConcurrentModificationError =>
diff --git a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
index 21da2e4..38a3f63 100644
--- a/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_string_builder.dart
@@ -43,9 +43,10 @@
return;
}
- // TODO(het): If toString method is guaranteed to return a string, then call
- // it directly instead of stringify. Or, better yet, do this later in the
- // optimization phase.
+ // TODO(efortuna): If we decide to do inlining before finishing constructing
+ // the control flow graph, we'd want to do the optimization of
+ // calling toString here if the type is provably a string rather than in the
+ // optimization phase (which is where we currently do it).
append(stringify(expression));
}
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 5f11f1d..de90a81 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -814,7 +814,7 @@
return node;
}
if (type.isFunctionType) {
- HInstruction input = node.checkedInput;
+ HInstruction input = node.checkedInput;
// `null` always passes type conversion.
if (input.isNull()) return input;
// TODO(johnniwinther): Optimize function type conversions.
diff --git a/pkg/compiler/lib/src/universe/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 5876a18..ce9a2c4 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -73,6 +73,7 @@
CLOSURE,
CONSTRUCTOR_INVOKE,
CONST_CONSTRUCTOR_INVOKE,
+ REDIRECTION,
DIRECT_INVOKE,
}
@@ -266,9 +267,12 @@
element, StaticUseKind.CONST_CONSTRUCTOR_INVOKE, type);
}
- /// Constructor redirection to [element].
- factory StaticUse.constructorRedirect(ConstructorElement element) {
- return new StaticUse.internal(element, StaticUseKind.GENERAL);
+ /// Constructor redirection to [element] on [type].
+ factory StaticUse.constructorRedirect(
+ ConstructorElement element, InterfaceType type) {
+ assert(invariant(element, type != null,
+ message: "No type provided for constructor invocation."));
+ return new StaticUse.internal(element, StaticUseKind.REDIRECTION, type);
}
/// Initialization of an instance field [element].
diff --git a/pkg/compiler/lib/src/universe/world_builder.dart b/pkg/compiler/lib/src/universe/world_builder.dart
index fa4108a..afcd031 100644
--- a/pkg/compiler/lib/src/universe/world_builder.dart
+++ b/pkg/compiler/lib/src/universe/world_builder.dart
@@ -14,9 +14,7 @@
import '../core_types.dart' show CoreClasses;
import '../dart_types.dart';
import '../elements/elements.dart';
-import '../types/masks.dart' show CommonMasks;
import '../universe/class_set.dart' show Instantiation;
-import '../util/enumset.dart';
import '../util/util.dart';
import '../world.dart' show World, ClosedWorld, OpenWorld, WorldImpl;
import 'selector.dart' show Selector;
@@ -164,9 +162,10 @@
/// Set of all fields that are statically known to be written to.
Iterable<Element> get fieldSetters;
- /// Call [f] for all directly or abstractly instantiated classes.
- void forEachInstantiatedClass(
- f(ClassElement cls, EnumSet<Instantiation> instantiations));
+ /// Call [f] for all classes with instantiated types. This includes the
+ /// directly and abstractly instantiated classes but also classes whose type
+ /// arguments are used in live factory constructors.
+ void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info));
/// `true` of `Object.runtimeType` is supported.
bool get hasRuntimeTypeSupport;
@@ -182,22 +181,172 @@
OpenWorld get openWorld;
}
+/// The type and kind of an instantiation registered through
+/// `ResolutionWorldBuilder.registerTypeInstantiation`.
+class Instance {
+ final InterfaceType type;
+ final Instantiation kind;
+ final bool isRedirection;
+
+ Instance(this.type, this.kind, {this.isRedirection: false});
+
+ int get hashCode {
+ return Hashing.objectHash(
+ type, Hashing.objectHash(kind, Hashing.objectHash(isRedirection)));
+ }
+
+ bool operator ==(other) {
+ if (identical(this, other)) return true;
+ if (other is! Instance) return false;
+ return type == other.type &&
+ kind == other.kind &&
+ isRedirection == other.isRedirection;
+ }
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write(type);
+ if (kind == Instantiation.DIRECTLY_INSTANTIATED) {
+ sb.write(' directly');
+ } else if (kind == Instantiation.ABSTRACTLY_INSTANTIATED) {
+ sb.write(' abstractly');
+ } else if (kind == Instantiation.UNINSTANTIATED) {
+ sb.write(' none');
+ }
+ if (isRedirection) {
+ sb.write(' redirect');
+ }
+ return sb.toString();
+ }
+}
+
+/// Information about instantiations of a class.
+class InstantiationInfo {
+ /// A map from constructor of the class to their instantiated types.
+ ///
+ /// For instance
+ ///
+ /// import 'dart:html';
+ ///
+ /// abstract class AbstractClass<S> {
+ /// factory AbstractClass.a() = Class<S>.a;
+ /// factory AbstractClass.b() => new Class<S>.b();
+ /// }
+ /// class Class<T> implements AbstractClass<T> {
+ /// Class.a();
+ /// Class.b();
+ /// factory Class.c() = Class.b<T>;
+ /// }
+ ///
+ ///
+ /// main() {
+ /// new Class.a();
+ /// new Class<int>.a();
+ /// new Class<String>.b();
+ /// new Class<num>.c();
+ /// new AbstractClass<double>.a();
+ /// new AbstractClass<bool>.b();
+ /// new DivElement(); // native instantiation
+ /// }
+ ///
+ /// will generate the mappings
+ ///
+ /// AbstractClass: {
+ /// AbstractClass.a: {
+ /// AbstractClass<double> none, // from `new AbstractClass<double>.a()`
+ /// },
+ /// AbstractClass.b: {
+ /// AbstractClass<bool> none, // from `new AbstractClass<bool>.b()`
+ /// },
+ /// },
+ /// Class: {
+ /// Class.a: {
+ /// Class directly, // from `new Class.a()`
+ /// Class<int> directly, // from `new Class<int>.a()`
+ /// Class<S> directly redirect, // from `factory AbstractClass.a`
+ /// },
+ /// Class.b: {
+ /// Class<String> directly, // from `new Class<String>.b()`
+ /// Class<T> directly redirect, // from `factory Class.c`
+ /// Class<S> directly, // from `factory AbstractClass.b`
+ /// },
+ /// Class.c: {
+ /// Class<num> directly, // from `new Class<num>.c()`
+ /// },
+ /// },
+ /// DivElement: {
+ /// DivElement: {
+ /// DivElement abstractly, // from `new DivElement()`
+ /// },
+ /// }
+ ///
+ /// If the constructor is unknown, for instance for native or mirror usage,
+ /// `null` is used as key.
+ Map<ConstructorElement, Set<Instance>> instantiationMap;
+
+ /// Register [type] as the instantiation [kind] using [constructor].
+ void addInstantiation(
+ ConstructorElement constructor, InterfaceType type, Instantiation kind,
+ {bool isRedirection: false}) {
+ instantiationMap ??= <ConstructorElement, Set<Instance>>{};
+ instantiationMap
+ .putIfAbsent(constructor, () => new Set<Instance>())
+ .add(new Instance(type, kind, isRedirection: isRedirection));
+ switch (kind) {
+ case Instantiation.DIRECTLY_INSTANTIATED:
+ isDirectlyInstantiated = true;
+ break;
+ case Instantiation.ABSTRACTLY_INSTANTIATED:
+ isAbstractlyInstantiated = true;
+ break;
+ case Instantiation.UNINSTANTIATED:
+ break;
+ default:
+ throw new StateError("Instantiation $kind is not allowed.");
+ }
+ }
+
+ /// `true` if the class is either directly or abstractly instantiated.
+ bool get hasInstantiation =>
+ isDirectlyInstantiated || isAbstractlyInstantiated;
+
+ /// `true` if the class is directly instantiated.
+ bool isDirectlyInstantiated = false;
+
+ /// `true` if the class is abstractly instantiated.
+ bool isAbstractlyInstantiated = false;
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('InstantiationInfo[');
+ if (instantiationMap != null) {
+ bool needsComma = false;
+ instantiationMap
+ .forEach((ConstructorElement constructor, Set<Instance> set) {
+ if (needsComma) {
+ sb.write(', ');
+ }
+ if (constructor != null) {
+ sb.write(constructor);
+ } else {
+ sb.write('<unknown>');
+ }
+ sb.write(': ');
+ sb.write(set);
+ needsComma = true;
+ });
+ }
+ sb.write(']');
+ return sb.toString();
+ }
+}
+
class ResolutionWorldBuilderImpl implements ResolutionWorldBuilder {
- /// The set of all directly instantiated classes, that is, classes with a
- /// generative constructor that has been called directly and not only through
- /// a super-call.
+ /// Instantiation information for all classes with instantiated types.
///
/// Invariant: Elements are declaration elements.
- // TODO(johnniwinther): [_directlyInstantiatedClasses] and
- // [_instantiatedTypes] sets should be merged.
- final Map<ClassElement, EnumSet<Instantiation>> _directlyInstantiatedClasses =
- <ClassElement, EnumSet<Instantiation>>{};
-
- /// The set of all directly instantiated types, that is, the types of the
- /// directly instantiated classes.
- ///
- /// See [_directlyInstantiatedClasses].
- final Set<DartType> _instantiatedTypes = new Set<DartType>();
+ final Map<ClassElement, InstantiationInfo> _instantiationInfo =
+ <ClassElement, InstantiationInfo>{};
/// Classes implemented by directly instantiated classes.
final Set<ClassElement> _implementedClasses = new Set<ClassElement>();
@@ -258,6 +407,10 @@
bool hasIsolateSupport = false;
bool hasFunctionApplySupport = false;
+ /// Used for testing the new more precise computation of instantiated types
+ /// and classes.
+ bool useInstantiationMap = false;
+
OpenWorld _openWorld;
ResolutionWorldBuilderImpl(Backend backend, CoreClasses coreClasses,
@@ -272,7 +425,13 @@
/// super-call.
// TODO(johnniwinther): Improve semantic precision.
Iterable<ClassElement> get directlyInstantiatedClasses {
- return _directlyInstantiatedClasses.keys;
+ Set<ClassElement> classes = new Set<ClassElement>();
+ getInstantiationMap().forEach((ClassElement cls, InstantiationInfo info) {
+ if (info.hasInstantiation) {
+ classes.add(cls);
+ }
+ });
+ return classes;
}
/// All directly instantiated types, that is, the types of the directly
@@ -280,7 +439,19 @@
///
/// See [directlyInstantiatedClasses].
// TODO(johnniwinther): Improve semantic precision.
- Iterable<DartType> get instantiatedTypes => _instantiatedTypes;
+ Iterable<DartType> get instantiatedTypes {
+ Set<InterfaceType> types = new Set<InterfaceType>();
+ getInstantiationMap().forEach((_, InstantiationInfo info) {
+ if (info.instantiationMap != null) {
+ for (Set<Instance> instances in info.instantiationMap.values) {
+ for (Instance instance in instances) {
+ types.add(instance.type);
+ }
+ }
+ }
+ });
+ return types;
+ }
/// Returns `true` if [cls] is considered to be implemented by an
/// instantiated class, either directly, through subclasses or through
@@ -298,11 +469,15 @@
// subclass and through subtype instantiated types/classes.
// TODO(johnniwinther): Support unknown type arguments for generic types.
void registerTypeInstantiation(InterfaceType type,
- {bool byMirrors: false,
+ {ConstructorElement constructor,
+ bool byMirrors: false,
bool isNative: false,
+ bool isRedirection: false,
void onImplemented(ClassElement cls)}) {
- _instantiatedTypes.add(type);
ClassElement cls = type.element;
+ InstantiationInfo info =
+ _instantiationInfo.putIfAbsent(cls, () => new InstantiationInfo());
+ Instantiation kind = Instantiation.UNINSTANTIATED;
if (!cls.isAbstract
// We can't use the closed-world assumption with native abstract
// classes; a native abstract class may have non-abstract subclasses
@@ -315,17 +490,17 @@
// TODO(herhut): Track classes required by mirrors seperately.
||
byMirrors) {
- EnumSet<Instantiation> instantiations = _directlyInstantiatedClasses
- .putIfAbsent(cls, () => new EnumSet<Instantiation>());
if (isNative || byMirrors) {
- instantiations.add(Instantiation.ABSTRACTLY_INSTANTIATED);
+ kind = Instantiation.ABSTRACTLY_INSTANTIATED;
} else {
- instantiations.add(Instantiation.DIRECTLY_INSTANTIATED);
+ kind = Instantiation.DIRECTLY_INSTANTIATED;
}
}
+ info.addInstantiation(constructor, type, kind,
+ isRedirection: isRedirection);
- // TODO(johnniwinther): Replace this by separate more specific mappings that
- // include the type arguments.
+ // TODO(johnniwinther): Use [_instantiationInfo] to compute this information
+ // instead.
if (_implementedClasses.add(cls)) {
onImplemented(cls);
cls.allSupertypes.forEach((InterfaceType supertype) {
@@ -337,9 +512,8 @@
}
@override
- void forEachInstantiatedClass(
- f(ClassElement cls, EnumSet<Instantiation> instantiations)) {
- _directlyInstantiatedClasses.forEach(f);
+ void forEachInstantiatedClass(f(ClassElement cls, InstantiationInfo info)) {
+ getInstantiationMap().forEach(f);
}
bool _hasMatchingSelector(Map<Selector, SelectorConstraints> selectors,
@@ -356,6 +530,50 @@
return false;
}
+ /// Returns the instantiation map used for computing the closed world.
+ ///
+ /// If [useInstantiationMap] is `true`, redirections are removed and
+ /// redirecting factories are converted to their effective target and type.
+ Map<ClassElement, InstantiationInfo> getInstantiationMap() {
+ if (!useInstantiationMap) return _instantiationInfo;
+
+ Map<ClassElement, InstantiationInfo> instantiationMap =
+ <ClassElement, InstantiationInfo>{};
+
+ InstantiationInfo infoFor(ClassElement cls) {
+ return instantiationMap.putIfAbsent(cls, () => new InstantiationInfo());
+ }
+
+ _instantiationInfo.forEach((cls, info) {
+ if (info.instantiationMap != null) {
+ info.instantiationMap
+ .forEach((ConstructorElement constructor, Set<Instance> set) {
+ for (Instance instance in set) {
+ if (instance.isRedirection) {
+ continue;
+ }
+ if (constructor == null || !constructor.isRedirectingFactory) {
+ infoFor(cls)
+ .addInstantiation(constructor, instance.type, instance.kind);
+ } else {
+ ConstructorElement target = constructor.effectiveTarget;
+ InterfaceType targetType =
+ constructor.computeEffectiveTargetType(instance.type);
+ Instantiation kind = Instantiation.DIRECTLY_INSTANTIATED;
+ if (target.enclosingClass.isAbstract) {
+ // If target is a factory constructor on an abstract class.
+ kind = Instantiation.UNINSTANTIATED;
+ }
+ infoFor(targetType.element)
+ .addInstantiation(target, targetType, kind);
+ }
+ }
+ });
+ }
+ });
+ return instantiationMap;
+ }
+
bool hasInvocation(Element member, OpenWorld world) {
return _hasMatchingSelector(_invokedNames[member.name], member, world);
}
@@ -422,6 +640,7 @@
case StaticUseKind.FIELD_GET:
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+ case StaticUseKind.REDIRECTION:
break;
case StaticUseKind.CLOSURE:
allClosures.add(element);
@@ -438,12 +657,7 @@
slowDirectlyNestedClosures(element).forEach(compiler.forgetElement);
closurizedMembers.remove(element);
fieldSetters.remove(element);
- _directlyInstantiatedClasses.remove(element);
- if (element is ClassElement) {
- assert(invariant(element, element.thisType.isRaw,
- message: 'Generic classes not supported (${element.thisType}).'));
- _instantiatedTypes..remove(element.rawType)..remove(element.thisType);
- }
+ _instantiationInfo.remove(element);
}
// TODO(ahe): Replace this method with something that is O(1), for example,
@@ -701,6 +915,7 @@
case StaticUseKind.FIELD_GET:
case StaticUseKind.CONSTRUCTOR_INVOKE:
case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
+ case StaticUseKind.REDIRECTION:
case StaticUseKind.DIRECT_INVOKE:
break;
}
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index dd786a4..c406d07 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -25,8 +25,8 @@
import 'universe/function_set.dart' show FunctionSet;
import 'universe/selector.dart' show Selector;
import 'universe/side_effects.dart' show SideEffects;
-import 'universe/world_builder.dart' show ResolutionWorldBuilder;
-import 'util/enumset.dart';
+import 'universe/world_builder.dart'
+ show InstantiationInfo, ResolutionWorldBuilder;
import 'util/util.dart' show Link;
/// Common superinterface for [OpenWorld] and [ClosedWorld].
@@ -1007,7 +1007,10 @@
/// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
/// properties of the [ClassHierarchyNode] for [cls].
- void addSubtypes(ClassElement cls, EnumSet<Instantiation> instantiations) {
+ void addSubtypes(ClassElement cls, InstantiationInfo info) {
+ if (!info.hasInstantiation) {
+ return;
+ }
if (cacheStrategy.hasIncrementalSupport && !alreadyPopulated.add(cls)) {
return;
}
@@ -1017,10 +1020,8 @@
}
_updateClassHierarchyNodeForClass(cls,
- directlyInstantiated:
- instantiations.contains(Instantiation.DIRECTLY_INSTANTIATED),
- abstractlyInstantiated:
- instantiations.contains(Instantiation.ABSTRACTLY_INSTANTIATED));
+ directlyInstantiated: info.isDirectlyInstantiated,
+ abstractlyInstantiated: info.isAbstractlyInstantiated);
// Walk through the superclasses, and record the types
// implemented by that type on the superclasses.
diff --git a/pkg/dev_compiler/lib/js/amd/dart_sdk.js b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
index c2cb697..2ed8598 100644
--- a/pkg/dev_compiler/lib/js/amd/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/amd/dart_sdk.js
@@ -797,43 +797,48 @@
}
return flatten;
};
- dart.generic = function(typeConstructor) {
- let length = typeConstructor.length;
- if (length < 1) {
- dart.throwInternalError('must have at least one generic type argument');
- }
- let resultMap = new Map();
- function makeGenericType(...args) {
- if (args.length != length && args.length != 0) {
- dart.throwInternalError('requires ' + length + ' or 0 type arguments');
+ dart.generic = function(typeConstructor, setBaseClass) {
+ if (setBaseClass === void 0) setBaseClass = null;
+ return (() => {
+ let length = typeConstructor.length;
+ if (length < 1) {
+ dart.throwInternalError('must have at least one generic type argument');
}
- while (args.length < length)
- args.push(dart.dynamic);
- let value = resultMap;
- for (let i = 0; i < length; i++) {
- let arg = args[i];
- if (arg == null) {
- dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
+ let resultMap = new Map();
+ function makeGenericType(...args) {
+ if (args.length != length && args.length != 0) {
+ dart.throwInternalError('requires ' + length + ' or 0 type arguments');
}
- let map = value;
- value = map.get(arg);
- if (value === void 0) {
- if (i + 1 == length) {
- value = typeConstructor.apply(null, args);
- if (value) {
- value[dart._typeArguments] = args;
- value[dart._originalDeclaration] = makeGenericType;
- }
- } else {
- value = new Map();
+ while (args.length < length)
+ args.push(dart.dynamic);
+ let value = resultMap;
+ for (let i = 0; i < length; i++) {
+ let arg = args[i];
+ if (arg == null) {
+ dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
}
- map.set(arg, value);
+ let map = value;
+ value = map.get(arg);
+ if (value === void 0) {
+ if (i + 1 == length) {
+ value = typeConstructor.apply(null, args);
+ if (value) {
+ value[dart._typeArguments] = args;
+ value[dart._originalDeclaration] = makeGenericType;
+ }
+ map.set(arg, value);
+ if (setBaseClass) setBaseClass(value);
+ } else {
+ value = new Map();
+ map.set(arg, value);
+ }
+ }
}
+ return value;
}
- return value;
- }
- makeGenericType[dart._genericTypeCtor] = typeConstructor;
- return makeGenericType;
+ makeGenericType[dart._genericTypeCtor] = typeConstructor;
+ return makeGenericType;
+ })();
};
dart.getGenericClass = function(type) {
return dart.safeGetOwnProperty(type, dart._originalDeclaration);
@@ -26760,7 +26765,6 @@
return this[_nextLink];
}
}
- dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
_UserDoubleLinkedQueueEntry[dart.implements] = () => [DoubleLinkedQueueEntryOfE()];
dart.setSignature(_UserDoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._UserDoubleLinkedQueueEntry$(E), [E])}),
@@ -26774,6 +26778,8 @@
})
});
return _UserDoubleLinkedQueueEntry;
+ }, _UserDoubleLinkedQueueEntry => {
+ dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
});
collection._UserDoubleLinkedQueueEntry = _UserDoubleLinkedQueueEntry();
const _queue = Symbol('_queue');
@@ -26803,7 +26809,6 @@
return this[_previousLink][_asNonSentinelEntry]();
}
}
- dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
dart.setSignature(_DoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._DoubleLinkedQueueEntry$(E), [DoubleLinkedQueueOfE()])}),
fields: () => ({[_queue]: DoubleLinkedQueueOfE()}),
@@ -26815,6 +26820,8 @@
})
});
return _DoubleLinkedQueueEntry;
+ }, _DoubleLinkedQueueEntry => {
+ dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
});
collection._DoubleLinkedQueueEntry = _DoubleLinkedQueueEntry();
const _elementCount = Symbol('_elementCount');
diff --git a/pkg/dev_compiler/lib/js/common/dart_sdk.js b/pkg/dev_compiler/lib/js/common/dart_sdk.js
index 78f09d2..f853c40 100644
--- a/pkg/dev_compiler/lib/js/common/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/common/dart_sdk.js
@@ -797,43 +797,48 @@
}
return flatten;
};
- dart.generic = function(typeConstructor) {
- let length = typeConstructor.length;
- if (length < 1) {
- dart.throwInternalError('must have at least one generic type argument');
- }
- let resultMap = new Map();
- function makeGenericType(...args) {
- if (args.length != length && args.length != 0) {
- dart.throwInternalError('requires ' + length + ' or 0 type arguments');
+ dart.generic = function(typeConstructor, setBaseClass) {
+ if (setBaseClass === void 0) setBaseClass = null;
+ return (() => {
+ let length = typeConstructor.length;
+ if (length < 1) {
+ dart.throwInternalError('must have at least one generic type argument');
}
- while (args.length < length)
- args.push(dart.dynamic);
- let value = resultMap;
- for (let i = 0; i < length; i++) {
- let arg = args[i];
- if (arg == null) {
- dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
+ let resultMap = new Map();
+ function makeGenericType(...args) {
+ if (args.length != length && args.length != 0) {
+ dart.throwInternalError('requires ' + length + ' or 0 type arguments');
}
- let map = value;
- value = map.get(arg);
- if (value === void 0) {
- if (i + 1 == length) {
- value = typeConstructor.apply(null, args);
- if (value) {
- value[dart._typeArguments] = args;
- value[dart._originalDeclaration] = makeGenericType;
- }
- } else {
- value = new Map();
+ while (args.length < length)
+ args.push(dart.dynamic);
+ let value = resultMap;
+ for (let i = 0; i < length; i++) {
+ let arg = args[i];
+ if (arg == null) {
+ dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
}
- map.set(arg, value);
+ let map = value;
+ value = map.get(arg);
+ if (value === void 0) {
+ if (i + 1 == length) {
+ value = typeConstructor.apply(null, args);
+ if (value) {
+ value[dart._typeArguments] = args;
+ value[dart._originalDeclaration] = makeGenericType;
+ }
+ map.set(arg, value);
+ if (setBaseClass) setBaseClass(value);
+ } else {
+ value = new Map();
+ map.set(arg, value);
+ }
+ }
}
+ return value;
}
- return value;
- }
- makeGenericType[dart._genericTypeCtor] = typeConstructor;
- return makeGenericType;
+ makeGenericType[dart._genericTypeCtor] = typeConstructor;
+ return makeGenericType;
+ })();
};
dart.getGenericClass = function(type) {
return dart.safeGetOwnProperty(type, dart._originalDeclaration);
@@ -26760,7 +26765,6 @@
return this[_nextLink];
}
}
- dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
_UserDoubleLinkedQueueEntry[dart.implements] = () => [DoubleLinkedQueueEntryOfE()];
dart.setSignature(_UserDoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._UserDoubleLinkedQueueEntry$(E), [E])}),
@@ -26774,6 +26778,8 @@
})
});
return _UserDoubleLinkedQueueEntry;
+ }, _UserDoubleLinkedQueueEntry => {
+ dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
});
collection._UserDoubleLinkedQueueEntry = _UserDoubleLinkedQueueEntry();
const _queue = Symbol('_queue');
@@ -26803,7 +26809,6 @@
return this[_previousLink][_asNonSentinelEntry]();
}
}
- dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
dart.setSignature(_DoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._DoubleLinkedQueueEntry$(E), [DoubleLinkedQueueOfE()])}),
fields: () => ({[_queue]: DoubleLinkedQueueOfE()}),
@@ -26815,6 +26820,8 @@
})
});
return _DoubleLinkedQueueEntry;
+ }, _DoubleLinkedQueueEntry => {
+ dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
});
collection._DoubleLinkedQueueEntry = _DoubleLinkedQueueEntry();
const _elementCount = Symbol('_elementCount');
diff --git a/pkg/dev_compiler/lib/js/es6/dart_sdk.js b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
index c16638f..bb1cb35 100644
--- a/pkg/dev_compiler/lib/js/es6/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/es6/dart_sdk.js
@@ -795,43 +795,48 @@
}
return flatten;
};
-dart.generic = function(typeConstructor) {
- let length = typeConstructor.length;
- if (length < 1) {
- dart.throwInternalError('must have at least one generic type argument');
- }
- let resultMap = new Map();
- function makeGenericType(...args) {
- if (args.length != length && args.length != 0) {
- dart.throwInternalError('requires ' + length + ' or 0 type arguments');
+dart.generic = function(typeConstructor, setBaseClass) {
+ if (setBaseClass === void 0) setBaseClass = null;
+ return (() => {
+ let length = typeConstructor.length;
+ if (length < 1) {
+ dart.throwInternalError('must have at least one generic type argument');
}
- while (args.length < length)
- args.push(dart.dynamic);
- let value = resultMap;
- for (let i = 0; i < length; i++) {
- let arg = args[i];
- if (arg == null) {
- dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
+ let resultMap = new Map();
+ function makeGenericType(...args) {
+ if (args.length != length && args.length != 0) {
+ dart.throwInternalError('requires ' + length + ' or 0 type arguments');
}
- let map = value;
- value = map.get(arg);
- if (value === void 0) {
- if (i + 1 == length) {
- value = typeConstructor.apply(null, args);
- if (value) {
- value[dart._typeArguments] = args;
- value[dart._originalDeclaration] = makeGenericType;
- }
- } else {
- value = new Map();
+ while (args.length < length)
+ args.push(dart.dynamic);
+ let value = resultMap;
+ for (let i = 0; i < length; i++) {
+ let arg = args[i];
+ if (arg == null) {
+ dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
}
- map.set(arg, value);
+ let map = value;
+ value = map.get(arg);
+ if (value === void 0) {
+ if (i + 1 == length) {
+ value = typeConstructor.apply(null, args);
+ if (value) {
+ value[dart._typeArguments] = args;
+ value[dart._originalDeclaration] = makeGenericType;
+ }
+ map.set(arg, value);
+ if (setBaseClass) setBaseClass(value);
+ } else {
+ value = new Map();
+ map.set(arg, value);
+ }
+ }
}
+ return value;
}
- return value;
- }
- makeGenericType[dart._genericTypeCtor] = typeConstructor;
- return makeGenericType;
+ makeGenericType[dart._genericTypeCtor] = typeConstructor;
+ return makeGenericType;
+ })();
};
dart.getGenericClass = function(type) {
return dart.safeGetOwnProperty(type, dart._originalDeclaration);
@@ -26758,7 +26763,6 @@
return this[_nextLink];
}
}
- dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
_UserDoubleLinkedQueueEntry[dart.implements] = () => [DoubleLinkedQueueEntryOfE()];
dart.setSignature(_UserDoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._UserDoubleLinkedQueueEntry$(E), [E])}),
@@ -26772,6 +26776,8 @@
})
});
return _UserDoubleLinkedQueueEntry;
+}, _UserDoubleLinkedQueueEntry => {
+ dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
});
collection._UserDoubleLinkedQueueEntry = _UserDoubleLinkedQueueEntry();
const _queue = Symbol('_queue');
@@ -26801,7 +26807,6 @@
return this[_previousLink][_asNonSentinelEntry]();
}
}
- dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
dart.setSignature(_DoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._DoubleLinkedQueueEntry$(E), [DoubleLinkedQueueOfE()])}),
fields: () => ({[_queue]: DoubleLinkedQueueOfE()}),
@@ -26813,6 +26818,8 @@
})
});
return _DoubleLinkedQueueEntry;
+}, _DoubleLinkedQueueEntry => {
+ dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
});
collection._DoubleLinkedQueueEntry = _DoubleLinkedQueueEntry();
const _elementCount = Symbol('_elementCount');
diff --git a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
index 2312c34..09a7b16 100644
--- a/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
+++ b/pkg/dev_compiler/lib/js/legacy/dart_sdk.js
@@ -798,43 +798,48 @@
}
return flatten;
};
- dart.generic = function(typeConstructor) {
- let length = typeConstructor.length;
- if (length < 1) {
- dart.throwInternalError('must have at least one generic type argument');
- }
- let resultMap = new Map();
- function makeGenericType(...args) {
- if (args.length != length && args.length != 0) {
- dart.throwInternalError('requires ' + length + ' or 0 type arguments');
+ dart.generic = function(typeConstructor, setBaseClass) {
+ if (setBaseClass === void 0) setBaseClass = null;
+ return (() => {
+ let length = typeConstructor.length;
+ if (length < 1) {
+ dart.throwInternalError('must have at least one generic type argument');
}
- while (args.length < length)
- args.push(dart.dynamic);
- let value = resultMap;
- for (let i = 0; i < length; i++) {
- let arg = args[i];
- if (arg == null) {
- dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
+ let resultMap = new Map();
+ function makeGenericType(...args) {
+ if (args.length != length && args.length != 0) {
+ dart.throwInternalError('requires ' + length + ' or 0 type arguments');
}
- let map = value;
- value = map.get(arg);
- if (value === void 0) {
- if (i + 1 == length) {
- value = typeConstructor.apply(null, args);
- if (value) {
- value[dart._typeArguments] = args;
- value[dart._originalDeclaration] = makeGenericType;
- }
- } else {
- value = new Map();
+ while (args.length < length)
+ args.push(dart.dynamic);
+ let value = resultMap;
+ for (let i = 0; i < length; i++) {
+ let arg = args[i];
+ if (arg == null) {
+ dart.throwInternalError('type arguments should not be null: ' + typeConstructor);
}
- map.set(arg, value);
+ let map = value;
+ value = map.get(arg);
+ if (value === void 0) {
+ if (i + 1 == length) {
+ value = typeConstructor.apply(null, args);
+ if (value) {
+ value[dart._typeArguments] = args;
+ value[dart._originalDeclaration] = makeGenericType;
+ }
+ map.set(arg, value);
+ if (setBaseClass) setBaseClass(value);
+ } else {
+ value = new Map();
+ map.set(arg, value);
+ }
+ }
}
+ return value;
}
- return value;
- }
- makeGenericType[dart._genericTypeCtor] = typeConstructor;
- return makeGenericType;
+ makeGenericType[dart._genericTypeCtor] = typeConstructor;
+ return makeGenericType;
+ })();
};
dart.getGenericClass = function(type) {
return dart.safeGetOwnProperty(type, dart._originalDeclaration);
@@ -26761,7 +26766,6 @@
return this[_nextLink];
}
}
- dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
_UserDoubleLinkedQueueEntry[dart.implements] = () => [DoubleLinkedQueueEntryOfE()];
dart.setSignature(_UserDoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._UserDoubleLinkedQueueEntry$(E), [E])}),
@@ -26775,6 +26779,8 @@
})
});
return _UserDoubleLinkedQueueEntry;
+ }, _UserDoubleLinkedQueueEntry => {
+ dart.setBaseClass(_UserDoubleLinkedQueueEntry, collection._DoubleLink$(_UserDoubleLinkedQueueEntry));
});
collection._UserDoubleLinkedQueueEntry = _UserDoubleLinkedQueueEntry();
const _queue = Symbol('_queue');
@@ -26804,7 +26810,6 @@
return this[_previousLink][_asNonSentinelEntry]();
}
}
- dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
dart.setSignature(_DoubleLinkedQueueEntry, {
constructors: () => ({new: dart.definiteFunctionType(collection._DoubleLinkedQueueEntry$(E), [DoubleLinkedQueueOfE()])}),
fields: () => ({[_queue]: DoubleLinkedQueueOfE()}),
@@ -26816,6 +26821,8 @@
})
});
return _DoubleLinkedQueueEntry;
+ }, _DoubleLinkedQueueEntry => {
+ dart.setBaseClass(_DoubleLinkedQueueEntry, collection._DoubleLink$(_DoubleLinkedQueueEntry));
});
collection._DoubleLinkedQueueEntry = _DoubleLinkedQueueEntry();
const _elementCount = Symbol('_elementCount');
diff --git a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
index 79fff65..04077ed 100644
--- a/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
+++ b/pkg/dev_compiler/lib/sdk/ddc_sdk.sum
Binary files differ
diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
index 231fcb9..b7f3d5a 100644
--- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
@@ -767,7 +767,8 @@
// Emit things that come after the ES6 `class ... { ... }`.
var jsPeerNames = _getJSPeerNames(classElem);
- _setBaseClass(classElem, className, jsPeerNames, body);
+ JS.Statement deferredBaseClass =
+ _setBaseClass(classElem, className, jsPeerNames, body);
_emitClassTypeTests(classElem, className, body);
@@ -779,9 +780,11 @@
_emitClassMetadata(node.metadata, className, body);
JS.Statement classDef = _statement(body);
+
var typeFormals = classElem.typeParameters;
if (typeFormals.isNotEmpty) {
- classDef = _defineClassTypeArguments(classElem, typeFormals, classDef);
+ classDef = _defineClassTypeArguments(
+ classElem, typeFormals, classDef, className, deferredBaseClass);
}
body = <JS.Statement>[classDef];
@@ -1126,14 +1129,23 @@
/// Wraps a possibly generic class in its type arguments.
JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
- List<TypeParameterElement> formals, JS.Statement body) {
+ List<TypeParameterElement> formals, JS.Statement body,
+ [JS.Expression className, JS.Statement deferredBaseClass]) {
assert(formals.isNotEmpty);
- var genericCall = _callHelper('generic((#) => { #; #; return #; })', [
+ var typeConstructor = js.call('(#) => { #; #; return #; }', [
_emitTypeFormals(formals),
_typeTable.discharge(formals),
body,
element.name
]);
+
+ var genericArgs = [typeConstructor];
+ if (deferredBaseClass != null) {
+ genericArgs.add(js.call('(#) => { #; }', [className, deferredBaseClass]));
+ }
+
+ var genericCall = _callHelper('generic(#)', [genericArgs]);
+
if (element.library.isDartAsync &&
(element.name == "Future" || element.name == "_Future")) {
genericCall = _callHelper('flattenFutures(#)', [genericCall]);
@@ -1601,9 +1613,10 @@
}
}
- void _setBaseClass(ClassElement classElem, JS.Expression className,
+ JS.Statement _setBaseClass(ClassElement classElem, JS.Expression className,
List<String> jsPeerNames, List<JS.Statement> body) {
- if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) {
+ var typeFormals = classElem.typeParameters;
+ if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) {
for (var peer in jsPeerNames) {
// TODO(jmesserly): we should just extend Array in the first place
var newBaseClass = _callHelper('global.#', [peer]);
@@ -1613,9 +1626,12 @@
} else if (_hasDeferredSupertype.contains(classElem)) {
var newBaseClass = _emitType(classElem.type.superclass,
nameType: false, subClass: classElem, className: className);
- body.add(_callHelperStatement(
- 'setBaseClass(#, #);', [className, newBaseClass]));
+ var deferredBaseClass = _callHelperStatement(
+ 'setBaseClass(#, #);', [className, newBaseClass]);
+ if (typeFormals.isNotEmpty) return deferredBaseClass;
+ body.add(deferredBaseClass);
}
+ return null;
}
void _defineNamedConstructors(List<ConstructorDeclaration> ctors,
@@ -2954,7 +2970,7 @@
hoistType: hoistType,
subClass: subClass,
className: className));
- } else if (lowerGeneric) {
+ } else if (lowerGeneric || element == subClass) {
jsArgs = [];
}
if (jsArgs != null) {
diff --git a/pkg/dev_compiler/test/codegen/language/field_test.dart b/pkg/dev_compiler/test/codegen/language/field_test.dart
index 6a1937f..ca41740 100644
--- a/pkg/dev_compiler/test/codegen/language/field_test.dart
+++ b/pkg/dev_compiler/test/codegen/language/field_test.dart
@@ -52,11 +52,11 @@
// The tests below are a little cumbersome because not
// everything is implemented yet.
var o = new Second();
- // 'a' getter is overriden, always returns -12.
+ // 'a' getter is overridden, always returns -12.
Expect.equals(-12, o.a);
o.a = 2;
Expect.equals(-12, o.a);
- // 'b' setter is overriden to write 12 to field 'c'.
+ // 'b' setter is overridden to write 12 to field 'c'.
o.b = o;
Expect.equals(12, o.c);
}
diff --git a/pkg/dev_compiler/test/codegen/language/recursive_generic_test.dart b/pkg/dev_compiler/test/codegen/language/recursive_generic_test.dart
new file mode 100644
index 0000000..3d8dcd6
--- /dev/null
+++ b/pkg/dev_compiler/test/codegen/language/recursive_generic_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:expect/expect.dart";
+
+abstract class S<T extends S<T>> { m() => 123; get S_T => T; }
+class C<T extends C<T>> extends S<C> { m() => 456; get C_T => T; }
+
+main() {
+ Expect.equals(new C().m(), 456);
+ // TODO(jmesserly): this should be dart1 vs dart2, not DDC vs VM.
+ var isVM = const bool.fromEnvironment('dart.isVM');
+ Expect.equals(new C().S_T.toString(), isVM ? 'C' : 'C<C>');
+ Expect.equals(new C().C_T.toString(), isVM ? 'dynamic' : 'C');
+}
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/convert/utf.dart b/pkg/dev_compiler/tool/input_sdk/lib/convert/utf.dart
index 69bb72c..486ab4d 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/convert/utf.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/convert/utf.dart
@@ -37,7 +37,7 @@
* The optional [allowMalformed] argument defines how [decoder] (and [decode])
* deal with invalid or unterminated character sequences.
*
- * If it is `true` (and not overriden at the method invocation) [decode] and
+ * If it is `true` (and not overridden at the method invocation) [decode] and
* the [decoder] replace invalid (or unterminated) octet
* sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
* they throw a [FormatException].
diff --git a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
index 1582f0d..34636a7 100644
--- a/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
+++ b/pkg/dev_compiler/tool/input_sdk/lib/js/dart2js/js_dart2js.dart
@@ -383,7 +383,7 @@
super['length'] = length;
}
- // Methods overriden for better performance
+ // Methods overridden for better performance
void add(E value) {
callMethod('push', [value]);
diff --git a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
index 1c77871..1899f96 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/classes.dart
@@ -97,7 +97,7 @@
})()''');
/// Memoize a generic type constructor function.
-generic(typeConstructor) => JS(
+generic(typeConstructor, [setBaseClass]) => JS(
'',
'''(() => {
let length = $typeConstructor.length;
@@ -128,10 +128,12 @@
value[$_typeArguments] = args;
value[$_originalDeclaration] = makeGenericType;
}
+ map.set(arg, value);
+ if ($setBaseClass) $setBaseClass(value);
} else {
value = new Map();
+ map.set(arg, value);
}
- map.set(arg, value);
}
}
return value;
diff --git a/runtime/bin/builtin_impl_sources.gypi b/runtime/bin/builtin_impl_sources.gypi
index 846244a..a60f8a8 100644
--- a/runtime/bin/builtin_impl_sources.gypi
+++ b/runtime/bin/builtin_impl_sources.gypi
@@ -37,6 +37,7 @@
'extensions_win.cc',
'fdutils.h',
'fdutils_android.cc',
+ 'fdutils_fuchsia.cc',
'fdutils_linux.cc',
'fdutils_macos.cc',
'file.cc',
diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc
index 2d0ebe3..c298e22 100644
--- a/runtime/bin/eventhandler_fuchsia.cc
+++ b/runtime/bin/eventhandler_fuchsia.cc
@@ -10,13 +10,25 @@
#include "bin/eventhandler.h"
#include "bin/eventhandler_fuchsia.h"
-#include <magenta/status.h>
-#include <magenta/syscalls.h>
+#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
+#include <pthread.h> // NOLINT
+#include <stdio.h> // NOLINT
+#include <string.h> // NOLINT
+#include <sys/epoll.h> // NOLINT
+#include <sys/stat.h> // NOLINT
+#include <unistd.h> // NOLINT
+#include "bin/fdutils.h"
+#include "bin/lockers.h"
#include "bin/log.h"
+#include "bin/socket.h"
#include "bin/thread.h"
#include "bin/utils.h"
+#include "platform/hashmap.h"
+#include "platform/utils.h"
+// #define EVENTHANDLER_LOGGING 1
#if defined(EVENTHANDLER_LOGGING)
#define LOG_ERR(msg, ...) Log::PrintErr(msg, ##__VA_ARGS__)
#define LOG_INFO(msg, ...) Log::Print(msg, ##__VA_ARGS__)
@@ -28,115 +40,204 @@
namespace dart {
namespace bin {
-MagentaWaitManyInfo::MagentaWaitManyInfo()
- : capacity_(kInitialCapacity), size_(0) {
- descriptor_infos_ = static_cast<DescriptorInfo**>(
- malloc(kInitialCapacity * sizeof(*descriptor_infos_)));
- if (descriptor_infos_ == NULL) {
- FATAL("Failed to allocate descriptor_infos array");
+#if defined(EVENTHANDLER_LOGGING)
+static void PrintEventMask(intptr_t fd, intptr_t events) {
+ Log::PrintErr("%d ", fd);
+ if ((events & EPOLLIN) != 0) {
+ Log::PrintErr("EPOLLIN ");
}
- items_ =
- static_cast<mx_wait_item_t*>(malloc(kInitialCapacity * sizeof(*items_)));
- if (items_ == NULL) {
- FATAL("Failed to allocate items array");
+ if ((events & EPOLLPRI) != 0) {
+ Log::PrintErr("EPOLLPRI ");
}
+ if ((events & EPOLLOUT) != 0) {
+ Log::PrintErr("EPOLLOUT ");
+ }
+ if ((events & EPOLLERR) != 0) {
+ Log::PrintErr("EPOLLERR ");
+ }
+ if ((events & EPOLLHUP) != 0) {
+ Log::PrintErr("EPOLLHUP ");
+ }
+ if ((events & EPOLLRDHUP) != 0) {
+ Log::PrintErr("EPOLLRDHUP ");
+ }
+ int all_events =
+ EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDHUP;
+ if ((events & ~all_events) != 0) {
+ Log::PrintErr("(and %08x) ", events & ~all_events);
+ }
+
+ Log::PrintErr("\n");
}
-
-
-MagentaWaitManyInfo::~MagentaWaitManyInfo() {
- free(descriptor_infos_);
- free(items_);
-}
-
-
-void MagentaWaitManyInfo::AddHandle(mx_handle_t handle,
- mx_signals_t signals,
- DescriptorInfo* di) {
-#if defined(DEBUG)
- // Check that the handle is not already in the list.
- for (intptr_t i = 0; i < size_; i++) {
- if (items_[i].handle == handle) {
- FATAL("The handle is already in the list!");
- }
- }
#endif
- intptr_t new_size = size_ + 1;
- GrowArraysIfNeeded(new_size);
- descriptor_infos_[size_] = di;
- items_[size_].handle = handle;
- items_[size_].waitfor = signals;
- items_[size_].pending = 0;
- size_ = new_size;
- LOG_INFO("AddHandle(%ld, %ld, %p), size = %ld\n", handle, signals, di, size_);
+
+
+intptr_t DescriptorInfo::GetPollEvents() {
+ // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
+ // triggered anyway.
+ intptr_t events = 0;
+ if ((Mask() & (1 << kInEvent)) != 0) {
+ events |= EPOLLIN;
+ }
+ if ((Mask() & (1 << kOutEvent)) != 0) {
+ events |= EPOLLOUT;
+ }
+ return events;
}
-void MagentaWaitManyInfo::RemoveHandle(mx_handle_t handle) {
- intptr_t idx;
- for (idx = 1; idx < size_; idx++) {
- if (handle == items_[idx].handle) {
- break;
- }
- }
- if (idx == size_) {
- FATAL("Handle is not in the list!");
- }
-
- if (idx != (size_ - 1)) {
- descriptor_infos_[idx] = descriptor_infos_[size_ - 1];
- items_[idx] = items_[size_ - 1];
- }
- descriptor_infos_[size_ - 1] = NULL;
- items_[size_ - 1] = {MX_HANDLE_INVALID, 0, 0};
- size_ = size_ - 1;
- LOG_INFO("RemoveHandle(%ld), size = %ld\n", handle, size_);
+// Unregister the file descriptor for a DescriptorInfo structure with
+// epoll.
+static void RemoveFromEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) {
+ LOG_INFO("RemoveFromEpollInstance: fd = %ld\n", di->fd());
+ VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, di->fd(), NULL));
}
-void MagentaWaitManyInfo::GrowArraysIfNeeded(intptr_t desired_size) {
- if (desired_size < capacity_) {
- return;
+static void AddToEpollInstance(intptr_t epoll_fd_, DescriptorInfo* di) {
+ struct epoll_event event;
+ event.events = EPOLLRDHUP | di->GetPollEvents();
+ if (!di->IsListeningSocket()) {
+ event.events |= EPOLLET;
}
- intptr_t new_capacity = desired_size + (desired_size >> 1);
- descriptor_infos_ = static_cast<DescriptorInfo**>(
- realloc(descriptor_infos_, new_capacity * sizeof(*descriptor_infos_)));
- if (descriptor_infos_ == NULL) {
- FATAL("Failed to grow descriptor_infos array");
+ event.data.ptr = di;
+ LOG_INFO("AddToEpollInstance: fd = %ld\n", di->fd());
+ int status =
+ NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, di->fd(), &event));
+ LOG_INFO("AddToEpollInstance: fd = %ld, status = %d\n", di->fd(), status);
+#if defined(EVENTHANDLER_LOGGING)
+ PrintEventMask(di->fd(), event.events);
+#endif
+ if (status == -1) {
+ // TODO(dart:io): Verify that the dart end is handling this correctly.
+
+ // Epoll does not accept the file descriptor. It could be due to
+ // already closed file descriptor, or unuspported devices, such
+ // as /dev/null. In such case, mark the file descriptor as closed,
+ // so dart will handle it accordingly.
+ di->NotifyAllDartPorts(1 << kCloseEvent);
}
- items_ = static_cast<mx_wait_item_t*>(
- realloc(items_, new_capacity * sizeof(*items_)));
- if (items_ == NULL) {
- FATAL("Failed to grow items array");
- }
- capacity_ = new_capacity;
- LOG_INFO("GrowArraysIfNeeded(%ld), capacity = %ld\n", desired_size,
- capacity_);
}
-EventHandlerImplementation::EventHandlerImplementation() {
- mx_status_t status =
- mx_channel_create(0, &interrupt_handles_[0], &interrupt_handles_[1]);
- if (status != NO_ERROR) {
- FATAL1("mx_channel_create failed: %s\n", mx_status_get_string(status));
+EventHandlerImplementation::EventHandlerImplementation()
+ : socket_map_(&HashMap::SamePointerValue, 16) {
+ intptr_t result;
+ result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
+ if (result != 0) {
+ FATAL("Pipe creation failed");
+ }
+ if (!FDUtils::SetNonBlocking(interrupt_fds_[0])) {
+ FATAL("Failed to set pipe fd non blocking\n");
+ }
+ if (!FDUtils::SetCloseOnExec(interrupt_fds_[0])) {
+ FATAL("Failed to set pipe fd close on exec\n");
+ }
+ if (!FDUtils::SetCloseOnExec(interrupt_fds_[1])) {
+ FATAL("Failed to set pipe fd close on exec\n");
}
shutdown_ = false;
- info_.AddHandle(interrupt_handles_[0],
- MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, NULL);
- LOG_INFO("EventHandlerImplementation initialized\n");
+ // The initial size passed to epoll_create is ignore on newer (>=
+ // 2.6.8) Linux versions
+ static const int kEpollInitialSize = 64;
+ epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
+ if (epoll_fd_ == -1) {
+ FATAL1("Failed creating epoll file descriptor: %i", errno);
+ }
+ if (!FDUtils::SetCloseOnExec(epoll_fd_)) {
+ FATAL("Failed to set epoll fd close on exec\n");
+ }
+ // Register the interrupt_fd with the epoll instance.
+ struct epoll_event event;
+ event.events = EPOLLIN;
+ event.data.ptr = NULL;
+ LOG_INFO("EventHandlerImplementation(): epoll_ctl: fd = %ld\n", epoll_fd_);
+ int status = NO_RETRY_EXPECTED(
+ epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupt_fds_[0], &event));
+ LOG_INFO("EventHandlerImplementation(): epoll_ctl: fd = %ld, status = %d\n",
+ epoll_fd_, status);
+ if (status == -1) {
+ FATAL("Failed adding interrupt fd to epoll instance");
+ }
+}
+
+
+static void DeleteDescriptorInfo(void* info) {
+ DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(info);
+ di->Close();
+ LOG_INFO("Closed %d\n", di->fd());
+ delete di;
}
EventHandlerImplementation::~EventHandlerImplementation() {
- mx_status_t status = mx_handle_close(interrupt_handles_[0]);
- if (status != NO_ERROR) {
- FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status));
+ socket_map_.Clear(DeleteDescriptorInfo);
+ VOID_NO_RETRY_EXPECTED(close(epoll_fd_));
+ VOID_NO_RETRY_EXPECTED(close(interrupt_fds_[0]));
+ VOID_NO_RETRY_EXPECTED(close(interrupt_fds_[1]));
+}
+
+
+void EventHandlerImplementation::UpdateEpollInstance(intptr_t old_mask,
+ DescriptorInfo* di) {
+ intptr_t new_mask = di->Mask();
+ LOG_INFO("UpdateEpollInstance: %d old=%ld, new=%ld\n", di->fd(), old_mask,
+ new_mask);
+ if ((old_mask != 0) && (new_mask == 0)) {
+ RemoveFromEpollInstance(epoll_fd_, di);
+ } else if ((old_mask == 0) && (new_mask != 0)) {
+ AddToEpollInstance(epoll_fd_, di);
+ } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) {
+ ASSERT(!di->IsListeningSocket());
+ RemoveFromEpollInstance(epoll_fd_, di);
+ AddToEpollInstance(epoll_fd_, di);
}
- status = mx_handle_close(interrupt_handles_[1]);
- if (status != NO_ERROR) {
- FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status));
+}
+
+
+DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo(
+ intptr_t fd,
+ bool is_listening) {
+ ASSERT(fd >= 0);
+ HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd),
+ GetHashmapHashFromFd(fd), true);
+ ASSERT(entry != NULL);
+ DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(entry->value);
+ if (di == NULL) {
+ // If there is no data in the hash map for this file descriptor a
+ // new DescriptorInfo for the file descriptor is inserted.
+ if (is_listening) {
+ di = new DescriptorInfoMultiple(fd);
+ } else {
+ di = new DescriptorInfoSingle(fd);
+ }
+ entry->value = di;
}
- LOG_INFO("EventHandlerImplementation destroyed\n");
+ ASSERT(fd == di->fd());
+ return di;
+}
+
+
+static ssize_t WriteToBlocking(int fd, const void* buffer, size_t count) {
+ size_t remaining = count;
+ char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
+ while (remaining > 0) {
+ ssize_t bytes_written = NO_RETRY_EXPECTED(write(fd, buffer_pos, remaining));
+ if (bytes_written == 0) {
+ return count - remaining;
+ } else if (bytes_written == -1) {
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ // Error code EWOULDBLOCK should only happen for non blocking
+ // file descriptors.
+ ASSERT(errno != EWOULDBLOCK);
+ return -1;
+ } else {
+ ASSERT(bytes_written > 0);
+ remaining -= bytes_written;
+ buffer_pos += bytes_written;
+ }
+ }
+ return count;
}
@@ -147,71 +248,171 @@
msg.id = id;
msg.dart_port = dart_port;
msg.data = data;
-
- mx_status_t status =
- mx_channel_write(interrupt_handles_[1], 0, &msg, sizeof(msg), NULL, 0);
- if (status != NO_ERROR) {
- FATAL1("mx_channel_write failed: %s\n", mx_status_get_string(status));
+ // WriteToBlocking will write up to 512 bytes atomically, and since our msg
+ // is smaller than 512, we don't need a thread lock.
+ // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'.
+ ASSERT(kInterruptMessageSize < PIPE_BUF);
+ intptr_t result =
+ WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize);
+ if (result != kInterruptMessageSize) {
+ if (result == -1) {
+ perror("Interrupt message failure:");
+ }
+ FATAL1("Interrupt message failure. Wrote %" Pd " bytes.", result);
}
- LOG_INFO("WakeupHandler(%ld, %ld, %lld)\n", id, dart_port, data);
}
void EventHandlerImplementation::HandleInterruptFd() {
- LOG_INFO("HandleInterruptFd entry\n");
- InterruptMessage msg;
- uint32_t bytes = kInterruptMessageSize;
- mx_status_t status;
- while (true) {
- status = mx_channel_read(interrupt_handles_[0], 0, &msg, bytes, &bytes,
- NULL, 0, NULL);
- if (status != NO_ERROR) {
- break;
- }
- ASSERT(bytes == kInterruptMessageSize);
- if (msg.id == kTimerId) {
+ const intptr_t MAX_MESSAGES = kInterruptMessageSize;
+ InterruptMessage msg[MAX_MESSAGES];
+ ssize_t bytes = NO_RETRY_EXPECTED(
+ read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize));
+ LOG_INFO("HandleInterruptFd read %ld bytes\n", bytes);
+ for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) {
+ if (msg[i].id == kTimerId) {
LOG_INFO("HandleInterruptFd read timer update\n");
- timeout_queue_.UpdateTimeout(msg.dart_port, msg.data);
- } else if (msg.id == kShutdownId) {
+ timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data);
+ } else if (msg[i].id == kShutdownId) {
LOG_INFO("HandleInterruptFd read shutdown\n");
shutdown_ = true;
} else {
- // TODO(zra): Handle commands to add and remove handles from the
- // MagentaWaitManyInfo.
- UNIMPLEMENTED();
+ ASSERT((msg[i].data & COMMAND_MASK) != 0);
+ LOG_INFO("HandleInterruptFd command\n");
+ DescriptorInfo* di =
+ GetDescriptorInfo(msg[i].id, IS_LISTENING_SOCKET(msg[i].data));
+ if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) {
+ ASSERT(!di->IsListeningSocket());
+ // Close the socket for reading.
+ LOG_INFO("\tSHUT_RD: %d\n", di->fd());
+ VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_RD));
+ } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) {
+ ASSERT(!di->IsListeningSocket());
+ // Close the socket for writing.
+ LOG_INFO("\tSHUT_WR: %d\n", di->fd());
+ VOID_NO_RETRY_EXPECTED(shutdown(di->fd(), SHUT_WR));
+ } else if (IS_COMMAND(msg[i].data, kCloseCommand)) {
+ // Close the socket and free system resources and move on to next
+ // message.
+ intptr_t old_mask = di->Mask();
+ Dart_Port port = msg[i].dart_port;
+ di->RemovePort(port);
+ intptr_t new_mask = di->Mask();
+ UpdateEpollInstance(old_mask, di);
+
+ LOG_INFO("\tCLOSE: %d: %lx -> %lx\n", di->fd(), old_mask, new_mask);
+ intptr_t fd = di->fd();
+ if (di->IsListeningSocket()) {
+ // We only close the socket file descriptor from the operating
+ // system if there are no other dart socket objects which
+ // are listening on the same (address, port) combination.
+ ListeningSocketRegistry* registry =
+ ListeningSocketRegistry::Instance();
+
+ MutexLocker locker(registry->mutex());
+
+ if (registry->CloseSafe(fd)) {
+ ASSERT(new_mask == 0);
+ socket_map_.Remove(GetHashmapKeyFromFd(fd),
+ GetHashmapHashFromFd(fd));
+ di->Close();
+ LOG_INFO("Closed %d\n", di->fd());
+ delete di;
+ }
+ } else {
+ ASSERT(new_mask == 0);
+ socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
+ di->Close();
+ LOG_INFO("Closed %d\n", di->fd());
+ delete di;
+ }
+
+ DartUtils::PostInt32(port, 1 << kDestroyedEvent);
+ } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) {
+ int count = TOKEN_COUNT(msg[i].data);
+ intptr_t old_mask = di->Mask();
+ LOG_INFO("\t Return Token: %d: %lx\n", di->fd(), old_mask);
+ di->ReturnTokens(msg[i].dart_port, count);
+ UpdateEpollInstance(old_mask, di);
+ } else if (IS_COMMAND(msg[i].data, kSetEventMaskCommand)) {
+ // `events` can only have kInEvent/kOutEvent flags set.
+ intptr_t events = msg[i].data & EVENT_MASK;
+ ASSERT(0 == (events & ~(1 << kInEvent | 1 << kOutEvent)));
+
+ intptr_t old_mask = di->Mask();
+ LOG_INFO("\t Set Event Mask: %d: %lx %lx\n", di->fd(), old_mask,
+ msg[i].data & EVENT_MASK);
+ di->SetPortAndMask(msg[i].dart_port, msg[i].data & EVENT_MASK);
+ UpdateEpollInstance(old_mask, di);
+ } else {
+ UNREACHABLE();
+ }
}
}
- // status == ERR_SHOULD_WAIT when we try to read and there are no messages
- // available, so it is an error if we get here and status != ERR_SHOULD_WAIT.
- if (status != ERR_SHOULD_WAIT) {
- FATAL1("mx_channel_read failed: %s\n", mx_status_get_string(status));
- }
LOG_INFO("HandleInterruptFd exit\n");
}
-void EventHandlerImplementation::HandleEvents() {
- LOG_INFO("HandleEvents entry\n");
- for (intptr_t i = 1; i < info_.size(); i++) {
- const mx_wait_item_t& wait_item = info_.items()[i];
- if (wait_item.pending & wait_item.waitfor) {
- // Only the control handle has no descriptor info.
- ASSERT(info_.descriptor_infos()[i] != NULL);
- ASSERT(wait_item.handle != interrupt_handles_[0]);
- // TODO(zra): Handle events on other handles. At the moment we are
- // only interrupted when there is a message on interrupt_handles_[0].
- UNIMPLEMENTED();
+intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
+ DescriptorInfo* di) {
+#ifdef EVENTHANDLER_LOGGING
+ PrintEventMask(di->fd(), events);
+#endif
+ if ((events & EPOLLERR) != 0) {
+ // Return error only if EPOLLIN is present.
+ return ((events & EPOLLIN) != 0) ? (1 << kErrorEvent) : 0;
+ }
+ intptr_t event_mask = 0;
+ if ((events & EPOLLIN) != 0) {
+ event_mask |= (1 << kInEvent);
+ }
+ if ((events & EPOLLOUT) != 0) {
+ event_mask |= (1 << kOutEvent);
+ }
+ if ((events & (EPOLLHUP | EPOLLRDHUP)) != 0) {
+ event_mask |= (1 << kCloseEvent);
+ }
+ return event_mask;
+}
+
+
+void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
+ int size) {
+ bool interrupt_seen = false;
+ for (int i = 0; i < size; i++) {
+ if (events[i].data.ptr == NULL) {
+ interrupt_seen = true;
+ } else {
+ DescriptorInfo* di =
+ reinterpret_cast<DescriptorInfo*>(events[i].data.ptr);
+ intptr_t event_mask = GetPollEvents(events[i].events, di);
+
+ if ((event_mask & (1 << kErrorEvent)) != 0) {
+ di->NotifyAllDartPorts(event_mask);
+ }
+ event_mask &= ~(1 << kErrorEvent);
+
+ LOG_INFO("HandleEvents: fd=%ld events=%ld\n", di->fd(), event_mask);
+ if (event_mask != 0) {
+ intptr_t old_mask = di->Mask();
+ Dart_Port port = di->NextNotifyDartPort(event_mask);
+ ASSERT(port != 0);
+ UpdateEpollInstance(old_mask, di);
+ LOG_INFO("HandleEvents: Posting %ld to %ld for fd=%ld\n", event_mask,
+ port, di->fd());
+ bool success = DartUtils::PostInt32(port, event_mask);
+ if (!success) {
+ // This can happen if e.g. the isolate that owns the port has died
+ // for some reason.
+ FATAL2("Failed to post event for fd %ld to port %ld", di->fd(), port);
+ }
+ }
}
}
-
- if ((info_.items()[0].pending & MX_SIGNAL_PEER_CLOSED) != 0) {
- FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n");
- }
- if ((info_.items()[0].pending & MX_SIGNAL_READABLE) != 0) {
- LOG_INFO("HandleEvents interrupt_handles_[0] readable\n");
+ if (interrupt_seen) {
+ // Handle after socket events, so we avoid closing a socket before we handle
+ // the current events.
HandleInterruptFd();
- } else {
- LOG_INFO("HandleEvents interrupt_handles_[0] not readable\n");
}
}
@@ -239,6 +440,8 @@
void EventHandlerImplementation::Poll(uword args) {
+ static const intptr_t kMaxEvents = 16;
+ struct epoll_event events[kMaxEvents];
EventHandler* handler = reinterpret_cast<EventHandler*>(args);
EventHandlerImplementation* handler_impl = &handler->delegate_;
ASSERT(handler_impl != NULL);
@@ -246,23 +449,21 @@
while (!handler_impl->shutdown_) {
int64_t millis = handler_impl->GetTimeout();
ASSERT((millis == kInfinityTimeout) || (millis >= 0));
- mx_time_t timeout =
- millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond;
- const MagentaWaitManyInfo& info = handler_impl->info();
- LOG_INFO("mx_handle_wait_many(%p, %ld, %lld)\n", info.items(), info.size(),
- timeout);
- mx_status_t status =
- mx_handle_wait_many(info.items(), info.size(), timeout);
- if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) {
- FATAL1("mx_handle_wait_many failed: %s\n", mx_status_get_string(status));
+ LOG_INFO("epoll_wait(millis = %ld)\n", millis);
+ intptr_t result = NO_RETRY_EXPECTED(
+ epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ LOG_INFO("epoll_wait(millis = %ld) -> %ld\n", millis, result);
+ if (result < 0) {
+ if (errno != EWOULDBLOCK) {
+ perror("Poll failed");
+ }
} else {
- LOG_INFO("mx_handle_wait_many returned: %ld\n", status);
handler_impl->HandleTimeout();
- handler_impl->HandleEvents();
+ handler_impl->HandleEvents(events, result);
}
}
handler->NotifyShutdownDone();
- LOG_INFO("EventHandlerImplementation notifying about shutdown\n");
}
@@ -286,6 +487,17 @@
WakeupHandler(id, dart_port, data);
}
+void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
+ // The hashmap does not support keys with value 0.
+ return reinterpret_cast<void*>(fd + 1);
+}
+
+
+uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
+ // The hashmap does not support keys with value 0.
+ return dart::Utils::WordHash(fd + 1);
+}
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/eventhandler_fuchsia.h b/runtime/bin/eventhandler_fuchsia.h
index acd4793..545fdb8 100644
--- a/runtime/bin/eventhandler_fuchsia.h
+++ b/runtime/bin/eventhandler_fuchsia.h
@@ -10,7 +10,9 @@
#endif
#include <errno.h>
-#include <magenta/syscalls.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <unistd.h>
#include "platform/signal_blocker.h"
@@ -23,8 +25,11 @@
virtual ~DescriptorInfo() {}
+ intptr_t GetPollEvents();
+
virtual void Close() {
- VOID_TEMP_FAILURE_RETRY(close(fd_));
+ // Should be VOID_TEMP_FAILURE_RETRY
+ VOID_NO_RETRY_EXPECTED(close(fd_));
fd_ = -1;
}
@@ -53,57 +58,37 @@
DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
};
-// Information needed to call mx_handle_wait_many(), and to handle events.
-class MagentaWaitManyInfo {
- public:
- MagentaWaitManyInfo();
- ~MagentaWaitManyInfo();
-
- intptr_t capacity() const { return capacity_; }
- intptr_t size() const { return size_; }
- DescriptorInfo** descriptor_infos() const { return descriptor_infos_; }
- mx_wait_item_t* items() const { return items_; }
-
- void AddHandle(mx_handle_t handle, mx_signals_t signals, DescriptorInfo* di);
- void RemoveHandle(mx_handle_t handle);
-
- private:
- static const intptr_t kInitialCapacity = 32;
-
- void GrowArraysIfNeeded(intptr_t desired_size);
-
- intptr_t capacity_;
- intptr_t size_;
- DescriptorInfo** descriptor_infos_;
- mx_wait_item_t* items_;
-
- DISALLOW_COPY_AND_ASSIGN(MagentaWaitManyInfo);
-};
-
class EventHandlerImplementation {
public:
EventHandlerImplementation();
~EventHandlerImplementation();
+ void UpdateEpollInstance(intptr_t old_mask, DescriptorInfo* di);
+
+ // Gets the socket data structure for a given file
+ // descriptor. Creates a new one if one is not found.
+ DescriptorInfo* GetDescriptorInfo(intptr_t fd, bool is_listening);
void SendData(intptr_t id, Dart_Port dart_port, int64_t data);
void Start(EventHandler* handler);
void Shutdown();
- const MagentaWaitManyInfo& info() const { return info_; }
-
private:
+ static void Poll(uword args);
+ static void* GetHashmapKeyFromFd(intptr_t fd);
+ static uint32_t GetHashmapHashFromFd(intptr_t fd);
+
int64_t GetTimeout() const;
- void HandleEvents();
+ void HandleEvents(struct epoll_event* events, int size);
void HandleTimeout();
void WakeupHandler(intptr_t id, Dart_Port dart_port, int64_t data);
+ intptr_t GetPollEvents(intptr_t events, DescriptorInfo* di);
void HandleInterruptFd();
- static void Poll(uword args);
+ HashMap socket_map_;
TimeoutQueue timeout_queue_;
bool shutdown_;
- mx_handle_t interrupt_handles_[2];
-
- MagentaWaitManyInfo info_;
+ int interrupt_fds_[2];
+ int epoll_fd_;
DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
};
diff --git a/runtime/bin/fdutils.h b/runtime/bin/fdutils.h
index 25cd4dd..81c4541 100644
--- a/runtime/bin/fdutils.h
+++ b/runtime/bin/fdutils.h
@@ -39,6 +39,9 @@
// descriptor must be in blocking mode.
static ssize_t WriteToBlocking(int fd, const void* buffer, size_t count);
+ // Closes fd without modifying errno.
+ static void SaveErrorAndClose(intptr_t fd);
+
private:
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(FDUtils);
diff --git a/runtime/bin/fdutils_android.cc b/runtime/bin/fdutils_android.cc
index 5d8a8e0..ad5b91e 100644
--- a/runtime/bin/fdutils_android.cc
+++ b/runtime/bin/fdutils_android.cc
@@ -137,6 +137,13 @@
return count;
}
+
+void FDUtils::SaveErrorAndClose(intptr_t fd) {
+ int err = errno;
+ VOID_TEMP_FAILURE_RETRY(close(fd));
+ errno = err;
+}
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/fdutils_fuchsia.cc b/runtime/bin/fdutils_fuchsia.cc
new file mode 100644
index 0000000..dd9e881
--- /dev/null
+++ b/runtime/bin/fdutils_fuchsia.cc
@@ -0,0 +1,154 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "platform/globals.h"
+#if defined(TARGET_OS_FUCHSIA)
+
+#include "bin/fdutils.h"
+
+#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
+#include <sys/ioctl.h> // NOLINT
+#include <unistd.h> // NOLINT
+
+#include "platform/signal_blocker.h"
+
+namespace dart {
+namespace bin {
+
+bool FDUtils::SetCloseOnExec(intptr_t fd) {
+ intptr_t status;
+ status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFD));
+ if (status < 0) {
+ perror("fcntl(F_GETFD) failed");
+ return false;
+ }
+ status |= FD_CLOEXEC;
+ if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFD, status)) < 0) {
+ perror("fcntl(F_SETFD, FD_CLOEXEC) failed");
+ return false;
+ }
+ return true;
+}
+
+
+static bool SetBlockingHelper(intptr_t fd, bool blocking) {
+ intptr_t status;
+ status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
+ if (status < 0) {
+ perror("fcntl(F_GETFL) failed");
+ return false;
+ }
+ status = blocking ? (status & ~O_NONBLOCK) : (status | O_NONBLOCK);
+ if (NO_RETRY_EXPECTED(fcntl(fd, F_SETFL, status)) < 0) {
+ perror("fcntl(F_SETFL, O_NONBLOCK) failed");
+ return false;
+ }
+ return true;
+}
+
+
+bool FDUtils::SetNonBlocking(intptr_t fd) {
+ return SetBlockingHelper(fd, false);
+}
+
+
+bool FDUtils::SetBlocking(intptr_t fd) {
+ return SetBlockingHelper(fd, true);
+}
+
+
+bool FDUtils::IsBlocking(intptr_t fd, bool* is_blocking) {
+ intptr_t status;
+ status = NO_RETRY_EXPECTED(fcntl(fd, F_GETFL));
+ if (status < 0) {
+ return false;
+ }
+ *is_blocking = (status & O_NONBLOCK) == 0;
+ return true;
+}
+
+
+intptr_t FDUtils::AvailableBytes(intptr_t fd) {
+// TODO(MG-364): Enable this code when it is supported.
+#if 0
+ int available; // ioctl for FIONREAD expects an 'int*' argument.
+ int result = NO_RETRY_EXPECTED(ioctl(fd, FIONREAD, &available));
+ if (result < 0) {
+ return result;
+ }
+ ASSERT(available >= 0);
+ return static_cast<intptr_t>(available);
+#endif
+ errno = ENOTSUP;
+ return -1;
+}
+
+
+ssize_t FDUtils::ReadFromBlocking(int fd, void* buffer, size_t count) {
+#ifdef DEBUG
+ bool is_blocking = false;
+ ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
+ ASSERT(is_blocking);
+#endif
+ size_t remaining = count;
+ char* buffer_pos = reinterpret_cast<char*>(buffer);
+ while (remaining > 0) {
+ ssize_t bytes_read = NO_RETRY_EXPECTED(read(fd, buffer_pos, remaining));
+ if (bytes_read == 0) {
+ return count - remaining;
+ } else if (bytes_read == -1) {
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ // Error code EWOULDBLOCK should only happen for non blocking
+ // file descriptors.
+ ASSERT(errno != EWOULDBLOCK);
+ return -1;
+ } else {
+ ASSERT(bytes_read > 0);
+ remaining -= bytes_read;
+ buffer_pos += bytes_read;
+ }
+ }
+ return count;
+}
+
+
+ssize_t FDUtils::WriteToBlocking(int fd, const void* buffer, size_t count) {
+#ifdef DEBUG
+ bool is_blocking = false;
+ ASSERT(FDUtils::IsBlocking(fd, &is_blocking));
+ ASSERT(is_blocking);
+#endif
+ size_t remaining = count;
+ char* buffer_pos = const_cast<char*>(reinterpret_cast<const char*>(buffer));
+ while (remaining > 0) {
+ ssize_t bytes_written = NO_RETRY_EXPECTED(write(fd, buffer_pos, remaining));
+ if (bytes_written == 0) {
+ return count - remaining;
+ } else if (bytes_written == -1) {
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ // Error code EWOULDBLOCK should only happen for non blocking
+ // file descriptors.
+ ASSERT(errno != EWOULDBLOCK);
+ return -1;
+ } else {
+ ASSERT(bytes_written > 0);
+ remaining -= bytes_written;
+ buffer_pos += bytes_written;
+ }
+ }
+ return count;
+}
+
+
+void FDUtils::SaveErrorAndClose(intptr_t fd) {
+ int err = errno;
+ NO_RETRY_EXPECTED(close(fd));
+ errno = err;
+}
+
+} // namespace bin
+} // namespace dart
+
+#endif // defined(TARGET_OS_FUCHSIA)
diff --git a/runtime/bin/fdutils_linux.cc b/runtime/bin/fdutils_linux.cc
index 5a174ee..7f4598b 100644
--- a/runtime/bin/fdutils_linux.cc
+++ b/runtime/bin/fdutils_linux.cc
@@ -137,6 +137,13 @@
return count;
}
+
+void FDUtils::SaveErrorAndClose(intptr_t fd) {
+ int err = errno;
+ VOID_TEMP_FAILURE_RETRY(close(fd));
+ errno = err;
+}
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/fdutils_macos.cc b/runtime/bin/fdutils_macos.cc
index ab1a603..4a0e3c0 100644
--- a/runtime/bin/fdutils_macos.cc
+++ b/runtime/bin/fdutils_macos.cc
@@ -137,6 +137,13 @@
return count;
}
+
+void FDUtils::SaveErrorAndClose(intptr_t fd) {
+ int err = errno;
+ VOID_TEMP_FAILURE_RETRY(close(fd));
+ errno = err;
+}
+
} // namespace bin
} // namespace dart
diff --git a/runtime/bin/run_vm_tests_fuchsia.cc b/runtime/bin/run_vm_tests_fuchsia.cc
index 0424f8a..71cf5c3 100644
--- a/runtime/bin/run_vm_tests_fuchsia.cc
+++ b/runtime/bin/run_vm_tests_fuchsia.cc
@@ -276,15 +276,13 @@
RETURN_IF_ERROR(r);
mx_info_process_t proc_info;
- mx_size_t info_size;
- mx_status_t status =
- mx_object_get_info(p, MX_INFO_PROCESS, sizeof(proc_info.rec), &proc_info,
- sizeof(proc_info), &info_size);
+ mx_status_t status = mx_object_get_info(p, MX_INFO_PROCESS, &proc_info,
+ sizeof(proc_info), nullptr, nullptr);
RETURN_IF_ERROR(status);
r = mx_handle_close(p);
RETURN_IF_ERROR(r);
- return proc_info.rec.return_code;
+ return proc_info.return_code;
}
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc
index 07e6894..08e49be 100644
--- a/runtime/bin/socket_android.cc
+++ b/runtime/bin/socket_android.cc
@@ -25,13 +25,6 @@
namespace dart {
namespace bin {
-static void SaveErrorAndClose(intptr_t fd) {
- int err = errno;
- VOID_TEMP_FAILURE_RETRY(close(fd));
- errno = err;
-}
-
-
SocketAddress::SocketAddress(struct sockaddr* sa) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_,
@@ -63,7 +56,7 @@
return -1;
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -76,7 +69,7 @@
if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -88,7 +81,7 @@
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return Connect(fd, addr);
@@ -105,7 +98,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
if ((result != 0) && (errno != EINPROGRESS)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -323,7 +316,7 @@
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -335,12 +328,12 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -377,7 +370,7 @@
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -393,7 +386,7 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -403,17 +396,17 @@
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return new_fd;
}
if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -451,11 +444,11 @@
}
} else {
if (!FDUtils::SetCloseOnExec(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
if (!FDUtils::SetNonBlocking(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
}
diff --git a/runtime/bin/socket_fuchsia.cc b/runtime/bin/socket_fuchsia.cc
index 7e8489b..a6498ce 100644
--- a/runtime/bin/socket_fuchsia.cc
+++ b/runtime/bin/socket_fuchsia.cc
@@ -10,56 +10,181 @@
#include "bin/socket.h"
#include "bin/socket_fuchsia.h"
+#include <errno.h> // NOLINT
+#include <fcntl.h> // NOLINT
+#include <ifaddrs.h> // NOLINT
+#include <net/if.h> // NOLINT
+#include <netinet/tcp.h> // NOLINT
+#include <stdio.h> // NOLINT
+#include <stdlib.h> // NOLINT
+#include <string.h> // NOLINT
+#include <sys/ioctl.h> // NOLINT
+#include <sys/stat.h> // NOLINT
+#include <unistd.h> // NOLINT
+
+#include "bin/fdutils.h"
#include "bin/file.h"
+#include "platform/signal_blocker.h"
+
+// #define SOCKET_LOG_INFO 1
+// #define SOCKET_LOG_ERROR 1
+
+// define SOCKET_LOG_ERROR to get log messages only for errors.
+// define SOCKET_LOG_INFO to get log messages for both information and errors.
+#if defined(SOCKET_LOG_INFO) || defined(SOCKET_LOG_ERROR)
+#define LOG_ERR(msg, ...) \
+ { \
+ int err = errno; \
+ Log::PrintErr("Dart Socket ERROR: %s:%d: " msg, __FILE__, __LINE__, \
+ ##__VA_ARGS__); \
+ errno = err; \
+ }
+#if defined(SOCKET_LOG_INFO)
+#define LOG_INFO(msg, ...) \
+ Log::Print("Dart Socket INFO: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__)
+#else
+#define LOG_INFO(msg, ...)
+#endif // defined(SOCKET_LOG_INFO)
+#else
+#define LOG_ERR(msg, ...)
+#define LOG_INFO(msg, ...)
+#endif // defined(SOCKET_LOG_INFO) || defined(SOCKET_LOG_ERROR)
namespace dart {
namespace bin {
SocketAddress::SocketAddress(struct sockaddr* sa) {
- UNIMPLEMENTED();
+ ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
+ if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_,
+ INET6_ADDRSTRLEN)) {
+ as_string_[0] = 0;
+ }
+ socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa));
+ memmove(reinterpret_cast<void*>(&addr_), sa, salen);
}
bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
- UNIMPLEMENTED();
- return false;
+ socklen_t salen = SocketAddress::GetAddrLength(addr);
+ LOG_INFO("Socket::FormatNumericAddress: calling getnameinfo\n");
+ return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL,
+ 0, NI_NUMERICHOST) == 0));
}
bool Socket::Initialize() {
- UNIMPLEMENTED();
+ // Nothing to do on Fuchsia.
return true;
}
-intptr_t Socket::CreateConnect(const RawAddr& addr) {
- UNIMPLEMENTED();
+static intptr_t Create(const RawAddr& addr) {
+ LOG_INFO("Create: calling socket(SOCK_STREAM)\n");
+ intptr_t fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+ if (fd < 0) {
+ LOG_ERR("Create: socket(SOCK_STREAM) failed\n");
+ return -1;
+ }
+ LOG_INFO("Create: socket(SOCK_STREAM) -> fd %ld\n", fd);
+ if (!FDUtils::SetCloseOnExec(fd)) {
+ LOG_ERR("Create: FDUtils::SetCloseOnExec(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ return fd;
+}
+
+
+static intptr_t CheckConnect(intptr_t fd) {
+ int val;
+ socklen_t vallen = sizeof(val);
+ LOG_INFO("CheckConnect: calling getsockopt(%ld)\n", fd);
+ intptr_t result = getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &vallen);
+ if (result != 0) {
+ FATAL1("CheckConnect: getsockopt(%ld) failed\n", fd);
+ } else if (vallen != sizeof(val)) {
+ FATAL1("CheckConnect: getsockopt(%ld) vallen != sizeof(val)!?!?\n", fd);
+ } else if (val != 0) {
+ LOG_ERR("CheckConnect: getsockopt(%ld) val = %d\n", fd, val);
+ return val;
+ }
+ LOG_INFO("CheckConnect: getsockopt(%ld) connected\n", fd);
+ return 0;
+}
+
+
+static intptr_t Connect(intptr_t fd, const RawAddr& addr) {
+ LOG_INFO("Connect: calling connect(%ld)\n", fd);
+ intptr_t result = NO_RETRY_EXPECTED(
+ connect(fd, &addr.addr, SocketAddress::GetAddrLength(addr)));
+ if ((result == 0) || (errno == EINPROGRESS)) {
+ LOG_INFO("Connect: connect(%ld) succeeded\n", fd);
+ intptr_t error = 0;
+ // TODO(US-87): When the issue is resolved this check is no longer needed.
+ while ((error = CheckConnect(fd)) != 0) {
+ if (error != EINPROGRESS) {
+ errno = error;
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ }
+ return fd;
+ }
+ LOG_ERR("Connect: connect(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
+intptr_t Socket::CreateConnect(const RawAddr& addr) {
+ intptr_t fd = Create(addr);
+ if (fd < 0) {
+ return fd;
+ }
+ if (!FDUtils::SetNonBlocking(fd)) {
+ LOG_ERR("CreateConnect: FDUtils::SetNonBlocking(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ return Connect(fd, addr);
+}
+
+
intptr_t Socket::CreateBindConnect(const RawAddr& addr,
const RawAddr& source_addr) {
+ LOG_ERR("Socket::CreateBindConnect is unimplemented\n");
UNIMPLEMENTED();
return -1;
}
bool Socket::IsBindError(intptr_t error_number) {
- UNIMPLEMENTED();
- return false;
+ return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL ||
+ error_number == EINVAL;
}
intptr_t Socket::Available(intptr_t fd) {
- UNIMPLEMENTED();
- return -1;
+ return FDUtils::AvailableBytes(fd);
}
intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
- UNIMPLEMENTED();
- return -1;
+ ASSERT(fd >= 0);
+ LOG_INFO("Socket::Read: calling read(%ld, %p, %ld)\n", fd, buffer, num_bytes);
+ ssize_t read_bytes = NO_RETRY_EXPECTED(read(fd, buffer, num_bytes));
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
+ // If the read would block we need to retry and therefore return 0
+ // as the number of bytes written.
+ read_bytes = 0;
+ } else if (read_bytes == -1) {
+ LOG_ERR("Socket::Read: read(%ld, %p, %ld) failed\n", fd, buffer, num_bytes);
+ } else {
+ LOG_INFO("Socket::Read: read(%ld, %p, %ld) succeeded\n", fd, buffer,
+ num_bytes);
+ }
+ return read_bytes;
}
@@ -67,14 +192,30 @@
void* buffer,
intptr_t num_bytes,
RawAddr* addr) {
+ LOG_ERR("Socket::RecvFrom is unimplemented\n");
UNIMPLEMENTED();
return -1;
}
intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
- UNIMPLEMENTED();
- return -1;
+ ASSERT(fd >= 0);
+ LOG_INFO("Socket::Write: calling write(%ld, %p, %ld)\n", fd, buffer,
+ num_bytes);
+ ssize_t written_bytes = NO_RETRY_EXPECTED(write(fd, buffer, num_bytes));
+ ASSERT(EAGAIN == EWOULDBLOCK);
+ if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
+ // If the would block we need to retry and therefore return 0 as
+ // the number of bytes written.
+ written_bytes = 0;
+ } else if (written_bytes == -1) {
+ LOG_ERR("Socket::Write: write(%ld, %p, %ld) failed\n", fd, buffer,
+ num_bytes);
+ } else {
+ LOG_INFO("Socket::Write: write(%ld, %p, %ld) succeeded\n", fd, buffer,
+ num_bytes);
+ }
+ return written_bytes;
}
@@ -82,35 +223,46 @@
const void* buffer,
intptr_t num_bytes,
const RawAddr& addr) {
+ LOG_ERR("Socket::SendTo is unimplemented\n");
UNIMPLEMENTED();
return -1;
}
intptr_t Socket::GetPort(intptr_t fd) {
- UNIMPLEMENTED();
- return -1;
+ ASSERT(fd >= 0);
+ RawAddr raw;
+ socklen_t size = sizeof(raw);
+ LOG_INFO("Socket::GetPort: calling getsockname(%ld)\n", fd);
+ if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
+ return 0;
+ }
+ return SocketAddress::GetAddrPort(raw);
}
SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) {
+ LOG_ERR("Socket::GetRemotePeer is unimplemented\n");
UNIMPLEMENTED();
return NULL;
}
void Socket::GetError(intptr_t fd, OSError* os_error) {
+ LOG_ERR("Socket::GetError is unimplemented\n");
UNIMPLEMENTED();
}
int Socket::GetType(intptr_t fd) {
+ LOG_ERR("Socket::GetType is unimplemented\n");
UNIMPLEMENTED();
return File::kOther;
}
intptr_t Socket::GetStdioHandle(intptr_t num) {
+ LOG_ERR("Socket::GetStdioHandle is unimplemented\n");
UNIMPLEMENTED();
return num;
}
@@ -119,13 +271,45 @@
AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
int type,
OSError** os_error) {
- // UNIMPLEMENTED
- ASSERT(*os_error == NULL);
- *os_error = new OSError(-1,
- "Socket::LookupAddress not implemented in "
- "Fuchsia Dart VM runtime",
- OSError::kGetAddressInfo);
- return NULL;
+ // Perform a name lookup for a host name.
+ struct addrinfo hints;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = SocketAddress::FromType(type);
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_ADDRCONFIG;
+ hints.ai_protocol = IPPROTO_TCP;
+ struct addrinfo* info = NULL;
+ LOG_INFO("Socket::LookupAddress: calling getaddrinfo\n");
+ int status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info));
+ if (status != 0) {
+ // We failed, try without AI_ADDRCONFIG. This can happen when looking up
+ // e.g. '::1', when there are no global IPv6 addresses.
+ hints.ai_flags = 0;
+ LOG_INFO("Socket::LookupAddress: calling getaddrinfo again\n");
+ status = NO_RETRY_EXPECTED(getaddrinfo(host, 0, &hints, &info));
+ if (status != 0) {
+ ASSERT(*os_error == NULL);
+ *os_error =
+ new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
+ return NULL;
+ }
+ }
+ intptr_t count = 0;
+ for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ count++;
+ }
+ }
+ intptr_t i = 0;
+ AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
+ for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
+ if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
+ addresses->SetAt(i, new SocketAddress(c->ai_addr));
+ i++;
+ }
+ }
+ freeaddrinfo(info);
+ return addresses;
}
@@ -133,18 +317,21 @@
char* host,
intptr_t host_len,
OSError** os_error) {
+ LOG_ERR("Socket::ReverseLookup is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
+ LOG_ERR("Socket::ParseAddress is unimplemented\n");
UNIMPLEMENTED();
return false;
}
intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
+ LOG_ERR("Socket::CreateBindDatagram is unimplemented\n");
UNIMPLEMENTED();
return -1;
}
@@ -166,71 +353,175 @@
intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
intptr_t backlog,
bool v6_only) {
- UNIMPLEMENTED();
- return -1;
+ LOG_INFO("ServerSocket::CreateBindListen: calling socket(SOCK_STREAM)\n");
+ intptr_t fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0));
+ if (fd < 0) {
+ LOG_ERR("ServerSocket::CreateBindListen: socket() failed\n");
+ return -1;
+ }
+ LOG_INFO("ServerSocket::CreateBindListen: socket(SOCK_STREAM) -> %ld\n", fd);
+
+ if (!FDUtils::SetCloseOnExec(fd)) {
+ LOG_ERR("ServerSocket::CreateBindListen: SetCloseOnExec(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+
+ LOG_INFO("ServerSocket::CreateBindListen: calling setsockopt(%ld)\n", fd);
+ int optval = 1;
+ VOID_NO_RETRY_EXPECTED(
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
+
+ if (addr.ss.ss_family == AF_INET6) {
+ optval = v6_only ? 1 : 0;
+ LOG_INFO("ServerSocket::CreateBindListen: calling setsockopt(%ld)\n", fd);
+ VOID_NO_RETRY_EXPECTED(
+ setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)));
+ }
+
+ LOG_INFO("ServerSocket::CreateBindListen: calling bind(%ld)\n", fd);
+ if (NO_RETRY_EXPECTED(
+ bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
+ LOG_ERR("ServerSocket::CreateBindListen: bind(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ LOG_INFO("ServerSocket::CreateBindListen: bind(%ld) succeeded\n", fd);
+
+ // Test for invalid socket port 65535 (some browsers disallow it).
+ if ((SocketAddress::GetAddrPort(addr) == 0) &&
+ (Socket::GetPort(fd) == 65535)) {
+ // Don't close the socket until we have created a new socket, ensuring
+ // that we do not get the bad port number again.
+ intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
+ FDUtils::SaveErrorAndClose(fd);
+ return new_fd;
+ }
+
+ LOG_INFO("ServerSocket::CreateBindListen: calling listen(%ld)\n", fd);
+ if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
+ LOG_ERR("ServerSocket::CreateBindListen: listen failed(%ld)\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ LOG_INFO("ServerSocket::CreateBindListen: listen(%ld) succeeded\n", fd);
+
+ if (!FDUtils::SetNonBlocking(fd)) {
+ LOG_ERR("CreateBindListen: FDUtils::SetNonBlocking(%ld) failed\n", fd);
+ FDUtils::SaveErrorAndClose(fd);
+ return -1;
+ }
+ return fd;
}
bool ServerSocket::StartAccept(intptr_t fd) {
- UNIMPLEMENTED();
- return false;
+ USE(fd);
+ return true;
+}
+
+
+static bool IsTemporaryAcceptError(int error) {
+ // On Linux a number of protocol errors should be treated as EAGAIN.
+ // These are the ones for TCP/IP.
+ return (error == EAGAIN) || (error == ENETDOWN) || (error == EPROTO) ||
+ (error == ENOPROTOOPT) || (error == EHOSTDOWN) || (error == ENONET) ||
+ (error == EHOSTUNREACH) || (error == EOPNOTSUPP) ||
+ (error == ENETUNREACH);
}
intptr_t ServerSocket::Accept(intptr_t fd) {
- UNIMPLEMENTED();
- return -1;
+ intptr_t socket;
+ struct sockaddr clientaddr;
+ socklen_t addrlen = sizeof(clientaddr);
+ LOG_INFO("ServerSocket::Accept: calling accept(%ld)\n", fd);
+ socket = NO_RETRY_EXPECTED(accept(fd, &clientaddr, &addrlen));
+ if (socket == -1) {
+ if (IsTemporaryAcceptError(errno)) {
+ // We need to signal to the caller that this is actually not an
+ // error. We got woken up from the poll on the listening socket,
+ // but there is no connection ready to be accepted.
+ ASSERT(kTemporaryFailure != -1);
+ socket = kTemporaryFailure;
+ } else {
+ LOG_ERR("ServerSocket::Accept: accept(%ld) failed\n", fd);
+ }
+ } else {
+ LOG_INFO("ServerSocket::Accept: accept(%ld) -> socket %ld\n", fd, socket);
+ if (!FDUtils::SetCloseOnExec(socket)) {
+ LOG_ERR("FDUtils::SetCloseOnExec(%ld) failed\n", socket);
+ FDUtils::SaveErrorAndClose(socket);
+ return -1;
+ }
+ if (!FDUtils::SetNonBlocking(socket)) {
+ LOG_ERR("FDUtils::SetNonBlocking(%ld) failed\n", socket);
+ FDUtils::SaveErrorAndClose(socket);
+ return -1;
+ }
+ }
+ return socket;
}
void Socket::Close(intptr_t fd) {
- UNIMPLEMENTED();
+ ASSERT(fd >= 0);
+ NO_RETRY_EXPECTED(close(fd));
}
bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
+ LOG_ERR("Socket::GetNoDelay is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
- UNIMPLEMENTED();
- return false;
+ int on = enabled ? 1 : 0;
+ return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
+ reinterpret_cast<char*>(&on),
+ sizeof(on))) == 0;
}
bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
+ LOG_ERR("Socket::GetMulticastLoop is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
+ LOG_ERR("Socket::SetMulticastLoop is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
+ LOG_ERR("Socket::GetMulticastHops is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
+ LOG_ERR("Socket::SetMulticastHops is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
+ LOG_ERR("Socket::GetBroadcast is unimplemented\n");
UNIMPLEMENTED();
return false;
}
bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
+ LOG_ERR("Socket::SetBroadcast is unimplemented\n");
UNIMPLEMENTED();
return false;
}
@@ -240,6 +531,7 @@
const RawAddr& addr,
const RawAddr&,
int interfaceIndex) {
+ LOG_ERR("Socket::JoinMulticast is unimplemented\n");
UNIMPLEMENTED();
return false;
}
@@ -249,6 +541,7 @@
const RawAddr& addr,
const RawAddr&,
int interfaceIndex) {
+ LOG_ERR("Socket::LeaveMulticast is unimplemented\n");
UNIMPLEMENTED();
return false;
}
diff --git a/runtime/bin/socket_fuchsia.h b/runtime/bin/socket_fuchsia.h
index 64c8545..a19df5d 100644
--- a/runtime/bin/socket_fuchsia.h
+++ b/runtime/bin/socket_fuchsia.h
@@ -9,4 +9,8 @@
#error Do not include socket_fuchsia.h directly. Use socket.h.
#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
#endif // RUNTIME_BIN_SOCKET_FUCHSIA_H_
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc
index e3d3103..af53878 100644
--- a/runtime/bin/socket_linux.cc
+++ b/runtime/bin/socket_linux.cc
@@ -28,13 +28,6 @@
namespace dart {
namespace bin {
-static void SaveErrorAndClose(intptr_t fd) {
- int err = errno;
- VOID_TEMP_FAILURE_RETRY(close(fd));
- errno = err;
-}
-
-
SocketAddress::SocketAddress(struct sockaddr* sa) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_,
@@ -76,7 +69,7 @@
if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
- SaveErrorAndClose(fd);
+ FDUtils::FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -100,7 +93,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
if ((result != 0) && (errno != EINPROGRESS)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -329,7 +322,7 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -415,7 +408,7 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -425,12 +418,12 @@
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return new_fd;
}
if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -469,11 +462,11 @@
}
} else {
if (!FDUtils::SetCloseOnExec(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
if (!FDUtils::SetNonBlocking(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
}
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc
index 4d0f53d..c1f48cc 100644
--- a/runtime/bin/socket_macos.cc
+++ b/runtime/bin/socket_macos.cc
@@ -27,13 +27,6 @@
namespace dart {
namespace bin {
-static void SaveErrorAndClose(intptr_t fd) {
- int err = errno;
- VOID_TEMP_FAILURE_RETRY(close(fd));
- errno = err;
-}
-
-
SocketAddress::SocketAddress(struct sockaddr* sa) {
ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_,
@@ -65,11 +58,11 @@
return -1;
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -82,7 +75,7 @@
if ((result == 0) || (errno == EINPROGRESS)) {
return fd;
}
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -107,7 +100,7 @@
intptr_t result = TEMP_FAILURE_RETRY(
bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
if ((result != 0) && (errno != EINPROGRESS)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -318,7 +311,7 @@
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -330,12 +323,12 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -409,7 +402,7 @@
}
if (!FDUtils::SetCloseOnExec(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -425,7 +418,7 @@
if (NO_RETRY_EXPECTED(
bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
@@ -435,17 +428,17 @@
// Don't close the socket until we have created a new socket, ensuring
// that we do not get the bad port number again.
intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return new_fd;
}
if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
if (!FDUtils::SetNonBlocking(fd)) {
- SaveErrorAndClose(fd);
+ FDUtils::SaveErrorAndClose(fd);
return -1;
}
return fd;
@@ -473,11 +466,11 @@
}
} else {
if (!FDUtils::SetCloseOnExec(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
if (!FDUtils::SetNonBlocking(socket)) {
- SaveErrorAndClose(socket);
+ FDUtils::SaveErrorAndClose(socket);
return -1;
}
}
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 1a09f7b..a085a72 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -2734,7 +2734,8 @@
* Dart_kScriptTag
*
* This tag indicates that the root script should be loaded from
- * 'url'. The 'library' parameter will always be null. Once the root
+ * 'url'. If the 'library' parameter is not null, it is the url of the
+ * package map that should be used when loading. Once the root
* script is loaded, the embedder should call Dart_LoadScript to
* install the root script in the VM. The return value should be an
* error or null.
@@ -2753,9 +2754,10 @@
* call Dart_LoadLibrary to provide the script source to the VM. The
* return value should be an error or null.
*/
-typedef Dart_Handle (*Dart_LibraryTagHandler)(Dart_LibraryTag tag,
- Dart_Handle library,
- Dart_Handle url);
+typedef Dart_Handle (*Dart_LibraryTagHandler)(
+ Dart_LibraryTag tag,
+ Dart_Handle library_or_package_map_url,
+ Dart_Handle url);
/**
* Sets library tag handler for the current isolate. This handler is
diff --git a/runtime/lib/regexp.cc b/runtime/lib/regexp.cc
index 7a50561..8779573 100644
--- a/runtime/lib/regexp.cc
+++ b/runtime/lib/regexp.cc
@@ -78,19 +78,34 @@
}
-DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
- // This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
+static RawObject* ExecuteMatch(Zone* zone,
+ NativeArguments* arguments,
+ bool sticky) {
const RegExp& regexp = RegExp::CheckedHandle(arguments->NativeArgAt(0));
ASSERT(!regexp.IsNull());
GET_NON_NULL_NATIVE_ARGUMENT(String, subject, arguments->NativeArgAt(1));
GET_NON_NULL_NATIVE_ARGUMENT(Smi, start_index, arguments->NativeArgAt(2));
- if (FLAG_interpret_irregexp || FLAG_precompiled_runtime) {
+ if (FLAG_interpret_irregexp) {
return BytecodeRegExpMacroAssembler::Interpret(regexp, subject, start_index,
- zone);
+ /*sticky=*/sticky, zone);
}
- return IRRegExpMacroAssembler::Execute(regexp, subject, start_index, zone);
+ return IRRegExpMacroAssembler::Execute(regexp, subject, start_index,
+ /*sticky=*/sticky, zone);
}
+
+DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatch, 3) {
+ // This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatch.
+ return ExecuteMatch(zone, arguments, /*sticky=*/false);
+}
+
+
+DEFINE_NATIVE_ENTRY(RegExp_ExecuteMatchSticky, 3) {
+ // This function is intrinsified. See Intrinsifier::RegExp_ExecuteMatchSticky.
+ return ExecuteMatch(zone, arguments, /*sticky=*/true);
+}
+
+
} // namespace dart
diff --git a/runtime/lib/regexp_patch.dart b/runtime/lib/regexp_patch.dart
index a9ccd55..0c93204 100644
--- a/runtime/lib/regexp_patch.dart
+++ b/runtime/lib/regexp_patch.dart
@@ -160,11 +160,8 @@
if (start < 0 || start > string.length) {
throw new RangeError.range(start, 0, string.length);
}
- // Inefficient check that searches for a later match too.
- // Change this when possible.
- List<int> list = _ExecuteMatch(string, start);
+ List<int> list = _ExecuteMatchSticky(string, start);
if (list == null) return null;
- if (list[0] != start) return null;
return new _RegExpMatch(this, string, list);
}
@@ -238,6 +235,9 @@
List _ExecuteMatch(String str, int start_index)
native "RegExp_ExecuteMatch";
+
+ List _ExecuteMatchSticky(String str, int start_index)
+ native "RegExp_ExecuteMatchSticky";
}
class _AllMatchesIterable extends IterableBase<Match> {
diff --git a/runtime/observatory/HACKING.md b/runtime/observatory/HACKING.md
index e8c5500..fe47693 100644
--- a/runtime/observatory/HACKING.md
+++ b/runtime/observatory/HACKING.md
@@ -185,7 +185,7 @@
See: __Run existing tests__
[build_sdk]: https://github.com/dart-lang/sdk/wiki/Building "Building the Dart SDK"
-[download_dartium]: https://www.dartlang.org/tools/dartium/ "Download Dartium"
+[download_dartium]: https://webdev.dartlang.org/tools/dartium/ "Download Dartium"
[build_dartium]: https://github.com/dart-lang/sdk/wiki/Building-Dartium "Build Dartium"
[open_observatory]: http://localhost:8080/ "Open Observatory"
[observatory_get_started]: https://dart-lang.github.io/observatory/get-started.html "Observatory get started"
diff --git a/runtime/observatory/lib/src/elements/view_footer.dart b/runtime/observatory/lib/src/elements/view_footer.dart
index f85b1d9..cd8cd94 100644
--- a/runtime/observatory/lib/src/elements/view_footer.dart
+++ b/runtime/observatory/lib/src/elements/view_footer.dart
@@ -40,7 +40,7 @@
void render() {
children = [
new AnchorElement()
- ..href = 'https://www.dartlang.org/tools/observatory'
+ ..href = 'https://dart-lang.github.io/observatory/'
..text = 'View documentation',
new AnchorElement()
..href =
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index e0f6e05..c638dd9 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -1333,9 +1333,19 @@
return invokeRpc('getSourceReport', params);
}
- Future<ServiceMap> reloadSources() {
- return invokeRpc('_reloadSources', {}).then((_) {
+ Future<ServiceMap> reloadSources(
+ {String rootLibUri,
+ bool pause}) {
+ Map<String, dynamic> params = <String, dynamic>{};
+ if (rootLibUri != null) {
+ params['rootLibUri'] = rootLibUri;
+ }
+ if (pause != null) {
+ params['pause'] = pause;
+ }
+ return invokeRpc('reloadSources', params).then((result) {
reloading = true;
+ return result;
});
}
diff --git a/runtime/observatory/tests/service/complex_reload/v1/main.dart b/runtime/observatory/tests/service/complex_reload/v1/main.dart
new file mode 100644
index 0000000..055565f
--- /dev/null
+++ b/runtime/observatory/tests/service/complex_reload/v1/main.dart
@@ -0,0 +1,14 @@
+// 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.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'dart:isolate';
+
+test() => 'apple';
+
+main() {
+ RawReceivePort keepAlive = new RawReceivePort();
+ print('slave isolate running');
+}
+
diff --git a/runtime/observatory/tests/service/complex_reload/v2/main.dart b/runtime/observatory/tests/service/complex_reload/v2/main.dart
new file mode 100644
index 0000000..b0cc841
--- /dev/null
+++ b/runtime/observatory/tests/service/complex_reload/v2/main.dart
@@ -0,0 +1,6 @@
+// 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.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+test() => 'banana';
diff --git a/runtime/observatory/tests/service/complex_reload/v3/main.dart b/runtime/observatory/tests/service/complex_reload/v3/main.dart
new file mode 100644
index 0000000..751ca96
--- /dev/null
+++ b/runtime/observatory/tests/service/complex_reload/v3/main.dart
@@ -0,0 +1,6 @@
+// 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.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+test() => 'cabbage';
diff --git a/runtime/observatory/tests/service/complex_reload_test.dart b/runtime/observatory/tests/service/complex_reload_test.dart
new file mode 100644
index 0000000..0b94084
--- /dev/null
+++ b/runtime/observatory/tests/service/complex_reload_test.dart
@@ -0,0 +1,85 @@
+// 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.
+// VMOptions=--error_on_bad_type --error_on_bad_override
+
+import 'test_helper.dart';
+import 'dart:async';
+import 'dart:developer';
+import 'dart:isolate' as I;
+import 'dart:io';
+import 'service_test_common.dart';
+import 'package:observatory/service.dart';
+import 'package:unittest/unittest.dart';
+
+testMain() async {
+ debugger(); // Stop here.
+ // Spawn the child isolate.
+ I.Isolate isolate =
+ await I.Isolate.spawnUri(Uri.parse('complex_reload/v1/main.dart'),
+ [],
+ null);
+ print(isolate);
+ debugger();
+}
+
+// Directory that we are running in.
+String directory = (Platform.isWindows ? '' : Platform.pathSeparator) +
+ Platform.script.pathSegments.sublist(
+ 0,
+ Platform.script.pathSegments.length - 1).join(Platform.pathSeparator);
+
+Future<String> invokeTest(Isolate isolate) async {
+ await isolate.reload();
+ Library lib = isolate.rootLibrary;
+ await lib.load();
+ Instance result = await lib.evaluate('test()');
+ expect(result.isString, isTrue);
+ return result.valueAsString;
+}
+
+var tests = [
+ // Stopped at 'debugger' statement.
+ hasStoppedAtBreakpoint,
+ // Resume the isolate into the while loop.
+ resumeIsolate,
+ // Stop at 'debugger' statement.
+ hasStoppedAtBreakpoint,
+ (Isolate mainIsolate) async {
+ // Grab the VM.
+ VM vm = mainIsolate.vm;
+ await vm.reloadIsolates();
+ expect(vm.isolates.length, 2);
+
+ // Find the slave isolate.
+ Isolate slaveIsolate =
+ vm.isolates.firstWhere((Isolate i) => i != mainIsolate);
+ expect(slaveIsolate, isNotNull);
+
+ // Invoke test in v1.
+ String v1 = await invokeTest(slaveIsolate);
+ expect(v1, 'apple');
+
+ // Reload to v2.
+ var response = await slaveIsolate.reloadSources(
+ rootLibUri: '$directory/complex_reload/v2/main.dart',
+ );
+ expect(response['success'], isTrue);
+
+ // Invoke test in v2.
+ String v2 = await invokeTest(slaveIsolate);
+ expect(v2, 'banana');
+
+ // Reload to v3.
+ response = await slaveIsolate.reloadSources(
+ rootLibUri: '$directory/complex_reload/v3/main.dart',
+ );
+ expect(response['success'], isTrue);
+
+ // Invoke test in v3.
+ String v3 = await invokeTest(slaveIsolate);
+ expect(v3, 'cabbage');
+ }
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain);
diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status
index 638f447..52be6ac 100644
--- a/runtime/observatory/tests/service/service.status
+++ b/runtime/observatory/tests/service/service.status
@@ -70,6 +70,7 @@
[ $system == windows ]
dev_fs_weird_char_test: Skip # Windows disallows question mark in paths
dev_fs_http_put_weird_char_test: Skip # Windows disallows carriage returns in paths
+complex_reload_test: Skip # Issue 27861
# Service protocol is not supported in product mode.
[ $mode == product ]
diff --git a/runtime/platform/globals.h b/runtime/platform/globals.h
index 231464c..101200b 100644
--- a/runtime/platform/globals.h
+++ b/runtime/platform/globals.h
@@ -142,6 +142,10 @@
#error DART_PRECOMPILED_RUNTIME and DART_PRECOMPILER are mutually exclusive
#endif // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_PRECOMPILER)
+#if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_NOSNAPSHOT)
+#error DART_PRECOMPILED_RUNTIME and DART_NOSNAPSHOT are mutually exclusive
+#endif // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_NOSNAPSHOT)
+
#if defined(DART_PRECOMPILED_RUNTIME)
#define NOT_IN_PRECOMPILED(code)
#else
diff --git a/runtime/tests/vm/dart/hello_fuchsia_test.dart b/runtime/tests/vm/dart/hello_fuchsia_test.dart
index 501ffe7..9ed439b 100644
--- a/runtime/tests/vm/dart/hello_fuchsia_test.dart
+++ b/runtime/tests/vm/dart/hello_fuchsia_test.dart
@@ -2,6 +2,216 @@
// 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.
-main() {
+import "dart:async";
+import "dart:io";
+
+testSimpleBind() async {
+ var s = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+ print("port = ${s.port}");
+ await s.close();
+}
+
+testSimpleConnect() async {
+ var server = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+ print("server port = ${server.port}");
+ server.listen((socket) {
+ print("listen socket port = ${socket.port}");
+ socket.close();
+ });
+ var socket = await RawSocket.connect("127.0.0.1", server.port);
+ print("socket port = ${socket.port}");
+ await server.close();
+ await socket.close();
+}
+
+testSimpleReadWrite({bool dropReads}) async {
+ // This test creates a server and a client connects. The client then
+ // writes and the server echos. When the server has finished its
+ // echo it half-closes. When the client gets the close event is
+ // closes fully.
+
+ const messageSize = 1000;
+ int serverReadCount = 0;
+ int clientReadCount = 0;
+
+ List<int> createTestData() {
+ return new List<int>.generate(messageSize, (index) => index & 0xff);
+ }
+
+ void verifyTestData(List<int> data) {
+ assert(messageSize == data.length);
+ List<int> expected = createTestData();
+ for (int i = 0; i < messageSize; i++) {
+ assert(expected[i] == data[i]);
+ }
+ }
+
+ var server = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+ server.listen((client) {
+ int bytesRead = 0;
+ int bytesWritten = 0;
+ bool closedEventReceived = false;
+ List<int> data = new List<int>(messageSize);
+ bool doneReading = false;
+
+ client.writeEventsEnabled = false;
+ client.listen((event) {
+ switch (event) {
+ case RawSocketEvent.READ:
+ if (doneReading) {
+ break;
+ }
+ if (dropReads) {
+ if (serverReadCount != 10) {
+ serverReadCount++;
+ break;
+ } else {
+ serverReadCount = 0;
+ }
+ }
+ print("client READ event bytesRead = $bytesRead");
+ assert(bytesWritten == 0);
+ assert(client.available() > 0);
+ var buffer = client.read(200);
+ print("client READ event: read ${buffer.length} more bytes");
+ data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+ bytesRead += buffer.length;
+ if (bytesRead == data.length) {
+ verifyTestData(data);
+ print("client READ event. Done reading, enabling writes");
+ client.writeEventsEnabled = true;
+ doneReading = true;
+ }
+ break;
+ case RawSocketEvent.WRITE:
+ assert(!client.writeEventsEnabled);
+ bytesWritten += client.write(
+ data, bytesWritten, data.length - bytesWritten);
+ print("client WRITE event: $bytesWritten written");
+ if (bytesWritten < data.length) {
+ client.writeEventsEnabled = true;
+ }
+ if (bytesWritten == data.length) {
+ print("client WRITE event: done writing.");
+ client.shutdown(SocketDirection.SEND);
+ }
+ break;
+ case RawSocketEvent.READ_CLOSED:
+ print("client READ_CLOSED event");
+ server.close();
+ break;
+ case RawSocketEvent.CLOSED:
+ assert(!closedEventReceived);
+ print("client CLOSED event");
+ closedEventReceived = true;
+ break;
+ default: throw "Unexpected event $event";
+ }
+ },
+ onDone: () {assert(closedEventReceived);});
+ });
+
+ {
+ var completer = new Completer();
+ var socket = await RawSocket.connect("127.0.0.1", server.port);
+ int bytesRead = 0;
+ int bytesWritten = 0;
+ bool closedEventReceived = false;
+ List<int> data = createTestData();
+
+ socket.listen((event) {
+ switch (event) {
+ case RawSocketEvent.READ:
+ assert(socket.available() > 0);
+ if (dropReads) {
+ if (clientReadCount != 10) {
+ clientReadCount++;
+ break;
+ } else {
+ clientReadCount = 0;
+ }
+ }
+ print("server READ event: ${bytesRead} read");
+ var buffer = socket.read();
+ print("server READ event: read ${buffer.length} more bytes");
+ data.setRange(bytesRead, bytesRead + buffer.length, buffer);
+ bytesRead += buffer.length;
+ break;
+ case RawSocketEvent.WRITE:
+ assert(bytesRead == 0);
+ assert(!socket.writeEventsEnabled);
+ bytesWritten += socket.write(
+ data, bytesWritten, data.length - bytesWritten);
+ print("server WRITE event: ${bytesWritten} written");
+ if (bytesWritten < data.length) {
+ socket.writeEventsEnabled = true;
+ } else {
+ print("server WRITE event: done writing");
+ data = new List<int>(messageSize);
+ }
+ break;
+ case RawSocketEvent.READ_CLOSED:
+ print("server READ_CLOSED event");
+ verifyTestData(data);
+ socket.close();
+ break;
+ case RawSocketEvent.CLOSED:
+ assert(!closedEventReceived);
+ print("server CLOSED event");
+ closedEventReceived = true;
+ break;
+ default: throw "Unexpected event $event";
+ }
+ },
+ onDone: () {
+ assert(closedEventReceived);
+ completer.complete(null);
+ });
+
+ return completer.future;
+ }
+}
+
+Future testGoogleUrl(SecurityContext context, String outcome) async {
+ var client = new HttpClient(context: context);
+ // We need to use an external server that is backed by a
+ // built-in root certificate authority.
+ try {
+ // First, check if the lookup works.
+ await InternetAddress.lookup('www.google.com');
+ var request = await client.getUrl(Uri.parse('http://www.google.com'));
+ request.followRedirects = false;
+ var response = await request.close();
+ assert('pass' == outcome);
+ try { await response.drain(); } catch (e) {
+ print('drain failed: $e');
+ }
+ } catch (e) {
+ // Lookup failed or connection failed. Don't report a failure.
+ print("SocketException: $e");
+ } finally {
+ client.close();
+ }
+}
+
+main() async {
print("Hello, Fuchsia!");
+
+ print("testSimpleBind");
+ await testSimpleBind();
+ print("testSimpleBind done");
+
+ print("testSimpleConnect");
+ await testSimpleConnect();
+ print("testSimpleConnect done");
+
+ // print("testSimpleReadWrite");
+ // await testSimpleReadWrite(dropReads: false);
+ // print("testSimpleReadWrite done");
+
+ // print("testGoogleUrl");
+ // await testGoogleUrl(null, 'pass');
+ // print("testGoogleUrl done");
+
+ print("Goodbyte, Fuchsia!");
}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 61d2bac..20ba97a 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -163,3 +163,6 @@
[ $hot_reload || $hot_reload_rollback ]
dart/spawn_shutdown_test: Skip # We can shutdown an isolate before it reloads.
dart/spawn_infinite_loop_test: Skip # We can shutdown an isolate before it reloads.
+
+[ $runtime == dartium ]
+dart/hello_fuchsia_test: Fail # Issue 27867
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index 8e47ef7..9bbc3a4 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -90,7 +90,6 @@
configs += [
"..:dart_config",
"..:dart_maybe_product_config",
- "..:dart_maybe_precompiled_runtime_config",
"..:dart_no_snapshot_config",
]
public_configs = [ ":libdart_vm_config" ]
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index 5b4c20f..a354ddc 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -321,8 +321,8 @@
const uint8_t* buffer,
intptr_t buffer_size) {
Zone* zone = thread->zone();
- kernel::Program* program =
- ReadPrecompiledKernelFromBuffer(buffer, buffer_size);
+ kernel::KernelReader reader(buffer, buffer_size, true);
+ kernel::Program* program = reader.ReadPrecompiledProgram();
if (program == NULL) {
const String& message =
String::Handle(zone, String::New("Failed to read Kernel file"));
@@ -343,7 +343,6 @@
Library& library = Library::Handle(zone);
String& dart_name = String::Handle(zone);
String& kernel_name = String::Handle(zone);
- kernel::KernelReader reader(NULL, -1, true);
for (intptr_t i = 0; i < kBootstrapLibraryCount; ++i) {
ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
library = isolate->object_store()->bootstrap_library(id);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 7ae1810..536299c 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -112,6 +112,7 @@
V(RegExp_getIsCaseSensitive, 1) \
V(RegExp_getGroupCount, 1) \
V(RegExp_ExecuteMatch, 3) \
+ V(RegExp_ExecuteMatchSticky, 3) \
V(List_allocate, 2) \
V(List_getIndexed, 2) \
V(List_setIndexed, 3) \
diff --git a/runtime/vm/bootstrap_nocore.cc b/runtime/vm/bootstrap_nocore.cc
index d804b24..9fda4b3 100644
--- a/runtime/vm/bootstrap_nocore.cc
+++ b/runtime/vm/bootstrap_nocore.cc
@@ -59,8 +59,8 @@
const uint8_t* buffer,
intptr_t buffer_length) {
Zone* zone = thread->zone();
- kernel::Program* program =
- ReadPrecompiledKernelFromBuffer(buffer, buffer_length);
+ kernel::KernelReader reader(buffer, buffer_length, true);
+ kernel::Program* program = reader.ReadPrecompiledProgram();
if (program == NULL) {
const String& message =
String::Handle(zone, String::New("Failed to read Kernel file"));
@@ -81,7 +81,6 @@
Library& library = Library::Handle(zone);
String& dart_name = String::Handle(zone);
String& kernel_name = String::Handle(zone);
- kernel::KernelReader reader(NULL, -1, true);
for (intptr_t i = 0; i < bootstrap_library_count; ++i) {
ObjectStore::BootstrapLibraryId id = bootstrap_libraries[i].index;
library = isolate->object_store()->bootstrap_library(id);
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index 16f2e18..e5a1dd9 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -207,14 +207,15 @@
// - Qualcomm Krait CPUs (QCT APQ8064) in Nexus 4 and 7 incorrectly report
// that they lack integer division.
// - Marvell Armada 370/XP incorrectly reports that it has integer division.
- // - The Pixel lacks integer division even though ARMv8 requires it in A32.
+ // - Qualcomm Snapdragon 820/821 CPUs (MSM 8996 and MSM8996pro) in Xiaomi MI5
+ // and Pixel lack integer division even though ARMv8 requires it in A32.
bool is_krait = CpuInfo::FieldContains(kCpuInfoHardware, "QCT APQ8064");
bool is_armada_370xp =
CpuInfo::FieldContains(kCpuInfoHardware, "Marvell Armada 370/XP");
- bool is_pixel = CpuInfo::FieldContains(kCpuInfoHardware, "MSM8996pro");
+ bool is_snapdragon = CpuInfo::FieldContains(kCpuInfoHardware, "MSM8996");
if (is_krait) {
integer_division_supported_ = FLAG_use_integer_division;
- } else if (is_armada_370xp || is_pixel) {
+ } else if (is_armada_370xp || is_snapdragon) {
integer_division_supported_ = false;
} else {
integer_division_supported_ =
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index e5cf6ae..e58810d 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -5094,7 +5094,7 @@
}
}
}
- // Check for default VM provided values. If it was not overriden on the
+ // Check for default VM provided values. If it was not overridden on the
// command line.
if (Symbols::DartIsVM().Equals(name)) {
return Symbols::True().raw();
@@ -6326,15 +6326,16 @@
DART_EXPORT Dart_Handle
Dart_Precompile(Dart_QualifiedFunctionName entry_points[], bool reset_fields) {
- UNREACHABLE();
- return 0;
+ return Api::NewError(
+ "This VM was built without support for AOT compilation.");
}
DART_EXPORT Dart_Handle
Dart_CreatePrecompiledSnapshotAssembly(uint8_t** assembly_buffer,
intptr_t* assembly_size) {
- UNREACHABLE();
+ return Api::NewError(
+ "This VM was built without support for AOT compilation.");
return 0;
}
@@ -6348,8 +6349,8 @@
intptr_t* instructions_blob_size,
uint8_t** rodata_blob_buffer,
intptr_t* rodata_blob_size) {
- UNREACHABLE();
- return 0;
+ return Api::NewError(
+ "This VM was built without support for AOT compilation.");
}
#else // DART_PRECOMPILER
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 4b73efd..f1334b8 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -381,12 +381,11 @@
Instance& stacktrace = Instance::Handle(zone);
bool handler_exists = false;
bool handler_needs_stacktrace = false;
+ // Find the exception handler and determine if the handler needs a
+ // stacktrace.
+ handler_exists = FindExceptionHandler(thread, &handler_pc, &handler_sp,
+ &handler_fp, &handler_needs_stacktrace);
if (use_preallocated_stacktrace) {
- stacktrace ^= isolate->object_store()->preallocated_stack_trace();
- PreallocatedStacktraceBuilder frame_builder(stacktrace);
- handler_exists =
- FindExceptionHandler(thread, &handler_pc, &handler_sp, &handler_fp,
- &handler_needs_stacktrace);
if (handler_pc == 0) {
// No Dart frame.
ASSERT(incoming_exception.raw() ==
@@ -396,37 +395,33 @@
thread->long_jump_base()->Jump(1, error);
UNREACHABLE();
}
+ stacktrace ^= isolate->object_store()->preallocated_stack_trace();
+ PreallocatedStacktraceBuilder frame_builder(stacktrace);
if (handler_needs_stacktrace) {
BuildStackTrace(&frame_builder);
}
} else {
- // Get stacktrace field of class Error. This is needed to determine whether
- // we have a subclass of Error which carries around its stack trace.
- const Field& stacktrace_field =
- Field::Handle(zone, LookupStacktraceField(exception));
-
- // Find the exception handler and determine if the handler needs a
- // stacktrace.
- handler_exists =
- FindExceptionHandler(thread, &handler_pc, &handler_sp, &handler_fp,
- &handler_needs_stacktrace);
if (!existing_stacktrace.IsNull()) {
// If we have an existing stack trace then this better be a rethrow. The
// reverse is not necessarily true (e.g. Dart_PropagateError can cause
// a rethrow being called without an existing stacktrace.)
ASSERT(is_rethrow);
- ASSERT(stacktrace_field.IsNull() ||
- (exception.GetField(stacktrace_field) != Object::null()));
stacktrace = existing_stacktrace.raw();
- } else if (!stacktrace_field.IsNull() || handler_needs_stacktrace) {
- // Collect the stacktrace if needed.
- ASSERT(existing_stacktrace.IsNull());
- stacktrace = Exceptions::CurrentStacktrace();
- // If we have an Error object, then set its stackTrace field only if it
- // not yet initialized.
- if (!stacktrace_field.IsNull() &&
- (exception.GetField(stacktrace_field) == Object::null())) {
- exception.SetField(stacktrace_field, stacktrace);
+ } else {
+ // Get stacktrace field of class Error to determine whether we have a
+ // subclass of Error which carries around its stack trace.
+ const Field& stacktrace_field =
+ Field::Handle(zone, LookupStacktraceField(exception));
+ if (!stacktrace_field.IsNull() || handler_needs_stacktrace) {
+ // Collect the stacktrace if needed.
+ ASSERT(existing_stacktrace.IsNull());
+ stacktrace = Exceptions::CurrentStacktrace();
+ // If we have an Error object, then set its stackTrace field only if it
+ // not yet initialized.
+ if (!stacktrace_field.IsNull() &&
+ (exception.GetField(stacktrace_field) == Object::null())) {
+ exception.SetField(stacktrace_field, stacktrace);
+ }
}
}
}
@@ -511,12 +506,15 @@
DartFrameIterator iterator;
const Script& script = Script::Handle(zone, GetCallerScript(&iterator));
- intptr_t line;
+ intptr_t line = -1;
intptr_t column = -1;
- if (script.HasSource()) {
- script.GetTokenLocation(location, &line, &column);
- } else {
- script.GetTokenLocation(location, &line, NULL);
+ ASSERT(!script.IsNull());
+ if (location.IsReal()) {
+ if (script.HasSource() || script.kind() == RawScript::kKernelTag) {
+ script.GetTokenLocation(location, &line, &column);
+ } else {
+ script.GetTokenLocation(location, &line, NULL);
+ }
}
// Initialize '_url', '_line', and '_column' arguments.
args.SetAt(0, String::Handle(zone, script.url()));
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc
index b8e84b5..fdf1d2e 100644
--- a/runtime/vm/flow_graph.cc
+++ b/runtime/vm/flow_graph.cc
@@ -428,7 +428,7 @@
// Use CHA to determine if the call needs a class check: if the callee's
-// receiver is the same as the caller's receiver and there are no overriden
+// receiver is the same as the caller's receiver and there are no overridden
// callee functions, then no class check is needed.
bool FlowGraph::InstanceCallNeedsClassCheck(InstanceCallInstr* call,
RawFunction::Kind kind) const {
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index d2ee67e..729608f 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -1096,15 +1096,6 @@
}
-void FlowGraphCompiler::GeneratePatchableCall(TokenPosition token_pos,
- const StubEntry& stub_entry,
- RawPcDescriptors::Kind kind,
- LocationSummary* locs) {
- // No patchable calls on ia32.
- GenerateCall(token_pos, stub_entry, kind, locs);
-}
-
-
void FlowGraphCompiler::GenerateDartCall(intptr_t deopt_id,
TokenPosition token_pos,
const StubEntry& stub_entry,
diff --git a/runtime/vm/intermediate_language_dbc.cc b/runtime/vm/intermediate_language_dbc.cc
index 207153d..f11a372 100644
--- a/runtime/vm/intermediate_language_dbc.cc
+++ b/runtime/vm/intermediate_language_dbc.cc
@@ -417,13 +417,17 @@
}
-EMIT_NATIVE_CODE(InitStaticField, 1) {
+EMIT_NATIVE_CODE(InitStaticField,
+ 1,
+ Location::NoLocation(),
+ LocationSummary::kCall) {
if (compiler->is_optimizing()) {
__ Push(locs()->in(0).reg());
__ InitStaticTOS();
} else {
__ InitStaticTOS();
}
+ compiler->RecordAfterCall(this);
}
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index c90b2c5..c3f905d 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -845,20 +845,17 @@
__ movl(EDX, Immediate(argc_tag));
const StubEntry* stub_entry;
- if (link_lazily()) {
- stub_entry = StubCode::CallBootstrapCFunction_entry();
- __ movl(ECX, Immediate(NativeEntry::LinkNativeCallEntry()));
- compiler->GeneratePatchableCall(token_pos(), *stub_entry,
- RawPcDescriptors::kOther, locs());
- } else {
- stub_entry = (is_bootstrap_native())
- ? StubCode::CallBootstrapCFunction_entry()
- : StubCode::CallNativeCFunction_entry();
- const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
- __ movl(ECX, Immediate(label.address()));
- compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
- locs());
- }
+
+ // There is no lazy-linking support on ia32.
+ ASSERT(!link_lazily());
+ stub_entry = (is_bootstrap_native())
+ ? StubCode::CallBootstrapCFunction_entry()
+ : StubCode::CallNativeCFunction_entry();
+ const ExternalLabel label(reinterpret_cast<uword>(native_c_function()));
+ __ movl(ECX, Immediate(label.address()));
+ compiler->GenerateCall(token_pos(), *stub_entry, RawPcDescriptors::kOther,
+ locs());
+
__ popl(result);
}
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc
index 1f50387..26573ce 100644
--- a/runtime/vm/intrinsifier.cc
+++ b/runtime/vm/intrinsifier.cc
@@ -1160,6 +1160,16 @@
return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound);
}
+
+
+void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+ IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/false);
+}
+
+
+void Intrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler) {
+ IntrinsifyRegExpExecuteMatch(assembler, /*sticky=*/true);
+}
#endif // !defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h
index 9242937..81d9e65 100644
--- a/runtime/vm/intrinsifier.h
+++ b/runtime/vm/intrinsifier.h
@@ -56,6 +56,8 @@
GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
#undef DECLARE_FUNCTION
+
+ static void IntrinsifyRegExpExecuteMatch(Assembler* assembler, bool sticky);
#endif
};
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc
index d79a9da..99205a7 100644
--- a/runtime/vm/intrinsifier_arm.cc
+++ b/runtime/vm/intrinsifier_arm.cc
@@ -2218,7 +2218,8 @@
}
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+ bool sticky) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2237,7 +2238,8 @@
__ LoadClassId(R1, R1);
__ AddImmediate(R1, R1, -kOneByteStringCid);
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
- __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
+ __ ldr(R0,
+ FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
// Registers are now set up for the lazy compile stub. It expects the function
// in R0, the argument descriptor in R4, and IC-Data in R9.
diff --git a/runtime/vm/intrinsifier_arm64.cc b/runtime/vm/intrinsifier_arm64.cc
index a78bae6..06f623e 100644
--- a/runtime/vm/intrinsifier_arm64.cc
+++ b/runtime/vm/intrinsifier_arm64.cc
@@ -2284,7 +2284,8 @@
}
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+ bool sticky) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2303,7 +2304,8 @@
__ LoadClassId(R1, R1);
__ AddImmediate(R1, R1, -kOneByteStringCid);
__ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
- __ ldr(R0, FieldAddress(R1, RegExp::function_offset(kOneByteStringCid)));
+ __ ldr(R0,
+ FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
// Registers are now set up for the lazy compile stub. It expects the function
// in R0, the argument descriptor in R4, and IC-Data in R5.
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc
index 9b5cf1d..6c0f6a1 100644
--- a/runtime/vm/intrinsifier_ia32.cc
+++ b/runtime/vm/intrinsifier_ia32.cc
@@ -2230,7 +2230,8 @@
}
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+ bool sticky) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2248,8 +2249,8 @@
__ movl(EDI, Address(ESP, kStringParamOffset));
__ LoadClassId(EDI, EDI);
__ SubImmediate(EDI, Immediate(kOneByteStringCid));
- __ movl(EAX, FieldAddress(EBX, EDI, TIMES_4,
- RegExp::function_offset(kOneByteStringCid)));
+ __ movl(EAX, FieldAddress(EBX, EDI, TIMES_4, RegExp::function_offset(
+ kOneByteStringCid, sticky)));
// Registers are now set up for the lazy compile stub. It expects the function
// in EAX, the argument descriptor in EDX, and IC-Data in ECX.
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc
index 54753a2..04707c7 100644
--- a/runtime/vm/intrinsifier_mips.cc
+++ b/runtime/vm/intrinsifier_mips.cc
@@ -2339,7 +2339,8 @@
}
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+ bool sticky) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 2 * kWordSize;
@@ -2359,7 +2360,8 @@
__ AddImmediate(T2, -kOneByteStringCid);
__ sll(T2, T2, kWordSizeLog2);
__ addu(T2, T2, T1);
- __ lw(T0, FieldAddress(T2, RegExp::function_offset(kOneByteStringCid)));
+ __ lw(T0,
+ FieldAddress(T2, RegExp::function_offset(kOneByteStringCid, sticky)));
// Registers are now set up for the lazy compile stub. It expects the function
// in T0, the argument descriptor in S4, and IC-Data in S5.
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc
index b888804..fa250d4 100644
--- a/runtime/vm/intrinsifier_x64.cc
+++ b/runtime/vm/intrinsifier_x64.cc
@@ -2192,7 +2192,8 @@
}
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler) {
+void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+ bool sticky) {
if (FLAG_interpret_irregexp) return;
static const intptr_t kRegExpParamOffset = 3 * kWordSize;
@@ -2210,8 +2211,8 @@
__ movq(RDI, Address(RSP, kStringParamOffset));
__ LoadClassId(RDI, RDI);
__ SubImmediate(RDI, Immediate(kOneByteStringCid));
- __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8,
- RegExp::function_offset(kOneByteStringCid)));
+ __ movq(RAX, FieldAddress(RBX, RDI, TIMES_8, RegExp::function_offset(
+ kOneByteStringCid, sticky)));
// Registers are now set up for the lazy compile stub. It expects the function
// in RAX, the argument descriptor in R10, and IC-Data in RCX.
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 7f25aec..5e08876 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1102,11 +1102,13 @@
#ifndef PRODUCT
bool Isolate::ReloadSources(JSONStream* js,
bool force_reload,
+ const char* root_script_url,
+ const char* packages_url,
bool dont_delete_reload_context) {
ASSERT(!IsReloading());
has_attempted_reload_ = true;
reload_context_ = new IsolateReloadContext(this, js);
- reload_context_->Reload(force_reload);
+ reload_context_->Reload(force_reload, root_script_url, packages_url);
bool success = !reload_context_->reload_aborted();
if (!dont_delete_reload_context) {
DeleteReloadContext();
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 7d43c57..625be62 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -262,6 +262,8 @@
// the caller to delete is separately if it is still needed.
bool ReloadSources(JSONStream* js,
bool force_reload,
+ const char* root_script_url = NULL,
+ const char* packages_url = NULL,
bool dont_delete_reload_context = false);
bool MakeRunnable();
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 9d6569e..c375df3 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -420,7 +420,11 @@
const Library& a_lib = Library::Handle(a.library());
const Library& b_lib = Library::Handle(b.library());
- return IsSameLibrary(a_lib, b_lib);
+
+ if (a_lib.IsNull() || b_lib.IsNull()) {
+ return a_lib.raw() == b_lib.raw();
+ }
+ return (a_lib.private_key() == b_lib.private_key());
}
@@ -450,7 +454,7 @@
reasons_to_cancel_reload_(zone_, 0),
cid_mapper_(),
modified_libs_(NULL),
- script_uri_(String::null()),
+ script_url_(String::null()),
error_(Error::null()),
old_classes_set_storage_(Array::null()),
class_map_storage_(Array::null()),
@@ -459,7 +463,9 @@
become_map_storage_(Array::null()),
become_enum_mappings_(GrowableObjectArray::null()),
saved_root_library_(Library::null()),
- saved_libraries_(GrowableObjectArray::null()) {
+ saved_libraries_(GrowableObjectArray::null()),
+ root_url_prefix_(String::null()),
+ old_root_url_prefix_(String::null()) {
// NOTE: DO NOT ALLOCATE ANY RAW OBJECTS HERE. The IsolateReloadContext is not
// associated with the isolate yet and if a GC is triggered here the raw
// objects will not be properly accounted for.
@@ -502,20 +508,58 @@
};
+static intptr_t CommonSuffixLength(const char* a, const char* b) {
+ const intptr_t a_length = strlen(a);
+ const intptr_t b_length = strlen(b);
+ intptr_t a_cursor = a_length;
+ intptr_t b_cursor = b_length;
+
+ while ((a_cursor >= 0) && (b_cursor >= 0)) {
+ if (a[a_cursor] != b[b_cursor]) {
+ break;
+ }
+ a_cursor--;
+ b_cursor--;
+ }
+
+ ASSERT((a_length - a_cursor) == (b_length - b_cursor));
+ return (a_length - a_cursor);
+}
+
+
// NOTE: This function returns *after* FinalizeLoading is called.
-void IsolateReloadContext::Reload(bool force_reload) {
+void IsolateReloadContext::Reload(bool force_reload,
+ const char* root_script_url,
+ const char* packages_url_) {
TIMELINE_SCOPE(Reload);
Thread* thread = Thread::Current();
ASSERT(isolate() == thread->isolate());
// Grab root library before calling CheckpointBeforeReload.
- const Library& root_lib = Library::Handle(object_store()->root_library());
- ASSERT(!root_lib.IsNull());
- const String& root_lib_url = String::Handle(root_lib.url());
+ const Library& old_root_lib = Library::Handle(object_store()->root_library());
+ ASSERT(!old_root_lib.IsNull());
+ const String& old_root_lib_url = String::Handle(old_root_lib.url());
+ // Root library url.
+ const String& root_lib_url =
+ (root_script_url == NULL) ? old_root_lib_url
+ : String::Handle(String::New(root_script_url));
+
+ // Check to see if the base url of the loaded libraries has moved.
+ if (!old_root_lib_url.Equals(root_lib_url)) {
+ const char* old_root_library_url_c = old_root_lib_url.ToCString();
+ const char* root_library_url_c = root_lib_url.ToCString();
+ const intptr_t common_suffix_length =
+ CommonSuffixLength(root_library_url_c, old_root_library_url_c);
+ root_url_prefix_ = String::SubString(
+ root_lib_url, 0, root_lib_url.Length() - common_suffix_length + 1);
+ old_root_url_prefix_ =
+ String::SubString(old_root_lib_url, 0,
+ old_root_lib_url.Length() - common_suffix_length + 1);
+ }
// Check to see which libraries have been modified.
modified_libs_ = FindModifiedLibraries(force_reload);
- if (!modified_libs_->Contains(root_lib.index())) {
+ if (!modified_libs_->Contains(old_root_lib.index())) {
ASSERT(modified_libs_->IsEmpty());
reload_skipped_ = true;
ReportOnJSON(js_);
@@ -570,17 +614,25 @@
// for example, top level parse errors. We want to capture these errors while
// propagating the UnwindError or an UnhandledException error.
Object& result = Object::Handle(thread->zone());
+
+ String& packages_url = String::Handle();
+ if (packages_url_ != NULL) {
+ packages_url = String::New(packages_url_);
+ }
+
+ TIR_Print("---- ENTERING TAG HANDLER\n");
{
TransitionVMToNative transition(thread);
Api::Scope api_scope(thread);
Dart_Handle retval = (I->library_tag_handler())(
- Dart_kScriptTag, Api::NewHandle(thread, Library::null()),
+ Dart_kScriptTag, Api::NewHandle(thread, packages_url.raw()),
Api::NewHandle(thread, root_lib_url.raw()));
result = Api::UnwrapHandle(retval);
}
//
// WEIRD CONTROL FLOW ENDS.
+ TIR_Print("---- EXITED TAG HANDLER\n");
BackgroundCompiler::Enable();
@@ -613,6 +665,7 @@
AddClassMapping(new_cls, new_cls);
return;
}
+ VTIR_Print("Registering class: %s\n", new_cls.ToCString());
new_cls.set_id(old_cls.id());
isolate()->class_table()->SetAt(old_cls.id(), new_cls.raw());
if (!old_cls.is_enum_class()) {
@@ -1225,21 +1278,8 @@
}
}
- // Rehash constants map for all new classes and the closure class.
- Class& cls = Class::Handle(zone_);
- cls = I->class_table()->At(kClosureCid);
- cls.RehashConstants(zone_);
- {
- ASSERT(class_map_storage_ != Array::null());
- UnorderedHashMap<ClassMapTraits> map(class_map_storage_);
- UnorderedHashMap<ClassMapTraits>::Iterator it(&map);
- while (it.MoveNext()) {
- const intptr_t entry = it.Current();
- cls = Class::RawCast(map.GetKey(entry));
- cls.RehashConstants(zone_);
- }
- map.Release();
- }
+ // Rehash constants map for all classes.
+ RehashConstants();
#ifdef DEBUG
// Verify that all canonical instances are correctly setup in the
@@ -1252,6 +1292,28 @@
}
+void IsolateReloadContext::RehashConstants() {
+ TIMELINE_SCOPE(RehashConstants);
+ ClassTable* class_table = I->class_table();
+ Class& cls = Class::Handle(zone_);
+ const intptr_t top = class_table->NumCids();
+ for (intptr_t cid = kInstanceCid; cid < top; cid++) {
+ if (!class_table->IsValidIndex(cid) || !class_table->HasValidClassAt(cid)) {
+ // Skip invalid classes.
+ continue;
+ }
+ if (RawObject::IsNumberClassId(cid) || RawObject::IsStringClassId(cid)) {
+ // Skip classes that cannot be affected by the 'become' operation.
+ continue;
+ }
+ // Rehash constants.
+ cls = class_table->At(cid);
+ VTIR_Print("Rehashing constants in class `%s`\n", cls.ToCString());
+ cls.RehashConstants(zone_);
+ }
+}
+
+
bool IsolateReloadContext::IsDirty(const Library& lib) {
const intptr_t index = lib.index();
if (index == static_cast<classid_t>(-1)) {
@@ -1649,6 +1711,11 @@
if (old.IsNull()) {
return String::null();
}
+#if defined(DEBUG)
+ VTIR_Print("`%s` is getting `%s`'s private key.\n",
+ String::Handle(replacement_or_new.url()).ToCString(),
+ String::Handle(old.url()).ToCString());
+#endif
return old.private_key();
}
@@ -1660,10 +1727,54 @@
Library& lib = Library::Handle();
lib ^= old_libraries_set.GetOrNull(replacement_or_new);
old_libraries_set.Release();
+ if (lib.IsNull() && (root_url_prefix_ != String::null()) &&
+ (old_root_url_prefix_ != String::null())) {
+ return OldLibraryOrNullBaseMoved(replacement_or_new);
+ }
return lib.raw();
}
+// Attempt to find the pair to |replacement_or_new| with the knowledge that
+// the base url prefix has moved.
+RawLibrary* IsolateReloadContext::OldLibraryOrNullBaseMoved(
+ const Library& replacement_or_new) {
+ const String& url_prefix = String::Handle(root_url_prefix_);
+ const String& old_url_prefix = String::Handle(old_root_url_prefix_);
+ const intptr_t prefix_length = url_prefix.Length();
+ const intptr_t old_prefix_length = old_url_prefix.Length();
+ const String& new_url = String::Handle(replacement_or_new.url());
+ const String& suffix =
+ String::Handle(String::SubString(new_url, prefix_length));
+ if (!new_url.StartsWith(url_prefix)) {
+ return Library::null();
+ }
+ Library& old = Library::Handle();
+ String& old_url = String::Handle();
+ String& old_suffix = String::Handle();
+ GrowableObjectArray& saved_libs =
+ GrowableObjectArray::Handle(saved_libraries());
+ ASSERT(!saved_libs.IsNull());
+ for (intptr_t i = 0; i < saved_libs.Length(); i++) {
+ old = Library::RawCast(saved_libs.At(i));
+ old_url = old.url();
+ if (!old_url.StartsWith(old_url_prefix)) {
+ continue;
+ }
+ old_suffix ^= String::SubString(old_url, old_prefix_length);
+ if (old_suffix.IsNull()) {
+ continue;
+ }
+ if (old_suffix.Equals(suffix)) {
+ TIR_Print("`%s` is moving to `%s`\n", old_url.ToCString(),
+ new_url.ToCString());
+ return old.raw();
+ }
+ }
+ return Library::null();
+}
+
+
void IsolateReloadContext::BuildLibraryMapping() {
const GrowableObjectArray& libs =
GrowableObjectArray::Handle(object_store()->libraries());
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index e5e5da1..f83297e 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -136,7 +136,9 @@
explicit IsolateReloadContext(Isolate* isolate, JSONStream* js);
~IsolateReloadContext();
- void Reload(bool force_reload);
+ void Reload(bool force_reload,
+ const char* root_script_url = NULL,
+ const char* packages_url = NULL);
// All zone allocated objects must be allocated from this zone.
Zone* zone() const { return zone_; }
@@ -254,6 +256,8 @@
void PostCommit();
+ void RehashConstants();
+
void ClearReplacedObjectBits();
// atomic_install:
@@ -309,6 +313,9 @@
RawClass* OldClassOrNull(const Class& replacement_or_new);
RawLibrary* OldLibraryOrNull(const Library& replacement_or_new);
+
+ RawLibrary* OldLibraryOrNullBaseMoved(const Library& replacement_or_new);
+
void BuildLibraryMapping();
void AddClassMapping(const Class& replacement_or_new, const Class& original);
@@ -326,8 +333,8 @@
RawClass* MappedClass(const Class& replacement_or_new);
RawLibrary* MappedLibrary(const Library& replacement_or_new);
- RawObject** from() { return reinterpret_cast<RawObject**>(&script_uri_); }
- RawString* script_uri_;
+ RawObject** from() { return reinterpret_cast<RawObject**>(&script_url_); }
+ RawString* script_url_;
RawError* error_;
RawArray* old_classes_set_storage_;
RawArray* class_map_storage_;
@@ -337,7 +344,11 @@
RawGrowableObjectArray* become_enum_mappings_;
RawLibrary* saved_root_library_;
RawGrowableObjectArray* saved_libraries_;
- RawObject** to() { return reinterpret_cast<RawObject**>(&saved_libraries_); }
+ RawString* root_url_prefix_;
+ RawString* old_root_url_prefix_;
+ RawObject** to() {
+ return reinterpret_cast<RawObject**>(&old_root_url_prefix_);
+ }
friend class Isolate;
friend class Class; // AddStaticFieldMapping, AddEnumBecomeMapping.
diff --git a/runtime/vm/jit_optimizer.cc b/runtime/vm/jit_optimizer.cc
index 1a7cf2e..ff691b0 100644
--- a/runtime/vm/jit_optimizer.cc
+++ b/runtime/vm/jit_optimizer.cc
@@ -1,7 +1,7 @@
// 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.
-
+#ifndef DART_PRECOMPILED_RUNTIME
#include "vm/jit_optimizer.h"
#include "vm/bit_vector.h"
@@ -1864,3 +1864,4 @@
} // namespace dart
+#endif // DART_PRECOMPILED_RUNTIME
diff --git a/runtime/vm/kernel.h b/runtime/vm/kernel.h
index 93b828b..8e96941 100644
--- a/runtime/vm/kernel.h
+++ b/runtime/vm/kernel.h
@@ -9,6 +9,7 @@
#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/globals.h"
+#include "vm/token_position.h"
#define KERNEL_NODES_DO(M) \
@@ -308,7 +309,7 @@
class LineStartingTable {
public:
- void ReadFrom(Reader* reader, intptr_t length);
+ void ReadFrom(Reader* reader);
void WriteTo(Writer* writer);
~LineStartingTable() {
for (intptr_t i = 0; i < size_; ++i) {
@@ -413,6 +414,7 @@
virtual void VisitChildren(Visitor* visitor);
String* import_uri() { return import_uri_; }
+ intptr_t source_uri_index() { return source_uri_index_; }
String* name() { return name_; }
List<Class>& classes() { return classes_; }
List<Field>& fields() { return fields_; }
@@ -448,6 +450,7 @@
Ref<String> name_;
Ref<String> import_uri_;
+ intptr_t source_uri_index_;
List<Class> classes_;
List<Field> fields_;
List<Procedure> procedures_;
@@ -471,6 +474,7 @@
Library* parent() { return parent_; }
String* name() { return name_; }
+ intptr_t source_uri_index() { return source_uri_index_; }
bool is_abstract() { return is_abstract_; }
List<Expression>& annotations() { return annotations_; }
@@ -489,6 +493,7 @@
Ref<Library> parent_;
Ref<String> name_;
+ intptr_t source_uri_index_;
bool is_abstract_;
List<Expression> annotations_;
@@ -629,21 +634,25 @@
bool IsConst() { return (flags_ & kFlagConst) == kFlagConst; }
bool IsFinal() { return (flags_ & kFlagFinal) == kFlagFinal; }
bool IsStatic() { return (flags_ & kFlagStatic) == kFlagStatic; }
+ intptr_t source_uri_index() { return source_uri_index_; }
DartType* type() { return type_; }
InferredValue* inferred_value() { return inferred_value_; }
Expression* initializer() { return initializer_; }
+ TokenPosition position() { return position_; }
private:
- Field() {}
+ Field() : position_(TokenPosition::kNoSource) {}
template <typename T>
friend class List;
word flags_;
+ intptr_t source_uri_index_;
Child<DartType> type_;
Child<InferredValue> inferred_value_;
Child<Expression> initializer_;
+ TokenPosition position_;
DISALLOW_COPY_AND_ASSIGN(Field);
};
@@ -725,6 +734,7 @@
bool IsAbstract() { return (flags_ & kFlagAbstract) == kFlagAbstract; }
bool IsExternal() { return (flags_ & kFlagExternal) == kFlagExternal; }
bool IsConst() { return (flags_ & kFlagConst) == kFlagConst; }
+ intptr_t source_uri_index() { return source_uri_index_; }
private:
Procedure() : kind_(kIncompleteProcedure), flags_(0), function_(NULL) {}
@@ -734,6 +744,7 @@
ProcedureKind kind_;
word flags_;
+ intptr_t source_uri_index_;
Child<FunctionNode> function_;
DISALLOW_COPY_AND_ASSIGN(Procedure);
@@ -934,9 +945,11 @@
virtual void AcceptTreeVisitor(TreeVisitor* visitor);
virtual void AcceptExpressionVisitor(ExpressionVisitor* visitor) = 0;
+ TokenPosition position() { return position_; }
protected:
- Expression() {}
+ Expression() : position_(TokenPosition::kNoSource) {}
+ TokenPosition position_;
private:
DISALLOW_COPY_AND_ASSIGN(Expression);
@@ -1281,11 +1294,6 @@
public:
static StaticInvocation* ReadFrom(Reader* reader, bool is_const);
virtual void WriteTo(Writer* writer);
-
- explicit StaticInvocation(Procedure* procedure,
- Arguments* args,
- bool is_const)
- : procedure_(procedure), arguments_(args), is_const_(is_const) {}
~StaticInvocation();
virtual void AcceptExpressionVisitor(ExpressionVisitor* visitor);
@@ -2785,6 +2793,8 @@
virtual void VisitChildren(Visitor* visitor);
StringTable& string_table() { return string_table_; }
+ StringTable& source_uri_table() { return source_uri_table_; }
+ LineStartingTable& line_starting_table() { return line_starting_table_; }
List<Library>& libraries() { return libraries_; }
Procedure* main_method() { return main_method_; }
@@ -2794,6 +2804,8 @@
List<Library> libraries_;
Ref<Procedure> main_method_;
StringTable string_table_;
+ StringTable source_uri_table_;
+ LineStartingTable line_starting_table_;
DISALLOW_COPY_AND_ASSIGN(Program);
};
diff --git a/runtime/vm/kernel_binary.cc b/runtime/vm/kernel_binary.cc
index 350690d..a870dd9 100644
--- a/runtime/vm/kernel_binary.cc
+++ b/runtime/vm/kernel_binary.cc
@@ -355,6 +355,13 @@
}
}
+ TokenPosition ReadPosition() {
+ intptr_t value = ReadUInt();
+ // Position is saved as unsigned,
+ // but actually ranges from -1 and up (thus the -1)
+ return TokenPosition(value - 1);
+ }
+
intptr_t ReadListLength() { return ReadUInt(); }
uint8_t ReadByte() { return buffer_[offset_++]; }
@@ -550,6 +557,11 @@
offset_ += length;
}
+ void WritePosition(TokenPosition position) {
+ intptr_t value = position.value() + 1;
+ WriteUInt(value);
+ }
+
template <typename T>
void WriteOptional(T* object) {
if (object == NULL) {
@@ -794,8 +806,8 @@
}
-void LineStartingTable::ReadFrom(Reader* reader, intptr_t length) {
- size_ = length;
+void LineStartingTable::ReadFrom(Reader* reader) {
+ size_ = reader->helper()->program()->source_uri_table().strings().length();
values_ = new intptr_t*[size_];
for (intptr_t i = 0; i < size_; ++i) {
intptr_t line_count = reader->ReadUInt();
@@ -803,9 +815,9 @@
line_starts[0] = line_count;
intptr_t previous_line_start = 0;
for (intptr_t j = 0; j < line_count; ++j) {
- intptr_t lineStart = reader->ReadUInt() + previous_line_start;
- line_starts[j + 1] = lineStart;
- previous_line_start = lineStart;
+ intptr_t line_start = reader->ReadUInt() + previous_line_start;
+ line_starts[j + 1] = line_start;
+ previous_line_start = line_start;
}
values_[i] = line_starts;
}
@@ -834,7 +846,7 @@
ASSERT(flags == 0); // external libraries not supported
name_ = Reference::ReadStringFrom(reader);
import_uri_ = Reference::ReadStringFrom(reader);
- reader->ReadUInt();
+ source_uri_index_ = reader->ReadUInt();
int num_classes = reader->ReadUInt();
classes().EnsureInitialized(num_classes);
@@ -860,7 +872,7 @@
TRACE_WRITE_OFFSET();
name_->WriteTo(writer);
import_uri_->WriteTo(writer);
- writer->WriteUInt(0);
+ writer->WriteUInt(source_uri_index_);
writer->WriteUInt(classes_.length());
for (int i = 0; i < classes_.length(); i++) {
@@ -883,7 +895,7 @@
is_abstract_ = reader->ReadBool();
name_ = Reference::ReadStringFrom(reader);
- reader->ReadUInt();
+ source_uri_index_ = reader->ReadUInt();
annotations_.ReadFromStatic<Expression>(reader);
return this;
@@ -894,7 +906,7 @@
TRACE_WRITE_OFFSET();
writer->WriteBool(is_abstract_);
name_->WriteTo(writer);
- writer->WriteUInt(0);
+ writer->WriteUInt(source_uri_index_);
annotations_.WriteTo(writer);
}
@@ -1128,10 +1140,10 @@
Tag tag = reader->ReadTag();
ASSERT(tag == kField);
- reader->ReadUInt();
+ position_ = reader->ReadPosition();
flags_ = reader->ReadFlags();
name_ = Name::ReadFrom(reader);
- reader->ReadUInt();
+ source_uri_index_ = reader->ReadUInt();
annotations_.ReadFromStatic<Expression>(reader);
type_ = DartType::ReadFrom(reader);
inferred_value_ = reader->ReadOptional<InferredValue>();
@@ -1143,10 +1155,10 @@
void Field::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kField);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
writer->WriteFlags(flags_);
name_->WriteTo(writer);
- writer->WriteUInt(0);
+ writer->WriteUInt(source_uri_index_);
annotations_.WriteTo(writer);
type_->WriteTo(writer);
writer->WriteOptional<InferredValue>(inferred_value_);
@@ -1191,7 +1203,7 @@
kind_ = static_cast<ProcedureKind>(reader->ReadByte());
flags_ = reader->ReadFlags();
name_ = Name::ReadFrom(reader);
- reader->ReadUInt();
+ source_uri_index_ = reader->ReadUInt();
annotations_.ReadFromStatic<Expression>(reader);
function_ = reader->ReadOptional<FunctionNode>();
return this;
@@ -1206,7 +1218,7 @@
writer->WriteByte(kind_);
writer->WriteFlags(flags_);
name_->WriteTo(writer);
- writer->WriteUInt(0);
+ writer->WriteUInt(source_uri_index_);
annotations_.WriteTo(writer);
writer->WriteOptional<FunctionNode>(function_);
}
@@ -1489,7 +1501,7 @@
PropertyGet* PropertyGet::ReadFrom(Reader* reader) {
TRACE_READ_OFFSET();
PropertyGet* get = new PropertyGet();
- reader->ReadUInt();
+ get->position_ = reader->ReadPosition();
get->receiver_ = Expression::ReadFrom(reader);
get->name_ = Name::ReadFrom(reader);
get->interfaceTarget_ = Reference::ReadMemberFrom(reader, true);
@@ -1500,7 +1512,7 @@
void PropertyGet::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kPropertyGet);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
receiver_->WriteTo(writer);
name_->WriteTo(writer);
Reference::WriteMemberTo(writer, interfaceTarget_, true);
@@ -1510,7 +1522,7 @@
PropertySet* PropertySet::ReadFrom(Reader* reader) {
TRACE_READ_OFFSET();
PropertySet* set = new PropertySet();
- reader->ReadUInt();
+ set->position_ = reader->ReadPosition();
set->receiver_ = Expression::ReadFrom(reader);
set->name_ = Name::ReadFrom(reader);
set->value_ = Expression::ReadFrom(reader);
@@ -1522,7 +1534,7 @@
void PropertySet::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kPropertySet);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
receiver_->WriteTo(writer);
name_->WriteTo(writer);
value_->WriteTo(writer);
@@ -1569,7 +1581,7 @@
StaticGet* StaticGet::ReadFrom(Reader* reader) {
TRACE_READ_OFFSET();
StaticGet* get = new StaticGet();
- reader->ReadUInt();
+ get->position_ = reader->ReadPosition();
get->target_ = Reference::ReadMemberFrom(reader);
return get;
}
@@ -1578,7 +1590,7 @@
void StaticGet::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kStaticGet);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
Reference::WriteMemberTo(writer, target_);
}
@@ -1636,7 +1648,7 @@
MethodInvocation* MethodInvocation::ReadFrom(Reader* reader) {
TRACE_READ_OFFSET();
MethodInvocation* invocation = new MethodInvocation();
- reader->ReadUInt();
+ invocation->position_ = reader->ReadPosition();
invocation->receiver_ = Expression::ReadFrom(reader);
invocation->name_ = Name::ReadFrom(reader);
invocation->arguments_ = Arguments::ReadFrom(reader);
@@ -1648,7 +1660,7 @@
void MethodInvocation::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kMethodInvocation);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
receiver_->WriteTo(writer);
name_->WriteTo(writer);
arguments_->WriteTo(writer);
@@ -1677,19 +1689,19 @@
StaticInvocation* StaticInvocation::ReadFrom(Reader* reader, bool is_const) {
TRACE_READ_OFFSET();
-
- reader->ReadUInt();
- Member* member = Reference::ReadMemberFrom(reader);
- Arguments* args = Arguments::ReadFrom(reader);
-
- return new StaticInvocation(Procedure::Cast(member), args, is_const);
+ StaticInvocation* invocation = new StaticInvocation();
+ invocation->is_const_ = is_const;
+ invocation->position_ = reader->ReadPosition();
+ invocation->procedure_ = Procedure::Cast(Reference::ReadMemberFrom(reader));
+ invocation->arguments_ = Arguments::ReadFrom(reader);
+ return invocation;
}
void StaticInvocation::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(is_const_ ? kConstStaticInvocation : kStaticInvocation);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
Reference::WriteMemberTo(writer, procedure_);
arguments_->WriteTo(writer);
}
@@ -1700,7 +1712,7 @@
TRACE_READ_OFFSET();
ConstructorInvocation* invocation = new ConstructorInvocation();
invocation->is_const_ = is_const;
- reader->ReadUInt();
+ invocation->position_ = reader->ReadPosition();
invocation->target_ = Constructor::Cast(Reference::ReadMemberFrom(reader));
invocation->arguments_ = Arguments::ReadFrom(reader);
return invocation;
@@ -1711,7 +1723,7 @@
TRACE_WRITE_OFFSET();
writer->WriteTag(is_const_ ? kConstConstructorInvocation
: kConstructorInvocation);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
Reference::WriteMemberTo(writer, target_);
arguments_->WriteTo(writer);
}
@@ -1974,7 +1986,7 @@
Throw* Throw::ReadFrom(Reader* reader) {
TRACE_READ_OFFSET();
Throw* t = new Throw();
- reader->ReadUInt();
+ t->position_ = reader->ReadPosition();
t->expression_ = Expression::ReadFrom(reader);
return t;
}
@@ -1983,7 +1995,7 @@
void Throw::WriteTo(Writer* writer) {
TRACE_WRITE_OFFSET();
writer->WriteTag(kThrow);
- writer->WriteUInt(0);
+ writer->WritePosition(position_);
expression_->WriteTo(writer);
}
@@ -2793,10 +2805,8 @@
reader->helper()->set_program(program);
program->string_table_.ReadFrom(reader);
- StringTable dummy1;
- dummy1.ReadFrom(reader);
- LineStartingTable dummy2;
- dummy2.ReadFrom(reader, dummy1.strings_.length());
+ program->source_uri_table_.ReadFrom(reader);
+ program->line_starting_table_.ReadFrom(reader);
int libraries = reader->ReadUInt();
program->libraries().EnsureInitialized(libraries);
@@ -2820,10 +2830,8 @@
// NOTE: Currently we don't GC strings and we require that all referenced
// strings in nodes are present in [string_table_].
string_table_.WriteTo(writer);
- StringTable dummy1;
- dummy1.WriteTo(writer);
- LineStartingTable dummy2;
- dummy2.WriteTo(writer);
+ source_uri_table_.WriteTo(writer);
+ line_starting_table_.WriteTo(writer);
libraries_.WriteTo(writer);
Reference::WriteMemberTo(writer, main_method_);
diff --git a/runtime/vm/kernel_reader.cc b/runtime/vm/kernel_reader.cc
index 6c669e4..356d19c 100644
--- a/runtime/vm/kernel_reader.cc
+++ b/runtime/vm/kernel_reader.cc
@@ -93,10 +93,18 @@
return reader_->LookupClass(klass).raw();
}
+Program* KernelReader::ReadPrecompiledProgram() {
+ Program* program = ReadPrecompiledKernelFromBuffer(buffer_, buffer_length_);
+ if (program == NULL) return NULL;
+ intptr_t source_file_count = program->line_starting_table().size();
+ scripts_ = Array::New(source_file_count);
+ program_ = program;
+ return program;
+}
Object& KernelReader::ReadProgram() {
ASSERT(!bootstrapping_);
- Program* program = ReadPrecompiledKernelFromBuffer(buffer_, buffer_length_);
+ Program* program = ReadPrecompiledProgram();
if (program == NULL) {
const dart::String& error = H.DartString("Failed to read .kernell file");
return Object::Handle(Z, ApiError::New(error));
@@ -160,12 +168,7 @@
}
// Setup toplevel class (which contains library fields/procedures).
- // TODO(27590): Figure out why we need this script stuff here.
- Script& script = Script::Handle(
- Z,
- Script::New(H.DartString(""), H.DartString(""), RawScript::kScriptTag));
- script.SetLocationOffset(0, 0);
- script.Tokenize(H.DartString("nop() {}"));
+ Script& script = ScriptAt(kernel_library->source_uri_index());
dart::Class& toplevel_class = dart::Class::Handle(
Z, dart::Class::New(library, Symbols::TopLevel(), script,
TokenPosition::kNoSource));
@@ -183,10 +186,12 @@
ActiveMemberScope active_member_scope(&active_class_, kernel_field);
const dart::String& name = H.DartFieldName(kernel_field->name());
+ const Object& script_class =
+ ClassForScriptAt(toplevel_class, kernel_field->source_uri_index());
dart::Field& field = dart::Field::Handle(
Z, dart::Field::NewTopLevel(name, kernel_field->IsFinal(),
- kernel_field->IsConst(), toplevel_class,
- TokenPosition::kNoSource));
+ kernel_field->IsConst(), script_class,
+ kernel_field->position()));
field.set_kernel_field(kernel_field);
const AbstractType& type = T.TranslateType(kernel_field->type());
field.SetFieldType(type);
@@ -293,8 +298,6 @@
ActiveClassScope active_class_scope(&active_class_, kernel_klass, &klass);
- TokenPosition pos(0);
-
for (intptr_t i = 0; i < kernel_klass->fields().length(); i++) {
Field* kernel_field = kernel_klass->fields()[i];
ActiveMemberScope active_member_scope(&active_class_, kernel_field);
@@ -310,7 +313,7 @@
kernel_field->IsFinal() || kernel_field->IsConst(),
kernel_field->IsConst(),
false, // is_reflectable
- klass, type, pos));
+ klass, type, kernel_field->position()));
field.set_kernel_field(kernel_field);
field.set_has_initializer(kernel_field->initializer() != NULL);
GenerateFieldAccessors(klass, field, kernel_field);
@@ -331,7 +334,7 @@
false, // is_abstract
kernel_constructor->IsExternal(),
false, // is_native
- klass, pos));
+ klass, TokenPosition::kNoSource));
klass.AddFunction(function);
function.set_kernel_function(kernel_constructor);
function.set_result_type(T.ReceiverType(klass));
@@ -367,7 +370,6 @@
kernel_procedure->function());
const dart::String& name = H.DartProcedureName(kernel_procedure);
- TokenPosition pos(0);
bool is_method = kernel_klass != NULL && !kernel_procedure->IsStatic();
bool is_abstract = kernel_procedure->IsAbstract();
bool is_external = kernel_procedure->IsExternal();
@@ -403,13 +405,15 @@
break;
}
}
+ const Object& script_class =
+ ClassForScriptAt(owner, kernel_procedure->source_uri_index());
dart::Function& function = dart::Function::ZoneHandle(
Z, Function::New(name, GetFunctionType(kernel_procedure),
!is_method, // is_static
false, // is_const
is_abstract, is_external,
native_name != NULL, // is_native
- owner, pos));
+ script_class, TokenPosition::kNoSource));
owner.AddFunction(function);
function.set_kernel_function(kernel_procedure);
function.set_is_debuggable(false);
@@ -429,11 +433,42 @@
}
}
+const Object& KernelReader::ClassForScriptAt(const dart::Class& klass,
+ intptr_t source_uri_index) {
+ Script& correct_script = ScriptAt(source_uri_index);
+ if (klass.script() != correct_script.raw()) {
+ // TODO(jensj): We could probably cache this so we don't create
+ // new PatchClasses all the time
+ return PatchClass::ZoneHandle(Z, PatchClass::New(klass, correct_script));
+ }
+ return klass;
+}
+
+Script& KernelReader::ScriptAt(intptr_t source_uri_index) {
+ Script& script = Script::ZoneHandle(Z);
+ script ^= scripts_.At(source_uri_index);
+ if (script.IsNull()) {
+ String* uri = program_->source_uri_table().strings()[source_uri_index];
+ script = Script::New(H.DartString(uri), dart::String::ZoneHandle(Z),
+ RawScript::kKernelTag);
+ scripts_.SetAt(source_uri_index, script);
+ intptr_t* line_starts =
+ program_->line_starting_table().valuesFor(source_uri_index);
+ intptr_t line_count = line_starts[0];
+ Array& array_object = Array::Handle(Z, Array::New(line_count));
+ Smi& value = Smi::Handle(Z);
+ for (intptr_t i = 0; i < line_count; ++i) {
+ value = Smi::New(line_starts[i + 1]);
+ array_object.SetAt(i, value);
+ }
+ script.set_line_starts(array_object);
+ }
+ return script;
+}
+
void KernelReader::GenerateFieldAccessors(const dart::Class& klass,
const dart::Field& field,
Field* kernel_field) {
- TokenPosition pos(0);
-
if (kernel_field->IsStatic() && kernel_field->initializer() != NULL) {
// Static fields with initializers either have the static value set to the
// initializer value if it is simple enough or else set to an uninitialized
@@ -449,6 +484,8 @@
}
const dart::String& getter_name = H.DartGetterName(kernel_field->name());
+ const Object& script_class =
+ ClassForScriptAt(klass, kernel_field->source_uri_index());
Function& getter = Function::ZoneHandle(
Z,
Function::New(
@@ -465,7 +502,7 @@
false, // is_abstract
false, // is_external
false, // is_native
- klass, pos));
+ script_class, kernel_field->position()));
klass.AddFunction(getter);
if (klass.IsTopLevel()) {
dart::Library& library = dart::Library::Handle(Z, klass.library());
@@ -487,7 +524,7 @@
false, // is_abstract
false, // is_external
false, // is_native
- klass, pos));
+ script_class, kernel_field->position()));
klass.AddFunction(setter);
setter.set_kernel_function(kernel_field);
setter.set_result_type(Object::void_type());
@@ -620,26 +657,15 @@
// The class needs to have a script because all the functions in the class
// will inherit it. The predicate Function::IsOptimizable uses the
// absence of a script to detect test functions that should not be
- // optimized. Use a dummy script.
- //
- // TODO(27590): We shouldn't need a dummy script per class. At the
- // least we could have a singleton. At best, we'd change IsOptimizable to
- // detect test functions some other way (like simply not setting the
- // optimizable bit on those functions in the first place).
- TokenPosition pos(0);
- Script& script =
- Script::Handle(Z, Script::New(H.DartString(""), H.DartString(""),
- RawScript::kScriptTag));
- handle =
- &dart::Class::Handle(Z, dart::Class::New(library, name, script, pos));
+ // optimized.
+ Script& script = ScriptAt(klass->source_uri_index());
+ handle = &dart::Class::Handle(
+ Z, dart::Class::New(library, name, script, TokenPosition::kNoSource));
library.AddClass(*handle);
} else if (handle->script() == Script::null()) {
// When bootstrapping we can encounter classes that do not yet have a
// dummy script.
- TokenPosition pos(0);
- Script& script =
- Script::Handle(Z, Script::New(H.DartString(""), H.DartString(""),
- RawScript::kScriptTag));
+ Script& script = ScriptAt(klass->source_uri_index());
handle->set_script(script);
}
// Insert the class in the cache before calling ReadPreliminaryClass so
diff --git a/runtime/vm/kernel_reader.h b/runtime/vm/kernel_reader.h
index 6b1db8a..a361c14 100644
--- a/runtime/vm/kernel_reader.h
+++ b/runtime/vm/kernel_reader.h
@@ -58,6 +58,8 @@
: thread_(dart::Thread::Current()),
zone_(thread_->zone()),
isolate_(thread_->isolate()),
+ scripts_(Array::ZoneHandle(zone_)),
+ program_(NULL),
translation_helper_(this, thread_, zone_, isolate_),
type_translator_(&translation_helper_,
&active_class_,
@@ -66,6 +68,9 @@
buffer_(buffer),
buffer_length_(len) {}
+ // Returns either pointer to a program or null.
+ Program* ReadPrecompiledProgram();
+
// Returns either a library or a failure object.
dart::Object& ReadProgram();
@@ -89,6 +94,13 @@
Procedure* procedure,
Class* kernel_klass = NULL);
+ // If klass's script is not the script at the uri index, return a PatchClass
+ // for klass whose script corresponds to the uri index.
+ // Otherwise return klass.
+ const Object& ClassForScriptAt(const dart::Class& klass,
+ intptr_t source_uri_index);
+ Script& ScriptAt(intptr_t source_uri_index);
+
void GenerateFieldAccessors(const dart::Class& klass,
const dart::Field& field,
Field* kernel_field);
@@ -104,6 +116,8 @@
dart::Thread* thread_;
dart::Zone* zone_;
dart::Isolate* isolate_;
+ Array& scripts_;
+ Program* program_;
ActiveClass active_class_;
BuildingTranslationHelper translation_helper_;
DartTypeTranslator type_translator_;
diff --git a/runtime/vm/kernel_to_il.cc b/runtime/vm/kernel_to_il.cc
index 5490abb..9ebcfc1 100644
--- a/runtime/vm/kernel_to_il.cc
+++ b/runtime/vm/kernel_to_il.cc
@@ -2287,24 +2287,26 @@
}
-Fragment FlowGraphBuilder::InstanceCall(const dart::String& name,
+Fragment FlowGraphBuilder::InstanceCall(TokenPosition position,
+ const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
intptr_t num_args_checked) {
- return InstanceCall(name, kind, argument_count, Array::null_array(),
+ return InstanceCall(position, name, kind, argument_count, Array::null_array(),
num_args_checked);
}
-Fragment FlowGraphBuilder::InstanceCall(const dart::String& name,
+Fragment FlowGraphBuilder::InstanceCall(TokenPosition position,
+ const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
const Array& argument_names,
intptr_t num_args_checked) {
ArgumentArray arguments = GetArguments(argument_count);
- InstanceCallInstr* call = new (Z)
- InstanceCallInstr(TokenPosition::kNoSource, name, kind, arguments,
- argument_names, num_args_checked, ic_data_array_);
+ InstanceCallInstr* call =
+ new (Z) InstanceCallInstr(position, name, kind, arguments, argument_names,
+ num_args_checked, ic_data_array_);
Push(call);
return Fragment(call);
}
@@ -2321,11 +2323,10 @@
}
-Fragment FlowGraphBuilder::ThrowException() {
+Fragment FlowGraphBuilder::ThrowException(TokenPosition position) {
Fragment instructions;
instructions += Drop();
- instructions +=
- Fragment(new (Z) ThrowInstr(TokenPosition::kNoSource)).closed();
+ instructions += Fragment(new (Z) ThrowInstr(position)).closed();
// Use it's side effect of leaving a constant on the stack (does not change
// the graph).
NullConstant();
@@ -2360,10 +2361,22 @@
}
+const dart::Field& MayCloneField(Zone* zone, const dart::Field& field) {
+ if ((Compiler::IsBackgroundCompilation() ||
+ FLAG_force_clone_compiler_objects) &&
+ field.IsOriginal()) {
+ return dart::Field::ZoneHandle(zone, field.CloneFromOriginal());
+ } else {
+ ASSERT(field.IsZoneHandle());
+ return field;
+ }
+}
+
+
Fragment FlowGraphBuilder::LoadField(const dart::Field& field) {
- LoadFieldInstr* load = new (Z)
- LoadFieldInstr(Pop(), &field, AbstractType::ZoneHandle(Z, field.type()),
- TokenPosition::kNoSource);
+ LoadFieldInstr* load = new (Z) LoadFieldInstr(
+ Pop(), &MayCloneField(Z, field),
+ AbstractType::ZoneHandle(Z, field.type()), TokenPosition::kNoSource);
Push(load);
return Fragment(load);
}
@@ -2409,7 +2422,8 @@
Fragment FlowGraphBuilder::InitStaticField(const dart::Field& field) {
- InitStaticFieldInstr* init = new (Z) InitStaticFieldInstr(Pop(), field);
+ InitStaticFieldInstr* init =
+ new (Z) InitStaticFieldInstr(Pop(), MayCloneField(Z, field));
return Fragment(init);
}
@@ -2458,9 +2472,10 @@
}
-Fragment FlowGraphBuilder::StaticCall(const Function& target,
+Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
+ const Function& target,
intptr_t argument_count) {
- return StaticCall(target, argument_count, Array::null_array());
+ return StaticCall(position, target, argument_count, Array::null_array());
}
@@ -2486,13 +2501,13 @@
}
-Fragment FlowGraphBuilder::StaticCall(const Function& target,
+Fragment FlowGraphBuilder::StaticCall(TokenPosition position,
+ const Function& target,
intptr_t argument_count,
const Array& argument_names) {
ArgumentArray arguments = GetArguments(argument_count);
- StaticCallInstr* call =
- new (Z) StaticCallInstr(TokenPosition::kNoSource, target, argument_names,
- arguments, ic_data_array_);
+ StaticCallInstr* call = new (Z) StaticCallInstr(
+ position, target, argument_names, arguments, ic_data_array_);
const intptr_t list_cid =
GetResultCidOfListFactory(Z, target, argument_count);
if (list_cid != kDynamicCid) {
@@ -2527,23 +2542,26 @@
if (value->BindsToConstant()) {
emit_store_barrier = kNoStoreBarrier;
}
- StoreInstanceFieldInstr* store = new (Z) StoreInstanceFieldInstr(
- field, Pop(), value, emit_store_barrier, TokenPosition::kNoSource);
+ StoreInstanceFieldInstr* store = new (Z)
+ StoreInstanceFieldInstr(MayCloneField(Z, field), Pop(), value,
+ emit_store_barrier, TokenPosition::kNoSource);
return Fragment(store);
}
Fragment FlowGraphBuilder::StoreInstanceFieldGuarded(const dart::Field& field) {
Fragment instructions;
+ const dart::Field& field_clone = MayCloneField(Z, field);
if (FLAG_use_field_guards) {
LocalVariable* store_expression = MakeTemporary();
instructions += LoadLocal(store_expression);
- instructions += GuardFieldClass(field, Thread::Current()->GetNextDeoptId());
+ instructions +=
+ GuardFieldClass(field_clone, Thread::Current()->GetNextDeoptId());
instructions += LoadLocal(store_expression);
instructions +=
- GuardFieldLength(field, Thread::Current()->GetNextDeoptId());
+ GuardFieldLength(field_clone, Thread::Current()->GetNextDeoptId());
}
- instructions += StoreInstanceField(field);
+ instructions += StoreInstanceField(field_clone);
return instructions;
}
@@ -2580,8 +2598,8 @@
Fragment FlowGraphBuilder::StoreStaticField(const dart::Field& field) {
- return Fragment(
- new (Z) StoreStaticFieldInstr(field, Pop(), TokenPosition::kNoSource));
+ return Fragment(new (Z) StoreStaticFieldInstr(MayCloneField(Z, field), Pop(),
+ TokenPosition::kNoSource));
}
@@ -2629,12 +2647,12 @@
instructions += Constant(H.DartSymbol("Malformed type."));
instructions += PushArgument(); // message
- instructions += StaticCall(constructor, 5);
+ instructions += StaticCall(TokenPosition::kNoSource, constructor, 5);
instructions += Drop();
// Throw the exception
instructions += PushArgument();
- instructions += ThrowException();
+ instructions += ThrowException(TokenPosition::kNoSource);
return instructions;
}
@@ -2669,7 +2687,7 @@
instructions += NullConstant();
instructions += PushArgument(); // existingArgumentNames
- instructions += StaticCall(throw_function, 6);
+ instructions += StaticCall(TokenPosition::kNoSource, throw_function, 6);
// Leave "result" on the stack since callers expect it to be there (even
// though the function will result in an exception).
@@ -3431,7 +3449,8 @@
// Forward them to the target.
intptr_t argument_count = positional_argument_count + named_argument_count;
if (!target.is_static()) ++argument_count;
- body += StaticCall(target, argument_count, argument_names);
+ body += StaticCall(TokenPosition::kNoSource, target, argument_count,
+ argument_names);
// Return the result.
body += Return();
@@ -3518,7 +3537,7 @@
Z, mirror_class.LookupStaticFunction(dart::Library::PrivateCoreLibName(
Symbols::AllocateInvocationMirror())));
ASSERT(!allocation_function.IsNull());
- body += StaticCall(allocation_function, 4);
+ body += StaticCall(TokenPosition::kMinSource, allocation_function, 4);
body += PushArgument(); // For the call to noSuchMethod.
ArgumentsDescriptor two_arguments(
@@ -3534,7 +3553,7 @@
dart::Class::Handle(Z, I->object_store()->object_class()),
Symbols::NoSuchMethod(), two_arguments);
}
- body += StaticCall(no_such_method, 2);
+ body += StaticCall(TokenPosition::kMinSource, no_such_method, 2);
body += Return();
return new (Z) FlowGraph(*parsed_function_, graph_entry_, next_block_id_ - 1);
@@ -3598,7 +3617,8 @@
// Invoke the getter to get the field value.
body += LoadLocal(scope->VariableAt(0));
body += PushArgument();
- body += InstanceCall(getter_name, Token::kGET, 1);
+ body +=
+ InstanceCall(TokenPosition::kMinSource, getter_name, Token::kGET, 1);
}
body += PushArgument();
@@ -3617,8 +3637,8 @@
body += ClosureCall(descriptor.Count(), argument_names);
} else {
- body += InstanceCall(Symbols::Call(), Token::kILLEGAL, descriptor.Count(),
- argument_names);
+ body += InstanceCall(TokenPosition::kMinSource, Symbols::Call(),
+ Token::kILLEGAL, descriptor.Count(), argument_names);
}
body += Return();
@@ -3731,7 +3751,8 @@
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(init->target()));
intptr_t argument_count = init->arguments()->count() + 1;
- instructions += StaticCall(target, argument_count, argument_names);
+ instructions += StaticCall(TokenPosition::kNoSource, target,
+ argument_count, argument_names);
instructions += Drop();
} else if (initializer->IsRedirectingInitializer()) {
RedirectingInitializer* init = RedirectingInitializer::Cast(initializer);
@@ -3746,7 +3767,8 @@
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(init->target()));
intptr_t argument_count = init->arguments()->count() + 1;
- instructions += StaticCall(target, argument_count, argument_names);
+ instructions += StaticCall(TokenPosition::kNoSource, target,
+ argument_count, argument_names);
instructions += Drop();
} else if (initializer->IsLocalInitializer()) {
// The other initializers following this one might read the variable. This
@@ -4173,7 +4195,7 @@
Fragment instructions = Constant(field);
fragment_ = instructions + LoadStaticField();
} else {
- fragment_ = StaticCall(getter, 0);
+ fragment_ = StaticCall(node->position(), getter, 0);
}
}
} else {
@@ -4182,7 +4204,7 @@
Z, H.LookupStaticMethodByKernelProcedure(procedure));
if (procedure->kind() == Procedure::kGetter) {
- fragment_ = StaticCall(target, 0);
+ fragment_ = StaticCall(node->position(), target, 0);
} else if (procedure->kind() == Procedure::kMethod) {
ASSERT(procedure->IsStatic());
Function& closure_function =
@@ -4223,7 +4245,7 @@
Procedure* procedure = Procedure::Cast(target);
const Function& target = Function::ZoneHandle(
Z, H.LookupStaticMethodByKernelProcedure(procedure));
- instructions += StaticCall(target, 1);
+ instructions += StaticCall(node->position(), target, 1);
// Drop the unused result & leave the stored value on the stack.
fragment_ = instructions + Drop();
@@ -4235,7 +4257,8 @@
Fragment instructions = TranslateExpression(node->receiver());
instructions += PushArgument();
const dart::String& getter_name = H.DartGetterName(node->name());
- fragment_ = instructions + InstanceCall(getter_name, Token::kGET, 1);
+ fragment_ = instructions +
+ InstanceCall(node->position(), getter_name, Token::kGET, 1);
}
@@ -4249,7 +4272,7 @@
instructions += PushArgument();
const dart::String& setter_name = H.DartSetterName(node->name());
- instructions += InstanceCall(setter_name, Token::kSET, 2);
+ instructions += InstanceCall(node->position(), setter_name, Token::kSET, 2);
fragment_ = instructions + Drop();
}
@@ -4279,7 +4302,7 @@
Fragment instructions = TranslateExpression(node->receiver());
instructions += PushArgument();
- fragment_ = instructions + StaticCall(target, 1);
+ fragment_ = instructions + StaticCall(node->position(), target, 1);
}
@@ -4296,7 +4319,7 @@
instructions += TranslateExpression(node->value());
instructions += StoreLocal(value);
instructions += PushArgument();
- instructions += StaticCall(target, 2);
+ instructions += StaticCall(node->position(), target, 2);
fragment_ = instructions + Drop();
}
@@ -4381,7 +4404,8 @@
instructions += StrictCompare(Token::kEQ_STRICT, /*number_check=*/true);
} else {
instructions += TranslateArguments(node->arguments(), NULL);
- instructions += StaticCall(target, argument_count, argument_names);
+ instructions +=
+ StaticCall(node->position(), target, argument_count, argument_names);
if (target.IsGenerativeConstructor()) {
// Drop the result of the constructor call and leave [instance_variable]
@@ -4438,8 +4462,9 @@
num_args_checked = argument_count;
}
- fragment_ = instructions + InstanceCall(name, token_kind, argument_count,
- argument_names, num_args_checked);
+ fragment_ = instructions + InstanceCall(node->position(), name, token_kind,
+ argument_count, argument_names,
+ num_args_checked);
}
@@ -4456,7 +4481,8 @@
Fragment instructions = TranslateExpression(node->receiver());
instructions += PushArgument();
instructions += TranslateArguments(node->arguments(), &argument_names);
- fragment_ = instructions + StaticCall(target, argument_count, argument_names);
+ fragment_ = instructions + StaticCall(node->position(), target,
+ argument_count, argument_names);
}
@@ -4516,7 +4542,8 @@
const Function& target = Function::ZoneHandle(
Z, H.LookupConstructorByKernelConstructor(klass, node->target()));
intptr_t argument_count = node->arguments()->count() + 1;
- instructions += StaticCall(target, argument_count, argument_names);
+ instructions +=
+ StaticCall(node->position(), target, argument_count, argument_names);
fragment_ = instructions + Drop();
}
@@ -4559,7 +4586,8 @@
instructions += PushArgument(); // Negate?.
instructions +=
- InstanceCall(dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
+ InstanceCall(TokenPosition::kNoSource,
+ dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 4);
}
@@ -4599,6 +4627,7 @@
instructions += PushArgument(); // Type.
instructions += InstanceCall(
+ TokenPosition::kNoSource,
dart::Library::PrivateCoreLibName(Symbols::_as()), Token::kAS, 3);
}
@@ -4745,7 +4774,7 @@
const Function& factory_method = Function::ZoneHandle(
Z, factory_class.LookupFactory(
dart::Library::PrivateCoreLibName(Symbols::ListLiteralFactory())));
- fragment_ = instructions + StaticCall(factory_method, 2);
+ fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
}
@@ -4796,7 +4825,7 @@
}
instructions += PushArgument(); // The array.
- fragment_ = instructions + StaticCall(factory_method, 2);
+ fragment_ = instructions + StaticCall(node->position(), factory_method, 2);
}
@@ -4817,7 +4846,7 @@
instructions += TranslateExpression(node->expression());
instructions += PushArgument();
- instructions += ThrowException();
+ instructions += ThrowException(node->position());
ASSERT(instructions.is_closed());
fragment_ = instructions;
@@ -5101,7 +5130,8 @@
const dart::String& iterator_getter = dart::String::ZoneHandle(
Z, dart::Field::GetterSymbol(Symbols::Iterator()));
- instructions += InstanceCall(iterator_getter, Token::kGET, 1);
+ instructions +=
+ InstanceCall(TokenPosition::kNoSource, iterator_getter, Token::kGET, 1);
LocalVariable* iterator = scopes_->iterator_variables[for_in_depth_];
instructions += StoreLocal(iterator);
instructions += Drop();
@@ -5110,7 +5140,8 @@
++loop_depth_;
Fragment condition = LoadLocal(iterator);
condition += PushArgument();
- condition += InstanceCall(Symbols::MoveNext(), Token::kILLEGAL, 1);
+ condition += InstanceCall(TokenPosition::kNoSource, Symbols::MoveNext(),
+ Token::kILLEGAL, 1);
TargetEntryInstr* body_entry;
TargetEntryInstr* loop_exit;
condition += BranchIfTrue(&body_entry, &loop_exit);
@@ -5121,7 +5152,8 @@
body += PushArgument();
const dart::String& current_getter = dart::String::ZoneHandle(
Z, dart::Field::GetterSymbol(Symbols::Current()));
- body += InstanceCall(current_getter, Token::kGET, 1);
+ body +=
+ InstanceCall(TokenPosition::kNoSource, current_getter, Token::kGET, 1);
body += StoreLocal(LookupVariable(node->variable()));
body += Drop();
body += TranslateStatement(node->body());
@@ -5242,12 +5274,12 @@
body_fragment += NullConstant();
body_fragment += PushArgument(); // line
- body_fragment += StaticCall(constructor, 3);
+ body_fragment += StaticCall(TokenPosition::kNoSource, constructor, 3);
body_fragment += Drop();
// Throw the exception
body_fragment += PushArgument();
- body_fragment += ThrowException();
+ body_fragment += ThrowException(TokenPosition::kNoSource);
body_fragment += Drop();
}
@@ -5311,10 +5343,10 @@
current_instructions += PushArgument();
current_instructions += LoadLocal(scopes_->switch_variable);
current_instructions += PushArgument();
- current_instructions +=
- InstanceCall(Symbols::EqualOperator(), Token::kEQ,
- /*argument_count=*/2,
- /*num_args_checked=*/2);
+ current_instructions += InstanceCall(
+ TokenPosition::kNoSource, Symbols::EqualOperator(), Token::kEQ,
+ /*argument_count=*/2,
+ /*num_args_checked=*/2);
current_instructions += BranchIfTrue(&then, &otherwise);
Fragment then_fragment(then);
@@ -5434,12 +5466,12 @@
otherwise_fragment += IntConstant(0);
otherwise_fragment += PushArgument(); // column
- otherwise_fragment += StaticCall(constructor, 5);
+ otherwise_fragment += StaticCall(TokenPosition::kNoSource, constructor, 5);
otherwise_fragment += Drop();
// Throw _AssertionError exception.
otherwise_fragment += PushArgument();
- otherwise_fragment += ThrowException();
+ otherwise_fragment += ThrowException(TokenPosition::kNoSource);
otherwise_fragment += Drop();
fragment_ = Fragment(instructions.entry, then);
@@ -5594,6 +5626,7 @@
catch_body += Constant(Object::bool_false());
catch_body += PushArgument(); // negate
catch_body += InstanceCall(
+ TokenPosition::kNoSource,
dart::Library::PrivateCoreLibName(Symbols::_instanceOf()),
Token::kIS, 4);
@@ -5711,6 +5744,7 @@
for (intptr_t i = 0; i < scopes_->function_scopes.length(); ++i) {
if (scopes_->function_scopes[i].function != node) continue;
+ // NOTE: This is not TokenPosition in the general sense!
function = I->LookupClosureFunction(parsed_function_->function(),
TokenPosition(i));
if (function.IsNull()) {
@@ -5722,6 +5756,7 @@
name = &H.DartSymbol(
FunctionDeclaration::Cast(parent)->variable()->name());
}
+ // NOTE: This is not TokenPosition in the general sense!
function = Function::NewClosureFunction(
*name, parsed_function_->function(), TokenPosition(i));
function.set_is_debuggable(false);
diff --git a/runtime/vm/kernel_to_il.h b/runtime/vm/kernel_to_il.h
index 5f2539b..3f9db3e 100644
--- a/runtime/vm/kernel_to_il.h
+++ b/runtime/vm/kernel_to_il.h
@@ -753,17 +753,19 @@
Fragment CreateArray();
Fragment Goto(JoinEntryInstr* destination);
Fragment IntConstant(int64_t value);
- Fragment InstanceCall(const dart::String& name,
+ Fragment InstanceCall(TokenPosition position,
+ const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
intptr_t num_args_checked = 1);
- Fragment InstanceCall(const dart::String& name,
+ Fragment InstanceCall(TokenPosition position,
+ const dart::String& name,
Token::Kind kind,
intptr_t argument_count,
const Array& argument_names,
intptr_t num_args_checked = 1);
Fragment ClosureCall(int argument_count, const Array& argument_names);
- Fragment ThrowException();
+ Fragment ThrowException(TokenPosition position);
Fragment RethrowException(int catch_try_index);
Fragment LoadClassId();
Fragment LoadField(const dart::Field& field);
@@ -780,8 +782,11 @@
Fragment NativeCall(const dart::String* name, const Function* function);
Fragment PushArgument();
Fragment Return();
- Fragment StaticCall(const Function& target, intptr_t argument_count);
- Fragment StaticCall(const Function& target,
+ Fragment StaticCall(TokenPosition position,
+ const Function& target,
+ intptr_t argument_count);
+ Fragment StaticCall(TokenPosition position,
+ const Function& target,
intptr_t argument_count,
const Array& argument_names);
Fragment StoreIndexed(intptr_t class_id);
diff --git a/runtime/vm/method_recognizer.h b/runtime/vm/method_recognizer.h
index 580582f..5ab5eac 100644
--- a/runtime/vm/method_recognizer.h
+++ b/runtime/vm/method_recognizer.h
@@ -166,6 +166,8 @@
0x25a786de) \
V(_GrowableList, add, GrowableArray_add, Dynamic, 0x0d1358ed) \
V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, Dynamic, 0x6036d7fa) \
+ V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, Dynamic, \
+ 0x71c67f7d) \
V(Object, ==, ObjectEquals, Bool, 0x11662ed8) \
V(Object, get:runtimeType, ObjectRuntimeType, Type, 0x00e7c26b) \
V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, Bool, 0x72aad7e2) \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 673ae03..0cfa413 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5696,21 +5696,36 @@
}
+class StickySpecialization : public BitField<intptr_t, bool, 0, 1> {};
+class StringSpecializationCid
+ : public BitField<intptr_t, intptr_t, 1, RawObject::kClassIdTagSize> {};
+
+
intptr_t Function::string_specialization_cid() const {
ASSERT(kind() == RawFunction::kIrregexpFunction);
const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data_));
- return Smi::Value(Smi::RawCast(pair.At(1)));
+ return StringSpecializationCid::decode(Smi::Value(Smi::RawCast(pair.At(1))));
+}
+
+
+bool Function::is_sticky_specialization() const {
+ ASSERT(kind() == RawFunction::kIrregexpFunction);
+ const Array& pair = Array::Cast(Object::Handle(raw_ptr()->data_));
+ return StickySpecialization::decode(Smi::Value(Smi::RawCast(pair.At(1))));
}
void Function::SetRegExpData(const RegExp& regexp,
- intptr_t string_specialization_cid) const {
+ intptr_t string_specialization_cid,
+ bool sticky) const {
ASSERT(kind() == RawFunction::kIrregexpFunction);
ASSERT(RawObject::IsStringClassId(string_specialization_cid));
ASSERT(raw_ptr()->data_ == Object::null());
const Array& pair = Array::Handle(Array::New(2, Heap::kOld));
pair.SetAt(0, regexp);
- pair.SetAt(1, Smi::Handle(Smi::New(string_specialization_cid)));
+ pair.SetAt(1, Smi::Handle(Smi::New(StickySpecialization::encode(sticky) |
+ StringSpecializationCid::encode(
+ string_specialization_cid))));
set_data(pair);
}
@@ -8767,6 +8782,8 @@
return "patch";
case RawScript::kEvaluateTag:
return "evaluate";
+ case RawScript::kKernelTag:
+ return "kernel";
default:
UNIMPLEMENTED();
}
@@ -8789,6 +8806,10 @@
StorePointer(&raw_ptr()->source_, value.raw());
}
+void Script::set_line_starts(const Array& value) const {
+ StorePointer(&raw_ptr()->line_starts_, value.raw());
+}
+
void Script::set_kind(RawScript::Kind value) const {
StoreNonPointer(&raw_ptr()->kind_, value);
@@ -8839,9 +8860,49 @@
intptr_t* token_len) const {
ASSERT(line != NULL);
Zone* zone = Thread::Current()->zone();
+
+ if (kind() == RawScript::kKernelTag) {
+ const Array& line_starts_array = Array::Handle(line_starts());
+ if (line_starts_array.IsNull()) {
+ // Scripts in the AOT snapshot do not have a line starts array.
+ *line = -1;
+ if (column != NULL) {
+ *column = -1;
+ }
+ if (token_len != NULL) {
+ *token_len = 1;
+ }
+ return;
+ }
+ ASSERT(line_starts_array.Length() > 0);
+ intptr_t offset = token_pos.value();
+ int min = 0;
+ int max = line_starts_array.Length() - 1;
+
+ // Binary search to find the line containing this offset.
+ Smi& smi = Smi::Handle();
+ while (min < max) {
+ int midpoint = (max - min + 1) / 2 + min;
+
+ smi ^= line_starts_array.At(midpoint);
+ if (smi.Value() > offset) {
+ max = midpoint - 1;
+ } else {
+ min = midpoint;
+ }
+ }
+ *line = min + 1;
+ smi ^= line_starts_array.At(min);
+ *column = offset - smi.Value() + 1;
+ if (token_len != NULL) {
+ *token_len = 1;
+ }
+ return;
+ }
+
const TokenStream& tkns = TokenStream::Handle(zone, tokens());
if (tkns.IsNull()) {
- ASSERT(Dart::snapshot_kind() == Snapshot::kAppNoJIT);
+ ASSERT((Dart::snapshot_kind() == Snapshot::kAppNoJIT));
*line = -1;
if (column != NULL) {
*column = -1;
@@ -22296,7 +22357,7 @@
intptr_t line = -1;
intptr_t column = -1;
if (!script.IsNull() && token_pos.IsReal()) {
- if (script.HasSource()) {
+ if (script.HasSource() || script.kind() == RawScript::kKernelTag) {
script.GetTokenLocation(token_pos, &line, &column);
} else {
script.GetTokenLocation(token_pos, &line, NULL);
@@ -22394,16 +22455,28 @@
}
-void RegExp::set_function(intptr_t cid, const Function& value) const {
- StorePointer(FunctionAddr(cid), value.raw());
+void RegExp::set_function(intptr_t cid,
+ bool sticky,
+ const Function& value) const {
+ StorePointer(FunctionAddr(cid, sticky), value.raw());
}
-void RegExp::set_bytecode(bool is_one_byte, const TypedData& bytecode) const {
- if (is_one_byte) {
- StorePointer(&raw_ptr()->one_byte_bytecode_, bytecode.raw());
+void RegExp::set_bytecode(bool is_one_byte,
+ bool sticky,
+ const TypedData& bytecode) const {
+ if (sticky) {
+ if (is_one_byte) {
+ StorePointer(&raw_ptr()->one_byte_sticky_.bytecode_, bytecode.raw());
+ } else {
+ StorePointer(&raw_ptr()->two_byte_sticky_.bytecode_, bytecode.raw());
+ }
} else {
- StorePointer(&raw_ptr()->two_byte_bytecode_, bytecode.raw());
+ if (is_one_byte) {
+ StorePointer(&raw_ptr()->one_byte_.bytecode_, bytecode.raw());
+ } else {
+ StorePointer(&raw_ptr()->two_byte_.bytecode_, bytecode.raw());
+ }
}
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 837b833..bf2b009 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2215,8 +2215,10 @@
RawRegExp* regexp() const;
intptr_t string_specialization_cid() const;
+ bool is_sticky_specialization() const;
void SetRegExpData(const RegExp& regexp,
- intptr_t string_specialization_cid) const;
+ intptr_t string_specialization_cid,
+ bool sticky) const;
RawString* native_name() const;
void set_native_name(const String& name) const;
@@ -3501,6 +3503,10 @@
RawTokenStream* tokens() const { return raw_ptr()->tokens_; }
+ RawArray* line_starts() const { return raw_ptr()->line_starts_; }
+
+ void set_line_starts(const Array& value) const;
+
void Tokenize(const String& private_key, bool use_shared_tokens = true) const;
RawLibrary* FindLibrary() const;
@@ -8451,37 +8457,59 @@
return raw_ptr()->num_bracket_expressions_;
}
- RawTypedData* bytecode(bool is_one_byte) const {
- return is_one_byte ? raw_ptr()->one_byte_bytecode_
- : raw_ptr()->two_byte_bytecode_;
+ RawTypedData* bytecode(bool is_one_byte, bool sticky) const {
+ if (sticky) {
+ return is_one_byte ? raw_ptr()->one_byte_sticky_.bytecode_
+ : raw_ptr()->two_byte_sticky_.bytecode_;
+ } else {
+ return is_one_byte ? raw_ptr()->one_byte_.bytecode_
+ : raw_ptr()->two_byte_.bytecode_;
+ }
}
- static intptr_t function_offset(intptr_t cid) {
- switch (cid) {
- case kOneByteStringCid:
- return OFFSET_OF(RawRegExp, one_byte_function_);
- case kTwoByteStringCid:
- return OFFSET_OF(RawRegExp, two_byte_function_);
- case kExternalOneByteStringCid:
- return OFFSET_OF(RawRegExp, external_one_byte_function_);
- case kExternalTwoByteStringCid:
- return OFFSET_OF(RawRegExp, external_two_byte_function_);
+ static intptr_t function_offset(intptr_t cid, bool sticky) {
+ if (sticky) {
+ switch (cid) {
+ case kOneByteStringCid:
+ return OFFSET_OF(RawRegExp, one_byte_sticky_.function_);
+ case kTwoByteStringCid:
+ return OFFSET_OF(RawRegExp, two_byte_sticky_.function_);
+ case kExternalOneByteStringCid:
+ return OFFSET_OF(RawRegExp, external_one_byte_sticky_function_);
+ case kExternalTwoByteStringCid:
+ return OFFSET_OF(RawRegExp, external_two_byte_sticky_function_);
+ }
+ } else {
+ switch (cid) {
+ case kOneByteStringCid:
+ return OFFSET_OF(RawRegExp, one_byte_.function_);
+ case kTwoByteStringCid:
+ return OFFSET_OF(RawRegExp, two_byte_.function_);
+ case kExternalOneByteStringCid:
+ return OFFSET_OF(RawRegExp, external_one_byte_function_);
+ case kExternalTwoByteStringCid:
+ return OFFSET_OF(RawRegExp, external_two_byte_function_);
+ }
}
UNREACHABLE();
return -1;
}
- RawFunction** FunctionAddr(intptr_t cid) const {
+ RawFunction** FunctionAddr(intptr_t cid, bool sticky) const {
return reinterpret_cast<RawFunction**>(
- FieldAddrAtOffset(function_offset(cid)));
+ FieldAddrAtOffset(function_offset(cid, sticky)));
}
- RawFunction* function(intptr_t cid) const { return *FunctionAddr(cid); }
+ RawFunction* function(intptr_t cid, bool sticky) const {
+ return *FunctionAddr(cid, sticky);
+ }
void set_pattern(const String& pattern) const;
- void set_function(intptr_t cid, const Function& value) const;
- void set_bytecode(bool is_one_byte, const TypedData& bytecode) const;
+ void set_function(intptr_t cid, bool sticky, const Function& value) const;
+ void set_bytecode(bool is_one_byte,
+ bool sticky,
+ const TypedData& bytecode) const;
void set_num_bracket_expressions(intptr_t value) const;
void set_is_global() const { set_flags(flags() | kGlobal); }
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index b41ff6c..a5998b9 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -543,7 +543,7 @@
};
-// This is executed before interating over the instances.
+// This is executed before iterating over the instances.
void Class::CheckReload(const Class& replacement,
IsolateReloadContext* context) const {
ASSERT(IsolateReloadContext::IsSameClass(*this, replacement));
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index d5441a5..6d2bd9e 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1512,21 +1512,35 @@
jsobj.AddProperty("isCaseSensitive", !is_ignore_case());
jsobj.AddProperty("isMultiLine", is_multi_line());
- Function& func = Function::Handle();
- func = function(kOneByteStringCid);
- jsobj.AddProperty("_oneByteFunction", func);
- func = function(kTwoByteStringCid);
- jsobj.AddProperty("_twoByteFunction", func);
- func = function(kExternalOneByteStringCid);
- jsobj.AddProperty("_externalOneByteFunction", func);
- func = function(kExternalTwoByteStringCid);
- jsobj.AddProperty("_externalTwoByteFunction", func);
-
- TypedData& bc = TypedData::Handle();
- bc = bytecode(true);
- jsobj.AddProperty("_oneByteBytecode", bc);
- bc = bytecode(false);
- jsobj.AddProperty("_twoByteBytecode", bc);
+ if (!FLAG_interpret_irregexp) {
+ Function& func = Function::Handle();
+ func = function(kOneByteStringCid, /*sticky=*/false);
+ jsobj.AddProperty("_oneByteFunction", func);
+ func = function(kTwoByteStringCid, /*sticky=*/false);
+ jsobj.AddProperty("_twoByteFunction", func);
+ func = function(kExternalOneByteStringCid, /*sticky=*/false);
+ jsobj.AddProperty("_externalOneByteFunction", func);
+ func = function(kExternalTwoByteStringCid, /*sticky=*/false);
+ jsobj.AddProperty("_externalTwoByteFunction", func);
+ func = function(kOneByteStringCid, /*sticky=*/true);
+ jsobj.AddProperty("_oneByteFunctionSticky", func);
+ func = function(kTwoByteStringCid, /*sticky=*/true);
+ jsobj.AddProperty("_twoByteFunctionSticky", func);
+ func = function(kExternalOneByteStringCid, /*sticky=*/true);
+ jsobj.AddProperty("_externalOneByteFunctionSticky", func);
+ func = function(kExternalTwoByteStringCid, /*sticky=*/true);
+ jsobj.AddProperty("_externalTwoByteFunctionSticky", func);
+ } else {
+ TypedData& bc = TypedData::Handle();
+ bc = bytecode(/*is_one_byte=*/true, /*sticky=*/false);
+ jsobj.AddProperty("_oneByteBytecode", bc);
+ bc = bytecode(/*is_one_byte=*/false, /*sticky=*/false);
+ jsobj.AddProperty("_twoByteBytecode", bc);
+ bc = bytecode(/*is_one_byte=*/true, /*sticky=*/true);
+ jsobj.AddProperty("_oneByteBytecodeSticky", bc);
+ bc = bytecode(/*is_one_byte=*/false, /*sticky=*/true);
+ jsobj.AddProperty("_twoByteBytecodeSticky", bc);
+ }
}
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 50900b4..9097b1d 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -970,6 +970,7 @@
kSourceTag,
kPatchTag,
kEvaluateTag,
+ kKernelTag,
};
private:
@@ -979,6 +980,7 @@
RawString* url_;
RawString* resolved_url_;
RawArray* compile_time_constants_;
+ RawArray* line_starts_;
RawTokenStream* tokens_;
RawString* source_;
RawObject** to() { return reinterpret_cast<RawObject**>(&ptr()->source_); }
@@ -2116,14 +2118,29 @@
}
RawSmi* num_bracket_expressions_;
RawString* pattern_; // Pattern to be used for matching.
- RawFunction* one_byte_function_;
- RawFunction* two_byte_function_;
+ union {
+ RawFunction* function_;
+ RawTypedData* bytecode_;
+ } one_byte_;
+ union {
+ RawFunction* function_;
+ RawTypedData* bytecode_;
+ } two_byte_;
RawFunction* external_one_byte_function_;
RawFunction* external_two_byte_function_;
- RawTypedData* one_byte_bytecode_;
- RawTypedData* two_byte_bytecode_;
+ union {
+ RawFunction* function_;
+ RawTypedData* bytecode_;
+ } one_byte_sticky_;
+ union {
+ RawFunction* function_;
+ RawTypedData* bytecode_;
+ } two_byte_sticky_;
+ RawFunction* external_one_byte_sticky_function_;
+ RawFunction* external_two_byte_sticky_function_;
RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->two_byte_bytecode_);
+ return reinterpret_cast<RawObject**>(
+ &ptr()->external_two_byte_sticky_function_);
}
intptr_t num_registers_;
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index aebda45..2177722 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -2894,16 +2894,12 @@
reader->Read<int32_t>());
regex.StoreNonPointer(®ex.raw_ptr()->type_flags_, reader->Read<int8_t>());
- // TODO(18854): Need to implement a way of recreating the irrexp functions.
const Function& no_function = Function::Handle(reader->zone());
- regex.set_function(kOneByteStringCid, no_function);
- regex.set_function(kTwoByteStringCid, no_function);
- regex.set_function(kExternalOneByteStringCid, no_function);
- regex.set_function(kExternalTwoByteStringCid, no_function);
-
- const TypedData& no_bytecode = TypedData::Handle(reader->zone());
- regex.set_bytecode(true, no_bytecode);
- regex.set_bytecode(false, no_bytecode);
+ for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
+ cid++) {
+ regex.set_function(cid, /*sticky=*/false, no_function);
+ regex.set_function(cid, /*sticky=*/true, no_function);
+ }
return regex.raw();
}
diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
index 19b88c5..3516bc8 100644
--- a/runtime/vm/regexp.cc
+++ b/runtime/vm/regexp.cc
@@ -4824,6 +4824,7 @@
const Function& function = parsed_function->function();
const intptr_t specialization_cid = function.string_specialization_cid();
+ const intptr_t is_sticky = function.is_sticky_specialization();
const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
specialization_cid == kExternalOneByteStringCid);
RegExp& regexp = RegExp::Handle(zone, function.regexp());
@@ -4851,12 +4852,12 @@
RegExpCapture::ToNode(data->tree, 0, &compiler, compiler.accept());
RegExpNode* node = captured_body;
- bool is_end_anchored = data->tree->IsAnchoredAtEnd();
- bool is_start_anchored = data->tree->IsAnchoredAtStart();
+ const bool is_end_anchored = data->tree->IsAnchoredAtEnd();
+ const bool is_start_anchored = data->tree->IsAnchoredAtStart();
intptr_t max_length = data->tree->max_match();
- if (!is_start_anchored) {
+ if (!is_start_anchored && !is_sticky) {
// Add a .*? at the beginning, outside the body capture, unless
- // this expression is anchored at the beginning.
+ // this expression is anchored at the beginning or is sticky.
RegExpNode* loop_node = RegExpQuantifier::ToNode(
0, RegExpTree::kInfinity, false, new (zone) RegExpCharacterClass('*'),
&compiler, captured_body, data->contains_anchor);
@@ -4900,7 +4901,7 @@
// Inserted here, instead of in Assembler, because it depends on information
// in the AST that isn't replicated in the Node structure.
static const intptr_t kMaxBacksearchLimit = 1024;
- if (is_end_anchored && !is_start_anchored &&
+ if (is_end_anchored && !is_start_anchored && !is_sticky &&
max_length < kMaxBacksearchLimit) {
macro_assembler->SetCurrentPositionFromEnd(max_length);
}
@@ -4927,6 +4928,7 @@
RegExpCompileData* data,
const RegExp& regexp,
bool is_one_byte,
+ bool is_sticky,
Zone* zone) {
ASSERT(FLAG_interpret_irregexp);
const String& pattern = String::Handle(zone, regexp.pattern());
@@ -4956,7 +4958,7 @@
bool is_end_anchored = data->tree->IsAnchoredAtEnd();
bool is_start_anchored = data->tree->IsAnchoredAtStart();
intptr_t max_length = data->tree->max_match();
- if (!is_start_anchored) {
+ if (!is_start_anchored && !is_sticky) {
// Add a .*? at the beginning, outside the body capture, unless
// this expression is anchored at the beginning.
RegExpNode* loop_node = RegExpQuantifier::ToNode(
@@ -5002,7 +5004,7 @@
// Inserted here, instead of in Assembler, because it depends on information
// in the AST that isn't replicated in the Node structure.
static const intptr_t kMaxBacksearchLimit = 1024;
- if (is_end_anchored && !is_start_anchored &&
+ if (is_end_anchored && !is_start_anchored && !is_sticky &&
max_length < kMaxBacksearchLimit) {
macro_assembler->SetCurrentPositionFromEnd(max_length);
}
@@ -5029,6 +5031,7 @@
Zone* zone,
const RegExp& regexp,
intptr_t specialization_cid,
+ bool sticky,
const Object& owner) {
const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
@@ -5063,9 +5066,9 @@
fn.set_result_type(Type::Handle(zone, Type::ArrayType()));
// Cache the result.
- regexp.set_function(specialization_cid, fn);
+ regexp.set_function(specialization_cid, sticky, fn);
- fn.SetRegExpData(regexp, specialization_cid);
+ fn.SetRegExpData(regexp, specialization_cid, sticky);
fn.set_is_debuggable(false);
// The function is compiled lazily during the first call.
@@ -5098,12 +5101,13 @@
const Class& owner =
Class::Handle(zone, lib.LookupClass(Symbols::RegExp()));
- CreateSpecializedFunction(thread, zone, regexp, kOneByteStringCid, owner);
- CreateSpecializedFunction(thread, zone, regexp, kTwoByteStringCid, owner);
- CreateSpecializedFunction(thread, zone, regexp, kExternalOneByteStringCid,
- owner);
- CreateSpecializedFunction(thread, zone, regexp, kExternalTwoByteStringCid,
- owner);
+ for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
+ cid++) {
+ CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/false,
+ owner);
+ CreateSpecializedFunction(thread, zone, regexp, cid, /*sticky=*/true,
+ owner);
+ }
}
return regexp.raw();
diff --git a/runtime/vm/regexp.h b/runtime/vm/regexp.h
index e026073..dbb89a4 100644
--- a/runtime/vm/regexp.h
+++ b/runtime/vm/regexp.h
@@ -1398,6 +1398,7 @@
static CompilationResult CompileBytecode(RegExpCompileData* data,
const RegExp& regexp,
bool is_one_byte,
+ bool sticky,
Zone* zone);
static RawRegExp* CreateRegExp(Thread* thread,
diff --git a/runtime/vm/regexp_assembler_bytecode.cc b/runtime/vm/regexp_assembler_bytecode.cc
index a67c37b..4f31fcf 100644
--- a/runtime/vm/regexp_assembler_bytecode.cc
+++ b/runtime/vm/regexp_assembler_bytecode.cc
@@ -457,11 +457,12 @@
static intptr_t Prepare(const RegExp& regexp,
const String& subject,
+ bool sticky,
Zone* zone) {
bool is_one_byte =
subject.IsOneByteString() || subject.IsExternalOneByteString();
- if (regexp.bytecode(is_one_byte) == TypedData::null()) {
+ if (regexp.bytecode(is_one_byte, sticky) == TypedData::null()) {
const String& pattern = String::Handle(zone, regexp.pattern());
#if !defined(PRODUCT)
TimelineDurationScope tds(Thread::Current(), Timeline::GetCompilerStream(),
@@ -486,13 +487,13 @@
regexp.set_is_complex();
}
- RegExpEngine::CompilationResult result =
- RegExpEngine::CompileBytecode(compile_data, regexp, is_one_byte, zone);
+ RegExpEngine::CompilationResult result = RegExpEngine::CompileBytecode(
+ compile_data, regexp, is_one_byte, sticky, zone);
ASSERT(result.bytecode != NULL);
ASSERT((regexp.num_registers() == -1) ||
(regexp.num_registers() == result.num_registers));
regexp.set_num_registers(result.num_registers);
- regexp.set_bytecode(is_one_byte, *(result.bytecode));
+ regexp.set_bytecode(is_one_byte, sticky, *(result.bytecode));
}
ASSERT(regexp.num_registers() != -1);
@@ -505,6 +506,7 @@
static IrregexpInterpreter::IrregexpResult ExecRaw(const RegExp& regexp,
const String& subject,
intptr_t index,
+ bool sticky,
int32_t* output,
intptr_t output_size,
Zone* zone) {
@@ -527,7 +529,7 @@
}
const TypedData& bytecode =
- TypedData::Handle(zone, regexp.bytecode(is_one_byte));
+ TypedData::Handle(zone, regexp.bytecode(is_one_byte, sticky));
ASSERT(!bytecode.IsNull());
IrregexpInterpreter::IrregexpResult result =
IrregexpInterpreter::Match(bytecode, subject, raw_output, index, zone);
@@ -551,8 +553,9 @@
RawInstance* BytecodeRegExpMacroAssembler::Interpret(const RegExp& regexp,
const String& subject,
const Smi& start_index,
+ bool sticky,
Zone* zone) {
- intptr_t required_registers = Prepare(regexp, subject, zone);
+ intptr_t required_registers = Prepare(regexp, subject, sticky, zone);
if (required_registers < 0) {
// Compiling failed with an exception.
UNREACHABLE();
@@ -562,7 +565,7 @@
int32_t* output_registers = zone->Alloc<int32_t>(required_registers);
IrregexpInterpreter::IrregexpResult result =
- ExecRaw(regexp, subject, start_index.Value(), output_registers,
+ ExecRaw(regexp, subject, start_index.Value(), sticky, output_registers,
required_registers, zone);
if (result == IrregexpInterpreter::RE_SUCCESS) {
diff --git a/runtime/vm/regexp_assembler_bytecode.h b/runtime/vm/regexp_assembler_bytecode.h
index e8d6174..df9e46f 100644
--- a/runtime/vm/regexp_assembler_bytecode.h
+++ b/runtime/vm/regexp_assembler_bytecode.h
@@ -107,6 +107,7 @@
static RawInstance* Interpret(const RegExp& regexp,
const String& str,
const Smi& start_index,
+ bool is_sticky,
Zone* zone);
private:
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index efb9d64..bfe90b2 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -317,9 +317,10 @@
RawArray* IRRegExpMacroAssembler::Execute(const RegExp& regexp,
const String& input,
const Smi& start_offset,
+ bool sticky,
Zone* zone) {
const intptr_t cid = input.GetClassId();
- const Function& fun = Function::Handle(regexp.function(cid));
+ const Function& fun = Function::Handle(regexp.function(cid, sticky));
ASSERT(!fun.IsNull());
// Create the argument list.
const Array& args =
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index a08e05f..ae70952 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -40,6 +40,7 @@
static RawArray* Execute(const RegExp& regexp,
const String& input,
const Smi& start_offset,
+ bool sticky,
Zone* zone);
virtual bool IsClosed() const { return (current_instruction_ == NULL); }
diff --git a/runtime/vm/regexp_test.cc b/runtime/vm/regexp_test.cc
index b7f5a77..7eb55ad 100644
--- a/runtime/vm/regexp_test.cc
+++ b/runtime/vm/regexp_test.cc
@@ -18,7 +18,8 @@
const RegExp& regexp =
RegExp::Handle(RegExpEngine::CreateRegExp(thread, pat, false, false));
const Smi& idx = Smi::Handle(Smi::New(0));
- return IRRegExpMacroAssembler::Execute(regexp, str, idx, zone);
+ return IRRegExpMacroAssembler::Execute(regexp, str, idx, /*sticky=*/false,
+ zone);
}
TEST_CASE(RegExp_OneByteString) {
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 022199e..5e34b4a 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -552,6 +552,15 @@
};
+class StringParameter : public MethodParameter {
+ public:
+ StringParameter(const char* name, bool required)
+ : MethodParameter(name, required) {}
+
+ virtual bool Validate(const char* value) const { return (value != NULL); }
+};
+
+
class RunnableIsolateParameter : public MethodParameter {
public:
explicit RunnableIsolateParameter(const char* name)
@@ -2442,8 +2451,12 @@
static const MethodParameter* reload_sources_params[] = {
- RUNNABLE_ISOLATE_PARAMETER, new BoolParameter("force", false),
- new BoolParameter("pause", false), NULL,
+ RUNNABLE_ISOLATE_PARAMETER,
+ new BoolParameter("force", false),
+ new BoolParameter("pause", false),
+ new StringParameter("rootLibUri", false),
+ new StringParameter("packagesUri", false),
+ NULL,
};
@@ -2479,7 +2492,8 @@
const bool force_reload =
BoolParameter::Parse(js->LookupParam("force"), false);
- isolate->ReloadSources(js, force_reload);
+ isolate->ReloadSources(js, force_reload, js->LookupParam("rootLibUri"),
+ js->LookupParam("packagesUri"));
Service::CheckForPause(isolate, js);
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 0ac2ae9..ae9eaf8 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -2669,7 +2669,7 @@
}
{
- BYTECODE(LoadFieldTOS, A_D);
+ BYTECODE(LoadFieldTOS, __D);
const uint16_t offset_in_words = rD;
RawInstance* instance = static_cast<RawInstance*>(SP[0]);
SP[0] = reinterpret_cast<RawObject**>(instance->ptr())[offset_in_words];
@@ -2677,7 +2677,7 @@
}
{
- BYTECODE(InitStaticTOS, A);
+ BYTECODE(InitStaticTOS, 0);
RawField* field = static_cast<RawField*>(*SP--);
RawObject* value = field->ptr()->value_.static_value_;
if ((value == Object::sentinel().raw()) ||
diff --git a/runtime/vm/source_report.cc b/runtime/vm/source_report.cc
index 390c0f5..e156203 100644
--- a/runtime/vm/source_report.cc
+++ b/runtime/vm/source_report.cc
@@ -1,7 +1,7 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-
+#ifndef PRODUCT
#include "vm/source_report.h"
#include "vm/compiler.h"
@@ -533,3 +533,4 @@
}
} // namespace dart
+#endif // PRODUCT
diff --git a/runtime/vm/unit_test.cc b/runtime/vm/unit_test.cc
index 1c138e7..c036981 100644
--- a/runtime/vm/unit_test.cc
+++ b/runtime/vm/unit_test.cc
@@ -288,8 +288,9 @@
TransitionNativeToVM transition(Thread::Current());
success = isolate->ReloadSources(&js,
false, // force_reload
+ NULL, NULL,
true); // dont_delete_reload_context
- fprintf(stderr, "RELOAD REPORT:\n%s\n", js.ToCString());
+ OS::PrintErr("RELOAD REPORT:\n%s\n", js.ToCString());
}
if (success) {
diff --git a/runtime/vm/verifier.cc b/runtime/vm/verifier.cc
index 5bc4765..fc11867 100644
--- a/runtime/vm/verifier.cc
+++ b/runtime/vm/verifier.cc
@@ -92,7 +92,12 @@
if (obj->GetClassId() >= kInstanceCid) {
if (obj->IsCanonical()) {
instanceHandle_ ^= obj;
- ASSERT(instanceHandle_.CheckIsCanonical(thread_));
+ const bool is_canonical = instanceHandle_.CheckIsCanonical(thread_);
+ if (!is_canonical) {
+ OS::PrintErr("Instance `%s` is not canonical!\n",
+ instanceHandle_.ToCString());
+ }
+ ASSERT(is_canonical);
}
}
}
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart
index aeee9ef..86763cb 100644
--- a/sdk/lib/convert/utf.dart
+++ b/sdk/lib/convert/utf.dart
@@ -37,7 +37,7 @@
* The optional [allowMalformed] argument defines how [decoder] (and [decode])
* deal with invalid or unterminated character sequences.
*
- * If it is `true` (and not overriden at the method invocation) [decode] and
+ * If it is `true` (and not overridden at the method invocation) [decode] and
* the [decoder] replace invalid (or unterminated) octet
* sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
* they throw a [FormatException].
diff --git a/sdk/lib/html/dartium/nativewrappers.dart b/sdk/lib/html/dartium/nativewrappers.dart
index 441749c..0d4e111 100644
--- a/sdk/lib/html/dartium/nativewrappers.dart
+++ b/sdk/lib/html/dartium/nativewrappers.dart
@@ -4,31 +4,10 @@
library nativewrappers;
-class NativeFieldWrapperClass1 {
- NativeFieldWrapperClass1() {
- throw new UnsupportedError(
- "Generative constructors not supported on native types.");
- }
-}
+class NativeFieldWrapperClass1 { }
-class NativeFieldWrapperClass2 {
- NativeFieldWrapperClass2() {
- throw new UnsupportedError(
- "Generative constructors not supported on native types.");
- }
-}
+class NativeFieldWrapperClass2 { }
-class NativeFieldWrapperClass3 {
- NativeFieldWrapperClass3() {
- throw new UnsupportedError(
- "Generative constructors not supported on native types.");
- }
-}
+class NativeFieldWrapperClass3 { }
-class NativeFieldWrapperClass4 {
- NativeFieldWrapperClass4() {
- throw new UnsupportedError(
- "Generative constructors not supported on native types.");
- }
-}
-
+class NativeFieldWrapperClass4 { }
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart
index 61bf1da..b08f7ac 100644
--- a/sdk/lib/js/dart2js/js_dart2js.dart
+++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -465,7 +465,7 @@
super['length'] = length;
}
- // Methods overriden for better performance
+ // Methods overridden for better performance
void add(E value) {
callMethod('push', [value]);
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart
index fbda496..b14e032 100644
--- a/sdk/lib/js/dartium/js_dartium.dart
+++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -1557,7 +1557,7 @@
super['length'] = length;
}
- // Methods overriden for better performance
+ // Methods overridden for better performance
void add(E value) {
callMethod('push', [value]);
diff --git a/tests/co19/co19-kernel.status b/tests/co19/co19-kernel.status
index 8b0d135..49a7ba9 100644
--- a/tests/co19/co19-kernel.status
+++ b/tests/co19/co19-kernel.status
@@ -328,6 +328,13 @@
Language/Libraries_and_Scripts/Imports/static_type_t01/07: Pass
Language/Libraries_and_Scripts/Imports/static_type_t01/02: Pass
+# dartk: JIT failures (debug)
+[ $compiler == dartk && $runtime == vm && $mode == debug ]
+Language/Expressions/Shift/syntax_t15: Crash # Invalid class id during isolate shutdown Heap::VerifyGC
+Language/Expressions/Spawning_an_Isolate/new_isolate_t01: Crash # Class finalization issue
+Language/Libraries_and_Scripts/Scripts/top_level_main_t05: Crash # !main_obj.IsNull()
+LibTest/typed_data/ByteBuffer/runtimeType_A01_t02: Pass, Crash # Out of memory
+LibTest/collection/DoubleLinkedQueue/every_A01_t02: Pass, Crash # Out of memory
# dartk: precompilation failures
[ $compiler == dartkp && $runtime == dart_precompiled ]
@@ -631,4 +638,4 @@
LibTest/core/Invocation/isSetter_A01_t02: Crash
LibTest/core/Invocation/memberName_A01_t01: RuntimeError
LibTest/core/Invocation/namedArguments_A01_t01: Crash
-LibTest/core/Invocation/positionalArguments_A01_t01: Crash
\ No newline at end of file
+LibTest/core/Invocation/positionalArguments_A01_t01: Crash
diff --git a/tests/compiler/dart2js/dart2js.status b/tests/compiler/dart2js/dart2js.status
index 9b3a477..22d2c68 100644
--- a/tests/compiler/dart2js/dart2js.status
+++ b/tests/compiler/dart2js/dart2js.status
@@ -68,6 +68,7 @@
uri_retention_test: Pass, Slow
value_range_test: Pass, Slow
jsinterop/world_test: Pass, Slow
+sourcemaps/stacktrace_test: Pass, Slow
[ $mode == debug ]
check_elements_invariants_test: Skip # Slow and only needs to be run in one
diff --git a/tests/compiler/dart2js/kernel/closed_world_test.dart b/tests/compiler/dart2js/kernel/closed_world_test.dart
index d277221..aa21341 100644
--- a/tests/compiler/dart2js/kernel/closed_world_test.dart
+++ b/tests/compiler/dart2js/kernel/closed_world_test.dart
@@ -9,24 +9,18 @@
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common.dart';
-import 'package:compiler/src/common/names.dart';
import 'package:compiler/src/common/resolution.dart';
import 'package:compiler/src/compiler.dart';
-import 'package:compiler/src/constants/expressions.dart';
import 'package:compiler/src/dart_types.dart';
import 'package:compiler/src/elements/elements.dart';
import 'package:compiler/src/enqueue.dart';
import 'package:compiler/src/js_backend/backend.dart';
import 'package:compiler/src/js_backend/type_variable_handler.dart';
-import 'package:compiler/src/resolution/registry.dart';
-import 'package:compiler/src/resolution/tree_elements.dart';
import 'package:compiler/src/ssa/kernel_impact.dart';
import 'package:compiler/src/serialization/equivalence.dart';
-import 'package:compiler/src/universe/call_structure.dart';
-import 'package:compiler/src/universe/feature.dart';
+import 'package:compiler/src/universe/world_builder.dart';
import 'package:compiler/src/universe/world_impact.dart';
import 'package:compiler/src/world.dart';
-import 'package:expect/expect.dart';
import 'impact_test.dart';
import '../memory_compiler.dart';
import '../serialization/helper.dart';
@@ -34,8 +28,27 @@
const SOURCE = const {
'main.dart': '''
-main() {
- print('Hello World!');
+abstract class A {
+ // redirecting factory in abstract class to other class
+ factory A.a() = D.a;
+ // redirecting factory in abstract class to factory in abstract class
+ factory A.b() = B.a;
+}
+abstract class B implements A {
+ factory B.a() => null;
+}
+class C implements B {
+ // redirecting factory in concrete to other class
+ factory C.a() = D.a;
+}
+class D implements C {
+ D.a();
+}
+main(args) {
+ new A.a();
+ new A.b();
+ new C.a();
+ print(new List<String>()..add('Hello World!'));
}
'''
};
@@ -62,6 +75,9 @@
Flags.useKernel,
Flags.enableAssertMessage
]);
+ ResolutionWorldBuilderImpl worldBuilder =
+ compiler.enqueuer.resolution.universe;
+ worldBuilder.useInstantiationMap = true;
compiler.resolution.retainCachesForTesting = true;
await compiler.run(entryPoint);
compiler.openWorld.closeWorld(compiler.reporter);
@@ -78,14 +94,20 @@
compiler.globalDependencies,
backend,
compiler.commonElements,
- compiler.cacheStrategy);
+ compiler.cacheStrategy,
+ 'enqueuer from kernel');
// TODO(johnniwinther): Store backend info separately. This replacement is
// made to reset a field in [TypeVariableHandler] that prevents it from
// enqueuing twice.
backend.typeVariableHandler = new TypeVariableHandler(compiler);
backend.enqueueHelpers(enqueuer);
- enqueuer.addToWorkList(compiler.mainFunction);
+ enqueuer.applyImpact(
+ compiler.impactStrategy,
+ enqueuer.nativeEnqueuer
+ .processNativeClasses(compiler.libraryLoader.libraries));
+ enqueuer.applyImpact(compiler.impactStrategy,
+ backend.computeMainImpact(enqueuer, compiler.mainFunction));
enqueuer.forEach((work) {
AstElement element = work.element;
ResolutionImpact resolutionImpact = build(compiler, element.resolvedAst);
@@ -106,6 +128,15 @@
// Redirecting factory constructors are skipped in kernel.
return false;
}
+ if (element is ClassElement) {
+ for (ConstructorElement constructor in element.constructors) {
+ if (!constructor.isRedirectingFactory) {
+ return true;
+ }
+ }
+ // The class cannot itself be instantiated.
+ return false;
+ }
return true;
}, verbose: arguments.verbose);
checkClosedWorlds(compiler.closedWorld, closedWorld,
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 8d1ec64..f88787b 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -241,7 +241,8 @@
compiler.resolveStatement("Foo foo;");
ClassElement fooElement = compiler.mainApp.find("Foo");
FunctionElement funElement = fooElement.lookupLocalMember("foo");
- compiler.processQueue(compiler.enqueuer.resolution, funElement);
+ compiler.enqueuer.resolution.addToWorkList(funElement);
+ compiler.processQueue(compiler.enqueuer.resolution, null);
DiagnosticCollector collector = compiler.diagnosticCollector;
Expect.equals(0, collector.warnings.length);
Expect.equals(1, collector.errors.length);
diff --git a/tests/compiler/dart2js/serialization/model_test_helper.dart b/tests/compiler/dart2js/serialization/model_test_helper.dart
index 152bd39..e3e6614 100644
--- a/tests/compiler/dart2js/serialization/model_test_helper.dart
+++ b/tests/compiler/dart2js/serialization/model_test_helper.dart
@@ -22,6 +22,8 @@
import 'package:compiler/src/serialization/equivalence.dart';
import 'package:compiler/src/tree/nodes.dart';
import 'package:compiler/src/universe/class_set.dart';
+import 'package:compiler/src/universe/world_builder.dart';
+import 'package:compiler/src/util/enumset.dart';
import 'package:compiler/src/world.dart' show ClosedWorld;
import '../memory_compiler.dart';
import 'helper.dart';
@@ -108,15 +110,19 @@
{bool typeEquivalence(DartType a, DartType b): areTypesEquivalent,
bool elementFilter(Element element),
bool verbose: false}) {
- Iterable<Element> processedElements1 = enqueuer1.processedElements;
- Iterable<Element> processedElements2 = enqueuer2.processedElements;
- if (elementFilter != null) {
- processedElements1 = processedElements1.where(elementFilter);
- processedElements2 = processedElements2.where(elementFilter);
- }
-
- checkSets(processedElements1, processedElements2,
+ checkSets(enqueuer1.processedElements, enqueuer2.processedElements,
"Processed element mismatch", areElementsEquivalent,
+ elementFilter: elementFilter, verbose: verbose);
+
+ ResolutionWorldBuilderImpl worldBuilder1 = enqueuer1.universe;
+ ResolutionWorldBuilderImpl worldBuilder2 = enqueuer2.universe;
+
+ checkMaps(
+ worldBuilder1.getInstantiationMap(),
+ worldBuilder2.getInstantiationMap(),
+ "Instantiated classes mismatch",
+ areElementsEquivalent,
+ (a, b) => areInstantiationInfosEquivalent(a, b, typeEquivalence),
verbose: verbose);
checkSets(
@@ -419,3 +425,23 @@
outputUnit2.imports,
(a, b) => areElementsEquivalent(a.declaration, b.declaration));
}
+
+bool areInstantiationInfosEquivalent(InstantiationInfo info1,
+ InstantiationInfo info2, bool typeEquivalence(DartType a, DartType b)) {
+ checkMaps(
+ info1.instantiationMap,
+ info2.instantiationMap,
+ 'instantiationMap of\n '
+ '${info1.instantiationMap}\nvs ${info2.instantiationMap}',
+ areElementsEquivalent,
+ (a, b) => areSetsEquivalent(
+ a, b, (a, b) => areInstancesEquivalent(a, b, typeEquivalence)));
+ return true;
+}
+
+bool areInstancesEquivalent(Instance instance1, Instance instance2,
+ bool typeEquivalence(DartType a, DartType b)) {
+ return typeEquivalence(instance1.type, instance2.type) &&
+ instance1.kind == instance2.kind &&
+ instance1.isRedirection == instance2.isRedirection;
+}
diff --git a/tests/compiler/dart2js/serialization/test_helper.dart b/tests/compiler/dart2js/serialization/test_helper.dart
index f081bbd..1808b7f 100644
--- a/tests/compiler/dart2js/serialization/test_helper.dart
+++ b/tests/compiler/dart2js/serialization/test_helper.dart
@@ -208,18 +208,20 @@
// set.difference would work)
Set remaining = set2.toSet();
for (var element1 in set1) {
+ bool found = false;
var correspondingElement;
for (var element2 in remaining) {
if (sameElement(element1, element2)) {
if (checkElements != null) {
checkElements(element1, element2);
}
+ found = true;
correspondingElement = element2;
remaining.remove(element2);
break;
}
}
- if (correspondingElement != null) {
+ if (found) {
common.add([element1, correspondingElement]);
} else {
unfound.add(element1);
@@ -474,7 +476,17 @@
void onSameElement(a, b),
void onUnfoundElement(a),
void onExtraElement(b),
+ bool elementFilter(element),
+ elementConverter(element),
String elementToString(key): defaultToString}) {
+ if (elementFilter != null) {
+ set1 = set1.where(elementFilter);
+ set2 = set2.where(elementFilter);
+ }
+ if (elementConverter != null) {
+ set1 = set1.map(elementConverter);
+ set2 = set2.map(elementConverter);
+ }
List<List> common = <List>[];
List unfound = [];
Set remaining = computeSetDifference(set1, set2, common, unfound,
diff --git a/tests/compiler/dart2js/sourcemaps/diff.dart b/tests/compiler/dart2js/sourcemaps/diff.dart
index 7505892..9627b3c 100644
--- a/tests/compiler/dart2js/sourcemaps/diff.dart
+++ b/tests/compiler/dart2js/sourcemaps/diff.dart
@@ -11,11 +11,7 @@
import 'sourcemap_helper.dart';
import 'sourcemap_html_helper.dart';
-enum DiffKind {
- UNMATCHED,
- MATCHING,
- IDENTICAL,
-}
+enum DiffKind { UNMATCHED, MATCHING, IDENTICAL, }
/// Id for an output column.
class DiffColumn {
diff --git a/tests/compiler/dart2js/sourcemaps/html_parts.dart b/tests/compiler/dart2js/sourcemaps/html_parts.dart
index 2691a09..d4e809f 100644
--- a/tests/compiler/dart2js/sourcemaps/html_parts.dart
+++ b/tests/compiler/dart2js/sourcemaps/html_parts.dart
@@ -125,15 +125,7 @@
}
}
-enum HtmlPartKind {
- CODE,
- LINE,
- CONST,
- NEWLINE,
- TEXT,
- TAG,
- LINE_NUMBER,
-}
+enum HtmlPartKind { CODE, LINE, CONST, NEWLINE, TEXT, TAG, LINE_NUMBER, }
abstract class HtmlPart {
void printHtmlOn(StringBuffer buffer, HtmlPrintContext context);
diff --git a/tests/compiler/dart2js/sourcemaps/lax_json_test.dart b/tests/compiler/dart2js/sourcemaps/lax_json_test.dart
index 3d78c7e..4af0301 100644
--- a/tests/compiler/dart2js/sourcemaps/lax_json_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/lax_json_test.dart
@@ -51,9 +51,8 @@
expect(decode('{"foo":"bar"}'), equals({'foo': 'bar'}));
expect(decode('{"foo":"bar",}'), equals({'foo': 'bar'}));
expect(
- decode(
- '{"foo":true, "bar": false, "baz": true, '
- '"boz": \nnull\n,"qux": false,}'),
+ decode('{"foo":true, "bar": false, "baz": true, '
+ '"boz": \nnull\n,"qux": false,}'),
equals({
'foo': true,
'bar': false,
diff --git a/tests/compiler/dart2js/sourcemaps/output_structure.dart b/tests/compiler/dart2js/sourcemaps/output_structure.dart
index 648973a..21a5bc3 100644
--- a/tests/compiler/dart2js/sourcemaps/output_structure.dart
+++ b/tests/compiler/dart2js/sourcemaps/output_structure.dart
@@ -637,11 +637,7 @@
String toString() => '[$from,$to[';
}
-enum CodeKind {
- LIBRARY,
- CLASS,
- MEMBER,
-}
+enum CodeKind { LIBRARY, CLASS, MEMBER, }
class CodeLocation {
final Uri uri;
diff --git a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
index ddb6fdc..423c054 100644
--- a/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
+++ b/tests/compiler/dart2js/sourcemaps/sourcemap_html_helper.dart
@@ -307,7 +307,9 @@
void addAnnotations(List<Annotation> annotations) {
currentAnnotations.addAll(annotations);
- currentLine.annotations.addAll(annotations);
+ if (currentLine != null) {
+ currentLine.annotations.addAll(annotations);
+ }
}
void beginLine(int currentOffset) {
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
index 9fcebdc..8ece3d4 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace_test.dart
@@ -27,29 +27,35 @@
}
''',
'''
+import 'package:expect/expect.dart';
main() {
@{1:main}test();
}
+@NoInline()
test() {
@{2:test}throw '$EXCEPTION_MARKER';
}
''',
'''
+import 'package:expect/expect.dart';
main() {
@{1:main}Class.test();
}
class Class {
+ @NoInline()
static test() {
@{2:Class.test}throw '$EXCEPTION_MARKER';
}
}
''',
'''
+import 'package:expect/expect.dart';
main() {
var c = new Class();
c.@{1:main}test();
}
class Class {
+ @NoInline()
test() {
@{2:Class.test}throw '$EXCEPTION_MARKER';
}
@@ -67,6 +73,85 @@
}
}
''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ @{1:main}test();
+}
+@NoInline()
+test() {
+ try {
+ @{2:test}throw '$EXCEPTION_MARKER';
+ } finally {
+ }
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ @{1:main}test();
+}
+@NoInline()
+test() {
+ try {
+ @{2:test}throw '$EXCEPTION_MARKER';
+ } on Error catch (e) {
+ }
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ @{1:main}test();
+}
+@NoInline()
+test() {
+ try {
+ @{2:test}throw '$EXCEPTION_MARKER';
+ } on String catch (e) {
+ rethrow;
+ }
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ test(); // This call is no longer on the stack when the error is thrown.
+}
+@NoInline()
+test() async {
+ @{1:test}throw '$EXCEPTION_MARKER';
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ test1();
+}
+@NoInline()
+test1() async {
+ // This call is no longer on the stack when the error is thrown.
+ await test2();
+}
+@NoInline()
+test2() async {
+ @{1:test2}throw '$EXCEPTION_MARKER';
+}
+''',
+ '''
+import 'package:expect/expect.dart';
+main() {
+ test1();
+}
+@NoInline()
+test1() async {
+ @{1:test1}test2();
+}
+@NoInline()
+test2() {
+ @{2:test2}throw '$EXCEPTION_MARKER';
+}
+''',
];
class Test {
@@ -80,7 +165,6 @@
const int _CR = 0x0D;
const int _LBRACE = 0x7B;
-
Test processTestCode(String code) {
StringBuffer codeBuffer = new StringBuffer();
Map<int, StackTraceLine> stackTraceMap = <int, StackTraceLine>{};
@@ -135,12 +219,12 @@
void main(List<String> arguments) {
asyncTest(() async {
for (String code in TESTS) {
- await runTest(processTestCode(code));
+ await runTest(processTestCode(code), verbose: arguments.contains('-v'));
}
});
}
-Future runTest(Test test) async {
+Future runTest(Test test, {bool verbose: false}) async {
Directory tmpDir = await createTempDir();
String input = '${tmpDir.path}/$INPUT_FILE_NAME';
new File(input).writeAsStringSync(test.code);
@@ -162,9 +246,13 @@
JSON.decode(new File('$output.map').readAsStringSync()));
print("Running d8 $output");
- ProcessResult runResult =
- Process.runSync(d8executable, [output]);
+ ProcessResult runResult = Process.runSync(d8executable,
+ ['sdk/lib/_internal/js_runtime/lib/preambles/d8.js', output]);
String out = '${runResult.stderr}\n${runResult.stdout}';
+ if (verbose) {
+ print('d8 output:');
+ print(out);
+ }
List<String> lines = out.split(new RegExp(r'(\r|\n|\r\n)'));
List<StackTraceLine> jsStackTrace = <StackTraceLine>[];
bool seenMarker = false;
@@ -210,6 +298,12 @@
}
}
}
+ if (verbose) {
+ print('JavaScript stacktrace:');
+ print(jsStackTrace.join('\n'));
+ print('Dart stacktrace:');
+ print(dartStackTrace.join('\n'));
+ }
Expect.equals(
expectedIndex,
test.expectedLines.length,
@@ -341,4 +435,4 @@
return 'third_party/d8/macos/d8';
}
throw new UnsupportedError('Unsupported platform.');
-}
\ No newline at end of file
+}
diff --git a/tests/corelib/regexp/regexp_test.dart b/tests/corelib/regexp/regexp_test.dart
index 60483ba..3231f2a 100644
--- a/tests/corelib/regexp/regexp_test.dart
+++ b/tests/corelib/regexp/regexp_test.dart
@@ -591,4 +591,28 @@
// Tests skipped from V8:
// Test that RegExp.prototype.toString() throws TypeError for
// incompatible receivers (ES5 section 15.10.6 and 15.10.6.4).
+
+ testSticky();
+}
+
+testSticky() {
+ var re = new RegExp(r"foo.bar");
+ Expect.isNotNull(re.matchAsPrefix("foo_bar", 0));
+ Expect.isNull(re.matchAsPrefix("..foo_bar", 0));
+ Expect.isNotNull(re.matchAsPrefix("..foo_bar", 2));
+
+ re = new RegExp(r"^foo");
+ Expect.isNotNull(re.matchAsPrefix("foobar", 0));
+ Expect.isNull(re.matchAsPrefix("..foo", 0));
+ Expect.isNull(re.matchAsPrefix("..foo", 2));
+
+ re = new RegExp(r"^foo", multiLine: true);
+ Expect.isNotNull(re.matchAsPrefix("foobar", 0));
+ Expect.isNull(re.matchAsPrefix("..\nfoo", 0));
+ Expect.isNotNull(re.matchAsPrefix("..\nfoo", 3));
+ Expect.isNull(re.matchAsPrefix("..\nfoofoo", 6));
+
+ re = new RegExp(r"bar$");
+ Expect.isNull(re.matchAsPrefix("foobar", 0));
+ Expect.isNotNull(re.matchAsPrefix("foobar", 3));
}
diff --git a/tests/language/field_test.dart b/tests/language/field_test.dart
index 6a1937f..ca41740 100644
--- a/tests/language/field_test.dart
+++ b/tests/language/field_test.dart
@@ -52,11 +52,11 @@
// The tests below are a little cumbersome because not
// everything is implemented yet.
var o = new Second();
- // 'a' getter is overriden, always returns -12.
+ // 'a' getter is overridden, always returns -12.
Expect.equals(-12, o.a);
o.a = 2;
Expect.equals(-12, o.a);
- // 'b' setter is overriden to write 12 to field 'c'.
+ // 'b' setter is overridden to write 12 to field 'c'.
o.b = o;
Expect.equals(12, o.c);
}
diff --git a/tests/language/language.status b/tests/language/language.status
index e6b27de..5a23a4d 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -261,7 +261,6 @@
library_env_test/has_mirror_support: RuntimeError, OK
[ $hot_reload || $hot_reload_rollback ]
-methods_as_constants_test: Skip # Issue 27803
static_closure_identical_test: Pass, Fail # Closure identity
cha_deopt1_test: Crash # Requires deferred libraries
cha_deopt2_test: Crash # Requires deferred libraries
@@ -297,6 +296,10 @@
tearoff_basic_test: Crash # Requires deferred libraries
conditional_import_test: Crash # Requires deferred libraries
conditional_import_string_test: Crash # Requires deferred libraries
+override_field_method1_negative_test: Pass, Crash # Issue 27835
+override_field_method2_negative_test: Pass, Crash # Issue 27835
+override_field_method4_negative_test: Pass, Crash # Issue 27835
+override_field_method5_negative_test: Pass, Crash # Issue 27835
[$runtime != vm || $compiler != none]
assert_initializer_test: SKIP # not implemented yet, experiment is VM only.
diff --git a/tests/language/language_kernel.status b/tests/language/language_kernel.status
index 1346de2..3d87904 100644
--- a/tests/language/language_kernel.status
+++ b/tests/language/language_kernel.status
@@ -141,8 +141,6 @@
enum_test: RuntimeError
evaluation_redirecting_constructor_test: RuntimeError
example_constructor_test: RuntimeError
-execute_finally8_test: RuntimeError
-execute_finally9_test: RuntimeError
export_double_same_main_test: Crash
export_main_test: Crash
external_test/10: MissingRuntimeError
@@ -345,6 +343,15 @@
vm/type_cast_vm_test: RuntimeError
vm/type_vm_test: RuntimeError
+# dartk: JIT failures (debug)
+[ $compiler == dartk && $runtime == vm && $mode == debug ]
+async_star_regression_fisk_test: Crash # Stack mismatch during expression translation.
+async_star_test: Crash # Stack mismatch during expression translation.
+issue23244_test: Crash # Class finalization issue
+not_enough_positional_arguments_test/02: Crash # Crash
+not_enough_positional_arguments_test/05: Crash # Crash
+vm/optimized_guarded_field_isolates_test: Crash # Class finalization issue
+
# dartk: precompilation failures
[ $compiler == dartkp && $runtime == dart_precompiled ]
accessor_conflict_export2_test: RuntimeError
@@ -697,4 +704,4 @@
vm/debug_break_enabled_vm_test/none: CompileTimeError
vm/reflect_core_vm_test: CompileTimeError
vm/type_cast_vm_test: RuntimeError
-vm/type_vm_test: RuntimeError
\ No newline at end of file
+vm/type_vm_test: RuntimeError
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index 9bcdd8e..ab4f18c 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -396,11 +396,8 @@
convert/utf85_test: Pass, Timeout
[ $hot_reload || $hot_reload_rollback ]
-async/zone_debug_test: Skip # Issue 27803
-async/intercept_print1_test: Skip # Issue 27803
async/multiple_timer_test: Pass, Fail # Timing related
async/stream_transformer_test: Pass, Fail # Closure identity
-convert/json_toEncodable_reviver_test: Skip # Issue 27803
mirrors/closurization_equivalence_test: SkipByDesign # Method equality
mirrors/fake_function_with_call_test: SkipByDesign # Method equality
diff --git a/tools/VERSION b/tools/VERSION
index da4c303..b4d1f0b 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -28,5 +28,5 @@
MAJOR 1
MINOR 21
PATCH 0
-PRERELEASE 7
+PRERELEASE 8
PRERELEASE_PATCH 0
diff --git a/tools/bots/bot_utils.py b/tools/bots/bot_utils.py
index 1e2ce69..dcd5433 100644
--- a/tools/bots/bot_utils.py
+++ b/tools/bots/bot_utils.py
@@ -352,6 +352,7 @@
with open(checksum_filename, 'w') as f:
f.write('%s *%s' % (checksum, mangled_filename))
+ print "MD5 checksum of %s is %s" % (filename, checksum)
return checksum_filename
def CreateSha256ChecksumFile(filename, mangled_filename=None):
@@ -365,6 +366,7 @@
with open(checksum_filename, 'w') as f:
f.write('%s *%s' % (checksum, mangled_filename))
+ print "SHA256 checksum of %s is %s" % (filename, checksum)
return checksum_filename
def GetChannelFromName(name):
diff --git a/tools/dartk_wrappers/dartk b/tools/dartk_wrappers/dartk
new file mode 100755
index 0000000..ca93a28
--- /dev/null
+++ b/tools/dartk_wrappers/dartk
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# 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.
+
+# Unlike $0, $BASH_SOURCE points to the absolute path of this file.
+PROG_NAME="$BASH_SOURCE"
+WRAPPERS_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
+DART_ROOT="$(cd "${WRAPPERS_DIR}/../.." ; pwd -P)"
+DARTK="$DART_ROOT/third_party/pkg/kernel/bin/dartk.dart"
+
+if [[ `uname` == 'Darwin' ]];
+then
+ DART="$DART_ROOT/tools/sdks/mac/dart-sdk/bin/dart"
+else
+ DART="$DART_ROOT/tools/sdks/linux/dart-sdk/bin/dart"
+fi
+
+exec "$DART" "$DARTK" "$@"
diff --git a/tools/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 868c74c..f348318 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -217,7 +217,7 @@
@override
String computeCompilerPath(String buildDir) {
- return 'third_party/pkg/kernel/bin/dartk.dart';
+ return 'tools/dartk_wrappers/dartk$executableScriptSuffix';
}
CompilationCommand computeCompilationCommand(