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 |