astrelni updated this revision to Diff 206889. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D62977/new/
https://reviews.llvm.org/D62977 Files: clang-tools-extra/clang-tidy/google/CMakeLists.txt clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn
Index: llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn +++ llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/google/BUILD.gn @@ -28,6 +28,7 @@ "OverloadedUnaryAndCheck.cpp", "TodoCommentCheck.cpp", "UnnamedNamespaceInHeaderCheck.cpp", + "UpgradeGoogletestCaseCheck.cpp", "UsingNamespaceDirectiveCheck.cpp", ] } Index: clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/google-upgrade-googletest-case.cpp @@ -0,0 +1,1016 @@ +// RUN: %check_clang_tidy %s google-upgrade-googletest-case %t -- -- -I%S/Inputs +// RUN: %check_clang_tidy -check-suffix=NOSUITE %s google-upgrade-googletest-case %t -- -- -DNOSUITE -I%S/Inputs/gtest/nosuite + +#include "gtest/gtest.h" + +// When including a version of googletest without the replacement names, this +// check should not produce any diagnostics. The following dummy fix is present +// because `check_clang_tidy.py` requires at least one warning, fix or note. +void Dummy() {} +// CHECK-FIXES-NOSUITE: void Dummy() {} + +// ---------------------------------------------------------------------------- +// Macros + +TYPED_TEST_CASE(FooTest, FooTypes); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case' are deprecated; use equivalent APIs named with 'suite' +// CHECK-FIXES: TYPED_TEST_SUITE(FooTest, FooTypes); +TYPED_TEST_CASE_P(FooTest); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case' +// CHECK-FIXES: TYPED_TEST_SUITE_P(FooTest); +REGISTER_TYPED_TEST_CASE_P(FooTest, FooTestName); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case' +// CHECK-FIXES: REGISTER_TYPED_TEST_SUITE_P(FooTest, FooTestName); +INSTANTIATE_TYPED_TEST_CASE_P(FooPrefix, FooTest, FooTypes); +// CHECK-MESSAGES: [[@LINE-1]]:1: warning: Google Test APIs named with 'case' +// CHECK-FIXES: INSTANTIATE_TYPED_TEST_SUITE_P(FooPrefix, FooTest, FooTypes); + +#ifdef TYPED_TEST_CASE +// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case' +#undef TYPED_TEST_CASE +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' +#define TYPED_TEST_CASE(CaseName, Types, ...) +#endif + +#ifdef TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case' +#undef TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' +#define TYPED_TEST_CASE_P(SuiteName) +#endif + +#ifdef REGISTER_TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case' +#undef REGISTER_TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' +#define REGISTER_TYPED_TEST_CASE_P(SuiteName, ...) +#endif + +#ifdef INSTANTIATE_TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:2: warning: Google Test APIs named with 'case' +#undef INSTANTIATE_TYPED_TEST_CASE_P +// CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' +#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, SuiteName, Types, ...) +#endif + +TYPED_TEST_CASE(FooTest, FooTypes); +TYPED_TEST_CASE_P(FooTest); +REGISTER_TYPED_TEST_CASE_P(FooTest, FooTestName); +INSTANTIATE_TYPED_TEST_CASE_P(FooPrefix, FooTest, FooTypes); + +// ---------------------------------------------------------------------------- +// testing::Test + +class FooTest : public testing::Test { +public: + static void SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: static void SetUpTestSuite(); + static void TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: static void TearDownTestSuite(); +}; + +void FooTest::SetUpTestCase() {} +// CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTest::SetUpTestSuite() {} + +void FooTest::TearDownTestCase() {} +// CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTest::TearDownTestSuite() {} + +template <typename T> class FooTypedTest : public testing::Test { +public: + static void SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: static void SetUpTestSuite(); + static void TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: static void TearDownTestSuite(); +}; + +template <typename T> void FooTypedTest<T>::SetUpTestCase() {} +// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTypedTest<T>::SetUpTestSuite() {} + +template <typename T> void FooTypedTest<T>::TearDownTestCase() {} +// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTypedTest<T>::TearDownTestSuite() {} + +class BarTest : public testing::Test { +public: + using Test::SetUpTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using Test::SetUpTestSuite; + using Test::TearDownTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using Test::TearDownTestSuite; +}; + +class BarTest2 : public FooTest { +public: + using FooTest::SetUpTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using FooTest::SetUpTestSuite; + using FooTest::TearDownTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using FooTest::TearDownTestSuite; +}; + +// If a derived type already has the replacements, we only provide a warning +// since renaming or deleting the old declarations may not be safe. +class BarTest3 : public testing::Test { + public: + static void SetUpTestCase() {} + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + static void SetUpTestSuite() {} + + static void TearDownTestCase() {} + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + static void TearDownTestSuite() {} +}; + +namespace nesting_ns { +namespace testing { + +class Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); +}; + +} // namespace testing + +void Test() { + testing::Test::SetUpTestCase(); + testing::Test::TearDownTestCase(); +} + +} // namespace nesting_ns + +template <typename T> +void testInstantiationOnlyWarns() { + T::SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Google Test APIs named with 'case' + T::TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:6: warning: Google Test APIs named with 'case' +} + +#define SET_UP_TEST_CASE_MACRO_REPLACE SetUpTestCase +#define TEST_SET_UP_TEST_CASE_MACRO_WARN_ONLY ::testing::Test::SetUpTestCase + +void setUpTearDownCallAndReference() { + testing::Test::SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::Test::SetUpTestSuite(); + FooTest::SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-FIXES: FooTest::SetUpTestSuite(); + + testing::Test::TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::Test::TearDownTestSuite(); + FooTest::TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-FIXES: FooTest::TearDownTestSuite(); + + auto F = &testing::Test::SetUpTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F = &testing::Test::SetUpTestSuite; + F = &testing::Test::TearDownTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: F = &testing::Test::TearDownTestSuite; + F = &FooTest::SetUpTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: Google Test APIs named with 'case' + // CHECK-FIXES: F = &FooTest::SetUpTestSuite; + F = &FooTest::TearDownTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:17: warning: Google Test APIs named with 'case' + // CHECK-FIXES: F = &FooTest::TearDownTestSuite; + + using MyTest = testing::Test; + MyTest::SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + // CHECK-FIXES: MyTest::SetUpTestSuite(); + MyTest::TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + // CHECK-FIXES: MyTest::TearDownTestSuite(); + + BarTest3::SetUpTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case' + // CHECK-FIXES: BarTest3::SetUpTestSuite(); + BarTest3::TearDownTestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case' + // CHECK-FIXES: BarTest3::TearDownTestSuite(); + + testInstantiationOnlyWarns<testing::Test>(); + + testing::Test::SET_UP_TEST_CASE_MACRO_REPLACE(); + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::Test::SetUpTestSuite(); + TEST_SET_UP_TEST_CASE_MACRO_WARN_ONLY(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' +} + +// ---------------------------------------------------------------------------- +// testing::TestInfo + +class FooTestInfo : public testing::TestInfo { +public: + const char *test_case_name() const; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const char *test_suite_name() const; +}; + +const char *FooTestInfo::test_case_name() const {} +// CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case' +// CHECK-FIXES: const char *FooTestInfo::test_suite_name() const {} + +class BarTestInfo : public testing::TestInfo { +public: + using TestInfo::test_case_name; + // CHECK-MESSAGES: [[@LINE-1]]:19: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using TestInfo::test_suite_name; +}; + +class BarTestInfo2 : public FooTestInfo { +public: + using FooTestInfo::test_case_name; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using FooTestInfo::test_suite_name; +}; + +class BarTestInfo3 : public testing::TestInfo { + public: + const char* test_case_name() const; + // CHECK-MESSAGES: [[@LINE-1]]:15: warning: Google Test APIs named with 'case' + const char* test_suite_name() const; +}; + +namespace nesting_ns { +namespace testing { + +class TestInfo { +public: + const char *test_case_name() const; +}; + +} // namespace testing + +void FuncInfo() { + testing::TestInfo t; + (void)t.test_case_name(); +} + +} // namespace nesting_ns + +template <typename T> +void testInfoInstantiationOnlyWarns() { + T t; + (void)t.test_case_name(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' +} + +#define TEST_CASE_NAME_MACRO_REPLACE test_case_name +#define TEST_CASE_NAME_MACRO_WARN_ONLY testing::TestInfo().test_case_name + +void testInfoCallAndReference() { + (void)testing::TestInfo().test_case_name(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::TestInfo().test_suite_name(); + (void)FooTestInfo().test_case_name(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooTestInfo().test_suite_name(); + auto F1 = &testing::TestInfo::test_case_name; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F1 = &testing::TestInfo::test_suite_name; + auto F2 = &FooTestInfo::test_case_name; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F2 = &FooTestInfo::test_suite_name; + using MyTestInfo = testing::TestInfo; + (void)MyTestInfo().test_case_name(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyTestInfo().test_suite_name(); + (void)BarTestInfo3().test_case_name(); + // CHECK-MESSAGES: [[@LINE-1]]:24: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)BarTestInfo3().test_suite_name(); + + testInfoInstantiationOnlyWarns<testing::TestInfo>(); + + (void)testing::TestInfo().TEST_CASE_NAME_MACRO_REPLACE(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::TestInfo().test_suite_name(); + (void)TEST_CASE_NAME_MACRO_WARN_ONLY(); + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: Google Test APIs named with 'case' +} + +// ---------------------------------------------------------------------------- +// testing::TestEventListener + +class FooTestEventListener : public testing::TestEventListener { +public: + void OnTestCaseStart(const testing::TestCase &) override; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:39: warning: Google Test APIs named with 'case' + // CHECK-FIXES: void OnTestSuiteStart(const testing::TestSuite &) override; + void OnTestCaseEnd(const testing::TestCase &) override; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:37: warning: Google Test APIs named with 'case' + // CHECK-FIXES: void OnTestSuiteEnd(const testing::TestSuite &) override; +}; + +void FooTestEventListener::OnTestCaseStart(const testing::TestCase &) {} +// CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' +// CHECK-MESSAGES: [[@LINE-2]]:59: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTestEventListener::OnTestSuiteStart(const testing::TestSuite &) {} + +void FooTestEventListener::OnTestCaseEnd(const testing::TestCase &) {} +// CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' +// CHECK-MESSAGES: [[@LINE-2]]:57: warning: Google Test APIs named with 'case' +// CHECK-FIXES: void FooTestEventListener::OnTestSuiteEnd(const testing::TestSuite &) {} + +class BarTestEventListener : public testing::TestEventListener { +public: + using TestEventListener::OnTestCaseStart; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using TestEventListener::OnTestSuiteStart; + using TestEventListener::OnTestCaseEnd; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using TestEventListener::OnTestSuiteEnd; +}; + +class BarTestEventListener2 : public BarTestEventListener { +public: + using BarTestEventListener::OnTestCaseStart; + // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarTestEventListener::OnTestSuiteStart; + using BarTestEventListener::OnTestCaseEnd; + // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarTestEventListener::OnTestSuiteEnd; +}; + +#ifndef NOSUITE + +class BarTestEventListener3 : public testing::TestEventListener { +public: + void OnTestCaseStart(const testing::TestSuite &) override; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' + void OnTestSuiteStart(const testing::TestSuite &) override; + + void OnTestCaseEnd(const testing::TestSuite &) override; + // CHECK-MESSAGES: [[@LINE-1]]:8: warning: Google Test APIs named with 'case' + void OnTestSuiteEnd(const testing::TestSuite &) override; +}; + +#endif + +namespace nesting_ns { +namespace testing { + +class TestEventListener { +public: + virtual void OnTestCaseStart(const ::testing::TestCase &); + // CHECK-MESSAGES: [[@LINE-1]]:49: warning: Google Test APIs named with 'case' + // CHECK-FIXES: virtual void OnTestCaseStart(const ::testing::TestSuite &); + virtual void OnTestCaseEnd(const ::testing::TestCase &); + // CHECK-MESSAGES: [[@LINE-1]]:47: warning: Google Test APIs named with 'case' + // CHECK-FIXES: virtual void OnTestCaseEnd(const ::testing::TestSuite &); +}; + +} // namespace testing + +void FuncTestEventListener(::testing::TestCase &Case) { + // CHECK-MESSAGES: [[@LINE-1]]:39: warning: Google Test APIs named with 'case' + // CHECK-FIXES: void FuncTestEventListener(::testing::TestSuite &Case) { + testing::TestEventListener().OnTestCaseStart(Case); + testing::TestEventListener().OnTestCaseEnd(Case); +} + +} // namespace nesting_ns + +#ifndef NOSUITE + +template <typename T> +void testEventListenerInstantiationOnlyWarns() { + T().OnTestCaseStart(testing::TestSuite()); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + T().OnTestCaseEnd(testing::TestSuite()); + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' +} + +#endif + +#define ON_TEST_CASE_START_MACRO_REPLACE OnTestCaseStart +#define ON_TEST_CASE_START_MACRO_WARN_ONLY \ + testing::TestEventListener().OnTestCaseStart + +#define ON_TEST_CASE_END_MACRO_REPLACE OnTestCaseEnd +#define ON_TEST_CASE_END_MACRO_WARN_ONLY \ + testing::TestEventListener().OnTestCaseEnd + +void testEventListenerCallAndReference(testing::TestCase &Case) { + // CHECK-MESSAGES: [[@LINE-1]]:49: warning: Google Test APIs named with 'case' + // CHECK-FIXES: void testEventListenerCallAndReference(testing::TestSuite &Case) { + testing::TestEventListener().OnTestCaseStart(Case); + // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestEventListener().OnTestSuiteStart(Case); + testing::TestEventListener().OnTestCaseEnd(Case); + // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestEventListener().OnTestSuiteEnd(Case); + + FooTestEventListener().OnTestCaseStart(Case); + // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case' + // CHECK-FIXES: FooTestEventListener().OnTestSuiteStart(Case); + FooTestEventListener().OnTestCaseEnd(Case); + // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case' + // CHECK-FIXES: FooTestEventListener().OnTestSuiteEnd(Case); + + auto F1 = &testing::TestEventListener::OnTestCaseStart; + // CHECK-MESSAGES: [[@LINE-1]]:42: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F1 = &testing::TestEventListener::OnTestSuiteStart; + F1 = &testing::TestEventListener::OnTestCaseEnd; + // CHECK-MESSAGES: [[@LINE-1]]:37: warning: Google Test APIs named with 'case' + // CHECK-FIXES: F1 = &testing::TestEventListener::OnTestSuiteEnd; + + auto F2 = &FooTestEventListener::OnTestCaseStart; + // CHECK-MESSAGES: [[@LINE-1]]:36: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F2 = &FooTestEventListener::OnTestSuiteStart; + F2 = &FooTestEventListener::OnTestCaseEnd; + // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case' + // CHECK-FIXES: F2 = &FooTestEventListener::OnTestSuiteEnd; + +#ifndef NOSUITE + + BarTestEventListener3().OnTestCaseStart(Case); + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: BarTestEventListener3().OnTestSuiteStart(Case); + BarTestEventListener3().OnTestCaseEnd(Case); + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: BarTestEventListener3().OnTestSuiteEnd(Case); + + testEventListenerInstantiationOnlyWarns<testing::TestEventListener>(); + +#endif + + testing::TestEventListener().ON_TEST_CASE_START_MACRO_REPLACE(Case); + // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestEventListener().OnTestSuiteStart(Case); + ON_TEST_CASE_START_MACRO_WARN_ONLY(Case); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + + testing::TestEventListener().ON_TEST_CASE_END_MACRO_REPLACE(Case); + // CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestEventListener().OnTestSuiteEnd(Case); + ON_TEST_CASE_END_MACRO_WARN_ONLY(Case); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' +} + +// ---------------------------------------------------------------------------- +// testing::UnitTest + +class FooUnitTest : public testing::UnitTest { +public: + testing::TestCase *current_test_case() const; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestSuite *current_test_suite() const; + int successful_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + // CHECK-FIXES: int successful_test_suite_count() const; + int failed_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + // CHECK-FIXES: int failed_test_suite_count() const; + int total_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + // CHECK-FIXES: int total_test_suite_count() const; + int test_case_to_run_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + // CHECK-FIXES: int test_suite_to_run_count() const; + const testing::TestCase *GetTestCase(int) const; + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const testing::TestSuite *GetTestSuite(int) const; +}; + +testing::TestCase *FooUnitTest::current_test_case() const {} +// CHECK-MESSAGES: [[@LINE-1]]:10: warning: Google Test APIs named with 'case' +// CHECK-MESSAGES: [[@LINE-2]]:33: warning: Google Test APIs named with 'case' +// CHECK-FIXES: testing::TestSuite *FooUnitTest::current_test_suite() const {} +int FooUnitTest::successful_test_case_count() const {} +// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' +// CHECK-FIXES: int FooUnitTest::successful_test_suite_count() const {} +int FooUnitTest::failed_test_case_count() const {} +// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' +// CHECK-FIXES: int FooUnitTest::failed_test_suite_count() const {} +int FooUnitTest::total_test_case_count() const {} +// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' +// CHECK-FIXES: int FooUnitTest::total_test_suite_count() const {} +int FooUnitTest::test_case_to_run_count() const {} +// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' +// CHECK-FIXES: int FooUnitTest::test_suite_to_run_count() const {} +const testing::TestCase *FooUnitTest::GetTestCase(int) const {} +// CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case' +// CHECK-MESSAGES: [[@LINE-2]]:39: warning: Google Test APIs named with 'case' +// CHECK-FIXES: const testing::TestSuite *FooUnitTest::GetTestSuite(int) const {} + +// Type derived from testing::TestCase +class BarUnitTest : public testing::UnitTest { +public: + using testing::UnitTest::current_test_case; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::current_test_suite; + using testing::UnitTest::successful_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::successful_test_suite_count; + using testing::UnitTest::failed_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::failed_test_suite_count; + using testing::UnitTest::total_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::total_test_suite_count; + using testing::UnitTest::test_case_to_run_count; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::test_suite_to_run_count; + using testing::UnitTest::GetTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using testing::UnitTest::GetTestSuite; +}; + +class BarUnitTest2 : public BarUnitTest { + using BarUnitTest::current_test_case; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::current_test_suite; + using BarUnitTest::successful_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::successful_test_suite_count; + using BarUnitTest::failed_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::failed_test_suite_count; + using BarUnitTest::total_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::total_test_suite_count; + using BarUnitTest::test_case_to_run_count; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::test_suite_to_run_count; + using BarUnitTest::GetTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: using BarUnitTest::GetTestSuite; +}; + +#ifndef NOSUITE + +class BarUnitTest3 : public testing::UnitTest { + testing::TestSuite *current_test_case() const; + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + int successful_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + int failed_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + int total_test_case_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + int test_case_to_run_count() const; + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + const testing::TestSuite *GetTestCase(int) const; + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + + testing::TestSuite *current_test_suite() const; + int successful_test_suite_count() const; + int failed_test_suite_count() const; + int total_test_suite_count() const; + int test_suite_to_run_count() const; + const testing::TestSuite *GetTestSuite(int) const; +}; + +#endif + +namespace nesting_ns { +namespace testing { + +class TestSuite; + +class UnitTest { +public: + TestSuite *current_test_case() const; + int successful_test_case_count() const; + int failed_test_case_count() const; + int total_test_case_count() const; + int test_case_to_run_count() const; + const TestSuite *GetTestCase(int) const; +}; + +} // namespace testing + +void FuncUnitTest() { + testing::UnitTest t; + (void)t.current_test_case(); + (void)t.successful_test_case_count(); + (void)t.failed_test_case_count(); + (void)t.total_test_case_count(); + (void)t.test_case_to_run_count(); + (void)t.GetTestCase(0); +} + +} // namespace nesting_ns + +template <typename T> +void unitTestInstantiationOnlyWarns() { + T t; + (void)t.current_test_case(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + (void)t.successful_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + (void)t.failed_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + (void)t.total_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + (void)t.test_case_to_run_count(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' + (void)t.GetTestCase(0); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' +} + +#define UNIT_TEST_NAME_MACRO_REPLACE1 current_test_case +#define UNIT_TEST_NAME_MACRO_REPLACE2 successful_test_case_count +#define UNIT_TEST_NAME_MACRO_REPLACE3 failed_test_case_count +#define UNIT_TEST_NAME_MACRO_REPLACE4 total_test_case_count +#define UNIT_TEST_NAME_MACRO_REPLACE5 test_case_to_run_count +#define UNIT_TEST_NAME_MACRO_REPLACE6 GetTestCase +#define UNIT_TEST_NAME_MACRO_WARN_ONLY1 testing::UnitTest().current_test_case +#define UNIT_TEST_NAME_MACRO_WARN_ONLY2 \ + testing::UnitTest().successful_test_case_count +#define UNIT_TEST_NAME_MACRO_WARN_ONLY3 \ + testing::UnitTest().failed_test_case_count +#define UNIT_TEST_NAME_MACRO_WARN_ONLY4 \ + testing::UnitTest().total_test_case_count +#define UNIT_TEST_NAME_MACRO_WARN_ONLY5 \ + testing::UnitTest().test_case_to_run_count +#define UNIT_TEST_NAME_MACRO_WARN_ONLY6 testing::UnitTest().GetTestCase + +void unitTestCallAndReference() { + (void)testing::UnitTest().current_test_case(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().current_test_suite(); + (void)testing::UnitTest().successful_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().successful_test_suite_count(); + (void)testing::UnitTest().failed_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().failed_test_suite_count(); + (void)testing::UnitTest().total_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().total_test_suite_count(); + (void)testing::UnitTest().test_case_to_run_count(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().test_suite_to_run_count(); + (void)testing::UnitTest().GetTestCase(0); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().GetTestSuite(0); + + (void)FooUnitTest().current_test_case(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().current_test_suite(); + (void)FooUnitTest().successful_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().successful_test_suite_count(); + (void)FooUnitTest().failed_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().failed_test_suite_count(); + (void)FooUnitTest().total_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().total_test_suite_count(); + (void)FooUnitTest().test_case_to_run_count(); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().test_suite_to_run_count(); + (void)FooUnitTest().GetTestCase(0); + // CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)FooUnitTest().GetTestSuite(0); + + auto U1 = &testing::UnitTest::current_test_case; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U1 = &testing::UnitTest::current_test_suite; + auto U2 = &testing::UnitTest::successful_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U2 = &testing::UnitTest::successful_test_suite_count; + auto U3 = &testing::UnitTest::failed_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U3 = &testing::UnitTest::failed_test_suite_count; + auto U4 = &testing::UnitTest::total_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U4 = &testing::UnitTest::total_test_suite_count; + auto U5 = &testing::UnitTest::test_case_to_run_count; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U5 = &testing::UnitTest::test_suite_to_run_count; + auto U6 = &testing::UnitTest::GetTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto U6 = &testing::UnitTest::GetTestSuite; + + auto F1 = &FooUnitTest::current_test_case; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F1 = &FooUnitTest::current_test_suite; + auto F2 = &FooUnitTest::successful_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F2 = &FooUnitTest::successful_test_suite_count; + auto F3 = &FooUnitTest::failed_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F3 = &FooUnitTest::failed_test_suite_count; + auto F4 = &FooUnitTest::total_test_case_count; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F4 = &FooUnitTest::total_test_suite_count; + auto F5 = &FooUnitTest::test_case_to_run_count; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F5 = &FooUnitTest::test_suite_to_run_count; + auto F6 = &FooUnitTest::GetTestCase; + // CHECK-MESSAGES: [[@LINE-1]]:27: warning: Google Test APIs named with 'case' + // CHECK-FIXES: auto F6 = &FooUnitTest::GetTestSuite; + + using MyUnitTest = testing::UnitTest; + (void)MyUnitTest().current_test_case(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().current_test_suite(); + (void)MyUnitTest().successful_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().successful_test_suite_count(); + (void)MyUnitTest().failed_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().failed_test_suite_count(); + (void)MyUnitTest().total_test_case_count(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().total_test_suite_count(); + (void)MyUnitTest().test_case_to_run_count(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().test_suite_to_run_count(); + (void)MyUnitTest().GetTestCase(0); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)MyUnitTest().GetTestSuite(0); + + unitTestInstantiationOnlyWarns<testing::UnitTest>(); + + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE1(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().current_test_suite(); + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE2(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().successful_test_suite_count(); + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE3(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().failed_test_suite_count(); + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE4(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().total_test_suite_count(); + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE5(); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().test_suite_to_run_count(); + (void)testing::UnitTest().UNIT_TEST_NAME_MACRO_REPLACE6(0); + // CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)testing::UnitTest().GetTestSuite(0); + + UNIT_TEST_NAME_MACRO_WARN_ONLY1(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + UNIT_TEST_NAME_MACRO_WARN_ONLY2(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + UNIT_TEST_NAME_MACRO_WARN_ONLY3(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + UNIT_TEST_NAME_MACRO_WARN_ONLY4(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + UNIT_TEST_NAME_MACRO_WARN_ONLY5(); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + UNIT_TEST_NAME_MACRO_WARN_ONLY6(0); + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' +} + +// ---------------------------------------------------------------------------- +// testing::TestCase + +template <typename T> +void TestCaseInTemplate() { + T t; + + testing::TestCase Case; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestSuite Case; +} + +#define TEST_CASE_CAN_FIX TestCase +#define TEST_CASE_WARN_ONLY testing::TestCase + +const testing::TestCase *testCaseUses(const testing::TestCase &Case) { + // CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:54: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const testing::TestSuite *testCaseUses(const testing::TestSuite &Case) { + + // No change for implicit declarations: + auto Lambda = [&Case]() {}; + + TestCaseInTemplate<testing::TestCase>(); + // CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case' + // CHECK-FIXES: TestCaseInTemplate<testing::TestSuite>(); + + testing::TEST_CASE_CAN_FIX C1; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestSuite C1; + TEST_CASE_WARN_ONLY C2; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + + (void)new testing::TestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)new testing::TestSuite(); + const testing::TestCase *Result = &Case; + // CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const testing::TestSuite *Result = &Case; + return Result; +} + +struct TestCaseHolder { + testing::TestCase Case; + // CHECK-MESSAGES: [[@LINE-1]]:12: warning: Google Test APIs named with 'case' + // CHECK-FIXES: testing::TestSuite Case; +}; + +class MyTest : public testing::TestCase {}; +// CHECK-MESSAGES: [[@LINE-1]]:32: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class MyTest : public testing::TestSuite {}; + +template <typename T = testing::TestCase> +// CHECK-MESSAGES: [[@LINE-1]]:33: warning: Google Test APIs named with 'case' +// CHECK-FIXES: template <typename T = testing::TestSuite> +class TestTypeHolder {}; + +template <> +class TestTypeHolder<testing::TestCase> {}; +// CHECK-MESSAGES: [[@LINE-1]]:31: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class TestTypeHolder<testing::TestSuite> {}; + +namespace shadow_using_ns { + +using testing::TestCase; +// CHECK-MESSAGES: [[@LINE-1]]:16: warning: Google Test APIs named with 'case' +// CHECK-FIXES: using testing::TestSuite; + +const TestCase *testCaseUses(const TestCase &Case) { + // CHECK-MESSAGES: [[@LINE-1]]:7: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:36: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const TestSuite *testCaseUses(const TestSuite &Case) { + + // No change for implicit declarations: + auto Lambda = [&Case]() {}; + + (void)new TestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:13: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)new TestSuite(); + const TestCase *Result = &Case; + // CHECK-MESSAGES: [[@LINE-1]]:9: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const TestSuite *Result = &Case; + return Result; +} + +struct TestCaseHolder { + TestCase Case; + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: Google Test APIs named with 'case' + // CHECK-FIXES: TestSuite Case; +}; + +class MyTest : public TestCase {}; +// CHECK-MESSAGES: [[@LINE-1]]:23: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class MyTest : public TestSuite {}; + +template <typename T = TestCase> +// CHECK-MESSAGES: [[@LINE-1]]:24: warning: Google Test APIs named with 'case' +// CHECK-FIXES: template <typename T = TestSuite> +class TestTypeHolder {}; + +template <> +class TestTypeHolder<TestCase> {}; +// CHECK-MESSAGES: [[@LINE-1]]:22: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class TestTypeHolder<TestSuite> {}; + +} // namespace shadow_using_ns + +const shadow_using_ns::TestCase *shadowTestCaseUses( + const shadow_using_ns::TestCase &Case) { + // CHECK-MESSAGES: [[@LINE-2]]:24: warning: Google Test APIs named with 'case' + // CHECK-MESSAGES: [[@LINE-2]]:28: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const shadow_using_ns::TestSuite *shadowTestCaseUses( + // CHECK-FIXES: const shadow_using_ns::TestSuite &Case) { + + // No match for implicit declarations, as in the lambda capture: + auto Lambda = [&Case]() {}; + + (void)new shadow_using_ns::TestCase(); + // CHECK-MESSAGES: [[@LINE-1]]:30: warning: Google Test APIs named with 'case' + // CHECK-FIXES: (void)new shadow_using_ns::TestSuite(); + const shadow_using_ns::TestCase *Result = &Case; + // CHECK-MESSAGES: [[@LINE-1]]:26: warning: Google Test APIs named with 'case' + // CHECK-FIXES: const shadow_using_ns::TestSuite *Result = &Case; + return Result; +} + +struct ShadowTestCaseHolder { + shadow_using_ns::TestCase Case; + // CHECK-MESSAGES: [[@LINE-1]]:20: warning: Google Test APIs named with 'case' + // CHECK-FIXES: shadow_using_ns::TestSuite Case; +}; + +class ShadowMyTest : public shadow_using_ns::TestCase {}; +// CHECK-MESSAGES: [[@LINE-1]]:46: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class ShadowMyTest : public shadow_using_ns::TestSuite {}; + +template <typename T = shadow_using_ns::TestCase> +// CHECK-MESSAGES: [[@LINE-1]]:41: warning: Google Test APIs named with 'case' +// CHECK-FIXES: template <typename T = shadow_using_ns::TestSuite> +class ShadowTestTypeHolder {}; + +template <> +class ShadowTestTypeHolder<shadow_using_ns::TestCase> {}; +// CHECK-MESSAGES: [[@LINE-1]]:45: warning: Google Test APIs named with 'case' +// CHECK-FIXES: class ShadowTestTypeHolder<shadow_using_ns::TestSuite> {}; + +namespace typedef_ns { + +typedef testing::TestCase MyTestCase; +// CHECK-MESSAGES: [[@LINE-1]]:18: warning: Google Test APIs named with 'case' +// CHECK-FIXES: typedef testing::TestSuite MyTestCase; + +const MyTestCase *testCaseUses(const MyTestCase &Case) { + auto Lambda = [&Case]() {}; + (void)new MyTestCase(); + const MyTestCase *Result = &Case; + return Result; +} + +struct TestCaseHolder { + MyTestCase Case; +}; + +class MyTest : public MyTestCase {}; + +template <typename T = MyTestCase> +class TestTypeHolder {}; + +template <> +class TestTypeHolder<MyTestCase> {}; + +} // namespace typedef_ns + +const typedef_ns::MyTestCase *typedefTestCaseUses( + const typedef_ns::MyTestCase &Case) { + auto Lambda = [&Case]() {}; + (void)new typedef_ns::MyTestCase(); + const typedef_ns::MyTestCase *Result = &Case; + return Result; +} + +struct TypedefTestCaseHolder { + typedef_ns::MyTestCase Case; +}; + +class TypedefMyTest : public typedef_ns::MyTestCase {}; +template <typename T = typedef_ns::MyTestCase> class TypedefTestTypeHolder {}; +template <> class TypedefTestTypeHolder<typedef_ns::MyTestCase> {}; + +namespace alias_ns { + +using MyTestCase = testing::TestCase; +// CHECK-MESSAGES: [[@LINE-1]]:29: warning: Google Test APIs named with 'case' +// CHECK-FIXES: using MyTestCase = testing::TestSuite; + +const MyTestCase *testCaseUses(const MyTestCase &Case) { + auto Lambda = [&Case]() {}; + (void)new MyTestCase(); + const MyTestCase *Result = &Case; + return Result; +} + +struct TestCaseHolder { + MyTestCase Case; +}; + +class MyTest : public MyTestCase {}; +template <typename T = MyTestCase> class TestTypeHolder {}; +template <> class TestTypeHolder<MyTestCase> {}; + +} // namespace alias_ns + +const alias_ns::MyTestCase *aliasTestCaseUses( + const alias_ns::MyTestCase &Case) { + auto Lambda = [&Case]() {}; + (void)new alias_ns::MyTestCase(); + const alias_ns::MyTestCase *Result = &Case; + return Result; +} + +struct AliasTestCaseHolder { + alias_ns::MyTestCase Case; +}; + +class AliasMyTest : public alias_ns::MyTestCase {}; +template <typename T = alias_ns::MyTestCase> class AliasTestTypeHolder {}; +template <> class AliasTestTypeHolder<alias_ns::MyTestCase> {}; + +template <typename T> +void templateFunction(const T& t) { + (void)t.current_test_case(); + // CHECK-MESSAGES: [[@LINE-1]]:11: warning: Google Test APIs named with 'case' +} + +void instantiateTemplateFunction(const testing::UnitTest &Test) { + templateFunction(Test); +} Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest.h @@ -0,0 +1,47 @@ +#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ +#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ + +#include "gtest/gtest-typed-test.h" + +namespace testing { + +class Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); +}; + +class TestCase {}; + +class TestInfo { +public: + const char *test_case_name() const; +}; + +class TestEventListener { +public: + virtual void OnTestCaseStart(const TestCase &); + virtual void OnTestCaseEnd(const TestCase &); +}; + +class EmptyTestEventListener : public TestEventListener { +public: + void OnTestCaseStart(const TestCase &) override; + void OnTestCaseEnd(const TestCase &) override; +}; + +class UnitTest { +public: + static UnitTest *GetInstance(); + + TestCase *current_test_case() const; + int successful_test_case_count() const; + int failed_test_case_count() const; + int total_test_case_count() const; + int test_case_to_run_count() const; + const TestCase *GetTestCase(int) const; +}; + +} // namespace testing + +#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/Inputs/gtest/nosuite/gtest/gtest-typed-test.h @@ -0,0 +1,12 @@ +#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ +#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ + +#define TYPED_TEST_CASE(CaseName, Types, ...) + +#define TYPED_TEST_CASE_P(SuiteName) + +#define REGISTER_TYPED_TEST_CASE_P(SuiteName, ...) + +#define INSTANTIATE_TYPED_TEST_CASE_P(Prefix, SuiteName, Types, ...) + +#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest.h @@ -0,0 +1,66 @@ +#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ +#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ + +#include "gtest/gtest-typed-test.h" + +namespace testing { + +class Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + + static void SetUpTestSuite(); + static void TearDownTestSuite(); +}; + +class TestSuite {}; +using TestCase = TestSuite; + +class TestInfo { +public: + const char *test_case_name() const; + + const char *test_suite_name() const; +}; + +class TestEventListener { +public: + virtual void OnTestCaseStart(const TestCase &); + virtual void OnTestCaseEnd(const TestCase &); + + virtual void OnTestSuiteStart(const TestCase &); + virtual void OnTestSuiteEnd(const TestCase &); +}; + +class EmptyTestEventListener : public TestEventListener { +public: + void OnTestCaseStart(const TestCase &) override; + void OnTestCaseEnd(const TestCase &) override; + + void OnTestSuiteStart(const TestCase &) override; + void OnTestSuiteEnd(const TestCase &) override; +}; + +class UnitTest { +public: + static UnitTest *GetInstance(); + + TestCase *current_test_case() const; + int successful_test_case_count() const; + int failed_test_case_count() const; + int total_test_case_count() const; + int test_case_to_run_count() const; + const TestCase *GetTestCase(int) const; + + TestSuite *current_test_suite() const; + int successful_test_suite_count() const; + int failed_test_suite_count() const; + int total_test_suite_count() const; + int test_suite_to_run_count() const; + const TestSuite *GetTestSuite(int) const; +}; + +} // namespace testing + +#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_H_ Index: clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/Inputs/gtest/gtest-typed-test.h @@ -0,0 +1,16 @@ +#ifndef THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ +#define THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ + +#define TYPED_TEST_SUITE(CaseName, Types, ...) +#define TYPED_TEST_CASE TYPED_TEST_SUITE + +#define TYPED_TEST_SUITE_P(SuiteName) +#define TYPED_TEST_CASE_P TYPED_TEST_SUITE_P + +#define REGISTER_TYPED_TEST_SUITE_P(SuiteName, ...) +#define REGISTER_TYPED_TEST_CASE_P REGISTER_TYPED_TEST_SUITE_P + +#define INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, SuiteName, Types, ...) +#define INSTANTIATE_TYPED_TEST_CASE_P INSTANTIATE_TYPED_TEST_SUITE_P + +#endif // THIRD_PARTY_LLVM_LLVM_TOOLS_CLANG_TOOLS_EXTRA_TEST_CLANG_TIDY_INPUTS_GTEST_GTEST_TYPED_TEST_H_ Index: clang-tools-extra/docs/clang-tidy/checks/list.rst =================================================================== --- clang-tools-extra/docs/clang-tidy/checks/list.rst +++ clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -149,6 +149,7 @@ google-runtime-int google-runtime-operator google-runtime-references + google-upgrade-googletest-case hicpp-avoid-c-arrays (redirects to modernize-avoid-c-arrays) <hicpp-avoid-c-arrays> hicpp-avoid-goto hicpp-braces-around-statements (redirects to readability-braces-around-statements) <hicpp-braces-around-statements> Index: clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/google-upgrade-googletest-case.rst @@ -0,0 +1,53 @@ +.. title:: clang-tidy - google-upgrade-googletest-case + +google-upgrade-googletest-case +============================== + +Finds uses of deprecated Google Test version 1.9 APIs with names containing +``case`` and replaces them with equivalent APIs with ``suite``. + +All names containing ``case`` are being replaced to be consistent with the +meanings of "test case" and "test suite" as used by the International +Software Testing Qualifications Board and ISO 29119. + +The new names are a part of Google Test version 1.9 (release pending). It is +recommended that users update their dependency to version 1.9 and then use this +check to remove deprecated names. + +The affected APIs are: + +- Member functions of ``testing::Test``, ``testing::TestInfo``, + ``testing::TestEventListener``, ``testing::UnitTest``, and any type inheriting + from these types +- The macros ``TYPED_TEST_CASE``, ``TYPED_TEST_CASE_P``, + ``REGISTER_TYPED_TEST_CASE_P``, and ``INSTANTIATE_TYPED_TEST_CASE_P`` +- The type alias ``testing::TestCase`` + +Examples of fixes created by this check: + +.. code-block:: c++ + + class FooTest : public testing::Test { + public: + static void SetUpTestCase(); + static void TearDownTestCase(); + }; + + TYPED_TEST_CASE(BarTest, BarTypes); + +becomes + +.. code-block:: c++ + + class FooTest : public testing::Test { + public: + static void SetUpTestSuite(); + static void TearDownTestSuite(); + }; + + TYPED_TEST_SUITE(BarTest, BarTypes); + +For better consistency of user code, the check renames both virtual and +non-virtual member functions with matching names in derived types. The check +tries to provide a only warning when a fix cannot be made safely, as is the case +with some template and macro uses. Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -128,6 +128,12 @@ Checks for calls to ``+new`` or overrides of it, which are prohibited by the Google Objective-C style guide. +- New :doc:`google-upgrade-googletest-case + <clang-tidy/checks/google-upgrade-googletest-case>` check. + + Finds uses of deprecated Googletest APIs with names containing ``case`` and + replaces them with equivalent APIs with ``suite``. + - New :doc:`objc-super-self <clang-tidy/checks/objc-super-self>` check. Finds invocations of ``-self`` on super instances in initializers of Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.h @@ -0,0 +1,40 @@ +//===--- UpgradeGoogletestCaseCheck.h - clang-tidy --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace google { + +/// Finds uses of deprecated Googletest APIs with names containing "case" and +/// replaces them with equivalent names containing "suite". +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/google-upgrade-googletest-case.html +class UpgradeGoogletestCaseCheck : public ClangTidyCheck { +public: + UpgradeGoogletestCaseCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, + Preprocessor *ModuleExpanderPP) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + llvm::DenseSet<unsigned> MatchedTemplateLocations; +}; + +} // namespace google +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_GOOGLE_UPGRADEGOOGLETESTCASECHECK_H Index: clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/google/UpgradeGoogletestCaseCheck.cpp @@ -0,0 +1,354 @@ +//===--- UpgradeGoogletestCaseCheck.cpp - clang-tidy ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UpgradeGoogletestCaseCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace google { + +static const llvm::StringRef RenameCaseToSuiteMessage = + "Google Test APIs named with 'case' are deprecated; use equivalent APIs " + "named with 'suite'"; + +static llvm::Optional<llvm::StringRef> +getNewMacroName(llvm::StringRef MacroName) { + std::pair<llvm::StringRef, llvm::StringRef> ReplacementMap[] = { + {"TYPED_TEST_CASE", "TYPED_TEST_SUITE"}, + {"TYPED_TEST_CASE_P", "TYPED_TEST_SUITE_P"}, + {"REGISTER_TYPED_TEST_CASE_P", "REGISTER_TYPED_TEST_SUITE_P"}, + {"INSTANTIATE_TYPED_TEST_CASE_P", "INSTANTIATE_TYPED_TEST_SUITE_P"}, + {"INSTANTIATE_TEST_CASE_P", "INSTANTIATE_TEST_SUITE_P"}, + }; + + for (auto &Mapping : ReplacementMap) { + if (MacroName == Mapping.first) + return Mapping.second; + } + + return llvm::None; +} + +namespace { + +class UpgradeGoogletestCasePPCallback : public PPCallbacks { +public: + UpgradeGoogletestCasePPCallback(UpgradeGoogletestCaseCheck *Check, + Preprocessor *PP) + : ReplacementFound(false), Check(Check), PP(PP) {} + + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range, const MacroArgs *) override { + macroUsed(MacroNameTok, MD, Range.getBegin(), CheckAction::Rename); + } + + void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, + const MacroDirective *Undef) override { + if (Undef != nullptr) + macroUsed(MacroNameTok, MD, Undef->getLocation(), CheckAction::Warn); + } + + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override { + if (!ReplacementFound && MD != nullptr) { + // We check if the newly defined macro is one of the target replacements. + // This ensures that the check creates warnings only if it is including a + // recent enough version of Google Test. + llvm::StringRef FileName = PP->getSourceManager().getFilename( + MD->getMacroInfo()->getDefinitionLoc()); + ReplacementFound = FileName.endswith("gtest/gtest-typed-test.h") && + PP->getSpelling(MacroNameTok) == "TYPED_TEST_SUITE"; + } + } + + void Defined(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range) override { + macroUsed(MacroNameTok, MD, Range.getBegin(), CheckAction::Warn); + } + + void Ifdef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + macroUsed(MacroNameTok, MD, Loc, CheckAction::Warn); + } + + void Ifndef(SourceLocation Loc, const Token &MacroNameTok, + const MacroDefinition &MD) override { + macroUsed(MacroNameTok, MD, Loc, CheckAction::Warn); + } + +private: + enum class CheckAction { Warn, Rename }; + + void macroUsed(const clang::Token &MacroNameTok, const MacroDefinition &MD, + SourceLocation Loc, CheckAction Action) { + if (!ReplacementFound) + return; + + std::string Name = PP->getSpelling(MacroNameTok); + + llvm::Optional<llvm::StringRef> Replacement = getNewMacroName(Name); + if (!Replacement) + return; + + llvm::StringRef FileName = PP->getSourceManager().getFilename( + MD.getMacroInfo()->getDefinitionLoc()); + if (!FileName.endswith("gtest/gtest-typed-test.h")) + return; + + DiagnosticBuilder Diag = Check->diag(Loc, RenameCaseToSuiteMessage); + + if (Action == CheckAction::Rename) + Diag << FixItHint::CreateReplacement( + CharSourceRange::getTokenRange(Loc, Loc), *Replacement); + } + + bool ReplacementFound; + UpgradeGoogletestCaseCheck *Check; + Preprocessor *PP; +}; + +} // namespace + +void UpgradeGoogletestCaseCheck::registerPPCallbacks(const SourceManager &, + Preprocessor *PP, + Preprocessor *) { + if (!getLangOpts().CPlusPlus) + return; + + PP->addPPCallbacks( + llvm::make_unique<UpgradeGoogletestCasePPCallback>(this, PP)); +} + +void UpgradeGoogletestCaseCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + auto LocationFilter = + unless(isExpansionInFileMatching("gtest/gtest(-typed-test)?\\.h$")); + + // Matchers for the member functions that are being renamed. In each matched + // Google Test class, we check for the existence of one new method name. This + // makes sure the check gives warnings only if the included version of Google + // Test is recent enough. + auto Methods = + cxxMethodDecl( + anyOf( + cxxMethodDecl( + hasAnyName("SetUpTestCase", "TearDownTestCase"), + ofClass( + cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl( + hasName("::testing::Test"), + hasMethod(hasName("SetUpTestSuite"))))) + .bind("class"))), + cxxMethodDecl( + hasName("test_case_name"), + ofClass( + cxxRecordDecl(isSameOrDerivedFrom(cxxRecordDecl( + hasName("::testing::TestInfo"), + hasMethod(hasName("test_suite_name"))))) + .bind("class"))), + cxxMethodDecl( + hasAnyName("OnTestCaseStart", "OnTestCaseEnd"), + ofClass(cxxRecordDecl( + isSameOrDerivedFrom(cxxRecordDecl( + hasName("::testing::TestEventListener"), + hasMethod(hasName("OnTestSuiteStart"))))) + .bind("class"))), + cxxMethodDecl( + hasAnyName("current_test_case", "successful_test_case_count", + "failed_test_case_count", "total_test_case_count", + "test_case_to_run_count", "GetTestCase"), + ofClass(cxxRecordDecl( + isSameOrDerivedFrom(cxxRecordDecl( + hasName("::testing::UnitTest"), + hasMethod(hasName("current_test_suite"))))) + .bind("class"))))) + .bind("method"); + + Finder->addMatcher(expr(anyOf(callExpr(callee(Methods)).bind("call"), + declRefExpr(to(Methods)).bind("ref")), + LocationFilter), + this); + + Finder->addMatcher( + usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(Methods)), LocationFilter) + .bind("using"), + this); + + Finder->addMatcher(cxxMethodDecl(Methods, LocationFilter), this); + + // Matchers for `TestCase` -> `TestSuite`. The fact that `TestCase` is an + // alias and not a class declaration ensures we only match with a recent + // enough version of Google Test. + auto TestCaseTypeAlias = + typeAliasDecl(hasName("::testing::TestCase")).bind("test-case"); + Finder->addMatcher( + typeLoc(loc(qualType(typedefType(hasDeclaration(TestCaseTypeAlias)))), + unless(hasAncestor(decl(isImplicit()))), LocationFilter) + .bind("typeloc"), + this); + Finder->addMatcher( + usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(TestCaseTypeAlias))) + .bind("using"), + this); +} + +static llvm::StringRef getNewMethodName(llvm::StringRef CurrentName) { + std::pair<llvm::StringRef, llvm::StringRef> ReplacementMap[] = { + {"SetUpTestCase", "SetUpTestSuite"}, + {"TearDownTestCase", "TearDownTestSuite"}, + {"test_case_name", "test_suite_name"}, + {"OnTestCaseStart", "OnTestSuiteStart"}, + {"OnTestCaseEnd", "OnTestSuiteEnd"}, + {"current_test_case", "current_test_suite"}, + {"successful_test_case_count", "successful_test_suite_count"}, + {"failed_test_case_count", "failed_test_suite_count"}, + {"total_test_case_count", "total_test_suite_count"}, + {"test_case_to_run_count", "test_suite_to_run_count"}, + {"GetTestCase", "GetTestSuite"}}; + + for (auto &Mapping : ReplacementMap) { + if (CurrentName == Mapping.first) + return Mapping.second; + } + + llvm_unreachable("Unexpected function name"); +} + +template <typename NodeType> +static bool isInInstantiation(const NodeType &Node, + const MatchFinder::MatchResult &Result) { + return !match(isInTemplateInstantiation(), Node, *Result.Context).empty(); +} + +template <typename NodeType> +static bool isInTemplate(const NodeType &Node, + const MatchFinder::MatchResult &Result) { + internal::Matcher<NodeType> IsInsideTemplate = + hasAncestor(decl(anyOf(classTemplateDecl(), functionTemplateDecl()))); + return !match(IsInsideTemplate, Node, *Result.Context).empty(); +} + +static bool +derivedTypeHasReplacementMethod(const MatchFinder::MatchResult &Result, + llvm::StringRef ReplacementMethod) { + const auto *Class = Result.Nodes.getNodeAs<CXXRecordDecl>("class"); + return !match(cxxRecordDecl( + unless(isExpansionInFileMatching( + "gtest/gtest(-typed-test)?\\.h$")), + hasMethod(cxxMethodDecl(hasName(ReplacementMethod)))), + *Class, *Result.Context) + .empty(); +} + +static CharSourceRange +getAliasNameRange(const MatchFinder::MatchResult &Result) { + if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) { + return CharSourceRange::getTokenRange( + Using->getNameInfo().getSourceRange()); + } + return CharSourceRange::getTokenRange( + Result.Nodes.getNodeAs<TypeLoc>("typeloc")->getSourceRange()); +} + +void UpgradeGoogletestCaseCheck::check(const MatchFinder::MatchResult &Result) { + llvm::StringRef ReplacementText; + CharSourceRange ReplacementRange; + if (const auto *Method = Result.Nodes.getNodeAs<CXXMethodDecl>("method")) { + ReplacementText = getNewMethodName(Method->getName()); + + bool IsInInstantiation; + bool IsInTemplate; + bool AddFix = true; + if (const auto *Call = Result.Nodes.getNodeAs<CXXMemberCallExpr>("call")) { + const auto *Callee = llvm::cast<MemberExpr>(Call->getCallee()); + ReplacementRange = CharSourceRange::getTokenRange(Callee->getMemberLoc(), + Callee->getMemberLoc()); + IsInInstantiation = isInInstantiation(*Call, Result); + IsInTemplate = isInTemplate<Stmt>(*Call, Result); + } else if (const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>("ref")) { + ReplacementRange = + CharSourceRange::getTokenRange(Ref->getNameInfo().getSourceRange()); + IsInInstantiation = isInInstantiation(*Ref, Result); + IsInTemplate = isInTemplate<Stmt>(*Ref, Result); + } else if (const auto *Using = Result.Nodes.getNodeAs<UsingDecl>("using")) { + ReplacementRange = + CharSourceRange::getTokenRange(Using->getNameInfo().getSourceRange()); + IsInInstantiation = isInInstantiation(*Using, Result); + IsInTemplate = isInTemplate<Decl>(*Using, Result); + } else { + // This branch means we have matched a function declaration / definition + // either for a function from googletest or for a function in a derived + // class. + + ReplacementRange = CharSourceRange::getTokenRange( + Method->getNameInfo().getSourceRange()); + IsInInstantiation = isInInstantiation(*Method, Result); + IsInTemplate = isInTemplate<Decl>(*Method, Result); + + // If the type of the matched method is strictly derived from a googletest + // type and has both the old and new member function names, then we cannot + // safely rename (or delete) the old name version. + AddFix = !derivedTypeHasReplacementMethod(Result, ReplacementText); + } + + if (IsInInstantiation) { + if (MatchedTemplateLocations.count( + ReplacementRange.getBegin().getRawEncoding()) == 0) { + // For each location matched in a template instantiation, we check if + // the location can also be found in `MatchedTemplateLocations`. If it + // is not found, that means the expression did not create a match + // without the instantiation and depends on template parameters. A + // manual fix is probably required so we provide only a warning. + diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage); + } + return; + } + + if (IsInTemplate) { + // We gather source locations from template matches not in template + // instantiations for future matches. + MatchedTemplateLocations.insert( + ReplacementRange.getBegin().getRawEncoding()); + } + + if (!AddFix) { + diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage); + return; + } + } else { + // This is a match for `TestCase` to `TestSuite` refactoring. + assert(Result.Nodes.getNodeAs<TypeAliasDecl>("test-case") != nullptr); + ReplacementText = "TestSuite"; + ReplacementRange = getAliasNameRange(Result); + + // We do not need to keep track of template instantiations for this branch, + // because we are matching a `TypeLoc` for the alias declaration. Templates + // will only be instantiated with the true type name, `TestSuite`. + } + + DiagnosticBuilder Diag = + diag(ReplacementRange.getBegin(), RenameCaseToSuiteMessage); + + ReplacementRange = Lexer::makeFileCharRange( + ReplacementRange, *Result.SourceManager, Result.Context->getLangOpts()); + if (ReplacementRange.isInvalid()) + // An invalid source range likely means we are inside a macro body. A manual + // fix is likely needed so we do not create a fix-it hint. + return; + + Diag << FixItHint::CreateReplacement(ReplacementRange, ReplacementText); +} + +} // namespace google +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp =================================================================== --- clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp +++ clang-tools-extra/clang-tidy/google/GoogleTidyModule.cpp @@ -27,6 +27,7 @@ #include "OverloadedUnaryAndCheck.h" #include "TodoCommentCheck.h" #include "UnnamedNamespaceInHeaderCheck.h" +#include "UpgradeGoogletestCaseCheck.h" #include "UsingNamespaceDirectiveCheck.h" using namespace clang::ast_matchers; @@ -79,6 +80,8 @@ CheckFactories .registerCheck<clang::tidy::readability::NamespaceCommentCheck>( "google-readability-namespace-comments"); + CheckFactories.registerCheck<UpgradeGoogletestCaseCheck>( + "google-upgrade-googletest-case"); } ClangTidyOptions getModuleOptions() override { Index: clang-tools-extra/clang-tidy/google/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/google/CMakeLists.txt +++ clang-tools-extra/clang-tidy/google/CMakeLists.txt @@ -17,6 +17,7 @@ OverloadedUnaryAndCheck.cpp TodoCommentCheck.cpp UnnamedNamespaceInHeaderCheck.cpp + UpgradeGoogletestCaseCheck.cpp UsingNamespaceDirectiveCheck.cpp LINK_LIBS
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits