Skip to content

Commit 267034c

Browse files
author
Eric Liu
committedAug 1, 2016
Changes related to new implementation of tooling::Replacements as class.
Summary: See http://reviews.llvm.org/D21748 for details. Reviewers: djasper, klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D21749 llvm-svn: 277336
1 parent 40ef2fb commit 267034c

File tree

11 files changed

+152
-36
lines changed

11 files changed

+152
-36
lines changed
 

‎clang-tools-extra/clang-apply-replacements/include/clang-apply-replacements/Tooling/ApplyReplacements.h

+5
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ bool mergeAndDeduplicate(const TUReplacements &TUs,
9191
FileToReplacementsMap &GroupedReplacements,
9292
clang::SourceManager &SM);
9393

94+
// FIXME: Remove this function after changing clang-apply-replacements to use
95+
// Replacements class.
96+
bool applyAllReplacements(const std::vector<tooling::Replacement> &Replaces,
97+
Rewriter &Rewrite);
98+
9499
/// \brief Apply all replacements in \c GroupedReplacements.
95100
///
96101
/// \param[in] GroupedReplacements Deduplicated and conflict free Replacements

‎clang-tools-extra/clang-apply-replacements/lib/Tooling/ApplyReplacements.cpp

+77-2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,81 @@ static void reportConflict(
122122
}
123123
}
124124

125+
// FIXME: Remove this function after changing clang-apply-replacements to use
126+
// Replacements class.
127+
bool applyAllReplacements(const std::vector<tooling::Replacement> &Replaces,
128+
Rewriter &Rewrite) {
129+
bool Result = true;
130+
for (std::vector<tooling::Replacement>::const_iterator I = Replaces.begin(),
131+
E = Replaces.end();
132+
I != E; ++I) {
133+
if (I->isApplicable()) {
134+
Result = I->apply(Rewrite) && Result;
135+
} else {
136+
Result = false;
137+
}
138+
}
139+
return Result;
140+
}
141+
142+
143+
// FIXME: moved from libToolingCore. remove this when std::vector<Replacement>
144+
// is replaced with tooling::Replacements class.
145+
static void deduplicate(std::vector<tooling::Replacement> &Replaces,
146+
std::vector<tooling::Range> &Conflicts) {
147+
if (Replaces.empty())
148+
return;
149+
150+
auto LessNoPath = [](const tooling::Replacement &LHS,
151+
const tooling::Replacement &RHS) {
152+
if (LHS.getOffset() != RHS.getOffset())
153+
return LHS.getOffset() < RHS.getOffset();
154+
if (LHS.getLength() != RHS.getLength())
155+
return LHS.getLength() < RHS.getLength();
156+
return LHS.getReplacementText() < RHS.getReplacementText();
157+
};
158+
159+
auto EqualNoPath = [](const tooling::Replacement &LHS,
160+
const tooling::Replacement &RHS) {
161+
return LHS.getOffset() == RHS.getOffset() &&
162+
LHS.getLength() == RHS.getLength() &&
163+
LHS.getReplacementText() == RHS.getReplacementText();
164+
};
165+
166+
// Deduplicate. We don't want to deduplicate based on the path as we assume
167+
// that all replacements refer to the same file (or are symlinks).
168+
std::sort(Replaces.begin(), Replaces.end(), LessNoPath);
169+
Replaces.erase(std::unique(Replaces.begin(), Replaces.end(), EqualNoPath),
170+
Replaces.end());
171+
172+
// Detect conflicts
173+
tooling::Range ConflictRange(Replaces.front().getOffset(),
174+
Replaces.front().getLength());
175+
unsigned ConflictStart = 0;
176+
unsigned ConflictLength = 1;
177+
for (unsigned i = 1; i < Replaces.size(); ++i) {
178+
tooling::Range Current(Replaces[i].getOffset(), Replaces[i].getLength());
179+
if (ConflictRange.overlapsWith(Current)) {
180+
// Extend conflicted range
181+
ConflictRange =
182+
tooling::Range(ConflictRange.getOffset(),
183+
std::max(ConflictRange.getLength(),
184+
Current.getOffset() + Current.getLength() -
185+
ConflictRange.getOffset()));
186+
++ConflictLength;
187+
} else {
188+
if (ConflictLength > 1)
189+
Conflicts.push_back(tooling::Range(ConflictStart, ConflictLength));
190+
ConflictRange = Current;
191+
ConflictStart = i;
192+
ConflictLength = 1;
193+
}
194+
}
195+
196+
if (ConflictLength > 1)
197+
Conflicts.push_back(tooling::Range(ConflictStart, ConflictLength));
198+
}
199+
125200
/// \brief Deduplicates and tests for conflicts among the replacements for each
126201
/// file in \c Replacements. Any conflicts found are reported.
127202
///
@@ -144,7 +219,7 @@ static bool deduplicateAndDetectConflicts(FileToReplacementsMap &Replacements,
144219
assert(Entry != nullptr && "No file entry!");
145220

146221
std::vector<tooling::Range> Conflicts;
147-
tooling::deduplicate(FileAndReplacements.second, Conflicts);
222+
deduplicate(FileAndReplacements.second, Conflicts);
148223

149224
if (Conflicts.empty())
150225
continue;
@@ -197,7 +272,7 @@ bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
197272
// However, until we nail down the design of ReplacementGroups, might as well
198273
// leave this as is.
199274
for (const auto &FileAndReplacements : GroupedReplacements) {
200-
if (!tooling::applyAllReplacements(FileAndReplacements.second, Rewrites))
275+
if (!applyAllReplacements(FileAndReplacements.second, Rewrites))
201276
return false;
202277
}
203278

‎clang-tools-extra/clang-apply-replacements/tool/ClangApplyReplacementsMain.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ getRewrittenData(const std::vector<tooling::Replacement> &Replacements,
108108
Rewriter &Rewrites, std::string &Result) {
109109
if (Replacements.empty()) return true;
110110

111-
if (!tooling::applyAllReplacements(Replacements, Rewrites))
111+
if (!applyAllReplacements(Replacements, Rewrites))
112112
return false;
113113

114114
SourceManager &SM = Rewrites.getSourceMgr();

‎clang-tools-extra/clang-rename/RenamingAction.cpp

+15-9
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ namespace rename {
3434

3535
class RenamingASTConsumer : public ASTConsumer {
3636
public:
37-
RenamingASTConsumer(const std::string &NewName, const std::string &PrevName,
38-
const std::vector<std::string> &USRs,
39-
tooling::Replacements &Replaces, bool PrintLocations)
40-
: NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),
41-
PrintLocations(PrintLocations) {}
37+
RenamingASTConsumer(
38+
const std::string &NewName, const std::string &PrevName,
39+
const std::vector<std::string> &USRs,
40+
std::map<std::string, tooling::Replacements> &FileToReplaces,
41+
bool PrintLocations)
42+
: NewName(NewName), PrevName(PrevName), USRs(USRs),
43+
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
4244

4345
void HandleTranslationUnit(ASTContext &Context) override {
4446
const auto &SourceMgr = Context.getSourceManager();
@@ -58,21 +60,25 @@ class RenamingASTConsumer : public ASTConsumer {
5860
<< ":" << FullLoc.getSpellingLineNumber() << ":"
5961
<< FullLoc.getSpellingColumnNumber() << "\n";
6062
}
61-
Replaces.insert(
62-
tooling::Replacement(SourceMgr, Loc, PrevNameLen, NewName));
63+
// FIXME: better error handling.
64+
auto Replace = tooling::Replacement(SourceMgr, Loc, PrevNameLen, NewName);
65+
auto Err = FileToReplaces[Replace.getFilePath()].add(Replace);
66+
if (Err)
67+
llvm::errs() << "Renaming failed in " << Replace.getFilePath() << "! "
68+
<< llvm::toString(std::move(Err)) << "\n";
6369
}
6470
}
6571

6672
private:
6773
const std::string &NewName, &PrevName;
6874
const std::vector<std::string> &USRs;
69-
tooling::Replacements &Replaces;
75+
std::map<std::string, tooling::Replacements> &FileToReplaces;
7076
bool PrintLocations;
7177
};
7278

7379
std::unique_ptr<ASTConsumer> RenamingAction::newASTConsumer() {
7480
return llvm::make_unique<RenamingASTConsumer>(NewName, PrevName, USRs,
75-
Replaces, PrintLocations);
81+
FileToReplaces, PrintLocations);
7682
}
7783

7884
} // namespace rename

‎clang-tools-extra/clang-rename/RenamingAction.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ class RenamingAction {
2727
public:
2828
RenamingAction(const std::string &NewName, const std::string &PrevName,
2929
const std::vector<std::string> &USRs,
30-
tooling::Replacements &Replaces, bool PrintLocations = false)
31-
: NewName(NewName), PrevName(PrevName), USRs(USRs), Replaces(Replaces),
32-
PrintLocations(PrintLocations) {
33-
}
30+
std::map<std::string, tooling::Replacements> &FileToReplaces,
31+
bool PrintLocations = false)
32+
: NewName(NewName), PrevName(PrevName), USRs(USRs),
33+
FileToReplaces(FileToReplaces), PrintLocations(PrintLocations) {}
3434

3535
std::unique_ptr<ASTConsumer> newASTConsumer();
3636

3737
private:
3838
const std::string &NewName, &PrevName;
3939
const std::vector<std::string> &USRs;
40-
tooling::Replacements &Replaces;
40+
std::map<std::string, tooling::Replacements> &FileToReplaces;
4141
bool PrintLocations;
4242
};
4343

‎clang-tools-extra/clang-rename/tool/ClangRename.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,10 @@ int main(int argc, const char **argv) {
146146

147147
// Export replacements.
148148
tooling::TranslationUnitReplacements TUR;
149-
const tooling::Replacements &Replacements = Tool.getReplacements();
150-
TUR.Replacements.insert(TUR.Replacements.end(), Replacements.begin(),
151-
Replacements.end());
149+
const auto &FileToReplacements = Tool.getReplacements();
150+
for (const auto &Entry : FileToReplacements)
151+
TUR.Replacements.insert(TUR.Replacements.end(), Entry.second.begin(),
152+
Entry.second.end());
152153

153154
yaml::Output YAML(OS);
154155
YAML << TUR;

‎clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp

+8-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,14 @@ class ClangTidyDiagnosticRenderer : public DiagnosticRenderer {
7777
assert(Range.getBegin().isFileID() && Range.getEnd().isFileID() &&
7878
"Only file locations supported in fix-it hints.");
7979

80-
Error.Fix.insert(tooling::Replacement(SM, Range, FixIt.CodeToInsert));
80+
auto Err =
81+
Error.Fix.add(tooling::Replacement(SM, Range, FixIt.CodeToInsert));
82+
// FIXME: better error handling.
83+
if (Err) {
84+
llvm::errs() << "Fix conflicts with existing fix! "
85+
<< llvm::toString(std::move(Err)) << "\n";
86+
}
87+
assert(!Err && "Fix conflicts with existing fix!");
8188
}
8289
}
8390

‎clang-tools-extra/include-fixer/IncludeFixer.cpp

+20-7
Original file line numberDiff line numberDiff line change
@@ -352,23 +352,36 @@ llvm::Expected<tooling::Replacements> createIncludeFixerReplacements(
352352
std::string IncludeName =
353353
"#include " + Context.getHeaderInfos().front().Header + "\n";
354354
// Create replacements for the new header.
355-
clang::tooling::Replacements Insertions = {
356-
tooling::Replacement(FilePath, UINT_MAX, 0, IncludeName)};
355+
clang::tooling::Replacements Insertions;
356+
auto Err =
357+
Insertions.add(tooling::Replacement(FilePath, UINT_MAX, 0, IncludeName));
358+
if (Err)
359+
return std::move(Err);
357360

358361
auto CleanReplaces = cleanupAroundReplacements(Code, Insertions, Style);
359362
if (!CleanReplaces)
360363
return CleanReplaces;
361364

365+
auto Replaces = std::move(*CleanReplaces);
362366
if (AddQualifiers) {
363367
for (const auto &Info : Context.getQuerySymbolInfos()) {
364368
// Ignore the empty range.
365-
if (Info.Range.getLength() > 0)
366-
CleanReplaces->insert({FilePath, Info.Range.getOffset(),
367-
Info.Range.getLength(),
368-
Context.getHeaderInfos().front().QualifiedName});
369+
if (Info.Range.getLength() > 0) {
370+
auto R = tooling::Replacement(
371+
{FilePath, Info.Range.getOffset(), Info.Range.getLength(),
372+
Context.getHeaderInfos().front().QualifiedName});
373+
auto Err = Replaces.add(R);
374+
if (Err) {
375+
llvm::consumeError(std::move(Err));
376+
R = tooling::Replacement(
377+
R.getFilePath(), Replaces.getShiftedCodePosition(R.getOffset()),
378+
R.getLength(), R.getReplacementText());
379+
Replaces = Replaces.merge(tooling::Replacements(R));
380+
}
381+
}
369382
}
370383
}
371-
return formatReplacements(Code, *CleanReplaces, Style);
384+
return formatReplacements(Code, Replaces, Style);
372385
}
373386

374387
} // namespace include_fixer

‎clang-tools-extra/include-fixer/tool/ClangIncludeFixer.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,8 @@ int includeFixerMain(int argc, const char **argv) {
350350
}
351351

352352
if (!Quiet)
353-
errs() << "Added #include " << Context.getHeaderInfos().front().Header
354-
<< '\n';
353+
llvm::errs() << "Added #include " << Context.getHeaderInfos().front().Header
354+
<< "\n";
355355

356356
// Set up a new source manager for applying the resulting replacements.
357357
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);

‎clang-tools-extra/tool-template/ToolTemplate.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,20 @@ using namespace llvm;
5353

5454
namespace {
5555
class ToolTemplateCallback : public MatchFinder::MatchCallback {
56-
public:
57-
ToolTemplateCallback(Replacements *Replace) : Replace(Replace) {}
56+
public:
57+
ToolTemplateCallback(std::map<std::string, Replacements> *Replace)
58+
: Replace(Replace) {}
5859

5960
void run(const MatchFinder::MatchResult &Result) override {
60-
// TODO: This routine will get called for each thing that the matchers find.
61+
// TODO: This routine will get called for each thing that the matchers
62+
// find.
6163
// At this point, you can examine the match, and do whatever you want,
6264
// including replacing the matched text with other text
6365
(void)Replace; // This to prevent an "unused member variable" warning;
6466
}
6567

66-
private:
67-
Replacements *Replace;
68+
private:
69+
std::map<std::string, Replacements> *Replace;
6870
};
6971
} // end anonymous namespace
7072

‎clang-tools-extra/unittests/clang-tidy/ClangTidyTest.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,14 @@ runCheckOnCode(StringRef Code, std::vector<ClangTidyError> *Errors = nullptr,
119119
DiagConsumer.finish();
120120
tooling::Replacements Fixes;
121121
for (const ClangTidyError &Error : Context.getErrors())
122-
Fixes.insert(Error.Fix.begin(), Error.Fix.end());
122+
for (const auto &Fix : Error.Fix) {
123+
auto Err = Fixes.add(Fix);
124+
// FIXME: better error handling. Keep the behavior for now.
125+
if (Err) {
126+
llvm::errs() << llvm::toString(std::move(Err)) << "\n";
127+
return "";
128+
}
129+
}
123130
if (Errors)
124131
*Errors = Context.getErrors();
125132
auto Result = tooling::applyAllReplacements(Code, Fixes);

0 commit comments

Comments
 (0)
Please sign in to comment.