// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "verilog/analysis/checkers/package_filename_rule.h"

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "common/analysis/lint_rule_status.h"
#include "common/analysis/syntax_tree_search.h"
#include "common/text/config_utils.h"
#include "common/text/text_structure.h"
#include "common/text/token_info.h"
#include "common/util/file_util.h"
#include "verilog/CST/package.h"
#include "verilog/analysis/descriptions.h"
#include "verilog/analysis/lint_rule_registry.h"

namespace verilog {
namespace analysis {

using verible::LintRuleStatus;
using verible::TextStructureView;

// Register the lint rule
VERILOG_REGISTER_LINT_RULE(PackageFilenameRule);

static const char optional_suffix[] = "_pkg";

static const char kMessage[] =
    "Package declaration name must match the file name "
    "(ignoring optional \"_pkg\" file name suffix).  ";

const LintRuleDescriptor& PackageFilenameRule::GetDescriptor() {
  static const LintRuleDescriptor d{
      .name = "package-filename",
      .topic = "file-names",
      .desc =
          "Checks that the package name matches the filename. Depending on "
          "configuration, it is also allowed to replace underscore with dashes "
          "in filenames.",
      .param = {{"allow-dash-for-underscore", "false",
                 "Allow dashes in the filename corresponding to the "
                 "underscores in the package"}},
  };
  return d;
}

void PackageFilenameRule::Lint(const TextStructureView& text_structure,
                               absl::string_view filename) {
  const auto& tree = text_structure.SyntaxTree();
  if (tree == nullptr) return;

  // Find all package declarations.
  auto package_matches = FindAllPackageDeclarations(*tree);

  // See if names match the stem of the filename.
  //
  // Note:  package name | filename   | allowed ?
  //        -------------+------------+-----------
  //        foo          | foo.sv     | yes
  //        foo_bar      | foo_bar.sv | yes
  //        foo_bar      | foo-bar.sv | yes, if allow-dash-for-underscore
  //        foo          | foo_pkg.sv | yes
  //        foo          | foo-pkg.sv | yes, iff allow-dash-for-underscore
  //        foo_pkg      | foo_pkg.sv | yes
  //        foo_pkg      | foo.sv     | NO.
  const absl::string_view basename =
      verible::file::Basename(verible::file::Stem(filename));
  std::vector<absl::string_view> basename_components =
      absl::StrSplit(basename, '.');
  std::string unitname(basename_components[0].begin(),
                       basename_components[0].end());
  if (unitname.empty()) return;

  if (allow_dash_for_underscore_) {
    // If we allow for dashes, let's first convert them back to underscore.
    std::replace(unitname.begin(), unitname.end(), '-', '_');
  }

  // Report a violation on every package declaration, potentially.
  for (const auto& package_match : package_matches) {
    const verible::TokenInfo* package_name_token =
        GetPackageNameToken(*package_match.match);
    if (!package_name_token) continue;
    absl::string_view package_id = package_name_token->text();
    auto package_id_plus_suffix = absl::StrCat(package_id, optional_suffix);
    if ((package_id != unitname) && (package_id_plus_suffix != unitname)) {
      violations_.insert(verible::LintViolation(
          *package_name_token,
          absl::StrCat(kMessage, "declaration: \"", package_id,
                       "\" vs. basename(file): \"", unitname, "\"")));
    }
  }
}

LintRuleStatus PackageFilenameRule::Report() const {
  return LintRuleStatus(violations_, GetDescriptor());
}

absl::Status PackageFilenameRule::Configure(absl::string_view configuration) {
  using verible::config::SetBool;
  return verible::ParseNameValues(
      configuration,
      {{"allow-dash-for-underscore", SetBool(&allow_dash_for_underscore_)}});
}
}  // namespace analysis
}  // namespace verilog
