// Copyright (c) 2019, 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:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/scope.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/dart/resolver/scope_context.dart';
import 'package:analyzer/src/summary2/function_type_builder.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/named_type_builder.dart';
import 'package:analyzer/src/summary2/record_type_builder.dart';
import 'package:analyzer/src/summary2/types_builder.dart';

/// Recursive visitor of LinkedNodes that resolves explicit type annotations
/// in outlines.  This includes resolving element references in identifiers
/// in type annotation, and setting LinkedNodeTypes for corresponding type
/// annotation nodes.
///
/// Declarations that have type annotations, e.g. return types of methods, get
/// the corresponding type set (so, if there is an explicit type annotation,
/// the type is set, otherwise we keep it empty, so we will attempt to infer
/// it later).
class ReferenceResolver extends ThrowingAstVisitor<void> {
  /// The library fragment in which the AST nodes are being resolved.
  final LibraryFragmentImpl libraryFragment;

  final ScopeContext _scopeContext;
  final Linker linker;
  final TypeSystemImpl typeSystem;
  final NodesToBuildType nodesToBuildType;

  ReferenceResolver(
    this.linker,
    this.nodesToBuildType,
    this.typeSystem,
    Scope scope, {
    required this.libraryFragment,
  }) : _scopeContext = ScopeContext(
         libraryFragment: libraryFragment,
         nameScope: scope,
       );

  Scope get nameScope => _scopeContext.nameScope;

  @override
  void visitAnnotation(covariant AnnotationImpl node) {
    if (node.arguments != null) {
      var identifier = node.name;
      if (identifier is PrefixedIdentifierImpl) {
        var prefixNode = identifier.prefix;
        var prefixElement = nameScope.lookup(prefixNode.name).getter;
        prefixNode.element = prefixElement;

        if (prefixElement is PrefixElement) {
          var name = identifier.identifier.name;
          var element = prefixElement.scope.lookup(name).getter;
          identifier.identifier.element = element;
        }
      } else if (identifier is SimpleIdentifierImpl) {
        var element = nameScope.lookup(identifier.name).getter;
        identifier.element = element;
        return;
      }
    }
  }

  @override
  void visitBlockClassBody(BlockClassBody node) {
    node.members.accept(this);
  }

  @override
  void visitBlockEnumBody(BlockEnumBody node) {
    node.constants.accept(this);
    node.members.accept(this);
  }

  @override
  void visitBlockFunctionBody(BlockFunctionBody node) {}

  @override
  void visitClassDeclaration(covariant ClassDeclarationImpl node) {
    _scopeContext.visitClassDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitClassTypeAlias(covariant ClassTypeAliasImpl node) {
    _scopeContext.visitClassTypeAlias(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitComment(Comment node) {}

  @override
  void visitCompilationUnit(CompilationUnit node) {
    node.declarations.accept(this);
  }

  @override
  void visitConstructorDeclaration(covariant ConstructorDeclarationImpl node) {
    _scopeContext.visitConstructorDeclaration(
      node,
      visitor: this,
      visitTypeName: (_) {},
      visitInitializers: (_) {},
      visitRedirectedConstructor: (_) {},
    );
  }

  @override
  void visitEmptyClassBody(EmptyClassBody node) {}

  @override
  void visitEmptyEnumBody(EmptyEnumBody node) {}

  @override
  void visitEmptyFunctionBody(EmptyFunctionBody node) {}

  @override
  void visitEnumConstantDeclaration(EnumConstantDeclaration node) {}

  @override
  void visitEnumDeclaration(covariant EnumDeclarationImpl node) {
    var fragment = node.declaredFragment!;

    _scopeContext.visitEnumDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);

    for (var field in fragment.fields) {
      if (field.isEnumConstant || field.isOriginEnumValues) {
        var fieldNode = linker.getLinkingNode(field);
        fieldNode as VariableDeclarationImpl;
        fieldNode.initializerScope = node.bodyScope;
      }
    }
  }

  @override
  void visitExpressionFunctionBody(ExpressionFunctionBody node) {}

  @override
  void visitExtendsClause(ExtendsClause node) {
    node.superclass.accept(this);
  }

  @override
  void visitExtensionDeclaration(covariant ExtensionDeclarationImpl node) {
    _scopeContext.visitExtensionDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitExtensionOnClause(ExtensionOnClause node) {
    node.extendedType.accept(this);
  }

  @override
  void visitExtensionTypeDeclaration(
    covariant ExtensionTypeDeclarationImpl node,
  ) {
    _scopeContext.visitExtensionTypeDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitFieldDeclaration(covariant FieldDeclarationImpl node) {
    _scopeContext.visitFieldDeclaration(node, visitor: this);
  }

  @override
  void visitFieldFormalParameter(covariant FieldFormalParameterImpl node) {
    _visitFormalParameter(node);
  }

  @override
  void visitFormalParameterDefaultClause(FormalParameterDefaultClause node) {}

  @override
  void visitFormalParameterList(FormalParameterList node) {
    node.parameters.accept(this);
  }

  @override
  void visitFunctionDeclaration(covariant FunctionDeclarationImpl node) {
    _scopeContext.visitFunctionDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitFunctionTypeAlias(covariant FunctionTypeAliasImpl node) {
    _scopeContext.visitFunctionTypeAlias(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) {
    _scopeContext.visitGenericFunctionType(node, visitor: this);

    var nullabilitySuffix = _getNullabilitySuffix(node.question != null);
    var builder = FunctionTypeBuilder.of(node, nullabilitySuffix);
    node.type = builder;
    nodesToBuildType.addDeclaration(node);
    nodesToBuildType.addTypeBuilder(builder);
  }

  @override
  void visitGenericTypeAlias(covariant GenericTypeAliasImpl node) {
    _scopeContext.visitGenericTypeAlias(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitImplementsClause(ImplementsClause node) {
    node.interfaces.accept(this);
  }

  @override
  void visitMethodDeclaration(covariant MethodDeclarationImpl node) {
    _scopeContext.visitMethodDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitMixinDeclaration(covariant MixinDeclarationImpl node) {
    _scopeContext.visitMixinDeclaration(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitMixinOnClause(MixinOnClause node) {
    node.superclassConstraints.accept(this);
  }

  @override
  void visitNamedType(covariant NamedTypeImpl node) {
    Element? element;
    var importPrefix = node.importPrefix;
    if (importPrefix != null) {
      var prefixToken = importPrefix.name;
      var prefixName = prefixToken.lexeme;
      var prefixElement = nameScope.lookup(prefixName).getter;
      importPrefix.element = prefixElement;

      if (prefixElement is PrefixElement) {
        var name = node.name.lexeme;
        element = prefixElement.scope.lookup(name).getter;
      }
    } else {
      var name = node.name.lexeme;

      if (name == 'void') {
        node.type = VoidTypeImpl.instance;
        return;
      }

      element = nameScope.lookup(name).getter;
    }
    node.element = element;

    node.typeArguments?.accept(this);

    var nullabilitySuffix = _getNullabilitySuffix(node.question != null);
    if (element == null) {
      node.type = InvalidTypeImpl.instance;
    } else if (element is TypeParameterElementImpl) {
      node.type = _scopeContext.instantiateTypeParameter(
        element: element,
        nullability: nullabilitySuffix,
      );
    } else {
      var builder = NamedTypeBuilder.of(
        linker: linker,
        typeSystem: typeSystem,
        node: node,
        element: element,
        nullabilitySuffix: nullabilitySuffix,
      );
      node.type = builder;
      nodesToBuildType.addTypeBuilder(builder);
    }
  }

  @override
  void visitNameWithTypeParameters(NameWithTypeParameters node) {
    node.typeParameters?.accept(this);
  }

  @override
  void visitNativeClause(NativeClause node) {}

  @override
  void visitNativeFunctionBody(NativeFunctionBody node) {}

  @override
  void visitPrimaryConstructorBody(covariant PrimaryConstructorBodyImpl node) {
    _scopeContext.visitPrimaryConstructorBody(
      node,
      visitor: this,
      visitInitializers: (_) {},
    );
  }

  @override
  void visitRecordTypeAnnotation(covariant RecordTypeAnnotationImpl node) {
    node.positionalFields.accept(this);
    node.namedFields?.accept(this);

    var builder = RecordTypeBuilder.of(typeSystem, node);
    node.type = builder;
    nodesToBuildType.addTypeBuilder(builder);
  }

  @override
  void visitRecordTypeAnnotationNamedField(
    RecordTypeAnnotationNamedField node,
  ) {
    node.type.accept(this);
  }

  @override
  void visitRecordTypeAnnotationNamedFields(
    RecordTypeAnnotationNamedFields node,
  ) {
    node.fields.accept(this);
  }

  @override
  void visitRecordTypeAnnotationPositionalField(
    RecordTypeAnnotationPositionalField node,
  ) {
    node.type.accept(this);
  }

  @override
  void visitRegularFormalParameter(covariant RegularFormalParameterImpl node) {
    _visitFormalParameter(node);
  }

  @override
  void visitSuperFormalParameter(covariant SuperFormalParameterImpl node) {
    _visitFormalParameter(node);
  }

  @override
  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
    node.visitChildren(this);
  }

  @override
  void visitTypeArgumentList(TypeArgumentList node) {
    node.arguments.accept(this);
  }

  @override
  void visitTypeParameter(covariant TypeParameterImpl node) {
    var bound = node.bound;
    if (bound != null) {
      bound.accept(this);
      var fragment = node.declaredFragment!;
      if (fragment.previousFragment == null) {
        fragment.element.bound = bound.type;
      }
      nodesToBuildType.addDeclaration(node);
    }
  }

  @override
  void visitTypeParameterList(TypeParameterList node) {
    node.typeParameters.accept(this);
  }

  @override
  void visitVariableDeclaration(covariant VariableDeclarationImpl node) {
    node.initializerScope = nameScope;
  }

  @override
  void visitVariableDeclarationList(
    covariant VariableDeclarationListImpl node,
  ) {
    _scopeContext.visitVariableDeclarationList(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }

  @override
  void visitWithClause(WithClause node) {
    node.mixinTypes.accept(this);
  }

  NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
    if (hasQuestion) {
      return NullabilitySuffix.question;
    } else {
      return NullabilitySuffix.none;
    }
  }

  void _visitFormalParameter(FormalParameterImpl node) {
    _scopeContext.visitFormalParameter(node, visitor: this);
    nodesToBuildType.addDeclaration(node);
  }
}
