Index: include-fixer/IncludeFixer.h =================================================================== --- include-fixer/IncludeFixer.h +++ include-fixer/IncludeFixer.h @@ -68,8 +68,9 @@ /// \param Header The header being inserted. /// \param Style clang-format style being used. /// -/// \return Replacements for inserting and sorting headers. -tooling::Replacements createInsertHeaderReplacements( +/// \return Replacements for inserting and sorting headers on success; +/// otherwise, an llvm::Error carrying llvm::StringError is returned. +llvm::Expected createInsertHeaderReplacements( StringRef Code, StringRef FilePath, StringRef Header, const clang::format::FormatStyle &Style = clang::format::getLLVMStyle()); Index: include-fixer/IncludeFixer.cpp =================================================================== --- include-fixer/IncludeFixer.cpp +++ include-fixer/IncludeFixer.cpp @@ -306,7 +306,7 @@ return !Compiler.getDiagnostics().hasFatalErrorOccurred(); } -tooling::Replacements +llvm::Expected createInsertHeaderReplacements(StringRef Code, StringRef FilePath, StringRef Header, const clang::format::FormatStyle &Style) { @@ -317,8 +317,11 @@ clang::tooling::Replacements Insertions = { tooling::Replacement(FilePath, UINT_MAX, 0, IncludeName)}; - return formatReplacements( - Code, cleanupAroundReplacements(Code, Insertions, Style), Style); + auto CleanReplaces = cleanupAroundReplacements(Code, Insertions, Style); + if (!CleanReplaces) + return CleanReplaces; + auto FormattedReplaces = formatReplacements(Code, *CleanReplaces, Style); + return FormattedReplaces; } } // namespace include_fixer Index: include-fixer/tool/ClangIncludeFixer.cpp =================================================================== --- include-fixer/tool/ClangIncludeFixer.cpp +++ include-fixer/tool/ClangIncludeFixer.cpp @@ -208,12 +208,21 @@ return 1; } - tooling::Replacements Replacements = + auto Replacements = clang::include_fixer::createInsertHeaderReplacements( Code->getBuffer(), FilePath, Context.Headers[0], InsertStyle); - std::string ChangedCode = - tooling::applyAllReplacements(Code->getBuffer(), Replacements); - llvm::outs() << ChangedCode; + if (!Replacements) { + errs() << "Failed to create header insertion replacement: " + << llvm::toString(Replacements.takeError()) << "\n"; + return 1; + } + auto ChangedCode = + tooling::applyAllReplacements(Code->getBuffer(), *Replacements); + if (!ChangedCode) { + llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n"; + return 1; + } + llvm::outs() << *ChangedCode; return 0; } @@ -249,10 +258,14 @@ } // FIXME: Rank the results and pick the best one instead of the first one. - tooling::Replacements Replacements = - clang::include_fixer::createInsertHeaderReplacements( - /*Code=*/Buffer.get()->getBuffer(), FilePath, Context.Headers.front(), - InsertStyle); + auto Replacements = clang::include_fixer::createInsertHeaderReplacements( + /*Code=*/Buffer.get()->getBuffer(), FilePath, Context.Headers.front(), + InsertStyle); + if (!Replacements) { + errs() << "Failed to create header insertion replacement: " + << llvm::toString(Replacements.takeError()) << "\n"; + return 1; + } if (!Quiet) llvm::errs() << "Added #include" << Context.Headers.front(); @@ -265,15 +278,19 @@ Diagnostics.setClient(&DiagnosticPrinter, false); if (STDINMode) { - std::string ChangedCode = - tooling::applyAllReplacements(Code->getBuffer(), Replacements); - llvm::outs() << ChangedCode; + auto ChangedCode = + tooling::applyAllReplacements(Code->getBuffer(), *Replacements); + if (!ChangedCode) { + llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n"; + return 1; + } + llvm::outs() << *ChangedCode; return 0; } // Write replacements to disk. Rewriter Rewrites(SM, LangOptions()); - tooling::applyAllReplacements(Replacements, Rewrites); + tooling::applyAllReplacements(*Replacements, Rewrites); return Rewrites.overwriteChangedFiles(); } Index: unittests/clang-tidy/ClangTidyTest.h =================================================================== --- unittests/clang-tidy/ClangTidyTest.h +++ unittests/clang-tidy/ClangTidyTest.h @@ -17,6 +17,7 @@ #include "clang/Frontend/FrontendActions.h" #include "clang/Tooling/Refactoring.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/Optional.h" #include #include @@ -121,7 +122,12 @@ Fixes.insert(Error.Fix.begin(), Error.Fix.end()); if (Errors) *Errors = Context.getErrors(); - return tooling::applyAllReplacements(Code, Fixes); + auto Result = tooling::applyAllReplacements(Code, Fixes); + if (!Result) { + // FIXME: propogate the error. + return ""; + } + return *Result; } #define EXPECT_NO_CHANGES(Check, Code) \ Index: unittests/include-fixer/IncludeFixerTest.cpp =================================================================== --- unittests/include-fixer/IncludeFixerTest.cpp +++ unittests/include-fixer/IncludeFixerTest.cpp @@ -85,12 +85,14 @@ runOnCode(&Factory, Code, "input.cc", ExtraArgs); if (FixerContext.Headers.empty()) return Code; - tooling::Replacements Replacements = - clang::include_fixer::createInsertHeaderReplacements( - Code, "input.cc", FixerContext.Headers.front()); + auto Replaces = clang::include_fixer::createInsertHeaderReplacements( + Code, "input.cc", FixerContext.Headers.front()); + EXPECT_TRUE((bool)Replaces) << llvm::toString(Replaces.takeError()) << "\n"; + if (!Replaces) + return ""; clang::RewriterTestContext Context; clang::FileID ID = Context.createInMemoryFile("input.cc", Code); - clang::tooling::applyAllReplacements(Replacements, Context.Rewrite); + clang::tooling::applyAllReplacements(*Replaces, Context.Rewrite); return Context.getRewrittenText(ID); }