From e623e291a79ec440783f4bd2ed3f9d87c03cc55e Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Thu, 27 Jul 2023 19:29:22 +0000 Subject: [PATCH] Add TypeSystemImpl.isValidExtensionTypeSuperinterface() Change-Id: Ic2d40f1faab9851b3f4f9ee7605dabf197dca433 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316640 Reviewed-by: Samuel Rawlins Commit-Queue: Konstantin Shcheglov --- .../lib/src/dart/element/type_system.dart | 20 +++++ .../test/generated/elements_types_mixin.dart | 19 ++++ .../test/src/dart/element/test_all.dart | 2 + .../src/dart/element/type_system_test.dart | 86 +++++++++++++++++++ 4 files changed, 127 insertions(+) create mode 100644 pkg/analyzer/test/src/dart/element/type_system_test.dart diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart index bd98d34f084..a67d1ea2876 100644 --- a/pkg/analyzer/lib/src/dart/element/type_system.dart +++ b/pkg/analyzer/lib/src/dart/element/type_system.dart @@ -1450,6 +1450,26 @@ class TypeSystemImpl implements TypeSystem { return false; } + /// Whether [type] is a valid superinterface for an extension type. + bool isValidExtensionTypeSuperinterface(DartType type) { + if (type is! InterfaceType) { + return false; + } + + if (type.nullabilitySuffix == NullabilitySuffix.question) { + return false; + } + + if (type.isDartAsyncFutureOr || + type.isDartCoreFunction || + type.isDartCoreNull || + type.isDartCoreRecord) { + return false; + } + + return true; + } + /// See `15.2 Super-bounded types` in the language specification. TypeBoundedResult isWellBounded( DartType type, { diff --git a/pkg/analyzer/test/generated/elements_types_mixin.dart b/pkg/analyzer/test/generated/elements_types_mixin.dart index 8c058fc8db9..164510b80c4 100644 --- a/pkg/analyzer/test/generated/elements_types_mixin.dart +++ b/pkg/analyzer/test/generated/elements_types_mixin.dart @@ -229,6 +229,25 @@ mixin ElementsTypesMixin { return ConstFieldElementImpl(name, 0)..isEnumConstant = true; } + ExtensionTypeElementImpl extensionType( + String name, { + String representationName = 'it', + required DartType representationType, + List typeParameters = const [], + List interfaces = const [], + }) { + final element = ExtensionTypeElementImpl(name, -1); + element.enclosingElement = testLibrary.definingCompilationUnit; + element.typeParameters = typeParameters; + element.interfaces = interfaces; + + final field = FieldElementImpl(representationName, -1); + field.type = representationType; + element.fields = [field]; + + return element; + } + FunctionTypeImpl functionType({ required List typeFormals, required List parameters, diff --git a/pkg/analyzer/test/src/dart/element/test_all.dart b/pkg/analyzer/test/src/dart/element/test_all.dart index c38a9e40511..1f8de8b69a0 100644 --- a/pkg/analyzer/test/src/dart/element/test_all.dart +++ b/pkg/analyzer/test/src/dart/element/test_all.dart @@ -34,6 +34,7 @@ import 'type_bounded_test.dart' as type_bounded; import 'type_constraint_gatherer_test.dart' as type_constraint_gatherer; import 'type_parameter_element_test.dart' as type_parameter_element; import 'type_references_any_test.dart' as type_references_any; +import 'type_system_test.dart' as type_system; import 'type_visitor_test.dart' as type_visitor; import 'upper_lower_bound_test.dart' as upper_bound; @@ -70,6 +71,7 @@ main() { type_constraint_gatherer.main(); type_parameter_element.main(); type_references_any.main(); + type_system.main(); type_visitor.main(); upper_bound.main(); }, name: 'element'); diff --git a/pkg/analyzer/test/src/dart/element/type_system_test.dart b/pkg/analyzer/test/src/dart/element/type_system_test.dart new file mode 100644 index 00000000000..b3ba7439e1e --- /dev/null +++ b/pkg/analyzer/test/src/dart/element/type_system_test.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'package:analyzer/dart/element/type.dart'; +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +import '../../../generated/type_system_base.dart'; + +main() { + defineReflectiveSuite(() { + defineReflectiveTests(IsValidExtensionTypeSuperinterfaceTest); + }); +} + +@reflectiveTest +class IsValidExtensionTypeSuperinterfaceTest extends AbstractTypeSystemTest { + test_functionType() { + _assertNotValid( + functionTypeNone(returnType: voidNone), + ); + } + + test_interfaceType() { + _assertValid(numNone); + } + + test_interfaceType_extensionType() { + final element = extensionType('A', representationType: intNone); + _assertValid( + interfaceTypeNone(element), + ); + } + + test_interfaceType_function() { + _assertNotValid(functionNone); + } + + test_interfaceType_futureOr() { + _assertNotValid( + futureOrNone(intNone), + ); + } + + test_interfaceType_null() { + _assertNotValid(nullNone); + } + + test_interfaceType_nullable() { + _assertNotValid(numQuestion); + } + + test_interfaceType_record() { + _assertNotValid(recordNone); + } + + test_recordType() { + _assertNotValid( + recordTypeNone( + positionalTypes: [intNone, stringNone], + ), + ); + } + + test_topType() { + _assertNotValid(dynamicType); + _assertNotValid(voidNone); + _assertNotValid(objectQuestion); + } + + test_typeParameterType() { + final T = typeParameter('T'); + _assertNotValid( + typeParameterTypeNone(T), + ); + } + + void _assertNotValid(DartType type) { + expect(typeSystem.isValidExtensionTypeSuperinterface(type), isFalse); + } + + void _assertValid(DartType type) { + expect(typeSystem.isValidExtensionTypeSuperinterface(type), isTrue); + } +}