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 TEST_P(SyntaxTreeTest, Mutations) { 23 if (!GetParam().isCXX11OrLater()) { 24 return; 25 } 26 27 using Transformation = std::function<void( 28 const llvm::Annotations & /*Input*/, syntax::TranslationUnit * /*Root*/)>; 29 auto CheckTransformation = [this](std::string Input, std::string Expected, 30 Transformation Transform) -> void { 31 llvm::Annotations Source(Input); 32 auto *Root = buildTree(Source.code(), GetParam()); 33 34 Transform(Source, Root); 35 36 auto Replacements = syntax::computeReplacements(*Arena, *Root); 37 auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 38 if (!Output) { 39 ADD_FAILURE() << "could not apply replacements: " 40 << llvm::toString(Output.takeError()); 41 return; 42 } 43 44 EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 45 }; 46 47 // Removes the selected statement. Input should have exactly one selected 48 // range and it should correspond to a single statement. 49 auto RemoveStatement = [this](const llvm::Annotations &Input, 50 syntax::TranslationUnit *TU) { 51 auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), TU)); 52 ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 53 syntax::removeStatement(*Arena, S); 54 EXPECT_TRUE(S->isDetached()); 55 EXPECT_FALSE(S->isOriginal()) 56 << "node removed from tree cannot be marked as original"; 57 }; 58 59 std::vector<std::pair<std::string /*Input*/, std::string /*Expected*/>> 60 Cases = { 61 {"void test() { [[100+100;]] test(); }", "void test() { test(); }"}, 62 {"void test() { if (true) [[{}]] else {} }", 63 "void test() { if (true) ; else {} }"}, 64 {"void test() { [[;]] }", "void test() { }"}}; 65 for (const auto &C : Cases) 66 CheckTransformation(C.first, C.second, RemoveStatement); 67 } 68 69 TEST_P(SyntaxTreeTest, SynthesizedNodes) { 70 buildTree("", GetParam()); 71 72 auto *C = syntax::createPunctuation(*Arena, tok::comma); 73 ASSERT_NE(C, nullptr); 74 EXPECT_EQ(C->token()->kind(), tok::comma); 75 EXPECT_TRUE(C->canModify()); 76 EXPECT_FALSE(C->isOriginal()); 77 EXPECT_TRUE(C->isDetached()); 78 79 auto *S = syntax::createEmptyStatement(*Arena); 80 ASSERT_NE(S, nullptr); 81 EXPECT_TRUE(S->canModify()); 82 EXPECT_FALSE(S->isOriginal()); 83 EXPECT_TRUE(S->isDetached()); 84 } 85 } // namespace 86