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 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>
getExtendedRange(const T & Node,tok::TokenKind Next,ASTContext & Context)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 CharSourceRange getAssociatedRange(const Decl &D, ASTContext &Context);
45 
46 /// Returns the source-code text in the specified range.
47 StringRef getText(CharSourceRange Range, const ASTContext &Context);
48 
49 /// Returns the source-code text corresponding to \p Node.
50 template <typename T>
getText(const T & Node,const ASTContext & Context)51 StringRef getText(const T &Node, const ASTContext &Context) {
52   return getText(CharSourceRange::getTokenRange(Node.getSourceRange()),
53                  Context);
54 }
55 
56 /// Returns the source text of the node, extended to include \p Next, if it
57 /// immediately follows the node. Otherwise, returns the text of just \p Node.
58 ///
59 /// For example, given statements S1 and S2 below:
60 /// \code
61 ///   {
62 ///     // S1:
63 ///     if (!x) return foo();
64 ///     // S2:
65 ///     if (!x) { return 3; }
66 ///   }
67 /// \endcode
68 /// then
69 /// \code
70 ///   getText(S1, Context) = "if (!x) return foo()"
71 ///   getExtendedText(S1, tok::TokenKind::semi, Context)
72 ///     = "if (!x) return foo();"
73 ///   getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context)
74 ///     = "return foo();"
75 ///   getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context)
76 ///     = getText(S2, Context) = "{ return 3; }"
77 /// \endcode
78 template <typename T>
getExtendedText(const T & Node,tok::TokenKind Next,ASTContext & Context)79 StringRef getExtendedText(const T &Node, tok::TokenKind Next,
80                           ASTContext &Context) {
81   return getText(getExtendedRange(Node, Next, Context), Context);
82 }
83 
84 /// Determines whether \p Range is one that can be edited by a rewrite;
85 /// generally, one that starts and ends within a particular file.
86 llvm::Error validateEditRange(const CharSourceRange &Range,
87                               const SourceManager &SM);
88 
89 /// Attempts to resolve the given range to one that can be edited by a rewrite;
90 /// generally, one that starts and ends within a particular file. It supports a
91 /// limited set of cases involving source locations in macro expansions. If a
92 /// value is returned, it satisfies \c validateEditRange.
93 llvm::Optional<CharSourceRange>
94 getRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM,
95                 const LangOptions &LangOpts);
96 inline llvm::Optional<CharSourceRange>
getRangeForEdit(const CharSourceRange & EditRange,const ASTContext & Context)97 getRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context) {
98   return getRangeForEdit(EditRange, Context.getSourceManager(),
99                          Context.getLangOpts());
100 }
101 } // namespace tooling
102 } // namespace clang
103 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCE_CODE_H
104