blob: e12de51facc1894b406eff5739dc98a43eda8c4a [file] [log] [blame]
// 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.
// File for registering lint rules so that they can by dynamically turned on
// and off at runtime. The goal is to provide a single place to register
// lint rules.
//
// To register an implemented rule, call
// VERILOG_REGISTER_LINT_RULE in source file.
//
// This will have the following effects:
// 1. Allow that rule to be used in commandline flags that accept vectors
// of LintRuleEnum's
// 2. Allow the rule to be used by any component that dynamically loads
// rules from LintRuleRegistry
//
#ifndef VERIBLE_VERILOG_ANALYSIS_LINT_RULE_REGISTRY_H_
#define VERIBLE_VERILOG_ANALYSIS_LINT_RULE_REGISTRY_H_
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "common/analysis/line_lint_rule.h"
#include "common/analysis/syntax_tree_lint_rule.h"
#include "common/analysis/text_structure_lint_rule.h"
#include "common/analysis/token_stream_lint_rule.h"
#include "common/strings/compare.h"
#include "verilog/analysis/descriptions.h"
namespace verilog {
namespace analysis {
template <typename RuleType>
class LintRuleRegisterer;
using LintRuleId = absl::string_view;
template <typename RuleType>
using LintRuleGenerator = std::function<std::unique_ptr<RuleType>()>;
using LintDescription = std::function<std::string(DescriptionType)>;
template <typename RuleType>
struct LintRuleInfo {
LintRuleGenerator<RuleType> lint_rule_generator;
LintDescription description;
};
struct LintRuleDescriptionInfo {
std::string description;
bool default_enabled = false;
};
using LintRuleDescriptionsMap =
std::map<LintRuleId, LintRuleDescriptionInfo, verible::StringViewCompare>;
// Helper macro to register a LintRule with LintRuleRegistry. In order to have
// a global registry, some static initialization is needed. This macros
// centralizes this unsafe code into one place in order to prevent mistakes.
//
// Args:
// class_name: the name of the class to register
//
// Usage:
// (in my_lint_rule.h):
// class MyLintRule : LintRuleType {
// public:
// using rule_type = LintRuleType;
// static absl::string_view Name();
// static std::string GetDescription(DescriptionType);
// ... implement internals ...
// }
//
// (in my_lint_rule.cc):
// VERILOG_REGISTER_LINT_RULE(MyLintRule);
//
// Name() needs to be a function and not a constant to guarantee proper
// string initialization (from first invocation during static global
// initialization, when registration happens), and must be backed by string
// memory with guaranteed lifetime. e.g.
//
// absl::string_view MyLintRule::Name() {
// return "my-lint-rule"; // safely initialized function-local string literal
// }
//
#define VERILOG_REGISTER_LINT_RULE(class_name) \
static verilog::analysis::LintRuleRegisterer<class_name::rule_type> \
__##class_name##__registerer( \
class_name::Name(), \
[]() { \
return std::unique_ptr<class_name::rule_type>(new class_name()); \
}, \
class_name::GetDescription);
// Static objects of type LintRuleRegisterer are used to register concrete
// parsers in LintRuleRegistry. Users are expected to create these objects
// using the VERILOG_REGISTER_LINT_RULE macro.
template <typename RuleType>
class LintRuleRegisterer {
public:
LintRuleRegisterer(const LintRuleId& rule,
const LintRuleGenerator<RuleType>& creator,
const LintDescription& descriptor);
};
// Returns true if rule_name refers to a known lint rule.
bool IsRegisteredLintRule(const LintRuleId& rule_name);
// Returns sequence of syntax tree rule names.
std::vector<LintRuleId> RegisteredSyntaxTreeRulesNames();
// Returns a syntax tree lint rule object corresponding the rule_name.
std::unique_ptr<verible::SyntaxTreeLintRule> CreateSyntaxTreeLintRule(
const LintRuleId& rule_name);
// Returns sequence of token stream rule names.
std::vector<LintRuleId> RegisteredTokenStreamRulesNames();
// Returns a token stream lint rule object corresponding the rule_name.
std::unique_ptr<verible::TokenStreamLintRule> CreateTokenStreamLintRule(
const LintRuleId& rule_name);
// Returns sequence of line rule names.
std::vector<LintRuleId> RegisteredLineRulesNames();
// Returns a token stream lint rule object corresponding the rule_name.
std::unique_ptr<verible::LineLintRule> CreateLineLintRule(
const LintRuleId& rule_name);
// Returns sequence of text structure rule names.
std::vector<LintRuleId> RegisteredTextStructureRulesNames();
// Returns a token stream lint rule object corresponding the rule_name.
std::unique_ptr<verible::TextStructureLintRule> CreateTextStructureLintRule(
const LintRuleId& rule_name);
// Returns set of all registered lint rule names.
// When storing string_views to the lint rule keys, use the ones returned in
// this set, because their lifetime is guaranteed by the registration process.
std::set<LintRuleId> GetAllRegisteredLintRuleNames();
// Returns a map mapping each rule to a struct of information about the rule to
// print.
LintRuleDescriptionsMap GetAllRuleDescriptionsHelpFlag();
// Returns a map mapping each rule to a struct of information about the rule in
// order to create the markdown describing the lint rules.
LintRuleDescriptionsMap GetAllRuleDescriptionsMarkdown();
} // namespace analysis
} // namespace verilog
#endif // VERIBLE_VERILOG_ANALYSIS_LINT_RULE_REGISTRY_H_