Skip to content

Commit

Permalink
NullabilityEliminator - Never to Null*, remove required from formal p…
Browse files Browse the repository at this point in the history
…arameters.

Change-Id: I3ad2cf15c2ed1e8eb347ac84c9dc401e807e2e7e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/127203
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
  • Loading branch information
scheglov authored and commit-bot@chromium.org committed Dec 6, 2019
1 parent 310c2eb commit f024d9d
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 30 deletions.
3 changes: 2 additions & 1 deletion pkg/analyzer/lib/src/dart/element/member.dart
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ abstract class Member implements Element {
/// Otherwise, return the type unchanged.
DartType _toLegacyType(DartType type) {
if (isLegacy) {
return NullabilityEliminator.perform(type);
var typeProvider = declaration.library.typeProvider;
return NullabilityEliminator.perform(typeProvider, type);
} else {
return type;
}
Expand Down
50 changes: 30 additions & 20 deletions pkg/analyzer/lib/src/dart/element/nullability_eliminator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_algebra.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/dart/element/type_visitor.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';

class NullabilityEliminator extends DartTypeVisitor<DartType> {
final TypeProviderImpl _typeProvider;

int _counter = 0;

NullabilityEliminator(this._typeProvider);

@override
DartType defaultDartType(DartType type) {
throw UnimplementedError('(${type.runtimeType}) $type');
Expand All @@ -35,10 +42,7 @@ class NullabilityEliminator extends DartTypeVisitor<DartType> {

type = _freshTypeParameters(type);

var parameters = type.parameters.map((parameter) {
var type = visit(parameter.type);
return _parameterElement(parameter, type);
}).toList();
var parameters = type.parameters.map(_parameterElement).toList();

var returnType = visit(type.returnType);
var typeArguments = type.typeArguments.map(visit).toList();
Expand Down Expand Up @@ -79,7 +83,8 @@ class NullabilityEliminator extends DartTypeVisitor<DartType> {

@override
DartType visitNeverType(NeverTypeImpl type) {
return type.withNullability(NullabilitySuffix.star);
_counter++;
return _typeProvider.nullStar;
}

@override
Expand Down Expand Up @@ -159,28 +164,33 @@ class NullabilityEliminator extends DartTypeVisitor<DartType> {
}
}

/// If the [type] itself, or any of its components, has any nullability,
/// return a new type with legacy nullability suffixes. Otherwise return the
/// original instance.
static T perform<T extends DartType>(T type) {
if (type == null) {
return type;
}
ParameterElementImpl _parameterElement(ParameterElement parameter) {
var type = visit(parameter.type);

return NullabilityEliminator().visit(type);
}
// ignore: deprecated_member_use_from_same_package
var parameterKind = parameter.parameterKind;
if (parameter.isRequiredNamed) {
parameterKind = ParameterKind.NAMED;
_counter++;
}

static ParameterElementImpl _parameterElement(
ParameterElement parameter,
DartType type,
) {
var result = ParameterElementImpl.synthetic(
parameter.name,
type,
// ignore: deprecated_member_use_from_same_package
parameter.parameterKind,
parameterKind,
);
result.isExplicitlyCovariant = parameter.isCovariant;
return result;
}

/// If the [type] itself, or any of its components, has any nullability,
/// return a new type with legacy nullability suffixes. Otherwise return the
/// original instance.
static T perform<T extends DartType>(TypeProviderImpl typeProvider, T type) {
if (type == null) {
return type;
}

return NullabilityEliminator(typeProvider).visit(type);
}
}
9 changes: 9 additions & 0 deletions pkg/analyzer/lib/src/dart/element/type_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class TypeProviderImpl extends TypeProviderBase {
InterfaceType _symbolType;
InterfaceType _typeType;

InterfaceTypeImpl _nullStar;

InterfaceType _iterableForSetMapDisambiguation;
InterfaceType _mapForSetMapDisambiguation;

Expand Down Expand Up @@ -359,6 +361,13 @@ class TypeProviderImpl extends TypeProviderBase {
return _nullElement ??= _getClassElement(_coreLibrary, 'Null');
}

InterfaceTypeImpl get nullStar {
return _nullStar ??= nullElement.instantiate(
typeArguments: const [],
nullabilitySuffix: NullabilitySuffix.star,
);
}

@override
DartObjectImpl get nullObject {
if (_nullObject == null) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/analyzer/lib/src/generated/error_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5984,7 +5984,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
/// Otherwise, return the original type.
DartType _toLegacyType(DartType type) {
if (_isNonNullable) return type;
return NullabilityEliminator.perform(type);
return NullabilityEliminator.perform(_typeProvider, type);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion pkg/analyzer/lib/src/generated/resolver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ class ResolverVisitor extends ScopedVisitor {
/// Otherwise, return the original type.
DartType toLegacyTypeIfOptOut(DartType type) {
if (_nonNullableEnabled) return type;
return NullabilityEliminator.perform(type);
return NullabilityEliminator.perform(typeProvider, type);
}

@override
Expand Down
2 changes: 1 addition & 1 deletion pkg/analyzer/lib/src/generated/type_system.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2888,7 +2888,7 @@ class GenericInferrer {
/// Otherwise, return the original type.
DartType _toLegacyType(DartType type) {
if (isNonNullableByDefault) return type;
return NullabilityEliminator.perform(type);
return NullabilityEliminator.perform(typeProvider, type);
}

static String _formatConstraints(Iterable<_TypeConstraint> constraints) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,53 @@ class NullabilityEliminatorTest with ElementsTypesMixin {
);
}

test_functionType_parameters_named() {
_verify(
functionTypeStar(
parameters: [
namedParameter(name: 'a', type: intNone),
],
returnType: voidNone,
),
functionTypeStar(
parameters: [
namedParameter(name: 'a', type: intStar),
],
returnType: voidNone,
),
);

_verify(
functionTypeStar(
parameters: [
namedRequiredParameter(name: 'a', type: intNone),
],
returnType: voidNone,
),
functionTypeStar(
parameters: [
namedParameter(name: 'a', type: intStar),
],
returnType: voidNone,
),
);

_verify(
functionTypeStar(
parameters: [
namedRequiredParameter(name: 'a', type: intStar),
],
returnType: voidNone,
),
functionTypeStar(
parameters: [
namedParameter(name: 'a', type: intStar),
],
returnType: voidNone,
),
);
}

test_functionType_returnType() {
_verify(
functionTypeStar(returnType: intNone),
Expand Down Expand Up @@ -216,9 +263,13 @@ class NullabilityEliminatorTest with ElementsTypesMixin {
}

test_neverType() {
_verify(neverNone, neverStar);
_verify(neverQuestion, neverStar);
_verifySame(neverStar);
_verify(neverNone, nullStar);
_verify(neverQuestion, nullStar);
_verify(neverStar, nullStar);

_verify(listNone(neverNone), listStar(nullStar));
_verify(listQuestion(neverNone), listStar(nullStar));
_verify(listStar(neverNone), listStar(nullStar));
}

test_typeParameterType() {
Expand All @@ -245,20 +296,20 @@ class NullabilityEliminatorTest with ElementsTypesMixin {
}

void _verify(DartType input, DartType expected) {
var result = NullabilityEliminator.perform(input);
var result = NullabilityEliminator.perform(typeProvider, input);
expect(result, isNot(same(input)));
expect(result, expected);
}

void _verifySame(DartType input) {
var result = NullabilityEliminator.perform(input);
var result = NullabilityEliminator.perform(typeProvider, input);
expect(result, same(input));
}

void _verifyStr(DartType input, String inputStr, String expectedStr) {
expect(_typeToString(input), inputStr);

var result = NullabilityEliminator.perform(input);
var result = NullabilityEliminator.perform(typeProvider, input);
expect(result, isNot(same(input)));
expect(_typeToString(result), expectedStr);
}
Expand Down

0 comments on commit f024d9d

Please sign in to comment.