Home | History | Annotate | Line # | Download | only in Edit
      1 //===- Commit.h - A unit of edits -------------------------------*- 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 #ifndef LLVM_CLANG_EDIT_COMMIT_H
     10 #define LLVM_CLANG_EDIT_COMMIT_H
     11 
     12 #include "clang/Basic/LLVM.h"
     13 #include "clang/Basic/SourceLocation.h"
     14 #include "clang/Edit/FileOffset.h"
     15 #include "llvm/ADT/SmallVector.h"
     16 #include "llvm/ADT/StringRef.h"
     17 #include "llvm/Support/Allocator.h"
     18 
     19 namespace clang {
     20 
     21 class LangOptions;
     22 class PPConditionalDirectiveRecord;
     23 class SourceManager;
     24 
     25 namespace edit {
     26 
     27 class EditedSource;
     28 
     29 class Commit {
     30 public:
     31   enum EditKind {
     32     Act_Insert,
     33     Act_InsertFromRange,
     34     Act_Remove
     35   };
     36 
     37   struct Edit {
     38     EditKind Kind;
     39     StringRef Text;
     40     SourceLocation OrigLoc;
     41     FileOffset Offset;
     42     FileOffset InsertFromRangeOffs;
     43     unsigned Length;
     44     bool BeforePrev;
     45 
     46     SourceLocation getFileLocation(SourceManager &SM) const;
     47     CharSourceRange getFileRange(SourceManager &SM) const;
     48     CharSourceRange getInsertFromRange(SourceManager &SM) const;
     49   };
     50 
     51 private:
     52   const SourceManager &SourceMgr;
     53   const LangOptions &LangOpts;
     54   const PPConditionalDirectiveRecord *PPRec;
     55   EditedSource *Editor = nullptr;
     56 
     57   bool IsCommitable = true;
     58   SmallVector<Edit, 8> CachedEdits;
     59 
     60   llvm::BumpPtrAllocator StrAlloc;
     61 
     62 public:
     63   explicit Commit(EditedSource &Editor);
     64   Commit(const SourceManager &SM, const LangOptions &LangOpts,
     65          const PPConditionalDirectiveRecord *PPRec = nullptr)
     66       : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {}
     67 
     68   bool isCommitable() const { return IsCommitable; }
     69 
     70   bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
     71               bool beforePreviousInsertions = false);
     72 
     73   bool insertAfterToken(SourceLocation loc, StringRef text,
     74                         bool beforePreviousInsertions = false) {
     75     return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
     76   }
     77 
     78   bool insertBefore(SourceLocation loc, StringRef text) {
     79     return insert(loc, text, /*afterToken=*/false,
     80                   /*beforePreviousInsertions=*/true);
     81   }
     82 
     83   bool insertFromRange(SourceLocation loc, CharSourceRange range,
     84                        bool afterToken = false,
     85                        bool beforePreviousInsertions = false);
     86   bool insertWrap(StringRef before, CharSourceRange range, StringRef after);
     87 
     88   bool remove(CharSourceRange range);
     89 
     90   bool replace(CharSourceRange range, StringRef text);
     91   bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange);
     92   bool replaceText(SourceLocation loc, StringRef text,
     93                    StringRef replacementText);
     94 
     95   bool insertFromRange(SourceLocation loc, SourceRange TokenRange,
     96                        bool afterToken = false,
     97                        bool beforePreviousInsertions = false) {
     98     return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
     99                            afterToken, beforePreviousInsertions);
    100   }
    101 
    102   bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
    103     return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
    104   }
    105 
    106   bool remove(SourceRange TokenRange) {
    107     return remove(CharSourceRange::getTokenRange(TokenRange));
    108   }
    109 
    110   bool replace(SourceRange TokenRange, StringRef text) {
    111     return replace(CharSourceRange::getTokenRange(TokenRange), text);
    112   }
    113 
    114   bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
    115     return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
    116                             CharSourceRange::getTokenRange(TokenInnerRange));
    117   }
    118 
    119   using edit_iterator = SmallVectorImpl<Edit>::const_iterator;
    120 
    121   edit_iterator edit_begin() const { return CachedEdits.begin(); }
    122   edit_iterator edit_end() const { return CachedEdits.end(); }
    123 
    124 private:
    125   void addInsert(SourceLocation OrigLoc,
    126                 FileOffset Offs, StringRef text, bool beforePreviousInsertions);
    127   void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
    128                           FileOffset RangeOffs, unsigned RangeLen,
    129                           bool beforePreviousInsertions);
    130   void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len);
    131 
    132   bool canInsert(SourceLocation loc, FileOffset &Offset);
    133   bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset,
    134                            SourceLocation &AfterLoc);
    135   bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
    136   bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len);
    137   bool canReplaceText(SourceLocation loc, StringRef text,
    138                       FileOffset &Offs, unsigned &Len);
    139 
    140   void commitInsert(FileOffset offset, StringRef text,
    141                     bool beforePreviousInsertions);
    142   void commitRemove(FileOffset offset, unsigned length);
    143 
    144   bool isAtStartOfMacroExpansion(SourceLocation loc,
    145                                  SourceLocation *MacroBegin = nullptr) const;
    146   bool isAtEndOfMacroExpansion(SourceLocation loc,
    147                                SourceLocation *MacroEnd = nullptr) const;
    148 };
    149 
    150 } // namespace edit
    151 
    152 } // namespace clang
    153 
    154 #endif // LLVM_CLANG_EDIT_COMMIT_H
    155