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