Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 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 | #include <optional> |
||
| 20 | |||
| 21 | namespace clang { |
||
| 22 | namespace tooling { |
||
| 23 | |||
| 24 | /// Extends \p Range to include the token \p Terminator, if it immediately |
||
| 25 | /// follows the end of the range. Otherwise, returns \p Range unchanged. |
||
| 26 | CharSourceRange maybeExtendRange(CharSourceRange Range, |
||
| 27 | tok::TokenKind Terminator, |
||
| 28 | ASTContext &Context); |
||
| 29 | |||
| 30 | /// Returns the source range spanning the node, extended to include \p Next, if |
||
| 31 | /// it immediately follows \p Node. Otherwise, returns the normal range of \p |
||
| 32 | /// Node. See comments on `getExtendedText()` for examples. |
||
| 33 | template <typename T> |
||
| 34 | CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next, |
||
| 35 | ASTContext &Context) { |
||
| 36 | return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()), |
||
| 37 | Next, Context); |
||
| 38 | } |
||
| 39 | |||
| 40 | /// Returns the logical source range of the node extended to include associated |
||
| 41 | /// comments and whitespace before and after the node, and associated |
||
| 42 | /// terminators. The returned range consists of file locations, if valid file |
||
| 43 | /// locations can be found for the associated content; otherwise, an invalid |
||
| 44 | /// range is returned. |
||
| 45 | /// |
||
| 46 | /// Note that parsing comments is disabled by default. In order to select a |
||
| 47 | /// range containing associated comments, you may need to invoke the tool with |
||
| 48 | /// `-fparse-all-comments`. |
||
| 49 | CharSourceRange getAssociatedRange(const Decl &D, ASTContext &Context); |
||
| 50 | |||
| 51 | /// Returns the source-code text in the specified range. |
||
| 52 | StringRef getText(CharSourceRange Range, const ASTContext &Context); |
||
| 53 | |||
| 54 | /// Returns the source-code text corresponding to \p Node. |
||
| 55 | template <typename T> |
||
| 56 | StringRef getText(const T &Node, const ASTContext &Context) { |
||
| 57 | return getText(CharSourceRange::getTokenRange(Node.getSourceRange()), |
||
| 58 | Context); |
||
| 59 | } |
||
| 60 | |||
| 61 | /// Returns the source text of the node, extended to include \p Next, if it |
||
| 62 | /// immediately follows the node. Otherwise, returns the text of just \p Node. |
||
| 63 | /// |
||
| 64 | /// For example, given statements S1 and S2 below: |
||
| 65 | /// \code |
||
| 66 | /// { |
||
| 67 | /// // S1: |
||
| 68 | /// if (!x) return foo(); |
||
| 69 | /// // S2: |
||
| 70 | /// if (!x) { return 3; } |
||
| 71 | /// } |
||
| 72 | /// \endcode |
||
| 73 | /// then |
||
| 74 | /// \code |
||
| 75 | /// getText(S1, Context) = "if (!x) return foo()" |
||
| 76 | /// getExtendedText(S1, tok::TokenKind::semi, Context) |
||
| 77 | /// = "if (!x) return foo();" |
||
| 78 | /// getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context) |
||
| 79 | /// = "return foo();" |
||
| 80 | /// getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context) |
||
| 81 | /// = getText(S2, Context) = "{ return 3; }" |
||
| 82 | /// \endcode |
||
| 83 | template <typename T> |
||
| 84 | StringRef getExtendedText(const T &Node, tok::TokenKind Next, |
||
| 85 | ASTContext &Context) { |
||
| 86 | return getText(getExtendedRange(Node, Next, Context), Context); |
||
| 87 | } |
||
| 88 | |||
| 89 | /// Determines whether \p Range is one that can be edited by a rewrite; |
||
| 90 | /// generally, one that starts and ends within a particular file. |
||
| 91 | llvm::Error validateEditRange(const CharSourceRange &Range, |
||
| 92 | const SourceManager &SM); |
||
| 93 | |||
| 94 | /// Attempts to resolve the given range to one that can be edited by a rewrite; |
||
| 95 | /// generally, one that starts and ends within a particular file. If a value is |
||
| 96 | /// returned, it satisfies \c validateEditRange. |
||
| 97 | /// |
||
| 98 | /// If \c IncludeMacroExpansion is true, a limited set of cases involving source |
||
| 99 | /// locations in macro expansions is supported. For example, if we're looking to |
||
| 100 | /// rewrite the int literal 3 to 6, and we have the following definition: |
||
| 101 | /// #define DO_NOTHING(x) x |
||
| 102 | /// then |
||
| 103 | /// foo(DO_NOTHING(3)) |
||
| 104 | /// will be rewritten to |
||
| 105 | /// foo(6) |
||
| 106 | std::optional<CharSourceRange> |
||
| 107 | getFileRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM, |
||
| 108 | const LangOptions &LangOpts, |
||
| 109 | bool IncludeMacroExpansion = true); |
||
| 110 | inline std::optional<CharSourceRange> |
||
| 111 | getFileRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context, |
||
| 112 | bool IncludeMacroExpansion = true) { |
||
| 113 | return getFileRangeForEdit(EditRange, Context.getSourceManager(), |
||
| 114 | Context.getLangOpts(), IncludeMacroExpansion); |
||
| 115 | } |
||
| 116 | |||
| 117 | /// Attempts to resolve the given range to one that starts and ends in a |
||
| 118 | /// particular file. |
||
| 119 | /// |
||
| 120 | /// If \c IncludeMacroExpansion is true, a limited set of cases involving source |
||
| 121 | /// locations in macro expansions is supported. For example, if we're looking to |
||
| 122 | /// get the range of the int literal 3, and we have the following definition: |
||
| 123 | /// #define DO_NOTHING(x) x |
||
| 124 | /// foo(DO_NOTHING(3)) |
||
| 125 | /// the returned range will hold the source text `DO_NOTHING(3)`. |
||
| 126 | std::optional<CharSourceRange> getFileRange(const CharSourceRange &EditRange, |
||
| 127 | const SourceManager &SM, |
||
| 128 | const LangOptions &LangOpts, |
||
| 129 | bool IncludeMacroExpansion); |
||
| 130 | inline std::optional<CharSourceRange> |
||
| 131 | getFileRange(const CharSourceRange &EditRange, const ASTContext &Context, |
||
| 132 | bool IncludeMacroExpansion) { |
||
| 133 | return getFileRange(EditRange, Context.getSourceManager(), |
||
| 134 | Context.getLangOpts(), IncludeMacroExpansion); |
||
| 135 | } |
||
| 136 | |||
| 137 | } // namespace tooling |
||
| 138 | } // namespace clang |
||
| 139 | #endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H |