Version 2.10.0-85.0.dev
Merge commit 'd27556656fba7b43d44b1bdc10d2635a34102fbe' into 'dev'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 817279d..011e3ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,10 @@
to cancel outgoing HTTP requests and stop following IO operations.
* A validation check is added to `path` of class `Cookie`. Having characters
ranging from 0x00 to 0x1f and 0x3b (";") will lead to a `FormatException`.
+* The `HttpClient` and `HttpServer` clasess now have a 1 MiB limit for the
+ total size of the HTTP headers when parsing a request or response, instead
+ of the former 8 KiB limit for each header name and value. This limit cannot
+ be configured at this time.
#### `dart:typed_data`
diff --git a/pkg/_fe_analyzer_shared/pubspec.yaml b/pkg/_fe_analyzer_shared/pubspec.yaml
index ca8de48..864c0a6 100644
--- a/pkg/_fe_analyzer_shared/pubspec.yaml
+++ b/pkg/_fe_analyzer_shared/pubspec.yaml
@@ -1,5 +1,5 @@
name: _fe_analyzer_shared
-version: 8.0.0
+version: 9.0.0
description: Logic that is shared between the front_end and analyzer packages.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/_fe_analyzer_shared
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index c695b73..e20987b 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -19,6 +19,7 @@
import 'package:analysis_server/src/services/correction/dart/convert_to_generic_function_syntax.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_if_null.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_int_literal.dart';
+import 'package:analysis_server/src/services/correction/dart/convert_to_null_aware.dart';
import 'package:analysis_server/src/services/correction/dart/convert_to_where_type.dart';
import 'package:analysis_server/src/services/correction/dart/create_method.dart';
import 'package:analysis_server/src/services/correction/dart/make_final.dart';
@@ -99,6 +100,7 @@
LintNames.prefer_is_empty: ReplaceWithIsEmpty.newInstance,
LintNames.prefer_is_not_empty: UesIsNotEmpty.newInstance,
LintNames.prefer_iterable_whereType: ConvertToWhereType.newInstance,
+ LintNames.prefer_null_aware_operators: ConvertToNullAware.newInstance,
LintNames.prefer_single_quotes: ConvertToSingleQuotes.newInstance,
LintNames.prefer_spread_collections: ConvertAddAllToSpread.newInstance,
LintNames.slash_for_doc_comments: ConvertDocumentationIntoLine.newInstance,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
index b9db2b2..3ddef42 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_quotes.dart
@@ -39,14 +39,17 @@
});
}
}
- } else if (node is InterpolationString) {
- StringInterpolation parent = node.parent;
- if (_fromDouble ? !parent.isSingleQuoted : parent.isSingleQuoted) {
- var newQuote = parent.isMultiline
+ } else if (node is InterpolationString || node is StringInterpolation) {
+ StringInterpolation stringNode =
+ node is StringInterpolation ? node : node.parent;
+ if (_fromDouble
+ ? !stringNode.isSingleQuoted
+ : stringNode.isSingleQuoted) {
+ var newQuote = stringNode.isMultiline
? (_fromDouble ? "'''" : '"""')
: (_fromDouble ? "'" : '"');
- var quoteLength = parent.isMultiline ? 3 : 1;
- var elements = parent.elements;
+ var quoteLength = stringNode.isMultiline ? 3 : 1;
+ var elements = stringNode.elements;
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (element is InterpolationString) {
@@ -58,10 +61,11 @@
}
await builder.addDartFileEdit(file, (builder) {
builder.addSimpleReplacement(
- SourceRange(parent.offset + (parent.isRaw ? 1 : 0), quoteLength),
+ SourceRange(
+ stringNode.offset + (stringNode.isRaw ? 1 : 0), quoteLength),
newQuote);
builder.addSimpleReplacement(
- SourceRange(parent.end - quoteLength, quoteLength), newQuote);
+ SourceRange(stringNode.end - quoteLength, quoteLength), newQuote);
});
}
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart
new file mode 100644
index 0000000..032264e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/convert_to_null_aware_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'bulk_fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(ConvertToNullAwareTest);
+ });
+}
+
+@reflectiveTest
+class ConvertToNullAwareTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.prefer_null_aware_operators;
+
+ Future<void> test_singleFile() async {
+ await resolveTestUnit('''
+abstract class A {
+ int m();
+}
+int f(A a) => null == a ? null : a.m();
+int g(A a) => a == null ? null : a.m();
+''');
+ await assertHasFix('''
+abstract class A {
+ int m();
+}
+int f(A a) => a?.m();
+int g(A a) => a?.m();
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
index 8b3aa1e..009ee47 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/test_all.dart
@@ -16,6 +16,7 @@
import 'convert_to_if_element_test.dart' as convert_to_if_element;
import 'convert_to_if_null_test.dart' as convert_to_if_null;
import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
+import 'convert_to_null_aware_test.dart' as convert_to_null_aware;
import 'convert_to_single_quoted_strings_test.dart'
as convert_to_single_quoted_strings;
import 'convert_to_spread_test.dart' as convert_to_spread;
@@ -60,6 +61,7 @@
convert_to_if_element.main();
convert_to_if_null.main();
convert_to_int_literal.main();
+ convert_to_null_aware.main();
convert_to_single_quoted_strings.main();
convert_to_spread.main();
convert_to_where_type.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_single_quoted_string_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_single_quoted_string_test.dart
index 18f6af1..9c46609 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_single_quoted_string_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_single_quoted_string_test.dart
@@ -23,6 +23,23 @@
@override
String get lintCode => LintNames.prefer_single_quotes;
+ Future<void> test_one_interpolation() async {
+ await resolveTestUnit(r'''
+main() {
+ var b = 'b';
+ var c = 'c';
+ print("a $b-${c} d");
+}
+''');
+ await assertHasFix(r'''
+main() {
+ var b = 'b';
+ var c = 'c';
+ print('a $b-${c} d');
+}
+''');
+ }
+
/// More coverage in the `convert_to_single_quoted_string_test.dart` assist test.
Future<void> test_one_simple() async {
await resolveTestUnit('''
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
index 07cd493..1744e2f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/add_type_parameter_test.dart
@@ -12,114 +12,89 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(AddTypeParameter_DeprecatedMemberUseTest);
- defineReflectiveTests(AddTypeParameter_InvalidOverrideTest);
- defineReflectiveTests(AddTypeParameter_WrongNumberOfTypeArgumentsTest);
+ defineReflectiveTests(AddTypeParameterToClassTest);
+ defineReflectiveTests(AddTypeParameterToConstructorTest);
+ defineReflectiveTests(AddTypeParameterToExtensionTest);
+ defineReflectiveTests(AddTypeParameterToMethodTest);
});
}
@reflectiveTest
-class AddTypeParameter_DeprecatedMemberUseTest extends _AddTypeParameterChange {
- Future<void> test_method_first() async {
+class AddTypeParameterToClassTest extends _AddTypeParameterChange {
+ Future<void> test_class_removed() async {
setPackageContent('''
-class C {
- @deprecated
- void m<T>() {}
-}
+class C<S, T> {}
''');
- setPackageData(_add(0));
+ setPackageData(_add(0, components: ['C']));
await resolveTestUnit('''
import '$importUri';
-void f(C c) {
- c.m<int>();
-}
+void f(C<int> c) {}
''');
await assertHasFix('''
import '$importUri';
-void f(C c) {
- c.m<String, int>();
-}
+void f(C<String, int> c) {}
''');
}
+}
- Future<void> test_method_last() async {
+@reflectiveTest
+class AddTypeParameterToConstructorTest extends _AddTypeParameterChange {
+ Future<void> test_constructor_removed() async {
setPackageContent('''
-class C {
- @deprecated
- void m<S, T>() {}
+class C<S, T> {
+ void C() {}
}
''');
- setPackageData(_add(2));
+ setPackageData(_add(0, components: ['C', 'C']));
await resolveTestUnit('''
import '$importUri';
-void f(C c) {
- c.m<int, double>();
+C f() {
+ return C<int>();
}
''');
await assertHasFix('''
import '$importUri';
-void f(C c) {
- c.m<int, double, String>();
-}
-''');
- }
-
- Future<void> test_method_middle() async {
- setPackageContent('''
-class C {
- @deprecated
- void m<S, U>() {}
-}
-''');
- setPackageData(_add(1));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(C c) {
- c.m<int, double>();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(C c) {
- c.m<int, String, double>();
-}
-''');
- }
-
- Future<void> test_method_only() async {
- setPackageContent('''
-class C {
- @deprecated
- void m() {}
-}
-''');
- setPackageData(_add(0));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(C c) {
- c.m();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(C c) {
- c.m<String>();
+C f() {
+ return C<String, int>();
}
''');
}
}
@reflectiveTest
-class AddTypeParameter_InvalidOverrideTest extends _AddTypeParameterChange {
- Future<void> test_method_bound() async {
+class AddTypeParameterToExtensionTest extends _AddTypeParameterChange {
+ Future<void> test_extension_removed() async {
+ setPackageContent('''
+class C {}
+extension E<S, T> on C {
+ void m() {}
+}
+''');
+ setPackageData(_add(0, components: ['E']));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ E<int>(c).m();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ E<String, int>(c).m();
+}
+''');
+ }
+}
+
+@reflectiveTest
+class AddTypeParameterToMethodTest extends _AddTypeParameterChange {
+ Future<void> test_method_bound_removed() async {
setPackageContent('''
class C {
void m<T extends num>() {}
@@ -144,7 +119,79 @@
''');
}
- Future<void> test_method_noBound() async {
+ Future<void> test_method_first_deprecated() async {
+ setPackageContent('''
+class C {
+ @deprecated
+ void m<T>() {}
+}
+''');
+ setPackageData(_add(0));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.m<int>();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m<String, int>();
+}
+''');
+ }
+
+ Future<void> test_method_last_deprecated() async {
+ setPackageContent('''
+class C {
+ @deprecated
+ void m<S, T>() {}
+}
+''');
+ setPackageData(_add(2));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.m<int, double>();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m<int, double, String>();
+}
+''');
+ }
+
+ Future<void> test_method_middle_deprecated() async {
+ setPackageContent('''
+class C {
+ @deprecated
+ void m<S, U>() {}
+}
+''');
+ setPackageData(_add(1));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.m<int, double>();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m<int, String, double>();
+}
+''');
+ }
+
+ Future<void> test_method_noBound_removed() async {
setPackageContent('''
class C {
void m<T>() {}
@@ -168,76 +215,32 @@
}
''');
}
-}
-@reflectiveTest
-class AddTypeParameter_WrongNumberOfTypeArgumentsTest
- extends _AddTypeParameterChange {
- Future<void> test_class() async {
+ Future<void> test_method_only_deprecated() async {
setPackageContent('''
-class C<S, T> {}
-''');
- setPackageData(_add(0, components: ['C']));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(C<int> c) {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(C<String, int> c) {}
-''');
- }
-
- Future<void> test_constructor() async {
- setPackageContent('''
-class C<S, T> {
- void C() {}
-}
-''');
- setPackageData(_add(0, components: ['C', 'C']));
- await resolveTestUnit('''
-import '$importUri';
-
-C f() {
- return C<int>();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-C f() {
- return C<String, int>();
-}
-''');
- }
-
- Future<void> test_extension() async {
- setPackageContent('''
-class C {}
-extension E<S, T> on C {
+class C {
+ @deprecated
void m() {}
}
''');
- setPackageData(_add(0, components: ['E']));
+ setPackageData(_add(0));
await resolveTestUnit('''
import '$importUri';
void f(C c) {
- E<int>(c).m();
+ c.m();
}
''');
await assertHasFix('''
import '$importUri';
void f(C c) {
- E<String, int>(c).m();
+ c.m<String>();
}
''');
}
- Future<void> test_method() async {
+ Future<void> test_method_removed() async {
setPackageContent('''
class C {
void m<S, T>() {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
index 685e14d..2287a48 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/modify_parameters_test.dart
@@ -14,50 +14,14 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(ModifyParameters_DeprecatedMemberUseTest);
- defineReflectiveTests(ModifyParameters_NotEnoughPositionalArgumentsTest);
- defineReflectiveTests(ModifyParameters_UndefinedMethodTest);
+ defineReflectiveTests(ModifyParametersOfMethodTest);
+ defineReflectiveTests(ModifyParametersOfTopLevelFunctionTest);
});
}
-/// In the tests where a required named parameter is being added, the tests
-/// avoid the question of whether the defining library is opted in to the
-/// null-safety feature by omitting both the `required` keyword and annotation.
-/// This works because the information the change needs is taken from the
-/// `AddParameter` object rather than the source code.
-///
-/// The tests for 'function' exist to check that these changes can also be
-/// applied to top-level functions, but are not intended to be exhaustive.
@reflectiveTest
-class ModifyParameters_DeprecatedMemberUseTest extends _ModifyParameters {
- Future<void> test_add_function_first_requiredNamed() async {
- setPackageContent('''
-@deprecated
-void f(int b) {}
-void g(int a, int b) {}
-''');
- setPackageData(_modify([
- 'f'
- ], [
- AddParameter(0, 'a', true, true, null, LiteralExtractor('0')),
- ], newName: 'g'));
- await resolveTestUnit('''
-import '$importUri';
-
-void h() {
- f(1);
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void h() {
- g(0, 1);
-}
-''');
- }
-
- Future<void> test_add_method_first_optionalNamed() async {
+class ModifyParametersOfMethodTest extends _ModifyParameters {
+ Future<void> test_add_first_optionalNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -84,7 +48,7 @@
''');
}
- Future<void> test_add_method_first_optionalPositional() async {
+ Future<void> test_add_first_optionalPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -114,7 +78,7 @@
''');
}
- Future<void> test_add_method_first_requiredNamed() async {
+ Future<void> test_add_first_requiredNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -144,7 +108,7 @@
''');
}
- Future<void> test_add_method_first_requiredPositional() async {
+ Future<void> test_add_first_requiredPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -174,7 +138,7 @@
''');
}
- Future<void> test_add_method_last_optionalNamed() async {
+ Future<void> test_add_last_optionalNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -201,7 +165,7 @@
''');
}
- Future<void> test_add_method_last_optionalPositional() async {
+ Future<void> test_add_last_optionalPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -231,7 +195,7 @@
''');
}
- Future<void> test_add_method_last_requiredNamed() async {
+ Future<void> test_add_last_requiredNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -261,7 +225,7 @@
''');
}
- Future<void> test_add_method_last_requiredPositional() async {
+ Future<void> test_add_last_requiredPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -291,7 +255,7 @@
''');
}
- Future<void> test_add_method_multiple() async {
+ Future<void> test_add_multiple_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -323,7 +287,59 @@
''');
}
- Future<void> test_mixed_method_noOverlap_removedFirst() async {
+ Future<void> test_add_renamed_removed() async {
+ setPackageContent('''
+class C {
+ void m2(int a, int b) {}
+}
+''');
+ setPackageData(_modify([
+ 'C',
+ 'm'
+ ], [
+ AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))
+ ], newName: 'm2'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.m(1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m2(0, 1);
+}
+''');
+ }
+
+ Future<void> test_add_sameName_removed() async {
+ setPackageContent('''
+class C {
+ void m(int a, int b) {}
+}
+''');
+ setPackageData(_modify(['C', 'm'],
+ [AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))]));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(C c) {
+ c.m(1);
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.m(0, 1);
+}
+''');
+ }
+
+ Future<void> test_mixed_noOverlap_removedFirst_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -354,7 +370,7 @@
''');
}
- Future<void> test_mixed_method_noOverlap_removedLast() async {
+ Future<void> test_mixed_noOverlap_removedLast_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -385,7 +401,7 @@
''');
}
- Future<void> test_mixed_method_overlap_first() async {
+ Future<void> test_mixed_overlap_first_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -417,7 +433,7 @@
''');
}
- Future<void> test_mixed_method_overlap_last() async {
+ Future<void> test_mixed_overlap_last_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -449,7 +465,7 @@
''');
}
- Future<void> test_mixed_method_overlap_middle() async {
+ Future<void> test_mixed_overlap_middle_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -482,32 +498,7 @@
''');
}
- Future<void> test_remove_function_first_requiredPositional() async {
- setPackageContent('''
-@deprecated
-void f(int a, int b) {}
-void g(int b) {}
-''');
- setPackageData(_modify(
- ['f'], [RemoveParameter(PositionalParameterReference(0))],
- newName: 'g'));
- await resolveTestUnit('''
-import '$importUri';
-
-void h() {
- f(0, 1);
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void h() {
- g(1);
-}
-''');
- }
-
- Future<void> test_remove_method_first_optionalNamed() async {
+ Future<void> test_remove_first_optionalNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -534,7 +525,7 @@
''');
}
- Future<void> test_remove_method_first_optionalPositional() async {
+ Future<void> test_remove_first_optionalPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -561,7 +552,7 @@
''');
}
- Future<void> test_remove_method_first_requiredPositional() async {
+ Future<void> test_remove_first_requiredPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -588,7 +579,7 @@
''');
}
- Future<void> test_remove_method_last_optionalNamed() async {
+ Future<void> test_remove_last_optionalNamed_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -615,7 +606,7 @@
''');
}
- Future<void> test_remove_method_last_optionalPositional() async {
+ Future<void> test_remove_last_optionalPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -642,7 +633,7 @@
''');
}
- Future<void> test_remove_method_last_requiredPositional() async {
+ Future<void> test_remove_last_requiredPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -669,7 +660,7 @@
''');
}
- Future<void> test_remove_method_multiple() async {
+ Future<void> test_remove_multiple_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -701,7 +692,7 @@
''');
}
- Future<void> test_remove_method_only_optionalNamed_withArg() async {
+ Future<void> test_remove_only_optionalNamed_withArg_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -728,7 +719,7 @@
''');
}
- Future<void> test_remove_method_only_optionalNamed_withoutArg() async {
+ Future<void> test_remove_only_optionalNamed_withoutArg_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -755,7 +746,7 @@
''');
}
- Future<void> test_remove_method_only_optionalPositional_withArg() async {
+ Future<void> test_remove_only_optionalPositional_withArg_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -782,7 +773,8 @@
''');
}
- Future<void> test_remove_method_only_optionalPositional_withoutArg() async {
+ Future<void>
+ test_remove_only_optionalPositional_withoutArg_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -809,7 +801,7 @@
''');
}
- Future<void> test_remove_method_only_requiredPositional() async {
+ Future<void> test_remove_only_requiredPositional_deprecated() async {
setPackageContent('''
class C {
@deprecated
@@ -837,60 +829,64 @@
}
}
+/// In the tests where a required named parameter is being added, the tests
+/// avoid the question of whether the defining library is opted in to the
+/// null-safety feature by omitting both the `required` keyword and annotation.
+/// This works because the information the change needs is taken from the
+/// `AddParameter` object rather than the source code.
+///
+/// The tests for 'function' exist to check that these changes can also be
+/// applied to top-level functions, but are not intended to be exhaustive.
@reflectiveTest
-class ModifyParameters_NotEnoughPositionalArgumentsTest
- extends _ModifyParameters {
- Future<void> test_method_sameName() async {
+class ModifyParametersOfTopLevelFunctionTest extends _ModifyParameters {
+ Future<void> test_add_first_requiredNamed_deprecated() async {
setPackageContent('''
-class C {
- void m(int a, int b) {}
-}
+@deprecated
+void f(int b) {}
+void g(int a, int b) {}
''');
- setPackageData(_modify(['C', 'm'],
- [AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))]));
+ setPackageData(_modify([
+ 'f'
+ ], [
+ AddParameter(0, 'a', true, true, null, LiteralExtractor('0')),
+ ], newName: 'g'));
await resolveTestUnit('''
import '$importUri';
-void f(C c) {
- c.m(1);
+void h() {
+ f(1);
}
''');
await assertHasFix('''
import '$importUri';
-void f(C c) {
- c.m(0, 1);
+void h() {
+ g(0, 1);
}
''');
}
-}
-@reflectiveTest
-class ModifyParameters_UndefinedMethodTest extends _ModifyParameters {
- Future<void> test_method_renamed() async {
+ Future<void> test_remove_first_requiredPositional_deprecated() async {
setPackageContent('''
-class C {
- void m2(int a, int b) {}
-}
+@deprecated
+void f(int a, int b) {}
+void g(int b) {}
''');
- setPackageData(_modify([
- 'C',
- 'm'
- ], [
- AddParameter(0, 'a', true, true, null, LiteralExtractor('0'))
- ], newName: 'm2'));
+ setPackageData(_modify(
+ ['f'], [RemoveParameter(PositionalParameterReference(0))],
+ newName: 'g'));
await resolveTestUnit('''
import '$importUri';
-void f(C c) {
- c.m(1);
+void h() {
+ f(0, 1);
}
''');
await assertHasFix('''
import '$importUri';
-void f(C c) {
- c.m2(0, 1);
+void h() {
+ g(1);
}
''');
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
index 466f678..74bda48 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/rename_test.dart
@@ -11,26 +11,21 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(Rename_DeprecatedMemberUseTest);
- defineReflectiveTests(Rename_ExtendsNonClassTest);
- defineReflectiveTests(Rename_ImplementsNonClassTest);
- defineReflectiveTests(Rename_MixinOfNonClassTest);
- defineReflectiveTests(Rename_OverrideOnNonOverridingMethodTest);
- defineReflectiveTests(Rename_UndefinedClassTest);
- defineReflectiveTests(Rename_UndefinedFunctionTest);
- defineReflectiveTests(Rename_UndefinedGetterTest);
- defineReflectiveTests(Rename_UndefinedIdentifierTest);
- defineReflectiveTests(Rename_UndefinedMethodTest);
+ defineReflectiveTests(RenameClassTest);
+ defineReflectiveTests(RenameConstructorTest);
+ defineReflectiveTests(RenameExtensionTest);
+ defineReflectiveTests(RenameFieldTest);
+ defineReflectiveTests(RenameMethodTest);
+ defineReflectiveTests(RenameMixinTest);
+ defineReflectiveTests(RenameTopLevelFunctionTest);
+ defineReflectiveTests(RenameTypedefTest);
});
}
@reflectiveTest
-class Rename_DeprecatedMemberUseTest extends _AbstractRenameTest {
- Future<void> test_class_reference_inExtends() async {
- addMetaPackage();
+class RenameClassTest extends _AbstractRenameTest {
+ Future<void> test_inExtends_deprecated() async {
setPackageContent('''
-import 'package:meta/meta.dart';
-
@deprecated
class Old {}
class New {}
@@ -48,11 +43,25 @@
''');
}
- Future<void> test_class_reference_inImplements() async {
- addMetaPackage();
+ Future<void> test_inExtends_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+class C extends Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C extends New {}
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_inImplements_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {}
class New {}
@@ -70,11 +79,25 @@
''');
}
- Future<void> test_class_reference_inOn() async {
- addMetaPackage();
+ Future<void> test_inImplements_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+class C implements Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C implements New {}
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_inOn_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {}
class New {}
@@ -92,11 +115,25 @@
''');
}
- Future<void> test_class_reference_inTypeAnnotation() async {
- addMetaPackage();
+ Future<void> test_inOn_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+extension E on Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+extension E on New {}
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_inTypeAnnotation_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {}
class New {}
@@ -114,11 +151,25 @@
''');
}
- Future<void> test_class_reference_inWith() async {
- addMetaPackage();
+ Future<void> test_inTypeAnnotation_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_inWith_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {}
class New {}
@@ -136,11 +187,25 @@
''');
}
- Future<void> test_class_reference_staticField() async {
- addMetaPackage();
+ Future<void> test_inWith_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_staticField_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {
static String empty = '';
@@ -162,11 +227,30 @@
''');
}
- Future<void> test_constructor_named_reference() async {
- addMetaPackage();
+ Future<void> test_staticField_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''', errorFilter: ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class RenameConstructorTest extends _AbstractRenameTest {
+ Future<void> test_named_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
C.old();
@@ -190,11 +274,31 @@
''');
}
- Future<void> test_constructor_unnamed_reference() async {
- addMetaPackage();
+ Future<void> test_named_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ C.new();
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+void f() {
+ C.old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new();
+}
+''');
+ }
+
+ Future<void> test_unnamed_deprecated() async {
+ setPackageContent('''
@deprecated
class Old {
Old();
@@ -220,11 +324,34 @@
''');
}
- Future<void> test_extension_reference_override() async {
- addMetaPackage();
+ Future<void> test_unnamed_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class New {
+ New();
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+void f() {
+ Old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ New();
+}
+''', errorFilter: ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class RenameExtensionTest extends _AbstractRenameTest {
+ Future<void> test_override_deprecated() async {
+ setPackageContent('''
@deprecated
extension Old on String {
int get double => length * 2;
@@ -246,11 +373,27 @@
''');
}
- Future<void> test_extension_reference_staticField() async {
- addMetaPackage();
+ Future<void> test_override_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+extension New on String {
+ int get double => length * 2;
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+var l = Old('a').double;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var l = New('a').double;
+''', errorFilter: ignoreUnusedImport);
+ }
+
+ Future<void> test_staticField_deprecated() async {
+ setPackageContent('''
@deprecated
extension Old on String {
static String empty = '';
@@ -272,11 +415,30 @@
''');
}
- Future<void> test_field_instance_reference() async {
- addMetaPackage();
+ Future<void> test_staticField_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+extension New on String {
+ static String empty = '';
+}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+var s = Old.empty;
+''');
+ await assertHasFix('''
+import '$importUri';
+
+var s = New.empty;
+''', errorFilter: ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class RenameFieldTest extends _AbstractRenameTest {
+ Future<void> test_instance_reference_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
int old;
@@ -300,11 +462,31 @@
''');
}
- Future<void> test_field_static_assignment() async {
- addMetaPackage();
+ Future<void> test_instance_reference_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+void f(C c) {
+ c.old;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.new;
+}
+''');
+ }
+
+ Future<void> test_static_assignment_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
static int old;
@@ -328,11 +510,31 @@
''');
}
- Future<void> test_field_static_reference() async {
- addMetaPackage();
+ Future<void> test_static_assignment_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ static int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+void f() {
+ C.old = 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new = 0;
+}
+''');
+ }
+
+ Future<void> test_static_reference_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
static int old;
@@ -356,12 +558,35 @@
''');
}
- @failingTest
- Future<void> test_method_instance_override() async {
- addMetaPackage();
+ Future<void> test_static_reference_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ static int new;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+void f() {
+ C.old;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ C.new;
+}
+''');
+ }
+}
+
+@reflectiveTest
+class RenameMethodTest extends _AbstractRenameTest {
+ @failingTest
+ Future<void> test_instance_override_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
int old() => 0;
@@ -387,11 +612,33 @@
''');
}
- Future<void> test_method_instance_reference() async {
- addMetaPackage();
+ Future<void> test_instance_override_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ int new() => 0;
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+class D extends C {
+ @override
+ int old() => 0;
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class D extends C {
+ @override
+ int new() => 0;
+}
+''');
+ }
+
+ Future<void> test_instance_reference_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
int old() {}
@@ -415,11 +662,31 @@
''');
}
- Future<void> test_method_static_reference() async {
- addMetaPackage();
+ Future<void> test_instance_reference_removed() async {
setPackageContent('''
-import 'package:meta/meta.dart';
+class C {
+ int new() {}
+}
+''');
+ setPackageData(_rename(['C', 'old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+void f(C c) {
+ c.old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(C c) {
+ c.new();
+}
+''');
+ }
+
+ Future<void> test_static_reference_deprecated() async {
+ setPackageContent('''
class C {
@deprecated
static int old() {}
@@ -443,441 +710,7 @@
''');
}
- Future<void> test_mixin_reference_inWith() async {
- addMetaPackage();
- setPackageContent('''
-import 'package:meta/meta.dart';
-
-@deprecated
-mixin Old {}
-mixin New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-class C with Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class C with New {}
-''');
- }
-
- Future<void> test_topLevelFunction_reference() async {
- addMetaPackage();
- setPackageContent('''
-import 'package:meta/meta.dart';
-
-@deprecated
-int old() {}
-int new() {}
-''');
- setPackageData(_rename(['old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f() {
- old();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f() {
- new();
-}
-''');
- }
-
- Future<void> test_typedef_reference() async {
- addMetaPackage();
- setPackageContent('''
-import 'package:meta/meta.dart';
-
-@deprecated
-typedef Old = int Function(int);
-typedef New = int Function(int);
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(Old o) {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(New o) {}
-''');
- }
-}
-
-@reflectiveTest
-class Rename_ExtendsNonClassTest extends _AbstractRenameTest {
- Future<void> test_class_reference_inExtends() async {
- setPackageContent('''
-class New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-class C extends Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class C extends New {}
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_ImplementsNonClassTest extends _AbstractRenameTest {
- Future<void> test_class_reference_inImplements() async {
- setPackageContent('''
-class New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-class C implements Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class C implements New {}
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_MixinOfNonClassTest extends _AbstractRenameTest {
- Future<void> test_class_reference_inWith() async {
- setPackageContent('''
-class New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-class C with Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class C with New {}
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_mixin_reference_inWith() async {
- setPackageContent('''
-mixin New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-class C with Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class C with New {}
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_OverrideOnNonOverridingMethodTest extends _AbstractRenameTest {
- Future<void> test_method_instance_override() async {
- setPackageContent('''
-class C {
- int new() => 0;
-}
-''');
- setPackageData(_rename(['C', 'old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-class D extends C {
- @override
- int old() => 0;
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-class D extends C {
- @override
- int new() => 0;
-}
-''');
- }
-}
-
-@reflectiveTest
-class Rename_UndefinedClassTest extends _AbstractRenameTest {
- Future<void> test_class_reference_inOn() async {
- setPackageContent('''
-class New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-extension E on Old {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-extension E on New {}
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_class_reference_inTypeAnnotation() async {
- setPackageContent('''
-class New {}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(Old o) {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(New o) {}
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_typedef_reference() async {
- setPackageContent('''
-typedef New = int Function(int);
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(Old o) {}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(New o) {}
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_UndefinedFunctionTest extends _AbstractRenameTest {
- Future<void> test_constructor_unnamed_reference() async {
- setPackageContent('''
-class New {
- New();
-}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f() {
- Old();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f() {
- New();
-}
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_extension_reference_override() async {
- setPackageContent('''
-extension New on String {
- int get double => length * 2;
-}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-var l = Old('a').double;
-''');
- await assertHasFix('''
-import '$importUri';
-
-var l = New('a').double;
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_field_instance_reference() async {
- setPackageContent('''
-class C {
- int new;
-}
-''');
- setPackageData(_rename(['C', 'old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(C c) {
- c.old;
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(C c) {
- c.new;
-}
-''');
- }
-
- Future<void> test_topLevelFunction_reference() async {
- setPackageContent('''
-int new() {}
-''');
- setPackageData(_rename(['old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f() {
- old();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f() {
- new();
-}
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_UndefinedGetterTest extends _AbstractRenameTest {
- Future<void> test_field_static_reference() async {
- setPackageContent('''
-class C {
- static int new;
-}
-''');
- setPackageData(_rename(['C', 'old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f() {
- C.old;
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f() {
- C.new;
-}
-''');
- }
-}
-
-@reflectiveTest
-class Rename_UndefinedIdentifierTest extends _AbstractRenameTest {
- Future<void> test_class_reference_staticField() async {
- setPackageContent('''
-class New {
- static String empty = '';
-}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-var s = Old.empty;
-''');
- await assertHasFix('''
-import '$importUri';
-
-var s = New.empty;
-''', errorFilter: ignoreUnusedImport);
- }
-
- Future<void> test_extension_reference_staticField() async {
- setPackageContent('''
-extension New on String {
- static String empty = '';
-}
-''');
- setPackageData(_rename(['Old'], 'New'));
- await resolveTestUnit('''
-import '$importUri';
-
-var s = Old.empty;
-''');
- await assertHasFix('''
-import '$importUri';
-
-var s = New.empty;
-''', errorFilter: ignoreUnusedImport);
- }
-}
-
-@reflectiveTest
-class Rename_UndefinedMethodTest extends _AbstractRenameTest {
- Future<void> test_constructor_named_reference() async {
- setPackageContent('''
-class C {
- C.new();
-}
-''');
- setPackageData(_rename(['C', 'old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f() {
- C.old();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f() {
- C.new();
-}
-''');
- }
-
- Future<void> test_method_instance_reference() async {
- setPackageContent('''
-class C {
- int new() {}
-}
-''');
- setPackageData(_rename(['C', 'old'], 'new'));
- await resolveTestUnit('''
-import '$importUri';
-
-void f(C c) {
- c.old();
-}
-''');
- await assertHasFix('''
-import '$importUri';
-
-void f(C c) {
- c.new();
-}
-''');
- }
-
- Future<void> test_method_static_reference() async {
+ Future<void> test_static_reference_removed() async {
setPackageContent('''
class C {
static int new() {}
@@ -902,29 +735,128 @@
}
@reflectiveTest
-class Rename_UndefinedSetterTest extends _AbstractRenameTest {
- Future<void> test_field_static_assignment() async {
+class RenameMixinTest extends _AbstractRenameTest {
+ Future<void> test_inWith_deprecated() async {
setPackageContent('''
-class C {
- static int new;
-}
+@deprecated
+mixin Old {}
+mixin New {}
''');
- setPackageData(_rename(['C', 'old'], 'new'));
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''');
+ }
+
+ Future<void> test_inWith_removed() async {
+ setPackageContent('''
+mixin New {}
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+class C with Old {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+class C with New {}
+''', errorFilter: ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class RenameTopLevelFunctionTest extends _AbstractRenameTest {
+ Future<void> test_deprecated() async {
+ setPackageContent('''
+@deprecated
+int old() {}
+int new() {}
+''');
+ setPackageData(_rename(['old'], 'new'));
await resolveTestUnit('''
import '$importUri';
void f() {
- C.old = 0;
+ old();
}
''');
await assertHasFix('''
import '$importUri';
void f() {
- C.new = 0;
+ new();
}
''');
}
+
+ Future<void> test_removed() async {
+ setPackageContent('''
+int new() {}
+''');
+ setPackageData(_rename(['old'], 'new'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f() {
+ old();
+}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f() {
+ new();
+}
+''', errorFilter: ignoreUnusedImport);
+ }
+}
+
+@reflectiveTest
+class RenameTypedefTest extends _AbstractRenameTest {
+ Future<void> test_deprecated() async {
+ setPackageContent('''
+@deprecated
+typedef Old = int Function(int);
+typedef New = int Function(int);
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''');
+ }
+
+ Future<void> test_removed() async {
+ setPackageContent('''
+typedef New = int Function(int);
+''');
+ setPackageData(_rename(['Old'], 'New'));
+ await resolveTestUnit('''
+import '$importUri';
+
+void f(Old o) {}
+''');
+ await assertHasFix('''
+import '$importUri';
+
+void f(New o) {}
+''', errorFilter: ignoreUnusedImport);
+ }
}
class _AbstractRenameTest extends DataDrivenFixProcessorTest {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 5919677..8f199a4 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,9 +1,17 @@
-## 0.40.1-dev
+## 0.40.1
* Added `LocalVariableElement.hasInitializer`,
`PropertyInducingElement.hasInitializer`, `ParameterElement.hasDefaultValue`.
* `ElementImpl.toString()` uses `getDisplayString(withNullability: true)`.
* Deprecated `ElementAnnotation.constantValue`, it does not guarantee that
the value has been computed. Use `computeConstantValue()` instead.
+* Added `CompoundAssignmentExpression` with read/write element/type getters.
+ This interface is implemented by `AssignmentExpression`, `PostfixExpression`
+ and `PrefixExpression`. Use it instead of `staticElement` and `staticType`
+ of the left-hand side expressions (target expressions in case of postfix
+ or prefix expressions with increment operator).
+* Changes to the way experiments are handled, and SDK version.
+* Bug fixes: 43268, 43214, 39642, 42379, 42629, 43168, 43144, 43100,
+ 43032, 43073.
## 0.40.0
* Added `LibraryElement.featureSet`.
diff --git a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
index 1f8e249..7559fa2 100644
--- a/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
+++ b/pkg/analyzer/lib/src/dart/element/class_hierarchy.dart
@@ -47,31 +47,21 @@
var library = element.library as LibraryElementImpl;
var typeSystem = library.typeSystem;
- var map = <ClassElement, _ClassInterfaceType>{};
-
- void appendOne(InterfaceType type) {
- var element = type.element;
- var classResult = map[element];
- if (classResult == null) {
- classResult = _ClassInterfaceType(typeSystem);
- map[element] = classResult;
- }
- classResult.update(type);
- }
+ var interfacesMerger = InterfacesMerger(typeSystem);
void append(InterfaceType type) {
if (type == null) {
return;
}
- appendOne(type);
+ interfacesMerger.add(type);
var substitution = Substitution.fromInterfaceType(type);
var rawInterfaces = implementedInterfaces(type.element);
for (var rawInterface in rawInterfaces) {
var newInterface = substitution.substituteType(rawInterface);
newInterface = library.toLegacyTypeIfOptOut(newInterface);
- appendOne(newInterface);
+ interfacesMerger.add(newInterface);
}
}
@@ -88,7 +78,7 @@
var errors = <ClassHierarchyError>[];
var interfaces = <InterfaceType>[];
- for (var collector in map.values) {
+ for (var collector in interfacesMerger._map.values) {
if (collector._error != null) {
errors.add(collector._error);
}
@@ -121,6 +111,36 @@
IncompatibleInterfacesClassHierarchyError(this.first, this.second);
}
+class InterfacesMerger {
+ final TypeSystemImpl _typeSystem;
+ final _map = <ClassElement, _ClassInterfaceType>{};
+
+ InterfacesMerger(this._typeSystem);
+
+ List<InterfaceType> get typeList {
+ return _map.values.map((e) => e.type).toList();
+ }
+
+ void add(InterfaceType type) {
+ var element = type.element;
+ var classResult = _map[element];
+ if (classResult == null) {
+ classResult = _ClassInterfaceType(_typeSystem);
+ _map[element] = classResult;
+ }
+ classResult.update(type);
+ }
+
+ void addWithSupertypes(InterfaceType type) {
+ if (type != null) {
+ for (var superType in type.allSupertypes) {
+ add(superType);
+ }
+ add(type);
+ }
+ }
+}
+
class _ClassInterfaceType {
final TypeSystemImpl _typeSystem;
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 2d4ef65..274b4be 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -10,6 +10,7 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
@@ -62,16 +63,9 @@
var left = node.leftHandSide;
var right = node.rightHandSide;
- // Case `id = e`.
- // Consider an assignment of the form `id = e`, where `id` is an identifier.
if (left is SimpleIdentifier) {
- var leftLookup = _resolver.nameScope.lookup2(left.name);
- // When the lexical lookup yields a local variable `v`.
- var leftGetter = leftLookup.getter;
- if (leftGetter is VariableElement) {
- _resolve_SimpleIdentifier_LocalVariable(node, left, leftGetter, right);
- return;
- }
+ _resolve_SimpleIdentifier(node, left);
+ return;
}
left?.accept(_resolver);
@@ -87,7 +81,8 @@
_resolver.setWriteElement(left, null);
}
- _resolve1(node);
+ _resolve1(node, getReadType(left));
+
_setRhsContext(node, left.staticType, operator, right);
_flowAnalysis?.assignmentExpression(node);
@@ -106,18 +101,6 @@
}
/// Set the static type of [node] to be the least upper bound of the static
- /// types of subexpressions [expr1] and [expr2].
- ///
- /// TODO(scheglov) this is duplicate
- void _analyzeLeastUpperBound(
- Expression node, Expression expr1, Expression expr2) {
- DartType staticType1 = getReadType(expr1);
- DartType staticType2 = getReadType(expr2);
-
- _analyzeLeastUpperBoundTypes(node, staticType1, staticType2);
- }
-
- /// Set the static type of [node] to be the least upper bound of the static
/// types [staticType1] and [staticType2].
///
/// TODO(scheglov) this is duplicate
@@ -138,6 +121,55 @@
_inferenceHelper.recordStaticType(node, staticType);
}
+ void _checkForInvalidAssignment(
+ DartType writeType,
+ Expression right,
+ DartType rightType,
+ ) {
+ // TODO(scheglov) should not happen
+ if (writeType == null) {
+ return;
+ }
+
+ if (!writeType.isVoid && _checkForUseOfVoidResult(right)) {
+ return;
+ }
+
+ if (_typeSystem.isAssignableTo2(rightType, writeType)) {
+ return;
+ }
+
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.INVALID_ASSIGNMENT,
+ right,
+ [rightType, writeType],
+ );
+ }
+
+ /// Check for situations where the result of a method or function is used,
+ /// when it returns 'void'. Or, in rare cases, when other types of expressions
+ /// are void, such as identifiers.
+ ///
+ /// See [StaticWarningCode.USE_OF_VOID_RESULT].
+ /// TODO(scheglov) this is duplicate
+ bool _checkForUseOfVoidResult(Expression expression) {
+ if (expression == null ||
+ !identical(expression.staticType, VoidTypeImpl.instance)) {
+ return false;
+ }
+
+ if (expression is MethodInvocation) {
+ SimpleIdentifier methodName = expression.methodName;
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.USE_OF_VOID_RESULT, methodName, []);
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.USE_OF_VOID_RESULT, expression, []);
+ }
+
+ return true;
+ }
+
/// Return the non-nullable variant of the [type] if null safety is enabled,
/// otherwise return the type itself.
///
@@ -175,14 +207,105 @@
}
}
- void _resolve1(AssignmentExpressionImpl node) {
+ void _reportNotSetter(
+ Expression left,
+ Element requested,
+ Element recovery,
+ ) {
+ if (requested != null) {
+ if (requested is VariableElement) {
+ if (requested.isConst) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
+ left,
+ );
+ } else if (requested.isFinal) {
+ if (_isNonNullableByDefault) {
+ // Handled during resolution, with flow analysis.
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
+ left,
+ [requested.name],
+ );
+ }
+ }
+ }
+ return;
+ }
+
+ if (recovery is ClassElement ||
+ recovery is DynamicElementImpl ||
+ recovery is FunctionTypeAliasElement ||
+ recovery is TypeParameterElement) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_TYPE,
+ left,
+ );
+ } else if (recovery is FunctionElement) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_FUNCTION,
+ left,
+ );
+ } else if (recovery is MethodElement) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_METHOD,
+ left,
+ );
+ } else if (recovery is PrefixElement) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
+ left,
+ [recovery.name],
+ );
+ } else if (recovery is PropertyAccessorElement && recovery.isGetter) {
+ var variable = recovery.variable;
+ if (variable.isConst) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_CONST,
+ left,
+ );
+ } else if (variable.isFinal && !variable.isLate) {
+ if (variable is FieldElement) {
+ if (variable.setter == null && variable.isSynthetic) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_NO_SETTER,
+ left,
+ [variable.name, variable.enclosingElement.displayName],
+ );
+ } else {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_FINAL,
+ left,
+ [variable.name],
+ );
+ }
+ return;
+ }
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.ASSIGNMENT_TO_FINAL_LOCAL,
+ left,
+ [variable.name],
+ );
+ }
+ } else if (recovery is MultiplyDefinedElementImpl) {
+ // Will be reported in ErrorVerifier.
+ } else {
+ if (left is SimpleIdentifier && !left.isSynthetic) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+ left,
+ [left.name],
+ );
+ }
+ }
+ }
+
+ void _resolve1(AssignmentExpressionImpl node, DartType leftType) {
Token operator = node.operator;
TokenType operatorType = operator.type;
Expression leftHandSide = node.leftHandSide;
- var leftType = getReadType(leftHandSide);
- leftType = _resolveTypeParameter(leftType);
-
if (identical(leftType, NeverTypeImpl.instance)) {
return;
}
@@ -241,13 +364,18 @@
// promoting the LHS/ to non-null (as we know its value will not be used
// if null)
_analyzeLeastUpperBoundTypes(
- node,
- _typeSystem.promoteToNonNull(getReadType(node.leftHandSide)),
- getReadType(node.rightHandSide));
+ node,
+ _typeSystem.promoteToNonNull(node.readType),
+ getReadType(node.rightHandSide),
+ );
} else {
// The static type of a compound assignment using ??= before NNBD is the
// least upper bound of the static types of the LHS and RHS.
- _analyzeLeastUpperBound(node, node.leftHandSide, node.rightHandSide);
+ _analyzeLeastUpperBoundTypes(
+ node,
+ node.readType,
+ node.rightHandSide.staticType,
+ );
}
} else if (operator == TokenType.AMPERSAND_AMPERSAND_EQ ||
operator == TokenType.BAR_BAR_EQ) {
@@ -285,30 +413,56 @@
_resolver.nullShortingTermination(node);
}
- void _resolve_SimpleIdentifier_LocalVariable(
+ void _resolve_SimpleIdentifier(
AssignmentExpressionImpl node,
SimpleIdentifier left,
- VariableElement leftElement,
- Expression right,
) {
+ var right = node.rightHandSide;
var operator = node.operator.type;
- left.staticElement = leftElement;
if (operator != TokenType.EQ) {
- _resolver.setReadElement(left, leftElement);
+ var readLookup = _resolver.lexicalLookup(node: left, setter: false);
+ var readElement = readLookup.requested;
+ _resolver.setReadElement(left, readElement);
}
- _resolver.setWriteElement(left, leftElement);
- var leftType = _resolver.localVariableTypeProvider.getType(left);
- // TODO(scheglov) Set the type only when `operator != TokenType.EQ`.
- _recordStaticType(left, leftType);
+ var writeLookup = _resolver.lexicalLookup(node: left, setter: true);
+ var writeElement = writeLookup.requested ?? writeLookup.recovery;
+ _resolver.setWriteElement(left, writeElement);
+ _reportNotSetter(left, writeLookup.requested, writeLookup.recovery);
+
+ // TODO(scheglov) This is mostly necessary for backward compatibility.
+ // Although we also use `staticElement` for `getType(left)` below.
+ {
+ if (operator != TokenType.EQ) {
+ var readElement = node.readElement;
+ if (readElement is PropertyAccessorElement) {
+ left.auxiliaryElements = AuxiliaryElements(readElement);
+ }
+ }
+ left.staticElement = node.writeElement;
+ if (node.readElement is VariableElement) {
+ var leftType = _resolver.localVariableTypeProvider.getType(left);
+ _recordStaticType(left, leftType);
+ } else {
+ _recordStaticType(left, node.writeType);
+ }
+ }
if (operator != TokenType.EQ) {
+ // TODO(scheglov) Change this method to work with elements.
_resolver.checkReadOfNotAssignedLocalVariable(left);
}
- _resolve1(node);
- _setRhsContext(node, leftType, operator, right);
+ _resolve1(node, node.readType);
+
+ {
+ var leftType = node.writeType;
+ if (node.writeElement is VariableElement) {
+ leftType = _resolver.localVariableTypeProvider.getType(left);
+ }
+ _setRhsContext(node, leftType, operator, right);
+ }
var flow = _flowAnalysis?.flow;
if (flow != null && operator == TokenType.QUESTION_QUESTION_EQ) {
@@ -320,21 +474,26 @@
_resolve2(node);
+ // TODO(scheglov) inline into resolve2().
+ DartType assignedType;
+ if (operator == TokenType.EQ ||
+ operator == TokenType.QUESTION_QUESTION_EQ) {
+ assignedType = right.staticType;
+ } else {
+ assignedType = node.staticType;
+ }
+ _checkForInvalidAssignment(node.writeType, right, assignedType);
+
if (flow != null) {
- flow.write(leftElement, node.staticType);
+ if (writeElement is VariableElement) {
+ flow.write(writeElement, node.staticType);
+ }
if (node.operator.type == TokenType.QUESTION_QUESTION_EQ) {
flow.ifNullExpression_end();
}
}
}
- /// If the given [type] is a type parameter, resolve it to the type that
- /// should be used when looking up members. Otherwise, return the original
- /// type.
- // TODO(scheglov) this is duplicate
- DartType _resolveTypeParameter(DartType type) =>
- type?.resolveToBound(_typeProvider.objectType);
-
void _setRhsContext(AssignmentExpressionImpl node, DartType leftType,
TokenType operator, Expression right) {
switch (operator) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart b/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart
new file mode 100644
index 0000000..9fedd9c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/lexical_lookup.dart
@@ -0,0 +1,101 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:meta/meta.dart';
+
+class LexicalLookup {
+ final ResolverVisitor _resolver;
+
+ LexicalLookup(this._resolver);
+
+ LexicalLookupResult perform({
+ @required SimpleIdentifier node,
+ @required bool setter,
+ }) {
+ var id = node.name;
+ var scopeResult = _resolver.nameScope.lookup2(id);
+ var scopeGetter = scopeResult.getter;
+ var scopeSetter = scopeResult.setter;
+ if (scopeGetter != null || scopeSetter != null) {
+ if (scopeGetter is VariableElement) {
+ return LexicalLookupResult(requested: scopeGetter);
+ }
+ if (setter) {
+ if (scopeSetter != null) {
+ return LexicalLookupResult(
+ requested: _resolver.toLegacyElement(scopeSetter),
+ );
+ }
+ if (!_isInstanceMember(scopeGetter)) {
+ return LexicalLookupResult(
+ recovery: _resolver.toLegacyElement(scopeGetter),
+ );
+ }
+ } else {
+ if (scopeGetter != null) {
+ return LexicalLookupResult(
+ requested: _resolver.toLegacyElement(scopeGetter),
+ );
+ }
+ }
+ }
+
+ var thisType = _resolver.thisType;
+ if (thisType == null) {
+ var recoveryElement = setter ? scopeGetter : scopeGetter;
+ return LexicalLookupResult(
+ recovery: _resolver.toLegacyElement(recoveryElement),
+ );
+ }
+
+ var propertyResult = _resolver.typePropertyResolver.resolve(
+ receiver: null,
+ receiverType: thisType,
+ name: id,
+ receiverErrorNode: node,
+ nameErrorNode: node,
+ );
+
+ if (setter) {
+ var setterElement = propertyResult.setter;
+ if (setterElement != null) {
+ return LexicalLookupResult(
+ requested: _resolver.toLegacyElement(setterElement),
+ );
+ } else {
+ var recoveryElement = scopeGetter ?? propertyResult.getter;
+ return LexicalLookupResult(
+ recovery: _resolver.toLegacyElement(recoveryElement),
+ );
+ }
+ } else {
+ var getterElement = propertyResult.getter;
+ if (getterElement != null) {
+ return LexicalLookupResult(
+ requested: _resolver.toLegacyElement(getterElement),
+ );
+ } else {
+ var recoveryElement = scopeSetter ?? propertyResult.setter;
+ return LexicalLookupResult(
+ recovery: _resolver.toLegacyElement(recoveryElement),
+ );
+ }
+ }
+ }
+
+ static bool _isInstanceMember(Element element) {
+ var enclosing = element.enclosingElement;
+ return enclosing is ClassElement || enclosing is ExtensionElement;
+ }
+}
+
+class LexicalLookupResult {
+ final Element requested;
+ final Element recovery;
+
+ LexicalLookupResult({this.requested, this.recovery});
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index edc0374..dbbcb96 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -51,6 +51,7 @@
@required AstNode receiverErrorNode,
@required Expression nameErrorNode,
}) {
+ assert(receiverType != null);
_receiver = receiver;
_name = name;
_nameErrorNode = nameErrorNode;
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index d45a6c0..3fa6b6d 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -4399,13 +4399,10 @@
"changing the import to not be deferred.");
/**
- * 15 Metadata: Metadata consists of a series of annotations, each of which
- * begin with the character @, followed by a constant expression that must be
- * either a reference to a compile-time constant variable, or a call to a
- * constant constructor.
+ * No parameters.
*/
static const CompileTimeErrorCode INVALID_ANNOTATION_GETTER =
- CompileTimeErrorCode(
+ CompileTimeErrorCodeWithUniqueName('INVALID_ANNOTATION',
'INVALID_ANNOTATION_GETTER', "Getters can't be used as annotations.",
correction: "Try using a top-level variable or a field.");
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 54211be..ef6c8c9 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -311,7 +311,10 @@
Expression rhs = node.rightHandSide;
if (operatorType == TokenType.EQ ||
operatorType == TokenType.QUESTION_QUESTION_EQ) {
- _checkForInvalidAssignment(lhs, rhs);
+ // Already handled in the assignment resolver.
+ if (lhs is! SimpleIdentifier) {
+ _checkForInvalidAssignment(lhs, rhs);
+ }
} else {
_checkForArgumentTypeNotAssignableForArgument(rhs);
}
@@ -1625,6 +1628,12 @@
/// [StaticWarningCode.ASSIGNMENT_TO_FINAL], and
/// [StaticWarningCode.ASSIGNMENT_TO_METHOD].
void _checkForAssignmentToFinal(Expression expression) {
+ // Already handled in the assignment resolver.
+ if (expression is SimpleIdentifier &&
+ expression.parent is AssignmentExpression) {
+ return;
+ }
+
// prepare element
Element element;
AstNode highlightedNode = expression;
@@ -4819,23 +4828,24 @@
return;
}
ClassElement classElement = node.declaredElement;
- var type = classElement.thisType;
var supertype = classElement.supertype;
- List<InterfaceType> supertypesForMixinInference = <InterfaceType>[];
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference, supertype, type);
+
+ var interfacesMerger = InterfacesMerger(_typeSystem);
+ interfacesMerger.addWithSupertypes(supertype);
+
for (var typeName in withClause.mixinTypes) {
var mixinType = typeName.type;
- var mixinElement = mixinType.element;
- if (mixinElement is ClassElement) {
+ if (mixinType is InterfaceType) {
+ var mixinElement = mixinType.element;
if (typeName.typeArguments == null) {
var mixinSupertypeConstraints = _typeSystem
.gatherMixinSupertypeConstraintsForInference(mixinElement);
if (mixinSupertypeConstraints.isNotEmpty) {
var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
- typeName,
- mixinSupertypeConstraints,
- supertypesForMixinInference);
+ typeName,
+ mixinSupertypeConstraints,
+ interfacesMerger.typeList,
+ );
if (matchingInterfaceTypes != null) {
// Try to pattern match matchingInterfaceType against
// mixinSupertypeConstraint to find the correct set of type
@@ -4855,8 +4865,7 @@
}
}
}
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference, mixinType, type);
+ interfacesMerger.addWithSupertypes(mixinType);
}
}
}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index e2fd8ef..0c60e48 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -33,6 +33,7 @@
import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
+import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
import 'package:analyzer/src/dart/resolver/postfix_expression_resolver.dart';
import 'package:analyzer/src/dart/resolver/prefix_expression_resolver.dart';
@@ -52,6 +53,7 @@
import 'package:analyzer/src/generated/migration.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/static_type_analyzer.dart';
+import 'package:analyzer/src/generated/this_access_tracker.dart';
import 'package:analyzer/src/generated/type_promotion_manager.dart';
import 'package:analyzer/src/generated/variable_type_provider.dart';
import 'package:meta/meta.dart';
@@ -207,6 +209,9 @@
/// or `null` if the current node is not contained in a mixin.
MixinDeclaration _enclosingMixinDeclaration;
+ /// The helper for tracking if the current location has access to `this`.
+ final ThisAccessTracker _thisAccessTracker = ThisAccessTracker.unit();
+
InferenceContext inferenceContext;
/// If a class, or mixin, is being resolved, the type of the class.
@@ -512,6 +517,16 @@
return null;
}
+ /// Return the result of lexical lookup for the [node], not `null`.
+ ///
+ /// Implements `16.35 Lexical Lookup` from the language specification.
+ LexicalLookupResult lexicalLookup({
+ @required SimpleIdentifier node,
+ @required bool setter,
+ }) {
+ return LexicalLookup(this).perform(node: node, setter: setter);
+ }
+
/// If we reached a null-shorting termination, and the [node] has null
/// shorting, make the type of the [node] nullable.
void nullShortingTermination(Expression node, {bool discardType = false}) {
@@ -803,8 +818,10 @@
void visitBlockFunctionBody(BlockFunctionBody node) {
try {
inferenceContext.pushFunctionBodyContext(node);
+ _thisAccessTracker.enterFunctionBody(node);
super.visitBlockFunctionBody(node);
} finally {
+ _thisAccessTracker.exitFunctionBody(node);
inferenceContext.popFunctionBodyContext(node);
}
}
@@ -1159,12 +1176,14 @@
if (resolveOnlyCommentInFunctionBody) {
return;
}
+
try {
inferenceContext.pushFunctionBodyContext(node);
InferenceContext.setType(
node.expression,
inferenceContext.bodyContext.contextType,
);
+ _thisAccessTracker.enterFunctionBody(node);
super.visitExpressionFunctionBody(node);
@@ -1172,6 +1191,7 @@
inferenceContext.bodyContext.addReturnExpression(node.expression);
} finally {
+ _thisAccessTracker.exitFunctionBody(node);
inferenceContext.popFunctionBodyContext(node);
}
}
@@ -1201,6 +1221,16 @@
}
@override
+ void visitFieldDeclaration(FieldDeclaration node) {
+ _thisAccessTracker.enterFieldDeclaration(node);
+ try {
+ super.visitFieldDeclaration(node);
+ } finally {
+ _thisAccessTracker.exitFieldDeclaration(node);
+ }
+ }
+
+ @override
void visitForElementInScope(ForElement node) {
_forResolver.resolveElement(node);
}
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index 5248e64..249c4eb 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/class_hierarchy.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
@@ -208,12 +209,14 @@
final FeatureSet featureSet;
final InterfaceType classType;
- List<InterfaceType> mixinTypes = [];
- List<InterfaceType> supertypesForMixinInference;
+ InterfacesMerger interfacesMerger;
_MixinInference(this.element, this.featureSet)
: typeSystem = element.library.typeSystem,
- classType = element.thisType;
+ classType = element.thisType {
+ interfacesMerger = InterfacesMerger(typeSystem);
+ interfacesMerger.addWithSupertypes(element.supertype);
+ }
NullabilitySuffix get _noneOrStarSuffix {
return _nonNullableEnabled
@@ -228,19 +231,7 @@
for (var mixinNode in withClause.mixinTypes) {
var mixinType = _inferSingle(mixinNode);
- mixinTypes.add(mixinType);
-
- _addSupertypes(mixinType);
- }
- }
-
- void _addSupertypes(InterfaceType type) {
- if (supertypesForMixinInference != null) {
- ClassElementImpl.collectAllSupertypes(
- supertypesForMixinInference,
- type,
- classType,
- );
+ interfacesMerger.addWithSupertypes(mixinType);
}
}
@@ -293,17 +284,9 @@
return mixinType;
}
- if (supertypesForMixinInference == null) {
- supertypesForMixinInference = <InterfaceType>[];
- _addSupertypes(classType.superclass);
- for (var previousMixinType in mixinTypes) {
- _addSupertypes(previousMixinType);
- }
- }
-
var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
mixinSupertypeConstraints,
- supertypesForMixinInference,
+ interfacesMerger.typeList,
);
// Note: if matchingInterfaceType is null, that's an error. Also,
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 2e7094e..1204ae1 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 0.40.1-dev
+version: 0.40.1
description: This package provides a library that performs static analysis of Dart code.
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -7,7 +7,7 @@
sdk: '>=2.7.0 <3.0.0'
dependencies:
- _fe_analyzer_shared: ^8.0.0
+ _fe_analyzer_shared: ^9.0.0
args: ^1.0.0
charcode: ^1.1.2
cli_util: '>=0.1.4 <0.3.0'
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index a207e65..db7b889 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -538,38 +538,6 @@
verifyTestResolved();
}
- test_getter_and_setter_fromMixins_bare_identifier() async {
- await assertNoErrorsInCode('''
-class B {}
-class M1 {
- get x => null;
- set x(value) {}
-}
-class M2 {
- get x => null;
- set x(value) {}
-}
-class C extends B with M1, M2 {
- void f() {
- x += 1;
- }
-}
-''');
- verifyTestResolved();
-
- // Verify that both the getter and setter for "x" in C.f() refer to the
- // accessors defined in M2.
- var leftHandSide = findNode.simple('x +=');
- expect(
- leftHandSide.staticElement,
- findElement.setter('x', of: 'M2'),
- );
- expect(
- leftHandSide.auxiliaryElements.staticElement,
- findElement.getter('x', of: 'M2'),
- );
- }
-
test_getter_and_setter_fromMixins_property_access() async {
await assertNoErrorsInCode(r'''
class B {}
@@ -1161,29 +1129,6 @@
verifyTestResolved();
}
- test_setter_fromMixins_bare_identifier() async {
- await resolveTestCode('''
-class B {}assertNoErrorsInCode
-class M1 {
- set x(value) {}
-}
-class M2 {
- set x(value) {}
-}
-class C extends B with M1, M2 {
- void f() {
- x = 1;
- }
-}
-''');
- verifyTestResolved();
-
- expect(
- findNode.simple('x = ').staticElement,
- findElement.setter('x', of: 'M2'),
- );
- }
-
test_setter_fromMixins_property_access() async {
await assertNoErrorsInCode('''
class B {}
@@ -1206,19 +1151,6 @@
);
}
- test_setter_inherited() async {
- await assertNoErrorsInCode(r'''
-class A {
- int get x => 0;
- set x(int p) {}
-}
-class B extends A {
- int get x => super.x == null ? 0 : super.x;
- int f() => x = 1;
-}''');
- verifyTestResolved();
- }
-
test_setter_static() async {
await assertNoErrorsInCode(r'''
set s(x) {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index 0aae50a..0476a9b 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -2,7 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
@@ -13,7 +12,6 @@
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/member.dart';
import 'package:analyzer/src/dart/element/type.dart';
-import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -21,12 +19,10 @@
import '../../../generated/elements_types_mixin.dart';
import '../../../utils.dart';
import '../resolution/context_collection_resolution.dart';
-import 'base.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisDriverResolutionTest);
- defineReflectiveTests(DriverResolutionWithExperimentsTest);
});
}
@@ -784,6 +780,29 @@
expect(value.staticType, typeProvider.intType);
}
+ test_binaryExpression_gtGtGt() async {
+ writeTestPackageAnalysisOptionsFile(
+ AnalysisOptionsFileConfig(
+ experiments: [EnableString.triple_shift],
+ ),
+ );
+
+ await resolveTestCode('''
+class A {
+ A operator >>>(int amount) => this;
+}
+f(A a) {
+ a >>> 3;
+}
+''');
+
+ assertBinaryExpression(
+ findNode.binary('>>> 3'),
+ element: findElement.method('>>>'),
+ type: 'A',
+ );
+ }
+
test_binaryExpression_ifNull() async {
String content = r'''
int x = 3;
@@ -8601,39 +8620,3 @@
fail('Not found $name');
}
}
-
-/// Resolution tests that are run with all of the experiments enabled.
-@reflectiveTest
-class DriverResolutionWithExperimentsTest extends BaseAnalysisDriverTest {
- @override
- AnalysisOptionsImpl createAnalysisOptions() => super.createAnalysisOptions()
- ..contextFeatures = FeatureSet.fromEnableFlags2(
- sdkLanguageVersion: ExperimentStatus.testingSdkLanguageVersion,
- flags: [EnableString.triple_shift],
- );
-
- test_binaryExpression_gtGtGt() async {
- addTestFile('''
-class A {
- A operator >>>(int amount) => this;
-}
-f(A a) {
- a >>> 3;
-}
-''');
- var result = await driver.getResult(testFile);
- CompilationUnit unit = result.unit;
- MethodDeclaration declaration =
- (unit.declarations[0] as ClassDeclaration).members[0];
- ExecutableElement operatorElement = declaration.declaredElement;
- expect(operatorElement.name, '>>>');
- ExpressionStatement statement =
- ((unit.declarations[1] as FunctionDeclaration).functionExpression.body
- as BlockFunctionBody)
- .block
- .statements[0];
- BinaryExpression binary = statement.expression;
- expect(binary.operator.type, TokenType.GT_GT_GT);
- expect(binary.staticElement, operatorElement);
- }
-}
diff --git a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
index 843a040..9700848 100644
--- a/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/assignment_test.dart
@@ -500,7 +500,7 @@
writeElement: null,
writeType: 'dynamic',
operatorElement: null,
- type: 'num',
+ type: 'dynamic',
);
assertSimpleIdentifier(
@@ -594,7 +594,7 @@
writeElement: null,
writeType: 'dynamic',
operatorElement: null,
- type: 'num',
+ type: 'dynamic',
);
assertSimpleIdentifier(
@@ -1483,6 +1483,43 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_importPrefix_hasSuperSetter_simple() async {
+ await assertErrorsInCode('''
+// ignore:unused_import
+import 'dart:math' as x;
+
+class A {
+ var x;
+}
+
+class B extends A {
+ void f() {
+ x = 2;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 109, 1),
+ ]);
+
+ var assignment = findNode.assignment('x = 2');
+ assertAssignment(
+ assignment,
+ readElement: null,
+ readType: null,
+ writeElement: findElement.prefix('x'),
+ writeType: 'dynamic',
+ operatorElement: null,
+ type: 'int',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: null,
+ writeElement: findElement.prefix('x'),
+ type: null,
+ );
+ }
+
test_simpleIdentifier_importPrefix_simple() async {
await assertErrorsInCode('''
import 'dart:math' as x;
@@ -1671,6 +1708,42 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_parameter_compound_ifNull2() async {
+ var question = typeToStringWithNullability ? '?' : '';
+ var errorOffset = typeToStringWithNullability ? 77 : 76;
+ await assertErrorsInCode('''
+class A {}
+class B extends A {}
+class C extends A {}
+
+void f(B$question x) {
+ x ??= C();
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_ASSIGNMENT, errorOffset, 3),
+ ]);
+
+ var assignment = findNode.assignment('x ??=');
+ assertAssignment(
+ assignment,
+ readElement: findElement.parameter('x'),
+ readType: 'B$question',
+ writeElement: findElement.parameter('x'),
+ writeType: 'B$question',
+ operatorElement: null,
+ type: 'A',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: findElement.parameter('x'),
+ writeElement: findElement.parameter('x'),
+ type: 'B$question',
+ );
+
+ assertType(assignment.rightHandSide, 'C');
+ }
+
test_simpleIdentifier_parameter_compound_ifNull_notAssignableType() async {
var question = typeToStringWithNullability ? '?' : '';
var code = '''
@@ -1773,6 +1846,41 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_parameter_simple_context() async {
+ await assertNoErrorsInCode(r'''
+void f(Object x) {
+ if (x is double) {
+ x = 1;
+ }
+}
+''');
+
+ var expectedType = typeStringByNullability(
+ nullable: 'double',
+ legacy: 'int',
+ );
+
+ var assignment = findNode.assignment('x = 1');
+ assertAssignment(
+ assignment,
+ readElement: null,
+ readType: null,
+ writeElement: findElement.parameter('x'),
+ writeType: 'Object',
+ operatorElement: null,
+ type: expectedType,
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: null,
+ writeElement: findElement.parameter('x'),
+ type: 'Object',
+ );
+
+ assertType(assignment.rightHandSide, expectedType);
+ }
+
test_simpleIdentifier_parameter_simple_notAssignableType() async {
await assertErrorsInCode(r'''
void f(int x) {
@@ -1833,6 +1941,40 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_superSetter_simple() async {
+ await assertNoErrorsInCode(r'''
+class A {
+ set x(num _) {}
+}
+
+class B extends A {
+ void f() {
+ x = 2;
+ }
+}
+''');
+
+ var assignment = findNode.assignment('x = 2');
+ assertAssignment(
+ assignment,
+ readElement: null,
+ readType: null,
+ writeElement: findElement.setter('x'),
+ writeType: 'num',
+ operatorElement: null,
+ type: 'int',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: null,
+ writeElement: findElement.setter('x'),
+ type: null,
+ );
+
+ assertType(assignment.rightHandSide, 'int');
+ }
+
test_simpleIdentifier_synthetic_simple() async {
await assertErrorsInCode('''
void f(int y) {
@@ -1868,6 +2010,42 @@
);
}
+ test_simpleIdentifier_thisGetter_superGetter_simple() async {
+ await assertNoErrorsInCode('''
+class A {
+ int x = 0;
+}
+
+class B extends A {
+ int get x => 1;
+
+ void f() {
+ x = 2;
+ }
+}
+''');
+
+ var assignment = findNode.assignment('x = 2');
+ assertAssignment(
+ assignment,
+ readElement: null,
+ readType: null,
+ writeElement: findElement.setter('x', of: 'A'),
+ writeType: 'int',
+ operatorElement: null,
+ type: 'int',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: null,
+ writeElement: findElement.setter('x', of: 'A'),
+ type: null,
+ );
+
+ assertType(assignment.rightHandSide, 'int');
+ }
+
test_simpleIdentifier_thisGetter_thisSetter_compound() async {
await assertNoErrorsInCode('''
class C {
@@ -1904,6 +2082,49 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_thisGetter_thisSetter_fromMixins_compound() async {
+ await assertNoErrorsInCode('''
+class M1 {
+ int get x => 0;
+ set x(num _) {}
+}
+
+class M2 {
+ int get x => 0;
+ set x(num _) {}
+}
+
+class C with M1, M2 {
+ void f() {
+ x += 2;
+ }
+}
+''');
+
+ var assignment = findNode.assignment('x += 2');
+ assertAssignment(
+ assignment,
+ readElement: findElement.getter('x', of: 'M2'),
+ readType: 'int',
+ writeElement: findElement.setter('x', of: 'M2'),
+ writeType: 'num',
+ operatorElement: elementMatcher(
+ numElement.getMethod('+'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary,
+ ),
+ type: 'int',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: findElement.getter('x', of: 'M2'),
+ writeElement: findElement.setter('x', of: 'M2'),
+ type: 'num',
+ );
+
+ assertType(assignment.rightHandSide, 'int');
+ }
+
test_simpleIdentifier_topGetter_topSetter_compound() async {
await assertNoErrorsInCode('''
int get x => 0;
@@ -1938,6 +2159,44 @@
assertType(assignment.rightHandSide, 'int');
}
+ test_simpleIdentifier_topGetter_topSetter_compound_ifNull2() async {
+ var question = typeToStringWithNullability ? '?' : '';
+ await assertErrorsInCode('''
+void f() {
+ x ??= C();
+}
+
+class A {}
+class B extends A {}
+class C extends A {}
+
+B$question get x => B();
+set x(B$question _) {}
+''', [
+ error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 3),
+ ]);
+
+ var assignment = findNode.assignment('x ??=');
+ assertAssignment(
+ assignment,
+ readElement: findElement.topGet('x'),
+ readType: 'B$question',
+ writeElement: findElement.topSet('x'),
+ writeType: 'B$question',
+ operatorElement: null,
+ type: 'A',
+ );
+
+ assertSimpleIdentifier(
+ assignment.leftHandSide,
+ readElement: findElement.topGet('x'),
+ writeElement: findElement.topSet('x'),
+ type: 'B$question',
+ );
+
+ assertType(assignment.rightHandSide, 'C');
+ }
+
test_simpleIdentifier_topGetter_topSetter_fromClass_compound() async {
await assertNoErrorsInCode('''
int get x => 0;
@@ -2075,13 +2334,12 @@
}
''', [
error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
- error(CompileTimeErrorCode.UNDEFINED_OPERATOR, 17, 2),
]);
var assignment = findNode.assignment('int += 3');
assertAssignment(
assignment,
- readElement: null,
+ readElement: intElement,
readType: 'dynamic',
writeElement: intElement,
writeType: 'dynamic',
@@ -2093,7 +2351,7 @@
assignment.leftHandSide,
readElement: null,
writeElement: intElement,
- type: 'Type',
+ type: 'dynamic',
);
assertType(assignment.rightHandSide, 'int');
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index 865a89e..3cfa0ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -141,6 +141,34 @@
);
}
+ test_inc_notLValue_typeLiteral_typeParameter() async {
+ await assertErrorsInCode(r'''
+void f<T>() {
+ T++;
+}
+''', [
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 16, 1),
+ ]);
+
+ var postfix = findNode.postfix('T++');
+ assertPostfixExpression(
+ postfix,
+ readElement: null,
+ readType: 'dynamic',
+ writeElement: findElement.typeParameter('T'),
+ writeType: 'dynamic',
+ element: null,
+ type: 'dynamic',
+ );
+
+ assertSimpleIdentifier(
+ postfix.operand,
+ readElement: findElement.typeParameter('T'),
+ writeElement: findElement.typeParameter('T'),
+ type: 'Type',
+ );
+ }
+
test_inc_prefixedIdentifier_instance() async {
await assertNoErrorsInCode(r'''
class A {
diff --git a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
index 47bac74..cdba72f 100644
--- a/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/assignment_to_type_test.dart
@@ -28,11 +28,11 @@
test_dynamic() async {
await assertErrorsInCode(r'''
-main() {
+void f() {
dynamic = 1;
}
''', [
- error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 11, 7),
+ error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 7),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/instance_member_access_from_static_test.dart b/pkg/analyzer/test/src/diagnostics/instance_member_access_from_static_test.dart
index 4ec14fa..c1a122b 100644
--- a/pkg/analyzer/test/src/diagnostics/instance_member_access_from_static_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/instance_member_access_from_static_test.dart
@@ -15,7 +15,23 @@
@reflectiveTest
class InstanceMemberAccessFromStaticTest extends PubPackageResolutionTest {
- test_class_getter_fromMethod() async {
+ test_class_superMethod_fromMethod() async {
+ await assertErrorsInCode(r'''
+class A {
+ void foo() {}
+}
+
+class B extends A {
+ static void bar() {
+ foo();
+ }
+}
+''', [
+ error(CompileTimeErrorCode.INSTANCE_MEMBER_ACCESS_FROM_STATIC, 75, 3),
+ ]);
+ }
+
+ test_class_thisGetter_fromMethod() async {
await assertErrorsInCode(r'''
class A {
int get foo => 0;
@@ -29,7 +45,7 @@
]);
}
- test_class_getter_fromMethod_fromClosure() async {
+ test_class_thisGetter_fromMethod_fromClosure() async {
await assertErrorsInCode(r'''
class A {
int get foo => 0;
@@ -45,7 +61,7 @@
]);
}
- test_class_method_fromMethod() async {
+ test_class_thisMethod_fromMethod() async {
await assertErrorsInCode(r'''
class A {
void foo() {}
@@ -59,7 +75,7 @@
]);
}
- test_class_setter_fromMethod() async {
+ test_class_thisSetter_fromMethod() async {
await assertErrorsInCode(r'''
class A {
set foo(int _) {}
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_inference_no_possible_substitution_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_inference_no_possible_substitution_test.dart
new file mode 100644
index 0000000..cdc0fde
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_inference_no_possible_substitution_test.dart
@@ -0,0 +1,59 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+import '../dart/resolution/resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(MixinInferenceNoPossibleSubstitutionTest);
+ defineReflectiveTests(
+ MixinInferenceNoPossibleSubstitutionWithNullSafetyTest,
+ );
+ });
+}
+
+@reflectiveTest
+class MixinInferenceNoPossibleSubstitutionTest extends PubPackageResolutionTest
+ with MixinInferenceNoPossibleSubstitutionTestCases {}
+
+mixin MixinInferenceNoPossibleSubstitutionTestCases on ResolutionTest {
+ test_valid_single() async {
+ await assertNoErrorsInCode(r'''
+class A<T> {}
+
+mixin M<T> on A<T> {}
+
+class X extends A<int> with M {}
+''');
+
+ assertType(findNode.typeName('M {}'), 'M<int>');
+ }
+}
+
+@reflectiveTest
+class MixinInferenceNoPossibleSubstitutionWithNullSafetyTest
+ extends PubPackageResolutionTest
+ with WithNullSafetyMixin, MixinInferenceNoPossibleSubstitutionTestCases {
+ test_valid_nonNullableMixins_legacyApplication() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A<T> {}
+
+mixin B<T> on A<T> {}
+mixin C<T> on A<T> {}
+''');
+
+ await assertNoErrorsInCode('''
+// @dart=2.8
+import 'a.dart';
+
+class D extends A<int> with B<int>, C {}
+''');
+
+ assertType(findNode.typeName('B<int>'), 'B<int*>*');
+ assertType(findNode.typeName('C {}'), 'C<int*>*');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/prefix_identifier_not_followed_by_dot_test.dart b/pkg/analyzer/test/src/diagnostics/prefix_identifier_not_followed_by_dot_test.dart
index 76faf80..4f01073 100644
--- a/pkg/analyzer/test/src/diagnostics/prefix_identifier_not_followed_by_dot_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/prefix_identifier_not_followed_by_dot_test.dart
@@ -61,6 +61,25 @@
]);
}
+ test_assignment_in_method_hasSuperField() async {
+ await assertErrorsInCode('''
+// ignore:unused_import
+import 'dart:math' as p;
+
+class A {
+ var p;
+}
+
+class B extends A {
+ void f() {
+ p = 1;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, 109, 1),
+ ]);
+ }
+
test_assignment_not_in_method() async {
newFile('$testPackageLibPath/lib.dart', content: '''
library lib;
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index e23b641..94870ce 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -364,6 +364,8 @@
as mixin_class_declares_constructor;
import 'mixin_declares_constructor_test.dart' as mixin_declares_constructor;
import 'mixin_deferred_class_test.dart' as mixin_deferred_class;
+import 'mixin_inference_no_possible_substitution_test.dart'
+ as mixin_inference_no_possible_substitution;
import 'mixin_inherits_from_not_object_test.dart'
as mixin_inherits_from_not_object;
import 'mixin_of_disallowed_class_test.dart' as mixin_of_disallowed_class;
@@ -879,6 +881,7 @@
mixin_class_declares_constructor.main();
mixin_declares_constructor.main();
mixin_deferred_class.main();
+ mixin_inference_no_possible_substitution.main();
mixin_inherits_from_not_object.main();
mixin_of_disallowed_class.main();
mixin_of_non_class.main();
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index a9edb27..80b832c 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -9441,6 +9441,31 @@
annotateNullability: true);
}
+ test_mixin_inference_nullSafety2() async {
+ featureSet = enableNnbd;
+ addLibrarySource('/a.dart', r'''
+class A<T> {}
+
+mixin B<T> on A<T> {}
+mixin C<T> on A<T> {}
+''');
+ var library = await checkLibrary(r'''
+// @dart=2.8
+import 'a.dart';
+
+class D extends A<int> with B<int>, C {}
+''');
+ checkElementText(
+ library,
+ r'''
+import 'a.dart';
+class D extends A<int*>* with B<int*>*, C<int*>* {
+ synthetic D();
+}
+''',
+ annotateNullability: true);
+ }
+
test_mixin_inference_nullSafety_mixed_inOrder() async {
featureSet = enableNnbd;
addLibrarySource('/a.dart', r'''
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index e9d92c8..7be2213 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -4,6 +4,7 @@
- Added `isSystemIsolate` property to `IsolateRef` and `Isolate`.
- Added `isSystemIsolateGroup` property to `IsolateGroupRef` and `IsolateGroup`.
- Added `serviceIsolates` and `serviceIsolateGroups` properties to `VM`.
+- Fixed issue where `VmServerConnection` would always response with a string ID even if the request ID was not a string.
## 4.2.0
- Update to version `3.37.0` of the spec.
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 8cc7123..c9b4ec7 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -1166,6 +1166,20 @@
Future<Success> streamListen(String streamId);
}
+class _PendingServiceRequest {
+ Future<Map<String, Object>> get future => _completer.future;
+ final _completer = Completer<Map<String, Object>>();
+
+ final dynamic originalId;
+
+ _PendingServiceRequest(this.originalId);
+
+ void complete(Map<String, Object> response) {
+ response['id'] = originalId;
+ _completer.complete(response);
+ }
+}
+
/// A Dart VM Service Protocol connection that delegates requests to a
/// [VmServiceInterface] implementation.
///
@@ -1189,8 +1203,7 @@
final _doneCompleter = Completer<Null>();
/// Pending service extension requests to this client by id.
- final _pendingServiceExtensionRequests =
- <String, Completer<Map<String, Object>>>{};
+ final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
VmServerConnection(this._requestStream, this._responseSink,
this._serviceExtensionRegistry, this._serviceImplementation) {
@@ -1212,21 +1225,19 @@
// multiple clients ids.
var newId = '${_nextServiceRequestId++}:$originalId';
request['id'] = newId;
- var responseCompleter = Completer<Map<String, Object>>();
- _pendingServiceExtensionRequests[newId] = responseCompleter;
+ var pendingRequest = _PendingServiceRequest(originalId);
+ _pendingServiceExtensionRequests[newId] = pendingRequest;
_responseSink.add(request);
- return responseCompleter.future;
+ return pendingRequest.future;
}
void _delegateRequest(Map<String, Object> request) async {
try {
- var id = request['id'] as String;
+ var id = request['id'];
// Check if this is actually a response to a pending request.
if (_pendingServiceExtensionRequests.containsKey(id)) {
- // Restore the original request ID.
- var originalId = id.substring(id.indexOf(':') + 1);
- _pendingServiceExtensionRequests[id]
- .complete(Map.of(request)..['id'] = originalId);
+ final pending = _pendingServiceExtensionRequests[id];
+ pending.complete(Map.of(request));
return;
}
var method = request['method'] as String;
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 1553861..1fbe545 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -627,6 +627,20 @@
// The server class, takes a VmServiceInterface and delegates to it
// automatically.
gen.write('''
+ class _PendingServiceRequest {
+ Future<Map<String, Object>> get future => _completer.future;
+ final _completer = Completer<Map<String, Object>>();
+
+ final dynamic originalId;
+
+ _PendingServiceRequest(this.originalId);
+
+ void complete(Map<String, Object> response) {
+ response['id'] = originalId;
+ _completer.complete(response);
+ }
+ }
+
/// A Dart VM Service Protocol connection that delegates requests to a
/// [VmServiceInterface] implementation.
///
@@ -649,8 +663,7 @@
final _doneCompleter = Completer<Null>();
/// Pending service extension requests to this client by id.
- final _pendingServiceExtensionRequests =
- <String, Completer<Map<String, Object>>>{};
+ final _pendingServiceExtensionRequests = <dynamic, _PendingServiceRequest>{};
VmServerConnection(
this._requestStream, this._responseSink, this._serviceExtensionRegistry,
@@ -673,21 +686,19 @@
// multiple clients ids.
var newId = '\${_nextServiceRequestId++}:\$originalId';
request['id'] = newId;
- var responseCompleter = Completer<Map<String, Object>>();
- _pendingServiceExtensionRequests[newId] = responseCompleter;
+ var pendingRequest = _PendingServiceRequest(originalId);
+ _pendingServiceExtensionRequests[newId] = pendingRequest;
_responseSink.add(request);
- return responseCompleter.future;
+ return pendingRequest.future;
}
void _delegateRequest(Map<String, Object> request) async {
try {
- var id = request['id'] as String;
+ var id = request['id'];
// Check if this is actually a response to a pending request.
if (_pendingServiceExtensionRequests.containsKey(id)) {
- // Restore the original request ID.
- var originalId = id.substring(id.indexOf(':') + 1);
- _pendingServiceExtensionRequests[id].complete(
- Map.of(request)..['id'] = originalId);
+ final pending = _pendingServiceExtensionRequests[id];
+ pending.complete(Map.of(request));
return;
}
var method = request['method'] as String;
diff --git a/pkg/vm_snapshot_analysis/lib/precompiler_trace.dart b/pkg/vm_snapshot_analysis/lib/precompiler_trace.dart
index 42cd027..2cbcea2 100644
--- a/pkg/vm_snapshot_analysis/lib/precompiler_trace.dart
+++ b/pkg/vm_snapshot_analysis/lib/precompiler_trace.dart
@@ -122,8 +122,17 @@
final nodeByEntityId = <CallGraphNode>[];
ProgramInfoNode collapsed(ProgramInfoNode nn) {
+ // Root always collapses onto itself.
+ if (nn == program.root) {
+ return nn;
+ }
+
+ // Even though all code is grouped into libraries, not all libraries
+ // are grouped into packages (e.g. dart:* libraries). Meaning
+ // that if we are collapsing by package we need to stop right before
+ // hitting the root node.
var n = nn;
- while (n.parent != null && n.type != type) {
+ while (n.parent != program.root && n.type != type) {
n = n.parent;
}
return n;
diff --git a/pkg/vm_snapshot_analysis/test/precompiler_trace_test.dart b/pkg/vm_snapshot_analysis/test/precompiler_trace_test.dart
index ef294fe..c4ad546 100644
--- a/pkg/vm_snapshot_analysis/test/precompiler_trace_test.dart
+++ b/pkg/vm_snapshot_analysis/test/precompiler_trace_test.dart
@@ -6,6 +6,7 @@
import 'package:test/test.dart';
import 'package:vm_snapshot_analysis/precompiler_trace.dart';
+import 'package:vm_snapshot_analysis/program_info.dart';
import 'utils.dart';
@@ -99,5 +100,18 @@
]));
});
});
+
+ test('collapse-by-package', () async {
+ await withFlag(
+ 'collapse-by-package', testSource, '--trace_precompiler_to',
+ (json) async {
+ final jsonRaw = await loadJson(File(json));
+ final callGraph = loadTrace(jsonRaw).collapse(NodeType.packageNode);
+
+ // Collapsing by package should not collapse dart:* libraries into root
+ // node and create predecessors for the root node.
+ expect(callGraph.root.pred, isEmpty);
+ });
+ });
});
}
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc
index 507aadb..67e47df 100644
--- a/runtime/bin/directory_android.cc
+++ b/runtime/bin/directory_android.cc
@@ -172,8 +172,12 @@
}
stat_success =
TEMP_FAILURE_RETRY(fstatat(ns.fd(), ns.path(), &entry_info, 0));
- if (stat_success == -1) {
+ if (stat_success == -1 || (S_IFMT & entry_info.st_mode) == 0) {
// Report a broken link as a link, even if follow_links is true.
+ // A symbolic link can potentially point to an anon_inode. For
+ // example, an epoll file descriptor will have a symbolic link whose
+ // content is the string anon_inode:[eventpoll]. In this case, the
+ // target doesn't belong to any regular file catogory.
return kListLink;
}
if (S_ISDIR(entry_info.st_mode)) {
@@ -193,16 +197,12 @@
return Next(listing);
}
return kListDirectory;
- } else if (S_ISREG(entry_info.st_mode) || S_ISCHR(entry_info.st_mode) ||
- S_ISBLK(entry_info.st_mode) ||
- S_ISFIFO(entry_info.st_mode) ||
- S_ISSOCK(entry_info.st_mode)) {
- return kListFile;
} else if (S_ISLNK(entry_info.st_mode)) {
return kListLink;
} else {
- FATAL1("Unexpected st_mode: %d\n", entry_info.st_mode);
- return kListError;
+ // Regular files, character devices, block devices, fifos, sockets and
+ // unknown types are all considered as files.
+ return kListFile;
}
}
diff --git a/runtime/bin/directory_fuchsia.cc b/runtime/bin/directory_fuchsia.cc
index 0ddddd1..4cbffbe 100644
--- a/runtime/bin/directory_fuchsia.cc
+++ b/runtime/bin/directory_fuchsia.cc
@@ -178,8 +178,12 @@
}
stat_success =
TEMP_FAILURE_RETRY(fstatat(ns.fd(), ns.path(), &entry_info, 0));
- if (stat_success == -1) {
+ if (stat_success == -1 || (S_IFMT & entry_info.st_mode) == 0) {
// Report a broken link as a link, even if follow_links is true.
+ // A symbolic link can potentially point to an anon_inode. For
+ // example, an epoll file descriptor will have a symbolic link whose
+ // content is the string anon_inode:[eventpoll]. In this case, the
+ // target doesn't belong to any regular file catogory.
return kListLink;
}
if (S_ISDIR(entry_info.st_mode)) {
@@ -199,16 +203,12 @@
return Next(listing);
}
return kListDirectory;
- } else if (S_ISREG(entry_info.st_mode) || S_ISCHR(entry_info.st_mode) ||
- S_ISBLK(entry_info.st_mode) ||
- S_ISFIFO(entry_info.st_mode) ||
- S_ISSOCK(entry_info.st_mode)) {
- return kListFile;
} else if (S_ISLNK(entry_info.st_mode)) {
return kListLink;
} else {
- FATAL1("Unexpected st_mode: %d\n", entry_info.st_mode);
- return kListError;
+ // Regular files, character devices, block devices, fifos, sockets and
+ // unknown types are all considerred as files.
+ return kListFile;
}
}
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc
index 73a199a..5321a9a 100644
--- a/runtime/bin/directory_linux.cc
+++ b/runtime/bin/directory_linux.cc
@@ -172,8 +172,12 @@
}
stat_success =
TEMP_FAILURE_RETRY(fstatat64(ns.fd(), ns.path(), &entry_info, 0));
- if (stat_success == -1) {
+ if (stat_success == -1 || (S_IFMT & entry_info.st_mode) == 0) {
// Report a broken link as a link, even if follow_links is true.
+ // A symbolic link can potentially point to an anon_inode. For
+ // example, an epoll file descriptor will have a symbolic link whose
+ // content is the string anon_inode:[eventpoll]. In this case, the
+ // target doesn't belong to any regular file catogory.
return kListLink;
}
if (S_ISDIR(entry_info.st_mode)) {
@@ -193,16 +197,12 @@
return Next(listing);
}
return kListDirectory;
- } else if (S_ISREG(entry_info.st_mode) || S_ISCHR(entry_info.st_mode) ||
- S_ISBLK(entry_info.st_mode) ||
- S_ISFIFO(entry_info.st_mode) ||
- S_ISSOCK(entry_info.st_mode)) {
- return kListFile;
} else if (S_ISLNK(entry_info.st_mode)) {
return kListLink;
} else {
- FATAL1("Unexpected st_mode: %d\n", entry_info.st_mode);
- return kListError;
+ // Regular files, character devices, block devices, fifos, sockets and
+ // unknown types are all considered as files.
+ return kListFile;
}
}
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc
index e7bb3a5..7a884e9 100644
--- a/runtime/bin/directory_macos.cc
+++ b/runtime/bin/directory_macos.cc
@@ -159,8 +159,12 @@
}
stat_success = NO_RETRY_EXPECTED(
stat(listing->path_buffer().AsString(), &entry_info));
- if (stat_success == -1) {
+ if (stat_success == -1 || (S_IFMT & entry_info.st_mode) == 0) {
// Report a broken link as a link, even if follow_links is true.
+ // A symbolic link can potentially point to an anon_inode. For
+ // example, an epoll file descriptor will have a symbolic link whose
+ // content is the string anon_inode:[eventpoll]. In this case, the
+ // target doesn't belong to any regular file catogory.
return kListLink;
}
if (S_ISDIR(entry_info.st_mode)) {
@@ -180,16 +184,12 @@
return Next(listing);
}
return kListDirectory;
- } else if (S_ISREG(entry_info.st_mode) || S_ISCHR(entry_info.st_mode) ||
- S_ISBLK(entry_info.st_mode) ||
- S_ISFIFO(entry_info.st_mode) ||
- S_ISSOCK(entry_info.st_mode)) {
- return kListFile;
} else if (S_ISLNK(entry_info.st_mode)) {
return kListLink;
} else {
- FATAL1("Unexpected st_mode: %d\n", entry_info.st_mode);
- return kListError;
+ // Regular files, character devices, block devices, fifos, sockets and
+ // unknown types are all considered as files.
+ return kListFile;
}
}
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index cb13b24..23e4a2b 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -236,6 +236,7 @@
Uint8List? _buffer;
int _index = -1;
+ // Whether a HTTP request is being parsed (as opposed to a response).
final bool _requestParser;
int _state = _State.START;
int? _httpVersionIndex;
@@ -246,8 +247,8 @@
final List<int> _uriOrReasonPhrase = [];
final List<int> _headerField = [];
final List<int> _headerValue = [];
- // The limit for method, uriOrReasonPhrase, header field and value
- int _headerSizeLimit = 8 * 1024;
+ static const _headerTotalSizeLimit = 1024 * 1024;
+ int _headersReceivedSize = 0;
int _httpVersion = _HttpVersion.UNDETERMINED;
int _transferLength = -1;
@@ -946,6 +947,7 @@
_messageType = _MessageType.UNDETERMINED;
_headerField.clear();
_headerValue.clear();
+ _headersReceivedSize = 0;
_method.clear();
_uriOrReasonPhrase.clear();
@@ -977,8 +979,7 @@
}
static bool _isValueChar(int byte) {
- return (byte > 31 && byte < 128) ||
- (byte == _CharCode.HT);
+ return (byte > 31 && byte < 128) || (byte == _CharCode.HT);
}
static List<String> _tokenizeFieldValue(String headerValue) {
@@ -1036,7 +1037,8 @@
}
void _addWithValidation(List<int> list, int byte) {
- if (list.length < _headerSizeLimit) {
+ _headersReceivedSize++;
+ if (_headersReceivedSize < _headerTotalSizeLimit) {
list.add(byte);
} else {
_reportSizeLimitError();
@@ -1074,7 +1076,8 @@
throw UnsupportedError("Unexpected state: $_state");
break;
}
- throw HttpException("$method exceeds the $_headerSizeLimit size limit");
+ throw HttpException(
+ "$method exceeds the $_headerTotalSizeLimit size limit");
}
_HttpIncoming _createIncoming(int transferLength) {
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
index d9709b9..1f585c1 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/collection_patch.dart
@@ -307,9 +307,9 @@
// Used for DDC const sets.
class _ImmutableSet<E> extends _HashSet<E> {
- _ImmutableSet.from(JSArray entries) {
+ _ImmutableSet.from(JSArray<E> entries) {
var map = _map;
- for (Object key in entries) {
+ for (var key in entries) {
if (key == null) {
// Convert undefined to null, if needed.
JS('', '# = null', key);
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 0d5160f..dea69af 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -665,7 +665,7 @@
set effect(AnimationEffectReadOnly? value) native;
Future<Animation> get finished =>
- promiseToFuture<Animation>(JS("", "#.finished", this));
+ promiseToFuture<Animation>(JS("creates:Animation;", "#.finished", this));
String? get id native;
@@ -678,7 +678,7 @@
set playbackRate(num? value) native;
Future<Animation> get ready =>
- promiseToFuture<Animation>(JS("", "#.ready", this));
+ promiseToFuture<Animation>(JS("creates:Animation;", "#.ready", this));
num? get startTime native;
@@ -1354,13 +1354,18 @@
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture<BackgroundFetchRegistration>(
- JS("", "#.fetch(#, #, #)", this, id, requests, options_dict));
+ return promiseToFuture<BackgroundFetchRegistration>(JS(
+ "creates:BackgroundFetchRegistration;",
+ "#.fetch(#, #, #)",
+ this,
+ id,
+ requests,
+ options_dict));
}
Future<BackgroundFetchRegistration> get(String id) =>
promiseToFuture<BackgroundFetchRegistration>(
- JS("", "#.get(#)", this, id));
+ JS("creates:BackgroundFetchRegistration;", "#.get(#)", this, id));
Future<List<dynamic>> getIds() =>
promiseToFuture<List<dynamic>>(JS("", "#.getIds()", this));
@@ -1676,10 +1681,11 @@
Future arrayBuffer() => promiseToFuture(JS("", "#.arrayBuffer()", this));
- Future<Blob> blob() => promiseToFuture<Blob>(JS("", "#.blob()", this));
+ Future<Blob> blob() =>
+ promiseToFuture<Blob>(JS("creates:Blob;", "#.blob()", this));
Future<FormData> formData() =>
- promiseToFuture<FormData>(JS("", "#.formData()", this));
+ promiseToFuture<FormData>(JS("creates:FormData;", "#.formData()", this));
Future json() => promiseToFuture(JS("", "#.json()", this));
@@ -2014,17 +2020,17 @@
Future keys() => promiseToFuture(JS("", "#.keys()", this));
- Future match(/*RequestInfo*/ request, [Map? options]) {
+ Future<_Response> match(/*RequestInfo*/ request, [Map? options]) {
var options_dict = null;
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture(
- JS("", "#.match(#, #)", this, request, options_dict));
+ return promiseToFuture<_Response>(
+ JS("creates:_Response;", "#.match(#, #)", this, request, options_dict));
}
- Future open(String cacheName) =>
- promiseToFuture(JS("", "#.open(#)", this, cacheName));
+ Future<_Cache> open(String cacheName) => promiseToFuture<_Cache>(
+ JS("creates:_Cache;", "#.open(#)", this, cacheName));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -3065,8 +3071,8 @@
JS("", "#.matchAll(#)", this, options_dict));
}
- Future<WindowClient> openWindow(String url) =>
- promiseToFuture<WindowClient>(JS("", "#.openWindow(#)", this, url));
+ Future<WindowClient> openWindow(String url) => promiseToFuture<WindowClient>(
+ JS("creates:WindowClient;", "#.openWindow(#)", this, url));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -3229,12 +3235,12 @@
throw new UnsupportedError("Not supported");
}
- Future getAll([Map? options]) {
+ Future<Map<String, dynamic>?> getAll([Map? options]) {
var options_dict = null;
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture(JS("", "#.getAll(#)", this, options_dict));
+ return promiseToFutureAsMap(JS("", "#.getAll(#)", this, options_dict));
}
Future set(String name, String value, [Map? options]) {
@@ -3313,20 +3319,22 @@
throw new UnsupportedError("Not supported");
}
- Future create([Map? options]) {
+ Future<Credential> create([Map? options]) {
var options_dict = null;
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture(JS("", "#.create(#)", this, options_dict));
+ return promiseToFuture<Credential>(
+ JS("creates:Credential;", "#.create(#)", this, options_dict));
}
- Future get([Map? options]) {
+ Future<Credential> get([Map? options]) {
var options_dict = null;
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture(JS("", "#.get(#)", this, options_dict));
+ return promiseToFuture<Credential>(
+ JS("creates:Credential;", "#.get(#)", this, options_dict));
}
Future preventSilentAccess() =>
@@ -3335,8 +3343,9 @@
Future requireUserMediation() =>
promiseToFuture(JS("", "#.requireUserMediation()", this));
- Future store(Credential credential) =>
- promiseToFuture(JS("", "#.store(#)", this, credential));
+ Future<Credential> store(Credential credential) =>
+ promiseToFuture<Credential>(
+ JS("creates:Credential;", "#.store(#)", this, credential));
}
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -16488,7 +16497,7 @@
set featureSettings(String? value) native;
Future<FontFace> get loaded =>
- promiseToFuture<FontFace>(JS("", "#.loaded", this));
+ promiseToFuture<FontFace>(JS("creates:FontFace;", "#.loaded", this));
String? get status native;
@@ -16513,7 +16522,7 @@
set weight(String? value) native;
Future<FontFace> load() =>
- promiseToFuture<FontFace>(JS("", "#.load()", this));
+ promiseToFuture<FontFace>(JS("creates:FontFace;", "#.load()", this));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -18864,13 +18873,13 @@
Future<PhotoCapabilities> getPhotoCapabilities() =>
promiseToFuture<PhotoCapabilities>(
- JS("", "#.getPhotoCapabilities()", this));
+ JS("creates:PhotoCapabilities;", "#.getPhotoCapabilities()", this));
Future<Map<String, dynamic>?> getPhotoSettings() =>
promiseToFutureAsMap(JS("", "#.getPhotoSettings()", this));
- Future<ImageBitmap> grabFrame() =>
- promiseToFuture<ImageBitmap>(JS("", "#.grabFrame()", this));
+ Future<ImageBitmap> grabFrame() => promiseToFuture<ImageBitmap>(
+ JS("creates:ImageBitmap;", "#.grabFrame()", this));
Future setOptions(Map photoSettings) {
var photoSettings_dict = convertDartToNative_Dictionary(photoSettings);
@@ -18883,7 +18892,7 @@
photoSettings_dict = convertDartToNative_Dictionary(photoSettings);
}
return promiseToFuture<Blob>(
- JS("", "#.takePhoto(#)", this, photoSettings_dict));
+ JS("creates:Blob;", "#.takePhoto(#)", this, photoSettings_dict));
}
}
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
@@ -20468,14 +20477,20 @@
Future<MediaCapabilitiesInfo> decodingInfo(Map configuration) {
var configuration_dict = convertDartToNative_Dictionary(configuration);
- return promiseToFuture<MediaCapabilitiesInfo>(
- JS("", "#.decodingInfo(#)", this, configuration_dict));
+ return promiseToFuture<MediaCapabilitiesInfo>(JS(
+ "creates:MediaCapabilitiesInfo;",
+ "#.decodingInfo(#)",
+ this,
+ configuration_dict));
}
Future<MediaCapabilitiesInfo> encodingInfo(Map configuration) {
var configuration_dict = convertDartToNative_Dictionary(configuration);
- return promiseToFuture<MediaCapabilitiesInfo>(
- JS("", "#.encodingInfo(#)", this, configuration_dict));
+ return promiseToFuture<MediaCapabilitiesInfo>(JS(
+ "creates:MediaCapabilitiesInfo;",
+ "#.encodingInfo(#)",
+ this,
+ configuration_dict));
}
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -20540,8 +20555,8 @@
if (constraints != null) {
constraints_dict = convertDartToNative_Dictionary(constraints);
}
- return promiseToFuture<MediaStream>(
- JS("", "#.getUserMedia(#)", this, constraints_dict));
+ return promiseToFuture<MediaStream>(JS(
+ "creates:MediaStream;", "#.getUserMedia(#)", this, constraints_dict));
}
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -20848,8 +20863,8 @@
String? get keySystem native;
- Future createMediaKeys() =>
- promiseToFuture(JS("", "#.createMediaKeys()", this));
+ Future<MediaKeys> createMediaKeys() => promiseToFuture<MediaKeys>(
+ JS("creates:MediaKeys;", "#.createMediaKeys()", this));
Map getConfiguration() {
return convertNativeToDart_Dictionary(_getConfiguration_1())!;
@@ -20872,8 +20887,8 @@
@JSName('createSession')
MediaKeySession _createSession([String? sessionType]) native;
- Future getStatusForPolicy(MediaKeysPolicy policy) =>
- promiseToFuture(JS("", "#.getStatusForPolicy(#)", this, policy));
+ Future<String> getStatusForPolicy(MediaKeysPolicy policy) =>
+ promiseToFuture<String>(JS("", "#.getStatusForPolicy(#)", this, policy));
Future setServerCertificate(/*BufferSource*/ serverCertificate) =>
promiseToFuture(
@@ -21339,12 +21354,12 @@
String? get readyState native;
- Future applyConstraints([Map? constraints]) {
+ Future<Map<String, dynamic>?> applyConstraints([Map? constraints]) {
var constraints_dict = null;
if (constraints != null) {
constraints_dict = convertDartToNative_Dictionary(constraints);
}
- return promiseToFuture(
+ return promiseToFutureAsMap(
JS("", "#.applyConstraints(#)", this, constraints_dict));
}
@@ -22741,10 +22756,11 @@
List<Gamepad?> _getGamepads() native;
Future<RelatedApplication> getInstalledRelatedApps() =>
- promiseToFuture<RelatedApplication>(
- JS("", "#.getInstalledRelatedApps()", this));
+ promiseToFuture<RelatedApplication>(JS(
+ "creates:RelatedApplication;", "#.getInstalledRelatedApps()", this));
- Future getVRDisplays() => promiseToFuture(JS("", "#.getVRDisplays()", this));
+ Future<List<VRDisplay>> getVRDisplays() => promiseToFuture<List<VRDisplay>>(
+ JS("creates:VRDisplay;", "#.getVRDisplays()", this));
@Unstable()
void registerProtocolHandler(String scheme, String url, String title) native;
@@ -22774,10 +22790,14 @@
JS("", "#.requestMIDIAccess(#)", this, options_dict));
}
- Future requestMediaKeySystemAccess(
+ Future<MediaKeySystemAccess> requestMediaKeySystemAccess(
String keySystem, List<Map> supportedConfigurations) =>
- promiseToFuture(JS("", "#.requestMediaKeySystemAccess(#, #)", this,
- keySystem, supportedConfigurations));
+ promiseToFuture<MediaKeySystemAccess>(JS(
+ "creates:MediaKeySystemAccess;",
+ "#.requestMediaKeySystemAccess(#, #)",
+ this,
+ keySystem,
+ supportedConfigurations));
bool sendBeacon(String url, Object? data) native;
@@ -23981,7 +24001,7 @@
options_dict = convertDartToNative_Dictionary(options);
}
return promiseToFuture<Blob>(
- JS("", "#.convertToBlob(#)", this, options_dict));
+ JS("creates:Blob;", "#.convertToBlob(#)", this, options_dict));
}
Object? getContext(String contextType, [Map? attributes]) {
@@ -24990,8 +25010,8 @@
Future<bool> canMakePayment() =>
promiseToFuture<bool>(JS("", "#.canMakePayment()", this));
- Future<PaymentResponse> show() =>
- promiseToFuture<PaymentResponse>(JS("", "#.show()", this));
+ Future<PaymentResponse> show() => promiseToFuture<PaymentResponse>(
+ JS("creates:PaymentResponse;", "#.show()", this));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -25029,8 +25049,8 @@
Object? get total native;
- Future<WindowClient> openWindow(String url) =>
- promiseToFuture<WindowClient>(JS("", "#.openWindow(#)", this, url));
+ Future<WindowClient> openWindow(String url) => promiseToFuture<WindowClient>(
+ JS("creates:WindowClient;", "#.openWindow(#)", this, url));
void respondWith(Future response) native;
}
@@ -25463,23 +25483,23 @@
Future<PermissionStatus> query(Map permission) {
var permission_dict = convertDartToNative_Dictionary(permission);
return promiseToFuture<PermissionStatus>(
- JS("", "#.query(#)", this, permission_dict));
+ JS("creates:PermissionStatus;", "#.query(#)", this, permission_dict));
}
Future<PermissionStatus> request(Map permissions) {
var permissions_dict = convertDartToNative_Dictionary(permissions);
- return promiseToFuture<PermissionStatus>(
- JS("", "#.request(#)", this, permissions_dict));
+ return promiseToFuture<PermissionStatus>(JS(
+ "creates:PermissionStatus;", "#.request(#)", this, permissions_dict));
}
Future<PermissionStatus> requestAll(List<Map> permissions) =>
- promiseToFuture<PermissionStatus>(
- JS("", "#.requestAll(#)", this, permissions));
+ promiseToFuture<PermissionStatus>(JS(
+ "creates:PermissionStatus;", "#.requestAll(#)", this, permissions));
Future<PermissionStatus> revoke(Map permission) {
var permission_dict = convertDartToNative_Dictionary(permission);
return promiseToFuture<PermissionStatus>(
- JS("", "#.revoke(#)", this, permission_dict));
+ JS("creates:PermissionStatus;", "#.revoke(#)", this, permission_dict));
}
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -25898,7 +25918,7 @@
Future<PresentationConnectionList> get connectionList =>
promiseToFuture<PresentationConnectionList>(
- JS("", "#.connectionList", this));
+ JS("creates:PresentationConnectionList;", "#.connectionList", this));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -25928,14 +25948,15 @@
Future<PresentationAvailability> getAvailability() =>
promiseToFuture<PresentationAvailability>(
- JS("", "#.getAvailability()", this));
+ JS("creates:PresentationAvailability;", "#.getAvailability()", this));
Future<PresentationConnection> reconnect(String id) =>
promiseToFuture<PresentationConnection>(
- JS("", "#.reconnect(#)", this, id));
+ JS("creates:PresentationConnection;", "#.reconnect(#)", this, id));
Future<PresentationConnection> start() =>
- promiseToFuture<PresentationConnection>(JS("", "#.start()", this));
+ promiseToFuture<PresentationConnection>(
+ JS("creates:PresentationConnection;", "#.start()", this));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -26102,7 +26123,8 @@
static List<String>? get supportedContentEncodings native;
Future<PushSubscription> getSubscription() =>
- promiseToFuture<PushSubscription>(JS("", "#.getSubscription()", this));
+ promiseToFuture<PushSubscription>(
+ JS("creates:PushSubscription;", "#.getSubscription()", this));
Future permissionState([Map? options]) {
var options_dict = null;
@@ -26118,7 +26140,7 @@
options_dict = convertDartToNative_Dictionary(options);
}
return promiseToFuture<PushSubscription>(
- JS("", "#.subscribe(#)", this, options_dict));
+ JS("creates:PushSubscription;", "#.subscribe(#)", this, options_dict));
}
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
@@ -26936,8 +26958,11 @@
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture<RtcSessionDescription>(
- JS("", "#.createAnswer(#)", this, options_dict));
+ return promiseToFuture<RtcSessionDescription>(JS(
+ "creates:RtcSessionDescription;",
+ "#.createAnswer(#)",
+ this,
+ options_dict));
}
@JSName('createDTMFSender')
@@ -26961,8 +26986,11 @@
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture<RtcSessionDescription>(
- JS("", "#.createOffer(#)", this, options_dict));
+ return promiseToFuture<RtcSessionDescription>(JS(
+ "creates:RtcSessionDescription;",
+ "#.createOffer(#)",
+ this,
+ options_dict));
}
List<MediaStream> getLocalStreams() native;
@@ -26973,8 +27001,8 @@
List<RtcRtpSender> getSenders() native;
- Future<RtcStatsReport> getStats() =>
- promiseToFuture<RtcStatsReport>(JS("", "#.getStats()", this));
+ Future<RtcStatsReport> getStats() => promiseToFuture<RtcStatsReport>(
+ JS("creates:RTCStatsReport;", "#.getStats()", this));
void removeStream(MediaStream? stream) native;
@@ -27762,11 +27790,15 @@
ServiceWorker? get controller native;
Future<ServiceWorkerRegistration> get ready =>
- promiseToFuture<ServiceWorkerRegistration>(JS("", "#.ready", this));
+ promiseToFuture<ServiceWorkerRegistration>(
+ JS("creates:ServiceWorkerRegistration;", "#.ready", this));
Future<ServiceWorkerRegistration> getRegistration([String? documentURL]) =>
- promiseToFuture<ServiceWorkerRegistration>(
- JS("", "#.getRegistration(#)", this, documentURL));
+ promiseToFuture<ServiceWorkerRegistration>(JS(
+ "creates:ServiceWorkerRegistration;",
+ "#.getRegistration(#)",
+ this,
+ documentURL));
Future<List<dynamic>> getRegistrations() =>
promiseToFuture<List<dynamic>>(JS("", "#.getRegistrations()", this));
@@ -27776,8 +27808,12 @@
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture<ServiceWorkerRegistration>(
- JS("", "#.register(#, #)", this, url, options_dict));
+ return promiseToFuture<ServiceWorkerRegistration>(JS(
+ "creates:ServiceWorkerRegistration;",
+ "#.register(#, #)",
+ this,
+ url,
+ options_dict));
}
Stream<MessageEvent> get onMessage => messageEvent.forTarget(this);
@@ -31202,13 +31238,14 @@
Future end() => promiseToFuture(JS("", "#.end()", this));
- Future requestFrameOfReference(String type, [Map? options]) {
+ Future<VRFrameOfReference> requestFrameOfReference(String type,
+ [Map? options]) {
var options_dict = null;
if (options != null) {
options_dict = convertDartToNative_Dictionary(options);
}
- return promiseToFuture(
- JS("", "#.requestFrameOfReference(#, #)", this, type, options_dict));
+ return promiseToFuture<VRFrameOfReference>(JS("creates:VRFrameOfReference;",
+ "#.requestFrameOfReference(#, #)", this, type, options_dict));
}
Stream<Event> get onBlur => blurEvent.forTarget(this);
@@ -32849,12 +32886,13 @@
*/
bool confirm([String? message]) native;
- Future fetch(/*RequestInfo*/ input, [Map? init]) {
+ Future<_Response> fetch(/*RequestInfo*/ input, [Map? init]) {
var init_dict = null;
if (init != null) {
init_dict = convertDartToNative_Dictionary(init);
}
- return promiseToFuture(JS("", "#.fetch(#, #)", this, input, init_dict));
+ return promiseToFuture<_Response>(
+ JS("creates:_Response;", "#.fetch(#, #)", this, input, init_dict));
}
/**
@@ -33759,11 +33797,11 @@
String? get visibilityState native;
- Future<WindowClient> focus() =>
- promiseToFuture<WindowClient>(JS("", "#.focus()", this));
+ Future<WindowClient> focus() => promiseToFuture<WindowClient>(
+ JS("creates:WindowClient;", "#.focus()", this));
- Future<WindowClient> navigate(String url) =>
- promiseToFuture<WindowClient>(JS("", "#.navigate(#)", this, url));
+ Future<WindowClient> navigate(String url) => promiseToFuture<WindowClient>(
+ JS("creates:WindowClient;", "#.navigate(#)", this, url));
}
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
@@ -33918,12 +33956,13 @@
WorkerGlobalScope get self native;
- Future fetch(/*RequestInfo*/ input, [Map? init]) {
+ Future<_Response> fetch(/*RequestInfo*/ input, [Map? init]) {
var init_dict = null;
if (init != null) {
init_dict = convertDartToNative_Dictionary(init);
}
- return promiseToFuture(JS("", "#.fetch(#, #)", this, input, init_dict));
+ return promiseToFuture<_Response>(
+ JS("creates:_Response;", "#.fetch(#, #)", this, input, init_dict));
}
void importScripts(String urls) native;
@@ -34334,8 +34373,8 @@
throw new UnsupportedError("Not supported");
}
- Future<BudgetState> getBudget() =>
- promiseToFuture<BudgetState>(JS("", "#.getBudget()", this));
+ Future<BudgetState> getBudget() => promiseToFuture<BudgetState>(
+ JS("creates:BudgetState;", "#.getBudget()", this));
Future<double> getCost(String operation) =>
promiseToFuture<double>(JS("", "#.getCost(#)", this, operation));
@@ -34375,8 +34414,8 @@
throw new UnsupportedError("Not supported");
}
- Future<DataTransfer> read() =>
- promiseToFuture<DataTransfer>(JS("", "#.read()", this));
+ Future<DataTransfer> read() => promiseToFuture<DataTransfer>(
+ JS("creates:DataTransfer;", "#.read()", this));
Future<String> readText() =>
promiseToFuture<String>(JS("", "#.readText()", this));
diff --git a/sdk/lib/js/_js_annotations.dart b/sdk/lib/js/_js_annotations.dart
index b28e7b7..c188214 100644
--- a/sdk/lib/js/_js_annotations.dart
+++ b/sdk/lib/js/_js_annotations.dart
@@ -7,6 +7,8 @@
// https://github.com/dart-lang/sdk/blob/master/pkg/js/lib/js.dart
library _js_annotations;
+export 'dart:js' show allowInterop, allowInteropCaptureThis;
+
class JS {
final String? name;
const JS([this.name]);
diff --git a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
index da12ab3..a12d2fe 100644
--- a/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
+++ b/sdk/lib/web_audio/dart2js/web_audio_dart2js.dart
@@ -682,8 +682,13 @@
Future<AudioBuffer> decodeAudioData(ByteBuffer audioData,
[DecodeSuccessCallback? successCallback,
DecodeErrorCallback? errorCallback]) =>
- promiseToFuture<AudioBuffer>(JS("", "#.decodeAudioData(#, #, #)", this,
- audioData, successCallback, errorCallback));
+ promiseToFuture<AudioBuffer>(JS(
+ "creates:AudioBuffer;",
+ "#.decodeAudioData(#, #, #)",
+ this,
+ audioData,
+ successCallback,
+ errorCallback));
Future resume() => promiseToFuture(JS("", "#.resume()", this));
}
@@ -1075,8 +1080,8 @@
int? get length native;
- Future<AudioBuffer> startRendering() =>
- promiseToFuture<AudioBuffer>(JS("", "#.startRendering()", this));
+ Future<AudioBuffer> startRendering() => promiseToFuture<AudioBuffer>(
+ JS("creates:AudioBuffer;", "#.startRendering()", this));
@JSName('suspend')
Future suspendFor(num suspendTime) =>
diff --git a/tests/language/if_null/assignment_behavior_test.dart b/tests/language/if_null/assignment_behavior_test.dart
index c9c4fb8..b17afd1 100644
--- a/tests/language/if_null/assignment_behavior_test.dart
+++ b/tests/language/if_null/assignment_behavior_test.dart
@@ -177,8 +177,6 @@
//^
// [analyzer] COMPILE_TIME_ERROR.ASSIGNMENT_TO_TYPE
// [cfe] Can't assign to a type literal.
-// ^^^^
-// [analyzer] STATIC_WARNING.DEAD_NULL_AWARE_EXPRESSION
h ??= null;
//^
// [analyzer] COMPILE_TIME_ERROR.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT
diff --git a/tests/standalone/io/directory_list_sync_test.dart b/tests/standalone/io/directory_list_sync_test.dart
index 2c99a67..0df5081 100644
--- a/tests/standalone/io/directory_list_sync_test.dart
+++ b/tests/standalone/io/directory_list_sync_test.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-void main() {
+void testList() {
File script = new File.fromUri(Platform.script);
// tests/standalone/io/../..
Directory startingDir = script.parent.parent.parent;
@@ -13,3 +13,19 @@
startingDir.listSync(recursive: true, followLinks: false);
print("Found: ${each.length} entities");
}
+
+// The test is disabled by default, because it requires permission to run.
+// e.g. sudo dart directory_list_sync_test.dart
+void testAnonymousNodeOnLinux() {
+ // If a symbolic link points to an anon_inode, which doesn't have a regular
+ // file type like an epoll file descriptor, list() will return a link.
+ if (!Platform.isLinux) {
+ return;
+ }
+ Directory('/proc/').listSync(recursive: true);
+}
+
+void main() {
+ testList();
+ //testAnonymousNodeOnLinux();
+}
diff --git a/tests/standalone/io/http_big_header_test.dart b/tests/standalone/io/http_big_header_test.dart
new file mode 100644
index 0000000..e5d25fb
--- /dev/null
+++ b/tests/standalone/io/http_big_header_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+
+// This test checks whether a big header is accepted.
+
+Future<void> testClient(int limit) async {
+ final server = await HttpServer.bind('127.0.0.1', 0);
+ final str = 'a' * (1000);
+ int size = 0;
+ server.listen((request) async {
+ for (int i = 0; i < 10000; i++) {
+ request.response.headers.add('dummy', str);
+ size += 1000;
+ if (size > limit) {
+ break;
+ }
+ }
+ await request.response.close();
+ server.close();
+ });
+
+ final client = HttpClient();
+ final request = await client.get('127.0.0.1', server.port, '/');
+ await request.close();
+}
+
+Future<void> client() async {
+ int i = 64;
+ try {
+ for (; i < 101 * 1024 * 1024; i *= 100) {
+ await testClient(i);
+ }
+ } on HttpException catch (e) {
+ Expect.isTrue(e.toString().contains('size limit'));
+ Expect.isTrue(i > 1024 * 1024);
+ return;
+ }
+ Expect.fail('An exception is expected');
+}
+
+Future<void> testServer(int limit, int port) async {
+ final str = 'a' * (1000);
+ final client = HttpClient();
+ final request = await client.get('127.0.0.1', port, '/');
+ for (int size = 0; size < limit; size += 1000) {
+ request.headers.add('dummy', str);
+ }
+ await request.close();
+}
+
+Future<void> server() async {
+ final server = await HttpServer.bind('127.0.0.1', 0);
+ int i = 64;
+ try {
+ server.listen((request) async {
+ await request.response.close();
+ });
+ for (; i < 101 * 1024 * 1024; i *= 100) {
+ print(i);
+ await testServer(i, server.port);
+ }
+ } on SocketException catch (_) {
+ // Server will close on error and writing to the socket will be blocked due
+ // to broken pipe.
+ Expect.isTrue(i > 1024 * 1024);
+ server.close();
+ return;
+ }
+ server.close();
+ Expect.fail('An exception is expected');
+}
+
+Future<void> main() async {
+ await client();
+ await server();
+}
diff --git a/tests/standalone_2/io/directory_list_sync_test.dart b/tests/standalone_2/io/directory_list_sync_test.dart
index 2c99a67..0df5081 100644
--- a/tests/standalone_2/io/directory_list_sync_test.dart
+++ b/tests/standalone_2/io/directory_list_sync_test.dart
@@ -4,7 +4,7 @@
import 'dart:io';
-void main() {
+void testList() {
File script = new File.fromUri(Platform.script);
// tests/standalone/io/../..
Directory startingDir = script.parent.parent.parent;
@@ -13,3 +13,19 @@
startingDir.listSync(recursive: true, followLinks: false);
print("Found: ${each.length} entities");
}
+
+// The test is disabled by default, because it requires permission to run.
+// e.g. sudo dart directory_list_sync_test.dart
+void testAnonymousNodeOnLinux() {
+ // If a symbolic link points to an anon_inode, which doesn't have a regular
+ // file type like an epoll file descriptor, list() will return a link.
+ if (!Platform.isLinux) {
+ return;
+ }
+ Directory('/proc/').listSync(recursive: true);
+}
+
+void main() {
+ testList();
+ //testAnonymousNodeOnLinux();
+}
diff --git a/tests/standalone_2/io/http_big_header_test.dart b/tests/standalone_2/io/http_big_header_test.dart
new file mode 100644
index 0000000..e5d25fb
--- /dev/null
+++ b/tests/standalone_2/io/http_big_header_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:expect/expect.dart';
+
+// This test checks whether a big header is accepted.
+
+Future<void> testClient(int limit) async {
+ final server = await HttpServer.bind('127.0.0.1', 0);
+ final str = 'a' * (1000);
+ int size = 0;
+ server.listen((request) async {
+ for (int i = 0; i < 10000; i++) {
+ request.response.headers.add('dummy', str);
+ size += 1000;
+ if (size > limit) {
+ break;
+ }
+ }
+ await request.response.close();
+ server.close();
+ });
+
+ final client = HttpClient();
+ final request = await client.get('127.0.0.1', server.port, '/');
+ await request.close();
+}
+
+Future<void> client() async {
+ int i = 64;
+ try {
+ for (; i < 101 * 1024 * 1024; i *= 100) {
+ await testClient(i);
+ }
+ } on HttpException catch (e) {
+ Expect.isTrue(e.toString().contains('size limit'));
+ Expect.isTrue(i > 1024 * 1024);
+ return;
+ }
+ Expect.fail('An exception is expected');
+}
+
+Future<void> testServer(int limit, int port) async {
+ final str = 'a' * (1000);
+ final client = HttpClient();
+ final request = await client.get('127.0.0.1', port, '/');
+ for (int size = 0; size < limit; size += 1000) {
+ request.headers.add('dummy', str);
+ }
+ await request.close();
+}
+
+Future<void> server() async {
+ final server = await HttpServer.bind('127.0.0.1', 0);
+ int i = 64;
+ try {
+ server.listen((request) async {
+ await request.response.close();
+ });
+ for (; i < 101 * 1024 * 1024; i *= 100) {
+ print(i);
+ await testServer(i, server.port);
+ }
+ } on SocketException catch (_) {
+ // Server will close on error and writing to the socket will be blocked due
+ // to broken pipe.
+ Expect.isTrue(i > 1024 * 1024);
+ server.close();
+ return;
+ }
+ server.close();
+ Expect.fail('An exception is expected');
+}
+
+Future<void> main() async {
+ await client();
+ await server();
+}
diff --git a/tools/VERSION b/tools/VERSION
index ef50155..295e955 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 10
PATCH 0
-PRERELEASE 84
+PRERELEASE 85
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py
index 0761fe6..a43b242 100644
--- a/tools/dom/scripts/systemhtml.py
+++ b/tools/dom/scripts/systemhtml.py
@@ -890,53 +890,64 @@
promise_attributes = monitored.Dict(
'systemhtml.promise_attr_type', {
"Animation.finished": {
- "type": "Animation"
+ "type": "Animation",
+ "creates": "Animation"
},
"Animation.ready": {
- "type": "Animation"
+ "type": "Animation",
+ "creates": "Animation"
},
"BeforeInstallPromptEvent.userChoice": {
"type": "dictionary"
},
"FontFace.loaded": {
- "type": "FontFace"
+ "type": "FontFace",
+ "creates": "FontFace"
},
"FontFaceSet.ready": {
- "type": "FontFaceSet"
+ "type": "FontFaceSet",
+ "creates": "FontFaceSet"
},
"MediaKeySession.closed": {
"type": "void"
},
"PresentationReceiver.connectionList": {
- "type": "PresentationConnectionList"
+ "type": "PresentationConnectionList",
+ "creates": "PresentationConnectionList"
},
"ServiceWorkerContainer.ready": {
- "type": "ServiceWorkerRegistration"
+ "type": "ServiceWorkerRegistration",
+ "creates": "ServiceWorkerRegistration"
},
})
promise_operations = monitored.Dict(
'systemhtml.promise_oper_type', {
"Clipboard.read": {
- "type": "DataTransfer"
+ "type": "DataTransfer",
+ "creates": "DataTransfer"
},
"Clipboard.readText": {
"type": "String"
},
"FontFace.load": {
- "type": "FontFace"
+ "type": "FontFace",
+ "creates": "FontFace"
},
"FontFaceSet.load": {
"type": "List<dynamic>"
},
"OffscreenCanvas.load": {
- "type": "Blob"
+ "type": "Blob",
+ "creates": "Blob"
},
"BackgroundFetchManager.fetch": {
- "type": "BackgroundFetchRegistration"
+ "type": "BackgroundFetchRegistration",
+ "creates": "BackgroundFetchRegistration"
},
"BackgroundFetchManager.get": {
- "type": "BackgroundFetchRegistration"
+ "type": "BackgroundFetchRegistration",
+ "creates": "BackgroundFetchRegistration"
},
"BackgroundFetchManager.getIds": {
"type": "List<dynamic>"
@@ -951,49 +962,60 @@
"type": "double"
},
"BudgetService.getBudget": {
- "type": "BudgetState"
+ "type": "BudgetState",
+ "creates": "BudgetState"
},
"BudgetService.reserve": {
"type": "bool"
},
"Body.blob": {
- "type": "Blob"
+ "type": "Blob",
+ "creates": "Blob"
},
"Body.formData": {
- "type": "FormData"
+ "type": "FormData",
+ "creates": "FormData"
},
"Body.text": {
"type": "String"
},
"ImageCapture.getPhotoCapabilities": {
- "type": "PhotoCapabilities"
+ "type": "PhotoCapabilities",
+ "creates": "PhotoCapabilities"
},
"ImageCapture.getPhotoSettings": {
"type": "dictionary"
},
"ImageCapture.takePhoto": {
- "type": "Blob"
+ "type": "Blob",
+ "creates": "Blob"
},
"ImageCapture.grabFrame": {
- "type": "ImageBitmap"
+ "type": "ImageBitmap",
+ "creates": "ImageBitmap"
},
"Navigator.getInstalledRelatedApps": {
- "type": "RelatedApplication"
+ "type": "RelatedApplication",
+ "creates": "RelatedApplication"
},
"OffscreenCanvas.convertToBlob": {
- "type": "Blob"
+ "type": "Blob",
+ "creates": "Blob"
},
"MediaCapabilities.decodingInfo": {
- "type": "MediaCapabilitiesInfo"
+ "type": "MediaCapabilitiesInfo",
+ "creates": "MediaCapabilitiesInfo"
},
"MediaCapabilities.encodingInfo": {
- "type": "MediaCapabilitiesInfo"
+ "type": "MediaCapabilitiesInfo",
+ "creates": "MediaCapabilitiesInfo"
},
"MediaDevices.enumerateDevices": {
"type": "List<dynamic>"
},
"MediaDevices.getUserMedia": {
- "type": "MediaStream"
+ "type": "MediaStream",
+ "creates": "MediaStream"
},
"ServiceWorkerRegistration.getNotifications": {
"type": "List<dynamic>"
@@ -1011,53 +1033,68 @@
"type": "bool"
},
"PaymentRequest.show": {
- "type": "PaymentResponse"
+ "type": "PaymentResponse",
+ "creates": "PaymentResponse"
},
"PaymentRequest.canMakePayment": {
"type": "bool"
},
"PaymentRequestEvent.openWindow": {
- "type": "WindowClient"
+ "type": "WindowClient",
+ "creates": "WindowClient"
},
"RTCPeerConnection.createOffer": {
- "type": "RtcSessionDescription"
+ "type": "RtcSessionDescription",
+ "creates": "RtcSessionDescription"
},
"RTCPeerConnection.createAnswer": {
- "type": "RtcSessionDescription"
+ "type": "RtcSessionDescription",
+ "creates": "RtcSessionDescription"
},
"RTCPeerConnection.getStats": {
"type": "RtcStatsReport",
- "maplike": "RTCStatsReport"
+ "maplike": "RTCStatsReport",
+ "creates": "RTCStatsReport"
},
"RTCPeerConnection.generateCertificate": {
- "type": "RtcCertificate"
+ "type": "RtcCertificate",
+ "creates": "RtcCertificate"
},
"Permissions.query": {
- "type": "PermissionStatus"
+ "type": "PermissionStatus",
+ "creates": "PermissionStatus"
},
"Permissions.request": {
- "type": "PermissionStatus"
+ "type": "PermissionStatus",
+ "creates": "PermissionStatus"
},
"Permissions.revoke": {
- "type": "PermissionStatus"
+ "type": "PermissionStatus",
+ "creates": "PermissionStatus"
},
"Permissions.requestAll": {
- "type": "PermissionStatus"
+ "type": "PermissionStatus",
+ "creates": "PermissionStatus"
},
"PresentationRequest.start": {
- "type": "PresentationConnection"
+ "type": "PresentationConnection",
+ "creates": "PresentationConnection"
},
"PresentationRequest.reconnect": {
- "type": "PresentationConnection"
+ "type": "PresentationConnection",
+ "creates": "PresentationConnection"
},
"PresentationRequest.getAvailability": {
- "type": "PresentationAvailability"
+ "type": "PresentationAvailability",
+ "creates": "PresentationAvailability"
},
"PushManager.subscribe": {
- "type": "PushSubscription"
+ "type": "PushSubscription",
+ "creates": "PushSubscription"
},
"PushManager.getSubscription": {
- "type": "PushSubscription"
+ "type": "PushSubscription",
+ "creates": "PushSubscription"
},
"PushSubscription.unsubscribe": {
"type": "bool"
@@ -1078,31 +1115,37 @@
"type": "List<dynamic>"
},
"Clients.openWindow": {
- "type": "WindowClient"
+ "type": "WindowClient",
+ "creates": "WindowClient"
},
"NavigationPreloadManager.getState": {
"type": "dictionary"
},
"ServiceWorkerContainer.register": {
- "type": "ServiceWorkerRegistration"
+ "type": "ServiceWorkerRegistration",
+ "creates": "ServiceWorkerRegistration"
},
"ServiceWorkerContainer.getRegistration": {
- "type": "ServiceWorkerRegistration"
+ "type": "ServiceWorkerRegistration",
+ "creates": "ServiceWorkerRegistration"
},
"ServiceWorkerContainer.getRegistrations": {
"type": "List<dynamic>"
},
"ServiceWorkerGlobalScope.fetch": {
- "type": "Response"
+ "type": "_Response",
+ "creates": "_Response"
},
"ServiceWorkerRegistration.unregister": {
"type": "bool"
},
"WindowClient.focus": {
- "type": "WindowClient"
+ "type": "WindowClient",
+ "creates": "WindowClient"
},
"WindowClient.navigate": {
- "type": "WindowClient"
+ "type": "WindowClient",
+ "creates": "WindowClient"
},
"BarcodeDetector.detect": {
"type": "List<dynamic>"
@@ -1114,10 +1157,71 @@
"type": "List<dynamic>"
},
"BaseAudioContext.decodeAudioData": {
- "type": "AudioBuffer"
+ "type": "AudioBuffer",
+ "creates": "AudioBuffer"
},
"OfflineAudioContext.startRendering": {
- "type": "AudioBuffer"
+ "type": "AudioBuffer",
+ "creates": "AudioBuffer"
+ },
+ "CacheStorage.match": {
+ "type": "_Response",
+ "creates": "_Response"
+ },
+ "CacheStorage.open": {
+ "type": "_Cache",
+ "creates": "_Cache"
+ },
+ "CookieStore.getAll": {
+ "type": "dictionary"
+ },
+ "CredentialsContainer.create": {
+ "type": "Credential",
+ "creates": "Credential"
+ },
+ "CredentialsContainer.get": {
+ "type": "Credential",
+ "creates": "Credential"
+ },
+ "CredentialsContainer.store": {
+ "type": "Credential",
+ "creates": "Credential"
+ },
+ "FetchEvent.preloadResponse": {
+ "type": "_Response",
+ "creates": "_Response"
+ },
+ "MediaKeys.getStatusForPolicy": {
+ # Actual return value is MediaKeyStatus, which is an IDL enum of
+ # strings.
+ "type": "String"
+ },
+ "MediaKeySystemAccess.createMediaKeys": {
+ "type": "MediaKeys",
+ "creates": "MediaKeys"
+ },
+ "MediaStreamTrack.applyConstraints": {
+ "type": "dictionary"
+ },
+ "Navigator.getVRDisplays": {
+ "type": "List<VRDisplay>",
+ "creates": "VRDisplay"
+ },
+ "Navigator.requestMediaKeySystemAccess": {
+ "type": "MediaKeySystemAccess",
+ "creates": "MediaKeySystemAccess"
+ },
+ "VRSession.requestFrameOfReference": {
+ "type": "VRFrameOfReference",
+ "creates": "VRFrameOfReference"
+ },
+ "Window.fetch": {
+ "type": "_Response",
+ "creates": "_Response"
+ },
+ "WorkerGlobalScope.fetch": {
+ "type": "_Response",
+ "creates": "_Response"
},
})
@@ -1492,6 +1596,7 @@
promiseFound = _GetPromiseAttributeType(lookupOp)
promiseType = 'Future'
promiseCall = 'promiseToFuture'
+ type_description = ''
if promiseFound is not (None):
if 'maplike' in promiseFound:
promiseCall = 'promiseToFuture<dynamic>'
@@ -1510,10 +1615,14 @@
promiseCall = 'promiseToFuture<%s>' % paramType
promiseType = 'Future<%s>' % paramType
+ if 'creates' in promiseFound:
+ createsType = promiseFound['creates']
+ type_description = 'creates:%s;' % createsType
+
if attribute.type.nullable:
promiseType += '?'
- template = '\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("", "#.$NAME", this));\n'
+ template = '\n $RENAME$(ANNOTATIONS)$TYPE get $NAME => $PROMISE_CALL(JS("$TYPE_DESC", "#.$NAME", this));\n'
self._members_emitter.Emit(
template,
@@ -1521,7 +1630,8 @@
ANNOTATIONS=metadata,
TYPE=promiseType,
PROMISE_CALL=promiseCall,
- NAME=html_name)
+ TYPE_DESC=type_description,
+ NAME=html_name,)
else:
# Need to use a getter for list.length properties so we can
# add a setter which throws an exception, satisfying List
@@ -1733,11 +1843,12 @@
return resultType
def _zeroArgs(self, argsNames):
- return 'JS("", "#.$JSNAME()", this)'
+ return 'JS("$TYPE_DESC", "#.$JSNAME()", this)'
def _manyArgs(self, numberArgs, argsNames):
argsPound = "#" if numberArgs == 1 else ("#, " * numberArgs)[:-2]
- return ' JS("", "#.$JSNAME(%s)", this, %s)' % (argsPound, argsNames)
+ template = ' JS("$TYPE_DESC", "#.$JSNAME(%s)", this, %s)'
+ return template % (argsPound, argsNames)
""" If argument conversionsMapToDictionary is a list first entry is argument
name and second entry signals if argument is optional (True). """
@@ -1812,6 +1923,7 @@
promiseFound = _GetPromiseOperationType(lookupOp)
promiseType = 'Future'
promiseCall = 'promiseToFuture'
+ type_description = ''
if promiseFound is not (None):
paramType = promiseFound['type']
if 'maplike' in promiseFound:
@@ -1834,6 +1946,10 @@
promiseCall = 'promiseToFuture<%s>' % paramType
promiseType = 'Future<%s>' % paramType
+ if 'creates' in promiseFound:
+ createsType = promiseFound['creates']
+ type_description = 'creates:%s;' % createsType
+
argsNames = info.ParametersAsArgumentList()
dictionary_argument = info.dictionaryArgumentName()
codeTemplate = self._promiseToFutureCode(argsNames,
@@ -1851,6 +1967,7 @@
TYPE=promiseType,
PROMISE_CALL=promiseCall,
NAME=html_name,
+ TYPE_DESC=type_description,
JSNAME=info.declared_name,
PARAMS=info.ParametersAsDeclaration(self._NarrowInputType,
force_optional))