Version 2.17.0-171.0.dev
Merge commit '62628e4c0084ee4dbf4203e7317055e20bba3bf5' into 'dev'
diff --git a/DEPS b/DEPS
index f9788c5..90d3669 100644
--- a/DEPS
+++ b/DEPS
@@ -90,7 +90,7 @@
"chrome_rev" : "19997",
"cli_util_rev" : "b0adbba89442b2ea6fef39c7a82fe79cb31e1168",
"clock_rev" : "5631a0612f4ac7e1b32f7c9a00fc7c00a41615e1",
- "collection_rev": "a4c941ab94044d118b2086a3f261c30377604127",
+ "collection_rev": "e1407da23b9f17400b3a905aafe2b8fa10db3d86",
"convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
"crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
"csslib_rev": "518761b166974537f334dbf264e7f56cb157a96a",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
index 838e6a2..918c2a7 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
@@ -57,6 +57,11 @@
references = findLocalElementReferences(root, element);
}
}
+ } else if (element is PrefixElement) {
+ var root = node.thisOrAncestorOfType<CompilationUnit>();
+ if (root != null) {
+ references = findPrefixElementReferences(root, element);
+ }
}
if (references == null) {
return;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
new file mode 100644
index 0000000..08c09db
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryLate extends CorrectionProducer {
+ @override
+ bool get canBeAppliedInBulk => true;
+
+ @override
+ bool get canBeAppliedToFile => true;
+
+ @override
+ FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+ @override
+ FixKind get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_LATE_MULTI;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ final declaration = node;
+ if (declaration is! VariableDeclaration) {
+ return;
+ }
+ final declarationList = declaration.parent;
+ if (declarationList is! VariableDeclarationList) {
+ return;
+ }
+
+ if (declarationList.variables.any((v) => v.initializer == null)) {
+ // At least one variable declared in the same list does _not_ have an
+ // initializer; removing `late` may make such a variable declaration
+ // invalid.
+ return;
+ }
+
+ final lateToken = declarationList.lateKeyword;
+ if (lateToken == null) {
+ return;
+ }
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addDeletion(range.startStart(lateToken, lateToken.next!));
+ });
+ }
+
+ /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+ static RemoveUnnecessaryLate newInstance() => RemoveUnnecessaryLate();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 0f8b8ce..fa7be23 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1606,7 +1606,7 @@
LintCode.no_duplicate_case_values:
status: hasFix
LintCode.no_leading_underscores_for_library_prefixes:
- status: needsFix
+ status: hasFix
LintCode.no_leading_underscores_for_local_identifiers:
status: hasFix
LintCode.no_logic_in_create_state:
@@ -1779,7 +1779,7 @@
LintCode.unnecessary_lambdas:
status: hasFix
LintCode.unnecessary_late:
- status: needsFix
+ status: hasFix
LintCode.unnecessary_new:
status: hasFix
LintCode.unnecessary_null_aware_assignments:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 724920c..d3411f7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1073,6 +1073,16 @@
DartFixKindPriority.IN_FILE,
'Remove unnecessary const keywords everywhere in file',
);
+ static const REMOVE_UNNECESSARY_LATE = FixKind(
+ 'dart.fix.remove.unnecessaryLate',
+ DartFixKindPriority.DEFAULT,
+ 'Remove unnecessary late keyword',
+ );
+ static const REMOVE_UNNECESSARY_LATE_MULTI = FixKind(
+ 'dart.fix.remove.unnecessaryLate.multi',
+ DartFixKindPriority.IN_FILE,
+ 'Remove unnecessary late keywords everywhere in file',
+ );
static const REMOVE_UNNECESSARY_NEW = FixKind(
'dart.fix.remove.unnecessaryNew',
DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index bb89d71..11db925 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -131,6 +131,7 @@
import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_raw_string.dart';
@@ -454,6 +455,9 @@
LintNames.no_duplicate_case_values: [
RemoveDuplicateCase.newInstance,
],
+ LintNames.no_leading_underscores_for_library_prefixes: [
+ RemoveLeadingUnderscore.newInstance,
+ ],
LintNames.no_leading_underscores_for_local_identifiers: [
RemoveLeadingUnderscore.newInstance,
],
@@ -617,6 +621,9 @@
LintNames.unnecessary_lambdas: [
ReplaceWithTearOff.newInstance,
],
+ LintNames.unnecessary_late: [
+ RemoveUnnecessaryLate.newInstance,
+ ],
LintNames.unnecessary_new: [
RemoveUnnecessaryNew.newInstance,
],
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 0fac6a9..bdb7b99 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -161,6 +161,14 @@
return collector.references;
}
+/// Return references to the [element] inside the [root] node.
+List<SimpleIdentifier> findPrefixElementReferences(
+ AstNode root, PrefixElement element) {
+ var collector = _ElementReferenceCollector(element);
+ root.accept(collector);
+ return collector.references;
+}
+
/// TODO(scheglov) replace with nodes once there will be
/// [CompilationUnit.getComments].
///
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index d94fd94..472ddf8 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -59,6 +59,8 @@
static const String leading_newlines_in_multiline_strings =
'leading_newlines_in_multiline_strings';
static const String no_duplicate_case_values = 'no_duplicate_case_values';
+ static const String no_leading_underscores_for_library_prefixes =
+ 'no_leading_underscores_for_library_prefixes';
static const String no_leading_underscores_for_local_identifiers =
'no_leading_underscores_for_local_identifiers';
static const String non_constant_identifier_names =
@@ -132,6 +134,7 @@
static const String unnecessary_getters_setters =
'unnecessary_getters_setters';
static const String unnecessary_lambdas = 'unnecessary_lambdas';
+ static const String unnecessary_late = 'unnecessary_late';
static const String unnecessary_new = 'unnecessary_new';
static const String unnecessary_null_in_if_null_operators =
'unnecessary_null_in_if_null_operators';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 7de85d0..87e18e9 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -247,6 +247,7 @@
/// Return the kind of fixes being tested by this test class.
FixKind get kind;
+ /// Asserts that the resolved compilation unit has a fix which produces [expected] output.
Future<void> assertHasFix(String expected,
{bool Function(AnalysisError)? errorFilter,
int? length,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
index adf0a5a..3f0a3cd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
@@ -12,7 +12,8 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(RemoveLeadingUnderscoreBulkTest);
- defineReflectiveTests(RemoveLeadingUnderscoreTest);
+ defineReflectiveTests(RemoveLeadingUnderscoreForLibraryPrefixesTest);
+ defineReflectiveTests(RemoveLeadingUnderscoreForLocalVariablesTest);
});
}
@@ -44,7 +45,29 @@
}
@reflectiveTest
-class RemoveLeadingUnderscoreTest extends FixProcessorLintTest {
+class RemoveLeadingUnderscoreForLibraryPrefixesTest
+ extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
+
+ @override
+ String get lintCode => LintNames.no_leading_underscores_for_library_prefixes;
+
+ Future<void> test_importPrefix() async {
+ await resolveTestCode('''
+import 'dart:core' as _core;
+_core.int i = 1;
+''');
+ await assertHasFix('''
+import 'dart:core' as core;
+core.int i = 1;
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveLeadingUnderscoreForLocalVariablesTest
+ extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
new file mode 100644
index 0000000..171d193
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, 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/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(RemoveUnnecessaryLateBulkTest);
+ defineReflectiveTests(RemoveUnnecessaryLateTest);
+ });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateBulkTest extends BulkFixProcessorTest {
+ @override
+ String get lintCode => LintNames.unnecessary_late;
+
+ Future<void> test_singleFile() async {
+ await resolveTestCode('''
+late String s1 = '';
+late final String s2 = '';
+''');
+ await assertHasFix('''
+String s1 = '';
+final String s2 = '';
+''');
+ }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateTest extends FixProcessorLintTest {
+ @override
+ FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+ @override
+ String get lintCode => LintNames.unnecessary_late;
+
+ Future<void> test_static() async {
+ await resolveTestCode('''
+class C {
+ static late String s1 = '';
+}
+''');
+ await assertHasFix('''
+class C {
+ static String s1 = '';
+}
+''');
+ }
+
+ Future<void> test_topLevel() async {
+ await resolveTestCode('''
+late String s1 = '';
+''');
+ await assertHasFix('''
+String s1 = '';
+''');
+ }
+
+ Future<void> test_topLevel_multipleVariables_fixFirst() async {
+ await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+ await assertHasFix(
+ '''
+String s1 = '', s2 = '';
+''',
+ errorFilter: (error) => error.toString().contains('test.dart(21..27)'),
+ );
+ }
+
+ Future<void> test_topLevel_multipleVariables_fixSecond() async {
+ await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+ await assertHasFix(
+ '''
+String s1 = '', s2 = '';
+''',
+ errorFilter: (error) => error.toString().contains('test.dart(12..18)'),
+ );
+ }
+
+ Future<void> test_topLevel_multipleVariables_notAllHaveInitializer() async {
+ await resolveTestCode('''
+late String s1, s2 = '';
+''');
+ await assertNoFix();
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index fc4bb66..5997525 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -160,6 +160,7 @@
import 'remove_type_arguments_test.dart' as remove_type_arguments;
import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
+import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
import 'remove_unnecessary_parentheses_test.dart'
as remove_unnecessary_parentheses;
@@ -362,6 +363,7 @@
remove_type_arguments.main();
remove_unnecessary_cast.main();
remove_unnecessary_const.main();
+ remove_unnecessary_late.main();
remove_unnecessary_new.main();
remove_unnecessary_parentheses.main();
remove_unnecessary_raw_string.main();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index f4e2995..2322191 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -980,6 +980,12 @@
// The name of a NamedType does not provide any context.
// So, we don't need to resolve anything.
if (parent is NamedType) {
+ // `{foo^ print(0);}` looks as `foo print; (0);`.
+ var parent3 = parent.parent?.parent;
+ if (parent3 is VariableDeclarationStatement &&
+ parent3.semicolon.isSynthetic) {
+ return false;
+ }
return true;
}
diff --git a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
index 7e5b176..92fc5ba 100644
--- a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
@@ -273,18 +273,13 @@
// The bounds of type parameters must be equal.
// Otherwise the result is `Never`.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s) => t == s);
- if (freshTypeFormalTypes == null) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return NeverTypeImpl.instance;
}
- var typeFormals = freshTypeFormalTypes
- .map<TypeParameterElement>((t) => t.element)
- .toList();
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
var fParameters = f.parameters;
var gParameters = g.parameters;
@@ -379,7 +374,7 @@
var returnType = getGreatestLowerBound(f.returnType, g.returnType);
return FunctionTypeImpl(
- typeFormals: typeFormals,
+ typeFormals: fresh.typeParameters,
parameters: parameters,
returnType: returnType,
nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index 55f46ff..c675895 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -723,18 +723,13 @@
// The bounds of type parameters must be equal.
// Otherwise the result is `Function`.
- var freshTypeFormalTypes =
- FunctionTypeImpl.relateTypeFormals(f, g, (t, s) => t == s);
- if (freshTypeFormalTypes == null) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return _interfaceTypeFunctionNone;
}
- var typeFormals = freshTypeFormalTypes
- .map<TypeParameterElement>((t) => t.element)
- .toList();
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
var fParameters = f.parameters;
var gParameters = g.parameters;
@@ -822,7 +817,7 @@
var returnType = getLeastUpperBound(f.returnType, g.returnType);
return FunctionTypeImpl(
- typeFormals: typeFormals,
+ typeFormals: fresh.typeParameters,
parameters: parameters,
returnType: returnType,
nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/subtype.dart b/pkg/analyzer/lib/src/dart/element/subtype.dart
index 50ec06d..9ff6e69 100644
--- a/pkg/analyzer/lib/src/dart/element/subtype.dart
+++ b/pkg/analyzer/lib/src/dart/element/subtype.dart
@@ -20,16 +20,17 @@
/// https://github.com/dart-lang/language
/// See `resources/type-system/subtyping.md`
class SubtypeHelper {
+ final TypeSystemImpl _typeSystem;
final TypeProviderImpl _typeProvider;
final InterfaceTypeImpl _nullNone;
final InterfaceTypeImpl _objectNone;
final InterfaceTypeImpl _objectQuestion;
- SubtypeHelper(TypeSystemImpl typeSystem)
- : _typeProvider = typeSystem.typeProvider,
- _nullNone = typeSystem.nullNone,
- _objectNone = typeSystem.objectNone,
- _objectQuestion = typeSystem.objectQuestion;
+ SubtypeHelper(this._typeSystem)
+ : _typeProvider = _typeSystem.typeProvider,
+ _nullNone = _typeSystem.nullNone,
+ _objectNone = _typeSystem.objectNone,
+ _objectQuestion = _typeSystem.objectQuestion;
/// Return `true` if [T0_] is a subtype of [T1_].
bool isSubtypeOf(DartType T0_, DartType T1_) {
@@ -342,24 +343,13 @@
/// Check that [f] is a subtype of [g].
bool _isFunctionSubtypeOf(FunctionType f, FunctionType g) {
- var fTypeFormals = f.typeFormals;
- var gTypeFormals = g.typeFormals;
-
- // The number of type parameters must be the same.
- if (fTypeFormals.length != gTypeFormals.length) {
+ var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+ if (fresh == null) {
return false;
}
- // The bounds of type parameters must be equal.
- var freshTypeFormalTypes = FunctionTypeImpl.relateTypeFormals(f, g, (t, s) {
- return isSubtypeOf(t, s) && isSubtypeOf(s, t);
- });
- if (freshTypeFormalTypes == null) {
- return false;
- }
-
- f = f.instantiate(freshTypeFormalTypes);
- g = g.instantiate(freshTypeFormalTypes);
+ f = f.instantiate(fresh.typeParameterTypes);
+ g = g.instantiate(fresh.typeParameterTypes);
if (!isSubtypeOf(f.returnType, g.returnType)) {
return false;
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 1b41aeb5..9097f205 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -32,6 +32,19 @@
import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
import 'package:analyzer/src/dart/element/well_bounded.dart';
+/// Fresh type parameters created to unify two lists of type parameters.
+class RelatedTypeParameters {
+ static final _empty = RelatedTypeParameters._([], []);
+
+ final List<TypeParameterElement> typeParameters;
+ final List<TypeParameterType> typeParameterTypes;
+
+ RelatedTypeParameters._(
+ this.typeParameters,
+ this.typeParameterTypes,
+ );
+}
+
/// The [TypeSystem] implementation.
class TypeSystemImpl implements TypeSystem {
/// If `true`, then NNBD type rules should be used.
@@ -803,6 +816,15 @@
return false;
}
+ /// Check if [left] is equal to [right].
+ ///
+ /// Implements:
+ /// https://github.com/dart-lang/language
+ /// See `resources/type-system/subtyping.md#type-equality`
+ bool isEqualTo(DartType left, DartType right) {
+ return isSubtypeOf(left, right) && isSubtypeOf(right, left);
+ }
+
/// A function bounded type is either `Function` itself, or a type variable
/// whose bound is function bounded, or an intersection (promoted type
/// parameter type) whose second operand is function bounded.
@@ -1423,6 +1445,72 @@
}
}
+ /// Given two lists of type parameters, check that that they have the same
+ /// number of elements, and their bounds are equal.
+ ///
+ /// The return value will be a new list of fresh type parameters, that can
+ /// be used to instantiate both function types, allowing further comparison.
+ RelatedTypeParameters? relateTypeParameters(
+ List<TypeParameterElement> typeParameters1,
+ List<TypeParameterElement> typeParameters2,
+ ) {
+ if (typeParameters1.length != typeParameters2.length) {
+ return null;
+ }
+ if (typeParameters1.isEmpty) {
+ return RelatedTypeParameters._empty;
+ }
+
+ var freshTypeParameters = <TypeParameterElementImpl>[];
+ var freshTypeParameterTypes = <TypeParameterType>[];
+ for (var i = 0; i < typeParameters1.length; i++) {
+ var freshTypeParameter = TypeParameterElementImpl(
+ typeParameters1[i].name,
+ -1,
+ );
+ freshTypeParameters.add(freshTypeParameter);
+ freshTypeParameterTypes.add(
+ TypeParameterTypeImpl(
+ element: freshTypeParameter,
+ nullabilitySuffix: NullabilitySuffix.none,
+ ),
+ );
+ }
+
+ var substitution1 = Substitution.fromPairs(
+ typeParameters1,
+ freshTypeParameterTypes,
+ );
+ var substitution2 = Substitution.fromPairs(
+ typeParameters2,
+ freshTypeParameterTypes,
+ );
+
+ for (var i = 0; i < typeParameters1.length; i++) {
+ var bound1 = typeParameters1[i].bound;
+ var bound2 = typeParameters2[i].bound;
+ if (bound1 == null && bound2 == null) {
+ continue;
+ }
+ bound1 ??= DynamicTypeImpl.instance;
+ bound2 ??= DynamicTypeImpl.instance;
+ bound1 = substitution1.substituteType(bound1);
+ bound2 = substitution2.substituteType(bound2);
+ if (!isEqualTo(bound1, bound2)) {
+ return null;
+ }
+
+ if (!bound1.isDynamic) {
+ freshTypeParameters[i].bound = bound1;
+ }
+ }
+
+ return RelatedTypeParameters._(
+ freshTypeParameters,
+ freshTypeParameterTypes,
+ );
+ }
+
/// Replaces all covariant occurrences of `dynamic`, `void`, and `Object` or
/// `Object?` with `Null` or `Never` and all contravariant occurrences of
/// `Null` or `Never` with `Object` or `Object?`.
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d82f871..0e38986 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -387,7 +387,7 @@
if (interfaceElement.isDartCoreEnum &&
library.featureSet.isEnabled(Feature.enhanced_enums)) {
- if (classElement.isAbstract) {
+ if (classElement.isAbstract || classElement.isEnum) {
return false;
}
reporter.reportErrorForNode(
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index c923c69..01ff198 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -74,6 +74,9 @@
/// for the kind of the function body, e.g. not `Future` for `async`.
bool hasLegalReturnType = true;
+ /// The number of enclosing [CatchClause] in this executable.
+ int catchClauseLevel = 0;
+
EnclosingExecutableContext(this.element,
{bool? isAsynchronous, this.catchErrorOnErrorReturnType})
: isAsynchronous =
@@ -164,11 +167,6 @@
/// The manager for the inheritance mappings.
final InheritanceManager3 _inheritanceManager;
- /// A flag indicating whether the visitor is currently within a catch clause.
- ///
- /// See [visitCatchClause].
- bool _isInCatchClause = false;
-
/// A flag indicating whether the visitor is currently within a comment.
bool _isInComment = false;
@@ -250,7 +248,6 @@
_duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
_inheritanceManager, _currentLibrary, errorReporter) {
_isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
- _isInCatchClause = false;
_isInStaticVariableDeclaration = false;
_isInConstructorInitializer = false;
_intType = _typeProvider.intType;
@@ -409,13 +406,12 @@
@override
void visitCatchClause(CatchClause node) {
_duplicateDefinitionVerifier.checkCatchClause(node);
- bool previousIsInCatchClause = _isInCatchClause;
try {
- _isInCatchClause = true;
+ _enclosingExecutable.catchClauseLevel++;
_checkForTypeAnnotationDeferredClass(node.exceptionType);
super.visitCatchClause(node);
} finally {
- _isInCatchClause = previousIsInCatchClause;
+ _enclosingExecutable.catchClauseLevel--;
}
}
@@ -4112,7 +4108,7 @@
///
/// See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH].
void _checkForRethrowOutsideCatch(RethrowExpression expression) {
- if (!_isInCatchClause) {
+ if (_enclosingExecutable.catchClauseLevel == 0) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression);
}
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
deleted file mode 100644
index c457420..0000000
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-@Deprecated("Use package:analyzer/src/dart/element/type_system.dart instead")
-library type_system_generated;
-
-export 'package:analyzer/src/dart/element/type_system.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
index c8395fc..d570325 100644
--- a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
@@ -87,7 +87,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -96,7 +96,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
@@ -139,7 +139,7 @@
B() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -148,7 +148,7 @@
''');
result.assertResolvedNodes([
- 'B() {print(0); bar; print(1);}',
+ 'B() {print(0); bar print; (1);}',
]);
}
@@ -246,7 +246,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -255,7 +255,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
@@ -297,6 +297,24 @@
void foo2() {
print(0);
+ bar^
+ print(1);
+}
+
+void foo3() {}
+''');
+
+ result.assertResolvedNodes([
+ 'void foo2() {print(0); bar print; (1);}',
+ ]);
+ }
+
+ test_functionDeclaration_body_withSemicolon() async {
+ var result = _resolveTestCode(r'''
+void foo1() {}
+
+void foo2() {
+ print(0);
bar^;
print(1);
}
@@ -396,7 +414,7 @@
void foo2() {
print(0);
- bar^;
+ bar^
print(1);
}
@@ -405,7 +423,7 @@
''');
result.assertResolvedNodes([
- 'void foo2() {print(0); bar; print(1);}',
+ 'void foo2() {print(0); bar print; (1);}',
]);
}
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 481f288..884d010 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -1479,6 +1479,41 @@
);
}
+ test_functionType_74() {
+ var T1 = typeParameter('T');
+ var R1 = typeParameter(
+ 'R',
+ bound: typeParameterType(
+ T1,
+ nullabilitySuffix: NullabilitySuffix.none,
+ ),
+ );
+
+ var T2 = typeParameter('T');
+ var R2 = typeParameter(
+ 'R',
+ bound: typeParameterType(
+ T2,
+ nullabilitySuffix: NullabilitySuffix.none,
+ ),
+ );
+
+ // Note, the order `R extends T`, then `T` is important.
+ // We test that all type parameters replaced at once, not as we go.
+ isSubtype(
+ functionTypeNone(
+ typeFormals: [R1, T1],
+ returnType: voidNone,
+ ),
+ functionTypeNone(
+ typeFormals: [R2, T2],
+ returnType: voidNone,
+ ),
+ strT0: 'void Function<R extends T, T>()',
+ strT1: 'void Function<R extends T, T>()',
+ );
+ }
+
test_functionType_generic_nested() {
var E0 = typeParameter('E0');
var F0 = typeParameter('F0');
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 d5d78f2..1846448 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -30,15 +30,27 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('foo++'),
- readElement: findElement.getter('foo'),
- readType: 'int',
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- element: numElement.getMethod('+'),
- type: 'int?',
- );
+ assertResolvedNodeText(findNode.postfix('foo++'), r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@38
+ staticType: A?
+ operator: ?.
+ propertyName: SimpleIdentifier
+ token: foo
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::foo
+ readType: int
+ writeElement: self::@class::A::@setter::foo
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int?
+''');
}
test_inc_simpleIdentifier_parameter_depromote() async {
@@ -55,15 +67,20 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'A',
- writeElement: findElement.parameter('x'),
- writeType: 'Object',
- element: findElement.method('+'),
- type: 'A',
- );
+ assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@63
+ staticType: null
+ operator: ++
+ readElement: x@63
+ readType: A
+ writeElement: x@63
+ writeType: Object
+ staticElement: self::@class::A::@method::+
+ staticType: A
+''');
assertType(findNode.simple('x; // ref'), 'Object');
}
@@ -75,15 +92,16 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
+ assertResolvedNodeText(findNode.postfix('x!'), r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@12
+ staticType: int?
+ operator: !
+ staticElement: <null>
+ staticType: int
+''');
}
test_nullCheck_functionExpressionInvocation_rewrite() async {
@@ -118,15 +136,25 @@
staticType: int?
''');
- assertPostfixExpression(
- findNode.postfix(']!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
+ assertResolvedNodeText(findNode.postfix(']!'), r'''
+PostfixExpression
+ operand: IndexExpression
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@24
+ staticType: Map<String, int>
+ leftBracket: [
+ index: SimpleStringLiteral
+ literal: 'foo'
+ rightBracket: ]
+ staticElement: MethodMember
+ base: dart:core::@class::Map::@method::[]
+ substitution: {K: String, V: int}
+ staticType: int?
+ operator: !
+ staticElement: <null>
+ staticType: int
+''');
}
test_nullCheck_null() async {
@@ -156,15 +184,28 @@
type: 'int?',
);
- assertPostfixExpression(
- findNode.postfix('f(null)!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'int',
- );
+ assertResolvedNodeText(findNode.postfix('f(null)!'), r'''
+PostfixExpression
+ operand: MethodInvocation
+ methodName: SimpleIdentifier
+ token: f
+ staticElement: self::@function::f
+ staticType: T Function<T>(T)
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ NullLiteral
+ literal: null
+ staticType: Null
+ rightParenthesis: )
+ staticInvokeType: int? Function(int?)
+ staticType: int?
+ typeArgumentTypes
+ int?
+ operator: !
+ staticElement: <null>
+ staticType: int
+''');
}
/// See https://github.com/dart-lang/language/issues/1163
@@ -245,15 +286,15 @@
assertTypeDynamic(findNode.super_('super!'));
- assertPostfixExpression(
- findNode.postfix('super!'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'dynamic',
- );
+ assertResolvedNodeText(findNode.postfix('super!'), r'''
+PostfixExpression
+ operand: SuperExpression
+ superKeyword: super
+ staticType: dynamic
+ operator: !
+ staticElement: <null>
+ staticType: dynamic
+''');
assertMethodInvocation2(
findNode.methodInvocation('foo();'),
@@ -272,15 +313,16 @@
''');
var postfixExpression = findNode.postfix('x!');
- assertPostfixExpression(
- postfixExpression,
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'T & Object',
- );
+ assertResolvedNodeText(postfixExpression, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@13
+ staticType: T?
+ operator: !
+ staticElement: <null>
+ staticType: T & Object
+''');
}
test_nullCheck_typeParameter_already_promoted() async {
@@ -293,15 +335,16 @@
''');
var postfixExpression = findNode.postfix('x!');
- assertPostfixExpression(
- postfixExpression,
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'T & num',
- );
+ assertResolvedNodeText(postfixExpression, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@13
+ staticType: T? & num?
+ operator: !
+ staticElement: <null>
+ staticType: T & num
+''');
}
}
@@ -313,18 +356,40 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x--'),
- readElement: findElement.parameter('x'),
- readType: 'int',
- writeElement: findElement.parameter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('-'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x--');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: --
+ readElement: x@11
+ readType: int
+ writeElement: x@11
+ writeType: int
+ staticElement: dart:core::@class::num::@method::-
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: --
+ readElement: x@11
+ readType: int*
+ writeElement: x@11
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::-
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_indexExpression_instance() async {
@@ -339,18 +404,56 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('a[0]++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('a[0]++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@91
+ staticType: A
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@91
+ staticType: A*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_indexExpression_super() async {
@@ -367,18 +470,54 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('[0]++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('[0]++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: SuperExpression
+ superKeyword: super
+ staticType: B
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: SuperExpression
+ superKeyword: super
+ staticType: B*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_indexExpression_this() async {
@@ -393,18 +532,54 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('[0]++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('[0]++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: IndexExpression
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_notLValue_parenthesized() async {
@@ -416,15 +591,44 @@
error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 16, 2),
]);
- assertPostfixExpression(
- findNode.postfix('(0)++'),
- readElement: null,
- readType: 'dynamic',
- writeElement: null,
- writeType: 'dynamic',
- element: null,
- type: 'dynamic',
- );
+ var node = findNode.postfix('(0)++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: ParenthesizedExpression
+ leftParenthesis: (
+ expression: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightParenthesis: )
+ staticType: int
+ operator: ++
+ readElement: <null>
+ readType: dynamic
+ writeElement: <null>
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: ParenthesizedExpression
+ leftParenthesis: (
+ expression: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightParenthesis: )
+ staticType: int*
+ operator: ++
+ readElement: <null>
+ readType: dynamic
+ writeElement: <null>
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ }
}
test_inc_notLValue_simpleIdentifier_typeLiteral() async {
@@ -436,15 +640,38 @@
error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
]);
- assertPostfixExpression(
- findNode.postfix('int++'),
- readElement: intElement,
- readType: 'dynamic',
- writeElement: intElement,
- writeType: 'dynamic',
- element: null,
- type: 'dynamic',
- );
+ var node = findNode.postfix('int++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: int
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: dart:core::@class::int
+ readType: dynamic
+ writeElement: dart:core::@class::int
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: int
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: dart:core::@class::int
+ readType: dynamic
+ writeElement: dart:core::@class::int
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ }
}
test_inc_notLValue_simpleIdentifier_typeLiteral_typeParameter() async {
@@ -456,19 +683,41 @@
error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 16, 1),
]);
- var postfix = findNode.postfix('T++');
- assertPostfixExpression(
- postfix,
- readElement: findElement.typeParameter('T'),
- readType: 'dynamic',
- writeElement: findElement.typeParameter('T'),
- writeType: 'dynamic',
- element: null,
- type: 'dynamic',
- );
+ var node = findNode.postfix('T++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: T
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: T@7
+ readType: dynamic
+ writeElement: T@7
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: T
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: T@7
+ readType: dynamic
+ writeElement: T@7
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- postfix.operand,
+ node.operand,
);
}
@@ -483,18 +732,56 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: a
+ staticElement: a@35
+ staticType: A
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: a
+ staticElement: a@35
+ staticType: A*
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_prefixedIdentifier_topLevel() async {
@@ -511,21 +798,58 @@
var importFind = findElement.importFind('package:test/a.dart');
- var postfix = findNode.postfix('x++');
- assertPostfixExpression(
- postfix,
- readElement: importFind.topGet('x'),
- readType: 'int',
- writeElement: importFind.topSet('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: package:test/a.dart::@getter::x
+ readType: int
+ writeElement: package:test/a.dart::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: package:test/a.dart::@getter::x
+ readType: int*
+ writeElement: package:test/a.dart::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
- var prefixed = postfix.operand as PrefixedIdentifier;
+ var prefixed = node.operand as PrefixedIdentifier;
assertImportPrefix(prefixed.prefix, importFind.prefix);
}
@@ -540,18 +864,72 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A*
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_propertyAccess_super() async {
@@ -571,18 +949,52 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.getter('x', of: 'A'),
- readType: 'int',
- writeElement: findElement.setter('x', of: 'A'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: SuperExpression
+ superKeyword: super
+ staticType: B
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: SuperExpression
+ superKeyword: super
+ staticType: B*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_propertyAccess_this() async {
@@ -597,18 +1009,52 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: PropertyAccess
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ operator: ++
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_simpleIdentifier_parameter_double() async {
@@ -618,18 +1064,40 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'double',
- writeElement: findElement.parameter('x'),
- writeType: 'double',
- element: elementMatcher(
- doubleElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'double',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ operator: ++
+ readElement: x@14
+ readType: double
+ writeElement: x@14
+ writeType: double
+ staticElement: dart:core::@class::double::@method::+
+ staticType: double
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ operator: ++
+ readElement: x@14
+ readType: double*
+ writeElement: x@14
+ writeType: double*
+ staticElement: MethodMember
+ base: dart:core::@class::double::@method::+
+ isLegacy: true
+ staticType: double*
+''');
+ }
}
test_inc_simpleIdentifier_parameter_int() async {
@@ -639,18 +1107,40 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'int',
- writeElement: findElement.parameter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: ++
+ readElement: x@11
+ readType: int
+ writeElement: x@11
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: ++
+ readElement: x@11
+ readType: int*
+ writeElement: x@11
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_simpleIdentifier_parameter_num() async {
@@ -660,18 +1150,40 @@
}
''');
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'num',
- writeElement: findElement.parameter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'num',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: ++
+ readElement: x@11
+ readType: num
+ writeElement: x@11
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: num
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ operator: ++
+ readElement: x@11
+ readType: num*
+ writeElement: x@11
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: num*
+''');
+ }
}
test_inc_simpleIdentifier_thisGetter_superSetter() async {
@@ -688,22 +1200,43 @@
}
''');
- var postfix = findNode.postfix('x++');
- assertPostfixExpression(
- postfix,
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::B::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@class::B::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- postfix.operand,
+ node.operand,
);
}
@@ -718,22 +1251,43 @@
}
''');
- var postfix = findNode.postfix('x++');
- assertPostfixExpression(
- postfix,
- readElement: findElement.topGet('x'),
- readType: 'int',
- writeElement: findElement.topSet('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@getter::x
+ readType: int
+ writeElement: self::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@getter::x
+ readType: int*
+ writeElement: self::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- postfix.operand,
+ node.operand,
);
}
@@ -750,22 +1304,43 @@
}
''');
- var postfix = findNode.postfix('x++');
- assertPostfixExpression(
- postfix,
- readElement: findElement.topGet('x'),
- readType: 'int',
- writeElement: findElement.topSet('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.postfix('x++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@getter::x
+ readType: int
+ writeElement: self::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ operator: ++
+ readElement: self::@getter::x
+ readType: int*
+ writeElement: self::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- postfix.operand,
+ node.operand,
);
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 24948fe..59238ca 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_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/ast/ast.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -33,15 +32,23 @@
55, 6),
]);
- assertPrefixExpression(
- findNode.prefix('!a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: boolElement.getMethod('!'),
- type: 'bool',
- );
+ assertResolvedNodeText(findNode.prefix('!a'), r'''
+PrefixExpression
+ operator: !
+ operand: PropertyAccess
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@47
+ staticType: A?
+ operator: ?.
+ propertyName: SimpleIdentifier
+ token: foo
+ staticElement: self::@class::A::@getter::foo
+ staticType: bool
+ staticType: bool?
+ staticElement: <null>
+ staticType: bool
+''');
}
test_minus_no_nullShorting() async {
@@ -58,15 +65,23 @@
50, 1),
]);
- assertPrefixExpression(
- findNode.prefix('-a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: intElement.getMethod('unary-'),
- type: 'int',
- );
+ assertResolvedNodeText(findNode.prefix('-a'), r'''
+PrefixExpression
+ operator: -
+ operand: PropertyAccess
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@43
+ staticType: A?
+ operator: ?.
+ propertyName: SimpleIdentifier
+ token: foo
+ staticElement: self::@class::A::@getter::foo
+ staticType: int
+ staticType: int?
+ staticElement: dart:core::@class::int::@method::unary-
+ staticType: int
+''');
}
test_plusPlus_depromote() async {
@@ -82,15 +97,20 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'A',
- writeElement: findElement.parameter('x'),
- writeType: 'Object',
- element: findElement.method('+'),
- type: 'Object',
- );
+ assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@63
+ staticType: null
+ readElement: x@63
+ readType: A
+ writeElement: x@63
+ writeType: Object
+ staticElement: self::@class::A::@method::+
+ staticType: Object
+''');
}
test_plusPlus_nullShorting() async {
@@ -104,15 +124,27 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++a'),
- readElement: findElement.getter('foo'),
- readType: 'int',
- writeElement: findElement.setter('foo'),
- writeType: 'int',
- element: numElement.getMethod('+'),
- type: 'int?',
- );
+ assertResolvedNodeText(findNode.prefix('++a'), r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@38
+ staticType: A?
+ operator: ?.
+ propertyName: SimpleIdentifier
+ token: foo
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::foo
+ readType: int
+ writeElement: self::@class::A::@setter::foo
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int?
+''');
}
test_tilde_no_nullShorting() async {
@@ -129,15 +161,23 @@
50, 1),
]);
- assertPrefixExpression(
- findNode.prefix('~a'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: intElement.getMethod('~'),
- type: 'int',
- );
+ assertResolvedNodeText(findNode.prefix('~a'), r'''
+PrefixExpression
+ operator: ~
+ operand: PropertyAccess
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@43
+ staticType: A?
+ operator: ?.
+ propertyName: SimpleIdentifier
+ token: foo
+ staticElement: self::@class::A::@getter::foo
+ staticType: int
+ staticType: int?
+ staticElement: dart:core::@class::int::@method::~
+ staticType: int
+''');
}
}
@@ -161,15 +201,46 @@
type: 'bool',
);
- assertPrefixExpression(
- findNode.prefix('!f()'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: boolElement.getMethod('!'),
- type: 'bool',
- );
+ var node = findNode.prefix('!f()');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: MethodInvocation
+ methodName: SimpleIdentifier
+ token: f
+ staticElement: self::@function::f
+ staticType: T Function<T>()
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: bool Function()
+ staticType: bool
+ typeArgumentTypes
+ bool
+ staticElement: <null>
+ staticType: bool
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: MethodInvocation
+ methodName: SimpleIdentifier
+ token: f
+ staticElement: self::@function::f
+ staticType: T* Function<T>()*
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticInvokeType: bool* Function()*
+ staticType: bool*
+ typeArgumentTypes
+ bool*
+ staticElement: <null>
+ staticType: bool*
+''');
+ }
}
test_bang_bool_localVariable() async {
@@ -179,15 +250,30 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('!x'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: boolElement.getMethod('!'),
- type: 'bool',
- );
+ var node = findNode.prefix('!x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@12
+ staticType: bool
+ staticElement: <null>
+ staticType: bool
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@12
+ staticType: bool*
+ staticElement: <null>
+ staticType: bool*
+''');
+ }
}
test_bang_int_localVariable() async {
@@ -199,15 +285,30 @@
error(CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION, 19, 1),
]);
- assertPrefixExpression(
- findNode.prefix('!x'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: null,
- type: 'bool',
- );
+ var node = findNode.prefix('!x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int
+ staticElement: <null>
+ staticType: bool
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: !
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int*
+ staticElement: <null>
+ staticType: bool*
+''');
+ }
}
test_inc_indexExpression_instance() async {
@@ -222,18 +323,56 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@91
+ staticType: A
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: SimpleIdentifier
+ token: a
+ staticElement: a@91
+ staticType: A*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_indexExpression_super() async {
@@ -250,18 +389,54 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: SuperExpression
+ superKeyword: super
+ staticType: B
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: SuperExpression
+ superKeyword: super
+ staticType: B*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_inc_indexExpression_this() async {
@@ -276,18 +451,54 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.method('[]'),
- readType: 'int',
- writeElement: findElement.method('[]='),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int
+ writeElement: self::@class::A::@method::[]=
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: IndexExpression
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A*
+ leftBracket: [
+ index: IntegerLiteral
+ literal: 0
+ staticType: int*
+ rightBracket: ]
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@method::[]
+ readType: int*
+ writeElement: self::@class::A::@method::[]=
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_minus_simpleIdentifier_parameter_int() async {
@@ -297,18 +508,32 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('-x'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: elementMatcher(
- intElement.getMethod('unary-'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('-x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: -
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int
+ staticElement: dart:core::@class::int::@method::unary-
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: -
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::int::@method::unary-
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_notLValue_extensionOverride() async {
@@ -328,15 +553,60 @@
error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 103, 1),
]);
- assertPrefixExpression(
- findNode.prefix('++Ext'),
- readElement: null,
- readType: 'dynamic',
- writeElement: null,
- writeType: 'dynamic',
- element: findElement.method('+'),
- type: 'int',
- );
+ var node = findNode.prefix('++Ext');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: ExtensionOverride
+ extensionName: SimpleIdentifier
+ token: Ext
+ staticElement: self::@extension::Ext
+ staticType: null
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ SimpleIdentifier
+ token: c
+ staticElement: c@89
+ staticType: C
+ rightParenthesis: )
+ extendedType: C
+ staticType: null
+ readElement: <null>
+ readType: dynamic
+ writeElement: <null>
+ writeType: dynamic
+ staticElement: self::@extension::Ext::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: ExtensionOverride
+ extensionName: SimpleIdentifier
+ token: Ext
+ staticElement: self::@extension::Ext
+ staticType: null
+ argumentList: ArgumentList
+ leftParenthesis: (
+ arguments
+ SimpleIdentifier
+ token: c
+ staticElement: c@89
+ staticType: C*
+ rightParenthesis: )
+ extendedType: C*
+ staticType: null
+ readElement: <null>
+ readType: dynamic
+ writeElement: <null>
+ writeType: dynamic
+ staticElement: self::@extension::Ext::@method::+
+ staticType: int*
+''');
+ }
}
test_plusPlus_notLValue_simpleIdentifier_typeLiteral() async {
@@ -348,15 +618,38 @@
error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 15, 3),
]);
- assertPrefixExpression(
- findNode.prefix('++int'),
- readElement: intElement,
- readType: 'dynamic',
- writeElement: intElement,
- writeType: 'dynamic',
- element: null,
- type: 'dynamic',
- );
+ var node = findNode.prefix('++int');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: int
+ staticElement: <null>
+ staticType: null
+ readElement: dart:core::@class::int
+ readType: dynamic
+ writeElement: dart:core::@class::int
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: int
+ staticElement: <null>
+ staticType: null
+ readElement: dart:core::@class::int
+ readType: dynamic
+ writeElement: dart:core::@class::int
+ writeType: dynamic
+ staticElement: <null>
+ staticType: dynamic
+''');
+ }
}
test_plusPlus_prefixedIdentifier_instance() async {
@@ -370,18 +663,56 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: a
+ staticElement: a@35
+ staticType: A
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: a
+ staticElement: a@35
+ staticType: A*
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_prefixedIdentifier_topLevel() async {
@@ -396,24 +727,56 @@
}
''');
- var importFind = findElement.importFind('package:test/a.dart');
-
- var prefix = findNode.prefix('++');
- assertPrefixExpression(
- prefix,
- readElement: importFind.topGet('x'),
- readType: 'int',
- writeElement: importFind.topSet('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
-
- var prefixed = prefix.operand as PrefixedIdentifier;
- assertImportPrefix(prefixed.prefix, importFind.prefix);
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ readElement: package:test/a.dart::@getter::x
+ readType: int
+ writeElement: package:test/a.dart::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PrefixedIdentifier
+ prefix: SimpleIdentifier
+ token: p
+ staticElement: self::@prefix::p
+ staticType: null
+ period: .
+ identifier: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticElement: <null>
+ staticType: null
+ readElement: package:test/a.dart::@getter::x
+ readType: int*
+ writeElement: package:test/a.dart::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_propertyAccess_instance() async {
@@ -427,18 +790,72 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: InstanceCreationExpression
+ constructorName: ConstructorName
+ type: NamedType
+ name: SimpleIdentifier
+ token: A
+ staticElement: self::@class::A
+ staticType: null
+ type: A*
+ staticElement: self::@class::A::@constructor::•
+ argumentList: ArgumentList
+ leftParenthesis: (
+ rightParenthesis: )
+ staticType: A*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_propertyAccess_super() async {
@@ -458,18 +875,52 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.getter('x', of: 'A'),
- readType: 'int',
- writeElement: findElement.setter('x', of: 'A'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: SuperExpression
+ superKeyword: super
+ staticType: B
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: SuperExpression
+ superKeyword: super
+ staticType: B*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_propertyAccess_this() async {
@@ -484,18 +935,52 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++'),
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: PropertyAccess
+ target: ThisExpression
+ thisKeyword: this
+ staticType: A*
+ operator: .
+ propertyName: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_simpleIdentifier_parameter_double() async {
@@ -505,18 +990,40 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'double',
- writeElement: findElement.parameter('x'),
- writeType: 'double',
- element: elementMatcher(
- doubleElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'double',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ readElement: x@14
+ readType: double
+ writeElement: x@14
+ writeType: double
+ staticElement: dart:core::@class::double::@method::+
+ staticType: double
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ readElement: x@14
+ readType: double*
+ writeElement: x@14
+ writeType: double*
+ staticElement: MethodMember
+ base: dart:core::@class::double::@method::+
+ isLegacy: true
+ staticType: double*
+''');
+ }
}
test_plusPlus_simpleIdentifier_parameter_int() async {
@@ -526,18 +1033,40 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'int',
- writeElement: findElement.parameter('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ readElement: x@11
+ readType: int
+ writeElement: x@11
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ readElement: x@11
+ readType: int*
+ writeElement: x@11
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_plusPlus_simpleIdentifier_parameter_num() async {
@@ -547,18 +1076,40 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'num',
- writeElement: findElement.parameter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'num',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ readElement: x@11
+ readType: num
+ writeElement: x@11
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: num
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: null
+ readElement: x@11
+ readType: num*
+ writeElement: x@11
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: num*
+''');
+ }
}
test_plusPlus_simpleIdentifier_parameter_typeParameter() async {
@@ -573,18 +1124,40 @@
], legacy: []),
);
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'T',
- writeElement: findElement.parameter('x'),
- writeType: 'T',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'num',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@24
+ staticType: null
+ readElement: x@24
+ readType: T
+ writeElement: x@24
+ writeType: T
+ staticElement: dart:core::@class::num::@method::+
+ staticType: num
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@24
+ staticType: null
+ readElement: x@24
+ readType: T*
+ writeElement: x@24
+ writeType: T*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: num*
+''');
+ }
}
test_plusPlus_simpleIdentifier_thisGetter_superSetter() async {
@@ -601,22 +1174,43 @@
}
''');
- var prefix = findNode.prefix('++x');
- assertPrefixExpression(
- prefix,
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::B::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::B::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- prefix.operand,
+ node.operand,
);
}
@@ -631,22 +1225,43 @@
}
''');
- var prefix = findNode.prefix('++x');
- assertPrefixExpression(
- prefix,
- readElement: findElement.getter('x'),
- readType: 'int',
- writeElement: findElement.setter('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int
+ writeElement: self::@class::A::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@class::A::@getter::x
+ readType: int*
+ writeElement: self::@class::A::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- prefix.operand,
+ node.operand,
);
}
@@ -661,22 +1276,43 @@
}
''');
- var prefix = findNode.prefix('++x');
- assertPrefixExpression(
- prefix,
- readElement: findElement.topGet('x'),
- readType: 'int',
- writeElement: findElement.topSet('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int
+ writeElement: self::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int*
+ writeElement: self::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- prefix.operand,
+ node.operand,
);
}
@@ -693,22 +1329,43 @@
}
''');
- var prefix = findNode.prefix('++x');
- assertPrefixExpression(
- prefix,
- readElement: findElement.topGet('x'),
- readType: 'int',
- writeElement: findElement.topSet('x'),
- writeType: 'num',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int
+ writeElement: self::@setter::x
+ writeType: num
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int*
+ writeElement: self::@setter::x
+ writeType: num*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
assertSimpleIdentifierAssignmentTarget(
- prefix.operand,
+ node.operand,
);
}
@@ -723,18 +1380,40 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.topGet('x'),
- readType: 'int',
- writeElement: findElement.topSet('x'),
- writeType: 'int',
- element: elementMatcher(
- numElement.getMethod('+'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('++x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int
+ writeElement: self::@setter::x
+ writeType: int
+ staticElement: dart:core::@class::num::@method::+
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: <null>
+ staticType: null
+ readElement: self::@getter::x
+ readType: int*
+ writeElement: self::@setter::x
+ writeType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::num::@method::+
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
test_tilde_simpleIdentifier_parameter_int() async {
@@ -744,18 +1423,32 @@
}
''');
- assertPrefixExpression(
- findNode.prefix('~x'),
- readElement: null,
- readType: null,
- writeElement: null,
- writeType: null,
- element: elementMatcher(
- intElement.getMethod('~'),
- isLegacy: isLegacyLibrary,
- ),
- type: 'int',
- );
+ var node = findNode.prefix('~x');
+ if (isNullSafetyEnabled) {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ~
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int
+ staticElement: dart:core::@class::int::@method::~
+ staticType: int
+''');
+ } else {
+ assertResolvedNodeText(node, r'''
+PrefixExpression
+ operator: ~
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@11
+ staticType: int*
+ staticElement: MethodMember
+ base: dart:core::@class::int::@method::~
+ isLegacy: true
+ staticType: int*
+''');
+ }
}
}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 9dac30e..0495690 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -593,30 +593,6 @@
assertType(parameterElement.type, expected);
}
- void assertPostfixExpression(
- PostfixExpression node, {
- required Object? readElement,
- required String? readType,
- required Object? writeElement,
- required String? writeType,
- required Object? element,
- required String type,
- }) {
- assertCompoundAssignment(
- node,
- readElement: readElement,
- readType: readType,
- writeElement: writeElement,
- writeType: writeType,
- );
- assertElement(node.staticElement, element);
- assertType(node, type);
-
- if (writeElement != null) {
- _assertUnresolvedAssignmentTarget(node.operand);
- }
- }
-
void assertPrefixedIdentifier(
PrefixedIdentifier node, {
required Object? element,
@@ -626,30 +602,6 @@
assertType(node, type);
}
- void assertPrefixExpression(
- PrefixExpression node, {
- required Object? readElement,
- required String? readType,
- required Object? writeElement,
- required String? writeType,
- required Object? element,
- required String type,
- }) {
- assertCompoundAssignment(
- node,
- readElement: readElement,
- readType: readType,
- writeElement: writeElement,
- writeType: writeType,
- );
- assertElement(node.staticElement, element);
- assertType(node, type);
-
- if (writeElement != null) {
- _assertUnresolvedAssignmentTarget(node.operand);
- }
- }
-
void assertPropertyAccess(
PropertyAccess access,
Element expectedElement,
diff --git a/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart b/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
index 4b963e3..2a8c23e 100644
--- a/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
@@ -59,12 +59,10 @@
}
test_enum() async {
- await assertErrorsInCode('''
+ await assertNoErrorsInCode('''
enum E implements Enum {
v
}
-''', [
- error(CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE, 18, 4),
- ]);
+''');
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index 96157cc..cc85b0c 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -202,6 +202,18 @@
''');
}
+ test_issue48468() async {
+ await assertNoErrorsInCode(r'''
+abstract class A {
+ void foo<T extends R, R>();
+}
+
+class B implements A {
+ void foo<T extends R, R>() {}
+}
+''');
+ }
+
test_method_parameter_functionTyped_optOut_extends_optIn() async {
newFile('$testPackageLibPath/a.dart', content: r'''
abstract class A {
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 5707c74..ae6f8b6 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -463,15 +463,20 @@
error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
]);
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'Never',
- writeElement: findElement.parameter('x'),
- writeType: 'Never',
- element: null,
- type: 'Never',
- );
+ assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@13
+ staticType: null
+ operator: ++
+ readElement: x@13
+ readType: Never
+ writeElement: x@13
+ writeType: Never
+ staticElement: <null>
+ staticType: Never
+''');
}
test_postfixExpression_neverQ_plusPlus() async {
@@ -484,15 +489,20 @@
22, 2),
]);
- assertPostfixExpression(
- findNode.postfix('x++'),
- readElement: findElement.parameter('x'),
- readType: 'Never?',
- writeElement: findElement.parameter('x'),
- writeType: 'Never?',
- element: null,
- type: 'Never?',
- );
+ assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ operator: ++
+ readElement: x@14
+ readType: Never?
+ writeElement: x@14
+ writeType: Never?
+ staticElement: <null>
+ staticType: Never?
+''');
}
test_prefixExpression_never_plusPlus() async {
@@ -505,15 +515,20 @@
error(HintCode.RECEIVER_OF_TYPE_NEVER, 22, 1),
]);
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'Never',
- writeElement: findElement.parameter('x'),
- writeType: 'Never',
- element: null,
- type: 'Never',
- );
+ assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@13
+ staticType: null
+ readElement: x@13
+ readType: Never
+ writeElement: x@13
+ writeType: Never
+ staticElement: <null>
+ staticType: Never
+''');
}
test_prefixExpression_neverQ_plusPlus() async {
@@ -526,15 +541,20 @@
21, 2),
]);
- assertPrefixExpression(
- findNode.prefix('++x'),
- readElement: findElement.parameter('x'),
- readType: 'Never?',
- writeElement: findElement.parameter('x'),
- writeType: 'Never?',
- element: null,
- type: 'dynamic',
- );
+ assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+ operator: ++
+ operand: SimpleIdentifier
+ token: x
+ staticElement: x@14
+ staticType: null
+ readElement: x@14
+ readType: Never?
+ writeElement: x@14
+ writeType: Never?
+ staticElement: <null>
+ staticType: dynamic
+''');
}
test_propertyAccess_never_read() async {
diff --git a/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart b/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
index ee8c262..717c3a4 100644
--- a/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
@@ -17,9 +17,37 @@
class RethrowOutsideCatchTest extends PubPackageResolutionTest {
test_insideCatch() async {
await assertNoErrorsInCode(r'''
-class A {
- void m() {
- try {} catch (e) {rethrow;}
+void f() {
+ try {} catch (e) {
+ rethrow;
+ }
+}
+''');
+ }
+
+ test_insideCatch_insideClosure() async {
+ await assertErrorsInCode(r'''
+void f() {
+ try {} catch (e) {
+ () {
+ rethrow;
+ };
+ }
+}
+''', [
+ error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 47, 7),
+ ]);
+ }
+
+ test_insideCatch_insideClosure_insideCatch() async {
+ await assertNoErrorsInCode(r'''
+void f() {
+ try {} catch (e1) {
+ () {
+ try {} catch (e2) {
+ rethrow;
+ }
+ };
}
}
''');
@@ -27,11 +55,11 @@
test_withoutCatch() async {
await assertErrorsInCode(r'''
-f() {
+void f() {
rethrow;
}
''', [
- error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 8, 7),
+ error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 13, 7),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 3540ebc..9671ee1 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -80,6 +80,22 @@
''');
}
+ @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48509')
+ test_extensionOverride_optIn_fromOptOut_Null() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+extension E<X extends int> on List<X> {
+ void m() {}
+}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => E<Null>([]).m();
+''');
+ }
+
test_functionReference() async {
await assertErrorsInCode('''
void foo<T extends num>(T a) {}
@@ -130,6 +146,19 @@
''');
}
+ test_instanceCreation_optIn_fromOptOut_Null() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A<X extends int> {}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => A<Null>();
+''');
+ }
+
test_metadata_matching() async {
await assertNoErrorsInCode(r'''
class A<T extends num> {
@@ -193,6 +222,20 @@
]);
}
+ test_methodInvocation_optIn_fromOptOut_Null() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+ void m<X extends int>() {}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => A().m<Null>();
+''');
+ }
+
test_nonFunctionTypeAlias_body_typeArgument_mismatch() async {
await assertErrorsInCode(r'''
class A {}
@@ -282,6 +325,23 @@
]);
}
+ test_redirectingConstructor_optIn_fromOptOut_Null() async {
+ newFile('$testPackageLibPath/a.dart', content: r'''
+import 'test.dart';
+
+class A<X extends int> implements B {}
+''');
+
+ await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+class B {
+ factory B() = A<Null>;
+}
+''');
+ }
+
test_regression_42196() async {
await assertNoErrorsInCode(r'''
typedef G<X> = Function(X);
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index c9fe68b0..d135042 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -44,10 +44,14 @@
Process? _process;
- Completer<bool> _analysisFinished = Completer();
+ /// When not null, this is a [Completer] which completes when analysis has
+ /// finished, otherwise `null`.
+ Completer<bool>? _analysisFinished;
int _id = 0;
+ bool _shutdownResponseReceived = false;
+
Stream<bool> get onAnalyzing {
// {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
return _streamController('server.status')
@@ -59,7 +63,7 @@
/// This future completes when we next receive an analysis finished event
/// (unless there's no current analysis and we've already received a complete
/// event, in which case this future completes immediately).
- Future<bool> get analysisFinished => _analysisFinished.future;
+ Future<bool>? get analysisFinished => _analysisFinished?.future;
Stream<FileAnalysisErrors> get onErrors {
// {"event":"analysis.errors","params":{"file":"/Users/.../lib/main.dart","errors":[]}}
@@ -80,6 +84,11 @@
final Map<String, StreamController<Map<String, dynamic>>> _streamControllers =
{};
+ /// Completes when an analysis server crash has been detected.
+ Future<void> get onCrash => _onCrash.future;
+
+ final _onCrash = Completer<void>();
+
final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};
Future<void> start({bool setAnalysisRoots = true}) async {
@@ -96,17 +105,41 @@
if (packagesFile != null) '--packages=${packagesFile!.path}',
];
- _process = await startDartProcess(sdk, command);
- final proc = _process!;
+ final process = await startDartProcess(sdk, command);
+ _process = process;
+ _shutdownResponseReceived = false;
// This callback hookup can't throw.
- proc.exitCode.whenComplete(() => _process = null);
+ process.exitCode.whenComplete(() {
+ _process = null;
- final Stream<String> errorStream = proc.stderr
+ if (!_shutdownResponseReceived) {
+ // The process exited unexpectedly. Report the crash.
+ // If `server.error` reported an error, that has been logged by
+ // `_handleServerError`.
+
+ final error = StateError('The analysis server crashed unexpectedly');
+
+ final analysisFinished = _analysisFinished;
+ if (analysisFinished != null && !analysisFinished.isCompleted) {
+ // Complete this completer in order to unstick the process.
+ analysisFinished.completeError(error);
+ }
+
+ // Complete these completers in order to unstick the process.
+ for (final completer in _requestCompleters.values) {
+ completer.completeError(error);
+ }
+
+ _onCrash.complete();
+ }
+ });
+
+ final errorStream = process.stderr
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
errorStream.listen(log.stderr);
- final Stream<String> inStream = proc.stdout
+ final inStream = process.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
inStream.listen(_handleServerResponse);
@@ -130,12 +163,15 @@
];
onAnalyzing.listen((isAnalyzing) {
- if (isAnalyzing && _analysisFinished.isCompleted) {
+ final analysisFinished = _analysisFinished;
+ if (isAnalyzing && (analysisFinished?.isCompleted ?? true)) {
// Start a new completer, to be completed when we receive the
// corresponding analysis complete event.
_analysisFinished = Completer();
- } else if (!isAnalyzing && !_analysisFinished.isCompleted) {
- _analysisFinished.complete(true);
+ } else if (!isAnalyzing &&
+ analysisFinished != null &&
+ !analysisFinished.isCompleted) {
+ analysisFinished.complete(true);
}
});
@@ -166,6 +202,7 @@
Future<void> shutdown({Duration timeout = const Duration(seconds: 5)}) async {
// Request shutdown.
await _sendCommand('server.shutdown').then((value) {
+ _shutdownResponseReceived = true;
return null;
}).timeout(timeout, onTimeout: () async {
await dispose();
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 1112fe8..7bcc9c5 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -81,7 +81,7 @@
String get invocation => '${super.invocation} [<directory>]';
@override
- FutureOr<int> run() async {
+ Future<int> run() async {
final args = argResults!;
// Find targets from the 'rest' params.
final List<io.FileSystemEntity> targets = [];
@@ -135,6 +135,12 @@
}
});
+ server.onCrash.then((_) {
+ log.stderr('The analysis server shut down unexpectedly.');
+ log.stdout('Please report this at dartbug.com.');
+ io.exit(1);
+ });
+
await server.analysisFinished;
analysisFinished = true;
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 6e3d600..295bc86 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -23,38 +23,21 @@
final String help;
final String? abbr;
final String? defaultsTo;
+ final String? valueHelp;
final List<String>? allowed;
final Map<String, String>? allowedHelp;
- Option(
- {required this.flag,
- required this.help,
- this.abbr,
- this.defaultsTo,
- this.allowed,
- this.allowedHelp});
+ const Option({
+ required this.flag,
+ required this.help,
+ this.abbr,
+ this.defaultsTo,
+ this.valueHelp,
+ this.allowed,
+ this.allowedHelp,
+ });
}
-final Map<String, Option> commonOptions = {
- 'outputFile': Option(
- flag: 'output',
- abbr: 'o',
- help: '''
-Write the output to <file name>.
-This can be an absolute or relative path.
-''',
- ),
- 'verbosity': Option(
- flag: 'verbosity',
- help: '''
-Sets the verbosity level of the compilation.
-''',
- defaultsTo: Verbosity.defaultValue,
- allowed: Verbosity.allowedValues,
- allowedHelp: Verbosity.allowedValuesHelp,
- ),
-};
-
bool checkFile(String sourcePath) {
if (!FileSystemEntity.isFileSync(sourcePath)) {
stderr.writeln('"$sourcePath" file not found.');
@@ -117,19 +100,24 @@
}) : super(commandName, 'Compile Dart $help', verbose) {
argParser
..addOption(
- commonOptions['outputFile']!.flag,
- help: commonOptions['outputFile']!.help,
- abbr: commonOptions['outputFile']!.abbr,
+ outputFileOption.flag,
+ help: outputFileOption.help,
+ abbr: outputFileOption.abbr,
)
..addOption(
- commonOptions['verbosity']!.flag,
- help: commonOptions['verbosity']!.help,
- abbr: commonOptions['verbosity']!.abbr,
- defaultsTo: commonOptions['verbosity']!.defaultsTo,
- allowed: commonOptions['verbosity']!.allowed,
- allowedHelp: commonOptions['verbosity']!.allowedHelp,
+ verbosityOption.flag,
+ help: verbosityOption.help,
+ abbr: verbosityOption.abbr,
+ defaultsTo: verbosityOption.defaultsTo,
+ allowed: verbosityOption.allowed,
+ allowedHelp: verbosityOption.allowedHelp,
+ )
+ ..addMultiOption(
+ defineOption.flag,
+ help: defineOption.help,
+ abbr: defineOption.abbr,
+ valueHelp: defineOption.valueHelp,
);
-
addExperimentalFlags(argParser, verbose);
}
@@ -160,7 +148,7 @@
}
// Determine output file name.
- String? outputFile = args[commonOptions['outputFile']!.flag];
+ String? outputFile = args[outputFileOption.flag];
if (outputFile == null) {
final inputWithoutDart = sourcePath.endsWith('.dart')
? sourcePath.substring(0, sourcePath.length - 5)
@@ -169,12 +157,13 @@
}
final enabledExperiments = args.enabledExperiments;
+ final environmentVars = args['define'] ?? <String, String>{};
// Build arguments.
List<String> buildArgs = [];
buildArgs.add('--snapshot-kind=$formatName');
buildArgs.add('--snapshot=${path.canonicalize(outputFile)}');
- String? verbosity = args[commonOptions['verbosity']!.flag];
+ String? verbosity = args[verbosityOption.flag];
buildArgs.add('--verbosity=$verbosity');
if (enabledExperiments.isNotEmpty) {
@@ -183,6 +172,9 @@
if (verbose) {
buildArgs.add('-v');
}
+ if (environmentVars.isNotEmpty) {
+ buildArgs.addAll(environmentVars.map<String>((e) => '--define=$e'));
+ }
buildArgs.add(path.canonicalize(sourcePath));
// Add the training arguments.
@@ -214,21 +206,24 @@
}) : super(commandName, 'Compile Dart $help', verbose) {
argParser
..addOption(
- commonOptions['outputFile']!.flag,
- help: commonOptions['outputFile']!.help,
- abbr: commonOptions['outputFile']!.abbr,
+ outputFileOption.flag,
+ help: outputFileOption.help,
+ abbr: outputFileOption.abbr,
)
..addOption(
- commonOptions['verbosity']!.flag,
- help: commonOptions['verbosity']!.help,
- abbr: commonOptions['verbosity']!.abbr,
- defaultsTo: commonOptions['verbosity']!.defaultsTo,
- allowed: commonOptions['verbosity']!.allowed,
- allowedHelp: commonOptions['verbosity']!.allowedHelp,
+ verbosityOption.flag,
+ help: verbosityOption.help,
+ abbr: verbosityOption.abbr,
+ defaultsTo: verbosityOption.defaultsTo,
+ allowed: verbosityOption.allowed,
+ allowedHelp: verbosityOption.allowedHelp,
)
- ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
-Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
-For example: dart compile $commandName -Da=1,b=2 main.dart''')
+ ..addMultiOption(
+ defineOption.flag,
+ help: defineOption.help,
+ abbr: defineOption.abbr,
+ valueHelp: defineOption.valueHelp,
+ )
..addFlag('enable-asserts',
negatable: false, help: 'Enable assert statements.')
..addOption('packages',
@@ -307,9 +302,36 @@
}
abstract class CompileSubcommandCommand extends DartdevCommand {
+ final outputFileOption = Option(
+ flag: 'output',
+ abbr: 'o',
+ help: '''
+Write the output to <file name>.
+This can be an absolute or relative path.
+''',
+ );
+ final verbosityOption = Option(
+ flag: 'verbosity',
+ help: '''
+Sets the verbosity level of the compilation.
+''',
+ defaultsTo: Verbosity.defaultValue,
+ allowed: Verbosity.allowedValues,
+ allowedHelp: Verbosity.allowedValuesHelp,
+ );
+ late final Option defineOption;
+
CompileSubcommandCommand(String name, String description, bool verbose,
{bool hidden = false})
- : super(name, description, verbose, hidden: hidden);
+ : defineOption = Option(
+ flag: 'define',
+ abbr: 'D',
+ valueHelp: 'key=value',
+ help: '''
+Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
+For example: dart compile $name -Da=1,b=2 main.dart''',
+ ),
+ super(name, description, verbose, hidden: hidden);
}
class CompileCommand extends DartdevCommand {
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index aea2ecb..dffebaa 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -64,7 +64,7 @@
}
@override
- FutureOr<int> run() async {
+ Future<int> run() async {
final args = argResults!;
var dryRun = args['dry-run'];
var inTestMode = args['compare-to-golden'];
@@ -112,6 +112,12 @@
}
});
+ server.onCrash.then((_) {
+ log.stderr('The analysis server shut down unexpectedly.');
+ log.stdout('Please report this at dartbug.com.');
+ io.exit(1);
+ });
+
Future<Map<String, BulkFix>> _applyAllEdits() async {
var detailsMap = <String, BulkFix>{};
List<SourceFileEdit> edits;
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index 82478e9..bac5e34 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -12,7 +12,7 @@
const int compileErrorExitCode = 64;
void main() {
- group('compile', defineCompileTests, timeout: longTimeout);
+ group('compile -', defineCompileTests, timeout: longTimeout);
}
const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
@@ -99,6 +99,37 @@
expect(result.exitCode, 0);
});
+ test('Compile and run jit snapshot with environment variables', () async {
+ final p = project(mainSrc: '''
+ void main() {
+ print('1: ' + const String.fromEnvironment('foo'));
+ print('2: ' + const String.fromEnvironment('bar'));
+ }''');
+ final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+ final outFile = path.canonicalize(path.join(p.dirPath, 'main.jit'));
+
+ var result = await p.run([
+ 'compile',
+ 'jit-snapshot',
+ '-Dfoo=bar',
+ '--define=bar=foo',
+ '-o',
+ outFile,
+ '-v',
+ inFile,
+ ]);
+ expect(result.stderr, isEmpty);
+ expect(result.exitCode, 0);
+ final file = File(outFile);
+ expect(file.existsSync(), true, reason: 'File not found: $outFile');
+
+ result = await p.run(['run', 'main.jit']);
+
+ // Ensure the -D and --define arguments were processed correctly.
+ expect(result.stdout, contains('1: bar'));
+ expect(result.stdout, contains('2: foo'));
+ });
+
test('Compile and run executable', () async {
final p = project(mainSrc: 'void main() { print("I love executables"); }');
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d7d2208..9fbb7d0 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -4167,8 +4167,6 @@
!IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
RETURN_TYPE_ERROR(Z, object, 'TypedData');
}
- T->DecrementNoSafepointScopeDepth();
- END_NO_CALLBACK_SCOPE(T);
if (FLAG_verify_acquired_data) {
const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
WeakTable* table = I->group()->api_state()->acquired_table();
@@ -4180,6 +4178,8 @@
table->SetValue(obj.ptr(), 0); // Delete entry from table.
delete ad;
}
+ T->DecrementNoSafepointScopeDepth();
+ END_NO_CALLBACK_SCOPE(T);
return Api::Success();
}
diff --git a/tools/VERSION b/tools/VERSION
index f2a49b1..46a6247 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 170
+PRERELEASE 171
PRERELEASE_PATCH 0
\ No newline at end of file