diff --git a/clang/include/clang/Tooling/Refactoring/Transformer.h b/clang/include/clang/Tooling/Refactoring/Transformer.h --- a/clang/include/clang/Tooling/Refactoring/Transformer.h +++ b/clang/include/clang/Tooling/Refactoring/Transformer.h @@ -44,12 +44,18 @@ Name, }; -using TextGenerator = - std::function; - -/// Wraps a string as a TextGenerator. +// \c TextGenerator may fail because it processes dynamically-bound match +// results. For example, a typo in the name of a bound node can lead to a +// failure in the string generation code. We prefer to return \c Expected rather +// than assert on such failures to allow this code to be run in a variety of +// settings (including servers). +using TextGenerator = std::function( + const ast_matchers::MatchFinder::MatchResult &)>; + +/// Wraps a string as a (trivially successful) TextGenerator. inline TextGenerator text(std::string M) { - return [M](const ast_matchers::MatchFinder::MatchResult &) { return M; }; + return [M](const ast_matchers::MatchFinder::MatchResult &) + -> Expected { return M; }; } // Description of a source-code edit, expressed in terms of an AST node. diff --git a/clang/lib/Tooling/Refactoring/Transformer.cpp b/clang/lib/Tooling/Refactoring/Transformer.cpp --- a/clang/lib/Tooling/Refactoring/Transformer.cpp +++ b/clang/lib/Tooling/Refactoring/Transformer.cpp @@ -157,12 +157,16 @@ Edit.Target, It->second, Edit.Kind, Edit.Part, *Result.Context); if (auto Err = RangeOrErr.takeError()) return std::move(Err); - Transformation T; - T.Range = *RangeOrErr; - if (T.Range.isInvalid() || - isOriginMacroBody(*Result.SourceManager, T.Range.getBegin())) + auto &Range = *RangeOrErr; + if (Range.isInvalid() || + isOriginMacroBody(*Result.SourceManager, Range.getBegin())) return SmallVector(); - T.Replacement = Edit.Replacement(Result); + auto ReplacementOrErr = Edit.Replacement(Result); + if (auto Err = ReplacementOrErr.takeError()) + return std::move(Err); + Transformation T; + T.Range = Range; + T.Replacement = std::move(*ReplacementOrErr); Transformations.push_back(std::move(T)); } return Transformations;