18bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//===--- Rewriter.cpp - Code rewriting interface --------------------------===//
28bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//
38bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//                     The LLVM Compiler Infrastructure
48bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
78bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//
88bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//===----------------------------------------------------------------------===//
98bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//
108bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//  This file defines the Rewriter class, which is used for code
118bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//  transformations.
128bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//
138bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner//===----------------------------------------------------------------------===//
148bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner
15305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Rewrite/Core/Rewriter.h"
162c3352b5d1f5f4546af2f3051a304d84d57c697eTed Kremenek#include "clang/AST/Decl.h"
17a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "clang/AST/PrettyPrinter.h"
18a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "clang/AST/Stmt.h"
19bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/DiagnosticIDs.h"
20bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/FileManager.h"
218a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Basic/SourceManager.h"
22bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Lex/Lexer.h"
238fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h"
24bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/FileSystem.h"
25a93d0f280693b8418bc88cf7a8c93325f7fcf4c6Benjamin Kramer#include "llvm/Support/raw_ostream.h"
268bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattnerusing namespace clang;
278bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner
285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerraw_ostream &RewriteBuffer::write(raw_ostream &os) const {
290ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky  // FIXME: eliminate the copy by writing out each chunk at a time
300ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky  os << std::string(begin(), end());
310ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky  return os;
320ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky}
330ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky
34b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis/// \brief Return true if this character is non-new-line whitespace:
358c10f841040b1e2951d06d385c8eefbcbe578fcfJames Dennett/// ' ', '\\t', '\\f', '\\v', '\\r'.
36b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisstatic inline bool isWhitespace(unsigned char c) {
37b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  switch (c) {
38b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  case ' ':
39b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  case '\t':
40b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  case '\f':
41b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  case '\v':
42b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  case '\r':
43b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    return true;
44b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  default:
45b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    return false;
46b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  }
47b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis}
48b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
49b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisvoid RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size,
50b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis                               bool removeLineIfEmpty) {
517c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  // Nothing to remove, exit early.
527c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  if (Size == 0) return;
537c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner
547c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  unsigned RealOffset = getMappedOffset(OrigOffset, true);
557c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  assert(RealOffset+Size < Buffer.size() && "Invalid location");
561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
577c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  // Remove the dead characters.
58febe719596ee68605944da5f2e03258e18e6df8cChris Lattner  Buffer.erase(RealOffset, Size);
597c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner
607c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  // Add a delta so that future changes are offset correctly.
61a0978c24829dfd552d38fc3bae2b86e18bb90d49Eli Friedman  AddReplaceDelta(OrigOffset, -Size);
62b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
63b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  if (removeLineIfEmpty) {
64b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    // Find the line that the remove occurred and if it is completely empty
65b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    // remove the line as well.
66b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
67b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    iterator curLineStart = begin();
68b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    unsigned curLineStartOffs = 0;
69b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    iterator posI = begin();
70b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    for (unsigned i = 0; i != RealOffset; ++i) {
71b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      if (*posI == '\n') {
72b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis        curLineStart = posI;
73b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis        ++curLineStart;
74b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis        curLineStartOffs = i + 1;
75b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      }
76b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      ++posI;
77b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    }
78b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
79b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    unsigned lineSize = 0;
80b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    posI = curLineStart;
81b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    while (posI != end() && isWhitespace(*posI)) {
82b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      ++posI;
83b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      ++lineSize;
84b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    }
85b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    if (posI != end() && *posI == '\n') {
86b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      Buffer.erase(curLineStartOffs, lineSize + 1/* + '\n'*/);
87b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis      AddReplaceDelta(curLineStartOffs, -(lineSize + 1/* + '\n'*/));
88b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis    }
89b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  }
908bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner}
918bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner
925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str,
93886c8db545170850f7806f47b5f6120864effd09Ted Kremenek                               bool InsertAfter) {
941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
9503b071043593590b01fdf61df3e29c0ae7c067d3Chris Lattner  // Nothing to insert, exit early.
96d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  if (Str.empty()) return;
97febe719596ee68605944da5f2e03258e18e6df8cChris Lattner
98886c8db545170850f7806f47b5f6120864effd09Ted Kremenek  unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter);
99d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  Buffer.insert(RealOffset, Str.begin(), Str.end());
1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
10103b071043593590b01fdf61df3e29c0ae7c067d3Chris Lattner  // Add a delta so that future changes are offset correctly.
102d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  AddInsertDelta(OrigOffset, Str.size());
1038bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner}
1048a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
1057c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner/// ReplaceText - This method replaces a range of characters in the input
106febe719596ee68605944da5f2e03258e18e6df8cChris Lattner/// buffer with a new string.  This is effectively a combined "remove+insert"
1077c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner/// operation.
1087c239606f3a7a685653a0a7e64459c3f43522666Chris Lattnervoid RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength,
1095f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                StringRef NewStr) {
110a0978c24829dfd552d38fc3bae2b86e18bb90d49Eli Friedman  unsigned RealOffset = getMappedOffset(OrigOffset, true);
111febe719596ee68605944da5f2e03258e18e6df8cChris Lattner  Buffer.erase(RealOffset, OrigLength);
112d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  Buffer.insert(RealOffset, NewStr.begin(), NewStr.end());
113d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  if (OrigLength != NewStr.size())
114d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar    AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength);
1157c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner}
1168a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
1178a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
1188a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner//===----------------------------------------------------------------------===//
1198a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner// Rewriter class
1208a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner//===----------------------------------------------------------------------===//
1218a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
122311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner/// getRangeSize - Return the size in bytes of the specified range if they
123311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner/// are in the same file.  If not, this returns -1.
124b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisint Rewriter::getRangeSize(const CharSourceRange &Range,
125fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis                           RewriteOptions opts) const {
126311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner  if (!isRewritable(Range.getBegin()) ||
127311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner      !isRewritable(Range.getEnd())) return -1;
1281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1292b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID StartFileID, EndFileID;
1302b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned StartOff, EndOff;
1311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
132311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner  StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
133311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner  EndOff   = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
135311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner  if (StartFileID != EndFileID)
136311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner    return -1;
1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
138d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner  // If edits have been made to this buffer, the delta between the range may
139d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner  // have changed.
1402b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  std::map<FileID, RewriteBuffer>::const_iterator I =
141075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner    RewriteBuffers.find(StartFileID);
142d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner  if (I != RewriteBuffers.end()) {
143075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner    const RewriteBuffer &RB = I->second;
144fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis    EndOff = RB.getMappedOffset(EndOff, opts.IncludeInsertsAtEndOfRange);
145fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis    StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange);
146075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner  }
147075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner
1481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1499d62a5b31ec3762f416cc9ef89d1b7b433d13ac5Chris Lattner  // Adjust the end offset to the end of the last token, instead of being the
1500a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner  // start of the last token if this is a token range.
1510a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner  if (Range.isTokenRange())
1520a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner    EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
154d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner  return EndOff-StartOff;
155311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner}
156311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner
157fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidisint Rewriter::getRangeSize(SourceRange Range, RewriteOptions opts) const {
158fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis  return getRangeSize(CharSourceRange::getTokenRange(Range), opts);
1590a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner}
1600a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner
1610a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner
1626a12a14a529a79524e17889046c7098b80a73c49Ted Kremenek/// getRewrittenText - Return the rewritten form of the text in the specified
163b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// range.  If the start or end of the range was unrewritable or if they are
1641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// in different buffers, this returns an empty string.
165b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner///
166b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// Note that this method is not particularly efficient.
167b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner///
1686a12a14a529a79524e17889046c7098b80a73c49Ted Kremenekstd::string Rewriter::getRewrittenText(SourceRange Range) const {
169b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  if (!isRewritable(Range.getBegin()) ||
170b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner      !isRewritable(Range.getEnd()))
171b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    return "";
1721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1732b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID StartFileID, EndFileID;
1742b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned StartOff, EndOff;
175b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
176b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  EndOff   = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
1771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
178b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  if (StartFileID != EndFileID)
179b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    return ""; // Start and end in different buffers.
1801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
181b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  // If edits have been made to this buffer, the delta between the range may
182b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  // have changed.
1832b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  std::map<FileID, RewriteBuffer>::const_iterator I =
184b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    RewriteBuffers.find(StartFileID);
185b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  if (I == RewriteBuffers.end()) {
186b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    // If the buffer hasn't been rewritten, just return the text from the input.
187b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    const char *Ptr = SourceMgr->getCharacterData(Range.getBegin());
1881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
189b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    // Adjust the end offset to the end of the last token, instead of being the
190b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    // start of the last token.
1912c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner    EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
192b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner    return std::string(Ptr, Ptr+EndOff-StartOff);
193b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  }
1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
195b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  const RewriteBuffer &RB = I->second;
196b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  EndOff = RB.getMappedOffset(EndOff, true);
197b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  StartOff = RB.getMappedOffset(StartOff);
1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
199b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  // Adjust the end offset to the end of the last token, instead of being the
200b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  // start of the last token.
2012c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner  EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts);
202b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner
203b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  // Advance the iterators to the right spot, yay for linear time algorithms.
204b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  RewriteBuffer::iterator Start = RB.begin();
205b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  std::advance(Start, StartOff);
206b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  RewriteBuffer::iterator End = Start;
207b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  std::advance(End, EndOff-StartOff);
2081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
209b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner  return std::string(Start, End);
210b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner}
211311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner
2127c239606f3a7a685653a0a7e64459c3f43522666Chris Lattnerunsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
2132b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner                                              FileID &FID) const {
21454bd7cb491cce1fb55ce1baac40cf7002a317166Chris Lattner  assert(Loc.isValid() && "Invalid location");
215de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc);
2162b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FID = V.first;
2177c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  return V.second;
2187c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner}
2197c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner
2207c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner
2218a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
2228a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner///
2232b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerRewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
2242b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  std::map<FileID, RewriteBuffer>::iterator I =
2252b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner    RewriteBuffers.lower_bound(FID);
2261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (I != RewriteBuffers.end() && I->first == FID)
2278a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner    return I->second;
2282b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
2291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef MB = SourceMgr->getBufferData(FID);
231f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer  I->second.Initialize(MB.begin(), MB.end());
2321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2338a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner  return I->second;
2348a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner}
2358a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
23654a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner/// InsertText - Insert the specified string at the specified location in the
237aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner/// original buffer.
2385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool Rewriter::InsertText(SourceLocation Loc, StringRef Str,
239f85e193739c953358c865005855253af4f68a497John McCall                          bool InsertAfter, bool indentNewLines) {
240dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner  if (!isRewritable(Loc)) return true;
2412b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID FID;
2422b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
243f85e193739c953358c865005855253af4f68a497John McCall
244f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith  SmallString<128> indentedStr;
245f85e193739c953358c865005855253af4f68a497John McCall  if (indentNewLines && Str.find('\n') != StringRef::npos) {
246f85e193739c953358c865005855253af4f68a497John McCall    StringRef MB = SourceMgr->getBufferData(FID);
247f85e193739c953358c865005855253af4f68a497John McCall
248f85e193739c953358c865005855253af4f68a497John McCall    unsigned lineNo = SourceMgr->getLineNumber(FID, StartOffs) - 1;
249f85e193739c953358c865005855253af4f68a497John McCall    const SrcMgr::ContentCache *
250f85e193739c953358c865005855253af4f68a497John McCall        Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
251f85e193739c953358c865005855253af4f68a497John McCall    unsigned lineOffs = Content->SourceLineCache[lineNo];
252f85e193739c953358c865005855253af4f68a497John McCall
253f85e193739c953358c865005855253af4f68a497John McCall    // Find the whitespace at the start of the line.
254f85e193739c953358c865005855253af4f68a497John McCall    StringRef indentSpace;
255f85e193739c953358c865005855253af4f68a497John McCall    {
256f85e193739c953358c865005855253af4f68a497John McCall      unsigned i = lineOffs;
257f85e193739c953358c865005855253af4f68a497John McCall      while (isWhitespace(MB[i]))
258f85e193739c953358c865005855253af4f68a497John McCall        ++i;
259f85e193739c953358c865005855253af4f68a497John McCall      indentSpace = MB.substr(lineOffs, i-lineOffs);
260f85e193739c953358c865005855253af4f68a497John McCall    }
261f85e193739c953358c865005855253af4f68a497John McCall
2625f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    SmallVector<StringRef, 4> lines;
263f85e193739c953358c865005855253af4f68a497John McCall    Str.split(lines, "\n");
264f85e193739c953358c865005855253af4f68a497John McCall
265f85e193739c953358c865005855253af4f68a497John McCall    for (unsigned i = 0, e = lines.size(); i != e; ++i) {
266f85e193739c953358c865005855253af4f68a497John McCall      indentedStr += lines[i];
267f85e193739c953358c865005855253af4f68a497John McCall      if (i < e-1) {
268f85e193739c953358c865005855253af4f68a497John McCall        indentedStr += '\n';
269f85e193739c953358c865005855253af4f68a497John McCall        indentedStr += indentSpace;
270f85e193739c953358c865005855253af4f68a497John McCall      }
271f85e193739c953358c865005855253af4f68a497John McCall    }
272f85e193739c953358c865005855253af4f68a497John McCall    Str = indentedStr.str();
273f85e193739c953358c865005855253af4f68a497John McCall  }
274f85e193739c953358c865005855253af4f68a497John McCall
275d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter);
276dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner  return false;
27754a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner}
27854a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner
2795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool Rewriter::InsertTextAfterToken(SourceLocation Loc, StringRef Str) {
280b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  if (!isRewritable(Loc)) return true;
281b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  FileID FID;
282b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
283fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis  RewriteOptions rangeOpts;
284fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis  rangeOpts.IncludeInsertsAtBeginOfRange = false;
285fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis  StartOffs += getRangeSize(SourceRange(Loc, Loc), rangeOpts);
286b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  getEditBuffer(FID).InsertText(StartOffs, Str, /*InsertAfter*/true);
287b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  return false;
288b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis}
289b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
290aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner/// RemoveText - Remove the specified text region.
291b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisbool Rewriter::RemoveText(SourceLocation Start, unsigned Length,
292fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis                          RewriteOptions opts) {
293aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner  if (!isRewritable(Start)) return true;
2942b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID FID;
2952b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
296fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis  getEditBuffer(FID).RemoveText(StartOffs, Length, opts.RemoveLineIfEmpty);
297aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner  return false;
298674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner}
2998a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner
300674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// ReplaceText - This method replaces a range of characters in the input
301674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// buffer with a new string.  This is effectively a combined "remove/insert"
302674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// operation.
303aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattnerbool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
3045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                           StringRef NewStr) {
305aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner  if (!isRewritable(Start)) return true;
3062b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  FileID StartFileID;
3077c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner  unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
309d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr);
310aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner  return false;
3118a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner}
31201c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner
313b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisbool Rewriter::ReplaceText(SourceRange range, SourceRange replacementRange) {
314b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  if (!isRewritable(range.getBegin())) return true;
315b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  if (!isRewritable(range.getEnd())) return true;
316b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  if (replacementRange.isInvalid()) return true;
317b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  SourceLocation start = range.getBegin();
318b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  unsigned origLength = getRangeSize(range);
319b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  unsigned newLength = getRangeSize(replacementRange);
320b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  FileID FID;
321b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  unsigned newOffs = getLocationOffsetAndFileID(replacementRange.getBegin(),
322b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis                                                FID);
3235f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef MB = SourceMgr->getBufferData(FID);
324b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis  return ReplaceText(start, origLength, MB.substr(newOffs, newLength));
325b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis}
326b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis
32701c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty
32801c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// printer to generate the replacement code.  This returns true if the input
32901c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// could not be rewritten, or false if successful.
33088906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanianbool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) {
33101c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner  // Measaure the old text.
33288906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian  int Size = getRangeSize(From->getSourceRange());
33301c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner  if (Size == -1)
33401c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner    return true;
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33601c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner  // Get the new text.
337a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek  std::string SStr;
338a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek  llvm::raw_string_ostream S(SStr);
339e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner  To->printPretty(S, 0, PrintingPolicy(*LangOpts));
34001c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner  const std::string &Str = S.str();
34101c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner
342d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar  ReplaceText(From->getLocStart(), Size, Str);
34301c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner  return false;
34401c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner}
3451d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian
3461d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanianstd::string Rewriter::ConvertToString(Stmt *From) {
3471d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian  std::string SStr;
3481d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian  llvm::raw_string_ostream S(SStr);
3491d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian  From->printPretty(S, 0, PrintingPolicy(*LangOpts));
35085b1c7ce94904873b1c0b7d08a6bce885d8eb245Fariborz Jahanian  return S.str();
3511d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian}
35210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
35310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidisbool Rewriter::IncreaseIndentation(CharSourceRange range,
35410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis                                   SourceLocation parentIndent) {
355f85e193739c953358c865005855253af4f68a497John McCall  if (range.isInvalid()) return true;
35610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (!isRewritable(range.getBegin())) return true;
35710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (!isRewritable(range.getEnd())) return true;
35810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (!isRewritable(parentIndent)) return true;
35910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
36010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  FileID StartFileID, EndFileID, parentFileID;
36110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned StartOff, EndOff, parentOff;
36210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
36310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID);
36410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  EndOff   = getLocationOffsetAndFileID(range.getEnd(), EndFileID);
36510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID);
36610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
36710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (StartFileID != EndFileID || StartFileID != parentFileID)
36810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    return true;
369f85e193739c953358c865005855253af4f68a497John McCall  if (StartOff > EndOff)
37010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    return true;
37110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
37210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  FileID FID = StartFileID;
37310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  StringRef MB = SourceMgr->getBufferData(FID);
37410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
37510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1;
37610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1;
37710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1;
37810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
37910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  const SrcMgr::ContentCache *
38010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis      Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache();
38110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
382f85e193739c953358c865005855253af4f68a497John McCall  // Find where the lines start.
38310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned parentLineOffs = Content->SourceLineCache[parentLineNo];
38410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  unsigned startLineOffs = Content->SourceLineCache[startLineNo];
38510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
38610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  // Find the whitespace at the start of each line.
387f85e193739c953358c865005855253af4f68a497John McCall  StringRef parentSpace, startSpace;
38810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  {
38910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    unsigned i = parentLineOffs;
39010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    while (isWhitespace(MB[i]))
39110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis      ++i;
39210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    parentSpace = MB.substr(parentLineOffs, i-parentLineOffs);
39310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
39410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    i = startLineOffs;
39510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    while (isWhitespace(MB[i]))
39610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis      ++i;
39710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    startSpace = MB.substr(startLineOffs, i-startLineOffs);
39810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  }
39910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (parentSpace.size() >= startSpace.size())
40010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    return true;
40110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  if (!startSpace.startswith(parentSpace))
40210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis    return true;
40310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
4045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  StringRef indent = startSpace.substr(parentSpace.size());
40510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
40610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  // Indent the lines between start/end offsets.
40710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  RewriteBuffer &RB = getEditBuffer(FID);
408f85e193739c953358c865005855253af4f68a497John McCall  for (unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) {
409f85e193739c953358c865005855253af4f68a497John McCall    unsigned offs = Content->SourceLineCache[lineNo];
410f85e193739c953358c865005855253af4f68a497John McCall    unsigned i = offs;
411f85e193739c953358c865005855253af4f68a497John McCall    while (isWhitespace(MB[i]))
412f85e193739c953358c865005855253af4f68a497John McCall      ++i;
413f85e193739c953358c865005855253af4f68a497John McCall    StringRef origIndent = MB.substr(offs, i-offs);
414f85e193739c953358c865005855253af4f68a497John McCall    if (origIndent.startswith(startSpace))
415f85e193739c953358c865005855253af4f68a497John McCall      RB.InsertText(offs, indent, /*InsertAfter=*/false);
41610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  }
41710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis
41810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis  return false;
41910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis}
420bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
421c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramernamespace {
422bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// A wrapper for a file stream that atomically overwrites the target.
423bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek//
424bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// Creates a file output stream for a temporary file in the constructor,
425bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// which is later accessible via getStream() if ok() return true.
426bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// Flushes the stream and moves the temporary file to the target location
427bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// in the destructor.
428bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekclass AtomicallyMovedFile {
429bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekpublic:
430bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  AtomicallyMovedFile(DiagnosticsEngine &Diagnostics, StringRef Filename,
431bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek                      bool &AllWritten)
432bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) {
433bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    TempFilename = Filename;
434bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    TempFilename += "-%%%%%%%%";
435bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    int FD;
43670e7aeccbf5856a84f81366c6c1a0c0c01e70063Rafael Espindola    if (llvm::sys::fs::createUniqueFile(TempFilename.str(), FD, TempFilename)) {
437bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      AllWritten = false;
438bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      Diagnostics.Report(clang::diag::err_unable_to_make_temp)
439bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        << TempFilename;
440bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    } else {
441bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true));
442bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    }
443bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
444bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
445bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  ~AtomicallyMovedFile() {
446bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    if (!ok()) return;
447bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
448bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    FileStream->flush();
4492d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi#ifdef _WIN32
4502d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi    // Win32 does not allow rename/removing opened files.
4512d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi    FileStream.reset();
4522d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi#endif
453bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    if (llvm::error_code ec =
454bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek          llvm::sys::fs::rename(TempFilename.str(), Filename)) {
455bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      AllWritten = false;
456bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      Diagnostics.Report(clang::diag::err_unable_to_rename_temp)
457bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        << TempFilename << Filename << ec.message();
458bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      bool existed;
459bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      // If the remove fails, there's not a lot we can do - this is already an
460bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      // error.
461bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      llvm::sys::fs::remove(TempFilename.str(), existed);
462bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    }
463bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
464bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
4657247c88d1e41514a41085f83ebf03dd5220e054aDavid Blaikie  bool ok() { return FileStream.isValid(); }
466cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko  raw_ostream &getStream() { return *FileStream; }
467bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
468bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekprivate:
469bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  DiagnosticsEngine &Diagnostics;
470bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  StringRef Filename;
471bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  SmallString<128> TempFilename;
472bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  OwningPtr<llvm::raw_fd_ostream> FileStream;
473bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  bool &AllWritten;
474bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek};
475c2b914fb6fed213a7e7d9847e543f1e7f94d852dBenjamin Kramer} // end anonymous namespace
476bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek
477bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekbool Rewriter::overwriteChangedFiles() {
478bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  bool AllWritten = true;
479bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {
480bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    const FileEntry *Entry =
481bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek        getSourceMgr().getFileEntryForID(I->first);
482bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(),
483bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek                             AllWritten);
484bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    if (File.ok()) {
485bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek      I->second.write(File.getStream());
486bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek    }
487bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  }
488bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek  return !AllWritten;
489bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek}
490