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