1234287Sdim//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===//
2234287Sdim//
3234287Sdim//                     The LLVM Compiler Infrastructure
4234287Sdim//
5234287Sdim// This file is distributed under the University of Illinois Open Source
6234287Sdim// License. See LICENSE.TXT for details.
7234287Sdim//
8234287Sdim//===----------------------------------------------------------------------===//
9234287Sdim
10234287Sdim#ifndef LLVM_CLANG_EDIT_COMMIT_H
11234287Sdim#define LLVM_CLANG_EDIT_COMMIT_H
12234287Sdim
13234287Sdim#include "clang/Edit/FileOffset.h"
14252723Sdim#include "llvm/ADT/SmallVector.h"
15234287Sdim#include "llvm/ADT/StringRef.h"
16263509Sdim#include "llvm/Support/Allocator.h"
17234287Sdim
18234287Sdimnamespace clang {
19234287Sdim  class LangOptions;
20252723Sdim  class PPConditionalDirectiveRecord;
21234287Sdim
22234287Sdimnamespace edit {
23234287Sdim  class EditedSource;
24234287Sdim
25234287Sdimclass Commit {
26234287Sdimpublic:
27234287Sdim  enum EditKind {
28234287Sdim    Act_Insert,
29234287Sdim    Act_InsertFromRange,
30234287Sdim    Act_Remove
31234287Sdim  };
32234287Sdim
33234287Sdim  struct Edit {
34234287Sdim    EditKind Kind;
35234287Sdim    StringRef Text;
36234287Sdim    SourceLocation OrigLoc;
37234287Sdim    FileOffset Offset;
38234287Sdim    FileOffset InsertFromRangeOffs;
39234287Sdim    unsigned Length;
40234287Sdim    bool BeforePrev;
41234287Sdim
42234287Sdim    SourceLocation getFileLocation(SourceManager &SM) const;
43234287Sdim    CharSourceRange getFileRange(SourceManager &SM) const;
44234287Sdim    CharSourceRange getInsertFromRange(SourceManager &SM) const;
45234287Sdim  };
46234287Sdim
47234287Sdimprivate:
48234287Sdim  const SourceManager &SourceMgr;
49234287Sdim  const LangOptions &LangOpts;
50252723Sdim  const PPConditionalDirectiveRecord *PPRec;
51234287Sdim  EditedSource *Editor;
52263509Sdim
53263509Sdim  const bool ForceCommitInSystemHeader;
54234287Sdim  bool IsCommitable;
55234287Sdim  SmallVector<Edit, 8> CachedEdits;
56263509Sdim
57263509Sdim  llvm::BumpPtrAllocator StrAlloc;
58234287Sdim
59234287Sdimpublic:
60234287Sdim  explicit Commit(EditedSource &Editor);
61234287Sdim  Commit(const SourceManager &SM, const LangOptions &LangOpts,
62252723Sdim         const PPConditionalDirectiveRecord *PPRec = 0)
63234287Sdim    : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(0),
64263509Sdim      ForceCommitInSystemHeader(true), IsCommitable(true) { }
65234287Sdim
66234287Sdim  bool isCommitable() const { return IsCommitable; }
67234287Sdim
68234287Sdim  bool insert(SourceLocation loc, StringRef text, bool afterToken = false,
69234287Sdim              bool beforePreviousInsertions = false);
70234287Sdim  bool insertAfterToken(SourceLocation loc, StringRef text,
71234287Sdim                        bool beforePreviousInsertions = false) {
72234287Sdim    return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions);
73234287Sdim  }
74234287Sdim  bool insertBefore(SourceLocation loc, StringRef text) {
75234287Sdim    return insert(loc, text, /*afterToken=*/false,
76234287Sdim                  /*beforePreviousInsertions=*/true);
77234287Sdim  }
78234287Sdim  bool insertFromRange(SourceLocation loc, CharSourceRange range,
79234287Sdim                       bool afterToken = false,
80234287Sdim                       bool beforePreviousInsertions = false);
81234287Sdim  bool insertWrap(StringRef before, CharSourceRange range, StringRef after);
82234287Sdim
83234287Sdim  bool remove(CharSourceRange range);
84234287Sdim
85234287Sdim  bool replace(CharSourceRange range, StringRef text);
86234287Sdim  bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange);
87234287Sdim  bool replaceText(SourceLocation loc, StringRef text,
88234287Sdim                   StringRef replacementText);
89234287Sdim
90234287Sdim  bool insertFromRange(SourceLocation loc, SourceRange TokenRange,
91234287Sdim                       bool afterToken = false,
92234287Sdim                       bool beforePreviousInsertions = false) {
93234287Sdim    return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange),
94234287Sdim                           afterToken, beforePreviousInsertions);
95234287Sdim  }
96234287Sdim  bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) {
97234287Sdim    return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after);
98234287Sdim  }
99234287Sdim  bool remove(SourceRange TokenRange) {
100234287Sdim    return remove(CharSourceRange::getTokenRange(TokenRange));
101234287Sdim  }
102234287Sdim  bool replace(SourceRange TokenRange, StringRef text) {
103234287Sdim    return replace(CharSourceRange::getTokenRange(TokenRange), text);
104234287Sdim  }
105234287Sdim  bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) {
106234287Sdim    return replaceWithInner(CharSourceRange::getTokenRange(TokenRange),
107234287Sdim                            CharSourceRange::getTokenRange(TokenInnerRange));
108234287Sdim  }
109234287Sdim
110263509Sdim  typedef SmallVectorImpl<Edit>::const_iterator edit_iterator;
111234287Sdim  edit_iterator edit_begin() const { return CachedEdits.begin(); }
112234287Sdim  edit_iterator edit_end() const { return CachedEdits.end(); }
113234287Sdim
114234287Sdimprivate:
115234287Sdim  void addInsert(SourceLocation OrigLoc,
116234287Sdim                FileOffset Offs, StringRef text, bool beforePreviousInsertions);
117234287Sdim  void addInsertFromRange(SourceLocation OrigLoc, FileOffset Offs,
118234287Sdim                          FileOffset RangeOffs, unsigned RangeLen,
119234287Sdim                          bool beforePreviousInsertions);
120234287Sdim  void addRemove(SourceLocation OrigLoc, FileOffset Offs, unsigned Len);
121234287Sdim
122234287Sdim  bool canInsert(SourceLocation loc, FileOffset &Offset);
123234287Sdim  bool canInsertAfterToken(SourceLocation loc, FileOffset &Offset,
124234287Sdim                           SourceLocation &AfterLoc);
125234287Sdim  bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs);
126234287Sdim  bool canRemoveRange(CharSourceRange range, FileOffset &Offs, unsigned &Len);
127234287Sdim  bool canReplaceText(SourceLocation loc, StringRef text,
128234287Sdim                      FileOffset &Offs, unsigned &Len);
129234287Sdim
130234287Sdim  void commitInsert(FileOffset offset, StringRef text,
131234287Sdim                    bool beforePreviousInsertions);
132234287Sdim  void commitRemove(FileOffset offset, unsigned length);
133234287Sdim
134234287Sdim  bool isAtStartOfMacroExpansion(SourceLocation loc,
135234287Sdim                                 SourceLocation *MacroBegin = 0) const;
136234287Sdim  bool isAtEndOfMacroExpansion(SourceLocation loc,
137234287Sdim                               SourceLocation *MacroEnd = 0) const;
138263509Sdim
139263509Sdim  StringRef copyString(StringRef str) {
140263509Sdim    char *buf = StrAlloc.Allocate<char>(str.size());
141263509Sdim    std::memcpy(buf, str.data(), str.size());
142263509Sdim    return StringRef(buf, str.size());
143263509Sdim  }
144234287Sdim};
145234287Sdim
146234287Sdim}
147234287Sdim
148234287Sdim} // end namespace clang
149234287Sdim
150234287Sdim#endif
151