Add summary deserialization support for nullability.
In a follow-up CL I will add nullability support to the summary
linker.
Change-Id: I99f3dce1a695da65c7c09c11e73462c93aeb637f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101882
Commit-Queue: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/summary/resynthesize.dart b/pkg/analyzer/lib/src/summary/resynthesize.dart
index 6f8720e..b364311 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1343,17 +1343,18 @@
type = refinedType;
}
}
+ DartType result;
if (type.paramReference != 0) {
- return context.typeParameterContext
+ result = context.typeParameterContext
.getTypeParameterType(type.paramReference);
} else if (type.entityKind == EntityRefKind.genericFunctionType) {
GenericFunctionTypeElement element =
new GenericFunctionTypeElementImpl.forSerialized(context, type);
- return element.type;
+ result = element.type;
} else if (type.syntheticReturnType != null) {
FunctionElementImpl element =
new FunctionElementImpl_forLUB(context, type);
- return element.type;
+ result = element.type;
} else {
DartType getTypeArgument(int i) {
if (i < type.typeArguments.length) {
@@ -1369,12 +1370,18 @@
return DynamicTypeImpl.instance;
}
- return referenceInfo.buildType(
+ result = referenceInfo.buildType(
instantiateToBoundsAllowed,
type.typeArguments.length,
getTypeArgument,
type.implicitFunctionTypeIndices);
}
+ var nullabilitySuffix = _translateNullabilitySuffix(type.nullabilitySuffix);
+ var resultAsImpl = result as TypeImpl;
+ if (resultAsImpl.nullabilitySuffix != nullabilitySuffix) {
+ result = resultAsImpl.withNullability(nullabilitySuffix);
+ }
+ return result;
}
@override
@@ -1621,6 +1628,19 @@
return null;
}
+ NullabilitySuffix _translateNullabilitySuffix(
+ EntityRefNullabilitySuffix suffix) {
+ switch (suffix) {
+ case EntityRefNullabilitySuffix.none:
+ return NullabilitySuffix.none;
+ case EntityRefNullabilitySuffix.question:
+ return NullabilitySuffix.question;
+ case EntityRefNullabilitySuffix.starOrIrrelevant:
+ return NullabilitySuffix.star;
+ }
+ throw new StateError('Unrecognized nullability suffix');
+ }
+
/**
* If the given [kind] is a top-level or class member property accessor, and
* the given [name] does not end with `=`, i.e. does not denote a setter,
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 731f012..9629b2a 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -59,7 +59,8 @@
bool withOffsets: false,
bool withSyntheticAccessors: false,
bool withSyntheticFields: false,
- bool withTypes: false}) {
+ bool withTypes: false,
+ bool annotateNullability: false}) {
var writer = new _ElementWriter(
withCodeRanges: withCodeRanges,
withConstElements: withConstElements,
@@ -67,7 +68,8 @@
withOffsets: withOffsets,
withSyntheticAccessors: withSyntheticAccessors,
withSyntheticFields: withSyntheticFields,
- withTypes: withTypes);
+ withTypes: withTypes,
+ annotateNullability: annotateNullability);
writer.writeLibraryElement(library);
String actualText = writer.buffer.toString();
@@ -135,6 +137,7 @@
final bool withSyntheticAccessors;
final bool withSyntheticFields;
final bool withTypes;
+ final bool annotateNullability;
final StringBuffer buffer = new StringBuffer();
_ElementWriter(
@@ -144,7 +147,8 @@
this.withOffsets: false,
this.withSyntheticAccessors: false,
this.withSyntheticFields: false,
- this.withTypes: false});
+ this.withTypes: false,
+ this.annotateNullability: false});
bool isDynamicType(DartType type) => type is DynamicTypeImpl;
@@ -947,6 +951,18 @@
} else {
buffer.write(type.displayName);
}
+ if (annotateNullability) {
+ switch ((type as TypeImpl).nullabilitySuffix) {
+ case NullabilitySuffix.none:
+ break;
+ case NullabilitySuffix.question:
+ buffer.write('?');
+ break;
+ case NullabilitySuffix.star:
+ buffer.write('*');
+ break;
+ }
+ }
}
void writeType2(DartType type) {
diff --git a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 69d4a5b..352acf3 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -114,12 +114,41 @@
@override
@failingTest
+ test_class_ref_nullability_none() => super.test_class_ref_nullability_none();
+
+ @override
+ @failingTest
+ test_class_ref_nullability_question() =>
+ super.test_class_ref_nullability_question();
+
+ @override
+ @failingTest
+ test_generic_function_type_nullability_none() =>
+ super.test_generic_function_type_nullability_none();
+
+ @override
+ @failingTest
+ test_generic_function_type_nullability_question() =>
+ super.test_generic_function_type_nullability_question();
+
+ @override
+ @failingTest
test_syntheticFunctionType_genericClosure() async {
// TODO(scheglov) Bug in TypeSystem.getLeastUpperBound().
// LUB(<T>(T) → int, <T>(T) → int) gives `(T) → int`, note absence of `<T>`.
await super.test_syntheticFunctionType_genericClosure();
}
+ @override
+ @failingTest
+ test_type_param_ref_nullability_none() =>
+ super.test_type_param_ref_nullability_none();
+
+ @override
+ @failingTest
+ test_type_param_ref_nullability_question() =>
+ super.test_type_param_ref_nullability_question();
+
void _addLibraryUnits(
Source definingSource,
CompilationUnit definingUnit,
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 817015b..c2d13b7 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -204,6 +204,8 @@
/// applied to a class implementing [ResynthesizeTestStrategy], along with the
/// mixin [ResynthesizeTestHelpers].
mixin ResynthesizeTestCases implements ResynthesizeTestHelpers {
+ FeatureSet get disableNnbd => FeatureSet.forTesting(sdkVersion: '2.2.2');
+
FeatureSet get enableNnbd =>
FeatureSet.forTesting(additionalFeatures: [Feature.non_nullable]);
@@ -1476,6 +1478,54 @@
''');
}
+ test_class_ref_nullability_none() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+class C {}
+C c;
+''');
+ checkElementText(
+ library,
+ '''
+class C {
+}
+C c;
+''',
+ annotateNullability: true);
+ }
+
+ test_class_ref_nullability_question() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+class C {}
+C? c;
+''');
+ checkElementText(
+ library,
+ '''
+class C {
+}
+C? c;
+''',
+ annotateNullability: true);
+ }
+
+ test_class_ref_nullability_star() async {
+ featureSet = disableNnbd;
+ var library = await checkLibrary('''
+class C {}
+C c;
+''');
+ checkElementText(
+ library,
+ '''
+class C {
+}
+C* c;
+''',
+ annotateNullability: true);
+ }
+
test_class_setter_abstract() async {
var library =
await checkLibrary('abstract class C { void set x(int value); }');
@@ -6102,6 +6152,45 @@
expect(y.type.toString(), 'dynamic');
}
+ test_generic_function_type_nullability_none() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+void Function() f;
+''');
+ checkElementText(
+ library,
+ '''
+void Function() f;
+''',
+ annotateNullability: true);
+ }
+
+ test_generic_function_type_nullability_question() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+void Function()? f;
+''');
+ checkElementText(
+ library,
+ '''
+void Function()? f;
+''',
+ annotateNullability: true);
+ }
+
+ test_generic_function_type_nullability_star() async {
+ featureSet = disableNnbd;
+ var library = await checkLibrary('''
+void Function() f;
+''');
+ checkElementText(
+ library,
+ '''
+void Function()* f;
+''',
+ annotateNullability: true);
+ }
+
test_generic_gClass_gMethodStatic() async {
var library = await checkLibrary('''
class C<T, U> {
@@ -9211,6 +9300,57 @@
''');
}
+ test_type_param_ref_nullability_none() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+class C<T> {
+ T t;
+}
+''');
+ checkElementText(
+ library,
+ '''
+class C<T> {
+ T t;
+}
+''',
+ annotateNullability: true);
+ }
+
+ test_type_param_ref_nullability_question() async {
+ featureSet = enableNnbd;
+ var library = await checkLibrary('''
+class C<T> {
+ T? t;
+}
+''');
+ checkElementText(
+ library,
+ '''
+class C<T> {
+ T? t;
+}
+''',
+ annotateNullability: true);
+ }
+
+ test_type_param_ref_nullability_star() async {
+ featureSet = disableNnbd;
+ var library = await checkLibrary('''
+class C<T> {
+ T t;
+}
+''');
+ checkElementText(
+ library,
+ '''
+class C<T> {
+ T* t;
+}
+''',
+ annotateNullability: true);
+ }
+
test_type_reference_lib_to_lib() async {
var library = await checkLibrary('''
class C {}