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

20using namespace clang;

21using namespace edit;

22

29

34

41

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

44 PPRec(Editor.getPPCondDirectiveRecord()),

45 Editor(&Editor) {}

46

48 bool afterToken, bool beforePreviousInsertions) {

49 if (text.empty())

50 return true;

51

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

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

55 IsCommitable = false;

56 return false;

57 }

58

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

60 return true;

61}

62

65 bool afterToken, bool beforePreviousInsertions) {

67 unsigned RangeLen;

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

69 IsCommitable = false;

70 return false;

71 }

72

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

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

76 IsCommitable = false;

77 return false;

78 }

79

80 if (PPRec &&

81 PPRec->areInDifferentConditionalDirectiveRegion(loc, range.getBegin())) {

82 IsCommitable = false;

83 return false;

84 }

85

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

87 return true;

88}

89

92 unsigned Len;

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

94 IsCommitable = false;

95 return false;

96 }

97

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

99 return true;

100}

101

103 StringRef after) {

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

105 true);

106 bool commitableAfter;

107 if (range.isTokenRange())

109 else

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

111

112 return commitableBefore && commitableAfter;

113}

114

116 if (text.empty())

117 return remove(range);

118

120 unsigned Len;

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

122 IsCommitable = false;

123 return false;

124 }

125

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

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

128 return true;

129}

130

134 unsigned OuterLen;

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

136 IsCommitable = false;

137 return false;

138 }

139

141 unsigned InnerLen;

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

143 IsCommitable = false;

144 return false;

145 }

146

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

150 InnerBegin < OuterBegin ||

151 InnerBegin > OuterEnd ||

152 InnerEnd > OuterEnd) {

153 IsCommitable = false;

154 return false;

155 }

156

157 addRemove(range.getBegin(),

159 addRemove(replacementRange.getEnd(),

161 return true;

162}

163

165 StringRef replacementText) {

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

167 return true;

168

170 unsigned Len;

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

172 IsCommitable = false;

173 return false;

174 }

175

176 addRemove(loc, Offs, Len);

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

178 return true;

179}

180

182 bool beforePreviousInsertions) {

183 if (text.empty())

184 return;

185

186 Edit data;

188 data.OrigLoc = OrigLoc;

189 data.Offset = Offs;

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

191 data.BeforePrev = beforePreviousInsertions;

192 CachedEdits.push_back(data);

193}

194

196 FileOffset RangeOffs, unsigned RangeLen,

197 bool beforePreviousInsertions) {

198 if (RangeLen == 0)

199 return;

200

201 Edit data;

203 data.OrigLoc = OrigLoc;

204 data.Offset = Offs;

205 data.InsertFromRangeOffs = RangeOffs;

206 data.Length = RangeLen;

207 data.BeforePrev = beforePreviousInsertions;

208 CachedEdits.push_back(data);

209}

210

213 if (Len == 0)

214 return;

215

216 Edit data;

218 data.OrigLoc = OrigLoc;

219 data.Offset = Offs;

220 data.Length = Len;

221 CachedEdits.push_back(data);

222}

223

224bool Commit::canInsert(SourceLocation loc, FileOffset &offs) {

226 return false;

227

229 isAtStartOfMacroExpansion(loc, &loc);

230

231 const SourceManager &SM = SourceMgr;

232 loc = SM.getTopMacroCallerLoc(loc);

233

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

236 return false;

237

238 if (SM.isInSystemHeader(loc))

239 return false;

240

242 if (locInfo.first.isInvalid())

243 return false;

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

245 return canInsertInOffset(loc, offs);

246}

247

248bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs,

249 SourceLocation &AfterLoc) {

251

252 return false;

253

254 SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc);

257

259 isAtEndOfMacroExpansion(loc, &loc);

260

261 const SourceManager &SM = SourceMgr;

262 loc = SM.getTopMacroCallerLoc(loc);

263

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

266 return false;

267

268 if (SM.isInSystemHeader(loc))

269 return false;

270

273 return false;

274

276 if (locInfo.first.isInvalid())

277 return false;

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

279 return canInsertInOffset(loc, offs);

280}

281

282bool Commit::canInsertInOffset(SourceLocation OrigLoc, FileOffset Offs) {

283 for (const auto &act : CachedEdits)

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

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

287 return false;

288 }

289

290 if (!Editor)

291 return true;

292 return Editor->canInsertInOffset(OrigLoc, Offs);

293}

294

295bool Commit::canRemoveRange(CharSourceRange range,

297 const SourceManager &SM = SourceMgr;

299 if (range.isInvalid())

300 return false;

301

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

303 return false;

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

305 SM.isInSystemHeader(range.getEnd()))

306 return false;

307

308 if (PPRec && PPRec->rangeIntersectsConditionalDirective(range.getAsRange()))

309 return false;

310

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

314 beginInfo.second > endInfo.second)

315 return false;

316

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

318 Len = endInfo.second - beginInfo.second;

319 return true;

320}

321

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

324 assert(text.empty());

325

326 if (!canInsert(loc, Offs))

327 return false;

328

329

330 bool invalidTemp = false;

331 StringRef file = SourceMgr.getBufferData(Offs.getFID(), &invalidTemp);

332 if (invalidTemp)

333 return false;

334

335 Len = text.size();

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

337}

338

339bool Commit::isAtStartOfMacroExpansion(SourceLocation loc,

340 SourceLocation *MacroBegin) const {

342}

343

344bool Commit::isAtEndOfMacroExpansion(SourceLocation loc,

345 SourceLocation *MacroEnd) const {

347}

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.

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.

bool replaceWithInner(CharSourceRange range, CharSourceRange innerRange)

Definition Commit.cpp:131

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

Definition Commit.cpp:102

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

Definition Commit.cpp:63

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

Definition Commit.cpp:47

Commit(EditedSource &Editor)

Definition Commit.cpp:42

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

bool remove(CharSourceRange range)

Definition Commit.cpp:90

bool replace(CharSourceRange range, StringRef text)

Definition Commit.cpp:115

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

Definition Commit.cpp:164

FileOffset getWithOffset(unsigned offset) const

unsigned getOffset() const

RangeSelector range(RangeSelector Begin, RangeSelector End)

DEPRECATED. Use enclose.

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

std::pair< FileID, unsigned > FileIDAndOffset

SourceLocation getFileLocation(SourceManager &SM) const

Definition Commit.cpp:23

CharSourceRange getFileRange(SourceManager &SM) const

Definition Commit.cpp:30

FileOffset InsertFromRangeOffs

CharSourceRange getInsertFromRange(SourceManager &SM) const

Definition Commit.cpp:35