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 22c01d28dcSEduardo Caldas class MutationTest : public SyntaxTreeTest { 23c01d28dcSEduardo Caldas protected: 24c01d28dcSEduardo Caldas using Transformation = std::function<void(const llvm::Annotations & /*Input*/, 25c01d28dcSEduardo Caldas TranslationUnit * /*Root*/)>; 26c01d28dcSEduardo Caldas void CheckTransformation(Transformation Transform, std::string Input, 27c01d28dcSEduardo 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 33263dcf45SHaojian Wu auto Replacements = syntax::computeReplacements(*TM, *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. 46c01d28dcSEduardo Caldas Transformation RemoveStatement = [this](const llvm::Annotations &Input, 47c01d28dcSEduardo Caldas TranslationUnit *Root) { 48c01d28dcSEduardo Caldas auto *S = cast<syntax::Statement>(nodeByRange(Input.range(), Root)); 49d17437d2SEduardo Caldas ASSERT_TRUE(S->canModify()) << "cannot remove a statement"; 50263dcf45SHaojian Wu syntax::removeStatement(*Arena, *TM, 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 }; 55c01d28dcSEduardo Caldas }; 56d17437d2SEduardo Caldas 57*7dfdca19SJulian Schmidt INSTANTIATE_TEST_SUITE_P( 58*7dfdca19SJulian Schmidt SyntaxTreeTests, MutationTest, ::testing::ValuesIn(allTestClangConfigs()), 59*7dfdca19SJulian Schmidt [](const testing::TestParamInfo<TestClangConfig> &Info) { 60*7dfdca19SJulian Schmidt return Info.param.toShortString(); 61*7dfdca19SJulian Schmidt }); 62c01d28dcSEduardo Caldas 63c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_InCompound) { 64c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { [[100+100;]] test(); }", 65c01d28dcSEduardo Caldas "void test() { test(); }"); 66d17437d2SEduardo Caldas } 67d17437d2SEduardo Caldas 68c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_InCompound_Empty) { 69c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { [[;]] }", 70c01d28dcSEduardo Caldas "void test() { }"); 71c01d28dcSEduardo Caldas } 72d17437d2SEduardo Caldas 73c01d28dcSEduardo Caldas TEST_P(MutationTest, RemoveStatement_LeaveEmpty) { 74c01d28dcSEduardo Caldas CheckTransformation(RemoveStatement, "void test() { if (1) [[{}]] else {} }", 75c01d28dcSEduardo Caldas "void test() { if (1) ; else {} }"); 76d17437d2SEduardo Caldas } 77d17437d2SEduardo Caldas } // namespace 78