14#include "llvm/Support/Error.h"
15#include "gmock/gmock.h"
16#include "gtest/gtest.h"
25std::pair<llvm::StringRef, llvm::StringRef> wrapping(Context Ctx) {
30 return {
"void wrapperFunction(){\n",
"\n}"};
32 return {
"auto expressionWrapper(){return\n",
"\n;}"};
34 llvm_unreachable(
"Unknown TweakTest::CodeContext enum");
37std::string
wrap(Context Ctx, llvm::StringRef
Inner) {
38 auto Wrapping = wrapping(Ctx);
39 return (Wrapping.first +
Inner + Wrapping.second).str();
42llvm::StringRef unwrap(Context Ctx, llvm::StringRef Outer) {
43 auto Wrapping = wrapping(Ctx);
46 if (Outer.starts_with(Wrapping.first) && Outer.ends_with(Wrapping.second) &&
47 Outer.size() >= Wrapping.first.size() + Wrapping.second.size())
48 return Outer.drop_front(Wrapping.first.size())
49 .drop_back(Wrapping.second.size());
53llvm::Annotations::Range rangeOrPoint(
const llvm::Annotations &A) {
54 if (
A.points().size() != 0) {
55 assert(
A.ranges().size() == 0 &&
56 "both a cursor point and a selection range were specified");
57 return {
A.point(),
A.point()};
64std::optional<llvm::Expected<Tweak::Effect>>
65applyTweak(ParsedAST &
AST, llvm::Annotations::Range Range, StringRef TweakID,
66 const SymbolIndex *Index, llvm::vfs::FileSystem *FS) {
67 std::optional<llvm::Expected<Tweak::Effect>> Result;
69 Range.End, [&](SelectionTree ST) {
70 Tweak::Selection S(Index, AST, Range.Begin,
71 Range.End, std::move(ST), FS);
72 if (auto T = prepareTweak(TweakID, S, nullptr)) {
73 Result = (*T)->apply(S);
76 llvm::consumeError(T.takeError());
85std::string TweakTest::apply(llvm::StringRef MarkedCode,
86 llvm::StringMap<std::string> *EditedFiles)
const {
87 std::string WrappedCode = wrap(
Context, MarkedCode);
88 llvm::Annotations Input(WrappedCode);
93 TU.
Code = std::string(Input.code());
97 auto Result = applyTweak(
98 AST, rangeOrPoint(Input), TweakID, Index.get(),
99 &AST.getSourceManager().getFileManager().getVirtualFileSystem());
101 return "unavailable";
103 return "fail: " + llvm::toString(Result->takeError());
104 const auto &Effect = **Result;
105 if ((*Result)->ShowMessage)
106 return "message:\n" + *Effect.ShowMessage;
107 if (Effect.ApplyEdits.empty())
110 std::string EditedMainFile;
111 for (
auto &It : Effect.ApplyEdits) {
112 auto NewText = It.second.apply();
114 return "bad edits: " + llvm::toString(NewText.takeError());
115 llvm::StringRef Unwrapped = unwrap(
Context, *NewText);
117 EditedMainFile = std::string(Unwrapped);
120 ADD_FAILURE() <<
"There were changes to additional files, but client "
121 "provided a nullptr for EditedFiles.";
123 EditedFiles->insert_or_assign(It.first(), Unwrapped.str());
126 return EditedMainFile;
130 llvm::Annotations::Range
Range)
const {
132 Range.Begin += AST.second;
133 Range.End += AST.second;
134 auto Result = applyTweak(
135 AST.first,
Range, TweakID, Index.get(),
136 &AST.first.getSourceManager().getFileManager().getVirtualFileSystem());
138 if (Result && !*Result)
139 consumeError(Result->takeError());
140 return Result.has_value();
153std::string TweakTest::decorate(llvm::StringRef
Code,
unsigned Point) {
154 return (
Code.substr(0, Point) +
"^" +
Code.substr(Point)).str();
157std::string TweakTest::decorate(llvm::StringRef
Code,
158 llvm::Annotations::Range
Range) {
159 return (
Code.substr(0,
Range.Begin) +
"[[" +
std::pair< Context, Canceler > Inner
CharSourceRange Range
SourceRange for the file name.
A context is an immutable container for per-request data that must be propagated through layers that ...
Stores and provides access to parsed AST.
static bool createEach(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Begin, unsigned End, llvm::function_ref< bool(SelectionTree)> Func)
std::pair< ParsedAST, unsigned > WrappedAST
std::string testPath(PathRef File, llvm::sys::path::Style Style)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< std::string > ExtraArgs
llvm::StringMap< std::string > AdditionalFiles