Version 2.16.0-158.0.dev
Merge commit '44ba8ecdb2e5e9b24de9b63a6ab307240458f991' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index c3a351b..4932c25 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -28,6 +28,7 @@
import 'package:analysis_server/src/services/completion/dart/relevance_tables.g.dart';
import 'package:analysis_server/src/services/completion/dart/static_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/dart/super_formal_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
@@ -155,6 +156,7 @@
if (enableOverrideContributor) OverrideContributor(request, builder),
RedirectingContributor(request, builder),
StaticMemberContributor(request, builder),
+ SuperFormalContributor(request, builder),
TypeMemberContributor(request, builder),
if (enableUriContributor) UriContributor(request, builder),
VariableNameContributor(request, builder),
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 864f1f9..1dbfe52 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -352,6 +352,9 @@
var constructorDeclaration =
node.thisOrAncestorOfType<ConstructorDeclaration>();
if (constructorDeclaration != null) {
+ if (request.featureSet.isEnabled(Feature.super_parameters)) {
+ _addSuggestion(Keyword.SUPER);
+ }
_addSuggestion(Keyword.THIS);
}
final entity = this.entity;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index a441aa0..b4c063c 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -877,6 +877,17 @@
relevance: relevance));
}
+ /// Add a suggestion to reference a [parameter] in a super formal parameter.
+ void suggestSuperFormalParameter(ParameterElement parameter) {
+ _add(
+ _createSuggestion(
+ parameter,
+ kind: CompletionSuggestionKind.IDENTIFIER,
+ relevance: Relevance.superFormalParameter,
+ ),
+ );
+ }
+
/// Add a suggestion for a top-level [function]. If a [kind] is provided it
/// will be used as the kind for the suggestion. If the function can only be
/// referenced using a prefix, then the [prefix] should be provided.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart
new file mode 100644
index 0000000..fdd99bf
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/completion/dart/super_formal_contributor.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:collection/collection.dart';
+
+/// A contributor that produces suggestions for super formal parameters that
+/// are based on the parameters declared by the invoked super-constructor.
+/// The enclosing declaration is expected to be a constructor.
+class SuperFormalContributor extends DartCompletionContributor {
+ SuperFormalContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
+ @override
+ Future<void> computeSuggestions() async {
+ var node = request.target.containingNode;
+ if (node is! SuperFormalParameter) {
+ return;
+ }
+
+ var element = node.declaredElement as SuperFormalParameterElementImpl;
+
+ var constructor = node.thisOrAncestorOfType<ConstructorDeclaration>();
+ if (constructor == null) {
+ return;
+ }
+
+ var constructorElement = constructor.declaredElement;
+ constructorElement as ConstructorElementImpl;
+
+ var superConstructor = constructorElement.superConstructor;
+ if (superConstructor == null) {
+ return;
+ }
+
+ if (node.isNamed) {
+ var superConstructorInvocation = constructor.initializers
+ .whereType<SuperConstructorInvocation>()
+ .singleOrNull;
+ var specified = <String>{
+ ...constructorElement.parameters.map((e) => e.name),
+ ...?superConstructorInvocation?.argumentList.arguments
+ .whereType<NamedExpression>()
+ .map((e) => e.name.label.name),
+ };
+ for (var superParameter in superConstructor.parameters) {
+ if (superParameter.isNamed &&
+ !specified.contains(superParameter.name)) {
+ builder.suggestSuperFormalParameter(superParameter);
+ }
+ }
+ }
+
+ if (node.isPositional) {
+ var indexOfThis = element.indexIn(constructorElement);
+ var superPositionalList = superConstructor.parameters
+ .where((parameter) => parameter.isPositional)
+ .toList();
+ if (indexOfThis >= 0 && indexOfThis < superPositionalList.length) {
+ var superPositional = superPositionalList[indexOfThis];
+ builder.suggestSuperFormalParameter(superPositional);
+ }
+ }
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index 1b58a84..34e4921 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -657,6 +657,14 @@
DataDriven.newInstance,
ImportLibrary.forType,
],
+ CompileTimeErrorCode
+ .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_MISSING_REQUIRED_ARGUMENT: [
+ AddSuperConstructorInvocation.newInstance,
+ ],
+ CompileTimeErrorCode
+ .IMPLICIT_UNNAMED_SUPER_CONSTRUCTOR_INVOCATION_NOT_ENOUGH_POSITIONAL_ARGUMENTS: [
+ AddSuperConstructorInvocation.newInstance,
+ ],
CompileTimeErrorCode.INVALID_ANNOTATION: [
ImportLibrary.forTopLevelVariable,
ImportLibrary.forType,
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 432a8b3..c86b091 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -50,6 +50,7 @@
List<String> get experiments => [
EnableString.constructor_tearoffs,
EnableString.named_arguments_anywhere,
+ EnableString.super_parameters,
];
String get latestLanguageVersion =>
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 8128659..7bf72fe 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -55,7 +55,7 @@
..docSummary.isEqualTo('aaa')
..hasSelection(offset: 5)
..element.isNotNull.which((e) => e
- ..isParameter
+ ..kind.isParameter
..name.isEqualTo('fff'))
]);
}
@@ -79,7 +79,7 @@
..docSummary.isNull
..hasSelection(offset: 5)
..element.isNotNull.which((e) => e
- ..isParameter
+ ..kind.isParameter
..name.isEqualTo('fff'))
]);
}
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_check.dart b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
index f9cdaf1..4c15bd2 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_check.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_check.dart
@@ -55,6 +55,20 @@
extension CompletionResponseExtension
on CheckTarget<CompletionResponseForTesting> {
+ CheckTarget<int> get replacementLength {
+ return nest(
+ value.replacementLength,
+ (selected) => 'has replacementLength ${valueStr(selected)}',
+ );
+ }
+
+ CheckTarget<int> get replacementOffset {
+ return nest(
+ value.replacementOffset,
+ (selected) => 'has replacementOffset ${valueStr(selected)}',
+ );
+ }
+
CheckTarget<List<CompletionSuggestionForTesting>> get suggestions {
var suggestions = value.suggestions.map((e) {
return CompletionSuggestionForTesting(
@@ -67,6 +81,19 @@
(selected) => 'suggestions ${valueStr(selected)}',
);
}
+
+ /// Check that the replacement offset is the completion request offset,
+ /// and the length of the replacement is zero.
+ void hasEmptyReplacement() {
+ hasReplacement(left: 0, right: 0);
+ }
+
+ /// Check that the replacement offset is the completion request offset
+ /// minus [left], and the length of the replacement is `left + right`.
+ void hasReplacement({int left = 0, int right = 0}) {
+ replacementOffset.isEqualTo(value.requestOffset - left);
+ replacementLength.isEqualTo(left + right);
+ }
}
extension CompletionSuggestionExtension
@@ -113,6 +140,23 @@
);
}
+ void get isField {
+ kind.isIdentifier;
+ element.isNotNull.kind.isField;
+ }
+
+ void get isParameter {
+ kind.isIdentifier;
+ element.isNotNull.kind.isParameter;
+ }
+
+ CheckTarget<CompletionSuggestionKind> get kind {
+ return nest(
+ value.suggestion.kind,
+ (selected) => 'has kind ${valueStr(selected)}',
+ );
+ }
+
CheckTarget<String?> get parameterType {
return nest(
value.suggestion.parameterType,
@@ -136,6 +180,13 @@
);
}
+ CheckTarget<String?> get returnType {
+ return nest(
+ value.suggestion.returnType,
+ (selected) => 'has returnType ${valueStr(selected)}',
+ );
+ }
+
CheckTarget<int> get selectionLength {
return nest(
value.suggestion.selectionLength,
@@ -169,8 +220,22 @@
}
}
+extension CompletionSuggestionKindExtension
+ on CheckTarget<CompletionSuggestionKind> {
+ void get isIdentifier {
+ isEqualTo(CompletionSuggestionKind.IDENTIFIER);
+ }
+}
+
extension CompletionSuggestionsExtension
on CheckTarget<Iterable<CompletionSuggestionForTesting>> {
+ CheckTarget<List<String>> get completions {
+ return nest(
+ value.map((e) => e.suggestion.completion).toList(),
+ (selected) => 'completions ${valueStr(selected)}',
+ );
+ }
+
CheckTarget<Iterable<CompletionSuggestionForTesting>> get namedArguments {
var result = value
.where((suggestion) =>
@@ -185,10 +250,6 @@
}
extension ElementExtension on CheckTarget<Element> {
- void get isParameter {
- kind.isEqualTo(ElementKind.PARAMETER);
- }
-
CheckTarget<ElementKind> get kind {
return nest(
value.kind,
@@ -203,3 +264,13 @@
);
}
}
+
+extension ElementKindExtension on CheckTarget<ElementKind> {
+ void get isField {
+ isEqualTo(ElementKind.FIELD);
+ }
+
+ void get isParameter {
+ isEqualTo(ElementKind.PARAMETER);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index ff209f1..d63a695 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -6,9 +6,10 @@
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:test/test.dart';
+import 'package:analyzer_utilities/check/check.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'completion_check.dart';
import 'completion_contributor_util.dart';
void main() {
@@ -31,183 +32,120 @@
Future<void> test_mixin_constructor() async {
addTestSource('''
mixin M {
+ var field = 0;
M(this.^);
}
''');
- await computeSuggestions();
- expect(suggestions, isEmpty);
+
+ var response = await computeSuggestions2();
+ check(response).suggestions.isEmpty;
}
- Future<void> test_ThisExpression_constructor_param() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
+ Future<void> test_replacement_left() async {
addTestSource('''
- main() { }
- class I {X get f => new A();get _g => new A();}
- class A implements I {
- A(this.^) {}
- A.z() {}
- var b; X _c; static sb;
- X get d => new A();get _e => new A();
- // no semicolon between completion point and next statement
- set s1(I x) {} set _s2(I x) {m(null);}
- m(X x) {} I _n(X x) {}}
- class X{}''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestField('b', null);
- assertSuggestField('_c', 'X');
- assertNotSuggested('sb');
- assertNotSuggested('d');
- assertNotSuggested('_e');
- assertNotSuggested('f');
- assertNotSuggested('_g');
- assertNotSuggested('m');
- assertNotSuggested('_n');
- assertNotSuggested('s1');
- assertNotSuggested('_s2');
- assertNotSuggested('z');
- assertNotSuggested('I');
- assertNotSuggested('A');
- assertNotSuggested('X');
- assertNotSuggested('Object');
- assertNotSuggested('==');
+class A {
+ var field = 0;
+ A(this.f^);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasReplacement(left: 1)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('field')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
}
- Future<void> test_ThisExpression_constructor_param2() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
+ Future<void> test_replacement_right() async {
addTestSource('''
- main() { }
- class I {X get f => new A();get _g => new A();}
- class A implements I {
- A(this.b^) {}
- A.z() {}
- var b; X _c;
- X get d => new A();get _e => new A();
- // no semicolon between completion point and next statement
- set s1(I x) {} set _s2(I x) {m(null);}
- m(X x) {} I _n(X x) {}}
- class X{}''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset - 1);
- expect(replacementLength, 1);
- assertSuggestField('b', null);
- assertSuggestField('_c', 'X');
- assertNotSuggested('d');
- assertNotSuggested('_e');
- assertNotSuggested('f');
- assertNotSuggested('_g');
- assertNotSuggested('m');
- assertNotSuggested('_n');
- assertNotSuggested('s1');
- assertNotSuggested('_s2');
- assertNotSuggested('z');
- assertNotSuggested('I');
- assertNotSuggested('A');
- assertNotSuggested('X');
- assertNotSuggested('Object');
- assertNotSuggested('==');
+class A {
+ var field = 0;
+ A(this.^f);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasReplacement(right: 1)
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('field')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
}
- Future<void> test_ThisExpression_constructor_param3() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
+ Future<void> test_suggestions_onlyLocal() async {
addTestSource('''
- main() { }
- class I {X get f => new A();get _g => new A();}
- class A implements I {
- A(this.^b) {}
- A.z() {}
- var b; X _c;
- X get d => new A();get _e => new A();
- // no semicolon between completion point and next statement
- set s1(I x) {} set _s2(I x) {m(null);}
- m(X x) {} I _n(X x) {}}
- class X{}''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 1);
- assertSuggestField('b', null);
- assertSuggestField('_c', 'X');
- assertNotSuggested('d');
- assertNotSuggested('_e');
- assertNotSuggested('f');
- assertNotSuggested('_g');
- assertNotSuggested('m');
- assertNotSuggested('_n');
- assertNotSuggested('s1');
- assertNotSuggested('_s2');
- assertNotSuggested('z');
- assertNotSuggested('I');
- assertNotSuggested('A');
- assertNotSuggested('X');
- assertNotSuggested('Object');
- assertNotSuggested('==');
+class A {
+ var inherited = 0;
+}
+
+class B extends A {
+ var first = 0;
+ var second = 1.2;
+ B(this.^);
+ B.constructor() {}
+ void method() {}
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isField
+ ..returnType.isEqualTo('double'),
+ ]);
}
- Future<void> test_ThisExpression_constructor_param4() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
+ Future<void> test_suggestions_onlyNotSpecified_optionalNamed() async {
addTestSource('''
- main() { }
- class I {X get f => new A();get _g => new A();}
- class A implements I {
- A(this.b, this.^) {}
- A.z() {}
- var b; X _c;
- X get d => new A();get _e => new A();
- // no semicolon between completion point and next statement
- set s1(I x) {} set _s2(I x) {m(null);}
- m(X x) {} I _n(X x) {}}
- class X{}''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertNotSuggested('b');
- assertSuggestField('_c', 'X');
- assertNotSuggested('d');
- assertNotSuggested('_e');
- assertNotSuggested('f');
- assertNotSuggested('_g');
- assertNotSuggested('m');
- assertNotSuggested('_n');
- assertNotSuggested('s1');
- assertNotSuggested('_s2');
- assertNotSuggested('z');
- assertNotSuggested('I');
- assertNotSuggested('A');
- assertNotSuggested('X');
- assertNotSuggested('Object');
- assertNotSuggested('==');
+class Point {
+ final int x;
+ final int y;
+ Point({this.x, this.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('y')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
}
- Future<void> test_ThisExpression_constructor_param_optional() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
+ Future<void> test_suggestions_onlyNotSpecified_requiredPositional() async {
addTestSource('''
- main() { }
- class Point {
- int x;
- int y;
- Point({this.x, this.^}) {}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestField('y', 'int');
- assertNotSuggested('x');
- }
+class Point {
+ final int x;
+ final int y;
+ Point(this.x, this.^);
+}
+''');
- Future<void> test_ThisExpression_constructor_param_positional() async {
- // SimpleIdentifier FieldFormalParameter FormalParameterList
- addTestSource('''
- main() { }
- class Point {
- int x;
- int y;
- Point({this.x, this.^}) {}
- ''');
- await computeSuggestions();
- expect(replacementOffset, completionOffset);
- expect(replacementLength, 0);
- assertSuggestField('y', 'int');
- assertNotSuggested('x');
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('y')
+ ..isField
+ ..returnType.isEqualTo('int'),
+ ]);
}
}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 585012d..c2c05ab 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -74,6 +74,17 @@
var keywords = <Keyword>[
Keyword.COVARIANT,
Keyword.DYNAMIC,
+ Keyword.SUPER,
+ Keyword.THIS,
+ Keyword.VOID
+ ];
+ return keywords;
+ }
+
+ List<Keyword> get constructorParameter_language215 {
+ var keywords = <Keyword>[
+ Keyword.COVARIANT,
+ Keyword.DYNAMIC,
Keyword.THIS,
Keyword.VOID
];
@@ -1018,6 +1029,17 @@
assertSuggestKeywords(constructorParameter);
}
+ Future<void> test_constructor_param_noPrefix_language215() async {
+ addTestSource(r'''
+// @dart = 2.15
+class A {
+ A(^);
+}
+''');
+ await computeSuggestions();
+ assertSuggestKeywords(constructorParameter_language215);
+ }
+
Future<void> test_constructor_param_prefix() async {
addTestSource('class A { A(t^) {}}');
await computeSuggestions();
diff --git a/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
new file mode 100644
index 0000000..ff135e7
--- /dev/null
+++ b/pkg/analysis_server/test/services/completion/dart/super_formal_contributor_test.dart
@@ -0,0 +1,471 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
+import 'package:analysis_server/src/services/completion/dart/super_formal_contributor.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'completion_check.dart';
+import 'completion_contributor_util.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(SuperFormalContributorTest);
+ });
+}
+
+@reflectiveTest
+class SuperFormalContributorTest extends DartCompletionContributorTest {
+ @override
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return SuperFormalContributor(request, builder);
+ }
+
+ Future<void> test_explicit_optionalNamed_hasArgument_named() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.^}) : super(first: 0);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_explicit_optionalNamed_hasArgument_positional() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.^}) : super(0);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ /// It is an error, but the user already typed `super.`, so maybe do it.
+ Future<void> test_explicit_requiredPositional_hasArgument_positional() async {
+ addTestSource('''
+class A {
+ A(int first, double second);
+}
+
+class B extends A {
+ B(super.^) : super(0);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_explicitNamed_noOther() async {
+ addTestSource('''
+class A {
+ A.named(int first, double second);
+ A(int third)
+}
+
+class B extends A {
+ B(super.^) : super.named();
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_notSuper() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({int a, super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_notSuper2() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({int first, super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_super() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.first, super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasNamed_super2() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B({super.second, super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasPositional_notSuper() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B(int a, {super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_hasPositional_super() async {
+ addTestSource('''
+class A {
+ A({int first, double second});
+}
+
+class B extends A {
+ B(super.first, {super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalNamed_noOther() async {
+ addTestSource('''
+class A {
+ A(bool first, {int second, double third});
+}
+
+class B extends A {
+ B({super.^});
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ (suggestion) => suggestion
+ ..completion.isEqualTo('third')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_notSuper() async {
+ addTestSource('''
+class A {
+ A([int first, double second]);
+}
+
+class B extends A {
+ B([int one, super.^]);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_super() async {
+ addTestSource('''
+class A {
+ A([int first, double second, bool third]);
+}
+
+class B extends A {
+ B([super.one, super.^]);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_hasPositional_super2() async {
+ addTestSource('''
+class A {
+ A([int first, double second, bool third]);
+}
+
+class B extends A {
+ B([super.second, super.^]);
+}
+''');
+
+ // It does not matter what is the name of the positional parameter.
+ // Here `super.second` consumes `int first`.
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_optionalPositional_noOther() async {
+ addTestSource('''
+class A {
+ A([int first, double second]);
+}
+
+class B extends A {
+ B(super.^);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_notSuper() async {
+ addTestSource('''
+class A {
+ A(int first, double second);
+}
+
+class B extends A {
+ B(int one, super.^);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_super() async {
+ addTestSource('''
+class A {
+ A(int first, double second, bool third);
+}
+
+class B extends A {
+ B(super.one, super.^);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_hasPositional_super2() async {
+ addTestSource('''
+class A {
+ A(int first, double second, bool third);
+}
+
+class B extends A {
+ B(super.second, super.^);
+}
+''');
+
+ // It does not matter what is the name of the positional parameter.
+ // Here `super.second` consumes `int first`.
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('second')
+ ..isParameter
+ ..returnType.isEqualTo('double'),
+ ]);
+ }
+
+ Future<void> test_implicit_requiredPositional_noOther() async {
+ addTestSource('''
+class A {
+ A(int first, double second);
+ A.named(int third)
+}
+
+class B extends A {
+ B(super.^);
+}
+''');
+
+ var response = await computeSuggestions2();
+ check(response)
+ ..hasEmptyReplacement()
+ ..suggestions.matchesInAnyOrder([
+ (suggestion) => suggestion
+ ..completion.isEqualTo('first')
+ ..isParameter
+ ..returnType.isEqualTo('int'),
+ ]);
+ }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/test_all.dart b/pkg/analysis_server/test/services/completion/dart/test_all.dart
index 4ed7cd0..384422b 100644
--- a/pkg/analysis_server/test/services/completion/dart/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/dart/test_all.dart
@@ -21,6 +21,7 @@
import 'override_contributor_test.dart' as override_contributor_test;
import 'relevance/test_all.dart' as relevance_tests;
import 'static_member_contributor_test.dart' as static_contributor_test;
+import 'super_formal_contributor_test.dart' as super_formal_contributor;
import 'type_member_contributor_test.dart' as type_member_contributor_test;
import 'uri_contributor_test.dart' as uri_contributor_test;
import 'variable_name_contributor_test.dart' as variable_name_contributor_test;
@@ -44,6 +45,7 @@
override_contributor_test.main();
relevance_tests.main();
static_contributor_test.main();
+ super_formal_contributor.main();
type_member_contributor_test.main();
uri_contributor_test.main();
variable_name_contributor_test.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
index ce129cc..42c321b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_super_constructor_invocation_test.dart
@@ -11,11 +11,25 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(AddSuperConstructorInvocationTest);
+ defineReflectiveTests(AddSuperConstructorInvocationTest_language215);
});
}
@reflectiveTest
-class AddSuperConstructorInvocationTest extends FixProcessorTest {
+class AddSuperConstructorInvocationTest extends FixProcessorTest
+ with AddSuperConstructorInvocationTestCases {}
+
+@reflectiveTest
+class AddSuperConstructorInvocationTest_language215 extends FixProcessorTest
+ with AddSuperConstructorInvocationTestCases {
+ @override
+ void setUp() {
+ super.setUp();
+ writeTestPackageConfig(languageVersion: '2.15');
+ }
+}
+
+mixin AddSuperConstructorInvocationTestCases on FixProcessorTest {
@override
FixKind get kind => DartFixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION;
@@ -71,7 +85,26 @@
await assertNoFix();
}
- Future<void> test_requiredAndNamed() async {
+ Future<void> test_typeArgument() async {
+ await resolveTestCode('''
+class A<T> {
+ A(T p);
+}
+class B extends A<int> {
+ B();
+}
+''');
+ await assertHasFix('''
+class A<T> {
+ A(T p);
+}
+class B extends A<int> {
+ B() : super(0);
+}
+''');
+ }
+
+ Future<void> test_unnamed_requiredAndNamed() async {
await resolveTestCode('''
class A {
A(bool p1, int p2, double p3, String p4, {p5});
@@ -90,21 +123,24 @@
''');
}
- Future<void> test_typeArgument() async {
+ @FailingTest(
+ reason: 'Generates positional arguments instead of named',
+ )
+ Future<void> test_unnamed_requiredNamed() async {
await resolveTestCode('''
-class A<T> {
- A(T p);
+class A {
+ A({required int p1});
}
-class B extends A<int> {
+class B extends A {
B();
}
''');
await assertHasFix('''
-class A<T> {
- A(T p);
+class A {
+ A({required int p1});
}
-class B extends A<int> {
- B() : super(0);
+class B extends A {
+ B() : super(p1: 0);
}
''');
}
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index eabe7ee..d666d5c 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1745,6 +1745,32 @@
String? get defaultValueCode {
return constantInitializer?.toSource();
}
+
+ @override
+ bool get hasDefaultValue {
+ if (super.hasDefaultValue) {
+ return true;
+ }
+ return computeConstantValue() != null;
+ }
+
+ @override
+ DartObject? computeConstantValue() {
+ if (constantInitializer != null) {
+ return super.computeConstantValue();
+ }
+
+ var superDefault = superConstructorParameter?.computeConstantValue();
+ var superDefaultType = superDefault?.type;
+ var libraryElement = library;
+ if (superDefaultType != null &&
+ libraryElement != null &&
+ libraryElement.typeSystem.isSubtypeOf(superDefaultType, type)) {
+ return superDefault;
+ }
+
+ return null;
+ }
}
/// The synthetic element representing the declaration of the type `dynamic`.
@@ -5485,12 +5511,9 @@
return superParameters
.firstWhereOrNull((e) => e.isNamed && e.name == name);
} else {
+ var index = indexIn(enclosingElement);
var positionalSuperParameters =
superParameters.where((e) => e.isPositional).toList();
- var index = enclosingElement.parameters
- .whereType<SuperFormalParameterElementImpl>()
- .toList()
- .indexOf(this);
if (index >= 0 && index < positionalSuperParameters.length) {
return positionalSuperParameters[index];
}
@@ -5503,6 +5526,14 @@
@override
T? accept<T>(ElementVisitor<T> visitor) =>
visitor.visitSuperFormalParameterElement(this);
+
+ /// Return the index of this super-formal parameter among other super-formals.
+ int indexIn(ConstructorElementImpl enclosingElement) {
+ return enclosingElement.parameters
+ .whereType<SuperFormalParameterElementImpl>()
+ .toList()
+ .indexOf(this);
+ }
}
/// A concrete implementation of a [TopLevelVariableElement].
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 8138fda..c6522fb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -348,13 +348,13 @@
name: name,
nameOffset: nameOffset,
parameterKind: node.kind,
- );
+ )..constantInitializer = node.defaultValue;
} else {
element = DefaultParameterElementImpl(
name: name,
nameOffset: nameOffset,
parameterKind: node.kind,
- );
+ )..constantInitializer = node.defaultValue;
}
_elementHolder.addParameter(element);
@@ -383,7 +383,6 @@
defaultValue.accept(this);
});
});
- element.defaultValueCode = defaultValue.toSource();
}
}
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 78bd179..2582044 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4939,23 +4939,25 @@
parameterName ?? parameter,
);
}
- } else if (defaultValuesAreExpected && parameter.defaultValue == null) {
+ } else if (defaultValuesAreExpected) {
var parameterElement = parameter.declaredElement!;
- var type = parameterElement.type;
- if (typeSystem.isPotentiallyNonNullable(type)) {
- var parameterName = _parameterName(parameter);
- if (parameterElement.hasRequired) {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode
- .MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
- parameterName ?? parameter,
- );
- } else {
- errorReporter.reportErrorForNode(
- CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
- parameterName ?? parameter,
- [parameterName?.name ?? '?'],
- );
+ if (!parameterElement.hasDefaultValue) {
+ var type = parameterElement.type;
+ if (typeSystem.isPotentiallyNonNullable(type)) {
+ var parameterName = _parameterName(parameter);
+ if (parameterElement.hasRequired) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode
+ .MISSING_DEFAULT_VALUE_FOR_PARAMETER_WITH_ANNOTATION,
+ parameterName ?? parameter,
+ );
+ } else {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
+ parameterName ?? parameter,
+ [parameterName?.name ?? '?'],
+ );
+ }
}
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
index 0656a4b..4dc5158 100644
--- a/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/missing_default_value_for_parameter_test.dart
@@ -17,6 +17,34 @@
@reflectiveTest
class MissingDefaultValueForParameterTest extends PubPackageResolutionTest {
+ test_closure_nonNullable_named_optional_default() async {
+ await assertNoErrorsInCode('''
+var f = ({int a = 0}) {};
+''');
+ }
+
+ test_closure_nonNullable_named_optional_noDefault() async {
+ await assertErrorsInCode('''
+var f = ({int a}) {};
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 14, 1),
+ ]);
+ }
+
+ test_closure_nonNullable_positional_optional_default() async {
+ await assertNoErrorsInCode('''
+var f = ([int a = 0]) {};
+''');
+ }
+
+ test_closure_nonNullable_positional_optional_noDefault() async {
+ await assertErrorsInCode('''
+var f = ([int a]) {};
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 14, 1),
+ ]);
+ }
+
test_constructor_externalFactory_nonNullable_named_optional_noDefault() async {
await assertNoErrorsInCode('''
class C {
@@ -82,6 +110,54 @@
]);
}
+ test_constructor_generative_nonNullable_named_optional_super_hasDefault_explicit() async {
+ await assertNoErrorsInCode('''
+class A {
+ A({required int a});
+}
+class B extends A{
+ B({super.a = 0});
+}
+''');
+ }
+
+ test_constructor_generative_nonNullable_named_optional_super_hasDefault_fromSuper() async {
+ await assertNoErrorsInCode('''
+class A {
+ A({int a = 0});
+}
+class B extends A{
+ B({super.a});
+}
+''');
+ }
+
+ test_constructor_generative_nonNullable_named_optional_super_noDefault() async {
+ await assertErrorsInCode('''
+class A {
+ A({int? a});
+}
+class B extends A{
+ B({int super.a});
+}
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 61, 1),
+ ]);
+ }
+
+ test_constructor_generative_nonNullable_named_optional_super_noDefault_fromSuper() async {
+ await assertErrorsInCode('''
+class A {
+ A({num a = 1.2});
+}
+class B extends A{
+ B({int super.a});
+}
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 66, 1),
+ ]);
+ }
+
test_constructor_generative_nonNullable_positional_optional_noDefault() async {
await assertErrorsInCode('''
class C {
@@ -92,6 +168,54 @@
]);
}
+ test_constructor_generative_nonNullable_positional_optional_super_hasDefault_explicit() async {
+ await assertNoErrorsInCode('''
+class A {
+ A(int a);
+}
+class B extends A{
+ B([super.a = 0]);
+}
+''');
+ }
+
+ test_constructor_generative_nonNullable_positional_optional_super_hasDefault_fromSuper() async {
+ await assertNoErrorsInCode('''
+class A {
+ A([int a = 0]);
+}
+class B extends A{
+ B([super.a]);
+}
+''');
+ }
+
+ test_constructor_generative_nonNullable_positional_optional_super_noDefault() async {
+ await assertErrorsInCode('''
+class A {
+ A([int? a]);
+}
+class B extends A{
+ B([int super.a]);
+}
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 61, 1),
+ ]);
+ }
+
+ test_constructor_generative_nonNullable_positional_optional_super_noDefault_fromSuper() async {
+ await assertErrorsInCode('''
+class A {
+ A([num a = 1.2]);
+}
+class B extends A{
+ B([int super.a]);
+}
+''', [
+ error(CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER, 66, 1),
+ ]);
+ }
+
test_constructor_generative_nullable_named_optional_noDefault() async {
await assertNoErrorsInCode('''
class C {
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
index 96f4683..1209c3f 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
@@ -54,6 +54,10 @@
/// The relevance used when suggesting a named argument corresponding to a
/// named parameter that is required.
static const int requiredNamedArgument = 950;
+
+ /// The relevance used when suggesting a super-constructor parameter as
+ /// a super formal parameter.
+ static const int superFormalParameter = 1000;
}
/// A name scope for constants that are related to the relevance of completion
diff --git a/pkg/async_helper/lib/async_helper.dart b/pkg/async_helper/lib/async_helper.dart
index 1f3acb1..d4d536f 100644
--- a/pkg/async_helper/lib/async_helper.dart
+++ b/pkg/async_helper/lib/async_helper.dart
@@ -89,56 +89,50 @@
return f().then(asyncSuccess);
}
-bool _pass(dynamic object) => true;
-
-/// Calls [f] and verifies that it throws a `T`.
+/// Verifies that the asyncronous [result] throws a [T].
///
-/// The optional [check] function can provide additional validation that the
-/// correct object is being thrown. For example, to check the content of the
-/// thrown object you could write this:
+/// Fails if [result] completes with a value, or it completes with
+/// an error which is not a [T].
///
-/// asyncExpectThrows<MyException>(myThrowingFunction,
-/// (e) => e.myMessage.contains("WARNING"));
-///
-/// If `f` fails an expectation (i.e., throws an [ExpectException]), that
-/// exception is not caught by [asyncExpectThrows]. The test is still considered
-/// failing.
-void asyncExpectThrows<T>(Future<void> f(),
- [bool check(T error) = _pass, String reason = ""]) {
- var type = "";
- if (T != dynamic && T != Object) type = "<$T>";
+/// Returns the accepted thrown object.
+/// For example, to check the content of the thrown object,
+/// you could write this:
+/// ```
+/// var e = await asyncExpectThrows<MyException>(asyncExpression)
+/// Expect.isTrue(e.myMessage.contains("WARNING"));
+/// ```
+/// If `result` completes with an [ExpectException] error from another
+/// failed test expectation, that error cannot be caught and accepted.
+Future<T> asyncExpectThrows<T extends Object>(Future<void> result,
+ [String reason = ""]) {
// Handle null being passed in from legacy code while also avoiding producing
// an unnecessary null check warning here.
if ((reason as dynamic) == null) reason = "";
+
+ var type = "";
+ if (T != dynamic && T != Object) type = "<$T>";
var header = "asyncExpectThrows$type(${reason}):";
+ if ((result as dynamic) == null) {
+ Expect.testError("$header result Future must not be null.");
+ }
// TODO(rnystrom): It might useful to validate that T is not bound to
// ExpectException since that won't work.
- if (f is! Function()) {
- // Only throws from executing the function body should count as throwing.
- // The failure to even call `f` should throw outside the try/catch.
- Expect.testError("$header Function not callable with zero arguments.");
- }
-
- var result = f();
- if (result is! Future) {
- Expect.testError("$header Function did not return a Future.");
- }
-
asyncStart();
- result.then<Null>((_) {
+ return result.then<T>((_) {
throw ExpectException("$header Did not throw.");
- }).catchError((error, stack) {
+ }, onError: (error, stack) {
// A test failure doesn't count as throwing.
if (error is ExpectException) throw error;
- if (error is! T || (check != null && !check(error))) {
+ if (error is! T) {
// Throws something unexpected.
throw ExpectException(
"$header Unexpected '${Error.safeToString(error)}'\n$stack");
}
asyncEnd();
+ return error;
});
}
diff --git a/pkg/async_helper/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
index fa5d319..5b58930 100644
--- a/pkg/async_helper/lib/async_minitest.dart
+++ b/pkg/async_helper/lib/async_minitest.dart
@@ -215,14 +215,14 @@
Expect.isNull(o);
}
-void _checkThrow<T>(dynamic v, void onError(error)) {
+void _checkThrow<T extends Object>(dynamic v, void onError(error)) {
if (v is Future) {
asyncStart();
v.then((_) {
Expect.fail("Did not throw");
}, onError: (e, s) {
if (e is! T) throw e;
- if (onError != null) onError(e);
+ onError(e);
asyncEnd();
});
return;
diff --git a/pkg/compiler/test/inference/data/call_site.dart b/pkg/compiler/test/inference/data/call_site.dart
index 6cc8406..16f18e0 100644
--- a/pkg/compiler/test/inference/data/call_site.dart
+++ b/pkg/compiler/test/inference/data/call_site.dart
@@ -112,7 +112,7 @@
/*member: A8.:[exact=A8]*/
class A8 {
/*member: A8.x8:[empty]*/
- x8(/*Union([exact=JSString], [subclass=JsLinkedHashMap])*/ p) =>
+ x8(/*Union([exact=JSString], [exact=JsLinkedHashMap])*/ p) =>
/*invoke: [exact=A8]*/ x8("x");
}
@@ -126,7 +126,7 @@
/*member: A9.x9:[empty]*/ x9(
/*[exact=JSUInt31]*/ p1,
/*Union([exact=JSString], [exact=JSUInt31])*/ p2,
- /*Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ p3) =>
+ /*Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/ p3) =>
/*invoke: [exact=A9]*/ x9(p1, "x", {});
}
diff --git a/pkg/compiler/test/inference/data/closure2.dart b/pkg/compiler/test/inference/data/closure2.dart
index 793c24c..a3c5e37 100644
--- a/pkg/compiler/test/inference/data/closure2.dart
+++ b/pkg/compiler/test/inference/data/closure2.dart
@@ -14,7 +14,7 @@
return a;
}
-/*member: returnDyn1:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn1:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
returnDyn1() {
dynamic a = 42;
// ignore: unused_local_variable
@@ -34,7 +34,7 @@
return a;
}
-/*member: returnDyn2:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn2:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
returnDyn2() {
dynamic a = 42;
// ignore: unused_local_variable
@@ -60,10 +60,10 @@
return a;
}
-/*member: returnDyn3:Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/
+/*member: returnDyn3:Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/
returnDyn3() {
dynamic a = 42;
- if (a /*invoke: Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ == 53) {
+ if (a /*invoke: Union([exact=JSUInt31], [exact=JsLinkedHashMap])*/ == 53) {
// ignore: unused_local_variable
var f = /*[null]*/ () {
a = {};
diff --git a/pkg/compiler/test/inference/data/closure_tracer.dart b/pkg/compiler/test/inference/data/closure_tracer.dart
index e689520..6353470 100644
--- a/pkg/compiler/test/inference/data/closure_tracer.dart
+++ b/pkg/compiler/test/inference/data/closure_tracer.dart
@@ -59,11 +59,11 @@
dynamic b = <dynamic, dynamic>{'foo': 1};
b
- /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
['bar'] = a;
b
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
['bar']
/*Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)*/
diff --git a/pkg/compiler/test/inference/data/dictionary_types.dart b/pkg/compiler/test/inference/data/dictionary_types.dart
index 61c0072..e8a191a 100644
--- a/pkg/compiler/test/inference/data/dictionary_types.dart
+++ b/pkg/compiler/test/inference/data/dictionary_types.dart
@@ -13,7 +13,7 @@
test5();
}
-/*member: dictionaryA1:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: dictionaryA1:Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
dynamic dictionaryA1 = {
'string': "aString",
'int': 42,
@@ -21,7 +21,7 @@
'list': []
};
-/*member: dictionaryB1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+/*member: dictionaryB1:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
dynamic dictionaryB1 = {
'string': "aString",
'int': 42,
@@ -29,7 +29,7 @@
'list': []
};
-/*member: otherDict1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+/*member: otherDict1:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
dynamic otherDict1 = {'stringTwo': "anotherString", 'intTwo': 84};
/*member: int1:[exact=JSUInt31]*/
@@ -47,26 +47,26 @@
/*member: test1:[null]*/
test1() {
dictionaryA1
- . /*invoke: Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ . /*invoke: Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
addAll(otherDict1);
dictionaryB1
- . /*invoke: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ . /*invoke: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
addAll({'stringTwo': "anotherString", 'intTwo': 84});
int1 = dictionaryB1
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
['int'];
anotherInt1 = otherDict1
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
['intTwo'];
dynamic1 =
- dictionaryA1 /*Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
+ dictionaryA1 /*Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
'int'];
nullOrInt1 = dictionaryB1
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
['intTwo'];
}
-/*member: dictionaryA2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionaryA2:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
dynamic dictionaryA2 = {
'string': "aString",
'int': 42,
@@ -74,7 +74,7 @@
'list': []
};
-/*member: dictionaryB2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionaryB2:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
dynamic dictionaryB2 = {'string': "aString", 'intTwo': 42, 'list': []};
/*member: nullOrInt2:[null|exact=JSUInt31]*/
@@ -89,22 +89,22 @@
/*member: test2:[null]*/
test2() {
var union = dictionaryA2
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
['foo']
? dictionaryA2
: dictionaryB2;
nullOrInt2 = union
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
['intTwo'];
aString2 = union
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
['string'];
doubleOrNull2 = union
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSNumNotInt], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
['double'];
}
-/*member: dictionary3:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+/*member: dictionary3:Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
dynamic dictionary3 = {
'string': "aString",
'int': 42,
@@ -125,18 +125,18 @@
/*member: intOrNull3:[null|exact=JSUInt31]*/
dynamic intOrNull3 = dictionary3
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
[keyI3];
/*member: justNull3:[null]*/
dynamic justNull3 = dictionary3
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
[keyN3];
/*member: test3:[null]*/
test3() {
knownDouble3 = dictionary3
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt], [exact=JSString], [exact=JSUInt31]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSNumNotInt], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
[keyD3];
// ignore: unused_local_variable
var x = [intOrNull3, justNull3];
@@ -147,8 +147,8 @@
A4();
/*member: A4.foo4:[exact=JSUInt31]*/
foo4(
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
- return value /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+ return value /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
'anInt'];
}
}
@@ -159,7 +159,7 @@
/*member: B4.foo4:[exact=JSUInt31]*/
foo4(
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSString], [exact=JSUInt31]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
return 0;
}
}
@@ -180,7 +180,7 @@
2);
}
-/*member: dict5:Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: dict5:Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
dynamic dict5 = makeMap5([1, 2]);
/*member: notInt5:[null|subclass=Object]*/
@@ -189,7 +189,7 @@
/*member: alsoNotInt5:[null|subclass=Object]*/
dynamic alsoNotInt5 = 0;
-/*member: makeMap5:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+/*member: makeMap5:Map([exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
makeMap5(
/*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/ values) {
return {
@@ -205,14 +205,14 @@
/*member: test5:[null]*/
test5() {
dict5
- /*update: Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ /*update: Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
['goo'] = 42;
var closure =
- /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ /*Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
() => dict5;
notInt5 = closure()['boo'];
alsoNotInt5 = dict5
- /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ /*Map([null|exact=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
['goo'];
print("$notInt5 and $alsoNotInt5.");
}
diff --git a/pkg/compiler/test/inference/data/index.dart b/pkg/compiler/test/inference/data/index.dart
index 4a00271..c05e292 100644
--- a/pkg/compiler/test/inference/data/index.dart
+++ b/pkg/compiler/test/inference/data/index.dart
@@ -60,7 +60,7 @@
mapLookupSingle() {
var map = {0: 1};
return map
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[0];
}
@@ -72,7 +72,7 @@
mapLookupMultiple() {
var map = {0: 1, 2: 3, 4: 5};
return map
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[2];
}
@@ -84,7 +84,7 @@
mapLookupMissing() {
var map = {0: 1};
return map
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[2];
}
@@ -96,7 +96,7 @@
mapLookupMixedKeys() {
var map = {0: 1, '': 2};
return map
- /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
+ /*Map([exact=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
[''];
}
@@ -108,7 +108,7 @@
mapLookupMixedValues() {
var map = {0: 1, 2: ''};
return map
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
[2];
}
@@ -120,7 +120,7 @@
dictionaryLookupSingle() {
var map = {'foo': 'bar'};
return map
- /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
['foo'];
}
@@ -132,7 +132,7 @@
dictionaryLookupMultiple() {
var map = {'foo': 'bar', 'baz': 'boz'};
return map
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
['baz'];
}
@@ -144,7 +144,7 @@
dictionaryLookupMissing() {
var map = {'foo': 'bar', 'baz': 'boz'};
return map
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([exact=JSString], value: "boz")})*/
['unknown'];
}
@@ -156,7 +156,7 @@
intDictionaryLookupSingle() {
var map = {'foo': 0};
return map
- /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [exact=JSUInt31]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [exact=JSUInt31]})*/
['foo'];
}
diff --git a/pkg/compiler/test/inference/data/index_call.dart b/pkg/compiler/test/inference/data/index_call.dart
index 4454632..d563df2 100644
--- a/pkg/compiler/test/inference/data/index_call.dart
+++ b/pkg/compiler/test/inference/data/index_call.dart
@@ -63,9 +63,9 @@
var a = {
'a': {'b': 0}
};
- return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]}), map: {a: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})})*/
+ return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]}), map: {a: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})})*/
['a']
- /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|exact=JSUInt31], map: {b: [exact=JSUInt31]})*/
['b']
. /*invoke: [exact=JSUInt31]*/
abs();
@@ -77,9 +77,9 @@
var a = {
'a': {'b': closure}
};
- return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]}), map: {a: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})})*/
+ return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Dictionary([null|exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]}), map: {a: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})})*/
['a']
- /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "b"), value: [null|subclass=Closure], map: {b: [subclass=Closure]})*/
['b'](d: 0);
}
@@ -89,7 +89,7 @@
var a = {
'a': [closure]
};
- return a /*Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1), map: {a: Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+ return a /*Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "a"), value: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1), map: {a: Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
['a']
/*Container([exact=JSExtendableArray], element: [subclass=Closure], length: 1)*/
[0](d: 0);
diff --git a/pkg/compiler/test/inference/data/index_set.dart b/pkg/compiler/test/inference/data/index_set.dart
index 883962c..c383f3f 100644
--- a/pkg/compiler/test/inference/data/index_set.dart
+++ b/pkg/compiler/test/inference/data/index_set.dart
@@ -60,7 +60,7 @@
mapUpdateEmpty() {
var map = {};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[0] = 42;
}
@@ -72,7 +72,7 @@
mapUpdateSingle() {
var map = {0: 1};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[0] = 42;
}
@@ -84,7 +84,7 @@
mapUpdateMultiple() {
var map = {0: 1, 2: 3, 4: 5};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[2] = 42;
}
@@ -96,7 +96,7 @@
mapUpdateMissing() {
var map = {0: 1};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: [null|exact=JSUInt31])*/
[2] = 42;
}
@@ -108,7 +108,7 @@
mapUpdateMixedKeys() {
dynamic map = {'': 2};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
+ /*update: Map([exact=JsLinkedHashMap], key: Union([exact=JSString], [exact=JSUInt31]), value: [null|exact=JSUInt31])*/
[0] = 42;
}
@@ -120,7 +120,7 @@
mapUpdateMixedValues() {
dynamic map = {2: ''};
return map
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSUInt31], value: Union(null, [exact=JSString], [exact=JSUInt31]))*/
[2] = 42;
}
@@ -132,7 +132,7 @@
dictionaryUpdateEmpty() {
var map = {};
return map
- /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([null|exact=JSString], value: "bar")})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([null|exact=JSString], value: "bar")})*/
['foo'] = 'bar';
}
@@ -144,7 +144,7 @@
dictionaryUpdateSingle() {
var map = {'foo': 'bar'};
return map
- /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSString], map: {foo: [exact=JSString]})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSString], map: {foo: [exact=JSString]})*/
['foo'] = 'boz';
}
@@ -156,7 +156,7 @@
dictionaryReUpdateSingle() {
var map = {'foo': 'bar'};
return map
- /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: Value([null|exact=JSString], value: "bar"), map: {foo: Value([exact=JSString], value: "bar")})*/
['foo'] = 'bar';
}
@@ -168,7 +168,7 @@
dictionaryUpdateMultiple() {
var map = {'foo': 'bar'};
return map
- /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([null|exact=JSString], value: "boz")})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSString], map: {foo: Value([exact=JSString], value: "bar"), baz: Value([null|exact=JSString], value: "boz")})*/
['baz'] = 'boz';
}
@@ -180,7 +180,7 @@
intDictionaryUpdateSingle() {
var map = {};
return map
- /*update: Dictionary([subclass=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [null|exact=JSUInt31]})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: Value([exact=JSString], value: "foo"), value: [null|exact=JSUInt31], map: {foo: [null|exact=JSUInt31]})*/
['foo'] = 0;
}
diff --git a/pkg/compiler/test/inference/data/map_tracer_keys.dart b/pkg/compiler/test/inference/data/map_tracer_keys.dart
index beedfbf..1e70a9e 100644
--- a/pkg/compiler/test/inference/data/map_tracer_keys.dart
+++ b/pkg/compiler/test/inference/data/map_tracer_keys.dart
@@ -29,16 +29,16 @@
test1() {
var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
theMap
- /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
['d'] = 5.5;
/*iterator: [exact=LinkedHashMapKeyIterable]*/
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
keys) {
aDouble1 = theMap
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [null|exact=JSNumNotInt]})*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
@@ -60,16 +60,16 @@
test2() {
dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
theMap
- /*update: Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+ /*update: Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
[aList2] = 5.5;
/*iterator: [exact=LinkedHashMapKeyIterable]*/
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
keys) {
aDouble2 = theMap
- /*Map([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
+ /*Map([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt])*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
@@ -91,16 +91,16 @@
test3() {
dynamic theMap = <dynamic, dynamic>{'a': 2.2, 'b': 3.3, 'c': 4.4};
theMap
- /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
['d'] = aList3;
/*iterator: [exact=LinkedHashMapKeyIterable]*/
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
keys) {
aDouble3 = theMap
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([null|exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
@@ -125,10 +125,10 @@
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
keys) {
aDouble4 = theMap
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSNumNotInt], map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: [exact=JSNumNotInt]})*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
@@ -153,10 +153,10 @@
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
+ /*Map([exact=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
keys) {
aDouble5 = theMap
- /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
+ /*Map([exact=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSNumNotInt])*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
@@ -180,10 +180,10 @@
/*current: [exact=LinkedHashMapKeyIterator]*/
/*moveNext: [exact=LinkedHashMapKeyIterator]*/
for (var key in theMap.
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
keys) {
aDouble6 = theMap
- /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSNumNotInt]), map: {a: [exact=JSNumNotInt], b: [exact=JSNumNotInt], c: [exact=JSNumNotInt], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
[key];
}
// We have to reference it somewhere, so that it always gets resolved.
diff --git a/pkg/compiler/test/inference/data/no_such_method4.dart b/pkg/compiler/test/inference/data/no_such_method4.dart
index 0538869..2cd61c1 100644
--- a/pkg/compiler/test/inference/data/no_such_method4.dart
+++ b/pkg/compiler/test/inference/data/no_such_method4.dart
@@ -13,13 +13,13 @@
/*member: B.:[exact=B]*/
class B extends A {
- /*member: B.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
+ /*member: B.foo:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
{};
}
/*member: C.:[exact=C]*/
class C extends B {
- /*member: C.foo:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
+ /*member: C.foo:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/ foo() =>
{};
}
@@ -34,22 +34,22 @@
return e. /*invoke: [exact=A]*/ foo();
}
-/*member: test2:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test2:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test2() => a. /*invoke: [null|subclass=B]*/ foo();
-/*member: test3:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test3:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test3() => new B(). /*invoke: [exact=B]*/ foo();
-/*member: test4:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test4:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test4() => new C(). /*invoke: [exact=C]*/ foo();
-/*member: test5:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test5:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test5() {
dynamic e = (a ? new A() : new B());
return e. /*invoke: [subclass=A]*/ foo();
}
-/*member: test6:Dictionary([subclass=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
+/*member: test6:Dictionary([exact=JsLinkedHashMap], key: [empty], value: [null], map: {})*/
test6() => (a ? new B() : new C()). /*invoke: [subclass=B]*/ foo();
/*member: main:[null]*/
diff --git a/pkg/compiler/test/rti/data/map_literal.dart b/pkg/compiler/test/rti/data/map_literal.dart
index 1d91a1b..988f06e 100644
--- a/pkg/compiler/test/rti/data/map_literal.dart
+++ b/pkg/compiler/test/rti/data/map_literal.dart
@@ -11,7 +11,7 @@
/*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
/*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
/*prod.class: global#double:*/
/*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/data/map_to_set.dart b/pkg/compiler/test/rti/data/map_to_set.dart
index 79f0f2a..4c870c3 100644
--- a/pkg/compiler/test/rti/data/map_to_set.dart
+++ b/pkg/compiler/test/rti/data/map_to_set.dart
@@ -11,7 +11,7 @@
/*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
/*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K,JsLinkedHashMap.V],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
/*prod.class: global#double:*/
/*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/dds/lib/src/client.dart b/pkg/dds/lib/src/client.dart
index 7aaeafd..5b3abdc 100644
--- a/pkg/dds/lib/src/client.dart
+++ b/pkg/dds/lib/src/client.dart
@@ -97,7 +97,13 @@
void _registerJsonRpcMethods() {
_clientPeer.registerMethod('streamListen', (parameters) async {
final streamId = parameters['streamId'].asString;
- await dds.streamManager.streamListen(this, streamId);
+ final includePrivates =
+ parameters['_includePrivateMembers'].asBoolOr(false);
+ await dds.streamManager.streamListen(
+ this,
+ streamId,
+ includePrivates: includePrivates,
+ );
return RPCResponses.success;
});
diff --git a/pkg/dds/lib/src/dap/adapters/dart.dart b/pkg/dds/lib/src/dap/adapters/dart.dart
index 523cadf..48957f1 100644
--- a/pkg/dds/lib/src/dap/adapters/dart.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart.dart
@@ -1899,8 +1899,6 @@
final int? vmServicePort;
- final bool? enableAsserts;
-
/// Which console to run the program in.
///
/// If "terminal" or "externalTerminal" will cause the program to be run by
@@ -1939,7 +1937,6 @@
this.toolArgs,
this.vmAdditionalArgs,
this.console,
- this.enableAsserts,
this.customTool,
this.customToolReplacesArgs,
Object? restart,
@@ -1973,7 +1970,6 @@
vmAdditionalArgs = (obj['vmAdditionalArgs'] as List?)?.cast<String>(),
vmServicePort = obj['vmServicePort'] as int?,
console = obj['console'] as String?,
- enableAsserts = obj['enableAsserts'] as bool?,
customTool = obj['customTool'] as String?,
customToolReplacesArgs = obj['customToolReplacesArgs'] as int?,
super.fromMap(obj);
@@ -1988,7 +1984,6 @@
if (vmAdditionalArgs != null) 'vmAdditionalArgs': vmAdditionalArgs,
if (vmServicePort != null) 'vmServicePort': vmServicePort,
if (console != null) 'console': console,
- if (enableAsserts != null) 'enableAsserts': enableAsserts,
if (customTool != null) 'customTool': customTool,
if (customToolReplacesArgs != null)
'customToolReplacesArgs': customToolReplacesArgs,
diff --git a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
index 46e28e3..1ec25dd 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_cli_adapter.dart
@@ -98,9 +98,6 @@
'-DSILENT_OBSERVATORY=true',
'--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
],
- // Default to asserts on, this seems like the most useful behaviour for
- // editor-spawned debug sessions.
- if (args.enableAsserts ?? true) '--enable-asserts',
];
// Handle customTool and deletion of any arguments for it.
@@ -150,11 +147,6 @@
env: args.env,
);
}
-
- // Delay responding until the debugger is connected.
- if (debug) {
- await debuggerInitialized;
- }
}
/// Called by [attachRequest] to request that we actually connect to the app
diff --git a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
index 0f67af4..716fcfe 100644
--- a/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
+++ b/pkg/dds/lib/src/dap/adapters/dart_test_adapter.dart
@@ -93,11 +93,8 @@
'-DSILENT_OBSERVATORY=true',
'--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
],
- // Default to asserts on, this seems like the most useful behaviour for
- // editor-spawned debug sessions.
- if (args.enableAsserts ?? true) '--enable-asserts',
// TODO(dantup): This should be changed from "dart run test:test" to
- // "dart test" once the started-paused flags are working correctly.
+ // "dart test" once the start-paused flags are working correctly.
// Currently they start paused but do not write the vm-service-info file
// to give us the VM-service URI.
// https://github.com/dart-lang/sdk/issues/44200#issuecomment-726869539
diff --git a/pkg/dds/lib/src/stream_manager.dart b/pkg/dds/lib/src/stream_manager.dart
index ee0bc49..be5b3f4 100644
--- a/pkg/dds/lib/src/stream_manager.dart
+++ b/pkg/dds/lib/src/stream_manager.dart
@@ -170,16 +170,19 @@
/// `streamListen` request for `stream` to the VM service.
Future<void> streamListen(
DartDevelopmentServiceClient? client,
- String stream,
- ) async {
+ String stream, {
+ bool? includePrivates,
+ }) async {
await _streamSubscriptionMutex.runGuarded(
() async {
assert(stream.isNotEmpty);
+ bool streamNewlySubscribed = false;
if (!streamListeners.containsKey(stream)) {
// Initialize the list of clients for the new stream before we do
// anything else to ensure multiple clients registering for the same
// stream in quick succession doesn't result in multiple streamListen
// requests being sent to the VM service.
+ streamNewlySubscribed = true;
streamListeners[stream] = <DartDevelopmentServiceClient>[];
if ((stream == kDebugStream && client == null) ||
stream != kDebugStream) {
@@ -188,12 +191,18 @@
final result =
await dds.vmServiceClient.sendRequest('streamListen', {
'streamId': stream,
+ if (includePrivates != null)
+ '_includePrivateMembers': includePrivates,
});
assert(result['type'] == 'Success');
}
}
if (streamListeners[stream]!.contains(client)) {
throw kStreamAlreadySubscribedException;
+ } else if (!streamNewlySubscribed && includePrivates != null) {
+ await dds.vmServiceClient.sendRequest(
+ '_setStreamIncludePrivateMembers',
+ {'streamId': stream, 'includePrivateMembers': includePrivates});
}
if (client != null) {
streamListeners[stream]!.add(client);
diff --git a/pkg/dds/test/dap/dart_cli_test.dart b/pkg/dds/test/dap/dart_cli_test.dart
index d07dc37..57f2297 100644
--- a/pkg/dds/test/dap/dart_cli_test.dart
+++ b/pkg/dds/test/dap/dart_cli_test.dart
@@ -79,7 +79,6 @@
program: 'foo.dart',
customTool: '/custom/dart',
noDebug: true,
- enableAsserts: true, // to check args are still passed through
);
await adapter.configurationDoneRequest(request, null, () {});
@@ -87,8 +86,8 @@
await responseCompleter.future;
expect(adapter.executable, equals('/custom/dart'));
- // args should be in-tact
- expect(adapter.processArgs, contains('--enable-asserts'));
+ // a standard built-in arg should be present.
+ expect(adapter.processArgs, contains('--disable-dart-dev'));
});
test('with all args replaced', () async {
@@ -100,7 +99,6 @@
customTool: '/custom/dart',
customToolReplacesArgs: 9999, // replaces all built-in args
noDebug: true,
- enableAsserts: true, // should not be in args
toolArgs: ['tool_args'], // should still be in args
);
@@ -111,7 +109,7 @@
expect(adapter.executable, equals('/custom/dart'));
// normal built-in args are replaced by customToolReplacesArgs, but
// user-provided toolArgs are not.
- expect(adapter.processArgs, isNot(contains('--enable-asserts')));
+ expect(adapter.processArgs, isNot(contains('--disable-dart-dev')));
expect(adapter.processArgs, contains('tool_args'));
});
});
diff --git a/pkg/dds/test/dap/integration/debug_services.dart b/pkg/dds/test/dap/integration/debug_services_test.dart
similarity index 100%
rename from pkg/dds/test/dap/integration/debug_services.dart
rename to pkg/dds/test/dap/integration/debug_services_test.dart
diff --git a/pkg/dds/tool/dap/README.md b/pkg/dds/tool/dap/README.md
index 26bbeb3..ec49ac5 100644
--- a/pkg/dds/tool/dap/README.md
+++ b/pkg/dds/tool/dap/README.md
@@ -39,7 +39,6 @@
- `List<String>? toolArgs` - arguments passed after the tool that will run `program` (after `dart` for CLI scripts and after `dart run test:test` for test scripts)
- `List<String>? vmAdditionalArgs` - arguments passed directly to the Dart VM (after `dart` for both CLI scripts and test scripts)
- `String? console` - if set to `"terminal"` or `"externalTerminal"` will be run using the `runInTerminal` reverse-request; otherwise the debug adapter spawns the Dart process
-- `bool? enableAsserts` - whether to enable asserts (if not supplied, defaults to enabled)
- `String? customTool` - an optional tool to run instead of `dart` - the custom tool must be completely compatible with the tool/command it is replacing
- `int? customToolReplacesArgs` - the number of arguments to delete from the beginning of the argument list when invoking `customTool` - e.g. setting `customTool` to `dart_test` and
`customToolReplacesArgs` to `2` for a test run would invoke `dart_test foo_test.dart` instead of `dart run test:test foo_test.dart` (if larger than the number of computed arguments all arguments will be removed, if not supplied will default to `0`)
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 1b1a534..e7413dd17 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -243,9 +243,13 @@
buffer.write('_');
} else {
int first = equivalence[0];
- buffer..write('#')..write(first);
+ buffer
+ ..write('#')
+ ..write(first);
if (first == i) {
- buffer..write('=')..write(objects[i]);
+ buffer
+ ..write('=')
+ ..write(objects[i]);
}
}
}
@@ -259,7 +263,10 @@
if (first.isNotEmpty && first.length == objects.length) return;
var buffer = new StringBuffer("Expect.allIdentical([");
_writeEquivalences(objects, equivalences, buffer);
- buffer..write("]")..write(msg)..write(")");
+ buffer
+ ..write("]")
+ ..write(msg)
+ ..write(")");
_fail(buffer.toString());
}
@@ -290,7 +297,10 @@
if (!hasEquivalence) return;
var buffer = new StringBuffer("Expect.allDistinct([");
_writeEquivalences(objects, equivalences, buffer);
- buffer..write("]")..write(msg)..write(")");
+ buffer
+ ..write("]")
+ ..write(msg)
+ ..write(")");
_fail(buffer.toString());
}
@@ -387,7 +397,7 @@
String defaultMessage =
'Expect.stringEquals(expected: <$expected>", <$actual>$msg) fails';
- if ((expected == null) || (actual == null)) {
+ if ((expected as dynamic) == null || (actual as dynamic) == null) {
_fail('$defaultMessage');
}
@@ -583,45 +593,52 @@
}
}
- static bool _defaultCheck([dynamic e]) => true;
+ static bool _defaultCheck([dynamic _]) => true;
/**
- * Calls the function [f] and verifies that it throws a `T`.
- * The optional [check] function can provide additional validation
- * that the correct object is being thrown. For example, to check
- * the content of the thrown boject you could write this:
+ * Verifies that [computation] throws a [T].
*
- * Expect.throws<MyException>(myThrowingFunction,
- * (e) => e.myMessage.contains("WARNING"));
+ * Calls the [computation] function and fails if that call doesn't throw,
+ * throws something which is not a [T], or throws a [T] which does not
+ * satisfy the optional [check] function.
*
- * The type variable can be omitted and the type checked in [check]
- * instead. This was traditionally done before Dart had generic methods.
+ * Returns the accepted thrown [T] object, if one is caught.
+ * This value can be checked further, instead of checking it in the [check]
+ * function. For example, to check the content of the thrown object,
+ * you could write this:
+ * ```
+ * var e = Expect.throws<MyException>(myThrowingFunction);
+ * Expect.isTrue(e.myMessage.contains("WARNING"));
+ * ```
+ * The type variable can be omitted, in which case it defaults to [Object],
+ * and the (sub-)type of the object can be checked in [check] instead.
+ * This was traditionally done before Dart had generic methods.
*
- * If `f` fails an expectation (i.e., throws an [ExpectException]), that
- * exception is not caught by [Expect.throws]. The test is still considered
- * failing.
+ * If `computation` fails another test expectation
+ * (i.e., throws an [ExpectException]),
+ * that exception cannot be caught and accepted by [Expect.throws].
+ * The test is still considered failing.
*/
- static void throws<T>(void f(),
- [bool check(T error) = _defaultCheck, String reason = ""]) {
+ static T throws<T extends Object>(void Function() computation,
+ [bool Function(T error)? check, String? reason]) {
// TODO(vsm): Make check and reason nullable or change call sites.
// Existing tests pass null to set a reason and/or pass them through
// via helpers.
// TODO(rnystrom): Using the strange form below instead of "??=" to avoid
// warnings of unnecessary null checks when analyzed as NNBD code.
- if ((check as dynamic) == null) check = _defaultCheck;
- if ((reason as dynamic) == null) reason = "";
+ reason ??= "";
String msg = reason.isEmpty ? "" : "($reason)";
- if (f is! Function()) {
+ if ((computation as dynamic) == null) {
// Only throws from executing the function body should count as throwing.
// The failure to even call `f` should throw outside the try/catch.
- _fail("Expect.throws$msg: Function f not callable with zero arguments");
+ testError("Function must not be null");
}
try {
- f();
+ computation();
} catch (e, s) {
// A test failure doesn't count as throwing.
if (e is ExpectException) rethrow;
- if (e is T && check(e as dynamic)) return;
+ if (e is T && (check ?? _defaultCheck)(e)) return e;
// Throws something unexpected.
String type = "";
if (T != dynamic && T != Object) {
@@ -633,47 +650,41 @@
_fail('Expect.throws$msg fails: Did not throw');
}
- static void throwsArgumentError(void f(), [String reason = "ArgumentError"]) {
- Expect.throws(f, (error) => error is ArgumentError, reason);
- }
+ static ArgumentError throwsArgumentError(void f(),
+ [String reason = "ArgumentError"]) =>
+ Expect.throws<ArgumentError>(f, _defaultCheck, reason);
- static void throwsAssertionError(void f(),
- [String reason = "AssertionError"]) {
- Expect.throws(f, (error) => error is AssertionError, reason);
- }
+ static AssertionError throwsAssertionError(void f(),
+ [String reason = "AssertionError"]) =>
+ Expect.throws<AssertionError>(f, _defaultCheck, reason);
- static void throwsFormatException(void f(),
- [String reason = "FormatException"]) {
- Expect.throws(f, (error) => error is FormatException, reason);
- }
+ static FormatException throwsFormatException(void f(),
+ [String reason = "FormatException"]) =>
+ Expect.throws<FormatException>(f, _defaultCheck, reason);
- static void throwsNoSuchMethodError(void f(),
- [String reason = "NoSuchMethodError"]) {
- Expect.throws(f, (error) => error is NoSuchMethodError, reason);
- }
+ static NoSuchMethodError throwsNoSuchMethodError(void f(),
+ [String reason = "NoSuchMethodError"]) =>
+ Expect.throws<NoSuchMethodError>(f, _defaultCheck, reason);
- static void throwsReachabilityError(void f(),
- [String reason = "ReachabilityError"]) {
- Expect.throws(
- f, (error) => error.toString().startsWith('ReachabilityError'), reason);
- }
+ static Error throwsReachabilityError(void f(),
+ [String reason = "ReachabilityError"]) =>
+ Expect.throws<Error>(f,
+ (error) => error.toString().startsWith('ReachabilityError'), reason);
- static void throwsRangeError(void f(), [String reason = "RangeError"]) {
- Expect.throws(f, (error) => error is RangeError, reason);
- }
+ static RangeError throwsRangeError(void f(),
+ [String reason = "RangeError"]) =>
+ Expect.throws<RangeError>(f, _defaultCheck, reason);
- static void throwsStateError(void f(), [String reason = "StateError"]) {
- Expect.throws(f, (error) => error is StateError, reason);
- }
+ static StateError throwsStateError(void f(),
+ [String reason = "StateError"]) =>
+ Expect.throws<StateError>(f, _defaultCheck, reason);
- static void throwsTypeError(void f(), [String reason = "TypeError"]) {
- Expect.throws(f, (error) => error is TypeError, reason);
- }
+ static TypeError throwsTypeError(void f(), [String reason = "TypeError"]) =>
+ Expect.throws<TypeError>(f, _defaultCheck, reason);
- static void throwsUnsupportedError(void f(),
- [String reason = "UnsupportedError"]) {
- Expect.throws(f, (error) => error is UnsupportedError, reason);
- }
+ static UnsupportedError throwsUnsupportedError(void f(),
+ [String reason = "UnsupportedError"]) =>
+ Expect.throws<UnsupportedError>(f, _defaultCheck, reason);
/// Reports that there is an error in the test itself and not the code under
/// test.
@@ -748,20 +759,20 @@
_getTestName = getName;
}
- // TODO(rnystrom): Type this `String Function()?` once this library doesn't
- // need to be NNBD-agnostic.
- static dynamic _getTestName;
+ static String Function() _getTestName = _kEmptyString;
final String message;
final String name;
- ExpectException(this.message)
- : name = (_getTestName == null) ? "" : _getTestName();
+ ExpectException(this.message) : name = _getTestName();
String toString() {
if (name != "") return 'In test "$name" $message';
return message;
}
+
+ /// Initial value for _getTestName.
+ static String _kEmptyString() => "";
}
/// Is true iff type assertions are enabled.
@@ -769,7 +780,7 @@
final bool typeAssertionsEnabled = (() {
try {
dynamic i = 42;
- String s = i;
+ String s = i; // ignore: unused_local_variable
} on TypeError {
return true;
}
diff --git a/pkg/expect/test/nnbd_mode_test.dart b/pkg/expect/test/nnbd_mode_test.dart
index 35dd345..1bacdec 100644
--- a/pkg/expect/test/nnbd_mode_test.dart
+++ b/pkg/expect/test/nnbd_mode_test.dart
@@ -6,7 +6,7 @@
final bool strong = () {
try {
- int i = null as dynamic;
+ int i = null as dynamic; // ignore: unused_local_variable
return false;
} catch (e) {
return true;
diff --git a/pkg/front_end/test/spell_checking_list_tests.txt b/pkg/front_end/test/spell_checking_list_tests.txt
index 97ef414..d9f5fdf 100644
--- a/pkg/front_end/test/spell_checking_list_tests.txt
+++ b/pkg/front_end/test/spell_checking_list_tests.txt
@@ -1060,6 +1060,7 @@
xxxxxxxxxxxx
xyz
y's
+yaml2json
year
yxxx
yy
diff --git a/pkg/front_end/tool/smoke_test_quick.dart b/pkg/front_end/tool/smoke_test_quick.dart
index 12b77c3..2b7a200 100644
--- a/pkg/front_end/tool/smoke_test_quick.dart
+++ b/pkg/front_end/tool/smoke_test_quick.dart
@@ -29,6 +29,9 @@
futures.add(run(
"pkg/front_end/test/generated_files_up_to_date_git_test.dart", [],
filter: false));
+ futures.add(run("tools/yaml2json.dart",
+ ["sdk/lib/libraries.yaml", "sdk/lib/libraries.json", '--check'],
+ filter: false));
await Future.wait(futures);
print("\n-----------------------\n");
print("Done with exitcode $exitCode in ${stopwatch.elapsedMilliseconds} ms");
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
index 4203e7a..ba91b27 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/write_only_field2.dart.expect
@@ -56,7 +56,7 @@
new self::A::•();
new self::B::•();
self::C<core::num> c = new self::D::•();
- exp::Expect::throws<dynamic>(() → void {
+ exp::Expect::throws<core::Object>(() → void {
[@vm.call-site-attributes.metadata=receiverType:#lib::C<dart.core::num>] [@vm.direct-call.metadata=#lib::D.bar] c.{self::C::bar} = 3.14;
});
self::E e = new self::F::•();
diff --git a/runtime/lib/vmservice.cc b/runtime/lib/vmservice.cc
index 1f0744a..423381b 100644
--- a/runtime/lib/vmservice.cc
+++ b/runtime/lib/vmservice.cc
@@ -128,10 +128,13 @@
return Object::null();
}
-DEFINE_NATIVE_ENTRY(VMService_ListenStream, 0, 1) {
+DEFINE_NATIVE_ENTRY(VMService_ListenStream, 0, 2) {
#ifndef PRODUCT
GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
- bool result = Service::ListenStream(stream_id.ToCString());
+ GET_NON_NULL_NATIVE_ARGUMENT(Bool, include_privates,
+ arguments->NativeArgAt(1));
+ bool result =
+ Service::ListenStream(stream_id.ToCString(), include_privates.value());
return Bool::Get(result).ptr();
#else
return Object::null();
diff --git a/runtime/observatory/lib/service_common.dart b/runtime/observatory/lib/service_common.dart
index 236343c..5c62c48 100644
--- a/runtime/observatory/lib/service_common.dart
+++ b/runtime/observatory/lib/service_common.dart
@@ -149,7 +149,11 @@
return new Future.error(exception);
}
String serial = (_requestSerial++).toString();
- var request = new _WebSocketRequest(method, params);
+ var request = new _WebSocketRequest(method, <String, dynamic>{
+ ...params,
+ // Include internal response data.
+ '_includePrivateMembers': true,
+ });
if ((_webSocket != null) && _webSocket!.isOpen) {
// Already connected, send request immediately.
_sendRequest(serial, request);
diff --git a/runtime/observatory_2/lib/service_common.dart b/runtime/observatory_2/lib/service_common.dart
index b61f4a0..d6eba9b 100644
--- a/runtime/observatory_2/lib/service_common.dart
+++ b/runtime/observatory_2/lib/service_common.dart
@@ -149,7 +149,11 @@
return new Future.error(exception);
}
String serial = (_requestSerial++).toString();
- var request = new _WebSocketRequest(method, params);
+ var request = new _WebSocketRequest(method, <String, dynamic>{
+ ...params,
+ // Include internal response data.
+ '_includePrivateMembers': true,
+ });
if ((_webSocket != null) && _webSocket.isOpen) {
// Already connected, send request immediately.
_sendRequest(serial, request);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index ca3d03c..1742e8d 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -361,7 +361,7 @@
V(VMService_OnStart, 0) \
V(VMService_OnExit, 0) \
V(VMService_OnServerAddressChange, 1) \
- V(VMService_ListenStream, 1) \
+ V(VMService_ListenStream, 2) \
V(VMService_CancelStream, 1) \
V(VMService_RequestAssets, 0) \
V(VMService_DecodeAssets, 1) \
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index bf9a9ad..15f48ef 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -740,6 +740,13 @@
Type& TranslationHelper::GetDeclarationType(const Class& klass) {
ASSERT(!klass.IsNull());
+ // Forward expression evaluation class to a real class when
+ // creating types.
+ if (GetExpressionEvaluationClass().ptr() == klass.ptr()) {
+ ASSERT(GetExpressionEvaluationRealClass().ptr() != klass.ptr());
+ return GetDeclarationType(GetExpressionEvaluationRealClass());
+ }
+ ASSERT(klass.id() != kIllegalCid);
// Note that if cls is _Closure, the returned type will be _Closure,
// and not the signature type.
Type& type = Type::ZoneHandle(Z);
@@ -3556,6 +3563,14 @@
const Type& TypeTranslator::ReceiverType(const Class& klass) {
ASSERT(!klass.IsNull());
+ // Forward expression evaluation class to a real class when
+ // creating types.
+ if (translation_helper_.GetExpressionEvaluationClass().ptr() == klass.ptr()) {
+ ASSERT(translation_helper_.GetExpressionEvaluationRealClass().ptr() !=
+ klass.ptr());
+ return ReceiverType(translation_helper_.GetExpressionEvaluationRealClass());
+ }
+ ASSERT(klass.id() != kIllegalCid);
// Note that if klass is _Closure, the returned type will be _Closure,
// and not the signature type.
Type& type = Type::ZoneHandle(Z);
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 35b2647..ea30fa5 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -209,14 +209,27 @@
}
return *expression_evaluation_function_;
}
+ void SetExpressionEvaluationClass(const Class& cls) {
+ ASSERT(expression_evaluation_class_ == nullptr);
+ ASSERT(!cls.IsNull());
+ expression_evaluation_class_ = &Class::Handle(zone_, cls.ptr());
+ }
+ const Class& GetExpressionEvaluationClass() {
+ if (expression_evaluation_class_ == nullptr) {
+ return Class::null_class();
+ }
+ return *expression_evaluation_class_;
+ }
void SetExpressionEvaluationRealClass(const Class& real_class) {
ASSERT(expression_evaluation_real_class_ == nullptr);
ASSERT(!real_class.IsNull());
expression_evaluation_real_class_ = &Class::Handle(zone_, real_class.ptr());
}
- ClassPtr GetExpressionEvaluationRealClass() {
- ASSERT(expression_evaluation_real_class_ != nullptr);
- return expression_evaluation_real_class_->ptr();
+ const Class& GetExpressionEvaluationRealClass() {
+ if (expression_evaluation_real_class_ == nullptr) {
+ return Class::null_class();
+ }
+ return *expression_evaluation_real_class_;
}
private:
@@ -250,6 +263,14 @@
Smi& name_index_handle_;
GrowableObjectArray* potential_extension_libraries_ = nullptr;
Function* expression_evaluation_function_ = nullptr;
+
+ // A temporary class needed to contain the function to which an eval
+ // expression is compiled. This is a fresh class so loading the kernel
+ // isn't a no-op. It should be unreachable after the eval function is loaded.
+ Class* expression_evaluation_class_ = nullptr;
+
+ // The original class that is the scope in which the eval expression is
+ // evaluated.
Class* expression_evaluation_real_class_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TranslationHelper);
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index a4e6c1a..8b8468d 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -95,6 +95,8 @@
Dart_Handle Api::false_handle_ = NULL;
Dart_Handle Api::null_handle_ = NULL;
Dart_Handle Api::empty_string_handle_ = NULL;
+Dart_Handle Api::no_callbacks_error_handle_ = NULL;
+Dart_Handle Api::unwind_in_progress_error_handle_ = NULL;
const char* CanonicalFunction(const char* func) {
if (strncmp(func, "dart::", 6) == 0) {
@@ -478,23 +480,6 @@
return Api::NewHandle(T, error.ptr());
}
-Dart_Handle Api::AcquiredError(IsolateGroup* isolate_group) {
- ApiState* state = isolate_group->api_state();
- ASSERT(state != NULL);
- PersistentHandle* acquired_error_handle = state->AcquiredError();
- return reinterpret_cast<Dart_Handle>(acquired_error_handle);
-}
-
-Dart_Handle Api::UnwindInProgressError() {
- Thread* T = Thread::Current();
- CHECK_API_SCOPE(T);
- TransitionToVM transition(T);
- HANDLESCOPE(T);
- const String& message = String::Handle(
- Z, String::New("No api calls are allowed while unwind is in progress"));
- return Api::NewHandle(T, UnwindError::New(message));
-}
-
bool Api::IsValid(Dart_Handle handle) {
Isolate* isolate = Isolate::Current();
Thread* thread = Thread::Current();
@@ -551,6 +536,14 @@
ASSERT(empty_string_handle_ == NULL);
empty_string_handle_ = InitNewReadOnlyApiHandle(Symbols::Empty().ptr());
+
+ ASSERT(no_callbacks_error_handle_ == NULL);
+ no_callbacks_error_handle_ =
+ InitNewReadOnlyApiHandle(Object::no_callbacks_error().ptr());
+
+ ASSERT(unwind_in_progress_error_handle_ == NULL);
+ unwind_in_progress_error_handle_ =
+ InitNewReadOnlyApiHandle(Object::unwind_in_progress_error().ptr());
}
void Api::Cleanup() {
@@ -558,6 +551,8 @@
false_handle_ = NULL;
null_handle_ = NULL;
empty_string_handle_ = NULL;
+ no_callbacks_error_handle_ = NULL;
+ unwind_in_progress_error_handle_ = NULL;
}
bool Api::StringGetPeerHelper(NativeArguments* arguments,
@@ -1156,9 +1151,9 @@
ApiState* state = isolate_group->api_state();
ASSERT(state != NULL);
ASSERT(state->IsActivePersistentHandle(object));
- PersistentHandle* ref = PersistentHandle::Cast(object);
- ASSERT(!state->IsProtectedHandle(ref));
- if (!state->IsProtectedHandle(ref)) {
+ ASSERT(!Api::IsProtectedHandle(object));
+ if (!Api::IsProtectedHandle(object)) {
+ PersistentHandle* ref = PersistentHandle::Cast(object);
state->FreePersistentHandle(ref);
}
}
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 47f9b7a..73f681f 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -181,12 +181,6 @@
// Gets the handle used to designate successful return.
static Dart_Handle Success() { return Api::True(); }
- // Gets the handle which holds the pre-created acquired error object.
- static Dart_Handle AcquiredError(IsolateGroup* isolate_group);
-
- // Gets the handle for unwind-is-in-progress error.
- static Dart_Handle UnwindInProgressError();
-
// Returns true if the handle holds a Smi.
static bool IsSmi(Dart_Handle handle) {
// Important: we do not require current thread to be in VM state because
@@ -241,6 +235,22 @@
// Gets a handle to EmptyString.
static Dart_Handle EmptyString() { return empty_string_handle_; }
+ // Gets the handle which holds the pre-created acquired error object.
+ static Dart_Handle NoCallbacksError() { return no_callbacks_error_handle_; }
+
+ // Gets the handle for unwind-is-in-progress error.
+ static Dart_Handle UnwindInProgressError() {
+ return unwind_in_progress_error_handle_;
+ }
+
+ static bool IsProtectedHandle(Dart_Handle object) {
+ if (object == NULL) return false;
+ return (object == true_handle_) || (object == false_handle_) ||
+ (object == null_handle_) || (object == empty_string_handle_) ||
+ (object == no_callbacks_error_handle_) ||
+ (object == unwind_in_progress_error_handle_);
+ }
+
// Retrieves the top ApiLocalScope.
static ApiLocalScope* TopScope(Thread* thread);
@@ -314,6 +324,8 @@
static Dart_Handle false_handle_;
static Dart_Handle null_handle_;
static Dart_Handle empty_string_handle_;
+ static Dart_Handle no_callbacks_error_handle_;
+ static Dart_Handle unwind_in_progress_error_handle_;
friend class ApiNativeScope;
};
@@ -326,8 +338,7 @@
#define CHECK_CALLBACK_STATE(thread) \
if (thread->no_callback_scope_depth() != 0) { \
- return reinterpret_cast<Dart_Handle>( \
- Api::AcquiredError(thread->isolate_group())); \
+ return reinterpret_cast<Dart_Handle>(Api::NoCallbacksError()); \
} \
if (thread->is_unwind_in_progress()) { \
return reinterpret_cast<Dart_Handle>(Api::UnwindInProgressError()); \
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 02cbfa3..c9851a6 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -2602,9 +2602,7 @@
// Now try allocating a string with outstanding Acquires and it should
// return an error.
result = NewString("We expect an error here");
- EXPECT_ERROR(result,
- "Internal Dart data pointers have been acquired, "
- "please release them using Dart_TypedDataReleaseData.");
+ EXPECT_ERROR(result, "Callbacks into the Dart VM are currently prohibited");
// Now modify the values in the directly accessible array and then check
// it we see the changes back in dart.
diff --git a/runtime/vm/dart_api_state.h b/runtime/vm/dart_api_state.h
index e23252e..f3f9775 100644
--- a/runtime/vm/dart_api_state.h
+++ b/runtime/vm/dart_api_state.h
@@ -702,31 +702,7 @@
// group basis and destroyed when the isolate group is shutdown.
class ApiState {
public:
- ApiState()
- : persistent_handles_(),
- weak_persistent_handles_(),
- null_(NULL),
- true_(NULL),
- false_(NULL),
- acquired_error_(NULL) {}
- ~ApiState() {
- if (null_ != NULL) {
- persistent_handles_.FreeHandle(null_);
- null_ = NULL;
- }
- if (true_ != NULL) {
- persistent_handles_.FreeHandle(true_);
- true_ = NULL;
- }
- if (false_ != NULL) {
- persistent_handles_.FreeHandle(false_);
- false_ = NULL;
- }
- if (acquired_error_ != NULL) {
- persistent_handles_.FreeHandle(acquired_error_);
- acquired_error_ = NULL;
- }
- }
+ ApiState() : persistent_handles_(), weak_persistent_handles_() {}
void MergeOtherApiState(ApiState* api_state);
@@ -790,30 +766,11 @@
!weak_persistent_handles_.IsFreeHandle(object);
}
- bool IsProtectedHandle(PersistentHandle* object) {
- MutexLocker ml(&mutex_);
- if (object == NULL) return false;
- return object == null_ || object == true_ || object == false_;
- }
-
int CountPersistentHandles() {
MutexLocker ml(&mutex_);
return persistent_handles_.CountHandles();
}
- PersistentHandle* AcquiredError() {
- // The ApiError pre-allocated in the "vm-isolate" since we will not be able
- // to allocate it when the error actually occurs.
- // When the error occurs there will be outstanding acquires to internal
- // data pointers making it unsafe to allocate objects on the dart heap.
- MutexLocker ml(&mutex_);
- if (acquired_error_ == nullptr) {
- acquired_error_ = persistent_handles_.AllocateHandle();
- acquired_error_->set_ptr(ApiError::typed_data_acquire_error());
- }
- return acquired_error_;
- }
-
void RunWithLockedPersistentHandles(
std::function<void(PersistentHandles&)> fun) {
MutexLocker ml(&mutex_);
@@ -835,12 +792,6 @@
FinalizablePersistentHandles weak_persistent_handles_;
WeakTable acquired_table_;
- // Persistent handles to important objects.
- PersistentHandle* null_;
- PersistentHandle* true_;
- PersistentHandle* false_;
- PersistentHandle* acquired_error_;
-
DISALLOW_COPY_AND_ASSIGN(ApiState);
};
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index dfac508..5194918 100644
--- a/runtime/vm/json_stream.cc
+++ b/runtime/vm/json_stream.cc
@@ -37,7 +37,9 @@
param_values_(NULL),
num_params_(0),
offset_(0),
- count_(-1) {
+ count_(-1),
+ include_private_members_(true),
+ ignore_object_depth_(0) {
ObjectIdRing* ring = NULL;
Isolate* isolate = Isolate::Current();
if (isolate != NULL) {
@@ -90,6 +92,10 @@
"request %s\n",
Dart::UptimeMillis(), main_port, isolate_name, method_);
}
+ const char* kIncludePrivateMembersKey = "_includePrivateMembers";
+ if (HasParam(kIncludePrivateMembersKey)) {
+ include_private_members_ = ParamIs(kIncludePrivateMembersKey, "true");
+ }
buffer()->Printf("{\"jsonrpc\":\"2.0\", \"result\":");
}
@@ -368,49 +374,61 @@
PrintProperty("id", id_zone_->GetServiceId(o));
}
+#define PRIVATE_NAME_CHECK() \
+ if (!IsAllowableKey(name) || ignore_object_depth_ > 0) return
+
void JSONStream::PrintProperty(const char* name, const ServiceEvent* event) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(event);
}
void JSONStream::PrintProperty(const char* name, Breakpoint* bpt) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(bpt);
}
void JSONStream::PrintProperty(const char* name, TokenPosition tp) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(tp);
}
void JSONStream::PrintProperty(const char* name, Metric* metric) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(metric);
}
void JSONStream::PrintProperty(const char* name, MessageQueue* queue) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(queue);
}
void JSONStream::PrintProperty(const char* name, Isolate* isolate) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(isolate);
}
void JSONStream::PrintProperty(const char* name,
const TimelineEvent* timeline_event) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(timeline_event);
}
void JSONStream::PrintProperty(const char* name,
const TimelineEventBlock* timeline_event_block) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(timeline_event_block);
}
void JSONStream::PrintfProperty(const char* name, const char* format, ...) {
+ PRIVATE_NAME_CHECK();
va_list args;
va_start(args, format);
writer_.VPrintfProperty(name, format, args);
@@ -462,11 +480,13 @@
}
void JSONStream::PrintProperty(const char* name, const Object& o, bool ref) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValue(o, ref);
}
void JSONStream::PrintPropertyVM(const char* name, bool ref) {
+ PRIVATE_NAME_CHECK();
PrintPropertyName(name);
PrintValueVM(ref);
}
diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h
index a00f266..5b37379 100644
--- a/runtime/vm/json_stream.h
+++ b/runtime/vm/json_stream.h
@@ -9,6 +9,7 @@
#include "platform/allocation.h"
#include "platform/text_buffer.h"
#include "vm/json_writer.h"
+#include "vm/os.h"
#include "vm/service.h"
#include "vm/token_position.h"
@@ -102,6 +103,18 @@
void set_reply_port(Dart_Port port);
+ bool include_private_members() const { return include_private_members_; }
+ void set_include_private_members(bool include_private_members) {
+ include_private_members_ = include_private_members;
+ }
+
+ bool IsAllowableKey(const char* key) {
+ if (include_private_members_) {
+ return true;
+ }
+ return *key != '_';
+ }
+
void SetParams(const char** param_keys,
const char** param_values,
intptr_t num_params);
@@ -167,15 +180,41 @@
void PostNullReply(Dart_Port port);
void OpenObject(const char* property_name = NULL) {
+ if (ignore_object_depth_ > 0 ||
+ (property_name != nullptr && !IsAllowableKey(property_name))) {
+ ignore_object_depth_++;
+ return;
+ }
writer_.OpenObject(property_name);
}
- void CloseObject() { writer_.CloseObject(); }
- void UncloseObject() { writer_.UncloseObject(); }
+ void CloseObject() {
+ if (ignore_object_depth_ > 0) {
+ ignore_object_depth_--;
+ return;
+ }
+ writer_.CloseObject();
+ }
+ void UncloseObject() {
+ // This should be updated to handle unclosing a private object if we need
+ // to handle that case, which we don't currently.
+ writer_.UncloseObject();
+ }
void OpenArray(const char* property_name = NULL) {
+ if (ignore_object_depth_ > 0 ||
+ (property_name != nullptr && !IsAllowableKey(property_name))) {
+ ignore_object_depth_++;
+ return;
+ }
writer_.OpenArray(property_name);
}
- void CloseArray() { writer_.CloseArray(); }
+ void CloseArray() {
+ if (ignore_object_depth_ > 0) {
+ ignore_object_depth_--;
+ return;
+ }
+ writer_.CloseArray();
+ }
void PrintValueNull() { writer_.PrintValueNull(); }
void PrintValueBool(bool b) { writer_.PrintValueBool(b); }
@@ -211,46 +250,67 @@
void PrintServiceId(const Object& o);
+#define PRIVATE_NAME_CHECK() \
+ if (!IsAllowableKey(name) || ignore_object_depth_ > 0) { \
+ return; \
+ }
+
void PrintPropertyBool(const char* name, bool b) {
+ PRIVATE_NAME_CHECK();
writer_.PrintPropertyBool(name, b);
}
void PrintProperty(const char* name, intptr_t i) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty(name, i);
}
void PrintProperty64(const char* name, int64_t i) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty64(name, i);
}
void PrintPropertyTimeMillis(const char* name, int64_t millis) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty64(name, millis);
}
void PrintPropertyTimeMicros(const char* name, int64_t micros) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty64(name, micros);
}
void PrintProperty(const char* name, double d) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty(name, d);
}
void PrintPropertyBase64(const char* name,
const uint8_t* bytes,
intptr_t length) {
+ PRIVATE_NAME_CHECK();
writer_.PrintPropertyBase64(name, bytes, length);
}
void PrintProperty(const char* name, const char* s) {
+ PRIVATE_NAME_CHECK();
writer_.PrintProperty(name, s);
}
bool PrintPropertyStr(const char* name,
const String& s,
intptr_t offset,
intptr_t count) {
+ if (!IsAllowableKey(name)) {
+ return false;
+ }
return writer_.PrintPropertyStr(name, s, offset, count);
}
void PrintPropertyNoEscape(const char* name, const char* s) {
+ PRIVATE_NAME_CHECK();
writer_.PrintPropertyNoEscape(name, s);
}
void PrintfProperty(const char* name, const char* format, ...)
PRINTF_ATTRIBUTE(3, 4);
void VPrintfProperty(const char* name, const char* format, va_list args) {
+ PRIVATE_NAME_CHECK();
writer_.VPrintfProperty(name, format, args);
}
+
+#undef PRIVATE_NAME_CHECK
+
void PrintProperty(const char* name, const Object& o, bool ref = true);
void PrintProperty(const char* name, const ServiceEvent* event);
@@ -285,7 +345,8 @@
intptr_t offset_;
intptr_t count_;
int64_t setup_time_micros_;
-
+ bool include_private_members_;
+ intptr_t ignore_object_depth_;
friend class JSONObject;
friend class JSONArray;
friend class TimelineEvent;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 39689f6..0507227 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -706,6 +706,7 @@
// Load the "evaluate:source" expression evaluation library.
ASSERT(expression_evaluation_library_.IsNull());
+ ASSERT(H.GetExpressionEvaluationClass().IsNull());
ASSERT(H.GetExpressionEvaluationFunction().IsNull());
H.SetExpressionEvaluationRealClass(real_class);
const Object& result = Object::Handle(Z, LoadProgram(true));
@@ -1449,6 +1450,9 @@
// they are not reachable anymore and we never look them up by name.
const bool register_class =
library.ptr() != expression_evaluation_library_.ptr();
+ if (!register_class) {
+ H.SetExpressionEvaluationClass(*out_class);
+ }
if (loading_native_wrappers_library_ || !register_class) {
FinishClassLoading(*out_class, library, toplevel_class, class_offset,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 3259317..cb4dcdf 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1158,10 +1158,14 @@
String& error_str = String::Handle();
error_str = String::New(
- "Internal Dart data pointers have been acquired, please release them "
- "using Dart_TypedDataReleaseData.",
+ "Callbacks into the Dart VM are currently prohibited. Either there are "
+ "outstanding pointers from Dart_TypedDataAcquireData that have not been "
+ "released with Dart_TypedDataReleaseData, or a finalizer is running.",
Heap::kOld);
- *typed_data_acquire_error_ = ApiError::New(error_str, Heap::kOld);
+ *no_callbacks_error_ = ApiError::New(error_str, Heap::kOld);
+ error_str = String::New(
+ "No api calls are allowed while unwind is in progress", Heap::kOld);
+ *unwind_in_progress_error_ = UnwindError::New(error_str, Heap::kOld);
error_str = String::New("SnapshotWriter Error", Heap::kOld);
*snapshot_writer_error_ =
LanguageError::New(error_str, Report::kError, Heap::kOld);
@@ -1238,8 +1242,10 @@
ASSERT(bool_false_->IsBool());
ASSERT(smi_illegal_cid_->IsSmi());
ASSERT(smi_zero_->IsSmi());
- ASSERT(!typed_data_acquire_error_->IsSmi());
- ASSERT(typed_data_acquire_error_->IsApiError());
+ ASSERT(!no_callbacks_error_->IsSmi());
+ ASSERT(no_callbacks_error_->IsApiError());
+ ASSERT(!unwind_in_progress_error_->IsSmi());
+ ASSERT(unwind_in_progress_error_->IsUnwindError());
ASSERT(!snapshot_writer_error_->IsSmi());
ASSERT(snapshot_writer_error_->IsLanguageError());
ASSERT(!branch_offset_error_->IsSmi());
@@ -21294,10 +21300,8 @@
ASSERT(Utils::IsUint(sizeof(untag()->type_class_id_) * kBitsPerByte, id));
// We should never need a Type object for a top-level class.
ASSERT(!ClassTable::IsTopLevelCid(id));
- // We must allow Types with kIllegalCid type class ids, because the class
- // used for evaluating expressions inside a instance method call context
- // from the debugger is not registered (and thus has kIllegalCid as an id).
- ASSERT(id == kIllegalCid || !IsInternalOnlyClassId(id));
+ ASSERT(id != kIllegalCid);
+ ASSERT(!IsInternalOnlyClassId(id));
StoreNonPointer(&untag()->type_class_id_, id);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index c402aab..ab78804 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -453,7 +453,8 @@
V(Bool, bool_false) \
V(Smi, smi_illegal_cid) \
V(Smi, smi_zero) \
- V(ApiError, typed_data_acquire_error) \
+ V(ApiError, no_callbacks_error) \
+ V(UnwindError, unwind_in_progress_error) \
V(LanguageError, snapshot_writer_error) \
V(LanguageError, branch_offset_error) \
V(LanguageError, speculative_inlining_error) \
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 50238aa..38e0d75 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -367,7 +367,8 @@
&Service::timeline_stream, &Service::profiler_stream,
};
-bool Service::ListenStream(const char* stream_id) {
+bool Service::ListenStream(const char* stream_id,
+ bool include_private_members) {
if (FLAG_trace_service) {
OS::PrintErr("vm-service: starting stream '%s'\n", stream_id);
}
@@ -375,6 +376,7 @@
for (intptr_t i = 0; i < num_streams; i++) {
if (strcmp(stream_id, streams_[i]->id()) == 0) {
streams_[i]->set_enabled(true);
+ streams_[i]->set_include_private_members(include_private_members);
return true;
}
}
@@ -1164,7 +1166,7 @@
}
void Service::HandleEvent(ServiceEvent* event, bool enter_safepoint) {
- if (event->stream_info() != NULL && !event->stream_info()->enabled()) {
+ if (event->stream_info() != nullptr && !event->stream_info()->enabled()) {
if (FLAG_warn_on_pause_with_no_debugger && event->IsPause()) {
// If we are about to pause a running program which has no
// debugger connected, tell the user about it.
@@ -1172,7 +1174,7 @@
}
// Ignore events when no one is listening to the event stream.
return;
- } else if (event->stream_info() != NULL &&
+ } else if (event->stream_info() != nullptr &&
FLAG_warn_on_pause_with_no_debugger && event->IsPause()) {
ReportPauseOnConsole(event);
}
@@ -1180,8 +1182,12 @@
return;
}
JSONStream js;
+ if (event->stream_info() != nullptr) {
+ js.set_include_private_members(
+ event->stream_info()->include_private_members());
+ }
const char* stream_id = event->stream_id();
- ASSERT(stream_id != NULL);
+ ASSERT(stream_id != nullptr);
{
JSONObject jsobj(&js);
jsobj.AddProperty("jsonrpc", "2.0");
@@ -1495,6 +1501,31 @@
}
}
+static const MethodParameter* const
+ set_stream_include_private_members_params[] = {
+ NO_ISOLATE_PARAMETER,
+ new BoolParameter("includePrivateMembers", true),
+ nullptr,
+};
+
+static void SetStreamIncludePrivateMembers(Thread* thread, JSONStream* js) {
+ const char* stream_id = js->LookupParam("streamId");
+ if (stream_id == nullptr) {
+ PrintMissingParamError(js, "streamId");
+ return;
+ }
+ bool include_private_members =
+ BoolParameter::Parse(js->LookupParam("includePrivateMembers"), false);
+ intptr_t num_streams = sizeof(streams_) / sizeof(streams_[0]);
+ for (intptr_t i = 0; i < num_streams; i++) {
+ if (strcmp(stream_id, streams_[i]->id()) == 0) {
+ streams_[i]->set_include_private_members(include_private_members);
+ break;
+ }
+ }
+ PrintSuccess(js);
+}
+
static void ActOnIsolateGroup(JSONStream* js,
std::function<void(IsolateGroup*)> visitor) {
const String& prefix =
@@ -5626,6 +5657,8 @@
set_library_debuggable_params },
{ "setName", SetName,
set_name_params },
+ { "_setStreamIncludePrivateMembers", SetStreamIncludePrivateMembers,
+ set_stream_include_private_members_params },
{ "setTraceClassAllocation", SetTraceClassAllocation,
set_trace_class_allocation_params },
{ "setVMName", SetVMName,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index f625b94..751c1e5 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -68,16 +68,23 @@
class StreamInfo {
public:
- explicit StreamInfo(const char* id) : id_(id), enabled_(false) {}
+ explicit StreamInfo(const char* id)
+ : id_(id), enabled_(false), include_private_members_(false) {}
const char* id() const { return id_; }
void set_enabled(bool value) { enabled_ = value; }
bool enabled() const { return enabled_; }
+ void set_include_private_members(bool value) {
+ include_private_members_ = value;
+ }
+ bool include_private_members() const { return include_private_members_; }
+
private:
const char* id_;
bool enabled_;
+ bool include_private_members_;
};
class Service : public AllStatic {
@@ -168,7 +175,7 @@
static StreamInfo timeline_stream;
static StreamInfo profiler_stream;
- static bool ListenStream(const char* stream_id);
+ static bool ListenStream(const char* stream_id, bool include_privates);
static void CancelStream(const char* stream_id);
static ObjectPtr RequestAssets();
diff --git a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
index b01ebb6..8db9d2a 100644
--- a/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/collection_patch.dart
@@ -17,8 +17,6 @@
import 'dart:_internal' hide Symbol;
-const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
-
const int _mask30 = 0x3fffffff; // Low 30 bits.
@patch
@@ -509,13 +507,13 @@
if (isValidKey == null) {
if (hashCode == null) {
if (equals == null) {
- return new JsLinkedHashMap<K, V>.es6();
+ return new JsLinkedHashMap<K, V>();
}
hashCode = _defaultHashCode;
} else {
if (identical(identityHashCode, hashCode) &&
identical(identical, equals)) {
- return new _LinkedIdentityHashMap<K, V>.es6();
+ return new _LinkedIdentityHashMap<K, V>();
}
if (equals == null) {
equals = _defaultEquals;
@@ -533,12 +531,12 @@
}
@patch
- factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>.es6;
+ factory LinkedHashMap.identity() = _LinkedIdentityHashMap<K, V>;
// Private factory constructor called by generated code for map literals.
@pragma('dart2js:noInline')
factory LinkedHashMap._literal(List keyValuePairs) {
- return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>.es6());
+ return fillLiteralMap(keyValuePairs, new JsLinkedHashMap<K, V>());
}
// Private factory constructor called by generated code for map literals.
@@ -546,7 +544,7 @@
@pragma('dart2js:noInline')
@pragma('dart2js:noSideEffects')
factory LinkedHashMap._empty() {
- return new JsLinkedHashMap<K, V>.es6();
+ return new JsLinkedHashMap<K, V>();
}
// Private factory static function called by generated code for map literals.
@@ -564,17 +562,6 @@
}
class _LinkedIdentityHashMap<K, V> extends JsLinkedHashMap<K, V> {
- static bool get _supportsEs6Maps {
- return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
- 'typeof Map != "undefined"');
- }
-
- factory _LinkedIdentityHashMap.es6() {
- return (_USE_ES6_MAPS && _LinkedIdentityHashMap._supportsEs6Maps)
- ? new _Es6LinkedIdentityHashMap<K, V>()
- : new _LinkedIdentityHashMap<K, V>();
- }
-
_LinkedIdentityHashMap();
int internalComputeHashCode(var key) {
@@ -595,161 +582,6 @@
}
}
-class _Es6LinkedIdentityHashMap<K, V> extends _LinkedIdentityHashMap<K, V>
- implements InternalMap {
- final _map;
- int _modifications = 0;
-
- _Es6LinkedIdentityHashMap() : _map = JS('var', 'new Map()');
-
- int get length => JS('int', '#.size', _map);
- bool get isEmpty => length == 0;
- bool get isNotEmpty => !isEmpty;
-
- Iterable<K> get keys => new _Es6MapIterable<K>(this, true);
-
- Iterable<V> get values => new _Es6MapIterable<V>(this, false);
-
- bool containsKey(Object? key) {
- return JS('bool', '#.has(#)', _map, key);
- }
-
- bool containsValue(Object? value) {
- return values.any((each) => each == value);
- }
-
- void addAll(Map<K, V> other) {
- other.forEach((K key, V value) {
- this[key] = value;
- });
- }
-
- V? operator [](Object? key) {
- return JS('var', '#.get(#)', _map, key);
- }
-
- void operator []=(K key, V value) {
- JS('var', '#.set(#, #)', _map, key, value);
- _modified();
- }
-
- V putIfAbsent(K key, V ifAbsent()) {
- if (containsKey(key)) return this[key] as V;
- V value = ifAbsent();
- this[key] = value;
- return value;
- }
-
- V? remove(Object? key) {
- V? value = this[key];
- JS('bool', '#.delete(#)', _map, key);
- _modified();
- return value;
- }
-
- void clear() {
- JS('void', '#.clear()', _map);
- _modified();
- }
-
- void forEach(void action(K key, V value)) {
- var jsEntries = JS('var', '#.entries()', _map);
- int modifications = _modifications;
- while (true) {
- var next = JS('var', '#.next()', jsEntries);
- bool done = JS('bool', '#.done', next);
- if (done) break;
- var entry = JS('var', '#.value', next);
- var key = JS('var', '#[0]', entry);
- var value = JS('var', '#[1]', entry);
- action(key, value);
- if (modifications != _modifications) {
- throw new ConcurrentModificationError(this);
- }
- }
- }
-
- void _modified() {
- // Value cycles after 2^30 modifications so that modification counts are
- // always unboxed (Smi) values. Modification detection will be missed if you
- // make exactly some multiple of 2^30 modifications between advances of an
- // iterator.
- _modifications = _mask30 & (_modifications + 1);
- }
-}
-
-class _Es6MapIterable<E> extends EfficientLengthIterable<E> {
- final _Es6LinkedIdentityHashMap _map;
- final bool _isKeys;
-
- _Es6MapIterable(this._map, this._isKeys);
-
- int get length => _map.length;
- bool get isEmpty => _map.isEmpty;
-
- Iterator<E> get iterator =>
- new _Es6MapIterator<E>(_map, _map._modifications, _isKeys);
-
- bool contains(Object? element) => _map.containsKey(element);
-
- void forEach(void f(E element)) {
- var jsIterator;
- if (_isKeys) {
- jsIterator = JS('var', '#.keys()', _map._map);
- } else {
- jsIterator = JS('var', '#.values()', _map._map);
- }
- int modifications = _map._modifications;
- while (true) {
- var next = JS('var', '#.next()', jsIterator);
- bool done = JS('bool', '#.done', next);
- if (done) break;
- var value = JS('var', '#.value', next);
- f(value);
- if (modifications != _map._modifications) {
- throw new ConcurrentModificationError(_map);
- }
- }
- }
-}
-
-class _Es6MapIterator<E> implements Iterator<E> {
- final _Es6LinkedIdentityHashMap _map;
- final int _modifications;
- final bool _isKeys;
- var _jsIterator;
- var _next;
- E? _current;
- bool _done = false;
-
- _Es6MapIterator(this._map, this._modifications, this._isKeys) {
- if (_isKeys) {
- _jsIterator = JS('var', '#.keys()', _map._map);
- } else {
- _jsIterator = JS('var', '#.values()', _map._map);
- }
- }
-
- E get current => _current as E;
-
- bool moveNext() {
- if (_modifications != _map._modifications) {
- throw new ConcurrentModificationError(_map);
- }
- if (_done) return false;
- _next = JS('var', '#.next()', _jsIterator);
- bool done = JS('bool', '#.done', _next);
- if (done) {
- _current = null;
- _done = true;
- return false;
- } else {
- _current = JS('var', '#.value', _next);
- return true;
- }
- }
-}
-
// TODO(floitsch): use ES6 maps when available.
class _LinkedCustomHashMap<K, V> extends JsLinkedHashMap<K, V> {
final _Equality<K> _equals;
diff --git a/sdk/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index 6d4d129..9579a76 100644
--- a/sdk/lib/_internal/js_runtime/lib/core_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
@@ -478,7 +478,7 @@
factory Map.unmodifiable(Map other) = ConstantMap<K, V>.from;
@patch
- factory Map() = JsLinkedHashMap<K, V>.es6;
+ factory Map() = JsLinkedHashMap<K, V>;
}
@patch
diff --git a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
index fdf9d23..bd8533a 100644
--- a/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
+++ b/sdk/lib/_internal/js_runtime/lib/linked_hash_map.dart
@@ -7,8 +7,6 @@
part of _js_helper;
-const _USE_ES6_MAPS = const bool.fromEnvironment("dart2js.use.es6.maps");
-
class JsLinkedHashMap<K, V> extends MapBase<K, V>
implements LinkedHashMap<K, V>, InternalMap {
int _length = 0;
@@ -35,21 +33,8 @@
// iterated over.
int _modifications = 0;
- static bool get _supportsEs6Maps {
- return JS('returns:bool;depends:none;effects:none;throws:never;gvn:true',
- 'typeof Map != "undefined"');
- }
-
JsLinkedHashMap();
- /// If ES6 Maps are available returns a linked hash-map backed by an ES6 Map.
- @pragma('dart2js:tryInline')
- factory JsLinkedHashMap.es6() {
- return (_USE_ES6_MAPS && JsLinkedHashMap._supportsEs6Maps)
- ? new Es6LinkedHashMap<K, V>()
- : new JsLinkedHashMap<K, V>();
- }
-
int get length => _length;
bool get isEmpty => _length == 0;
bool get isNotEmpty => !isEmpty;
@@ -342,38 +327,6 @@
}
}
-class Es6LinkedHashMap<K, V> extends JsLinkedHashMap<K, V> {
- @override
- LinkedHashMapCell? _getTableCell(var table, var key) {
- return JS('var', '#.get(#)', table, key);
- }
-
- @override
- List<LinkedHashMapCell>? _getTableBucket(var table, var key) {
- return JS('var', '#.get(#)', table, key);
- }
-
- @override
- void _setTableEntry(var table, var key, var value) {
- JS('void', '#.set(#, #)', table, key, value);
- }
-
- @override
- void _deleteTableEntry(var table, var key) {
- JS('void', '#.delete(#)', table, key);
- }
-
- @override
- bool _containsTableEntry(var table, var key) {
- return JS('bool', '#.has(#)', table, key);
- }
-
- @override
- _newHashTable() {
- return JS('var', 'new Map()');
- }
-}
-
class LinkedHashMapCell {
final dynamic hashMapCellKey;
dynamic hashMapCellValue;
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart
index cbda1c3..dabd9f4 100644
--- a/sdk/lib/io/directory.dart
+++ b/sdk/lib/io/directory.dart
@@ -234,7 +234,7 @@
/// with a [Directory] for the renamed directory.
///
/// If [newPath] identifies an existing directory, then the behavior is
- /// platform-specific. On all platforms, the future completes with an
+ /// platform-specific. On all platforms, the future completes with a
/// [FileSystemException] if the existing directory is not empty. On POSIX
/// systems, if [newPath] identifies an existing empty directory then that
/// directory is deleted before this directory is renamed.
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index c9a168a..b62cc71 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -182,9 +182,6 @@
"web_gl": {
"uri": "web_gl/dart2js/web_gl_dart2js.dart"
},
- "_dart2js_runtime_metrics": {
- "uri": "_internal/js_runtime/lib/dart2js_runtime_metrics.dart"
- },
"_metadata": {
"uri": "html/html_common/metadata.dart"
}
diff --git a/sdk/lib/vmservice/vmservice.dart b/sdk/lib/vmservice/vmservice.dart
index 5af3cfd..ae16c86 100644
--- a/sdk/lib/vmservice/vmservice.dart
+++ b/sdk/lib/vmservice/vmservice.dart
@@ -549,7 +549,9 @@
return encodeRpcError(message, kStreamAlreadySubscribed);
}
if (!_isAnyClientSubscribed(streamId)) {
- if (!serviceStreams.contains(streamId) && !_vmListenStream(streamId)) {
+ final includePrivates = message.params['_includePrivateMembers'] == true;
+ if (!serviceStreams.contains(streamId) &&
+ !_vmListenStream(streamId, includePrivates)) {
return encodeRpcError(message, kInvalidParams,
details: "streamListen: invalid 'streamId' parameter: ${streamId}");
}
@@ -831,7 +833,7 @@
/// Subscribe to a service stream.
@pragma("vm:external-name", "VMService_ListenStream")
-external bool _vmListenStream(String streamId);
+external bool _vmListenStream(String streamId, bool include_privates);
/// Cancel a subscription to a service stream.
@pragma("vm:external-name", "VMService_CancelStream")
diff --git a/tests/language/control_flow_collections/await_for_dynamic_null_test.dart b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
index aad701f2..36286b9 100644
--- a/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
+++ b/tests/language/control_flow_collections/await_for_dynamic_null_test.dart
@@ -9,11 +9,14 @@
asyncTest(() async {
// Null stream.
dynamic nullStream = null;
- asyncExpectThrows<Error>(
- () async => <int>[await for (var i in nullStream) 1]);
- asyncExpectThrows<Error>(
- () async => <int, int>{await for (var i in nullStream) 1: 1});
- asyncExpectThrows<Error>(
- () async => <int>{await for (var i in nullStream) 1});
+ asyncExpectThrows<Error>(() async {
+ <int>[await for (var i in nullStream) 1];
+ }());
+ asyncExpectThrows<Error>(() async {
+ <int, int>{await for (var i in nullStream) 1: 1};
+ }());
+ asyncExpectThrows<Error>(() async {
+ <int>{await for (var i in nullStream) 1};
+ }());
});
}
diff --git a/tests/language/control_flow_collections/await_for_test.dart b/tests/language/control_flow_collections/await_for_test.dart
index ce84fe0..d98f9f2 100644
--- a/tests/language/control_flow_collections/await_for_test.dart
+++ b/tests/language/control_flow_collections/await_for_test.dart
@@ -30,17 +30,28 @@
Expect.listEquals(list, <int>[await for (var i in stream(list)) i]);
// Await for at beginning.
- Expect.listEquals(list, <int>[await for (var i in stream([1, 2])) i, 3, 4]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, 2])) i,
+ 3,
+ 4
+ ]);
// Await for in middle.
- Expect.listEquals(list, <int>[1, await for (var i in stream([2, 3])) i, 4]);
+ Expect.listEquals(list, <int>[
+ 1,
+ await for (var i in stream([2, 3])) i,
+ 4
+ ]);
// Await for at end.
- Expect.listEquals(list, <int>[1, 2, await for (var i in stream([3, 4])) i]);
+ Expect.listEquals(list, <int>[
+ 1,
+ 2,
+ await for (var i in stream([3, 4])) i
+ ]);
// Empty await for.
- Expect.listEquals(list,
- <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
+ Expect.listEquals(list, <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
// Multiple await fors.
Expect.listEquals(list, <int>[
@@ -50,26 +61,44 @@
]);
// Spread inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+ ]);
// If inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i
+ ]);
// Else inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i else i
+ ]);
// For inside await for.
Expect.listEquals(list, <int>[
- await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+ await for (var i in stream([0, 2]))
+ for (var j = 1; j <= 2; j++) i + j
]);
// Does not flatten nested collection literal.
- Expect.listEquals([1], [await for (var i in stream([1])) [i]].first);
- Expect.mapEquals({1: 1}, [await for (var i in stream([1])) {i: i}].first);
- Expect.setEquals({1}, [await for (var i in stream([1])) {i}].first);
+ Expect.listEquals(
+ [1],
+ [
+ await for (var i in stream([1])) [i]
+ ].first);
+ Expect.mapEquals(
+ {1: 1},
+ [
+ await for (var i in stream([1])) {i: i}
+ ].first);
+ Expect.setEquals(
+ {1},
+ [
+ await for (var i in stream([1])) {i}
+ ].first);
}
Future<void> testMap() async {
@@ -77,26 +106,30 @@
Expect.mapEquals(map, <int, int>{await for (var i in stream(list)) i: i});
// Await for at beginning.
- Expect.mapEquals(map,
- <int, int>{await for (var i in stream([1, 2])) i: i, 3: 3, 4: 4});
-
- // Await for in middle.
- Expect.mapEquals(map,
- <int, int>{1: 1, await for (var i in stream([2, 3])) i: i, 4: 4});
-
- // Await for at end.
- Expect.mapEquals(map,
- <int, int>{1: 1, 2: 2, await for (var i in stream([3, 4])) i: i});
-
- // Empty await for.
Expect.mapEquals(map, <int, int>{
- 1: 1,
- await for (var i in stream([])) i: i,
- 2: 2,
+ await for (var i in stream([1, 2])) i: i,
3: 3,
4: 4
});
+ // Await for in middle.
+ Expect.mapEquals(map, <int, int>{
+ 1: 1,
+ await for (var i in stream([2, 3])) i: i,
+ 4: 4
+ });
+
+ // Await for at end.
+ Expect.mapEquals(map, <int, int>{
+ 1: 1,
+ 2: 2,
+ await for (var i in stream([3, 4])) i: i
+ });
+
+ // Empty await for.
+ Expect.mapEquals(map,
+ <int, int>{1: 1, await for (var i in stream([])) i: i, 2: 2, 3: 3, 4: 4});
+
// Multiple await fors.
Expect.mapEquals(map, <int, int>{
await for (var i in stream([1])) i: i,
@@ -106,18 +139,22 @@
// Spread inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([0, 2]))
- ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+ await for (var i in stream([0, 2])) ...<int, int>{
+ 1 + i: 1 + i,
+ 2 + i: 2 + i
+ }
});
// If inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i: i
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i: i
});
// Else inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i: -i else i: i
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i: -i else i: i
});
// For inside await for.
@@ -132,17 +169,28 @@
Expect.setEquals(set, <int>{await for (var i in stream(list)) i});
// Await for at beginning.
- Expect.setEquals(set, <int>{await for (var i in stream([1, 2])) i, 3, 4});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, 2])) i,
+ 3,
+ 4
+ });
// Await for in middle.
- Expect.setEquals(set, <int>{1, await for (var i in stream([2, 3])) i, 4});
+ Expect.setEquals(set, <int>{
+ 1,
+ await for (var i in stream([2, 3])) i,
+ 4
+ });
// Await for at end.
- Expect.setEquals(set, <int>{1, 2, await for (var i in stream([3, 4])) i});
+ Expect.setEquals(set, <int>{
+ 1,
+ 2,
+ await for (var i in stream([3, 4])) i
+ });
// Empty await for.
- Expect.setEquals(set,
- <int>{1, await for (var i in stream([])) i, 2, 3, 4});
+ Expect.setEquals(set, <int>{1, await for (var i in stream([])) i, 2, 3, 4});
// Multiple await fors.
Expect.setEquals(set, <int>{
@@ -152,26 +200,44 @@
});
// Spread inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+ });
// If inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i
+ });
// Else inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i else i
+ });
// For inside await for.
Expect.setEquals(set, <int>{
- await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+ await for (var i in stream([0, 2]))
+ for (var j = 1; j <= 2; j++) i + j
});
// Does not flatten nested collection literal.
- Expect.listEquals([1], {await for (var i in stream([1])) [i]}.first);
- Expect.mapEquals({1: 1}, {await for (var i in stream([1])) {i: i}}.first);
- Expect.setEquals({1}, {await for (var i in stream([1])) {i}}.first);
+ Expect.listEquals(
+ [1],
+ {
+ await for (var i in stream([1])) [i]
+ }.first);
+ Expect.mapEquals(
+ {1: 1},
+ {
+ await for (var i in stream([1])) {i: i}
+ }.first);
+ Expect.setEquals(
+ {1},
+ {
+ await for (var i in stream([1])) {i}
+ }.first);
}
Future<void> testDuplicateKeys() async {
@@ -207,28 +273,46 @@
Expect.equals("1:a,2:a", map.keys.join(","));
Expect.equals("2,4", map.values.join(","));
- var set = <Equality>{e1a, await for (var i in stream([0, 1, 2])) keys[i]};
+ var set = <Equality>{
+ e1a,
+ await for (var i in stream([0, 1, 2])) keys[i]
+ };
Expect.equals("1:a,2:a", set.join(","));
}
Future<void> testRuntimeErrors() async {
// Cast variable.
dynamic nonStream = 3;
- asyncExpectThrows<TypeError>(
- () async => <int>[await for (int i in nonStream) 1]);
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (int i in nonStream) 1: 1});
- asyncExpectThrows<TypeError>(
- () async => <int>{await for (int i in nonStream) 1});
+ asyncExpectThrows<TypeError>(() async {
+ <int>[await for (int i in nonStream) 1];
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{await for (int i in nonStream) 1: 1};
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int>{await for (int i in nonStream) 1};
+ }());
// Wrong element type.
dynamic nonInt = "string";
- asyncExpectThrows<TypeError>(
- () async => <int>[await for (var i in stream([1])) nonInt]);
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (var i in stream([1])) nonInt: 1});
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (var i in stream([1])) 1: nonInt});
- asyncExpectThrows<TypeError>(
- () async => <int>{await for (var i in stream([1])) nonInt});
+ asyncExpectThrows<TypeError>(() async {
+ <int>[
+ await for (var i in stream([1])) nonInt
+ ];
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{
+ await for (var i in stream([1])) nonInt: 1
+ };
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{
+ await for (var i in stream([1])) 1: nonInt
+ };
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int>{
+ await for (var i in stream([1])) nonInt
+ };
+ }());
}
diff --git a/tests/language_2/control_flow_collections/await_for_null_test.dart b/tests/language_2/control_flow_collections/await_for_null_test.dart
index 47529b2..482cbff 100644
--- a/tests/language_2/control_flow_collections/await_for_null_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_null_test.dart
@@ -11,11 +11,14 @@
asyncTest(() async {
// Null stream.
Stream<int> nullStream = null;
- asyncExpectThrows<Error>(
- () async => <int>[await for (var i in nullStream) 1]);
- asyncExpectThrows<Error>(
- () async => <int, int>{await for (var i in nullStream) 1: 1});
- asyncExpectThrows<Error>(
- () async => <int>{await for (var i in nullStream) 1});
+ asyncExpectThrows<Error>(() async {
+ <int>[await for (var i in nullStream) 1];
+ }());
+ asyncExpectThrows<Error>(() async {
+ <int, int>{await for (var i in nullStream) 1: 1};
+ }());
+ asyncExpectThrows<Error>(() async {
+ <int>{await for (var i in nullStream) 1};
+ }());
});
}
diff --git a/tests/language_2/control_flow_collections/await_for_test.dart b/tests/language_2/control_flow_collections/await_for_test.dart
index 402820b..d661143 100644
--- a/tests/language_2/control_flow_collections/await_for_test.dart
+++ b/tests/language_2/control_flow_collections/await_for_test.dart
@@ -32,17 +32,28 @@
Expect.listEquals(list, <int>[await for (var i in stream(list)) i]);
// Await for at beginning.
- Expect.listEquals(list, <int>[await for (var i in stream([1, 2])) i, 3, 4]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, 2])) i,
+ 3,
+ 4
+ ]);
// Await for in middle.
- Expect.listEquals(list, <int>[1, await for (var i in stream([2, 3])) i, 4]);
+ Expect.listEquals(list, <int>[
+ 1,
+ await for (var i in stream([2, 3])) i,
+ 4
+ ]);
// Await for at end.
- Expect.listEquals(list, <int>[1, 2, await for (var i in stream([3, 4])) i]);
+ Expect.listEquals(list, <int>[
+ 1,
+ 2,
+ await for (var i in stream([3, 4])) i
+ ]);
// Empty await for.
- Expect.listEquals(list,
- <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
+ Expect.listEquals(list, <int>[1, 2, await for (var i in stream([])) i, 3, 4]);
// Multiple await fors.
Expect.listEquals(list, <int>[
@@ -52,38 +63,58 @@
]);
// Spread inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+ ]);
// If inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i
+ ]);
// Else inside await for.
- Expect.listEquals(list,
- <int>[await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i]);
+ Expect.listEquals(list, <int>[
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i else i
+ ]);
// For inside await for.
Expect.listEquals(list, <int>[
- await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+ await for (var i in stream([0, 2]))
+ for (var j = 1; j <= 2; j++) i + j
]);
// Does not flatten nested collection literal.
- Expect.listEquals([1], [await for (var i in stream([1])) [i]].first);
- Expect.mapEquals({1: 1}, [await for (var i in stream([1])) {i: i}].first);
- Expect.setEquals({1}, [await for (var i in stream([1])) {i}].first);
+ Expect.listEquals(
+ [1],
+ [
+ await for (var i in stream([1])) [i]
+ ].first);
+ Expect.mapEquals(
+ {1: 1},
+ [
+ await for (var i in stream([1])) {i: i}
+ ].first);
+ Expect.setEquals(
+ {1},
+ [
+ await for (var i in stream([1])) {i}
+ ].first);
// Downcast stream.
Object obj = stream([1, 2, 3, 4]);
Expect.listEquals(list, <int>[await for (var n in obj) n]);
// Downcast variable.
- Expect.listEquals(list,
- <int>[await for (int n in numStream([1, 2, 3, 4])) n]);
+ Expect.listEquals(list, <int>[
+ await for (int n in numStream([1, 2, 3, 4])) n
+ ]);
// Downcast element.
- Expect.listEquals(list,
- <int>[await for (num n in numStream([1, 2, 3, 4])) n]);
+ Expect.listEquals(list, <int>[
+ await for (num n in numStream([1, 2, 3, 4])) n
+ ]);
}
Future<void> testMap() async {
@@ -91,26 +122,30 @@
Expect.mapEquals(map, <int, int>{await for (var i in stream(list)) i: i});
// Await for at beginning.
- Expect.mapEquals(map,
- <int, int>{await for (var i in stream([1, 2])) i: i, 3: 3, 4: 4});
-
- // Await for in middle.
- Expect.mapEquals(map,
- <int, int>{1: 1, await for (var i in stream([2, 3])) i: i, 4: 4});
-
- // Await for at end.
- Expect.mapEquals(map,
- <int, int>{1: 1, 2: 2, await for (var i in stream([3, 4])) i: i});
-
- // Empty await for.
Expect.mapEquals(map, <int, int>{
- 1: 1,
- await for (var i in stream([])) i: i,
- 2: 2,
+ await for (var i in stream([1, 2])) i: i,
3: 3,
4: 4
});
+ // Await for in middle.
+ Expect.mapEquals(map, <int, int>{
+ 1: 1,
+ await for (var i in stream([2, 3])) i: i,
+ 4: 4
+ });
+
+ // Await for at end.
+ Expect.mapEquals(map, <int, int>{
+ 1: 1,
+ 2: 2,
+ await for (var i in stream([3, 4])) i: i
+ });
+
+ // Empty await for.
+ Expect.mapEquals(map,
+ <int, int>{1: 1, await for (var i in stream([])) i: i, 2: 2, 3: 3, 4: 4});
+
// Multiple await fors.
Expect.mapEquals(map, <int, int>{
await for (var i in stream([1])) i: i,
@@ -120,18 +155,22 @@
// Spread inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([0, 2]))
- ...<int, int>{1 + i: 1 + i, 2 + i: 2 + i}
+ await for (var i in stream([0, 2])) ...<int, int>{
+ 1 + i: 1 + i,
+ 2 + i: 2 + i
+ }
});
// If inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i: i
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i: i
});
// Else inside await for.
Expect.mapEquals(map, <int, int>{
- await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i: -i else i: i
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i: -i else i: i
});
// For inside await for.
@@ -145,12 +184,14 @@
Expect.mapEquals(map, <int, int>{await for (var n in obj) n: n});
// Downcast variable.
- Expect.mapEquals(map,
- <int, int>{await for (int n in numStream([1, 2, 3, 4])) n: n});
+ Expect.mapEquals(map, <int, int>{
+ await for (int n in numStream([1, 2, 3, 4])) n: n
+ });
// Downcast element.
- Expect.mapEquals(map,
- <int, int>{await for (num n in numStream([1, 2, 3, 4])) n: n});
+ Expect.mapEquals(map, <int, int>{
+ await for (num n in numStream([1, 2, 3, 4])) n: n
+ });
}
Future<void> testSet() async {
@@ -158,17 +199,28 @@
Expect.setEquals(set, <int>{await for (var i in stream(list)) i});
// Await for at beginning.
- Expect.setEquals(set, <int>{await for (var i in stream([1, 2])) i, 3, 4});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, 2])) i,
+ 3,
+ 4
+ });
// Await for in middle.
- Expect.setEquals(set, <int>{1, await for (var i in stream([2, 3])) i, 4});
+ Expect.setEquals(set, <int>{
+ 1,
+ await for (var i in stream([2, 3])) i,
+ 4
+ });
// Await for at end.
- Expect.setEquals(set, <int>{1, 2, await for (var i in stream([3, 4])) i});
+ Expect.setEquals(set, <int>{
+ 1,
+ 2,
+ await for (var i in stream([3, 4])) i
+ });
// Empty await for.
- Expect.setEquals(set,
- <int>{1, await for (var i in stream([])) i, 2, 3, 4});
+ Expect.setEquals(set, <int>{1, await for (var i in stream([])) i, 2, 3, 4});
// Multiple await fors.
Expect.setEquals(set, <int>{
@@ -178,36 +230,58 @@
});
// Spread inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([0, 2])) ...<int>[1 + i, 2 + i]
+ });
// If inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([1, 9, 2, 3, 9, 4])) if (i != 9) i});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, 9, 2, 3, 9, 4]))
+ if (i != 9) i
+ });
// Else inside await for.
- Expect.setEquals(set,
- <int>{await for (var i in stream([1, -2, 3, -4])) if (i < 0) -i else i});
+ Expect.setEquals(set, <int>{
+ await for (var i in stream([1, -2, 3, -4]))
+ if (i < 0) -i else i
+ });
// For inside await for.
Expect.setEquals(set, <int>{
- await for (var i in stream([0, 2])) for (var j = 1; j <= 2; j++) i + j
+ await for (var i in stream([0, 2]))
+ for (var j = 1; j <= 2; j++) i + j
});
// Does not flatten nested collection literal.
- Expect.listEquals([1], {await for (var i in stream([1])) [i]}.first);
- Expect.mapEquals({1: 1}, {await for (var i in stream([1])) {i: i}}.first);
- Expect.setEquals({1}, {await for (var i in stream([1])) {i}}.first);
+ Expect.listEquals(
+ [1],
+ {
+ await for (var i in stream([1])) [i]
+ }.first);
+ Expect.mapEquals(
+ {1: 1},
+ {
+ await for (var i in stream([1])) {i: i}
+ }.first);
+ Expect.setEquals(
+ {1},
+ {
+ await for (var i in stream([1])) {i}
+ }.first);
// Downcast stream.
Object obj = stream([1, 2, 3, 4]);
Expect.setEquals(set, <int>{await for (var n in obj) n});
// Downcast variable.
- Expect.setEquals(set, <int>{await for (int n in numStream([1, 2, 3, 4])) n});
+ Expect.setEquals(set, <int>{
+ await for (int n in numStream([1, 2, 3, 4])) n
+ });
// Downcast element.
- Expect.setEquals(set, <int>{await for (num n in numStream([1, 2, 3, 4])) n});
+ Expect.setEquals(set, <int>{
+ await for (num n in numStream([1, 2, 3, 4])) n
+ });
}
Future<void> testDuplicateKeys() async {
@@ -243,28 +317,46 @@
Expect.equals("1:a,2:a", map.keys.join(","));
Expect.equals("2,4", map.values.join(","));
- var set = <Equality>{e1a, await for (var i in stream([0, 1, 2])) keys[i]};
+ var set = <Equality>{
+ e1a,
+ await for (var i in stream([0, 1, 2])) keys[i]
+ };
Expect.equals("1:a,2:a", set.join(","));
}
Future<void> testRuntimeErrors() async {
// Cast variable.
dynamic nonStream = 3;
- asyncExpectThrows<TypeError>(
- () async => <int>[await for (int i in nonStream) 1]);
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (int i in nonStream) 1: 1});
- asyncExpectThrows<TypeError>(
- () async => <int>{await for (int i in nonStream) 1});
+ asyncExpectThrows<TypeError>(() async {
+ <int>[await for (int i in nonStream) 1];
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{await for (int i in nonStream) 1: 1};
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int>{await for (int i in nonStream) 1};
+ }());
// Wrong element type.
dynamic nonInt = "string";
- asyncExpectThrows<TypeError>(
- () async => <int>[await for (var i in stream([1])) nonInt]);
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (var i in stream([1])) nonInt: 1});
- asyncExpectThrows<TypeError>(
- () async => <int, int>{await for (var i in stream([1])) 1: nonInt});
- asyncExpectThrows<TypeError>(
- () async => <int>{await for (var i in stream([1])) nonInt});
+ asyncExpectThrows<TypeError>(() async {
+ <int>[
+ await for (var i in stream([1])) nonInt
+ ];
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{
+ await for (var i in stream([1])) nonInt: 1
+ };
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int, int>{
+ await for (var i in stream([1])) 1: nonInt
+ };
+ }());
+ asyncExpectThrows<TypeError>(() async {
+ <int>{
+ await for (var i in stream([1])) nonInt
+ };
+ }());
}
diff --git a/tests/lib/js/js_util/async_test.dart b/tests/lib/js/js_util/async_test.dart
index 9172fe7..7e3316b 100644
--- a/tests/lib/js/js_util/async_test.dart
+++ b/tests/lib/js/js_util/async_test.dart
@@ -42,8 +42,9 @@
}
Future<void> testRejectedPromise() async {
- asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
- (String error) => error == 'rejected');
+ final String error = await asyncExpectThrows<String>(
+ js_util.promiseToFuture(rejectedPromise));
+ expect(error, equals('rejected'));
}
Future<void> testReturnResolvedPromise() async {
diff --git a/tests/lib_2/js/js_util/async_test.dart b/tests/lib_2/js/js_util/async_test.dart
index 6a49358..a913157 100644
--- a/tests/lib_2/js/js_util/async_test.dart
+++ b/tests/lib_2/js/js_util/async_test.dart
@@ -44,8 +44,9 @@
}
Future<void> testRejectedPromise() async {
- asyncExpectThrows<String>(() => js_util.promiseToFuture(rejectedPromise),
- (String error) => error == 'rejected');
+ final String error = await asyncExpectThrows<String>(
+ js_util.promiseToFuture(rejectedPromise));
+ expect(error, equals('rejected'));
}
Future<void> testReturnResolvedPromise() async {
diff --git a/tests/standalone/io/http_parser_header_add_test.dart b/tests/standalone/io/http_parser_header_add_test.dart
index 4421733..4fdf602 100644
--- a/tests/standalone/io/http_parser_header_add_test.dart
+++ b/tests/standalone/io/http_parser_header_add_test.dart
@@ -17,19 +17,15 @@
request.response.close();
});
- final completer = Completer<void>();
// The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
final client = HttpClient()..userAgent = 'Bob’s browser';
- asyncExpectThrows<FormatException>(() async {
- try {
- await client.open("CONNECT", "127.0.0.1", server.port, "/");
- } finally {
- client.close(force: true);
- server.close();
- completer.complete();
- }
- });
- await completer.future;
+ try {
+ await asyncExpectThrows<FormatException>(
+ client.open("CONNECT", "127.0.0.1", server.port, "/"));
+ } finally {
+ client.close(force: true);
+ server.close();
+ }
}
main() {
diff --git a/tests/standalone/io/io_override_test.dart b/tests/standalone/io/io_override_test.dart
index fdd49ba..4fe9c66 100644
--- a/tests/standalone/io/io_override_test.dart
+++ b/tests/standalone/io/io_override_test.dart
@@ -161,17 +161,17 @@
}
Future<Socket> socketConnect(dynamic host, int port,
- {dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) {
+ {dynamic sourceAddress, int sourcePort = 0, Duration? timeout}) async {
throw "";
}
Future<ConnectionTask<Socket>> socketStartConnect(dynamic host, int port,
- {dynamic sourceAddress, int sourcePort = 0}) {
+ {dynamic sourceAddress, int sourcePort = 0}) async {
throw "";
}
Future<ServerSocket> serverSocketBind(dynamic address, int port,
- {int backlog: 0, bool v6Only: false, bool shared: false}) {
+ {int backlog: 0, bool v6Only: false, bool shared: false}) async {
throw "";
}
@@ -217,9 +217,9 @@
Expect.identical(
_mockFileSystemEvent, new Directory("directory").watch());
Expect.isTrue(new Link("link") is LinkMock);
- asyncExpectThrows(() async => await Socket.connect(null, 0));
- asyncExpectThrows(() async => await Socket.startConnect(null, 0));
- asyncExpectThrows(() async => await ServerSocket.bind(null, 0));
+ asyncExpectThrows(Socket.connect(null, 0));
+ asyncExpectThrows(Socket.startConnect(null, 0));
+ asyncExpectThrows(ServerSocket.bind(null, 0));
Expect.isTrue(stdin is StdinMock);
Expect.identical(stdout, stdoutMock);
Expect.identical(stderr, stderrMock);
diff --git a/tests/standalone_2/io/http_parser_header_add_test.dart b/tests/standalone_2/io/http_parser_header_add_test.dart
index 7c86ff2..e597ea3 100644
--- a/tests/standalone_2/io/http_parser_header_add_test.dart
+++ b/tests/standalone_2/io/http_parser_header_add_test.dart
@@ -19,19 +19,15 @@
request.response.close();
});
- final completer = Completer<void>();
// The ’ character is U+2019 RIGHT SINGLE QUOTATION MARK.
final client = HttpClient()..userAgent = 'Bob’s browser';
- asyncExpectThrows<FormatException>(() async {
- try {
- await client.open("CONNECT", "127.0.0.1", server.port, "/");
- } finally {
- client.close(force: true);
- server.close();
- completer.complete();
- }
- });
- await completer.future;
+ try {
+ await asyncExpectThrows<FormatException>(
+ client.open("CONNECT", "127.0.0.1", server.port, "/"));
+ } finally {
+ client.close(force: true);
+ server.close();
+ }
}
main() {
diff --git a/tools/VERSION b/tools/VERSION
index 9518591..856c72a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 157
+PRERELEASE 158
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/yaml2json.dart b/tools/yaml2json.dart
index e8b6a07..abf313d 100644
--- a/tools/yaml2json.dart
+++ b/tools/yaml2json.dart
@@ -12,8 +12,13 @@
main(List<String> arguments) {
var port = new RawReceivePort();
+ bool check = false;
+ if (arguments.contains('--check')) {
+ arguments = arguments.toList()..remove('--check');
+ check = true;
+ }
if (arguments.length != 2) {
- stderr.writeln("Usage: yaml2json.dart input.yaml output.json");
+ stderr.writeln("Usage: yaml2json.dart input.yaml output.json [--check]");
exit(1);
}
Uri input = Uri.base.resolve(arguments[0]);
@@ -27,6 +32,23 @@
result[key] = yaml[key];
}
File file = new File.fromUri(output);
- file.writeAsStringSync(const JsonEncoder.withIndent(" ").convert(result));
+ String text = const JsonEncoder.withIndent(" ").convert(result);
+ if (check) {
+ bool needsUpdate = true;
+ if (file.existsSync()) {
+ String existingText = file.readAsStringSync();
+ needsUpdate = text != existingText;
+ }
+ if (needsUpdate) {
+ stderr.write('''
+The file ${arguments[1]} is not up to date. Regenerate using
+
+ dart tools/yaml2json.dart ${arguments[0]} ${arguments[1]}
+''');
+ exit(1);
+ }
+ } else {
+ file.writeAsStringSync(text);
+ }
port.close();
}