blob: 7b859a97782391e94334da56d0430645194f6707 [file] [log] [blame] [edit]
// 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/lint_rule_status.h"
#include <algorithm>
#include <functional>
#include <iterator>
#include <ostream>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "common/strings/line_column_map.h"
#include "common/text/concrete_syntax_leaf.h"
#include "common/text/symbol.h"
#include "common/text/syntax_tree_context.h"
#include "common/text/token_info.h"
#include "common/text/tree_utils.h"
namespace verible {
static TokenInfo SymbolToToken(const Symbol& root) {
const auto* leaf = GetLeftmostLeaf(root);
if (leaf) {
return leaf->get();
}
// There shouldn't be any leaf-less subtrees.
return TokenInfo::EOFToken();
}
LintViolation::LintViolation(const Symbol& root, const std::string& reason,
const SyntaxTreeContext& context)
: root(&root),
token(SymbolToToken(root)),
reason(reason),
context(context) {}
void LintStatusFormatter::FormatLintRuleStatus(std::ostream* stream,
const LintRuleStatus& status,
absl::string_view base,
absl::string_view path) const {
for (const auto& violation : status.violations) {
FormatViolation(stream, violation, base, path, status.url,
status.lint_rule_name);
(*stream) << std::endl;
}
}
struct LintViolationWithStatus {
const LintViolation* violation;
const LintRuleStatus* status;
LintViolationWithStatus(const LintViolation* v, const LintRuleStatus* s)
: violation(v), status(s) {}
bool operator<(const LintViolationWithStatus& r) const {
// compares addresses which correspond to locations within the same string
return violation->token.text().data() < r.violation->token.text().data();
}
};
void LintStatusFormatter::FormatLintRuleStatuses(
std::ostream* stream, const std::vector<LintRuleStatus>& statuses,
absl::string_view base, absl::string_view path) const {
std::set<LintViolationWithStatus> violations;
// TODO(fangism): rewrite as a linear time merge of pre-ordered sub-sequences
for (auto& status : statuses) {
for (auto& violation : status.violations) {
violations.insert(LintViolationWithStatus(&violation, &status));
}
}
for (auto violation : violations) {
FormatViolation(stream, *violation.violation, base, path,
violation.status->url, violation.status->lint_rule_name);
*stream << std::endl;
}
}
// Formats and outputs violation on stream
// Path is file path of original file and url is a link to violated rule
void LintStatusFormatter::FormatViolation(std::ostream* stream,
const LintViolation& violation,
absl::string_view base,
absl::string_view path,
absl::string_view url,
absl::string_view rule_name) const {
// TODO(fangism): Use the context member to print which named construct or
// design element the violation appears in (or full stack thereof).
(*stream) << path << ':' << line_column_map_(violation.token.left(base))
<< ": " << violation.reason << ' ' << url << " [" << rule_name
<< ']';
}
void LintRuleStatus::WaiveViolations(
std::function<bool(const LintViolation&)>&& is_waived) {
std::set<LintViolation> filtered_violations;
std::remove_copy_if(
violations.begin(), violations.end(),
std::inserter(filtered_violations, filtered_violations.begin()),
is_waived);
violations.swap(filtered_violations);
}
} // namespace verible