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" 152e4a20fdSEduardo Caldas #include "clang/Tooling/Syntax/BuildTree.h" 16d17437d2SEduardo Caldas 172e4a20fdSEduardo Caldas using namespace clang; 182e4a20fdSEduardo Caldas using namespace clang::syntax; 192e4a20fdSEduardo Caldas 20d17437d2SEduardo Caldas namespace { 21d17437d2SEduardo Caldas 22*c01d28dcSEduardo Caldas class MutationTest : public SyntaxTreeTest { 23*c01d28dcSEduardo Caldas protected: 24*c01d28dcSEduardo Caldas using Transformation = std::function<void(const llvm::Annotations & /*Input*/, 25*c01d28dcSEduardo Caldas TranslationUnit * /*Root*/)>; 26*c01d28dcSEduardo Caldas void CheckTransformation(Transformation Transform, std::string Input, 27*c01d28dcSEduardo Caldas std::string Expected) { 28d17437d2SEduardo Caldas llvm::Annotations Source(Input); 29d17437d2SEduardo Caldas auto *Root = buildTree(Source.code(), GetParam()); 30d17437d2SEduardo Caldas 31d17437d2SEduardo Caldas Transform(Source, Root); 32d17437d2SEduardo Caldas 33d17437d2SEduardo Caldas auto Replacements = syntax::computeReplacements(*Arena, *Root); 34d17437d2SEduardo Caldas auto Output = tooling::applyAllReplacements(Source.code(), Replacements); 35d17437d2SEduardo Caldas if (!Output) { 36d17437d2SEduardo Caldas ADD_FAILURE() << "could not apply replacements: " 37d17437d2SEduardo Caldas << llvm::toString(Output.takeError()); 38d17437d2SEduardo Caldas return; 39d17437d2SEduardo Caldas } 40d17437d2SEduardo Caldas 41d17437d2SEduardo Caldas EXPECT_EQ(Expected, *Output) << "input is:\n" << Input; 42d17437d2SEduardo Caldas }; 43d17437d2SEduardo Caldas 44d17437d2SEduardo Caldas // Removes the selected statement. Input should have exactly one selected 45d17437d2SEduardo Caldas // range and it should correspond to a single statement. 46*c01d28dcSEduardo Caldas Transformation RemoveStatement = [this](const llvm::Annotations &Input, 47*c01d28dcSEduardo Caldas TranslationUnit *Root) { 48*c01d28dcSEduardo Caldas auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), Root)); 49d17437d2SEduardo Caldas ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 50d17437d2SEduardo Caldas syntax::removeStatement(*Arena, S); 51d17437d2SEduardo Caldas EXPECT_TRUE(S->isDetached()); 52d17437d2SEduardo Caldas EXPECT_FALSE(S->isOriginal()) 53d17437d2SEduardo Caldas << "node removed from tree cannot be marked as original"; 54d17437d2SEduardo Caldas }; 55*c01d28dcSEduardo Caldas }; 56d17437d2SEduardo Caldas 57*c01d28dcSEduardo Caldas INSTANTIATE_TEST_CASE_P(SyntaxTreeTests, MutationTest, 58*c01d28dcSEduardo Caldas ::testing::ValuesIn(allTestClangConfigs()), ); 59*c01d28dcSEduardo Caldas 60*c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_InCompound) { 61*c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { [[100+100;]] test(); }", 62*c01d28dcSEduardo Caldas "void test() { test(); }"); 63d17437d2SEduardo Caldas } 64d17437d2SEduardo Caldas 65*c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_InCompound_Empty) { 66*c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { [[;]] }", 67*c01d28dcSEduardo Caldas "void test() { }"); 68*c01d28dcSEduardo Caldas } 69d17437d2SEduardo Caldas 70*c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_LeaveEmpty) { 71*c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { if (1) [[{}]] else {} }", 72*c01d28dcSEduardo Caldas "void test() { if (1) ; else {} }"); 73d17437d2SEduardo Caldas } 74d17437d2SEduardo Caldas } // namespace 75