// Copyright (c) 2017, 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/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';

/// A visitor that visits an [AstNode] and its parent recursively along with any
/// declarations in those nodes. Consumers typically call [visit] which catches
/// the exception thrown by [finished].
abstract class LocalDeclarationVisitor extends GeneralizingAstVisitor {
  final int offset;

  LocalDeclarationVisitor(this.offset);

  void declaredClass(ClassDeclaration declaration) {}

  void declaredClassTypeAlias(ClassTypeAlias declaration) {}

  void declaredConstructor(ConstructorDeclaration declaration) {}

  void declaredEnum(EnumDeclaration declaration) {}

  void declaredExtension(ExtensionDeclaration declaration) {}

  void declaredField(FieldDeclaration fieldDecl, VariableDeclaration varDecl) {}

  void declaredFunction(FunctionDeclaration declaration) {}

  void declaredFunctionTypeAlias(FunctionTypeAlias declaration) {}

  void declaredGenericTypeAlias(GenericTypeAlias declaration) {}

  void declaredLabel(Label label, bool isCaseLabel) {}

  void declaredLocalVar(
    Token name,
    TypeAnnotation? type,
    LocalVariableElement declaredElement,
  ) {}

  void declaredMethod(MethodDeclaration declaration) {}

  void declaredMixin(MixinDeclaration declaration) {}

  void declaredParam(Token name, Element? element, TypeAnnotation? type) {}

  void declaredTopLevelVar(
      VariableDeclarationList varList, VariableDeclaration varDecl) {}

  void declaredTypeParameter(TypeParameter declaration) {}

  /// Throw an exception indicating that [LocalDeclarationVisitor] should
  /// stop visiting. This is caught in [visit] which then exits normally.
  void finished() {
    throw _LocalDeclarationVisitorFinished();
  }

  /// Visit the given [AstNode] and its parent recursively along with any
  /// declarations in those nodes. Return `true` if [finished] is called
  /// while visiting, else `false`.
  bool visit(AstNode node) {
    try {
      node.accept(this);
      return false;
    } on _LocalDeclarationVisitorFinished {
      return true;
    }
  }

  @override
  void visitBlock(Block node) {
    _visitStatements(node.statements);
    visitNode(node);
  }

  @override
  void visitCatchClause(CatchClause node) {
    var exceptionParameter = node.exceptionParameter2;
    if (exceptionParameter != null) {
      declaredParam(
        exceptionParameter.name,
        exceptionParameter.declaredElement,
        node.exceptionType,
      );
    }

    var stackTraceParameter = node.stackTraceParameter2;
    if (stackTraceParameter != null) {
      declaredParam(
        stackTraceParameter.name,
        stackTraceParameter.declaredElement,
        null,
      );
    }

    visitNode(node);
  }

  @override
  void visitClassDeclaration(ClassDeclaration node) {
    _visitClassOrMixinMembers(node.members);
    visitNode(node);
  }

  @override
  void visitCompilationUnit(CompilationUnit node) {
    _visitCompilationUnit(node);
  }

  @override
  void visitConstructorDeclaration(ConstructorDeclaration node) {
    _visitParamList(node.parameters);
    visitNode(node);
  }

  @override
  void visitExtensionDeclaration(ExtensionDeclaration node) {
    _visitClassOrMixinMembers(node.members);
    visitNode(node);
  }

  @override
  void visitForElement(ForElement node) {
    var forLoopParts = node.forLoopParts;
    if (forLoopParts is ForEachPartsWithDeclaration) {
      var loopVariable = forLoopParts.loopVariable;
      declaredLocalVar(
          loopVariable.name, loopVariable.type, loopVariable.declaredElement2!);
    } else if (forLoopParts is ForPartsWithDeclarations) {
      var varList = forLoopParts.variables;
      for (var varDecl in varList.variables) {
        declaredLocalVar(varDecl.name, varList.type,
            varDecl.declaredElement2 as LocalVariableElement);
      }
    }
    visitNode(node);
  }

  @override
  void visitForStatement(ForStatement node) {
    var forLoopParts = node.forLoopParts;
    if (forLoopParts is ForEachPartsWithDeclaration) {
      var loopVariable = forLoopParts.loopVariable;
      declaredLocalVar(
          loopVariable.name, loopVariable.type, loopVariable.declaredElement2!);
    } else if (forLoopParts is ForPartsWithDeclarations) {
      var varList = forLoopParts.variables;
      for (var varDecl in varList.variables) {
        declaredLocalVar(varDecl.name, varList.type,
            varDecl.declaredElement2 as LocalVariableElement);
      }
    }
    visitNode(node);
  }

  @override
  void visitFunctionDeclaration(FunctionDeclaration node) {
    // declaredFunction is called by the compilation unit containing it
    visitNode(node);
  }

  @override
  void visitFunctionExpression(FunctionExpression node) {
    _visitTypeParameters(node, node.typeParameters);
    _visitParamList(node.parameters);
    visitNode(node);
  }

  @override
  void visitGenericFunctionType(GenericFunctionType node) {
    _visitTypeParameters(node, node.typeParameters);
    visitNode(node);
  }

  @override
  void visitInterpolationExpression(InterpolationExpression node) {
    visitNode(node);
  }

  @override
  void visitLabeledStatement(LabeledStatement node) {
    for (var label in node.labels) {
      declaredLabel(label, false);
    }
    visitNode(node);
  }

  @override
  void visitMethodDeclaration(MethodDeclaration node) {
    _visitTypeParameters(node, node.typeParameters);
    _visitParamList(node.parameters);
    visitNode(node);
  }

  @override
  void visitMixinDeclaration(MixinDeclaration node) {
    _visitClassOrMixinMembers(node.members);
    visitNode(node);
  }

  @override
  void visitNode(AstNode node) {
    // Support the case of searching partial ASTs by aborting on nodes with no
    // parents. This is useful for the angular plugin.
    node.parent?.accept(this);
  }

  @override
  void visitStringInterpolation(StringInterpolation node) {
    visitNode(node);
  }

  @override
  void visitSwitchMember(SwitchMember node) {
    _visitStatements(node.statements);
    visitNode(node);
  }

  @override
  void visitSwitchStatement(SwitchStatement node) {
    for (var member in node.members) {
      for (var label in member.labels) {
        declaredLabel(label, true);
      }
    }
    visitNode(node);
  }

  void _visitClassOrMixinMembers(List<ClassMember> members) {
    for (var member in members) {
      if (member is FieldDeclaration) {
        for (var varDecl in member.fields.variables) {
          declaredField(member, varDecl);
        }
      } else if (member is MethodDeclaration) {
        declaredMethod(member);
        _visitTypeParameters(member, member.typeParameters);
      }
    }
  }

  void _visitCompilationUnit(CompilationUnit node) {
    for (var declaration in node.declarations) {
      if (declaration is ClassDeclaration) {
        declaredClass(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);
        // Call declaredConstructor all ConstructorDeclarations when the class
        // is called: constructors are accessible if the class is accessible.
        for (var classDeclaration
            in node.declarations.whereType<ClassDeclaration>()) {
          for (var constructor
              in classDeclaration.members.whereType<ConstructorDeclaration>()) {
            declaredConstructor(constructor);
          }
        }
      } else if (declaration is EnumDeclaration) {
        declaredEnum(declaration);
      } else if (declaration is ExtensionDeclaration) {
        declaredExtension(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);
      } else if (declaration is FunctionDeclaration) {
        declaredFunction(declaration);
        _visitTypeParameters(
          declaration,
          declaration.functionExpression.typeParameters,
        );
      } else if (declaration is TopLevelVariableDeclaration) {
        var varList = declaration.variables;
        for (var varDecl in varList.variables) {
          declaredTopLevelVar(varList, varDecl);
        }
      } else if (declaration is ClassTypeAlias) {
        declaredClassTypeAlias(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);
      } else if (declaration is FunctionTypeAlias) {
        declaredFunctionTypeAlias(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);
      } else if (declaration is GenericTypeAlias) {
        declaredGenericTypeAlias(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);

        var type = declaration.type;
        if (type is GenericFunctionType) {
          _visitTypeParameters(type, type.typeParameters);
        }
      } else if (declaration is MixinDeclaration) {
        declaredMixin(declaration);
        _visitTypeParameters(declaration, declaration.typeParameters);
      }
    }
  }

  void _visitParamList(FormalParameterList? paramList) {
    if (paramList != null) {
      for (var param in paramList.parameters) {
        NormalFormalParameter? normalParam;
        if (param is DefaultFormalParameter) {
          normalParam = param.parameter;
        } else if (param is NormalFormalParameter) {
          normalParam = param;
        }
        TypeAnnotation? type;
        if (normalParam is FieldFormalParameter) {
          type = normalParam.type;
        } else if (normalParam is FunctionTypedFormalParameter) {
          type = normalParam.returnType;
        } else if (normalParam is SimpleFormalParameter) {
          type = normalParam.type;
        }
        declaredParam(param.name!, param.declaredElement, type);
      }
    }
  }

  void _visitStatements(NodeList<Statement> statements) {
    for (var stmt in statements) {
      if (stmt.offset < offset) {
        if (stmt is VariableDeclarationStatement) {
          var varList = stmt.variables;
          for (var varDecl in varList.variables) {
            if (varDecl.end < offset) {
              declaredLocalVar(varDecl.name, varList.type,
                  varDecl.declaredElement2 as LocalVariableElement);
            }
          }
        } else if (stmt is FunctionDeclarationStatement) {
          var declaration = stmt.functionDeclaration;
          if (declaration.offset < offset) {
            var name = declaration.name.lexeme;
            if (name.isNotEmpty) {
              declaredFunction(declaration);
              _visitTypeParameters(
                declaration,
                declaration.functionExpression.typeParameters,
              );
            }
          }
        }
      }
    }
  }

  void _visitTypeParameters(AstNode node, TypeParameterList? typeParameters) {
    if (typeParameters == null) return;

    if (node.offset < offset && offset < node.end) {
      for (var typeParameter in typeParameters.typeParameters) {
        declaredTypeParameter(typeParameter);
      }
    }
  }
}

/// Internal exception used to indicate that [LocalDeclarationVisitor]
/// should stop visiting.
class _LocalDeclarationVisitorFinished {}
