1 //===- EditedSource.h - Collection of source 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_EDITEDSOURCE_H 10 #define LLVM_CLANG_EDIT_EDITEDSOURCE_H 11 12 #include "clang/Basic/IdentifierTable.h" 13 #include "clang/Basic/LLVM.h" 14 #include "clang/Basic/SourceLocation.h" 15 #include "clang/Edit/FileOffset.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/Allocator.h" 20 #include <map> 21 #include <tuple> 22 #include <utility> 23 24 namespace clang { 25 26 class LangOptions; 27 class PPConditionalDirectiveRecord; 28 class SourceManager; 29 30 namespace edit { 31 32 class Commit; 33 class EditsReceiver; 34 35 class EditedSource { 36 const SourceManager &SourceMgr; 37 const LangOptions &LangOpts; 38 const PPConditionalDirectiveRecord *PPRec; 39 40 struct FileEdit { 41 StringRef Text; 42 unsigned RemoveLen = 0; 43 44 FileEdit() = default; 45 }; 46 47 using FileEditsTy = std::map<FileOffset, FileEdit>; 48 49 FileEditsTy FileEdits; 50 51 struct MacroArgUse { 52 IdentifierInfo *Identifier; 53 SourceLocation ImmediateExpansionLoc; 54 55 // Location of argument use inside the top-level macro 56 SourceLocation UseLoc; 57 58 bool operator==(const MacroArgUse &Other) const { 59 return std::tie(Identifier, ImmediateExpansionLoc, UseLoc) == 60 std::tie(Other.Identifier, Other.ImmediateExpansionLoc, 61 Other.UseLoc); 62 } 63 }; 64 65 llvm::DenseMap<SourceLocation, SmallVector<MacroArgUse, 2>> ExpansionToArgMap; 66 SmallVector<std::pair<SourceLocation, MacroArgUse>, 2> 67 CurrCommitMacroArgExps; 68 69 IdentifierTable IdentTable; 70 llvm::BumpPtrAllocator StrAlloc; 71 72 public: 73 EditedSource(const SourceManager &SM, const LangOptions &LangOpts, 74 const PPConditionalDirectiveRecord *PPRec = nullptr) SourceMgr(SM)75 : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts) {} 76 getSourceManager()77 const SourceManager &getSourceManager() const { return SourceMgr; } getLangOpts()78 const LangOptions &getLangOpts() const { return LangOpts; } 79 getPPCondDirectiveRecord()80 const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const { 81 return PPRec; 82 } 83 84 bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs); 85 86 bool commit(const Commit &commit); 87 88 void applyRewrites(EditsReceiver &receiver, bool adjustRemovals = true); 89 void clearRewrites(); 90 copyString(StringRef str)91 StringRef copyString(StringRef str) { return str.copy(StrAlloc); } 92 StringRef copyString(const Twine &twine); 93 94 private: 95 bool commitInsert(SourceLocation OrigLoc, FileOffset Offs, StringRef text, 96 bool beforePreviousInsertions); 97 bool commitInsertFromRange(SourceLocation OrigLoc, FileOffset Offs, 98 FileOffset InsertFromRangeOffs, unsigned Len, 99 bool beforePreviousInsertions); 100 void commitRemove(SourceLocation OrigLoc, FileOffset BeginOffs, unsigned Len); 101 102 StringRef getSourceText(FileOffset BeginOffs, FileOffset EndOffs, 103 bool &Invalid); 104 FileEditsTy::iterator getActionForOffset(FileOffset Offs); 105 void deconstructMacroArgLoc(SourceLocation Loc, 106 SourceLocation &ExpansionLoc, 107 MacroArgUse &ArgUse); 108 109 void startingCommit(); 110 void finishedCommit(); 111 }; 112 113 } // namespace edit 114 115 } // namespace clang 116 117 #endif // LLVM_CLANG_EDIT_EDITEDSOURCE_H 118