xref: /llvm-project/clang/tools/clang-refactor/TestSupport.h (revision 2d861436a9eb789bb70a3644393b21e548240ac6)
1b54ef6a2SAlex Lorenz //===--- TestSupport.h - Clang-based refactoring tool -----------*- C++ -*-===//
2b54ef6a2SAlex Lorenz //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b54ef6a2SAlex Lorenz //
7b54ef6a2SAlex Lorenz //===----------------------------------------------------------------------===//
8b54ef6a2SAlex Lorenz ///
9b54ef6a2SAlex Lorenz /// \file
109fc8faf9SAdrian Prantl /// Declares datatypes and routines that are used by test-specific code
11b54ef6a2SAlex Lorenz /// in clang-refactor.
12b54ef6a2SAlex Lorenz ///
13b54ef6a2SAlex Lorenz //===----------------------------------------------------------------------===//
14b54ef6a2SAlex Lorenz 
15b54ef6a2SAlex Lorenz #ifndef LLVM_CLANG_TOOLS_CLANG_REFACTOR_TEST_SUPPORT_H
16b54ef6a2SAlex Lorenz #define LLVM_CLANG_TOOLS_CLANG_REFACTOR_TEST_SUPPORT_H
17b54ef6a2SAlex Lorenz 
18f5ca27ccSAlex Lorenz #include "ToolRefactoringResultConsumer.h"
19b54ef6a2SAlex Lorenz #include "clang/Basic/LLVM.h"
20b54ef6a2SAlex Lorenz #include "clang/Basic/SourceLocation.h"
21b54ef6a2SAlex Lorenz #include "llvm/ADT/SmallVector.h"
22b54ef6a2SAlex Lorenz #include "llvm/Support/Error.h"
23b54ef6a2SAlex Lorenz #include <map>
24a1580d7bSKazu Hirata #include <optional>
25b54ef6a2SAlex Lorenz #include <string>
26b54ef6a2SAlex Lorenz 
27b54ef6a2SAlex Lorenz namespace clang {
28b54ef6a2SAlex Lorenz 
29b54ef6a2SAlex Lorenz class SourceManager;
30b54ef6a2SAlex Lorenz 
31b54ef6a2SAlex Lorenz namespace refactor {
32b54ef6a2SAlex Lorenz 
33b54ef6a2SAlex Lorenz /// A source selection range that's specified in a test file using an inline
34b54ef6a2SAlex Lorenz /// command in the comment. These commands can take the following forms:
35b54ef6a2SAlex Lorenz ///
36b54ef6a2SAlex Lorenz /// - /*range=*/ will create an empty selection range in the default group
37b54ef6a2SAlex Lorenz ///   right after the comment.
38b54ef6a2SAlex Lorenz /// - /*range a=*/ will create an empty selection range in the 'a' group right
39b54ef6a2SAlex Lorenz ///   after the comment.
40b54ef6a2SAlex Lorenz /// - /*range = +1*/ will create an empty selection range at a location that's
41b54ef6a2SAlex Lorenz ///   right after the comment with one offset to the column.
42b54ef6a2SAlex Lorenz /// - /*range= -> +2:3*/ will create a selection range that starts at the
43b54ef6a2SAlex Lorenz ///   location right after the comment, and ends at column 3 of the 2nd line
44b54ef6a2SAlex Lorenz ///   after the line of the starting location.
45b54ef6a2SAlex Lorenz ///
46b54ef6a2SAlex Lorenz /// Clang-refactor will expected all ranges in one test group to produce
47b54ef6a2SAlex Lorenz /// identical results.
48b54ef6a2SAlex Lorenz struct TestSelectionRange {
49b54ef6a2SAlex Lorenz   unsigned Begin, End;
50b54ef6a2SAlex Lorenz };
51b54ef6a2SAlex Lorenz 
52b54ef6a2SAlex Lorenz /// A set of test selection ranges specified in one file.
53b54ef6a2SAlex Lorenz struct TestSelectionRangesInFile {
54b54ef6a2SAlex Lorenz   std::string Filename;
55b54ef6a2SAlex Lorenz   struct RangeGroup {
56b54ef6a2SAlex Lorenz     std::string Name;
57b54ef6a2SAlex Lorenz     SmallVector<TestSelectionRange, 8> Ranges;
58b54ef6a2SAlex Lorenz   };
59b54ef6a2SAlex Lorenz   std::vector<RangeGroup> GroupedRanges;
60b54ef6a2SAlex Lorenz 
61b54ef6a2SAlex Lorenz   bool foreachRange(const SourceManager &SM,
62b54ef6a2SAlex Lorenz                     llvm::function_ref<void(SourceRange)> Callback) const;
63b54ef6a2SAlex Lorenz 
64f5ca27ccSAlex Lorenz   std::unique_ptr<ClangRefactorToolConsumerInterface> createConsumer() const;
65b54ef6a2SAlex Lorenz 
66b54ef6a2SAlex Lorenz   void dump(llvm::raw_ostream &OS) const;
67b54ef6a2SAlex Lorenz };
68b54ef6a2SAlex Lorenz 
69b54ef6a2SAlex Lorenz /// Extracts the grouped selection ranges from the file that's specified in
70b54ef6a2SAlex Lorenz /// the -selection=test:<filename> option.
71b54ef6a2SAlex Lorenz ///
72b54ef6a2SAlex Lorenz /// The grouped ranges are specified in comments using the following syntax:
73b54ef6a2SAlex Lorenz /// "range" [ group-name ] "=" [ "+" starting-column-offset ] [ "->"
74b54ef6a2SAlex Lorenz ///                              "+" ending-line-offset ":"
75b54ef6a2SAlex Lorenz ///                                  ending-column-position ]
76b54ef6a2SAlex Lorenz ///
77b54ef6a2SAlex Lorenz /// The selection range is then computed from this command by taking the ending
78b54ef6a2SAlex Lorenz /// location of the comment, and adding 'starting-column-offset' to the column
79b54ef6a2SAlex Lorenz /// for that location. That location in turns becomes the whole selection range,
80b54ef6a2SAlex Lorenz /// unless 'ending-line-offset' and 'ending-column-position' are specified. If
81b54ef6a2SAlex Lorenz /// they are specified, then the ending location of the selection range is
82b54ef6a2SAlex Lorenz /// the starting location's line + 'ending-line-offset' and the
83b54ef6a2SAlex Lorenz /// 'ending-column-position' column.
84b54ef6a2SAlex Lorenz ///
85b54ef6a2SAlex Lorenz /// All selection ranges in one group are expected to produce the same
86b54ef6a2SAlex Lorenz /// refactoring result.
87b54ef6a2SAlex Lorenz ///
88b54ef6a2SAlex Lorenz /// When testing, zero is returned from clang-refactor even when a group
89b54ef6a2SAlex Lorenz /// produces an initiation error, which is different from normal invocation
90b54ef6a2SAlex Lorenz /// that returns a non-zero value. This is done on purpose, to ensure that group
91b54ef6a2SAlex Lorenz /// consistency checks can return non-zero, but still print the output of
92b54ef6a2SAlex Lorenz /// the group. So even if a test matches the output of group, it will still fail
93b54ef6a2SAlex Lorenz /// because clang-refactor should return zero on exit when the group results are
94b54ef6a2SAlex Lorenz /// consistent.
95b54ef6a2SAlex Lorenz ///
9635b4fbb5SKazu Hirata /// \returns std::nullopt on failure (errors are emitted to stderr), or a set of
97b54ef6a2SAlex Lorenz /// grouped source ranges in the given file otherwise.
98*6ad0788cSKazu Hirata std::optional<TestSelectionRangesInFile>
99*6ad0788cSKazu Hirata findTestSelectionRanges(StringRef Filename);
100b54ef6a2SAlex Lorenz 
101b54ef6a2SAlex Lorenz } // end namespace refactor
102b54ef6a2SAlex Lorenz } // end namespace clang
103b54ef6a2SAlex Lorenz 
104b54ef6a2SAlex Lorenz #endif // LLVM_CLANG_TOOLS_CLANG_REFACTOR_TEST_SUPPORT_H
105