15 #include "clang/Tooling/Core/Replacement.h"
16 #include "llvm/Support/Error.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
26 std::pair<llvm::StringRef, llvm::StringRef> wrapping(Context
Ctx) {
31 return {
"void wrapperFunction(){\n",
"\n}"};
33 return {
"auto expressionWrapper(){return\n",
"\n;}"};
35 llvm_unreachable(
"Unknown TweakTest::CodeContext enum");
39 auto Wrapping = wrapping(
Ctx);
40 return (Wrapping.first +
Inner + Wrapping.second).str();
43 llvm::StringRef unwrap(Context
Ctx, llvm::StringRef
Outer) {
44 auto Wrapping = wrapping(
Ctx);
47 if (
Outer.startswith(Wrapping.first) &&
Outer.endswith(Wrapping.second) &&
48 Outer.size() >= Wrapping.first.size() + Wrapping.second.size())
49 return Outer.drop_front(Wrapping.first.size()).drop_back(Wrapping.second.size());
53 std::pair<unsigned, unsigned> rangeOrPoint(
const Annotations &A) {
55 if (A.points().size() != 0) {
56 assert(A.ranges().size() == 0 &&
57 "both a cursor point and a selection range were specified");
58 SelectionRng =
Range{A.point(), A.point()};
60 SelectionRng = A.range();
68 llvm::Optional<llvm::Expected<Tweak::Effect>>
69 applyTweak(ParsedAST &AST,
const Annotations &Input, StringRef TweakID,
70 const SymbolIndex *
Index) {
71 auto Range = rangeOrPoint(Input);
72 llvm::Optional<llvm::Expected<Tweak::Effect>> Result;
74 Range.second, [&](SelectionTree ST) {
76 Range.second, std::move(ST));
78 Result = (*T)->apply(S);
81 llvm::consumeError(T.takeError());
88 MATCHER_P7(TweakIsAvailable, TweakID,
Ctx, Header, ExtraArgs, ExtraFiles,
Index,
90 (TweakID + (negation ?
" is unavailable" :
" is available")).str()) {
91 std::string WrappedCode =
wrap(
Ctx, arg);
92 Annotations Input(WrappedCode);
95 TU.HeaderCode = Header;
96 TU.Code = std::string(Input.code());
97 TU.ExtraArgs = ExtraArgs;
98 TU.AdditionalFiles = std::move(ExtraFiles);
99 ParsedAST AST = TU.
build();
100 auto Result = applyTweak(AST, Input, TweakID,
Index);
102 if (Result && !*Result)
103 consumeError(Result->takeError());
104 return Result.hasValue();
110 llvm::StringMap<std::string> *EditedFiles)
const {
111 std::string WrappedCode =
wrap(
Context, MarkedCode);
117 TU.
Code = std::string(Input.code());
121 auto Result = applyTweak(
AST, Input, TweakID,
Index.get());
123 return "unavailable";
126 const auto &Effect = **Result;
127 if ((*Result)->ShowMessage)
128 return "message:\n" + *Effect.ShowMessage;
129 if (Effect.ApplyEdits.empty())
132 std::string EditedMainFile;
133 for (
auto &It : Effect.ApplyEdits) {
134 auto NewText = It.second.apply();
137 llvm::StringRef Unwrapped = unwrap(
Context, *NewText);
139 EditedMainFile = std::string(Unwrapped);
142 ADD_FAILURE() <<
"There were changes to additional files, but client "
143 "provided a nullptr for EditedFiles.";
145 EditedFiles->insert_or_assign(It.first(), Unwrapped.str());
148 return EditedMainFile;
158 llvm::StringRef
Code = Test.code();
159 std::vector<std::string> Cases;
160 for (
const auto& Point : Test.
points()) {
167 Cases.push_back((
Code.substr(0, Begin) +
"[[" +
168 Code.substr(Begin, End - Begin) +
"]]" +
Code.substr(End))
171 assert(!Cases.empty() &&
"No markings in MarkedCode?");