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
24namespace clang {
25
26class LangOptions;
27class PPConditionalDirectiveRecord;
28class SourceManager;
29
30namespace edit {
31
32class Commit;
33class EditsReceiver;
34
35class 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<unsigned, SmallVector<MacroArgUse, 2>> ExpansionToArgMap;
66 SmallVector<std::pair<SourceLocation, MacroArgUse>, 2>
67 CurrCommitMacroArgExps;
68
69 IdentifierTable IdentTable;
70 llvm::BumpPtrAllocator StrAlloc;
71
72public:
73 EditedSource(const SourceManager &SM, const LangOptions &LangOpts,
74 const PPConditionalDirectiveRecord *PPRec = nullptr)
75 : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts) {}
76
77 const SourceManager &getSourceManager() const { return SourceMgr; }
78 const LangOptions &getLangOpts() const { return LangOpts; }
79
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
91 StringRef copyString(StringRef str) { return str.copy(StrAlloc); }
92 StringRef copyString(const Twine &twine);
93
94private:
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