Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:59

0001 //===- Rewriter.h - Code rewriting interface --------------------*- 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 defines the Rewriter class, which is used for code
0010 //  transformations.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_REWRITE_CORE_REWRITER_H
0015 #define LLVM_CLANG_REWRITE_CORE_REWRITER_H
0016 
0017 #include "clang/Basic/LLVM.h"
0018 #include "clang/Basic/SourceLocation.h"
0019 #include "llvm/ADT/RewriteBuffer.h"
0020 #include "llvm/ADT/StringRef.h"
0021 #include <map>
0022 #include <string>
0023 
0024 namespace clang {
0025 
0026 class LangOptions;
0027 class SourceManager;
0028 
0029 /// Rewriter - This is the main interface to the rewrite buffers.  Its primary
0030 /// job is to dispatch high-level requests to the low-level RewriteBuffers that
0031 /// are involved.
0032 class Rewriter {
0033   SourceManager *SourceMgr = nullptr;
0034   const LangOptions *LangOpts = nullptr;
0035   std::map<FileID, llvm::RewriteBuffer> RewriteBuffers;
0036 
0037 public:
0038   struct RewriteOptions {
0039     /// Given a source range, true to include previous inserts at the
0040     /// beginning of the range as part of the range itself (true by default).
0041     bool IncludeInsertsAtBeginOfRange = true;
0042 
0043     /// Given a source range, true to include previous inserts at the
0044     /// end of the range as part of the range itself (true by default).
0045     bool IncludeInsertsAtEndOfRange = true;
0046 
0047     /// If true and removing some text leaves a blank line
0048     /// also remove the empty line (false by default).
0049     ///
0050     /// FIXME: This sometimes corrupts the file's rewrite buffer due to
0051     /// incorrect indexing in the implementation (see the FIXME in
0052     /// llvm::RewriteBuffer::RemoveText).  Moreover, it's inefficient because
0053     /// it must scan the buffer from the beginning to find the start of the
0054     /// line.  When feasible, it's better for the caller to check for a blank
0055     /// line and then, if found, expand the removal range to include it.
0056     /// Checking for a blank line is easy if, for example, the caller can
0057     /// guarantee this is the first edit of a line.  In that case, it can just
0058     /// scan before and after the removal range until the next newline or
0059     /// begin/end of the input.
0060     bool RemoveLineIfEmpty = false;
0061 
0062     RewriteOptions() {}
0063   };
0064 
0065   using buffer_iterator = std::map<FileID, llvm::RewriteBuffer>::iterator;
0066   using const_buffer_iterator =
0067       std::map<FileID, llvm::RewriteBuffer>::const_iterator;
0068 
0069   explicit Rewriter() = default;
0070   explicit Rewriter(SourceManager &SM, const LangOptions &LO)
0071       : SourceMgr(&SM), LangOpts(&LO) {}
0072 
0073   void setSourceMgr(SourceManager &SM, const LangOptions &LO) {
0074     SourceMgr = &SM;
0075     LangOpts = &LO;
0076   }
0077 
0078   SourceManager &getSourceMgr() const { return *SourceMgr; }
0079   const LangOptions &getLangOpts() const { return *LangOpts; }
0080 
0081   /// isRewritable - Return true if this location is a raw file location, which
0082   /// is rewritable.  Locations from macros, etc are not rewritable.
0083   static bool isRewritable(SourceLocation Loc) {
0084     return Loc.isFileID();
0085   }
0086 
0087   /// getRangeSize - Return the size in bytes of the specified range if they
0088   /// are in the same file.  If not, this returns -1.
0089   int getRangeSize(SourceRange Range,
0090                    RewriteOptions opts = RewriteOptions()) const;
0091   int getRangeSize(const CharSourceRange &Range,
0092                    RewriteOptions opts = RewriteOptions()) const;
0093 
0094   /// getRewrittenText - Return the rewritten form of the text in the specified
0095   /// range.  If the start or end of the range was unrewritable or if they are
0096   /// in different buffers, this returns an empty string.
0097   ///
0098   /// Note that this method is not particularly efficient.
0099   std::string getRewrittenText(CharSourceRange Range) const;
0100 
0101   /// getRewrittenText - Return the rewritten form of the text in the specified
0102   /// range.  If the start or end of the range was unrewritable or if they are
0103   /// in different buffers, this returns an empty string.
0104   ///
0105   /// Note that this method is not particularly efficient.
0106   std::string getRewrittenText(SourceRange Range) const {
0107     return getRewrittenText(CharSourceRange::getTokenRange(Range));
0108   }
0109 
0110   /// InsertText - Insert the specified string at the specified location in the
0111   /// original buffer.  This method returns true (and does nothing) if the input
0112   /// location was not rewritable, false otherwise.
0113   ///
0114   /// \param indentNewLines if true new lines in the string are indented
0115   /// using the indentation of the source line in position \p Loc.
0116   bool InsertText(SourceLocation Loc, StringRef Str,
0117                   bool InsertAfter = true, bool indentNewLines = false);
0118 
0119   /// InsertTextAfter - Insert the specified string at the specified location in
0120   ///  the original buffer.  This method returns true (and does nothing) if
0121   ///  the input location was not rewritable, false otherwise.  Text is
0122   ///  inserted after any other text that has been previously inserted
0123   ///  at the some point (the default behavior for InsertText).
0124   bool InsertTextAfter(SourceLocation Loc, StringRef Str) {
0125     return InsertText(Loc, Str);
0126   }
0127 
0128   /// Insert the specified string after the token in the
0129   /// specified location.
0130   bool InsertTextAfterToken(SourceLocation Loc, StringRef Str);
0131 
0132   /// InsertText - Insert the specified string at the specified location in the
0133   /// original buffer.  This method returns true (and does nothing) if the input
0134   /// location was not rewritable, false otherwise.  Text is
0135   /// inserted before any other text that has been previously inserted
0136   /// at the some point.
0137   bool InsertTextBefore(SourceLocation Loc, StringRef Str) {
0138     return InsertText(Loc, Str, false);
0139   }
0140 
0141   /// RemoveText - Remove the specified text region.
0142   bool RemoveText(SourceLocation Start, unsigned Length,
0143                   RewriteOptions opts = RewriteOptions());
0144 
0145   /// Remove the specified text region.
0146   bool RemoveText(CharSourceRange range,
0147                   RewriteOptions opts = RewriteOptions()) {
0148     return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
0149   }
0150 
0151   /// Remove the specified text region.
0152   bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) {
0153     return RemoveText(range.getBegin(), getRangeSize(range, opts), opts);
0154   }
0155 
0156   /// ReplaceText - This method replaces a range of characters in the input
0157   /// buffer with a new string.  This is effectively a combined "remove/insert"
0158   /// operation.
0159   bool ReplaceText(SourceLocation Start, unsigned OrigLength,
0160                    StringRef NewStr);
0161 
0162   /// ReplaceText - This method replaces a range of characters in the input
0163   /// buffer with a new string.  This is effectively a combined "remove/insert"
0164   /// operation.
0165   bool ReplaceText(CharSourceRange range, StringRef NewStr) {
0166     return ReplaceText(range.getBegin(), getRangeSize(range), NewStr);
0167   }
0168 
0169   /// ReplaceText - This method replaces a range of characters in the input
0170   /// buffer with a new string.  This is effectively a combined "remove/insert"
0171   /// operation.
0172   bool ReplaceText(SourceRange range, StringRef NewStr) {
0173     return ReplaceText(range.getBegin(), getRangeSize(range), NewStr);
0174   }
0175 
0176   /// ReplaceText - This method replaces a range of characters in the input
0177   /// buffer with a new string.  This is effectively a combined "remove/insert"
0178   /// operation.
0179   bool ReplaceText(SourceRange range, SourceRange replacementRange);
0180 
0181   /// Increase indentation for the lines between the given source range.
0182   /// To determine what the indentation should be, 'parentIndent' is used
0183   /// that should be at a source location with an indentation one degree
0184   /// lower than the given range.
0185   bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent);
0186   bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) {
0187     return IncreaseIndentation(CharSourceRange::getTokenRange(range),
0188                                parentIndent);
0189   }
0190 
0191   /// getEditBuffer - This is like getRewriteBufferFor, but always returns a
0192   /// buffer, and allows you to write on it directly.  This is useful if you
0193   /// want efficient low-level access to apis for scribbling on one specific
0194   /// FileID's buffer.
0195   llvm::RewriteBuffer &getEditBuffer(FileID FID);
0196 
0197   /// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
0198   /// If no modification has been made to it, return null.
0199   const llvm::RewriteBuffer *getRewriteBufferFor(FileID FID) const {
0200     std::map<FileID, llvm::RewriteBuffer>::const_iterator I =
0201         RewriteBuffers.find(FID);
0202     return I == RewriteBuffers.end() ? nullptr : &I->second;
0203   }
0204 
0205   // Iterators over rewrite buffers.
0206   buffer_iterator buffer_begin() { return RewriteBuffers.begin(); }
0207   buffer_iterator buffer_end() { return RewriteBuffers.end(); }
0208   const_buffer_iterator buffer_begin() const { return RewriteBuffers.begin(); }
0209   const_buffer_iterator buffer_end() const { return RewriteBuffers.end(); }
0210 
0211   /// overwriteChangedFiles - Save all changed files to disk.
0212   ///
0213   /// Returns true if any files were not saved successfully.
0214   /// Outputs diagnostics via the source manager's diagnostic engine
0215   /// in case of an error.
0216   bool overwriteChangedFiles();
0217 
0218 private:
0219   unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
0220 };
0221 
0222 } // namespace clang
0223 
0224 #endif // LLVM_CLANG_REWRITE_CORE_REWRITER_H