758d3a8803
Converts the code that reports diagnostic codes `invalidAssignment` and `argumentTypeNotAssignable` to use the literate diagnostic reporting API. This was challenging because some of the code for reporting these diagnostics (specifically the method `ErrorDetectionHelpers.checkForAssignableExpressionAtType`) was parameterized by diagnostic code, but the two diagnostics accepted a different number of parameters. To get the type safety of the literate diagnostic API while preserving the existing behavior, I've created an abstract base class, `NonAssignabilityReporter`, with a method `createDiagnostic`, that encapsulates the differences in how to handle the two diagnostic codes. Change-Id: I6a6a69649e53f6980b5033771b14dbfdaa5895d6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/467481 Commit-Queue: Paul Berry <paulberry@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
93 lines
3.2 KiB
Dart
93 lines
3.2 KiB
Dart
// Copyright (c) 2020, 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:_fe_analyzer_shared/src/types/shared_type.dart';
|
|
import 'package:analyzer/dart/element/element.dart';
|
|
import 'package:analyzer/src/dart/ast/ast.dart';
|
|
import 'package:analyzer/src/dart/ast/extensions.dart';
|
|
import 'package:analyzer/src/dart/element/element.dart';
|
|
import 'package:analyzer/src/dart/element/type_schema.dart';
|
|
import 'package:analyzer/src/diagnostic/diagnostic.dart' as diag;
|
|
import 'package:analyzer/src/generated/error_detection_helpers.dart';
|
|
import 'package:analyzer/src/generated/resolver.dart';
|
|
|
|
/// Helper for resolving [VariableDeclaration]s.
|
|
class VariableDeclarationResolver {
|
|
final ResolverVisitor _resolver;
|
|
final bool _strictInference;
|
|
|
|
VariableDeclarationResolver({
|
|
required ResolverVisitor resolver,
|
|
required bool strictInference,
|
|
}) : _resolver = resolver,
|
|
_strictInference = strictInference;
|
|
|
|
void resolve(VariableDeclarationImpl node) {
|
|
var parent = node.parent as VariableDeclarationList;
|
|
|
|
var initializer = node.initializer;
|
|
|
|
if (initializer == null) {
|
|
if (_strictInference && parent.type == null) {
|
|
_resolver.diagnosticReporter.atNode(
|
|
node,
|
|
diag.inferenceFailureOnUninitializedVariable,
|
|
arguments: [node.name.lexeme],
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
|
|
var element = node.declaredFragment!.element;
|
|
var isTopLevel =
|
|
element is FieldElement || element is TopLevelVariableElement;
|
|
|
|
if (isTopLevel) {
|
|
_resolver.flowAnalysis.bodyOrInitializer_enter(node, null);
|
|
} else if (element.isLate) {
|
|
_resolver.flowAnalysis.flow?.lateInitializer_begin(node);
|
|
}
|
|
|
|
var contextType =
|
|
element is! PropertyInducingElementImpl ||
|
|
element.shouldUseTypeForInitializerInference
|
|
? element.type
|
|
: UnknownInferredType.instance;
|
|
_resolver.analyzeExpression(initializer, SharedTypeSchemaView(contextType));
|
|
initializer = _resolver.popRewrite()!;
|
|
var whyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(
|
|
initializer,
|
|
);
|
|
|
|
var initializerType = initializer.typeOrThrow;
|
|
if (parent.type == null && element is LocalVariableElementImpl) {
|
|
element.type = _resolver
|
|
.variableTypeFromInitializerType(SharedTypeView(initializerType))
|
|
.unwrapTypeView();
|
|
}
|
|
|
|
if (isTopLevel) {
|
|
_resolver.flowAnalysis.bodyOrInitializer_exit();
|
|
_resolver.nullSafetyDeadCodeVerifier.flowEnd(node);
|
|
} else if (element.isLate) {
|
|
_resolver.flowAnalysis.flow?.lateInitializer_end();
|
|
}
|
|
|
|
// Initializers of top-level variables and fields are already included
|
|
// into elements during linking.
|
|
if (element is LocalVariableElementImpl && element.isConst) {
|
|
var fragment = element.firstFragment;
|
|
fragment.constantInitializer = initializer;
|
|
}
|
|
|
|
_resolver.checkForAssignableExpressionAtType(
|
|
initializer,
|
|
initializerType,
|
|
element.type,
|
|
const NonAssignabilityReporterForAssignment(),
|
|
whyNotPromoted: whyNotPromoted,
|
|
);
|
|
}
|
|
}
|