| // 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_ |