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