clang-tools  14.0.0git
TweakTesting.h
Go to the documentation of this file.
1 //===--- TweakTesting.h - Test helpers for refactoring actions ---*- C++-*-===//
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 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_TWEAKS_TWEAKTESTING_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_UNITTESTS_TWEAKS_TWEAKTESTING_H
11 
12 #include "TestTU.h"
13 #include "index/Index.h"
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 #include <memory>
19 #include <string>
20 
21 namespace clang {
22 namespace clangd {
23 
24 // Fixture base for testing tweaks. Intended to be subclassed for each tweak.
25 //
26 // Usage:
27 // TWEAK_TEST(ExpandAutoType);
28 //
29 // TEST_F(ExpandAutoTypeTest, ShortensTypes) {
30 // Header = R"cpp(
31 // namespace foo { template<typename> class X{}; }
32 // using namespace foo;
33 // )cpp";
34 // Context = Function;
35 // EXPECT_THAT(apply("[[auto]] X = foo<int>();"),
36 // "foo<int> X = foo<int();");
37 // EXPECT_AVAILABLE("^a^u^t^o^ X = foo<int>();");
38 // EXPECT_UNAVAILABLE("auto ^X^ = ^foo<int>();");
39 // }
40 class TweakTest : public ::testing::Test {
41  const char *TweakID;
42 
43 public:
44  // Inputs are wrapped in file boilerplate before attempting to apply a tweak.
45  // Context describes the type of boilerplate.
46  enum CodeContext {
47  // Code snippet is placed directly into the source file. e.g. a declaration.
49  // Snippet will appear within a function body. e.g. a statement.
51  // Snippet is an expression.
53  };
54 
55  // Mapping from file name to contents.
56  llvm::StringMap<std::string> ExtraFiles;
57 
58 protected:
59  TweakTest(const char *TweakID) : TweakID(TweakID) {}
60 
61  // Contents of a header file to be implicitly included.
62  // This typically contains declarations that will be used for a set of related
63  // testcases.
64  std::string Header;
65 
66  llvm::StringRef FileName = "TestTU.cpp";
67 
68  // Extra flags passed to the compilation in apply().
69  std::vector<std::string> ExtraArgs;
70 
71  // Context in which snippets of code should be placed to run tweaks.
73 
74  // Index to be passed into Tweak::Selection.
75  std::unique_ptr<const SymbolIndex> Index = nullptr;
76 
77  // Apply the current tweak to the range (or point) in MarkedCode.
78  // MarkedCode will be wrapped according to the Context.
79  // - if the tweak produces edits, returns the edited code (without markings)
80  // for the main file.
81  // Populates \p EditedFiles if there were changes to other files whenever
82  // it is non-null. It is a mapping from absolute path of the edited file to
83  // its new contents. Passing a nullptr to \p EditedFiles when there are
84  // changes, will result in a failure.
85  // The context added to MarkedCode will be stripped away before returning,
86  // unless the tweak edited it.
87  // - if the tweak produces a message, returns "message:\n<message>"
88  // - if prepare() returns false, returns "unavailable"
89  // - if apply() returns an error, returns "fail: <message>"
90  std::string apply(llvm::StringRef MarkedCode,
91  llvm::StringMap<std::string> *EditedFiles = nullptr) const;
92 
93  // Accepts a code snippet with many ranges (or points) marked, and returns a
94  // list of snippets with one range marked each.
95  // Primarily used from EXPECT_AVAILABLE/EXPECT_UNAVAILABLE macro.
96  static std::vector<std::string> expandCases(llvm::StringRef MarkedCode);
97 
98  // Returns a matcher that accepts marked code snippets where the tweak is
99  // available at the marked range.
100  ::testing::Matcher<llvm::StringRef> isAvailable() const;
101 };
102 
103 MATCHER_P2(FileWithContents, FileName, Contents, "") {
104  return arg.first() == FileName && arg.second == Contents;
105 }
106 
107 #define TWEAK_TEST(TweakID) \
108  class TweakID##Test : public ::clang::clangd::TweakTest { \
109  protected: \
110  TweakID##Test() : TweakTest(#TweakID) {} \
111  }
112 
113 #define EXPECT_AVAILABLE(MarkedCode) \
114  do { \
115  for (const auto &Case : expandCases(MarkedCode)) \
116  EXPECT_THAT(Case, ::clang::clangd::TweakTest::isAvailable()); \
117  } while (0)
118 
119 #define EXPECT_UNAVAILABLE(MarkedCode) \
120  do { \
121  for (const auto &Case : expandCases(MarkedCode)) \
122  EXPECT_THAT(Case, \
123  ::testing::Not(::clang::clangd::TweakTest::isAvailable())); \
124  } while (0)
125 
126 } // namespace clangd
127 } // namespace clang
128 
129 #endif
clang::clangd::MATCHER_P2
MATCHER_P2(hasFlag, Flag, Path, "")
Definition: GlobalCompilationDatabaseTests.cpp:450
Index.h
TestTU.h
clang::clangd::TweakTest::apply
std::string apply(llvm::StringRef MarkedCode, llvm::StringMap< std::string > *EditedFiles=nullptr) const
Definition: TweakTesting.cpp:113
clang::clangd::TweakTest::Header
std::string Header
Definition: TweakTesting.h:64
clang::clangd::TweakTest::CodeContext
CodeContext
Definition: TweakTesting.h:46
clang::clangd::TweakTest::Function
@ Function
Definition: TweakTesting.h:50
clang::clangd::TweakTest
Definition: TweakTesting.h:40
clang::clangd::TweakTest::TweakTest
TweakTest(const char *TweakID)
Definition: TweakTesting.h:59
clang::clangd::TweakTest::isAvailable
::testing::Matcher< llvm::StringRef > isAvailable() const
Definition: TweakTesting.cpp:157
clang::clangd::TweakTest::expandCases
static std::vector< std::string > expandCases(llvm::StringRef MarkedCode)
Definition: TweakTesting.cpp:162
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:46
clang::clangd::TweakTest::Index
std::unique_ptr< const SymbolIndex > Index
Definition: TweakTesting.h:75
clang::clangd::TweakTest::ExtraFiles
llvm::StringMap< std::string > ExtraFiles
Definition: TweakTesting.h:56
clang::clangd::TweakTest::ExtraArgs
std::vector< std::string > ExtraArgs
Definition: TweakTesting.h:69
clang::clangd::TweakTest::File
@ File
Definition: TweakTesting.h:48
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::TweakTest::FileName
llvm::StringRef FileName
Definition: TweakTesting.h:66
clang::clangd::Context
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
clang::clangd::TweakTest::Expression
@ Expression
Definition: TweakTesting.h:52