@@ -122,6 +122,81 @@ static void reportConflict(
122
122
}
123
123
}
124
124
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
+
125
200
// / \brief Deduplicates and tests for conflicts among the replacements for each
126
201
// / file in \c Replacements. Any conflicts found are reported.
127
202
// /
@@ -144,7 +219,7 @@ static bool deduplicateAndDetectConflicts(FileToReplacementsMap &Replacements,
144
219
assert (Entry != nullptr && " No file entry!" );
145
220
146
221
std::vector<tooling::Range> Conflicts;
147
- tooling:: deduplicate (FileAndReplacements.second , Conflicts);
222
+ deduplicate (FileAndReplacements.second , Conflicts);
148
223
149
224
if (Conflicts.empty ())
150
225
continue ;
@@ -197,7 +272,7 @@ bool applyReplacements(const FileToReplacementsMap &GroupedReplacements,
197
272
// However, until we nail down the design of ReplacementGroups, might as well
198
273
// leave this as is.
199
274
for (const auto &FileAndReplacements : GroupedReplacements) {
200
- if (!tooling:: applyAllReplacements (FileAndReplacements.second , Rewrites))
275
+ if (!applyAllReplacements (FileAndReplacements.second , Rewrites))
201
276
return false ;
202
277
}
203
278
0 commit comments