1 //===--- SourceCode.h - Source code manipulation routines -------*- 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 // This file provides functions that simplify extraction of source code. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H 14 #define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H 15 16 #include "clang/AST/ASTContext.h" 17 #include "clang/Basic/SourceLocation.h" 18 #include "clang/Basic/TokenKinds.h" 19 20 namespace clang { 21 namespace tooling { 22 23 /// Extends \p Range to include the token \p Terminator, if it immediately 24 /// follows the end of the range. Otherwise, returns \p Range unchanged. 25 CharSourceRange maybeExtendRange(CharSourceRange Range, 26 tok::TokenKind Terminator, 27 ASTContext &Context); 28 29 /// Returns the source range spanning the node, extended to include \p Next, if 30 /// it immediately follows \p Node. Otherwise, returns the normal range of \p 31 /// Node. See comments on `getExtendedText()` for examples. 32 template <typename T> 33 CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next, 34 ASTContext &Context) { 35 return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()), 36 Next, Context); 37 } 38 39 /// Returns the logical source range of the node extended to include associated 40 /// comments and whitespace before and after the node, and associated 41 /// terminators. The returned range consists of file locations, if valid file 42 /// locations can be found for the associated content; otherwise, an invalid 43 /// range is returned. 44 /// 45 /// Note that parsing comments is disabled by default. In order to select a 46 /// range containing associated comments, you may need to invoke the tool with 47 /// `-fparse-all-comments`. 48 CharSourceRange getAssociatedRange(const Decl &D, ASTContext &Context); 49 50 /// Returns the source-code text in the specified range. 51 StringRef getText(CharSourceRange Range, const ASTContext &Context); 52 53 /// Returns the source-code text corresponding to \p Node. 54 template <typename T> 55 StringRef getText(const T &Node, const ASTContext &Context) { 56 return getText(CharSourceRange::getTokenRange(Node.getSourceRange()), 57 Context); 58 } 59 60 /// Returns the source text of the node, extended to include \p Next, if it 61 /// immediately follows the node. Otherwise, returns the text of just \p Node. 62 /// 63 /// For example, given statements S1 and S2 below: 64 /// \code 65 /// { 66 /// // S1: 67 /// if (!x) return foo(); 68 /// // S2: 69 /// if (!x) { return 3; } 70 /// } 71 /// \endcode 72 /// then 73 /// \code 74 /// getText(S1, Context) = "if (!x) return foo()" 75 /// getExtendedText(S1, tok::TokenKind::semi, Context) 76 /// = "if (!x) return foo();" 77 /// getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context) 78 /// = "return foo();" 79 /// getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context) 80 /// = getText(S2, Context) = "{ return 3; }" 81 /// \endcode 82 template <typename T> 83 StringRef getExtendedText(const T &Node, tok::TokenKind Next, 84 ASTContext &Context) { 85 return getText(getExtendedRange(Node, Next, Context), Context); 86 } 87 88 /// Determines whether \p Range is one that can be edited by a rewrite; 89 /// generally, one that starts and ends within a particular file. 90 llvm::Error validateEditRange(const CharSourceRange &Range, 91 const SourceManager &SM); 92 93 /// Attempts to resolve the given range to one that can be edited by a rewrite; 94 /// generally, one that starts and ends within a particular file. It supports a 95 /// limited set of cases involving source locations in macro expansions. If a 96 /// value is returned, it satisfies \c validateEditRange. 97 llvm::Optional<CharSourceRange> 98 getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM, 99 const LangOptions &LangOpts); 100 inline llvm::Optional<CharSourceRange> 101 getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) { 102 return getRangeForEdit(EditRange, Context.getSourceManager(), 103 Context.getLangOpts()); 104 } 105 } // namespace tooling 106 } // namespace clang 107 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H 108