// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ZIRCON_TOOLS_FIDL_INCLUDE_FIDL_LINTER_H_
#define ZIRCON_TOOLS_FIDL_INCLUDE_FIDL_LINTER_H_

#include <array>
#include <deque>
#include <regex>
#include <set>

#include <fidl/check_def.h>
#include <fidl/findings.h>
#include <fidl/linting_tree_callbacks.h>
#include <fidl/tree_visitor.h>
#include <fidl/utils.h>

namespace fidl {
namespace linter {

// The primary business logic for lint-checks on a FIDL file is implemented in
// the |Linter| class. This class is not thread safe.
class Linter {
 public:
  // On initialization, the |Linter| constructs the |CheckDef|
  // objects with associated check logic (lambdas registered via
  // |CheckCallbacks|).
  Linter();

  // If a user specifies the command line flag --include-check=<check-id>
  // (one or more times) without any --exclude_check flags, the default
  // state is to exclude all checks EXCEPT those specifically indicated.
  void set_exclude_by_default(bool exclude_by_default) { exclude_by_default_ = exclude_by_default; }

  // Copies the given list of check-ids to be included, if otherwise excluded or disabled.
  // By default, all checks are included unless explicitly disabled (see linter/main.cc), excluded
  // by command line option, or if |excluded_by_default| is set to true.
  void set_included_checks(const std::set<std::string>& included_check_ids) {
    included_check_ids_ = included_check_ids;
  }

  // Copies the given list of check-ids to be excluded, unless |exclude_by_default| is true, in
  // which case, all checks are excluded if not explicitly included.
  void set_excluded_checks(const std::set<std::string>& excluded_check_ids) {
    excluded_check_ids_ = excluded_check_ids;
  }

  // Calling Lint() invokes the callbacks for elements
  // of the given |SourceFile|. If a check fails, the callback generates a
  // |Finding| and adds it to the given Findings (vector of Finding).
  // Lint() is single-threaded, and modifies state of the |Linter| class
  // as it evaluates a single file at a time.
  //
  // * parsed_source - The abstract syntax tree (AST) returned from the FIDL Parser.
  // * findings - a std::list of Finding objects (ordered by filename and location) to add
  //   additional Finding objects to, if triggered for a check. The list may or may not be
  //   empty.
  // * excluded_checks_not_found (optional) - If not nullptr, excluded_checks_not_found is a
  //   pointer to the caller's std::set of check-ids that were
  //   excluded and have not yet been removed via a pevious invocation of Lint() (if any). If this
  //   set is not empty, and a matching check-id is triggered, remove the check-id. An error
  //   status will be returned by the linter program, after all files have been linted, if any
  //   excluded check IDs remain in this set.
  //
  // Returns true if no new findings were generated.
  bool Lint(std::unique_ptr<raw::File> const& parsed_source, Findings* findings,
            std::set<std::string>* excluded_checks_not_found);

  bool Lint(std::unique_ptr<raw::File> const& parsed_source, Findings* findings) {
    return Lint(parsed_source, findings, nullptr);
  }

 private:
  // Holds function pointers for an identify case type. For example,
  // for "UpperCamelCase" type, |matches| points to is_upper_camel_case()
  // and |convert| points to to_upper_camel_case().
  struct CaseType {
    fit::function<bool(std::string)> matches;
    fit::function<std::string(std::string)> convert;
  };

  // Holds information about a nesting context in a FIDL file, for checks
  // that must compare information about the context with information about
  // a nested entity. The outer-most context is the FIDL file itself
  // (including the file's declared library name). Contexts nested in a
  // file's context include type definitions with nested entities, such as
  // enum, bits, struct, table, and union.
  class Context {
   public:
    struct RepeatsContextNames;

    Context(std::string type, std::string id, CheckDef context_check)
        : type_(type), id_(id), context_check_(context_check) {}

    // Enables move construction and assignment
    Context(Context&& rhs) = default;
    Context& operator=(Context&&) = default;

    // no copy or assign (move-only or pass by reference)
    Context(const Context&) = delete;
    Context& operator=(const Context&) = delete;

    std::string type() const { return type_; }

    std::string id() const { return id_; }

    // A |vector| of information about potential violations of the FIDL rubric
    // rule that prohibits repeating names from the outer type or library.
    // Exceptions to this rule cannot be determined until all nested identifiers
    // are reviewed, so this vector saves the required information until that
    // time.
    std::vector<RepeatsContextNames>& name_repeaters() { return name_repeaters_; }

    const std::set<std::string>& words() {
      if (words_.empty()) {
        auto words = utils::id_to_words(id_);
        words_.insert(words.begin(), words.end());
      }
      return words_;
    }

    const CheckDef& context_check() const { return context_check_; }

    template <typename... Args>
    void AddRepeatsContextNames(Args&&... args) {
      name_repeaters_.emplace_back(args...);
    }

    // Stores minimum information needed to construct a |Finding| if a
    // nested identifier repeats names from one of its contexts.
    // Determination is deferred until all nested identifiers are evaluated
    // because some cases of repeated names are allowed if the repeated
    // names help differentiate two identifiers that represent different
    // parts of the concept represented by the context identifier.
    struct RepeatsContextNames {
      RepeatsContextNames(std::string a_type, SourceSpan a_span, std::set<std::string> a_repeats)
          : type(std::move(a_type)), span(a_span), repeats(std::move(a_repeats)) {}

      const std::string type;
      const SourceSpan span;
      const std::set<std::string> repeats;
    };

   private:
    std::string type_;
    std::string id_;
    std::set<std::string> words_;
    CheckDef context_check_;
    std::vector<RepeatsContextNames> name_repeaters_;
  };

  const std::set<std::string>& permitted_library_prefixes() const;
  std::string kPermittedLibraryPrefixesas_string() const;

  CheckDef DefineCheck(std::string check_id, std::string message_template);

  Finding* AddFinding(SourceSpan source_span, std::string check_id, std::string message);

  const Finding* AddFinding(SourceSpan span, const CheckDef& check,
                            Substitutions substitutions = {}, std::string suggestion_template = "",
                            std::string replacement_template = "");

  template <typename SourceElementSubtypeRefOrPtr>
  const Finding* AddFinding(const SourceElementSubtypeRefOrPtr& element, const CheckDef& check,
                            Substitutions substitutions = {}, std::string suggestion_template = "",
                            std::string replacement_template = "");

  const Finding* AddRepeatedNameFinding(const Context& context,
                                        const Context::RepeatsContextNames& name_repeater);

  bool CurrentLibraryIsPlatformSourceLibrary();
  bool CurrentFileIsInPlatformSourceTree();

  // Initialization and checks at the start of a new file. The |Linter|
  // can be called multiple times with many different files.
  void NewFile(const raw::File& element);

  // If a finding was added, return a pointer to that finding.
  const Finding* CheckCase(std::string type, const std::unique_ptr<raw::Identifier>& identifier,
                           const CheckDef& check_def, const CaseType& case_type);

  // CheckRepeatedName() does not add Finding objects immediately. It checks for
  // potential violations, but must wait until ExitContext() so the potential
  // violation can be compared to its peers.
  void CheckRepeatedName(std::string type, const std::unique_ptr<raw::Identifier>& id);

  template <typename... Args>
  void EnterContext(Args&&... args) {
    context_stack_.emplace_front(args...);
  }

  // Pops the context stack. If any contained types repeat names from the
  // context, this function compares the nested identifiers with each other.
  // If two nested identifiers repeat different names from the context,
  // assume the repeated names were necessary in order to disambiguate the
  // concepts represented by each of the nested entities. If not, add Finding
  // objects for violating the repeated name rule.
  void ExitContext();

  std::string GetCopyrightSuggestion();
  void AddInvalidCopyrightFinding(SourceSpan span);
  void CheckInvalidCopyright(SourceSpan span, std::string line_comment, std::string line_to_match);
  bool CopyrightCheckIsComplete();

  std::string MakeCopyrightBlock();

  // All check types created in during |Linter| construction. The |std::set|
  // ensures each CheckDef has a unique |id|, and an iterator will traverse
  // the set in lexicographical order.
  // Must be defined before constant checks.
  std::set<CheckDef> checks_;

  // const variables not trivially destructible (static storage is forbidden)
  // (https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables)
  const CheckDef kLibraryNameDepthCheck;
  const CheckDef kLibraryNameComponentCheck;
  const CheckDef kRepeatsLibraryNameCheck;
  const CheckDef kLibraryPrefixCheck;
  const CheckDef kInvalidCopyrightCheck;

  const std::vector<std::string> kCopyrightLines;
  const std::string kCopyrightBlock;
  const std::string kDocAttribute;
  const std::regex kYearRegex;
  const std::regex kDocCommentRegex;
  const std::regex kDisallowedLibraryComponentRegex;

  const std::set<std::string> kPermittedLibraryPrefixes;
  const std::set<std::string> kStopWords;

  std::deque<Context> context_stack_;

  size_t line_comments_checked_ = 0;

  // Set to true for the first line that does not match the standard
  // Copyright block (if checked) so subsequent lines do not have to
  // be checked. (Prevents duplicate findings.)
  bool added_invalid_copyright_finding_ = false;

  // If good copyright lines
  size_t good_copyright_lines_found_ = 0;

  // 4 digits assumed to be the intended copyright date.
  std::string copyright_date_;

  // true if a const declaration was entered, and not yet exited.
  bool in_const_declaration_ = false;

  // The first name in the FIDL library declaration; for example, for:
  //   library fidl.types;
  // |library_prefix_| will be "fidl"
  std::string library_prefix_;
  bool library_is_platform_source_library_;

  std::string filename_;
  bool file_is_in_platform_source_tree_;

  enum class LintStyle {
    IpcStyle,
    CStyle,
  };
  LintStyle lint_style_;

  LintingTreeCallbacks callbacks_;

  // Case type functions used by CheckCase().
  CaseType lower_snake_{utils::is_lower_snake_case, utils::to_lower_snake_case};
  CaseType upper_snake_{utils::is_upper_snake_case, utils::to_upper_snake_case};
  CaseType upper_camel_{utils::is_upper_camel_case, utils::to_upper_camel_case};

  // In IpcStyle, bits, protocols, protocol methods, structs, tables, unions,
  // and enums use UpperCamelCase. In CStyle used for syscalls, they
  // use lower_camel_case. This member is set in NewFile once the style that's
  // being used has been determined.
  CheckDef invalid_case_for_decl_name_{"", TemplateString()};
  const CheckDef& invalid_case_for_decl_name() const { return invalid_case_for_decl_name_; }

  const CaseType& decl_case_type_for_style() const {
    switch (lint_style_) {
      case LintStyle::IpcStyle:
        return upper_camel_;
      case LintStyle::CStyle:
        return lower_snake_;
    }
  }

  bool exclude_by_default_ = false;
  std::set<std::string> included_check_ids_;
  std::set<std::string> excluded_check_ids_;

  using FindingPtr = std::unique_ptr<Finding>;

  // Compare type provides the function for ordering elements in the set, and
  // ensuring elements are set-wise unique. The current assumption is that no
  // two findings from the same subcategory at the same location are expected.
  // By including both source span and subcategory, all expected Findings
  // will be unique, and any Finding added with the same location and
  // subcategory as another will be considered a bug.
  struct FindingPtrCompare {
    // Return true if lhs < rhs.
    bool operator()(const FindingPtr& lhs, const FindingPtr& rhs) const {
      return lhs->span() < rhs->span() ||
             (lhs->span() == rhs->span() && lhs->subcategory() < rhs->subcategory());
    }
  };

  // An ordered collection of |std::unique_ptr| to |Finding| objects,
  // populated only for the duration of the Visit(), to lint a given FIDL
  // file.
  //
  // Some lint checks can only be assessed after processing more of the FIDL
  // (for example, "name-repeats-enclosing-type-name" checks cannot be added
  // until all members of the enclosing type are available). Other checks on
  // the same members will be added as they are encountered. Since |Finding|
  // objects are collected out of source order, an ordered collecttion
  // ensures |Finding| objects are in sorted order.
  //
  // |Finding| objects must be returned in source order (filename, starting
  // character, and ending character).
  //
  // |Finding| objects are sorted by SourceSpan, with additional criteria
  // to sort multiple findings for the same source element. If a Finding is
  // added to an ordered collection that does not allow duplicates, and the
  // sort criteria is not specific enough to avoid a key collision, an
  // assertion error will halt the program, to be resolved either by adding
  // additional sort criteriea or changing the Finding objects to ensure
  // uinqueness.
  //
  // When the Visit() is over, the |Finding| objects are transferred, in order
  // (by filename and source location of each finding, with any duplicates
  // also included in the order they were discovered/added) into the |Findings|
  // list passed into the Lint() method, and |current_findings_| is cleared.
  std::set<FindingPtr, FindingPtrCompare> current_findings_;
};

}  // namespace linter
}  // namespace fidl
#endif  // ZIRCON_TOOLS_FIDL_INCLUDE_FIDL_LINTER_H_
