clang: lib/Edit/Commit.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

17#include "llvm/ADT/StringRef.h"

18#include

19#include

20

21using namespace clang;

22using namespace edit;

23

28 return Loc;

29}

30

34}

35

37 SourceLocation Loc = SM.getLocForStartOfFile(InsertFromRangeOffs.getFID());

41}

42

44 : SourceMgr(Editor.getSourceManager()), LangOpts(Editor.getLangOpts()),

45 PPRec(Editor.getPPCondDirectiveRecord()),

46 Editor(&Editor) {}

47

49 bool afterToken, bool beforePreviousInsertions) {

50 if (text.empty())

51 return true;

52

54 if ((!afterToken && !canInsert(loc, Offs)) ||

55 ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {

56 IsCommitable = false;

57 return false;

58 }

59

60 addInsert(loc, Offs, text, beforePreviousInsertions);

61 return true;

62}

63

66 bool afterToken, bool beforePreviousInsertions) {

68 unsigned RangeLen;

69 if (!canRemoveRange(range, RangeOffs, RangeLen)) {

70 IsCommitable = false;

71 return false;

72 }

73

75 if ((!afterToken && !canInsert(loc, Offs)) ||

76 ( afterToken && !canInsertAfterToken(loc, Offs, loc))) {

77 IsCommitable = false;

78 return false;

79 }

80

81 if (PPRec &&

83 IsCommitable = false;

84 return false;

85 }

86

87 addInsertFromRange(loc, Offs, RangeOffs, RangeLen, beforePreviousInsertions);

88 return true;

89}

90

93 unsigned Len;

94 if (!canRemoveRange(range, Offs, Len)) {

95 IsCommitable = false;

96 return false;

97 }

98

99 addRemove(range.getBegin(), Offs, Len);

100 return true;

101}

102

104 StringRef after) {

105 bool commitableBefore = insert(range.getBegin(), before, false,

106 true);

107 bool commitableAfter;

108 if (range.isTokenRange())

110 else

111 commitableAfter = insert(range.getEnd(), after);

112

113 return commitableBefore && commitableAfter;

114}

115

117 if (text.empty())

118 return remove(range);

119

121 unsigned Len;

122 if (!canInsert(range.getBegin(), Offs) || !canRemoveRange(range, Offs, Len)) {

123 IsCommitable = false;

124 return false;

125 }

126

127 addRemove(range.getBegin(), Offs, Len);

128 addInsert(range.getBegin(), Offs, text, false);

129 return true;

130}

131

135 unsigned OuterLen;

136 if (!canRemoveRange(range, OuterBegin, OuterLen)) {

137 IsCommitable = false;

138 return false;

139 }

140

142 unsigned InnerLen;

143 if (!canRemoveRange(replacementRange, InnerBegin, InnerLen)) {

144 IsCommitable = false;

145 return false;

146 }

147

150 if (OuterBegin.getFID() != InnerBegin.getFID() ||

151 InnerBegin < OuterBegin ||

152 InnerBegin > OuterEnd ||

153 InnerEnd > OuterEnd) {

154 IsCommitable = false;

155 return false;

156 }

157

158 addRemove(range.getBegin(),

160 addRemove(replacementRange.getEnd(),

162 return true;

163}

164

166 StringRef replacementText) {

167 if (text.empty() || replacementText.empty())

168 return true;

169

171 unsigned Len;

172 if (!canReplaceText(loc, replacementText, Offs, Len)) {

173 IsCommitable = false;

174 return false;

175 }

176

177 addRemove(loc, Offs, Len);

178 addInsert(loc, Offs, text, false);

179 return true;

180}

181

183 bool beforePreviousInsertions) {

184 if (text.empty())

185 return;

186

187 Edit data;

189 data.OrigLoc = OrigLoc;

190 data.Offset = Offs;

191 data.Text = text.copy(StrAlloc);

192 data.BeforePrev = beforePreviousInsertions;

193 CachedEdits.push_back(data);

194}

195

197 FileOffset RangeOffs, unsigned RangeLen,

198 bool beforePreviousInsertions) {

199 if (RangeLen == 0)

200 return;

201

202 Edit data;

204 data.OrigLoc = OrigLoc;

205 data.Offset = Offs;

206 data.InsertFromRangeOffs = RangeOffs;

207 data.Length = RangeLen;

208 data.BeforePrev = beforePreviousInsertions;

209 CachedEdits.push_back(data);

210}

211

214 if (Len == 0)

215 return;

216

217 Edit data;

219 data.OrigLoc = OrigLoc;

220 data.Offset = Offs;

221 data.Length = Len;

222 CachedEdits.push_back(data);

223}

224

227 return false;

228

230 isAtStartOfMacroExpansion(loc, &loc);

231

233 loc = SM.getTopMacroCallerLoc(loc);

234

236 if (!isAtStartOfMacroExpansion(loc, &loc))

237 return false;

238

239 if (SM.isInSystemHeader(loc))

240 return false;

241

242 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);

243 if (locInfo.first.isInvalid())

244 return false;

245 offs = FileOffset(locInfo.first, locInfo.second);

246 return canInsertInOffset(loc, offs);

247}

248

252

253 return false;

254

258

260 isAtEndOfMacroExpansion(loc, &loc);

261

263 loc = SM.getTopMacroCallerLoc(loc);

264

266 if (!isAtEndOfMacroExpansion(loc, &loc))

267 return false;

268

269 if (SM.isInSystemHeader(loc))

270 return false;

271

274 return false;

275

276 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);

277 if (locInfo.first.isInvalid())

278 return false;

279 offs = FileOffset(locInfo.first, locInfo.second);

280 return canInsertInOffset(loc, offs);

281}

282

284 for (const auto &act : CachedEdits)

286 if (act.Offset.getFID() == Offs.getFID() &&

287 Offs > act.Offset && Offs < act.Offset.getWithOffset(act.Length))

288 return false;

289 }

290

291 if (!Editor)

292 return true;

294}

295

300 if (range.isInvalid())

301 return false;

302

303 if (range.getBegin().isMacroID() || range.getEnd().isMacroID())

304 return false;

305 if (SM.isInSystemHeader(range.getBegin()) ||

306 SM.isInSystemHeader(range.getEnd()))

307 return false;

308

310 return false;

311

312 std::pair<FileID, unsigned> beginInfo = SM.getDecomposedLoc(range.getBegin());

313 std::pair<FileID, unsigned> endInfo = SM.getDecomposedLoc(range.getEnd());

314 if (beginInfo.first != endInfo.first ||

315 beginInfo.second > endInfo.second)

316 return false;

317

318 Offs = FileOffset(beginInfo.first, beginInfo.second);

319 Len = endInfo.second - beginInfo.second;

320 return true;

321}

322

323bool Commit::canReplaceText(SourceLocation loc, StringRef text,

325 assert(text.empty());

326

327 if (!canInsert(loc, Offs))

328 return false;

329

330

331 bool invalidTemp = false;

333 if (invalidTemp)

334 return false;

335

336 Len = text.size();

337 return file.substr(Offs.getOffset()).starts_with(text);

338}

339

340bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,

343}

344

345bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,

348}

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::SourceLocation class and associated facilities.

Defines the SourceManager interface.

Represents a character-granular source range.

static CharSourceRange getCharRange(SourceRange R)

SourceLocation getEnd() const

static bool isAtStartOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroBegin=nullptr)

Returns true if the given MacroID location points at the first token of the macro expansion.

static bool isAtEndOfMacroExpansion(SourceLocation loc, const SourceManager &SM, const LangOptions &LangOpts, SourceLocation *MacroEnd=nullptr)

Returns true if the given MacroID location points at the last token of the macro expansion.

static CharSourceRange makeFileCharRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)

Accepts a range and returns a character range with file locations.

static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)

MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...

static SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset, const SourceManager &SM, const LangOptions &LangOpts)

Computes the source location just past the end of the token at this source location.

bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, SourceLocation RHS) const

Returns true if the given locations are in different regions, separated by conditional directive bloc...

bool rangeIntersectsConditionalDirective(SourceRange Range) const

Returns true if the given range intersects with a conditional directive.

Encodes a location in the source.

SourceLocation getLocWithOffset(IntTy Offset) const

Return a source location with the specified offset from this SourceLocation.

This class handles loading and caching of source files into memory.

StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const

Return a StringRef to the source buffer data for the specified FileID.

SourceLocation getSpellingLoc(SourceLocation Loc) const

Given a SourceLocation object, return the spelling location referenced by the ID.

bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange)

bool insertWrap(StringRef before, CharSourceRange range, StringRef after)

bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken=false, bool beforePreviousInsertions=false)

bool insert(SourceLocation loc, StringRef text, bool afterToken=false, bool beforePreviousInsertions=false)

Commit(EditedSource &Editor)

bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions=false)

bool remove(CharSourceRange range)

bool replace(CharSourceRange range, StringRef text)

bool replaceText(SourceLocation loc, StringRef text, StringRef replacementText)

bool canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs)

FileOffset getWithOffset(unsigned offset) const

unsigned getOffset() const

RangeSelector range(RangeSelector Begin, RangeSelector End)

DEPRECATED. Use enclose.

EditGenerator edit(ASTEdit E)

Generates a single (specified) edit.

The JSON file list parser is used to communicate input to InstallAPI.

SourceLocation getFileLocation(SourceManager &SM) const

CharSourceRange getFileRange(SourceManager &SM) const

CharSourceRange getInsertFromRange(SourceManager &SM) const