| // Copyright 2017-2021 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_COMMON_ANALYSIS_VIOLATION_HANDLER_H_ | |
| #define VERIBLE_COMMON_ANALYSIS_VIOLATION_HANDLER_H_ | |
| #include <functional> | |
| #include <map> | |
| #include <ostream> | |
| #include <set> | |
| #include "absl/strings/string_view.h" | |
| #include "common/analysis/lint_rule_status.h" | |
| namespace verible { | |
| // Interface for implementing violation handlers. | |
| // | |
| // The linting process produces a list of violations found in source code. Those | |
| // violations are then sorted and passed to `HandleViolations()` method of an | |
| // instance passed to LintOneFile(). | |
| class ViolationHandler { | |
| public: | |
| virtual ~ViolationHandler() = default; | |
| // This method is called with a list of sorted violations found in file | |
| // located at `path`. It can be called multiple times with statuses generated | |
| // from different files. `base` contains source code from the file. | |
| virtual void HandleViolations( | |
| const std::set<verible::LintViolationWithStatus>& violations, | |
| absl::string_view base, absl::string_view path) = 0; | |
| }; | |
| // ViolationHandler that prints all violations in a form of user-friendly | |
| // messages. | |
| class ViolationPrinter : public ViolationHandler { | |
| public: | |
| explicit ViolationPrinter(std::ostream* stream) | |
| : stream_(stream), formatter_(nullptr) {} | |
| void HandleViolations( | |
| const std::set<verible::LintViolationWithStatus>& violations, | |
| absl::string_view base, absl::string_view path) override; | |
| protected: | |
| std::ostream* const stream_; | |
| verible::LintStatusFormatter* formatter_; | |
| }; | |
| // ViolationHandler that prints all violations in a format required by | |
| // --waiver_files flag | |
| class ViolationWaiverPrinter : public ViolationHandler { | |
| public: | |
| explicit ViolationWaiverPrinter(std::ostream* message_stream_, | |
| std::ostream* waiver_stream_) | |
| : message_stream_(message_stream_), | |
| waiver_stream_(waiver_stream_), | |
| formatter_(nullptr) {} | |
| void HandleViolations( | |
| const std::set<verible::LintViolationWithStatus>& violations, | |
| absl::string_view base, absl::string_view path) override; | |
| protected: | |
| std::ostream* const message_stream_; | |
| std::ostream* const waiver_stream_; | |
| verible::LintStatusFormatter* formatter_; | |
| }; | |
| // ViolationHandler that prints all violations and gives an option to fix those | |
| // that have autofixes available. | |
| // | |
| // By default, when violation has an autofix available, ViolationFixer asks an | |
| // user what to do. The answers can be provided by AnswerChooser callback passed | |
| // to the constructor as the answer_chooser parameter. The callback is called | |
| // once for each fixable violation with a current violation object and a | |
| // violated rule name as arguments, and must return one of the values from | |
| // AnswerChoice enum. | |
| // | |
| // When the constructor's patch_stream parameter is not null, the fixes are | |
| // written to specified stream in unified diff format. Otherwise the fixes are | |
| // applied directly to the source file. | |
| // | |
| // The HandleLintRuleStatuses method can be called multiple times with statuses | |
| // generated from different files. The state of answers like "apply all for | |
| // rule" or "apply all" is kept between the calls. | |
| class ViolationFixer : public verible::ViolationHandler { | |
| public: | |
| enum class AnswerChoice { | |
| kUnknown, | |
| kApply, // apply fix | |
| kReject, // reject fix | |
| kApplyAllForRule, // apply this and all remaining fixes for violations | |
| // of this rule | |
| kRejectAllForRule, // reject this and all remaining fixes for violations | |
| // of this rule | |
| kApplyAll, // apply this and all remaining fixes | |
| kRejectAll, // reject this and all remaining fixes | |
| kPrintFix, // show fix | |
| kPrintAppliedFixes, // show fixes applied so far | |
| }; | |
| struct Answer { | |
| AnswerChoice choice; | |
| // If there are multiple alternatives for fixes available, this is | |
| // the one chosen. By default the first one. | |
| size_t alternative = 0; | |
| }; | |
| using AnswerChooser = | |
| std::function<Answer(const verible::LintViolation&, absl::string_view)>; | |
| // Violation fixer with user-chosen answer chooser. | |
| ViolationFixer(std::ostream* message_stream, std::ostream* patch_stream, | |
| const AnswerChooser& answer_chooser) | |
| : ViolationFixer(message_stream, patch_stream, answer_chooser, false) {} | |
| // Violation fixer with interactive answer choice. | |
| ViolationFixer(std::ostream* message_stream, std::ostream* patch_stream) | |
| : ViolationFixer(message_stream, patch_stream, InteractiveAnswerChooser, | |
| true) {} | |
| void HandleViolations( | |
| const std::set<verible::LintViolationWithStatus>& violations, | |
| absl::string_view base, absl::string_view path) final; | |
| private: | |
| ViolationFixer(std::ostream* message_stream, std::ostream* patch_stream, | |
| const AnswerChooser& answer_chooser, bool is_interactive) | |
| : message_stream_(message_stream), | |
| patch_stream_(patch_stream), | |
| answer_chooser_(answer_chooser), | |
| is_interactive_(is_interactive), | |
| ultimate_answer_({AnswerChoice::kUnknown, 0}) {} | |
| void HandleViolation(const verible::LintViolation& violation, | |
| absl::string_view base, absl::string_view path, | |
| absl::string_view url, absl::string_view rule_name, | |
| const verible::LintStatusFormatter& formatter, | |
| verible::AutoFix* fix); | |
| static Answer InteractiveAnswerChooser( | |
| const verible::LintViolation& violation, absl::string_view rule_name); | |
| void CommitFixes(absl::string_view source_content, | |
| absl::string_view source_path, | |
| const verible::AutoFix& fix) const; | |
| std::ostream* const message_stream_; | |
| std::ostream* const patch_stream_; | |
| const AnswerChooser answer_chooser_; | |
| const bool is_interactive_; | |
| Answer ultimate_answer_; | |
| std::map<absl::string_view, Answer> rule_answers_; | |
| }; | |
| } // namespace verible | |
| #endif // VERIBLE_COMMON_ANALYSIS_VIOLATION_HANDLER_H_ |