| 1 | //===- MutationsTest.cpp --------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file tests mutation API for syntax trees. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "clang/Tooling/Syntax/Mutations.h" |
| 14 | #include "TreeTestBase.h" |
| 15 | #include "clang/Tooling/Syntax/BuildTree.h" |
| 16 | |
| 17 | using namespace clang; |
| 18 | using namespace clang::syntax; |
| 19 | |
| 20 | namespace { |
| 21 | |
| 22 | class MutationTest : public SyntaxTreeTest { |
| 23 | protected: |
| 24 | using Transformation = std::function<void(const llvm::Annotations & /*Input*/, |
| 25 | TranslationUnit * /*Root*/)>; |
| 26 | void CheckTransformation(Transformation Transform, std::string Input, |
| 27 | std::string Expected) { |
| 28 | llvm::Annotations Source(Input); |
| 29 | auto *Root = buildTree(Source.code(), GetParam()); |
| 30 | |
| 31 | Transform(Source, Root); |
| 32 | |
| 33 | auto Replacements = syntax::computeReplacements(*TM, *Root); |
| 34 | auto Output = tooling::applyAllReplacements(Source.code(), Replacements); |
| 35 | if (!Output) { |
| 36 | ADD_FAILURE() << "could not apply replacements: " |
| 37 | << llvm::toString(Output.takeError()); |
| 38 | return; |
| 39 | } |
| 40 | |
| 41 | EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; |
| 42 | }; |
| 43 | |
| 44 | // Removes the selected statement. Input should have exactly one selected |
| 45 | // range and it should correspond to a single statement. |
| 46 | Transformation RemoveStatement = [this](const llvm::Annotations &Input, |
| 47 | TranslationUnit *Root) { |
| 48 | auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), Root)); |
| 49 | ASSERT_TRUE(S->canModify()) << "cannot remove a statement" ; |
| 50 | syntax::removeStatement(*Arena, *TM, S); |
| 51 | EXPECT_TRUE(S->isDetached()); |
| 52 | EXPECT_FALSE(S->isOriginal()) |
| 53 | << "node removed from tree cannot be marked as original" ; |
| 54 | }; |
| 55 | }; |
| 56 | |
| 57 | INSTANTIATE_TEST_SUITE_P( |
| 58 | SyntaxTreeTests, MutationTest, ::testing::ValuesIn(allTestClangConfigs()), |
| 59 | [](const testing::TestParamInfo<TestClangConfig> &Info) { |
| 60 | return Info.param.toShortString(); |
| 61 | }); |
| 62 | |
| 63 | TEST_P(MutationTest, RemoveStatement_InCompound) { |
| 64 | CheckTransformation(RemoveStatement, "void test() { [[100+100;]] test(); }" , |
| 65 | "void test() { test(); }" ); |
| 66 | } |
| 67 | |
| 68 | TEST_P(MutationTest, RemoveStatement_InCompound_Empty) { |
| 69 | CheckTransformation(RemoveStatement, "void test() { [[;]] }" , |
| 70 | "void test() { }" ); |
| 71 | } |
| 72 | |
| 73 | TEST_P(MutationTest, RemoveStatement_LeaveEmpty) { |
| 74 | CheckTransformation(RemoveStatement, "void test() { if (1) [[{}]] else {} }" , |
| 75 | "void test() { if (1) ; else {} }" ); |
| 76 | } |
| 77 | } // namespace |
| 78 | |