Version 2.12.0-285.0.dev
Merge commit '950234803ba8a9636db187bfe5c13e2b531151bd' into 'dev'
diff --git a/pkg/analysis_server/benchmark/perf/memory_tests.dart b/pkg/analysis_server/benchmark/perf/memory_tests.dart
index 651763f..5806745 100644
--- a/pkg/analysis_server/benchmark/perf/memory_tests.dart
+++ b/pkg/analysis_server/benchmark/perf/memory_tests.dart
@@ -10,6 +10,7 @@
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/lsp/handlers/handler_completion.dart';
import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:test/test.dart';
import '../../test/integration/lsp_server/integration_tests.dart';
@@ -69,8 +70,11 @@
Future<int> getMemoryUsage() => _test.getMemoryUsage();
@override
- Future<void> openFile(String filePath, String contents) =>
- _test.sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
+ Future<void> openFile(String filePath, String contents) async {
+ await _test
+ .sendAnalysisUpdateContent({filePath: AddContentOverlay(contents)});
+ await _test.sendAnalysisSetPriorityFiles([filePath]);
+ }
@override
Future<void> setUp(List<String> roots) async {
@@ -135,6 +139,7 @@
class LspAnalysisServerBenchmarkTest extends AbstractBenchmarkTest
with ClientCapabilitiesHelperMixin {
final _test = LspAnalysisServerMemoryUsageTest();
+ final PrintableLogger _logger = PrintableLogger();
/// Track the file contents so we can easily convert offsets (used in
/// the interface) to Positions required by LSP without having to keep
@@ -159,7 +164,7 @@
}
@override
- void debugStdio() {}
+ void debugStdio() => _logger.debugStdio();
@override
Future<int> getMemoryUsage() => _test.getMemoryUsage();
@@ -167,11 +172,13 @@
@override
Future<void> openFile(String filePath, String contents) {
_fileContents[filePath] = contents;
- return _test.openFile(Uri.file(filePath), contents);
+ return _test.openFile(Uri.file(filePath), contents,
+ version: _fileVersion++);
}
@override
Future<void> setUp(List<String> roots) async {
+ _test.instrumentationService = InstrumentationLogAdapter(_logger);
await _test.setUp();
_test.projectFolderPath = roots.single;
_test.projectFolderUri = Uri.file(_test.projectFolderPath);
@@ -194,7 +201,10 @@
}
@override
- Future<void> shutdown() async => _test.tearDown();
+ Future<void> shutdown() async {
+ _test.tearDown();
+ _logger.shutdown();
+ }
@override
Future<void> updateFile(String filePath, String contents) {
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 1165746..0adfd67 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -121,6 +121,12 @@
/// A progress reporter for analysis status.
ProgressReporter analyzingProgressReporter;
+ /// The last paths that were set as included analysis roots.
+ Set<String> _lastIncludedRootPaths;
+
+ /// The last paths that were set as excluded analysis roots.
+ Set<String> _lastExcludedRootPaths;
+
/// Initialize a newly created server to send and receive messages to the
/// given [channel].
LspAnalysisServer(
@@ -671,9 +677,8 @@
void _refreshAnalysisRoots() {
// Always include any temporary analysis roots for open files.
- final includedPaths = HashSet<String>.of(_explicitAnalysisRoots)
- ..addAll(_temporaryAnalysisRoots.values)
- ..toList();
+ final includedPaths = _explicitAnalysisRoots.toSet()
+ ..addAll(_temporaryAnalysisRoots.values);
final excludedPaths = clientConfiguration.analysisExcludedFolders
.expand((excludePath) => isAbsolute(excludePath)
@@ -683,11 +688,27 @@
// calling workspace/configuration whenever workspace folders change
// and caching the config for each one.
: _explicitAnalysisRoots.map((root) => join(root, excludePath)))
- .toList();
+ .toSet();
+
+ // If the roots didn't actually change from the last time they were set
+ // (this can happen a lot as temporary roots are collected for open files)
+ // we can avoid doing expensive work like discarding/re-scanning the
+ // declarations.
+ final rootsChanged =
+ includedPaths.length != _lastIncludedRootPaths?.length ||
+ !includedPaths.every(_lastIncludedRootPaths.contains) ||
+ excludedPaths.length != _lastExcludedRootPaths?.length ||
+ !excludedPaths.every(_lastExcludedRootPaths.contains);
+
+ if (!rootsChanged) return;
+
+ _lastIncludedRootPaths = includedPaths;
+ _lastExcludedRootPaths = excludedPaths;
declarationsTracker?.discardContexts();
- notificationManager.setAnalysisRoots(includedPaths.toList(), excludedPaths);
- contextManager.setRoots(includedPaths.toList(), excludedPaths);
+ notificationManager.setAnalysisRoots(
+ includedPaths.toList(), excludedPaths.toList());
+ contextManager.setRoots(includedPaths.toList(), excludedPaths.toList());
addContextsToDeclarationsTracker();
}
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index b9a8e93..9914359 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -24,6 +24,7 @@
show SourceChange, SourceEdit;
import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
+import 'package:meta/meta.dart';
import 'package:path/path.dart' as pathos;
/// Adds edits to the given [change] that ensure that all the [libraries] are
@@ -813,23 +814,19 @@
/// used by the generated source, but not imported.
String getTypeSource(DartType type, Set<Source> librariesToImport,
{StringBuffer parametersBuffer}) {
- var sb = StringBuffer();
- // type parameter
- if (!_isTypeVisible(type)) {
+ if (type.aliasElement != null) {
+ return _getTypeCodeElementArguments(
+ librariesToImport: librariesToImport,
+ element: type.aliasElement,
+ typeArguments: type.aliasArguments,
+ );
+ }
+
+ if (type is DynamicType) {
return 'dynamic';
}
- var element = type.element;
-
- // Typedef(s) are represented as FunctionTypeAliasElement(s).
- if (element is GenericFunctionTypeElement &&
- element.typeParameters.isEmpty &&
- element.enclosingElement is FunctionTypeAliasElement) {
- element = element.enclosingElement;
- }
-
- // just a Function, not FunctionTypeAliasElement
- if (type is FunctionType && element is! FunctionTypeAliasElement) {
+ if (type is FunctionType) {
if (parametersBuffer == null) {
return 'Function';
}
@@ -846,68 +843,33 @@
parametersBuffer.write(')');
return getTypeSource(type.returnType, librariesToImport);
}
- // <Bottom>, Null
- if (type.isBottom || type.isDartCoreNull) {
- return 'dynamic';
+
+ if (type is InterfaceType) {
+ return _getTypeCodeElementArguments(
+ librariesToImport: librariesToImport,
+ element: type.element,
+ typeArguments: type.typeArguments,
+ );
}
- // prepare element
- if (element == null) {
- var source = type.toString();
- source = source.replaceAll('<dynamic>', '');
- source = source.replaceAll('<dynamic, dynamic>', '');
- return source;
+
+ if (type is NeverType) {
+ return 'Never';
}
- // check if imported
- var library = element.library;
- if (library != null && library != _library) {
- // no source, if private
- if (element.isPrivate) {
- return null;
- }
- // ensure import
- var importElement = _getImportElement(element);
- if (importElement != null) {
- if (importElement.prefix != null) {
- sb.write(importElement.prefix.displayName);
- sb.write('.');
- }
+
+ if (type is TypeParameterType) {
+ var element = type.element;
+ if (_isTypeParameterVisible(element)) {
+ return element.name;
} else {
- librariesToImport.add(library.source);
+ return 'dynamic';
}
}
- // append simple name
- var name = element.displayName;
- sb.write(name);
- // may be type arguments
- if (type is ParameterizedType) {
- var arguments = type.typeArguments;
- // check if has arguments
- var hasArguments = false;
- var allArgumentsVisible = true;
- for (var argument in arguments) {
- hasArguments = hasArguments || !argument.isDynamic;
- allArgumentsVisible = allArgumentsVisible && _isTypeVisible(argument);
- }
- // append type arguments
- if (hasArguments && allArgumentsVisible) {
- sb.write('<');
- for (var i = 0; i < arguments.length; i++) {
- var argument = arguments[i];
- if (i != 0) {
- sb.write(', ');
- }
- var argumentSrc = getTypeSource(argument, librariesToImport);
- if (argumentSrc != null) {
- sb.write(argumentSrc);
- } else {
- return null;
- }
- }
- sb.write('>');
- }
+
+ if (type is VoidType) {
+ return 'void';
}
- // done
- return sb.toString();
+
+ throw UnimplementedError('(${type.runtimeType}) $type');
}
/// Indents given source left or right.
@@ -1145,6 +1107,58 @@
return null;
}
+ String _getTypeCodeElementArguments({
+ @required Set<Source> librariesToImport,
+ @required Element element,
+ @required List<DartType> typeArguments,
+ }) {
+ var sb = StringBuffer();
+
+ // check if imported
+ var library = element.library;
+ if (library != null && library != _library) {
+ // no source, if private
+ if (element.isPrivate) {
+ return null;
+ }
+ // ensure import
+ var importElement = _getImportElement(element);
+ if (importElement != null) {
+ if (importElement.prefix != null) {
+ sb.write(importElement.prefix.displayName);
+ sb.write('.');
+ }
+ } else {
+ librariesToImport.add(library.source);
+ }
+ }
+
+ // append simple name
+ var name = element.displayName;
+ sb.write(name);
+
+ // append type arguments
+ if (typeArguments.isNotEmpty) {
+ sb.write('<');
+ for (var i = 0; i < typeArguments.length; i++) {
+ var argument = typeArguments[i];
+ if (i != 0) {
+ sb.write(', ');
+ }
+ var argumentSrc = getTypeSource(argument, librariesToImport);
+ if (argumentSrc != null) {
+ sb.write(argumentSrc);
+ } else {
+ return null;
+ }
+ }
+ sb.write('>');
+ }
+
+ // done
+ return sb.toString();
+ }
+
/// @return the [InvertedCondition] for the given logical expression.
_InvertedCondition _invertCondition0(Expression expression) {
if (expression is BooleanLiteral) {
@@ -1213,16 +1227,12 @@
return _InvertedCondition._simple(getNodeText(expression));
}
- /// Checks if [type] is visible in [targetExecutableElement] or
+ /// Checks if [element] is visible in [targetExecutableElement] or
/// [targetClassElement].
- bool _isTypeVisible(DartType type) {
- if (type is TypeParameterType) {
- var parameterElement = type.element;
- var parameterClassElement = parameterElement.enclosingElement;
- return identical(parameterClassElement, targetExecutableElement) ||
- identical(parameterClassElement, targetClassElement);
- }
- return true;
+ bool _isTypeParameterVisible(TypeParameterElement element) {
+ var enclosing = element.enclosingElement;
+ return identical(enclosing, targetExecutableElement) ||
+ identical(enclosing, targetClassElement);
}
/// Return `true` if [selection] covers [range] and there are any
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index 4370af4..1201756 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -762,7 +762,8 @@
} else if (_returnType == null) {
variableType = null;
if (_hasAwait) {
- returnType = _getTypeCode(typeProvider.futureDynamicType);
+ var futureVoid = typeProvider.futureType2(typeProvider.voidType);
+ returnType = _getTypeCode(futureVoid);
} else {
returnType = 'void';
}
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index c07285d..bd8a64f 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -17,6 +17,7 @@
with ClientCapabilitiesHelperMixin, LspAnalysisServerTestMixin {
final List<String> vmArgs = [];
LspServerClient client;
+ InstrumentationService instrumentationService;
final Map<int, Completer<ResponseMessage>> _completers = {};
@@ -79,7 +80,7 @@
analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
analysisOptionsUri = Uri.file(analysisOptionsPath);
- client = LspServerClient();
+ client = LspServerClient(instrumentationService);
await client.start(vmArgs: vmArgs);
client.serverToClient.listen((message) {
if (message is ResponseMessage) {
@@ -104,11 +105,14 @@
}
class LspServerClient {
+ final InstrumentationService instrumentationService;
Process _process;
LspByteStreamServerChannel channel;
final StreamController<Message> _serverToClient =
StreamController<Message>.broadcast();
+ LspServerClient(this.instrumentationService);
+
Future<int> get exitCode => _process.exitCode;
Stream<Message> get serverToClient => _serverToClient.stream;
@@ -172,8 +176,35 @@
throw 'Analysis Server wrote to stderr:\n\n$message';
});
- channel = LspByteStreamServerChannel(
- _process.stdout, _process.stdin, InstrumentationService.NULL_SERVICE);
+ channel = LspByteStreamServerChannel(_process.stdout, _process.stdin,
+ instrumentationService ?? InstrumentationService.NULL_SERVICE);
channel.listen(_serverToClient.add);
}
}
+
+/// An [InstrumentationLogger] that buffers logs until [debugStdio()] is called.
+class PrintableLogger extends InstrumentationLogger {
+ bool _printLogs = false;
+ final _buffer = StringBuffer();
+
+ void debugStdio() {
+ print(_buffer.toString());
+ _buffer.clear();
+ _printLogs = true;
+ }
+
+ @override
+ void log(String message) {
+ if (_printLogs) {
+ print(message);
+ } else {
+ _buffer.writeln(message);
+ }
+ }
+
+ @override
+ Future<void> shutdown() async {
+ _printLogs = false;
+ _buffer.clear();
+ }
+}
diff --git a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
index 2396564..71155fe 100644
--- a/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/extract_method_test.dart
@@ -2334,7 +2334,7 @@
print(v);
}
-Future res() async {
+Future<dynamic> res() async {
var v = await getValue();
return v;
}
@@ -2431,7 +2431,7 @@
// end
}
-Future res() async {
+Future<void> res() async {
int v = await getValue();
print(v);
}
@@ -2812,7 +2812,7 @@
// end
}
-List res(bool b) {
+List<dynamic> res(bool b) {
if (b) {
print(true);
return <int>[];
diff --git a/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart b/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart
index dff3ac4..fd2fea7 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/create_function_test.dart
@@ -7,6 +7,7 @@
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../../../../abstract_context.dart';
import 'fix_processor.dart';
void main() {
@@ -16,21 +17,20 @@
}
@reflectiveTest
-class CreateFunctionTest extends FixProcessorTest {
+class CreateFunctionTest extends FixProcessorTest
+ with WithNonFunctionTypeAliasesMixin {
@override
FixKind get kind => DartFixKind.CREATE_FUNCTION;
Future<void> assert_returnType_bool(String lineWithTest) async {
await resolveTestCode('''
-main() {
- bool b = true;
+void f(bool b) {
$lineWithTest
print(b);
}
''');
await assertHasFix('''
-main() {
- bool b = true;
+void f(bool b) {
$lineWithTest
print(b);
}
@@ -59,7 +59,7 @@
Future<void> test_duplicateArgumentNames() async {
await resolveTestCode('''
class C {
- int x;
+ int x = 0;
}
foo(C c1, C c2) {
@@ -68,7 +68,7 @@
''');
await assertHasFix('''
class C {
- int x;
+ int x = 0;
}
foo(C c1, C c2) {
@@ -159,7 +159,7 @@
Future<void> test_functionType_cascadeSecond() async {
await resolveTestCode('''
class A {
- B ma() => null;
+ B ma() => throw 0;
}
class B {
useFunction(int g(double a, String b)) {}
@@ -172,7 +172,7 @@
''');
await assertHasFix('''
class A {
- B ma() => null;
+ B ma() => throw 0;
}
class B {
useFunction(int g(double a, String b)) {}
@@ -193,13 +193,13 @@
main() {
useFunction(g: test);
}
-useFunction({Function g}) {}
+useFunction({Function? g}) {}
''');
await assertHasFix('''
main() {
useFunction(g: test);
}
-useFunction({Function g}) {}
+useFunction({Function? g}) {}
test() {
}
@@ -247,13 +247,13 @@
main() {
useFunction(g: test);
}
-useFunction({int g(double a, String b)}) {}
+useFunction({int g(double a, String b)?}) {}
''');
await assertHasFix('''
main() {
useFunction(g: test);
}
-useFunction({int g(double a, String b)}) {}
+useFunction({int g(double a, String b)?}) {}
int test(double a, String b) {
}
@@ -291,7 +291,7 @@
Future<void> test_functionType_notFunctionType() async {
await resolveTestCode('''
-main(A a) {
+void f(A a) {
useFunction(a.test);
}
typedef A();
@@ -303,7 +303,7 @@
Future<void> test_generic_type() async {
await resolveTestCode('''
class A {
- List<int> items;
+ List<int> items = [];
main() {
process(items);
}
@@ -311,7 +311,7 @@
''');
await assertHasFix('''
class A {
- List<int> items;
+ List<int> items = [];
main() {
process(items);
}
@@ -330,7 +330,7 @@
Future<void> test_generic_typeParameter() async {
await resolveTestCode('''
class A<T> {
- Map<int, T> items;
+ Map<int, T> items = {};
main() {
process(items);
}
@@ -338,7 +338,7 @@
''');
await assertHasFix('''
class A<T> {
- Map<int, T> items;
+ Map<int, T> items = {};
main() {
process(items);
}
@@ -471,14 +471,14 @@
Future<void> test_returnType_fromAssignment_plusEq() async {
await resolveTestCode('''
main() {
- int v;
+ num v = 0;
v += myUndefinedFunction();
print(v);
}
''');
await assertHasFix('''
main() {
- int v;
+ num v = 0;
v += myUndefinedFunction();
print(v);
}
@@ -556,6 +556,30 @@
''');
}
+ Future<void> test_returnType_typeAlias_function() async {
+ await resolveTestCode('''
+typedef A<T> = void Function(T a);
+
+void f(A<int> Function() a) {}
+
+void g() {
+ f(test);
+}
+''');
+ await assertHasFix('''
+typedef A<T> = void Function(T a);
+
+void f(A<int> Function() a) {}
+
+void g() {
+ f(test);
+}
+
+A<int> test() {
+}
+''');
+ }
+
Future<void> test_returnType_void() async {
await resolveTestCode('''
main() {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 51bfd9e..278145e 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -7,6 +7,7 @@
Use `CompilationUnitElement.typeAliases` instead.
* Added `AnalysisContext.sdkRoot`.
* Removed `NullSafetyUnderstandingFlag`.
+* Removed `functionTypeAliasElement` from `TypeSystem.instantiateToBounds2`.
## 0.41.1
* Updated `PackageBuildWorkspace` that supports `package:build` to stop
diff --git a/pkg/analyzer/lib/dart/element/type_provider.dart b/pkg/analyzer/lib/dart/element/type_provider.dart
index f263c27..17b4101 100644
--- a/pkg/analyzer/lib/dart/element/type_provider.dart
+++ b/pkg/analyzer/lib/dart/element/type_provider.dart
@@ -10,159 +10,157 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class TypeProvider {
- /// Return the element representing the built-in class 'bool'.
+ /// Return the element representing the built-in class `bool`.
ClassElement get boolElement;
- /// Return the type representing the built-in type 'bool'.
+ /// Return the type representing the built-in type `bool`.
InterfaceType get boolType;
- /// Return the type representing the type 'bottom'.
+ /// Return the type representing the type `bottom`.
DartType get bottomType;
- /// Return the type representing the built-in type 'Deprecated'.
+ /// Return the type representing the built-in type `Deprecated`.
InterfaceType get deprecatedType;
- /// Return the element representing the built-in class 'double'.
+ /// Return the element representing the built-in class `double`.
ClassElement get doubleElement;
- /// Return the type representing the built-in type 'double'.
+ /// Return the type representing the built-in type `double`.
InterfaceType get doubleType;
- /// Return the type representing the built-in type 'dynamic'.
+ /// Return the type representing the built-in type `dynamic`.
DartType get dynamicType;
- /// Return the type representing the built-in type 'Function'.
+ /// Return the type representing the built-in type `Function`.
InterfaceType get functionType;
- /// Return the type representing 'Future<dynamic>'.
+ /// Return the type representing `Future<dynamic>`.
InterfaceType get futureDynamicType;
- /// Return the element representing the built-in class 'Future'.
+ /// Return the element representing the built-in class `Future`.
ClassElement get futureElement;
- /// Return the type representing 'Future<Null>'.
+ /// Return the type representing `Future<Null>`.
InterfaceType get futureNullType;
- /// Return the element representing the built-in class 'FutureOr'.
+ /// Return the element representing the built-in class `FutureOr`.
ClassElement get futureOrElement;
- /// Return the type representing 'FutureOr<Null>'.
+ /// Return the type representing `FutureOr<Null>`.
InterfaceType get futureOrNullType;
- /// Return the element representing the built-in class 'int'.
+ /// Return the element representing the built-in class `int`.
ClassElement get intElement;
- /// Return the type representing the built-in type 'int'.
+ /// Return the type representing the built-in type `int`.
InterfaceType get intType;
- /// Return the type representing the type 'Iterable<dynamic>'.
+ /// Return the type representing the type `Iterable<dynamic>`.
InterfaceType get iterableDynamicType;
- /// Return the element representing the built-in class 'Iterable'.
+ /// Return the element representing the built-in class `Iterable`.
ClassElement get iterableElement;
- /// Return the type representing the type 'Iterable<Object>'.
+ /// Return the type representing the type `Iterable<Object>`.
InterfaceType get iterableObjectType;
- /// Return the element representing the built-in class 'List'.
+ /// Return the element representing the built-in class `List`.
ClassElement get listElement;
- /// Return the element representing the built-in class 'Map'.
+ /// Return the element representing the built-in class `Map`.
ClassElement get mapElement;
- /// Return the type representing 'Map<Object, Object>'.
+ /// Return the type representing `Map<Object, Object>`.
InterfaceType get mapObjectObjectType;
- /// Return the type representing the built-in type 'Never'.
+ /// Return the type representing the built-in type `Never`.
DartType get neverType;
/// Return a list containing all of the types that cannot be either extended
/// or implemented.
Set<ClassElement> get nonSubtypableClasses;
- /// Return the element representing the built-in class 'null'.
+ /// Return the element representing the built-in class `Null`.
ClassElement get nullElement;
- /// Return the type representing the built-in type 'Null'.
+ /// Return the type representing the built-in type `Null`.
InterfaceType get nullType;
- /// Return the element representing the built-in class 'num'.
+ /// Return the element representing the built-in class `num`.
ClassElement get numElement;
- /// Return the type representing the built-in type 'num'.
+ /// Return the type representing the built-in type `num`.
InterfaceType get numType;
- /// Return the type representing the built-in type 'Object'.
+ /// Return the type representing the built-in type `Object`.
InterfaceType get objectType;
- /// Return the element representing the built-in class 'Set'.
+ /// Return the element representing the built-in class `Set`.
ClassElement get setElement;
- /// Return the type representing the built-in type 'StackTrace'.
+ /// Return the type representing the built-in type `StackTrace`.
InterfaceType get stackTraceType;
- /// Return the type representing 'Stream<dynamic>'.
+ /// Return the type representing `Stream<dynamic>`.
InterfaceType get streamDynamicType;
- /// Return the element representing the built-in class 'Stream'.
+ /// Return the element representing the built-in class `Stream`.
ClassElement get streamElement;
- /// Return the element representing the built-in class 'String'.
+ /// Return the element representing the built-in class `String`.
ClassElement get stringElement;
- /// Return the type representing the built-in type 'String'.
+ /// Return the type representing the built-in type `String`.
InterfaceType get stringType;
- /// Return the element representing the built-in class 'Symbol'.
+ /// Return the element representing the built-in class `Symbol`.
ClassElement get symbolElement;
- /// Return the type representing the built-in type 'Symbol'.
+ /// Return the type representing the built-in type `Symbol`.
InterfaceType get symbolType;
- /// Return the type representing the built-in type 'Type'.
+ /// Return the type representing the built-in type `Type`.
InterfaceType get typeType;
/// Return the type representing the built-in type `void`.
VoidType get voidType;
- /// Return the instantiation of the built-in class 'FutureOr' with the
+ /// Return the instantiation of the built-in class `FutureOr` with the
/// given [valueType]. The type has the nullability suffix of this provider.
InterfaceType futureOrType2(DartType valueType);
- /// Return the instantiation of the built-in class 'Future' with the
+ /// Return the instantiation of the built-in class `Future` with the
/// given [valueType]. The type has the nullability suffix of this provider.
InterfaceType futureType2(DartType valueType);
- /// Return 'true' if [id] is the name of a getter on
- /// the Object type.
+ /// Return 'true' if [id] is the name of a getter on the Object type.
bool isObjectGetter(String id);
- /// Return 'true' if [id] is the name of a method or getter on
- /// the Object type.
+ /// Return 'true' if [id] is the name of a method or getter on the Object
+ /// type.
bool isObjectMember(String id);
- /// Return 'true' if [id] is the name of a method on
- /// the Object type.
+ /// Return 'true' if [id] is the name of a method on the Object type.
bool isObjectMethod(String id);
- /// Return the instantiation of the built-in class 'Iterable' with the
+ /// Return the instantiation of the built-in class `Iterable` with the
/// given [elementType]. The type has the nullability suffix of this provider.
InterfaceType iterableType2(DartType elementType);
- /// Return the instantiation of the built-in class 'List' with the
+ /// Return the instantiation of the built-in class `List` with the
/// given [elementType]. The type has the nullability suffix of this provider.
InterfaceType listType2(DartType elementType);
- /// Return the instantiation of the built-in class 'List' with the
+ /// Return the instantiation of the built-in class `List` with the
/// given [keyType] and [valueType]. The type has the nullability suffix of
/// this provider.
InterfaceType mapType2(DartType keyType, DartType valueType);
- /// Return the instantiation of the built-in class 'Set' with the
+ /// Return the instantiation of the built-in class `Set` with the
/// given [elementType]. The type has the nullability suffix of this provider.
InterfaceType setType2(DartType elementType);
- /// Return the instantiation of the built-in class 'Stream' with the
+ /// Return the instantiation of the built-in class `Stream` with the
/// given [elementType]. The type has the nullability suffix of this provider.
InterfaceType streamType2(DartType elementType);
}
diff --git a/pkg/analyzer/lib/dart/element/type_system.dart b/pkg/analyzer/lib/dart/element/type_system.dart
index 8e3d4db..e8c7158 100644
--- a/pkg/analyzer/lib/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/dart/element/type_system.dart
@@ -42,8 +42,6 @@
/// be provided.
DartType instantiateToBounds2({
ClassElement? classElement,
- @Deprecated("Use 'typeAliasElement' instead")
- FunctionTypeAliasElement? functionTypeAliasElement,
TypeAliasElement? typeAliasElement,
required NullabilitySuffix nullabilitySuffix,
});
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index beb67a5..b79502d 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -527,12 +527,9 @@
@override
DartType instantiateToBounds2({
ClassElement? classElement,
- @Deprecated("Use 'typeAliasElement' instead")
- FunctionTypeAliasElement? functionTypeAliasElement,
TypeAliasElement? typeAliasElement,
required NullabilitySuffix nullabilitySuffix,
}) {
- typeAliasElement ??= functionTypeAliasElement;
if (classElement != null) {
var typeParameters = classElement.typeParameters;
var typeArguments = _defaultTypeArguments(typeParameters);
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 58e5bf1..719f8d7 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -125,12 +125,6 @@
if (element is ClassElement) {
_resolveReceiverTypeLiteral(node, element, nameNode, name);
return;
- } else if (element is FunctionTypeAliasElement) {
- _reportUndefinedMethod(
- node,
- name,
- _resolver.typeProvider.typeType.element,
- );
} else if (element is TypeAliasElement) {
var aliasedType = element.aliasedType;
if (aliasedType is InterfaceType) {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 148ef98..b1db9af 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1718,7 +1718,6 @@
CompileTimeErrorCode.ASSIGNMENT_TO_METHOD, expression);
} else if (element is ClassElement ||
element is DynamicElementImpl ||
- element is FunctionTypeAliasElement ||
element is TypeParameterElement) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, expression);
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
index 8767c86..0114920 100644
--- a/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/undefined_method_test.dart
@@ -14,7 +14,8 @@
}
@reflectiveTest
-class UndefinedMethodTest extends PubPackageResolutionTest {
+class UndefinedMethodTest extends PubPackageResolutionTest
+ with WithNonFunctionTypeAliasesMixin {
test_constructor_defined() async {
await assertNoErrorsInCode(r'''
class C {
@@ -97,9 +98,10 @@
test_leastUpperBoundWithNull() async {
await assertErrorsInCode('''
+// @dart = 2.9
f(bool b, int i) => (b ? null : i).foo();
''', [
- error(CompileTimeErrorCode.UNDEFINED_METHOD, 35, 3),
+ error(CompileTimeErrorCode.UNDEFINED_METHOD, 50, 3),
]);
}
@@ -159,12 +161,13 @@
test_method_undefined_onNull() async {
await assertErrorsInCode(r'''
+// @dart = 2.9
Null f(int x) => null;
main() {
f(42).abs();
}
''', [
- error(CompileTimeErrorCode.UNDEFINED_METHOD, 40, 3),
+ error(CompileTimeErrorCode.UNDEFINED_METHOD, 55, 3),
]);
}
@@ -198,6 +201,30 @@
]);
}
+ test_typeAlias_functionType() async {
+ await assertErrorsInCode(r'''
+typedef A = void Function();
+
+void f() {
+ A.foo();
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_METHOD, 45, 3),
+ ]);
+ }
+
+ test_typeAlias_interfaceType() async {
+ await assertErrorsInCode(r'''
+typedef A = List<int>;
+
+void f() {
+ A.foo();
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_METHOD, 39, 3),
+ ]);
+ }
+
test_withExtension() async {
await assertErrorsInCode(r'''
class C {}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index 993cf7e..eb831fc 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -24,6 +24,7 @@
import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:dart_style/dart_style.dart';
+import 'package:meta/meta.dart';
/// A [ChangeBuilder] used to build changes in Dart files.
@Deprecated('Use ChangeBuilder')
@@ -1178,22 +1179,19 @@
}
return false;
}
- // The type `void` does not have an element.
- if (type is VoidType) {
- write('void');
+
+ var aliasElement = type.aliasElement;
+ if (aliasElement != null) {
+ _writeTypeElementArguments(
+ element: aliasElement,
+ typeArguments: type.aliasArguments,
+ methodBeingCopied: methodBeingCopied,
+ );
+ _writeTypeNullability(type);
return true;
}
- var element = type.element;
- // Typedef(s) are represented as GenericFunctionTypeElement(s).
- if (element is GenericFunctionTypeElement &&
- element.typeParameters.isEmpty &&
- element.enclosingElement is FunctionTypeAliasElement) {
- element = element.enclosingElement;
- }
-
- // Just a Function, not FunctionTypeAliasElement.
- if (type is FunctionType && element is! FunctionTypeAliasElement) {
+ if (type is FunctionType) {
if (_writeType(type.returnType, methodBeingCopied: methodBeingCopied)) {
write(' ');
}
@@ -1204,6 +1202,41 @@
return true;
}
+ if (type is InterfaceType) {
+ _writeTypeElementArguments(
+ element: type.element,
+ typeArguments: type.typeArguments,
+ methodBeingCopied: methodBeingCopied,
+ );
+ _writeTypeNullability(type);
+ return true;
+ }
+
+ if (type is NeverType) {
+ write('Never');
+ _writeTypeNullability(type);
+ return true;
+ }
+
+ if (type is TypeParameterType) {
+ write(type.element.name);
+ _writeTypeNullability(type);
+ return true;
+ }
+
+ if (type is VoidType) {
+ write('void');
+ return true;
+ }
+
+ throw UnimplementedError('(${type.runtimeType}) $type');
+ }
+
+ void _writeTypeElementArguments({
+ @required Element element,
+ @required List<DartType> typeArguments,
+ @required ExecutableElement methodBeingCopied,
+ }) {
// Ensure that the element is imported.
_writeLibraryReference(element);
@@ -1212,12 +1245,11 @@
write(name);
// Write type arguments.
- if (type is ParameterizedType) {
- var arguments = type.typeArguments;
+ if (typeArguments.isNotEmpty) {
// Check if has arguments.
var hasArguments = false;
var allArgumentsVisible = true;
- for (var argument in arguments) {
+ for (var argument in typeArguments) {
hasArguments = hasArguments || !argument.isDynamic;
allArgumentsVisible = allArgumentsVisible &&
_getVisibleType(argument, methodBeingCopied: methodBeingCopied) !=
@@ -1226,8 +1258,8 @@
// Write type arguments only if they are useful.
if (hasArguments && allArgumentsVisible) {
write('<');
- for (var i = 0; i < arguments.length; i++) {
- var argument = arguments[i];
+ for (var i = 0; i < typeArguments.length; i++) {
+ var argument = typeArguments[i];
if (i != 0) {
write(', ');
}
@@ -1237,12 +1269,12 @@
write('>');
}
}
+ }
+ void _writeTypeNullability(DartType type) {
if (type.nullabilitySuffix == NullabilitySuffix.question) {
write('?');
}
-
- return true;
}
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 6d37cfe..430be10 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -106,6 +106,14 @@
var edit = getEdit(builder);
expect(edit.replacement, equalsIgnoringWhitespace('required a'));
}
+
+ Future<void> test_writeType_Never_none() async {
+ await _assertWriteType('Never');
+ }
+
+ Future<void> test_writeType_Never_question() async {
+ await _assertWriteType('Never?');
+ }
}
class DartEditBuilderImplTest extends AbstractContextTest
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 84e0ea0..0362d62 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -395,7 +395,7 @@
// case) `Function(T)`. Without this we would get `Function<T>(T)` which
// is incorrect. This is a known issue with `.type` on typedefs in the
// analyzer.
- element = (element as FunctionTypeAliasElement).aliasedElement;
+ element = (element as TypeAliasElement).aliasedElement;
}
var target = NullabilityNodeTarget.element(element, _getLineInfo);
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index f6a97c1..322f952 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,11 +1,15 @@
# Changelog
-## 6.1.0-nullsafety.0
+## 6.1.0
- Added `identityHashCode` property to `HeapSnapshotObject`, which can be used to compare
objects across heap snapshots.
- Added `successors` iterable to `HeapSnapshotObject`, which provides a convenient way to
access children of a given object.
- Added `klass` getter to `HeapSnapshotObject`.
+- Fixed issue where `null` could be returned instead of `InstanceRef` of type `Null`.
+
+## 6.0.1
+- Stable null-safe release.
## 6.0.1-nullsafety.1
- Fix issue where some `Instance` properties were not being populated correctly.
@@ -16,6 +20,7 @@
## 6.0.0-nullsafety.4
- Fixed issue where response parsing could fail for `SourceReportRange.coverage`
if no coverage information was provided.
+
## 6.0.0-nullsafety.3
- Fixed issue where `Response.type` and classes which override `Response.type` were
returning the name of the `package:vm_service` reference object (e.g., InstanceRef) instead of
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index fa49390..cc0643e 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -55,7 +55,8 @@
} else {
return null;
}
- } else if (_isNullInstance(json) && (!expectedTypes.contains(type))) {
+ } else if (_isNullInstance(json) &&
+ (!expectedTypes.contains('InstanceRef'))) {
// Replace null instances with null when we don't expect an instance to
// be returned.
return null;
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 3e87a37..7760e11 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
A library to communicate with a service implementing the Dart VM
service protocol.
-version: 6.1.0-nullsafety.0
+version: 6.1.0-dev
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
@@ -13,10 +13,10 @@
dependencies:
dev_dependencies:
- async: ^2.5.0-nullsafety.3
+ async: ^2.5.0
markdown: ^4.0.0-nullsafety.0
mockito: ^5.0.0-nullsafety.1
- path: ^1.8.0-nullsafety.3
+ path: ^1.8.0
pedantic: ^1.10.0-nullsafety.3
pub_semver: ^2.0.0-nullsafety.0
test: ^1.16.0-nullsafety.13
diff --git a/pkg/vm_service/test/regress_44842_test.dart b/pkg/vm_service/test/regress_44842_test.dart
new file mode 100644
index 0000000..8a794b4
--- /dev/null
+++ b/pkg/vm_service/test/regress_44842_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+const Map<String, dynamic> kNullInstance = {
+ 'type': '@Instance',
+ 'id': 'instance/123',
+ 'kind': 'Null',
+ 'class': {
+ 'type': '@Class',
+ 'id': 'object/0',
+ 'name': 'Null',
+ }
+};
+
+void main() {
+ test('Ensure createServiceObject handles Null @Instances properly', () {
+ expect(createServiceObject(kNullInstance, ['InstanceRef']), isNotNull);
+ expect(createServiceObject(kNullInstance, ['ClassRef']), isNull);
+ });
+}
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 81b2970..3f4f20c 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -535,7 +535,7 @@
} else {
return null;
}
- } else if (_isNullInstance(json) && (!expectedTypes.contains(type))) {
+ } else if (_isNullInstance(json) && (!expectedTypes.contains('InstanceRef'))) {
// Replace null instances with null when we don't expect an instance to
// be returned.
return null;
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index c42fa15..44d6148 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -27,15 +27,23 @@
public:
explicit RegisterRunningIsolatesVisitor(Thread* thread)
: IsolateVisitor(),
+ zone_(thread->zone()),
register_function_(Function::Handle(thread->zone())),
- service_isolate_(thread->isolate()) {
- }
+ service_isolate_(thread->isolate()) {}
virtual void VisitIsolate(Isolate* isolate) {
- ServiceIsolate::RegisterRunningIsolate(isolate);
+ isolate_ports_.Add(isolate->main_port());
+ isolate_names_.Add(&String::Handle(zone_, String::New(isolate->name())));
+ }
+
+ void RegisterIsolates() {
+ ServiceIsolate::RegisterRunningIsolates(isolate_ports_, isolate_names_);
}
private:
+ Zone* zone_;
+ GrowableArray<Dart_Port> isolate_ports_;
+ GrowableArray<const String*> isolate_names_;
Function& register_function_;
Isolate* service_isolate_;
};
@@ -90,6 +98,7 @@
OS::PrintErr("vm-service: Registering running isolates.\n");
}
Isolate::VisitIsolates(®ister_isolates);
+ register_isolates.RegisterIsolates();
#endif
return Object::null();
}
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index 5e1a8c9..9596513 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
final result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], 'Version');
expect(result['major'], 3);
- expect(result['minor'], 42);
+ expect(result['minor'], 43);
expect(result['_privateMajor'], 0);
expect(result['_privateMinor'], 0);
},
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index 5160f96..9e2bc43 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
var result = await vm.invokeRpcNoUpgrade('getVersion', {});
expect(result['type'], equals('Version'));
expect(result['major'], equals(3));
- expect(result['minor'], equals(42));
+ expect(result['minor'], equals(43));
expect(result['_privateMajor'], equals(0));
expect(result['_privateMinor'], equals(0));
},
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0390269..bd3b5d4 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -38,30 +38,6 @@
virtual void AddFrame(const Object& code, const Smi& offset) = 0;
};
-class RegularStackTraceBuilder : public StackTraceBuilder {
- public:
- explicit RegularStackTraceBuilder(Zone* zone)
- : code_list_(
- GrowableObjectArray::Handle(zone, GrowableObjectArray::New())),
- pc_offset_list_(
- GrowableObjectArray::Handle(zone, GrowableObjectArray::New())) {}
- ~RegularStackTraceBuilder() {}
-
- const GrowableObjectArray& code_list() const { return code_list_; }
- const GrowableObjectArray& pc_offset_list() const { return pc_offset_list_; }
-
- virtual void AddFrame(const Object& code, const Smi& offset) {
- code_list_.Add(code);
- pc_offset_list_.Add(offset);
- }
-
- private:
- const GrowableObjectArray& code_list_;
- const GrowableObjectArray& pc_offset_list_;
-
- DISALLOW_COPY_AND_ASSIGN(RegularStackTraceBuilder);
-};
-
class PreallocatedStackTraceBuilder : public StackTraceBuilder {
public:
explicit PreallocatedStackTraceBuilder(const Instance& stacktrace)
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index f66a951..00a3f32 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
namespace dart {
#define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 42
+#define SERVICE_PROTOCOL_MINOR_VERSION 43
class Array;
class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index 20deaed..39e71d2 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.42
+# Dart VM Service Protocol 3.43
> Please post feedback to the [observatory-discuss group][discuss-list]
-This document describes of _version 3.42_ of the Dart VM Service Protocol. This
+This document describes of _version 3.43_ of the Dart VM Service Protocol. This
protocol is used to communicate with a running Dart Virtual Machine.
To use the Service Protocol, start the VM with the *--observe* flag.
@@ -3948,5 +3948,6 @@
3.40 | Added `IsolateFlag` object and `isolateFlags` property to `Isolate`.
3.41 | Added `PortList` object, `ReceivePort` `InstanceKind`, and `getPorts` RPC.
3.42 | Added `limit` optional parameter to `getStack` RPC.
+3.43 | Updated heap snapshot format to include identity hash codes.
[discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index e01ccd4..07e58ba 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -583,42 +583,49 @@
ServiceIsolate::SetServicePort(port);
}
-void ServiceIsolate::RegisterRunningIsolate(Isolate* isolate) {
- ASSERT(ServiceIsolate::IsServiceIsolate(Isolate::Current()));
+void ServiceIsolate::RegisterRunningIsolates(
+ const GrowableArray<Dart_Port>& isolate_ports,
+ const GrowableArray<const String*>& isolate_names) {
+ auto thread = Thread::Current();
+ auto zone = thread->zone();
- // Get library.
+ ASSERT(ServiceIsolate::IsServiceIsolate(thread->isolate()));
+
+ // Obtain "_registerIsolate" function to call.
const String& library_url = Symbols::DartVMService();
ASSERT(!library_url.IsNull());
- // TODO(bkonyi): hoist Thread::Current()
const Library& library =
- Library::Handle(Library::LookupLibrary(Thread::Current(), library_url));
+ Library::Handle(zone, Library::LookupLibrary(thread, library_url));
ASSERT(!library.IsNull());
- // Get function.
- const String& function_name = String::Handle(String::New("_registerIsolate"));
+ const String& function_name =
+ String::Handle(zone, String::New("_registerIsolate"));
ASSERT(!function_name.IsNull());
const Function& register_function_ =
- Function::Handle(library.LookupFunctionAllowPrivate(function_name));
+ Function::Handle(zone, library.LookupFunctionAllowPrivate(function_name));
ASSERT(!register_function_.IsNull());
- // Setup arguments for call.
- Dart_Port port_id = isolate->main_port();
- const Integer& port_int = Integer::Handle(Integer::New(port_id));
- ASSERT(!port_int.IsNull());
- const SendPort& send_port = SendPort::Handle(SendPort::New(port_id));
- const String& name = String::Handle(String::New(isolate->name()));
- ASSERT(!name.IsNull());
- const Array& args = Array::Handle(Array::New(3));
- ASSERT(!args.IsNull());
- args.SetAt(0, port_int);
- args.SetAt(1, send_port);
- args.SetAt(2, name);
- const Object& r =
- Object::Handle(DartEntry::InvokeFunction(register_function_, args));
- if (FLAG_trace_service) {
- OS::PrintErr("vm-service: Isolate %s %" Pd64 " registered.\n",
- name.ToCString(), port_id);
+ Integer& port_int = Integer::Handle(zone);
+ SendPort& send_port = SendPort::Handle(zone);
+ Array& args = Array::Handle(zone, Array::New(3));
+ Object& result = Object::Handle(zone);
+
+ ASSERT(isolate_ports.length() == isolate_names.length());
+ for (intptr_t i = 0; i < isolate_ports.length(); ++i) {
+ const Dart_Port port_id = isolate_ports[i];
+ const String& name = *isolate_names[i];
+
+ port_int = Integer::New(port_id);
+ send_port = SendPort::New(port_id);
+ args.SetAt(0, port_int);
+ args.SetAt(1, send_port);
+ args.SetAt(2, name);
+ result = DartEntry::InvokeFunction(register_function_, args);
+ if (FLAG_trace_service) {
+ OS::PrintErr("vm-service: Isolate %s %" Pd64 " registered.\n",
+ name.ToCString(), port_id);
+ }
+ ASSERT(!result.IsError());
}
- ASSERT(!r.IsError());
}
void ServiceIsolate::VisitObjectPointers(ObjectPointerVisitor* visitor) {}
diff --git a/runtime/vm/service_isolate.h b/runtime/vm/service_isolate.h
index 5411bb9..0fc018a 100644
--- a/runtime/vm/service_isolate.h
+++ b/runtime/vm/service_isolate.h
@@ -50,7 +50,9 @@
static void BootVmServiceLibrary();
- static void RegisterRunningIsolate(Isolate* isolate);
+ static void RegisterRunningIsolates(
+ const GrowableArray<Dart_Port>& isolate_ports,
+ const GrowableArray<const String*>& isolate_names);
static void RequestServerInfo(const SendPort& sp);
static void ControlWebServer(const SendPort& sp,
diff --git a/sdk/lib/io/file.dart b/sdk/lib/io/file.dart
index 14d68bb..07c3aeb 100644
--- a/sdk/lib/io/file.dart
+++ b/sdk/lib/io/file.dart
@@ -291,7 +291,7 @@
/// with a [File] for the renamed file.
///
/// If [newPath] is a relative path, it is resolved against
- /// the current working directory ([Directory.cwd]).
+ /// the current working directory ([Directory.current]).
/// This means that simply changing the name of a file,
/// but keeping it the original directory,
/// requires creating a new complete path with the new name
@@ -306,7 +306,7 @@
/// ```
/// On some platforms, a rename operation cannot move a file between
/// different file systems. If that is the case, instead [copy] the
- /// file to the new location and then [remove] the original.
+ /// file to the new location and then remove the original.
///
/// If [newPath] identifies an existing file, that file is
/// removed first. If [newPath] identifies an existing directory, the
@@ -318,7 +318,7 @@
/// Returns a [File] for the renamed file.
///
/// If [newPath] is a relative path, it is resolved against
- /// the current working directory ([Directory.cwd]).
+ /// the current working directory ([Directory.current]).
/// This means that simply changing the name of a file,
/// but keeping it the original directory,
/// requires creating a new complete path with the new name
@@ -333,7 +333,7 @@
/// ```
/// On some platforms, a rename operation cannot move a file between
/// different file systems. If that is the case, instead [copySync] the
- /// file to the new location and then [removeSync] the original.
+ /// file to the new location and then [deleteSync] the original.
///
/// If [newPath] identifies an existing file, that file is
/// removed first. If [newPath] identifies an existing directory the
@@ -343,7 +343,7 @@
/// Copies this file.
///
/// If [newPath] is a relative path, it is resolved against
- /// the current working directory ([Directory.cwd]).
+ /// the current working directory ([Directory.current]).
///
/// Returns a `Future<File>` that completes
/// with a [File] for the copied file.
@@ -356,7 +356,7 @@
/// Synchronously copies this file.
///
/// If [newPath] is a relative path, it is resolved against
- /// the current working directory ([Directory.cwd]).
+ /// the current working directory ([Directory.current]).
///
/// Returns a [File] for the copied file.
///
diff --git a/sdk/lib/io/io.dart b/sdk/lib/io/io.dart
index 5be8785..9a89e63 100644
--- a/sdk/lib/io/io.dart
+++ b/sdk/lib/io/io.dart
@@ -47,8 +47,8 @@
///
/// To get information about a path,
/// you can use the [FileSystemEntity] static methods
-/// such as [FileSystemEntitiy.isDirectory], [FileSystemEntitiy.isFile],
-/// and [FileSystemEntitiy.exists].
+/// such as [FileSystemEntity.isDirectory], [FileSystemEntity.isFile],
+/// and [FileSystemEntity.exists].
/// Because file system access involves I/O, these methods
/// are asynchronous and return a [Future].
/// ```dart
@@ -124,7 +124,7 @@
/// ```
/// The client connects to the [WebSocket] using the [WebSocket.connect] method
/// and a URI that uses the Web Socket protocol.
-/// The client can write to the [WebSocket] with the [Websocket.add] method.
+/// The client can write to the [WebSocket] with the [WebSocket.add] method.
/// For example,
/// ```dart
/// var socket = await WebSocket.connect('ws://127.0.0.1:4040/ws');
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index a0eea00..22d57dd 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -310,11 +310,11 @@
/// the system.
///
/// The optional argument [shared] specifies whether additional ServerSocket
- /// objects can bind to the same combination of [address], [port] [and] [v6Only].
- /// If [shared] is `true` and more [ServerSockets] from this isolate or other
- /// isolates are bound to the port, then the incoming connections will be
- /// distributed among all the bound [ServerSockets]. Connections can be
- /// distributed over multiple isolates this way.
+ /// objects can bind to the same combination of [address], [port] and
+ /// [v6Only]. If [shared] is `true` and more server sockets from this
+ /// isolate or other isolates are bound to the port, then the incoming
+ /// connections will be distributed among all the bound server sockets.
+ /// Connections can be distributed over multiple isolates this way.
static Future<ServerSocket> bind(address, int port,
{int backlog = 0, bool v6Only = false, bool shared = false}) {
final IOOverrides? overrides = IOOverrides.current;
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 20d17f8..df48112 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -10,6 +10,7 @@
/// import 'dart:typed_data';
/// ```
/// {@category Core}
+/// {@canonicalFor dart:_internal.BytesBuilder}
library dart.typed_data;
import "dart:_internal" show Since, UnmodifiableListBase;
diff --git a/sdk/lib/vmservice/message.dart b/sdk/lib/vmservice/message.dart
index 5b07cea..a3a0e61 100644
--- a/sdk/lib/vmservice/message.dart
+++ b/sdk/lib/vmservice/message.dart
@@ -155,10 +155,15 @@
return new_list;
}
- Future<Response> sendToIsolate(SendPort sendPort) {
+ Future<Response> sendToIsolate(
+ List<RawReceivePort> ports, SendPort sendPort) {
final receivePort = RawReceivePort(null, 'Isolate Message');
+ // Keep track of receive port associated with the request so we can close
+ // it if isolate exits before sending a response.
+ ports.add(receivePort);
receivePort.handler = (value) {
receivePort.close();
+ ports.remove(receivePort);
_setResponseFromPort(value);
};
final keys = _makeAllString(params.keys.toList(growable: false));
@@ -172,6 +177,7 @@
..[5] = values;
if (!sendIsolateServiceMessage(sendPort, request)) {
receivePort.close();
+ ports.remove(receivePort);
_completer.complete(Response.internalError(
'could not send message [${serial}] to isolate'));
}
diff --git a/sdk/lib/vmservice/running_isolate.dart b/sdk/lib/vmservice/running_isolate.dart
index 8a6dd36..3902193 100644
--- a/sdk/lib/vmservice/running_isolate.dart
+++ b/sdk/lib/vmservice/running_isolate.dart
@@ -8,15 +8,22 @@
final int portId;
final SendPort sendPort;
final String name;
+ final pendingMessagesReceivePorts = <RawReceivePort>[];
RunningIsolate(this.portId, this.sendPort, this.name);
+ void onIsolateExit() {
+ pendingMessagesReceivePorts.forEach((port) {
+ (port as RawReceivePort).close();
+ });
+ }
+
String get serviceId => 'isolates/$portId';
@override
Future<Response> routeRequest(VMService service, Message message) {
// Send message to isolate.
- return message.sendToIsolate(sendPort);
+ return message.sendToIsolate(pendingMessagesReceivePorts, sendPort);
}
@override
diff --git a/sdk/lib/vmservice/running_isolates.dart b/sdk/lib/vmservice/running_isolates.dart
index 03a6811..f9db4a5 100644
--- a/sdk/lib/vmservice/running_isolates.dart
+++ b/sdk/lib/vmservice/running_isolates.dart
@@ -22,7 +22,7 @@
if (_rootPortId == portId) {
_rootPortId = null;
}
- isolates.remove(portId);
+ (isolates.remove(portId))?.onIsolateExit();
}
@override
diff --git a/tools/VERSION b/tools/VERSION
index a403296..16de12d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 284
+PRERELEASE 285
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 4093a81..e8829df 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -623,6 +623,24 @@
]
}
},
+ "dart2js-o0-(linux|mac|win)-d8": {
+ "options": {
+ "builder-tag": "dart2js_o0",
+ "use-sdk": true,
+ "dart2js-options": [
+ "-O0"
+ ]
+ }
+ },
+ "dart2js-modern-(linux|mac|win)-d8": {
+ "options": {
+ "builder-tag": "dart2js_modern",
+ "use-sdk": true,
+ "dart2js-options": [
+ "--no-legacy-javascript"
+ ]
+ }
+ },
"dart2js-hostasserts-(linux|mac|win)-(ia32|x64)-d8": {
"options": {
"host-checked": true,
@@ -2444,6 +2462,22 @@
"--dart2js-batch",
"dart2js_2"
]
+ },
+ {
+ "name": "dart2js -O0 smoke tests",
+ "arguments": [
+ "-ndart2js-o0-linux-d8",
+ "--dart2js-batch",
+ "dart2js_2"
+ ]
+ },
+ {
+ "name": "dart2js --no-legacy-javascript smoke tests",
+ "arguments": [
+ "-ndart2js-modern-linux-d8",
+ "--dart2js-batch",
+ "dart2js_2"
+ ]
}
]
},
@@ -3250,7 +3284,7 @@
"script": "out/ReleaseX64/dart-sdk/bin/dartdoc",
"arguments": [
"--exclude",
- "dart:ffi,dart:html,dart:web_sql,dart:web_audio,dart:svg,dart:indexed_db,dart:io",
+ "dart:ffi,dart:html,dart:web_sql,dart:web_audio,dart:svg,dart:indexed_db",
"--sdk-docs",
"--no-generate-docs"
],