mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
Replace DartType.resolveToBound() with TypeSystem.resolveToBound()
Bug: https://github.com/dart-lang/sdk/issues/48952 Change-Id: I38add3e0d633f947640283eda46b5399f4559ef8 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243702 Reviewed-by: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
56765625e0
commit
d78797d014
|
@ -158,13 +158,13 @@ class FeatureComputer {
|
|||
/// offset is within the given [node], or `null` if the context does not
|
||||
/// impose any type.
|
||||
DartType? computeContextType(AstNode node, int offset) {
|
||||
var type = node
|
||||
.accept(_ContextTypeVisitor(typeProvider, offset))
|
||||
?.resolveToBound(typeProvider.objectType);
|
||||
if (type == null || type.isDynamic) {
|
||||
final contextType = node.accept(
|
||||
_ContextTypeVisitor(typeProvider, offset),
|
||||
);
|
||||
if (contextType == null || contextType.isDynamic) {
|
||||
return null;
|
||||
}
|
||||
return type;
|
||||
return typeSystem.resolveToBound(contextType);
|
||||
}
|
||||
|
||||
/// Return the element kind used to compute relevance for the given [element].
|
||||
|
|
|
@ -42,7 +42,10 @@ class TypeMemberContributor extends DartCompletionContributor {
|
|||
}
|
||||
|
||||
// Determine the target expression's type.
|
||||
var type = expression.staticType?.resolveToBound(request.objectType);
|
||||
final expressionType = expression.staticType;
|
||||
var type = expressionType != null
|
||||
? request.libraryElement.typeSystem.resolveToBound(expressionType)
|
||||
: null;
|
||||
if (type == null || type.isDynamic) {
|
||||
// If the expression does not provide a good type, then attempt to get a
|
||||
// better type from the element.
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* Deprecated `ParameterElement.isNotOptional`, use `isRequired` instead.
|
||||
* Deprecated `ResourceProviderMixin.newFile2`, use `newFile` instead.
|
||||
* Deprecated `ResourceProviderMixin.newAnalysisOptionsYamlFile2`, use `newAnalysisOptionsYamlFile` instead.
|
||||
* Deprecated `DartType.resolveToBound`, use `TypeSystem.resolveToBound` instead.
|
||||
|
||||
## 4.0.0
|
||||
* Removed deprecated `UriKind` and `Source.uriKind`.
|
||||
|
|
|
@ -176,6 +176,7 @@ abstract class DartType {
|
|||
///
|
||||
/// For any other type, returns `this`. Applies recursively -- if the bound is
|
||||
/// itself a type parameter, that is resolved too.
|
||||
@Deprecated('Use TypeSystem.resolveToBound() instead')
|
||||
DartType resolveToBound(DartType objectType);
|
||||
}
|
||||
|
||||
|
|
|
@ -1063,6 +1063,7 @@ abstract class TypeImpl implements DartType {
|
|||
return false;
|
||||
}
|
||||
|
||||
@Deprecated('Use TypeSystem.resolveToBound() instead')
|
||||
@override
|
||||
DartType resolveToBound(DartType objectType) => this;
|
||||
|
||||
|
@ -1201,6 +1202,7 @@ class TypeParameterTypeImpl extends TypeImpl implements TypeParameterType {
|
|||
return parameters.contains(element);
|
||||
}
|
||||
|
||||
@Deprecated('Use TypeSystem.resolveToBound() instead')
|
||||
@override
|
||||
DartType resolveToBound(DartType objectType) {
|
||||
final promotedBound = this.promotedBound;
|
||||
|
|
|
@ -1468,26 +1468,26 @@ class TypeSystemImpl implements TypeSystem {
|
|||
@override
|
||||
DartType resolveToBound(DartType type) {
|
||||
if (type is TypeParameterTypeImpl) {
|
||||
var element = type.element;
|
||||
final promotedBound = type.promotedBound;
|
||||
if (promotedBound != null) {
|
||||
return resolveToBound(promotedBound);
|
||||
}
|
||||
|
||||
var bound = element.bound;
|
||||
final bound = type.element.bound;
|
||||
if (bound == null) {
|
||||
return typeProvider.objectType;
|
||||
return isNonNullableByDefault ? objectQuestion : objectStar;
|
||||
}
|
||||
|
||||
NullabilitySuffix nullabilitySuffix = type.nullabilitySuffix;
|
||||
NullabilitySuffix newNullabilitySuffix;
|
||||
if (nullabilitySuffix == NullabilitySuffix.question ||
|
||||
bound.nullabilitySuffix == NullabilitySuffix.question) {
|
||||
newNullabilitySuffix = NullabilitySuffix.question;
|
||||
} else if (nullabilitySuffix == NullabilitySuffix.star ||
|
||||
bound.nullabilitySuffix == NullabilitySuffix.star) {
|
||||
newNullabilitySuffix = NullabilitySuffix.star;
|
||||
} else {
|
||||
newNullabilitySuffix = NullabilitySuffix.none;
|
||||
}
|
||||
final resolved = resolveToBound(bound) as TypeImpl;
|
||||
|
||||
final newNullabilitySuffix = uniteNullabilities(
|
||||
uniteNullabilities(
|
||||
type.nullabilitySuffix,
|
||||
bound.nullabilitySuffix,
|
||||
),
|
||||
resolved.nullabilitySuffix,
|
||||
);
|
||||
|
||||
var resolved = resolveToBound(bound) as TypeImpl;
|
||||
return resolved.withNullability(newNullabilitySuffix);
|
||||
}
|
||||
|
||||
|
|
|
@ -233,13 +233,6 @@ class BinaryExpressionResolver {
|
|||
contextType: contextType);
|
||||
}
|
||||
|
||||
/// If the given [type] is a type parameter, resolve it to the type that should
|
||||
/// be used when looking up members. Otherwise, return the original type.
|
||||
///
|
||||
/// TODO(scheglov) this is duplicate
|
||||
DartType _resolveTypeParameter(DartType type) =>
|
||||
type.resolveToBound(_typeProvider.objectType);
|
||||
|
||||
void _resolveUnsupportedOperator(BinaryExpressionImpl node,
|
||||
{required DartType? contextType}) {
|
||||
node.leftOperand.accept(_resolver);
|
||||
|
@ -304,7 +297,7 @@ class BinaryExpressionResolver {
|
|||
}
|
||||
|
||||
var leftType = leftOperand.typeOrThrow;
|
||||
leftType = _resolveTypeParameter(leftType);
|
||||
leftType = _typeSystem.resolveToBound(leftType);
|
||||
|
||||
if (identical(leftType, NeverTypeImpl.instance)) {
|
||||
_resolver.errorReporter.reportErrorForNode(
|
||||
|
@ -354,7 +347,7 @@ class BinaryExpressionResolver {
|
|||
leftType = leftOperand.extendedType!;
|
||||
} else {
|
||||
leftType = leftOperand.typeOrThrow;
|
||||
leftType = _resolveTypeParameter(leftType);
|
||||
leftType = _typeSystem.resolveToBound(leftType);
|
||||
}
|
||||
|
||||
if (identical(leftType, NeverTypeImpl.instance)) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:analyzer/dart/element/element.dart';
|
|||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/element/type_provider.dart';
|
||||
import 'package:analyzer/src/dart/element/type_system.dart';
|
||||
import 'package:analyzer/src/dart/resolver/type_property_resolver.dart';
|
||||
import 'package:analyzer/src/generated/resolver.dart';
|
||||
|
||||
|
@ -21,6 +22,8 @@ class CommentReferenceResolver {
|
|||
CommentReferenceResolver(this._typeProvider, this._resolver)
|
||||
: _typePropertyResolver = _resolver.typePropertyResolver;
|
||||
|
||||
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
|
||||
|
||||
/// Resolves [commentReference].
|
||||
void resolve(CommentReference commentReference) {
|
||||
_resolver.errorReporter.lockLevel++;
|
||||
|
@ -150,8 +153,9 @@ class CommentReferenceResolver {
|
|||
if (enclosingExtension == null) {
|
||||
return null;
|
||||
}
|
||||
var extendedType = enclosingExtension.extendedType
|
||||
.resolveToBound(_typeProvider.objectType);
|
||||
var extendedType = _typeSystem.resolveToBound(
|
||||
enclosingExtension.extendedType,
|
||||
);
|
||||
if (extendedType is InterfaceType) {
|
||||
enclosingType = extendedType;
|
||||
} else if (extendedType is FunctionType) {
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:analyzer/src/dart/ast/ast.dart';
|
|||
import 'package:analyzer/src/dart/element/element.dart';
|
||||
import 'package:analyzer/src/dart/element/type.dart';
|
||||
import 'package:analyzer/src/dart/element/type_schema.dart';
|
||||
import 'package:analyzer/src/dart/element/type_system.dart';
|
||||
import 'package:analyzer/src/dart/resolver/assignment_expression_resolver.dart';
|
||||
import 'package:analyzer/src/dart/resolver/typed_literal_resolver.dart';
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
|
@ -22,6 +23,8 @@ class ForResolver {
|
|||
required ResolverVisitor resolver,
|
||||
}) : _resolver = resolver;
|
||||
|
||||
TypeSystemImpl get _typeSystem => _resolver.typeSystem;
|
||||
|
||||
void resolveElement(ForElementImpl node, CollectionLiteralContext? context) {
|
||||
var forLoopParts = node.forLoopParts;
|
||||
void visitBody() {
|
||||
|
@ -57,8 +60,7 @@ class ForResolver {
|
|||
DartType? _computeForEachElementType(Expression iterable, bool isAsync) {
|
||||
var iterableType = iterable.staticType;
|
||||
if (iterableType == null) return null;
|
||||
iterableType =
|
||||
iterableType.resolveToBound(_resolver.typeProvider.objectType);
|
||||
iterableType = _typeSystem.resolveToBound(iterableType);
|
||||
|
||||
ClassElement iteratedElement = isAsync
|
||||
? _resolver.typeProvider.streamElement
|
||||
|
|
|
@ -868,15 +868,6 @@ class MethodInvocationResolver {
|
|||
}
|
||||
}
|
||||
|
||||
/// If the given [type] is a type parameter, replace with its bound.
|
||||
/// Otherwise, return the original type.
|
||||
DartType _resolveTypeParameter(DartType type) {
|
||||
if (type is TypeParameterType) {
|
||||
return type.resolveToBound(_resolver.typeProvider.objectType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/// We have identified that [node] is not a real [MethodInvocation],
|
||||
/// because it does not invoke a method, but instead invokes the result
|
||||
/// of a getter execution, or implicitly invokes the `call` method of
|
||||
|
@ -885,7 +876,7 @@ class MethodInvocationResolver {
|
|||
void _rewriteAsFunctionExpressionInvocation(
|
||||
MethodInvocationImpl node, DartType getterReturnType,
|
||||
{required DartType? contextType}) {
|
||||
var targetType = _resolveTypeParameter(getterReturnType);
|
||||
var targetType = _typeSystem.resolveToBound(getterReturnType);
|
||||
_inferenceHelper.recordStaticType(node.methodName, targetType,
|
||||
contextType: contextType);
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ class PropertyElementResolver {
|
|||
}
|
||||
|
||||
var targetType = target.typeOrThrow;
|
||||
targetType = _resolveTypeParameter(targetType);
|
||||
targetType = _typeSystem.resolveToBound(targetType);
|
||||
|
||||
if (targetType.isVoid) {
|
||||
// TODO(scheglov) Report directly in TypePropertyResolver?
|
||||
|
@ -815,15 +815,6 @@ class PropertyElementResolver {
|
|||
);
|
||||
}
|
||||
|
||||
/// If the given [type] is a type parameter, replace with its bound.
|
||||
/// Otherwise, return the original type.
|
||||
DartType _resolveTypeParameter(DartType type) {
|
||||
if (type is TypeParameterType) {
|
||||
return type.resolveToBound(_resolver.typeProvider.objectType);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
PropertyElementResolverResult _toIndexResult(ResolutionResult result) {
|
||||
var readElement = result.getter;
|
||||
var writeElement = result.setter;
|
||||
|
|
|
@ -282,7 +282,7 @@ class TypePropertyResolver {
|
|||
bool ifNullSafe = false,
|
||||
}) {
|
||||
if (_typeSystem.isNonNullableByDefault ? ifNullSafe : ifLegacy) {
|
||||
return type.resolveToBound(_typeProvider.objectType);
|
||||
return _typeSystem.resolveToBound(type);
|
||||
} else {
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -2393,7 +2393,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
|
|||
// The object being iterated has to implement Iterable<T> for some T that
|
||||
// is assignable to the variable's type.
|
||||
// TODO(rnystrom): Move this into mostSpecificTypeArgument()?
|
||||
iterableType = iterableType.resolveToBound(_typeProvider.objectType);
|
||||
iterableType = typeSystem.resolveToBound(iterableType);
|
||||
|
||||
var requiredSequenceType = awaitKeyword != null
|
||||
? _typeProvider.streamDynamicType
|
||||
|
|
|
@ -789,6 +789,7 @@ class FunctionTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(types[1], stringNone);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound() {
|
||||
var type = functionTypeNone(
|
||||
typeFormals: [],
|
||||
|
@ -1235,6 +1236,7 @@ class InterfaceTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(0 == typeA.hashCode, isFalse);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound() {
|
||||
var type = interfaceTypeStar(ElementFactory.classElement2('A'));
|
||||
|
||||
|
@ -1414,6 +1416,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.element, element);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1422,6 +1425,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), interfaceTypeStar(classS));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_nullableInner() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1430,6 +1434,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), same(element.bound));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_nullableInnerOuter() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1439,6 +1444,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), same(element.bound));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_nullableInnerStarOuter() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1449,6 +1455,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
type.resolveToBound(objectNone), equals(interfaceTypeQuestion(classS)));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_nullableOuter() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1459,6 +1466,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
type.resolveToBound(objectNone), equals(interfaceTypeQuestion(classS)));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_starInner() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1467,6 +1475,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), same(element.bound));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_starInnerNullableOuter() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1476,6 +1485,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), same(element.bound));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_bound_starOuter() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl element = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1485,6 +1495,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(type.resolveToBound(objectNone), interfaceTypeStar(classS));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_nestedBound() {
|
||||
ClassElementImpl classS = class_(name: 'A');
|
||||
TypeParameterElementImpl elementE = TypeParameterElementImpl('E', -1);
|
||||
|
@ -1496,6 +1507,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(typeF.resolveToBound(objectNone), interfaceTypeStar(classS));
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_promotedBound_interfaceType() {
|
||||
var A = class_(name: 'A');
|
||||
var A_none = interfaceTypeNone(A);
|
||||
|
@ -1505,6 +1517,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(T_A.resolveToBound(objectQuestion), A_none);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_promotedBound_typeParameterType_interfaceType() {
|
||||
var A = class_(name: 'A');
|
||||
var A_none = interfaceTypeNone(A);
|
||||
|
@ -1517,6 +1530,7 @@ class TypeParameterTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(U_T.resolveToBound(objectQuestion), A_none);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound_unbound() {
|
||||
TypeParameterTypeImpl type =
|
||||
typeParameterTypeStar(TypeParameterElementImpl('E', -1));
|
||||
|
@ -1597,6 +1611,7 @@ class VoidTypeImplTest extends AbstractTypeSystemTest {
|
|||
expect(_voidType.isVoid, isTrue);
|
||||
}
|
||||
|
||||
@deprecated
|
||||
void test_resolveToBound() {
|
||||
// Returns this.
|
||||
expect(_voidType.resolveToBound(objectNone), same(_voidType));
|
||||
|
|
225
pkg/analyzer/test/src/dart/element/resolve_to_bound_test.dart
Normal file
225
pkg/analyzer/test/src/dart/element/resolve_to_bound_test.dart
Normal file
|
@ -0,0 +1,225 @@
|
|||
// 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:analyzer/dart/element/type.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../../../generated/type_system_test.dart';
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ResolveToBoundTest);
|
||||
defineReflectiveTests(ResolveToBoundWithoutNullSafetyTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ResolveToBoundTest extends AbstractTypeSystemTest {
|
||||
test_dynamic() {
|
||||
_check(dynamicType, 'dynamic');
|
||||
}
|
||||
|
||||
test_functionType() {
|
||||
_check(
|
||||
functionTypeNone(returnType: voidNone),
|
||||
'void Function()',
|
||||
);
|
||||
}
|
||||
|
||||
test_interfaceType() {
|
||||
_check(intNone, 'int');
|
||||
_check(intQuestion, 'int?');
|
||||
_check(intStar, 'int*');
|
||||
}
|
||||
|
||||
test_typeParameter_bound() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: intNone),
|
||||
),
|
||||
'int',
|
||||
);
|
||||
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: intQuestion),
|
||||
),
|
||||
'int?',
|
||||
);
|
||||
|
||||
_check(
|
||||
typeParameterTypeStar(
|
||||
typeParameter('T', bound: intStar),
|
||||
),
|
||||
'int*',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_bound_functionType() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter(
|
||||
'T',
|
||||
bound: functionTypeNone(
|
||||
returnType: voidNone,
|
||||
),
|
||||
),
|
||||
),
|
||||
'void Function()',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nested_noBound() {
|
||||
final T = typeParameter('T');
|
||||
final U = typeParameter(
|
||||
'U',
|
||||
bound: typeParameterTypeNone(T),
|
||||
);
|
||||
_check(typeParameterTypeNone(U), 'Object?');
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nested_none() {
|
||||
final T = typeParameter('T', bound: intNone);
|
||||
final U = typeParameter(
|
||||
'U',
|
||||
bound: typeParameterTypeNone(T),
|
||||
);
|
||||
_check(typeParameterTypeNone(U), 'int');
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nested_none_outerNullable() {
|
||||
final T = typeParameter('T', bound: intNone);
|
||||
final U = typeParameter(
|
||||
'U',
|
||||
bound: typeParameterTypeQuestion(T),
|
||||
);
|
||||
_check(typeParameterTypeNone(U), 'int?');
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nested_question() {
|
||||
final T = typeParameter('T', bound: intQuestion);
|
||||
final U = typeParameter(
|
||||
'U',
|
||||
bound: typeParameterTypeNone(T),
|
||||
);
|
||||
_check(typeParameterTypeNone(U), 'int?');
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nullableInner() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: intQuestion),
|
||||
),
|
||||
'int?',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nullableInnerOuter() {
|
||||
_check(
|
||||
typeParameterTypeQuestion(
|
||||
typeParameter('T', bound: intQuestion),
|
||||
),
|
||||
'int?',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_bound_nullableOuter() {
|
||||
_check(
|
||||
typeParameterTypeQuestion(
|
||||
typeParameter('T', bound: intNone),
|
||||
),
|
||||
'int?',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_noBound() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T'),
|
||||
),
|
||||
'Object?',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_promotedBound() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: numNone),
|
||||
promotedBound: intNone,
|
||||
),
|
||||
'int',
|
||||
);
|
||||
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: numQuestion),
|
||||
promotedBound: intQuestion,
|
||||
),
|
||||
'int?',
|
||||
);
|
||||
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T', bound: numStar),
|
||||
promotedBound: intStar,
|
||||
),
|
||||
'int*',
|
||||
);
|
||||
}
|
||||
|
||||
test_void() {
|
||||
_check(voidNone, 'void');
|
||||
}
|
||||
|
||||
void _check(DartType type, String expectedStr) {
|
||||
var result = typeSystem.resolveToBound(type);
|
||||
var resultStr = _typeString(result);
|
||||
expect(resultStr, expectedStr);
|
||||
}
|
||||
|
||||
String _typeString(DartType type) {
|
||||
return type.getDisplayString(withNullability: true);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ResolveToBoundWithoutNullSafetyTest
|
||||
extends AbstractTypeSystemWithoutNullSafetyTest {
|
||||
test_dynamic() {
|
||||
_check(dynamicType, 'dynamic');
|
||||
}
|
||||
|
||||
test_typeParameter_bound() {
|
||||
_check(
|
||||
typeParameterTypeStar(
|
||||
typeParameter('T', bound: intStar),
|
||||
),
|
||||
'int*',
|
||||
);
|
||||
}
|
||||
|
||||
test_typeParameter_noBound() {
|
||||
_check(
|
||||
typeParameterTypeNone(
|
||||
typeParameter('T'),
|
||||
),
|
||||
'Object*',
|
||||
);
|
||||
}
|
||||
|
||||
test_void() {
|
||||
_check(voidNone, 'void');
|
||||
}
|
||||
|
||||
void _check(DartType type, String expectedStr) {
|
||||
var result = typeSystem.resolveToBound(type);
|
||||
var resultStr = _typeString(result);
|
||||
expect(resultStr, expectedStr);
|
||||
}
|
||||
|
||||
String _typeString(DartType type) {
|
||||
return type.getDisplayString(withNullability: true);
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import 'normalize_type_test.dart' as normalize_type;
|
|||
import 'nullability_eliminator_test.dart' as nullability_eliminator;
|
||||
import 'nullable_test.dart' as nullable;
|
||||
import 'replace_top_bottom_test.dart' as replace_top_bottom;
|
||||
import 'resolve_to_bound_test.dart' as resolve_to_bound;
|
||||
import 'runtime_type_equality_test.dart' as runtime_type_equality;
|
||||
import 'subtype_test.dart' as subtype;
|
||||
import 'top_merge_test.dart' as top_merge;
|
||||
|
@ -52,6 +53,7 @@ main() {
|
|||
nullability_eliminator.main();
|
||||
nullable.main();
|
||||
replace_top_bottom.main();
|
||||
resolve_to_bound.main();
|
||||
runtime_type_equality.main();
|
||||
subtype.main();
|
||||
top_merge.main();
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:analyzer/dart/ast/ast.dart';
|
|||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer/dart/ast/visitor.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/dart/element/nullability_suffix.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:analyzer/dart/element/type_provider.dart';
|
||||
import 'package:analyzer/dart/element/type_system.dart';
|
||||
|
@ -280,8 +281,7 @@ class EdgeBuilder extends GeneralizingAstVisitor<DecoratedType>
|
|||
if (targetType != null) {
|
||||
var enclosingElement = baseElement!.enclosingElement;
|
||||
if (enclosingElement is ClassElement) {
|
||||
if (targetType.type!.resolveToBound(typeProvider.dynamicType)
|
||||
is InterfaceType &&
|
||||
if (targetType.type.explicitBound is InterfaceType &&
|
||||
enclosingElement.typeParameters.isNotEmpty) {
|
||||
substitution = _decoratedClassHierarchy!
|
||||
.asInstanceOf(targetType, enclosingElement)
|
||||
|
@ -3971,3 +3971,14 @@ class _ConditionInfo {
|
|||
trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
|
||||
falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
|
||||
}
|
||||
|
||||
extension on DartType? {
|
||||
DartType? get explicitBound {
|
||||
final self = this;
|
||||
if (self is TypeParameterType &&
|
||||
self.nullabilitySuffix == NullabilitySuffix.star) {
|
||||
return self.element.bound.explicitBound;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue