clang-tools  10.0.0
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_UNITTESTS_CLANGD_TWEAKTESTING_H
10 #define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANGD_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<const char *> 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 #define TWEAK_TEST(TweakID) \
104  class TweakID##Test : public ::clang::clangd::TweakTest { \
105  protected: \
106  TweakID##Test() : TweakTest(#TweakID) {} \
107  }
108 
109 #define EXPECT_AVAILABLE(MarkedCode) \
110  do { \
111  for (const auto &Case : expandCases(MarkedCode)) \
112  EXPECT_THAT(Case, ::clang::clangd::TweakTest::isAvailable()); \
113  } while (0)
114 
115 #define EXPECT_UNAVAILABLE(MarkedCode) \
116  do { \
117  for (const auto &Case : expandCases(MarkedCode)) \
118  EXPECT_THAT(Case, \
119  ::testing::Not(::clang::clangd::TweakTest::isAvailable())); \
120  } while (0)
121 
122 } // namespace clangd
123 } // namespace clang
124 
125 #endif
std::vector< const char * > ExtraArgs
Definition: TweakTesting.h:69
::testing::Matcher< llvm::StringRef > isAvailable() const
static std::vector< std::string > expandCases(llvm::StringRef MarkedCode)
std::string apply(llvm::StringRef MarkedCode, llvm::StringMap< std::string > *EditedFiles=nullptr) const
std::unique_ptr< const SymbolIndex > Index
Definition: TweakTesting.h:75
llvm::StringMap< std::string > ExtraFiles
Definition: TweakTesting.h:56
TweakTest(const char *TweakID)
Definition: TweakTesting.h:59
A context is an immutable container for per-request data that must be propagated through layers that ...
Definition: Context.h:69
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::StringRef FileName
Definition: TweakTesting.h:66