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