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" 1601c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner#include "clang/AST/Stmt.h" 172c3352b5d1f5f4546af2f3051a304d84d57c697eTed Kremenek#include "clang/AST/Decl.h" 18bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/DiagnosticIDs.h" 19bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Basic/FileManager.h" 208a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Basic/SourceManager.h" 21bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "clang/Lex/Lexer.h" 228fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer#include "llvm/ADT/SmallString.h" 23bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek#include "llvm/Support/FileSystem.h" 248bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattnerusing namespace clang; 258bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner 265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerraw_ostream &RewriteBuffer::write(raw_ostream &os) const { 270ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky // FIXME: eliminate the copy by writing out each chunk at a time 280ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky os << std::string(begin(), end()); 290ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky return os; 300ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky} 310ade808e0ac411baa2dbc1f76ad352b9b6d6d3f8Nick Lewycky 32b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis/// \brief Return true if this character is non-new-line whitespace: 338c10f841040b1e2951d06d385c8eefbcbe578fcfJames Dennett/// ' ', '\\t', '\\f', '\\v', '\\r'. 34b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisstatic inline bool isWhitespace(unsigned char c) { 35b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis switch (c) { 36b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis case ' ': 37b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis case '\t': 38b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis case '\f': 39b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis case '\v': 40b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis case '\r': 41b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis return true; 42b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis default: 43b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis return false; 44b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 45b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis} 46b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 47b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisvoid RewriteBuffer::RemoveText(unsigned OrigOffset, unsigned Size, 48b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis bool removeLineIfEmpty) { 497c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner // Nothing to remove, exit early. 507c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner if (Size == 0) return; 517c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner 527c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner unsigned RealOffset = getMappedOffset(OrigOffset, true); 537c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner assert(RealOffset+Size < Buffer.size() && "Invalid location"); 541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 557c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner // Remove the dead characters. 56febe719596ee68605944da5f2e03258e18e6df8cChris Lattner Buffer.erase(RealOffset, Size); 577c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner 587c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner // Add a delta so that future changes are offset correctly. 59a0978c24829dfd552d38fc3bae2b86e18bb90d49Eli Friedman AddReplaceDelta(OrigOffset, -Size); 60b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 61b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (removeLineIfEmpty) { 62b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis // Find the line that the remove occurred and if it is completely empty 63b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis // remove the line as well. 64b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 65b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis iterator curLineStart = begin(); 66b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned curLineStartOffs = 0; 67b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis iterator posI = begin(); 68b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis for (unsigned i = 0; i != RealOffset; ++i) { 69b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (*posI == '\n') { 70b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis curLineStart = posI; 71b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis ++curLineStart; 72b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis curLineStartOffs = i + 1; 73b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 74b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis ++posI; 75b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 76b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 77b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned lineSize = 0; 78b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis posI = curLineStart; 79b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis while (posI != end() && isWhitespace(*posI)) { 80b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis ++posI; 81b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis ++lineSize; 82b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 83b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (posI != end() && *posI == '\n') { 84b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis Buffer.erase(curLineStartOffs, lineSize + 1/* + '\n'*/); 85b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis AddReplaceDelta(curLineStartOffs, -(lineSize + 1/* + '\n'*/)); 86b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 87b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis } 888bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner} 898bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner 905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid RewriteBuffer::InsertText(unsigned OrigOffset, StringRef Str, 91886c8db545170850f7806f47b5f6120864effd09Ted Kremenek bool InsertAfter) { 921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9303b071043593590b01fdf61df3e29c0ae7c067d3Chris Lattner // Nothing to insert, exit early. 94d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (Str.empty()) return; 95febe719596ee68605944da5f2e03258e18e6df8cChris Lattner 96886c8db545170850f7806f47b5f6120864effd09Ted Kremenek unsigned RealOffset = getMappedOffset(OrigOffset, InsertAfter); 97d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar Buffer.insert(RealOffset, Str.begin(), Str.end()); 981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9903b071043593590b01fdf61df3e29c0ae7c067d3Chris Lattner // Add a delta so that future changes are offset correctly. 100d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar AddInsertDelta(OrigOffset, Str.size()); 1018bd12b848bc353a9d34b54144c3dd3407b064292Chris Lattner} 1028a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 1037c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner/// ReplaceText - This method replaces a range of characters in the input 104febe719596ee68605944da5f2e03258e18e6df8cChris Lattner/// buffer with a new string. This is effectively a combined "remove+insert" 1057c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner/// operation. 1067c239606f3a7a685653a0a7e64459c3f43522666Chris Lattnervoid RewriteBuffer::ReplaceText(unsigned OrigOffset, unsigned OrigLength, 1075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef NewStr) { 108a0978c24829dfd552d38fc3bae2b86e18bb90d49Eli Friedman unsigned RealOffset = getMappedOffset(OrigOffset, true); 109febe719596ee68605944da5f2e03258e18e6df8cChris Lattner Buffer.erase(RealOffset, OrigLength); 110d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar Buffer.insert(RealOffset, NewStr.begin(), NewStr.end()); 111d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (OrigLength != NewStr.size()) 112d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar AddReplaceDelta(OrigOffset, NewStr.size() - OrigLength); 1137c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner} 1148a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 1158a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 1168a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner//===----------------------------------------------------------------------===// 1178a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner// Rewriter class 1188a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner//===----------------------------------------------------------------------===// 1198a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 120311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner/// getRangeSize - Return the size in bytes of the specified range if they 121311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner/// are in the same file. If not, this returns -1. 122b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisint Rewriter::getRangeSize(const CharSourceRange &Range, 123fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis RewriteOptions opts) const { 124311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner if (!isRewritable(Range.getBegin()) || 125311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner !isRewritable(Range.getEnd())) return -1; 1261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1272b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID StartFileID, EndFileID; 1282b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner unsigned StartOff, EndOff; 1291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 130311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID); 131311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID); 1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 133311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner if (StartFileID != EndFileID) 134311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner return -1; 1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 136d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner // If edits have been made to this buffer, the delta between the range may 137d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner // have changed. 1382b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::map<FileID, RewriteBuffer>::const_iterator I = 139075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner RewriteBuffers.find(StartFileID); 140d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner if (I != RewriteBuffers.end()) { 141075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner const RewriteBuffer &RB = I->second; 142fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis EndOff = RB.getMappedOffset(EndOff, opts.IncludeInsertsAtEndOfRange); 143fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis StartOff = RB.getMappedOffset(StartOff, !opts.IncludeInsertsAtBeginOfRange); 144075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner } 145075eb6eae0506e041e0086ddcab31ba2e55f0472Chris Lattner 1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1479d62a5b31ec3762f416cc9ef89d1b7b433d13ac5Chris Lattner // Adjust the end offset to the end of the last token, instead of being the 1480a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner // start of the last token if this is a token range. 1490a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner if (Range.isTokenRange()) 1500a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts); 1511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 152d6690b20b3340f30a225dffa49603951dcd75e4eChris Lattner return EndOff-StartOff; 153311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner} 154311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 155fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidisint Rewriter::getRangeSize(SourceRange Range, RewriteOptions opts) const { 156fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis return getRangeSize(CharSourceRange::getTokenRange(Range), opts); 1570a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner} 1580a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner 1590a76aae8c03cb7dd7bdbe683485560afaf695959Chris Lattner 1606a12a14a529a79524e17889046c7098b80a73c49Ted Kremenek/// getRewrittenText - Return the rewritten form of the text in the specified 161b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// range. If the start or end of the range was unrewritable or if they are 1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// in different buffers, this returns an empty string. 163b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// 164b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// Note that this method is not particularly efficient. 165b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner/// 1666a12a14a529a79524e17889046c7098b80a73c49Ted Kremenekstd::string Rewriter::getRewrittenText(SourceRange Range) const { 167b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner if (!isRewritable(Range.getBegin()) || 168b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner !isRewritable(Range.getEnd())) 169b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner return ""; 1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1712b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID StartFileID, EndFileID; 1722b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner unsigned StartOff, EndOff; 173b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID); 174b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID); 1751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 176b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner if (StartFileID != EndFileID) 177b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner return ""; // Start and end in different buffers. 1781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 179b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // If edits have been made to this buffer, the delta between the range may 180b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // have changed. 1812b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::map<FileID, RewriteBuffer>::const_iterator I = 182b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner RewriteBuffers.find(StartFileID); 183b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner if (I == RewriteBuffers.end()) { 184b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // If the buffer hasn't been rewritten, just return the text from the input. 185b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner const char *Ptr = SourceMgr->getCharacterData(Range.getBegin()); 1861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 187b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // Adjust the end offset to the end of the last token, instead of being the 188b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // start of the last token. 1892c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts); 190b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner return std::string(Ptr, Ptr+EndOff-StartOff); 191b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner } 1921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 193b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner const RewriteBuffer &RB = I->second; 194b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner EndOff = RB.getMappedOffset(EndOff, true); 195b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner StartOff = RB.getMappedOffset(StartOff); 1961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 197b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // Adjust the end offset to the end of the last token, instead of being the 198b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // start of the last token. 1992c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner EndOff += Lexer::MeasureTokenLength(Range.getEnd(), *SourceMgr, *LangOpts); 200b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner 201b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner // Advance the iterators to the right spot, yay for linear time algorithms. 202b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner RewriteBuffer::iterator Start = RB.begin(); 203b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner std::advance(Start, StartOff); 204b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner RewriteBuffer::iterator End = Start; 205b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner std::advance(End, EndOff-StartOff); 2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 207b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner return std::string(Start, End); 208b5cd09a2bf1509167a2e7a46bdd0316812a93335Chris Lattner} 209311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 2107c239606f3a7a685653a0a7e64459c3f43522666Chris Lattnerunsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc, 2112b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID &FID) const { 21254bd7cb491cce1fb55ce1baac40cf7002a317166Chris Lattner assert(Loc.isValid() && "Invalid location"); 213de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner std::pair<FileID,unsigned> V = SourceMgr->getDecomposedLoc(Loc); 2142b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FID = V.first; 2157c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner return V.second; 2167c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner} 2177c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner 2187c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner 2198a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID. 2208a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner/// 2212b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerRewriteBuffer &Rewriter::getEditBuffer(FileID FID) { 2222b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner std::map<FileID, RewriteBuffer>::iterator I = 2232b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner RewriteBuffers.lower_bound(FID); 2241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (I != RewriteBuffers.end() && I->first == FID) 2258a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner return I->second; 2262b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer())); 2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef MB = SourceMgr->getBufferData(FID); 229f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer I->second.Initialize(MB.begin(), MB.end()); 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2318a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner return I->second; 2328a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 2338a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 23454a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner/// InsertText - Insert the specified string at the specified location in the 235aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner/// original buffer. 2365f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool Rewriter::InsertText(SourceLocation Loc, StringRef Str, 237f85e193739c953358c865005855253af4f68a497John McCall bool InsertAfter, bool indentNewLines) { 238dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner if (!isRewritable(Loc)) return true; 2392b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID; 2402b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID); 241f85e193739c953358c865005855253af4f68a497John McCall 242f7ccbad5d9949e7ddd1cbef43d482553b811e026Dylan Noblesmith SmallString<128> indentedStr; 243f85e193739c953358c865005855253af4f68a497John McCall if (indentNewLines && Str.find('\n') != StringRef::npos) { 244f85e193739c953358c865005855253af4f68a497John McCall StringRef MB = SourceMgr->getBufferData(FID); 245f85e193739c953358c865005855253af4f68a497John McCall 246f85e193739c953358c865005855253af4f68a497John McCall unsigned lineNo = SourceMgr->getLineNumber(FID, StartOffs) - 1; 247f85e193739c953358c865005855253af4f68a497John McCall const SrcMgr::ContentCache * 248f85e193739c953358c865005855253af4f68a497John McCall Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache(); 249f85e193739c953358c865005855253af4f68a497John McCall unsigned lineOffs = Content->SourceLineCache[lineNo]; 250f85e193739c953358c865005855253af4f68a497John McCall 251f85e193739c953358c865005855253af4f68a497John McCall // Find the whitespace at the start of the line. 252f85e193739c953358c865005855253af4f68a497John McCall StringRef indentSpace; 253f85e193739c953358c865005855253af4f68a497John McCall { 254f85e193739c953358c865005855253af4f68a497John McCall unsigned i = lineOffs; 255f85e193739c953358c865005855253af4f68a497John McCall while (isWhitespace(MB[i])) 256f85e193739c953358c865005855253af4f68a497John McCall ++i; 257f85e193739c953358c865005855253af4f68a497John McCall indentSpace = MB.substr(lineOffs, i-lineOffs); 258f85e193739c953358c865005855253af4f68a497John McCall } 259f85e193739c953358c865005855253af4f68a497John McCall 2605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<StringRef, 4> lines; 261f85e193739c953358c865005855253af4f68a497John McCall Str.split(lines, "\n"); 262f85e193739c953358c865005855253af4f68a497John McCall 263f85e193739c953358c865005855253af4f68a497John McCall for (unsigned i = 0, e = lines.size(); i != e; ++i) { 264f85e193739c953358c865005855253af4f68a497John McCall indentedStr += lines[i]; 265f85e193739c953358c865005855253af4f68a497John McCall if (i < e-1) { 266f85e193739c953358c865005855253af4f68a497John McCall indentedStr += '\n'; 267f85e193739c953358c865005855253af4f68a497John McCall indentedStr += indentSpace; 268f85e193739c953358c865005855253af4f68a497John McCall } 269f85e193739c953358c865005855253af4f68a497John McCall } 270f85e193739c953358c865005855253af4f68a497John McCall Str = indentedStr.str(); 271f85e193739c953358c865005855253af4f68a497John McCall } 272f85e193739c953358c865005855253af4f68a497John McCall 273d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar getEditBuffer(FID).InsertText(StartOffs, Str, InsertAfter); 274dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner return false; 27554a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner} 27654a2f071a37ee63d3ef1d4e7ca2570542ee12115Chris Lattner 2775f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerbool Rewriter::InsertTextAfterToken(SourceLocation Loc, StringRef Str) { 278b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (!isRewritable(Loc)) return true; 279b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis FileID FID; 280b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID); 281fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis RewriteOptions rangeOpts; 282fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis rangeOpts.IncludeInsertsAtBeginOfRange = false; 283fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis StartOffs += getRangeSize(SourceRange(Loc, Loc), rangeOpts); 284b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis getEditBuffer(FID).InsertText(StartOffs, Str, /*InsertAfter*/true); 285b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis return false; 286b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis} 287b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 288aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner/// RemoveText - Remove the specified text region. 289b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisbool Rewriter::RemoveText(SourceLocation Start, unsigned Length, 290fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis RewriteOptions opts) { 291aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner if (!isRewritable(Start)) return true; 2922b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID FID; 2932b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner unsigned StartOffs = getLocationOffsetAndFileID(Start, FID); 294fd183ba0b16718ff05e161bc479678e447df4999Argyrios Kyrtzidis getEditBuffer(FID).RemoveText(StartOffs, Length, opts.RemoveLineIfEmpty); 295aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return false; 296674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner} 2978a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 298674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// ReplaceText - This method replaces a range of characters in the input 299674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// buffer with a new string. This is effectively a combined "remove/insert" 300674af9541256dc3ef803e3723027a8b028f1f7a2Chris Lattner/// operation. 301aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattnerbool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength, 3025f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef NewStr) { 303aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner if (!isRewritable(Start)) return true; 3042b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID StartFileID; 3057c239606f3a7a685653a0a7e64459c3f43522666Chris Lattner unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID); 3061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 307d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength, NewStr); 308aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return false; 3098a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 31001c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner 311b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidisbool Rewriter::ReplaceText(SourceRange range, SourceRange replacementRange) { 312b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (!isRewritable(range.getBegin())) return true; 313b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (!isRewritable(range.getEnd())) return true; 314b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis if (replacementRange.isInvalid()) return true; 315b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis SourceLocation start = range.getBegin(); 316b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned origLength = getRangeSize(range); 317b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned newLength = getRangeSize(replacementRange); 318b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis FileID FID; 319b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis unsigned newOffs = getLocationOffsetAndFileID(replacementRange.getBegin(), 320b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis FID); 3215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef MB = SourceMgr->getBufferData(FID); 322b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis return ReplaceText(start, origLength, MB.substr(newOffs, newLength)); 323b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis} 324b65ed34ebf0380c001756eea7a1c1d01e110b557Argyrios Kyrtzidis 32501c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty 32601c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// printer to generate the replacement code. This returns true if the input 32701c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner/// could not be rewritten, or false if successful. 32888906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanianbool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) { 32901c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner // Measaure the old text. 33088906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian int Size = getRangeSize(From->getSourceRange()); 33101c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner if (Size == -1) 33201c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner return true; 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33401c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner // Get the new text. 335a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string SStr; 336a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream S(SStr); 337e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner To->printPretty(S, 0, PrintingPolicy(*LangOpts)); 33801c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner const std::string &Str = S.str(); 33901c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner 340d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar ReplaceText(From->getLocStart(), Size, Str); 34101c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner return false; 34201c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner} 3431d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian 3441d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanianstd::string Rewriter::ConvertToString(Stmt *From) { 3451d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian std::string SStr; 3461d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian llvm::raw_string_ostream S(SStr); 3471d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian From->printPretty(S, 0, PrintingPolicy(*LangOpts)); 34885b1c7ce94904873b1c0b7d08a6bce885d8eb245Fariborz Jahanian return S.str(); 3491d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian} 35010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 35110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidisbool Rewriter::IncreaseIndentation(CharSourceRange range, 35210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis SourceLocation parentIndent) { 353f85e193739c953358c865005855253af4f68a497John McCall if (range.isInvalid()) return true; 35410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (!isRewritable(range.getBegin())) return true; 35510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (!isRewritable(range.getEnd())) return true; 35610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (!isRewritable(parentIndent)) return true; 35710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 35810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis FileID StartFileID, EndFileID, parentFileID; 35910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned StartOff, EndOff, parentOff; 36010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 36110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis StartOff = getLocationOffsetAndFileID(range.getBegin(), StartFileID); 36210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis EndOff = getLocationOffsetAndFileID(range.getEnd(), EndFileID); 36310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis parentOff = getLocationOffsetAndFileID(parentIndent, parentFileID); 36410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 36510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (StartFileID != EndFileID || StartFileID != parentFileID) 36610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis return true; 367f85e193739c953358c865005855253af4f68a497John McCall if (StartOff > EndOff) 36810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis return true; 36910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 37010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis FileID FID = StartFileID; 37110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis StringRef MB = SourceMgr->getBufferData(FID); 37210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 37310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned parentLineNo = SourceMgr->getLineNumber(FID, parentOff) - 1; 37410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned startLineNo = SourceMgr->getLineNumber(FID, StartOff) - 1; 37510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned endLineNo = SourceMgr->getLineNumber(FID, EndOff) - 1; 37610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 37710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis const SrcMgr::ContentCache * 37810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis Content = SourceMgr->getSLocEntry(FID).getFile().getContentCache(); 37910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 380f85e193739c953358c865005855253af4f68a497John McCall // Find where the lines start. 38110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned parentLineOffs = Content->SourceLineCache[parentLineNo]; 38210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned startLineOffs = Content->SourceLineCache[startLineNo]; 38310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 38410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis // Find the whitespace at the start of each line. 385f85e193739c953358c865005855253af4f68a497John McCall StringRef parentSpace, startSpace; 38610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis { 38710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis unsigned i = parentLineOffs; 38810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis while (isWhitespace(MB[i])) 38910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis ++i; 39010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis parentSpace = MB.substr(parentLineOffs, i-parentLineOffs); 39110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 39210c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis i = startLineOffs; 39310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis while (isWhitespace(MB[i])) 39410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis ++i; 39510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis startSpace = MB.substr(startLineOffs, i-startLineOffs); 39610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis } 39710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (parentSpace.size() >= startSpace.size()) 39810c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis return true; 39910c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis if (!startSpace.startswith(parentSpace)) 40010c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis return true; 40110c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 4025f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef indent = startSpace.substr(parentSpace.size()); 40310c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 40410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis // Indent the lines between start/end offsets. 40510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis RewriteBuffer &RB = getEditBuffer(FID); 406f85e193739c953358c865005855253af4f68a497John McCall for (unsigned lineNo = startLineNo; lineNo <= endLineNo; ++lineNo) { 407f85e193739c953358c865005855253af4f68a497John McCall unsigned offs = Content->SourceLineCache[lineNo]; 408f85e193739c953358c865005855253af4f68a497John McCall unsigned i = offs; 409f85e193739c953358c865005855253af4f68a497John McCall while (isWhitespace(MB[i])) 410f85e193739c953358c865005855253af4f68a497John McCall ++i; 411f85e193739c953358c865005855253af4f68a497John McCall StringRef origIndent = MB.substr(offs, i-offs); 412f85e193739c953358c865005855253af4f68a497John McCall if (origIndent.startswith(startSpace)) 413f85e193739c953358c865005855253af4f68a497John McCall RB.InsertText(offs, indent, /*InsertAfter=*/false); 41410c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis } 41510c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis 41610c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis return false; 41710c8d9e63bcc96d55f788e7c08b72ce626c8aeecArgyrios Kyrtzidis} 418bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 419bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// A wrapper for a file stream that atomically overwrites the target. 420bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// 421bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// Creates a file output stream for a temporary file in the constructor, 422bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// which is later accessible via getStream() if ok() return true. 423bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// Flushes the stream and moves the temporary file to the target location 424bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek// in the destructor. 425bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekclass AtomicallyMovedFile { 426bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekpublic: 427bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek AtomicallyMovedFile(DiagnosticsEngine &Diagnostics, StringRef Filename, 428bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek bool &AllWritten) 429bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek : Diagnostics(Diagnostics), Filename(Filename), AllWritten(AllWritten) { 430bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek TempFilename = Filename; 431bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek TempFilename += "-%%%%%%%%"; 432bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek int FD; 433bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek if (llvm::sys::fs::unique_file(TempFilename.str(), FD, TempFilename, 434bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek /*makeAbsolute=*/true, 0664)) { 435bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek AllWritten = false; 436bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Diagnostics.Report(clang::diag::err_unable_to_make_temp) 437bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek << TempFilename; 438bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } else { 439bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileStream.reset(new llvm::raw_fd_ostream(FD, /*shouldClose=*/true)); 440bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 441bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 442bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 443bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek ~AtomicallyMovedFile() { 444bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek if (!ok()) return; 445bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 446bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek FileStream->flush(); 4472d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi#ifdef _WIN32 4482d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi // Win32 does not allow rename/removing opened files. 4492d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi FileStream.reset(); 4502d9c4dfad1f58c42a31721054cd99218d9ac3d52NAKAMURA Takumi#endif 451bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek if (llvm::error_code ec = 452bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::sys::fs::rename(TempFilename.str(), Filename)) { 453bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek AllWritten = false; 454bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek Diagnostics.Report(clang::diag::err_unable_to_rename_temp) 455bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek << TempFilename << Filename << ec.message(); 456bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek bool existed; 457bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // If the remove fails, there's not a lot we can do - this is already an 458bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek // error. 459bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::sys::fs::remove(TempFilename.str(), existed); 460bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 461bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 462bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 463bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek bool ok() { return FileStream; } 464bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek llvm::raw_ostream &getStream() { return *FileStream; } 465bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 466bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekprivate: 467bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek DiagnosticsEngine &Diagnostics; 468bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek StringRef Filename; 469bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek SmallString<128> TempFilename; 470bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek OwningPtr<llvm::raw_fd_ostream> FileStream; 471bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek bool &AllWritten; 472bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek}; 473bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek 474bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimekbool Rewriter::overwriteChangedFiles() { 475bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek bool AllWritten = true; 476bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek for (buffer_iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) { 477bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek const FileEntry *Entry = 478bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek getSourceMgr().getFileEntryForID(I->first); 479bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek AtomicallyMovedFile File(getSourceMgr().getDiagnostics(), Entry->getName(), 480bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek AllWritten); 481bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek if (File.ok()) { 482bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek I->second.write(File.getStream()); 483bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 484bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek } 485bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek return !AllWritten; 486bfbfee51ec8f20f3f1b9f8329705d816b67438e7Manuel Klimek} 487