| // 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. |
| |
| #ifndef VERIBLE_VERILOG_ANALYSIS_VERILOG_LINTER_CONFIGURATION_H_ |
| #define VERIBLE_VERILOG_ANALYSIS_VERILOG_LINTER_CONFIGURATION_H_ |
| |
| #include <iosfwd> |
| #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 "verilog/analysis/lint_rule_registry.h" |
| |
| namespace verilog { |
| |
| // Setting for a configuration |
| struct RuleSetting { |
| bool enabled; |
| std::string configuration; |
| }; |
| |
| // Enum denoting a ruleset |
| // kNone no rules are enabled |
| // kDefault default ruleset is enabled |
| // kAll all rules are enabled |
| enum class RuleSet { kNone, kDefault, kAll }; |
| |
| // Pair of functions that perform stringification and destringification |
| // in order to support commandline flags. |
| // |
| // AbslUnparseFlag takes the parsed representation of a ruleset |
| // and converts it into string representation. |
| std::string AbslUnparseFlag(const RuleSet& rules); |
| |
| // ParseFlags takes a source string text and a target Ruleset. |
| // It attempts to parse text into a RuleSet and put that RuleSet into rules |
| // If successful, returns true. |
| // Otherwise, sets string error to the a error message and returns false. |
| bool AbslParseFlag(absl::string_view text, RuleSet* rules, std::string* error); |
| |
| // Container class for parse/unparse flags |
| // Keys must be the exact string_views in registered maps (not just string |
| // equivalent) for the lifetime guarantee. |
| struct RuleBundle { |
| std::map<absl::string_view, RuleSetting> rules; |
| // Parse configuration from input. Separator between rules is 'separator', |
| // typically that would be a comma or newline. |
| bool ParseConfiguration(absl::string_view text, char separator, |
| std::string* error); |
| std::string UnparseConfiguration(const char separator) const; |
| }; |
| |
| // Pair of functions that perform stringification and destringification |
| // in order to support commandline flags. |
| // |
| // AbslUnparseFlag takes the parsed representation of a flag (RuleBundle) |
| // and converts it into string representation. |
| std::string AbslUnparseFlag(const RuleBundle& bundle); |
| |
| // ParseFlags takes a source string text and a target RuleBundle. |
| // It clears bundle and parses text into it by checking to make sure |
| // each rule is registered with the LintRuleRegistry. |
| // If a rule is prepended with '-', then it is mapped to RuleSetting::kRuleOff |
| // Otherwise, it is mapped to RuleSetting::kRuleOn |
| // If all rules are parsed successfully, returns true. |
| // Otherwise, sets string error to the a error message containing the |
| // invalid lint rule and returns false. |
| bool AbslParseFlag(absl::string_view text, RuleBundle* bundle, |
| std::string* error); |
| |
| // ProjectPolicy is needed in a transitional period when new rules are |
| // becoming enabled while pre-existing code is still following their |
| // respective project conventions and guidelines. These blanket waivers |
| // are intended to minimize agony on current projects, while allowing |
| // the full set of rules to take effect on new projects. |
| struct ProjectPolicy { |
| // A short name for policy, for diagnostic purposes. |
| absl::string_view name; |
| |
| // Raw string to check for being part of the path. Not a regex pattern. |
| // Apply this exemption only if substring occurs in the file path. |
| std::vector<const char*> path_substrings; |
| |
| // Raw string to check for being part of the path. Not a regex pattern. |
| // Files that match the exclusion will not be analyzed. |
| // This is suitable for paths that contain files that no human will ever |
| // read. |
| std::vector<const char*> path_exclusions; |
| |
| // Reviewers to involve for policy changes. At least two. |
| std::vector<const char*> owners; |
| |
| // Names of lint rules to disable. |
| std::vector<const char*> disabled_rules; |
| |
| // Names of lint rules to enable (takes precedence over disabled_rules). |
| std::vector<const char*> enabled_rules; |
| |
| // Returns a path if filename matches any of path_substrings, |
| // otherwise nullptr. |
| const char* MatchesAnyPath(absl::string_view filename) const; |
| |
| // Returns a path if filename matches any of path_exclusions, |
| // otherwise nullptr. |
| const char* MatchesAnyExclusions(absl::string_view filename) const; |
| |
| // Returns true if all disabled_rules and enabled_rules refer to registered |
| // rules. This helps catch typos. |
| bool IsValid() const; |
| |
| // Returns a glob pattern for shell case statement: "*path1* | *path2* | ..." |
| std::string ListPathGlobs() const; |
| }; |
| |
| struct LinterOptions { |
| // strings, ints, bools, and unprocessed values from flags, no other derived |
| // information. Reasonable default values may be specified here for each |
| // member |
| |
| // The base set of rules used by linter |
| const RuleSet ruleset; |
| // Bundle of rules to enable/disable in addition to the base set |
| const RuleBundle& rules; |
| // Path to a file with extra linter configuration, applied on top of the |
| // base 'ruleset' and extra 'rules' |
| std::string config_file; |
| // Indicates whether the 'config_file' is the default config file or a custom |
| // one |
| bool config_file_is_custom; |
| // Enables upward config file search |
| bool rules_config_search; |
| // Defines the starting point for the upward config search algorithm, |
| // usually set to the currently linted file |
| std::string linting_start_file; |
| // Path to the external waivers configuration file |
| std::string waiver_files; |
| }; |
| |
| // LinterConfiguration is used for tracking enabled lint rules |
| // Individual LintRules are defined LintRuleRegistry. Their names are the |
| // strings that they are registered under. |
| // |
| // Usage |
| // LinterConfiguration config; |
| // config.UseRuleSet(RuleSet::kDefault); |
| // config.TurnOn("rule-1"); |
| // config.TurnOn("rule-2"); |
| // linter.Configure(config); |
| // |
| class LinterConfiguration { |
| public: |
| // Constructor has no rules enabled by default; |
| LinterConfiguration() {} |
| |
| // This is copy-able. |
| LinterConfiguration(const LinterConfiguration&) = default; |
| |
| void TurnOn(const analysis::LintRuleId& rule) { |
| configuration_[rule] = {true, ""}; |
| } |
| |
| void TurnOff(const analysis::LintRuleId& rule) { |
| configuration_[rule] = {false, ""}; |
| } |
| |
| bool RuleIsOn(const analysis::LintRuleId& rule) const; |
| |
| // Clears configuration and updates to passed ruleset. |
| // Behavior is as follows: |
| // RuleSet::kAll Turns on all registered rules |
| // RuleSet::kNone Turns off all rules |
| // RuleSet::kDefault Turns on default set of rules as defined in |
| // analysis/default_rules.h |
| // |
| // Note that additional rules can be layered on top of a ruleset via |
| // TurnOn/TurnOff/UseRuleBundle. |
| void UseRuleSet(const RuleSet& rules); |
| |
| // Updates LinterConfiguration to enabled/disable all lint rules |
| // in rule_bundle |
| void UseRuleBundle(const RuleBundle& rule_bundle); |
| |
| // Adjust set of active rules based on the filename. |
| void UseProjectPolicy(const ProjectPolicy& policy, |
| absl::string_view filename); |
| |
| // Return the keys of enabled lint rules, sorted. |
| std::set<analysis::LintRuleId> ActiveRuleIds() const; |
| |
| // Creates instances of every enabled syntax tree rule |
| std::vector<std::unique_ptr<verible::SyntaxTreeLintRule>> |
| CreateSyntaxTreeRules() const; |
| |
| // Creates instances of every enabled token stream rule |
| std::vector<std::unique_ptr<verible::TokenStreamLintRule>> |
| CreateTokenStreamRules() const; |
| |
| // Creates instances of every enabled line rule |
| std::vector<std::unique_ptr<verible::LineLintRule>> CreateLineRules() const; |
| |
| // Creates instances of every enabled text structure lint rule |
| std::vector<std::unique_ptr<verible::TextStructureLintRule>> |
| CreateTextStructureRules() const; |
| |
| // Path to external lint waivers configuration file |
| std::string external_waivers; |
| |
| // Returns true if configurations are equivalent. |
| bool operator==(const LinterConfiguration&) const; |
| |
| bool operator!=(const LinterConfiguration& r) const { return !(*this == r); } |
| |
| // Appends linter rules configuration from a file |
| absl::Status AppendFromFile(absl::string_view filename); |
| |
| // Generates configuration forn LinterOptions |
| absl::Status ConfigureFromOptions(const LinterOptions& options); |
| |
| private: |
| // map of all enabled rules |
| std::map<analysis::LintRuleId, RuleSetting> configuration_; |
| }; |
| |
| std::ostream& operator<<(std::ostream&, const LinterConfiguration&); |
| |
| } // namespace verilog |
| |
| #endif // VERIBLE_VERILOG_ANALYSIS_VERILOG_LINTER_CONFIGURATION_H_ |