Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:12

0001 //===--- SourceCode.h - Source code manipulation routines -------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file provides functions that simplify extraction of source code.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H
0014 #define LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H
0015 
0016 #include "clang/AST/ASTContext.h"
0017 #include "clang/Basic/SourceLocation.h"
0018 #include "clang/Basic/TokenKinds.h"
0019 #include <optional>
0020 
0021 namespace clang {
0022 namespace tooling {
0023 
0024 /// Extends \p Range to include the token \p Terminator, if it immediately
0025 /// follows the end of the range. Otherwise, returns \p Range unchanged.
0026 CharSourceRange maybeExtendRange(CharSourceRange Range,
0027                                  tok::TokenKind Terminator,
0028                                  ASTContext &Context);
0029 
0030 /// Returns the source range spanning the node, extended to include \p Next, if
0031 /// it immediately follows \p Node. Otherwise, returns the normal range of \p
0032 /// Node.  See comments on `getExtendedText()` for examples.
0033 template <typename T>
0034 CharSourceRange getExtendedRange(const T &Node, tok::TokenKind Next,
0035                                  ASTContext &Context) {
0036   return maybeExtendRange(CharSourceRange::getTokenRange(Node.getSourceRange()),
0037                           Next, Context);
0038 }
0039 
0040 /// Returns the logical source range of the node extended to include associated
0041 /// comments and whitespace before and after the node, and associated
0042 /// terminators. The returned range consists of file locations, if valid file
0043 /// locations can be found for the associated content; otherwise, an invalid
0044 /// range is returned.
0045 ///
0046 /// Note that parsing comments is disabled by default. In order to select a
0047 /// range containing associated comments, you may need to invoke the tool with
0048 /// `-fparse-all-comments`.
0049 CharSourceRange getAssociatedRange(const Decl &D, ASTContext &Context);
0050 
0051 /// Returns the source-code text in the specified range.
0052 StringRef getText(CharSourceRange Range, const ASTContext &Context);
0053 
0054 /// Returns the source-code text corresponding to \p Node.
0055 template <typename T>
0056 StringRef getText(const T &Node, const ASTContext &Context) {
0057   return getText(CharSourceRange::getTokenRange(Node.getSourceRange()),
0058                  Context);
0059 }
0060 
0061 /// Returns the source text of the node, extended to include \p Next, if it
0062 /// immediately follows the node. Otherwise, returns the text of just \p Node.
0063 ///
0064 /// For example, given statements S1 and S2 below:
0065 /// \code
0066 ///   {
0067 ///     // S1:
0068 ///     if (!x) return foo();
0069 ///     // S2:
0070 ///     if (!x) { return 3; }
0071 ///   }
0072 /// \endcode
0073 /// then
0074 /// \code
0075 ///   getText(S1, Context) = "if (!x) return foo()"
0076 ///   getExtendedText(S1, tok::TokenKind::semi, Context)
0077 ///     = "if (!x) return foo();"
0078 ///   getExtendedText(*S1.getThen(), tok::TokenKind::semi, Context)
0079 ///     = "return foo();"
0080 ///   getExtendedText(*S2.getThen(), tok::TokenKind::semi, Context)
0081 ///     = getText(S2, Context) = "{ return 3; }"
0082 /// \endcode
0083 template <typename T>
0084 StringRef getExtendedText(const T &Node, tok::TokenKind Next,
0085                           ASTContext &Context) {
0086   return getText(getExtendedRange(Node, Next, Context), Context);
0087 }
0088 
0089 /// Determines whether \p Range is one that can be edited by a rewrite;
0090 /// generally, one that starts and ends within a particular file.
0091 llvm::Error validateEditRange(const CharSourceRange &Range,
0092                               const SourceManager &SM);
0093 
0094 /// Determines whether \p Range is one that can be read from. If
0095 /// `AllowSystemHeaders` is false, a range that falls within a system header
0096 /// fails validation.
0097 llvm::Error validateRange(const CharSourceRange &Range, const SourceManager &SM,
0098                           bool AllowSystemHeaders);
0099 
0100 /// Attempts to resolve the given range to one that can be edited by a rewrite;
0101 /// generally, one that starts and ends within a particular file. If a value is
0102 /// returned, it satisfies \c validateEditRange.
0103 ///
0104 /// If \c IncludeMacroExpansion is true, a limited set of cases involving source
0105 /// locations in macro expansions is supported. For example, if we're looking to
0106 /// rewrite the int literal 3 to 6, and we have the following definition:
0107 ///    #define DO_NOTHING(x) x
0108 /// then
0109 ///    foo(DO_NOTHING(3))
0110 /// will be rewritten to
0111 ///    foo(6)
0112 std::optional<CharSourceRange>
0113 getFileRangeForEdit(const CharSourceRange &EditRange, const SourceManager &SM,
0114                     const LangOptions &LangOpts,
0115                     bool IncludeMacroExpansion = true);
0116 inline std::optional<CharSourceRange>
0117 getFileRangeForEdit(const CharSourceRange &EditRange, const ASTContext &Context,
0118                     bool IncludeMacroExpansion = true) {
0119   return getFileRangeForEdit(EditRange, Context.getSourceManager(),
0120                              Context.getLangOpts(), IncludeMacroExpansion);
0121 }
0122 
0123 /// Attempts to resolve the given range to one that starts and ends in a
0124 /// particular file.
0125 ///
0126 /// If \c IncludeMacroExpansion is true, a limited set of cases involving source
0127 /// locations in macro expansions is supported. For example, if we're looking to
0128 /// get the range of the int literal 3, and we have the following definition:
0129 ///    #define DO_NOTHING(x) x
0130 ///    foo(DO_NOTHING(3))
0131 /// the returned range will hold the source text `DO_NOTHING(3)`.
0132 std::optional<CharSourceRange> getFileRange(const CharSourceRange &EditRange,
0133                                             const SourceManager &SM,
0134                                             const LangOptions &LangOpts,
0135                                             bool IncludeMacroExpansion);
0136 inline std::optional<CharSourceRange>
0137 getFileRange(const CharSourceRange &EditRange, const ASTContext &Context,
0138              bool IncludeMacroExpansion) {
0139   return getFileRange(EditRange, Context.getSourceManager(),
0140                       Context.getLangOpts(), IncludeMacroExpansion);
0141 }
0142 
0143 } // namespace tooling
0144 } // namespace clang
0145 #endif // LLVM_CLANG_TOOLING_TRANSFORMER_SOURCECODE_H