| // 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/error/codes.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, |
| WarningCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE, |
| 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, |
| CompileTimeErrorCode.INVALID_ASSIGNMENT, |
| whyNotPromoted: whyNotPromoted, |
| ); |
| } |
| } |