diff options
author | Alex Lorenz <arphaman@gmail.com> | 2017-10-16 18:28:26 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2017-10-16 18:28:26 +0000 |
commit | 6de2efd1953adaa9a190b2cdfbe7b5c15f6d6efe (patch) | |
tree | 1728368a264c212d5c7d90e5d03e247bb5a0afc7 /tools/clang-refactor | |
parent | e9ec96ff9701eec60e4bafd9b3e5b2daa6b101cc (diff) | |
download | clang-6de2efd1953adaa9a190b2cdfbe7b5c15f6d6efe.tar.gz |
[refactor] allow the use of refactoring diagnostics
This commit allows the refactoring library to use its own set of
refactoring-specific diagnostics to reports things like initiation errors.
Differential Revision: https://reviews.llvm.org/D38772
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@315924 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/clang-refactor')
-rw-r--r-- | tools/clang-refactor/ClangRefactor.cpp | 35 | ||||
-rw-r--r-- | tools/clang-refactor/TestSupport.cpp | 18 | ||||
-rw-r--r-- | tools/clang-refactor/TestSupport.h | 4 | ||||
-rw-r--r-- | tools/clang-refactor/ToolRefactoringResultConsumer.h | 48 |
4 files changed, 89 insertions, 16 deletions
diff --git a/tools/clang-refactor/ClangRefactor.cpp b/tools/clang-refactor/ClangRefactor.cpp index 8a5c8e6630..ed9bf5ed28 100644 --- a/tools/clang-refactor/ClangRefactor.cpp +++ b/tools/clang-refactor/ClangRefactor.cpp @@ -15,6 +15,7 @@ #include "TestSupport.h" #include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Tooling/CommonOptionsParser.h" #include "clang/Tooling/Refactoring.h" @@ -65,7 +66,8 @@ public: /// logic into the refactoring operation. The test-specific consumer /// ensures that the individual results in a particular test group are /// identical. - virtual std::unique_ptr<RefactoringResultConsumer> createCustomConsumer() { + virtual std::unique_ptr<ClangRefactorToolConsumerInterface> + createCustomConsumer() { return nullptr; } @@ -85,7 +87,8 @@ public: void print(raw_ostream &OS) override { TestSelections.dump(OS); } - std::unique_ptr<RefactoringResultConsumer> createCustomConsumer() override { + std::unique_ptr<ClangRefactorToolConsumerInterface> + createCustomConsumer() override { return TestSelections.createConsumer(); } @@ -304,10 +307,20 @@ private: RefactoringActionCommandLineOptions Options; }; -class ClangRefactorConsumer : public RefactoringResultConsumer { +class ClangRefactorConsumer final : public ClangRefactorToolConsumerInterface { public: + ClangRefactorConsumer() {} + void handleError(llvm::Error Err) override { - llvm::errs() << llvm::toString(std::move(Err)) << "\n"; + Optional<PartialDiagnosticAt> Diag = DiagnosticError::take(Err); + if (!Diag) { + llvm::errs() << llvm::toString(std::move(Err)) << "\n"; + return; + } + llvm::cantFail(std::move(Err)); // This is a success. + DiagnosticBuilder DB( + getDiags().Report(Diag->first, Diag->second.getDiagID())); + Diag->second.Emit(DB); } void handle(AtomicChanges Changes) override { @@ -468,8 +481,8 @@ public: return true; } - bool HasFailed = false; ClangRefactorConsumer Consumer; + bool HasFailed = false; if (foreachTranslationUnit(DB, Sources, [&](ASTContext &AST) { RefactoringRuleContext Context(AST.getSourceManager()); Context.setASTContext(AST); @@ -488,21 +501,27 @@ public: "The action must have at least one selection rule"); }; + std::unique_ptr<ClangRefactorToolConsumerInterface> CustomConsumer; + if (HasSelection) + CustomConsumer = Subcommand.getSelection()->createCustomConsumer(); + ClangRefactorToolConsumerInterface &ActiveConsumer = + CustomConsumer ? *CustomConsumer : Consumer; + ActiveConsumer.beginTU(AST); if (HasSelection) { assert(Subcommand.getSelection() && "Missing selection argument?"); if (opts::Verbose) Subcommand.getSelection()->print(llvm::outs()); - auto CustomConsumer = - Subcommand.getSelection()->createCustomConsumer(); if (Subcommand.getSelection()->forAllRanges( Context.getSources(), [&](SourceRange R) { Context.setSelectionRange(R); - InvokeRule(CustomConsumer ? *CustomConsumer : Consumer); + InvokeRule(ActiveConsumer); })) HasFailed = true; + ActiveConsumer.endTU(); return; } // FIXME (Alex L): Implement non-selection based invocation path. + ActiveConsumer.endTU(); })) return true; return HasFailed || applySourceChanges(Consumer.getSourceChanges()); diff --git a/tools/clang-refactor/TestSupport.cpp b/tools/clang-refactor/TestSupport.cpp index 66e1bb7807..2f127bd7f6 100644 --- a/tools/clang-refactor/TestSupport.cpp +++ b/tools/clang-refactor/TestSupport.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "TestSupport.h" +#include "clang/Basic/DiagnosticError.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" #include "llvm/ADT/STLExtras.h" @@ -106,7 +107,7 @@ bool printRewrittenSources(const tooling::AtomicChanges &Changes, } class TestRefactoringResultConsumer final - : public tooling::RefactoringResultConsumer { + : public ClangRefactorToolConsumerInterface { public: TestRefactoringResultConsumer(const TestSelectionRangesInFile &TestRanges) : TestRanges(TestRanges) { @@ -182,10 +183,15 @@ bool TestRefactoringResultConsumer::handleAllResults() { std::string ErrorMessage; bool HasResult = !!Result; if (!HasResult) { - // FIXME: Handle diagnostic error as well. - handleAllErrors(Result.takeError(), [&](StringError &Err) { - ErrorMessage = Err.getMessage(); - }); + handleAllErrors( + Result.takeError(), + [&](StringError &Err) { ErrorMessage = Err.getMessage(); }, + [&](DiagnosticError &Err) { + const PartialDiagnosticAt &Diag = Err.getDiagnostic(); + llvm::SmallString<100> DiagText; + Diag.second.EmitToString(getDiags(), DiagText); + ErrorMessage = DiagText.str().str(); + }); } if (!CanonicalResult && !CanonicalErrorMessage) { if (HasResult) @@ -248,7 +254,7 @@ bool TestRefactoringResultConsumer::handleAllResults() { return Failed; } -std::unique_ptr<tooling::RefactoringResultConsumer> +std::unique_ptr<ClangRefactorToolConsumerInterface> TestSelectionRangesInFile::createConsumer() const { return llvm::make_unique<TestRefactoringResultConsumer>(*this); } diff --git a/tools/clang-refactor/TestSupport.h b/tools/clang-refactor/TestSupport.h index 9d082a74ec..101f35bd94 100644 --- a/tools/clang-refactor/TestSupport.h +++ b/tools/clang-refactor/TestSupport.h @@ -16,9 +16,9 @@ #ifndef LLVM_CLANG_TOOLS_CLANG_REFACTOR_TEST_SUPPORT_H #define LLVM_CLANG_TOOLS_CLANG_REFACTOR_TEST_SUPPORT_H +#include "ToolRefactoringResultConsumer.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Error.h" @@ -65,7 +65,7 @@ struct TestSelectionRangesInFile { bool foreachRange(const SourceManager &SM, llvm::function_ref<void(SourceRange)> Callback) const; - std::unique_ptr<tooling::RefactoringResultConsumer> createConsumer() const; + std::unique_ptr<ClangRefactorToolConsumerInterface> createConsumer() const; void dump(llvm::raw_ostream &OS) const; }; diff --git a/tools/clang-refactor/ToolRefactoringResultConsumer.h b/tools/clang-refactor/ToolRefactoringResultConsumer.h new file mode 100644 index 0000000000..64a994d88b --- /dev/null +++ b/tools/clang-refactor/ToolRefactoringResultConsumer.h @@ -0,0 +1,48 @@ +//===--- ToolRefactoringResultConsumer.h - ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_CLANG_REFACTOR_TOOL_REFACTORING_RESULT_CONSUMER_H +#define LLVM_CLANG_TOOLS_CLANG_REFACTOR_TOOL_REFACTORING_RESULT_CONSUMER_H + +#include "clang/AST/ASTContext.h" +#include "clang/Tooling/Refactoring/RefactoringResultConsumer.h" + +namespace clang { +namespace refactor { + +/// An interface that subclasses the \c RefactoringResultConsumer interface +/// that stores the reference to the TU-specific diagnostics engine. +class ClangRefactorToolConsumerInterface + : public tooling::RefactoringResultConsumer { +public: + /// Called when a TU is entered. + void beginTU(ASTContext &Context) { + assert(!Diags && "Diags has been set"); + Diags = &Context.getDiagnostics(); + } + + /// Called when the tool is done with a TU. + void endTU() { + assert(Diags && "Diags unset"); + Diags = nullptr; + } + + DiagnosticsEngine &getDiags() const { + assert(Diags && "no diags"); + return *Diags; + } + +private: + DiagnosticsEngine *Diags = nullptr; +}; + +} // end namespace refactor +} // end namespace clang + +#endif // LLVM_CLANG_TOOLS_CLANG_REFACTOR_TOOL_REFACTORING_RESULT_CONSUMER_H |