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