// Copyright (c) 2018, 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/src/dart/ast/token.dart';
import 'package:analyzer/src/summary/api_signature.dart';

/// Return the bytes of the unlinked API signature of the given [unit].
///
/// If API signatures of two units are different, they may have different APIs.
List<int> computeUnlinkedApiSignature(CompilationUnit unit) {
  var computer = new _UnitApiSignatureComputer();
  computer.compute(unit);
  return computer.signature.toByteList();
}

class _UnitApiSignatureComputer {
  final signature = new ApiSignature();

  void addClassOrMixin(ClassOrMixinDeclaration node) {
    addTokens(node.beginToken, node.leftBracket);

    bool hasConstConstructor = node.members
        .any((m) => m is ConstructorDeclaration && m.constKeyword != null);

    signature.addInt(node.members.length);
    for (var member in node.members) {
      if (member is ConstructorDeclaration) {
        var lastInitializer = member.constKeyword != null &&
                member.initializers != null &&
                member.initializers.isNotEmpty
            ? member.initializers.last
            : null;
        addTokens(
          member.beginToken,
          (lastInitializer ?? member.parameters ?? member.name).endToken,
        );
      } else if (member is FieldDeclaration) {
        addVariables(member, member.fields, hasConstConstructor);
      } else if (member is MethodDeclaration) {
        addTokens(
          member.beginToken,
          (member.parameters ?? member.name).endToken,
        );
      } else {
        addNode(member);
      }
    }

    addToken(node.rightBracket);
  }

  void addNode(AstNode node) {
    addTokens(node.beginToken, node.endToken);
  }

  void addToken(Token token) {
    signature.addString(token.lexeme);
  }

  /// Appends tokens from [begin] (including), to [end] (also including).
  void addTokens(Token begin, Token end) {
    if (begin is CommentToken) {
      begin = (begin as CommentToken).parent;
    }
    Token token = begin;
    while (token != null) {
      addToken(token);
      if (token == end) {
        break;
      }
      token = token.next;
    }
  }

  void addVariables(
    AstNode node,
    VariableDeclarationList variableList,
    bool includeFinalInitializers,
  ) {
    if (variableList.type == null ||
        variableList.isConst ||
        variableList.isFinal && includeFinalInitializers) {
      addTokens(node.beginToken, node.endToken);
    } else {
      addTokens(node.beginToken, variableList.type.endToken);

      signature.addInt(variableList.variables.length);
      for (var variable in variableList.variables) {
        addTokens(variable.beginToken, variable.name.endToken);
        addToken(variable.endToken.next); // `,` or `;`
      }
    }
  }

  void compute(CompilationUnit unit) {
    signature.addInt(unit.directives.length);
    unit.directives.forEach(addNode);

    signature.addInt(unit.declarations.length);
    for (var declaration in unit.declarations) {
      if (declaration is ClassOrMixinDeclaration) {
        addClassOrMixin(declaration);
      } else if (declaration is FunctionDeclaration) {
        var parameters = declaration.functionExpression.parameters;
        addTokens(
          declaration.beginToken,
          (parameters ?? declaration.name).endToken,
        );
      } else if (declaration is TopLevelVariableDeclaration) {
        addVariables(declaration, declaration.variables, false);
      } else {
        addNode(declaration);
      }
    }
  }
}
