Implement record type resolution in RecordTypeAnnotationResolver, from ResolutionVisitor.
Change-Id: Ia3ab904c05d7800088ca6467d35151821130a523
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/256432
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/resolver/record_type_annotation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/record_type_annotation_resolver.dart
index 4bd6875..fbf4079 100644
--- a/pkg/analyzer/lib/src/dart/resolver/record_type_annotation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/record_type_annotation_resolver.dart
@@ -3,25 +3,27 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type_provider.dart';
import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
import 'package:analyzer/src/error/codes.g.dart';
-import 'package:analyzer/src/generated/resolver.dart';
/// Helper for resolving [RecordTypeAnnotation]s.
class RecordTypeAnnotationResolver {
/// A regular expression used to match positional field names.
static final RegExp positionalFieldName = RegExp(r'^\$[0-9]+$');
- final ResolverVisitor _resolver;
+ final TypeProviderImpl typeProvider;
+ final ErrorReporter errorReporter;
RecordTypeAnnotationResolver({
- required ResolverVisitor resolver,
- }) : _resolver = resolver;
-
- ErrorReporter get errorReporter => _resolver.errorReporter;
+ required this.typeProvider,
+ required this.errorReporter,
+ });
/// Report any named fields in the record type [node] that use a previously
/// defined name.
@@ -44,8 +46,7 @@
/// Report any fields in the record type [node] that use an invalid name.
void reportInvalidFieldNames(RecordTypeAnnotationImpl node) {
- var fields = node.fields;
- for (var field in fields) {
+ for (var field in node.fields) {
var nameToken = field.name;
if (nameToken != null) {
var name = nameToken.lexeme;
@@ -56,7 +57,7 @@
errorReporter.reportErrorForToken(
CompileTimeErrorCode.INVALID_FIELD_NAME_POSITIONAL, nameToken);
} else {
- var objectElement = _resolver.typeProvider.objectElement;
+ var objectElement = typeProvider.objectElement;
if (objectElement.getGetter(name) != null ||
objectElement.getMethod(name) != null) {
errorReporter.reportErrorForToken(
@@ -67,16 +68,32 @@
}
}
- void resolve(RecordTypeAnnotationImpl node,
- {required DartType? contextType}) {
- // TODO(brianwilkerson) Move resolution from the `visitRecordTypeAnnotation`
- // methods of `ResolverVisitor` and `StaticTypeAnalyzer` to this class.
+ void resolve(RecordTypeAnnotationImpl node) {
+ _buildType(node);
+ reportDuplicateFieldDefinitions(node);
+ reportInvalidFieldNames(node);
}
-}
-extension on RecordTypeAnnotation {
- List<RecordTypeAnnotationField> get fields => [
- ...positionalFields,
- ...?namedFields?.fields,
- ];
+ void _buildType(RecordTypeAnnotationImpl node) {
+ final positionalFields = node.positionalFields.map((field) {
+ return RecordTypePositionalFieldImpl(
+ type: field.type.typeOrThrow,
+ );
+ }).toList();
+
+ final namedFields = node.namedFields?.fields.map((field) {
+ return RecordTypeNamedFieldImpl(
+ name: field.name.lexeme,
+ type: field.type.typeOrThrow,
+ );
+ }).toList();
+
+ node.type = RecordTypeImpl(
+ positionalFields: positionalFields,
+ namedFields: namedFields ?? const [],
+ nullabilitySuffix: node.question != null
+ ? NullabilitySuffix.question
+ : NullabilitySuffix.none,
+ );
+ }
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 3e94ae7..4818b5d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -19,11 +19,11 @@
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/resolver/ast_rewrite.dart';
import 'package:analyzer/src/dart/resolver/named_type_resolver.dart';
+import 'package:analyzer/src/dart/resolver/record_type_annotation_resolver.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/element_walker.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
-import 'package:analyzer/src/summary2/record_type_builder.dart';
class ElementHolder {
final ElementImpl _element;
@@ -65,6 +65,7 @@
final ErrorReporter _errorReporter;
final AstRewriter _astRewriter;
final NamedTypeResolver _namedTypeResolver;
+ final RecordTypeAnnotationResolver _recordTypeResolver;
/// This index is incremented every time we visit a [LibraryDirective].
/// There is just one [LibraryElement], so we can support only one node.
@@ -111,6 +112,11 @@
errorReporter,
);
+ final recordTypeResolver = RecordTypeAnnotationResolver(
+ typeProvider: typeProvider,
+ errorReporter: errorReporter,
+ );
+
return ResolutionVisitor._(
libraryElement,
typeProvider,
@@ -119,6 +125,7 @@
errorReporter,
AstRewriter(errorReporter, typeProvider),
namedTypeResolver,
+ recordTypeResolver,
nameScope,
elementWalker,
ElementHolder(unitElement),
@@ -133,6 +140,7 @@
this._errorReporter,
this._astRewriter,
this._namedTypeResolver,
+ this._recordTypeResolver,
this._nameScope,
this._elementWalker,
this._elementHolder,
@@ -971,7 +979,7 @@
@override
void visitRecordTypeAnnotation(covariant RecordTypeAnnotationImpl node) {
node.visitChildren(this);
- RecordTypeBuilder.buildType(node);
+ _recordTypeResolver.resolve(node);
}
@override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8dd3bc7..a09991b 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -51,7 +51,6 @@
import 'package:analyzer/src/dart/resolver/prefixed_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
import 'package:analyzer/src/dart/resolver/record_literal_resolver.dart';
-import 'package:analyzer/src/dart/resolver/record_type_annotation_resolver.dart';
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/dart/resolver/simple_identifier_resolver.dart';
import 'package:analyzer/src/dart/resolver/this_lookup.dart';
@@ -253,9 +252,6 @@
late final RecordLiteralResolver _recordLiteralResolver =
RecordLiteralResolver(resolver: this);
- late final RecordTypeAnnotationResolver _recordTypeAnnotationResolver =
- RecordTypeAnnotationResolver(resolver: this);
-
late final AnnotationResolver _annotationResolver = AnnotationResolver(this);
final bool genericMetadataIsEnabled;
@@ -2235,10 +2231,11 @@
@override
void visitRecordTypeAnnotation(covariant RecordTypeAnnotationImpl node) {
+ // All RecordTypeAnnotation(s) are already resolved, so we don't resolve
+ // it here. But there might be types with Expression(s), such as default
+ // values for formal parameters of GenericFunctionType(s). These are
+ // invalid, but if they exist, they should be resolved.
node.visitChildren(this);
- _recordTypeAnnotationResolver
- ..reportDuplicateFieldDefinitions(node)
- ..reportInvalidFieldNames(node);
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/record_type_builder.dart b/pkg/analyzer/lib/src/summary2/record_type_builder.dart
index 7d17359..59530b6 100644
--- a/pkg/analyzer/lib/src/summary2/record_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/record_type_builder.dart
@@ -123,30 +123,6 @@
);
}
- /// TODO(scheglov) Move to [RecordTypeAnnotationResolver].
- static RecordTypeImpl buildType(RecordTypeAnnotationImpl node) {
- final positionalFields = node.positionalFields.map((field) {
- return RecordTypePositionalFieldImpl(
- type: field.type.typeOrThrow,
- );
- }).toList();
-
- final namedFields = node.namedFields?.fields.map((field) {
- return RecordTypeNamedFieldImpl(
- name: field.name.lexeme,
- type: field.type.typeOrThrow,
- );
- }).toList();
-
- return node.type = RecordTypeImpl(
- positionalFields: positionalFields,
- namedFields: namedFields ?? const [],
- nullabilitySuffix: node.question != null
- ? NullabilitySuffix.question
- : NullabilitySuffix.none,
- );
- }
-
/// If the [type] is a [TypeBuilder], build it; otherwise return as is.
static DartType _buildType(DartType type) {
if (type is TypeBuilder) {