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_SOURCE_CODE_H 14 #define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_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 Next, if it immediately follows the 24 /// end of the range. Otherwise, returns \p Range unchanged. 25 CharSourceRange maybeExtendRange(CharSourceRange Range, tok::TokenKind Next, 26 ASTContext &Context); 27 28 /// Returns the source range spanning the node, extended to include \p Next, if 29 /// it immediately follows \p Node. Otherwise, returns the normal range of \p 30 /// Node. See comments on `getExtendedText()` for examples. 31 template <typename T> 32 CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next, 33 ASTContext &Context) { 34 return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()), 35 Next, Context); 36 } 37 38 /// Returns the source-code text in the specified range. 39 StringRef getText(CharSourceRange Range, const ASTContext &Context); 40 41 /// Returns the source-code text corresponding to \p Node. 42 template <typename T> 43 StringRef getText(const T &Node, const ASTContext &Context) { 44 return getText(CharSourceRange::getTokenRange(Node.getSourceRange()), 45 Context); 46 } 47 48 /// Returns the source text of the node, extended to include \p Next, if it 49 /// immediately follows the node. Otherwise, returns the text of just \p Node. 50 /// 51 /// For example, given statements S1 and S2 below: 52 /// \code 53 /// { 54 /// // S1: 55 /// if (!x) return foo(); 56 /// // S2: 57 /// if (!x) { return 3; } 58 /// } 59 /// \endcode 60 /// then 61 /// \code 62 /// getText(S1, Context) = "if (!x) return foo()" 63 /// getExtendedText(S1, tok::TokenKind::semi, Context) 64 /// = "if (!x) return foo();" 65 /// getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context) 66 /// = "return foo();" 67 /// getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context) 68 /// = getText(S2, Context) = "{ return 3; }" 69 /// \endcode 70 template <typename T> 71 StringRef getExtendedText(const T &Node, tok::TokenKind Next, 72 ASTContext &Context) { 73 return getText(getExtendedRange(Node, Next, Context), Context); 74 } 75 76 // Attempts to resolve the given range to one that can be edited by a rewrite; 77 // generally, one that starts and ends within a particular file. It supports 78 // a limited set of cases involving source locations in macro expansions. 79 llvm::Optional<CharSourceRange> 80 getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM, 81 const LangOptions &LangOpts); 82 83 inline llvm::Optional<CharSourceRange> 84 getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) { 85 return getRangeForEdit(EditRange, Context.getSourceManager(), 86 Context.getLangOpts()); 87 } 88 } // namespace tooling 89 } // namespace clang 90 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H 91