// 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 "common/analysis/text_structure_linter.h"

#include <memory>
#include <vector>

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "common/analysis/lint_rule_status.h"
#include "common/analysis/text_structure_lint_rule.h"
#include "common/text/text_structure.h"
#include "common/text/token_info.h"

namespace verible {
namespace {

using testing::IsEmpty;
using testing::SizeIs;

// Example lint rule that uses raw contents and lines array.
class RequireHelloRule : public TextStructureLintRule {
 public:
  RequireHelloRule() {}

  void Lint(const TextStructureView& text_structure,
            absl::string_view filename) override {
    const auto& lines = text_structure.Lines();
    const absl::string_view contents = text_structure.Contents();
    if (!lines.empty() && !absl::StartsWith(contents, "Hello")) {
      const TokenInfo token(1, lines[0]);
      violations_.emplace(token, "Text must begin with Hello");
    }
  }

  LintRuleStatus Report() const override { return LintRuleStatus(violations_); }

 private:
  std::set<LintViolation> violations_;
};

std::unique_ptr<TextStructureLintRule> MakeHelloRule() {
  return std::unique_ptr<TextStructureLintRule>(new RequireHelloRule);
}

// This test verifies that TextStructureLinter works with no rules.
TEST(TextStructureLinterTest, NoRules) {
  const TextStructureView text_structure("Hello, world!\nGoodbye world.\n");
  TextStructureLinter linter;
  linter.Lint(text_structure, "");
  std::vector<LintRuleStatus> statuses = linter.ReportStatus();
  EXPECT_THAT(statuses, IsEmpty());
}

// This test verifies that TextStructureLinter works with a single rule.
TEST(TextStructureLinterTest, OneRuleAcceptsEmptyStream) {
  const TextStructureView text_structure("Hello, world!\nGoodbye world.\n");
  TextStructureLinter linter;
  linter.AddRule(MakeHelloRule());
  linter.Lint(text_structure, "");
  std::vector<LintRuleStatus> statuses = linter.ReportStatus();
  EXPECT_THAT(statuses, SizeIs(1));
  EXPECT_TRUE(statuses[0].isOk());
  EXPECT_THAT(statuses[0].violations, IsEmpty());
}

// This test verifies that TextStructureLinter can find violations.
TEST(TextStructureLinterTest, OneRuleRejectsTextStructure) {
  const TextStructureView text_structure("Goodbye cruel world.\n");
  TextStructureLinter linter;
  linter.AddRule(MakeHelloRule());
  linter.Lint(text_structure, "");
  std::vector<LintRuleStatus> statuses = linter.ReportStatus();
  EXPECT_THAT(statuses, SizeIs(1));
  EXPECT_FALSE(statuses[0].isOk());
  EXPECT_THAT(statuses[0].violations, SizeIs(1));
}

}  // namespace
}  // namespace verible
