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