@@ -176,35 +176,102 @@ bool SemaLocResolver::visitModuleReference(ModuleEntity Mod,
176
176
177
177
struct RangeResolver ::Implementation {
178
178
SourceFile &File;
179
+ private:
180
+ enum class RangeMatchKind : int8_t {
181
+ NoneMatch,
182
+ StartMatch,
183
+ EndMatch,
184
+ RangeMatch,
185
+ };
186
+
187
+ struct ContextInfo {
188
+ ASTNode Parent;
189
+ std::vector<ASTNode> StartMatches;
190
+ std::vector<ASTNode> EndMatches;
191
+ ContextInfo (ASTNode Parent) : Parent(Parent) {}
192
+ };
193
+
179
194
SourceLoc Start;
180
195
SourceLoc End;
196
+ StringRef Content;
181
197
Optional<ResolvedRangeInfo> Result;
182
- Implementation (SourceFile &File, SourceLoc Start, SourceLoc End) :
183
- File (File), Start(Start), End(End) {}
198
+ std::vector<ContextInfo> ContextStack;
199
+ ContextInfo &getCurrentDC () {
200
+ assert (!ContextStack.empty ());
201
+ return ContextStack.back ();
202
+ }
184
203
185
- bool isRangeMatch (SourceRange Input) {
186
- return Input.Start == Start && Input.End == End;
204
+ ResolvedRangeInfo getSingleNodeKind (ASTNode Node) {
205
+ assert (!Node.isNull ());
206
+ if (Node.is <Expr*>())
207
+ return ResolvedRangeInfo (RangeKind::SingleExpression,
208
+ Node.get <Expr*>()->getType (), Content);
209
+ else if (Node.is <Stmt*>())
210
+ return ResolvedRangeInfo (RangeKind::SingleStatement, Type (), Content);
211
+ else {
212
+ assert (Node.is <Decl*>());
213
+ return ResolvedRangeInfo (RangeKind::SingleDecl, Type (), Content);
214
+ }
215
+ }
216
+
217
+ public:
218
+ Implementation (SourceFile &File, SourceLoc Start, SourceLoc End) :
219
+ File (File), Start(Start), End(End), Content(getContent()) {}
220
+ ~Implementation () { assert (ContextStack.empty ()); }
221
+ bool hasResult () { return Result.hasValue (); }
222
+ void enter (ASTNode Node) { ContextStack.emplace_back (Node); }
223
+ void leave () { ContextStack.pop_back (); }
224
+
225
+ void analyze (ASTNode Node) {
226
+ auto &DCInfo = getCurrentDC ();
227
+ switch (getRangeMatchKind (Node.getSourceRange ())) {
228
+ case RangeMatchKind::NoneMatch:
229
+ return ;
230
+ case RangeMatchKind::RangeMatch:
231
+ Result = getSingleNodeKind (Node);
232
+ return ;
233
+ case RangeMatchKind::StartMatch:
234
+ DCInfo.StartMatches .emplace_back (Node);
235
+ break ;
236
+ case RangeMatchKind::EndMatch:
237
+ DCInfo.EndMatches .emplace_back (Node);
238
+ break ;
239
+ }
240
+ if (!DCInfo.StartMatches .empty () && !DCInfo.EndMatches .empty ()) {
241
+ Result = {RangeKind::MultiStatement, Type (), Content};
242
+ return ;
243
+ }
187
244
}
188
245
189
- bool shouldEnter (SourceRange Input ) {
246
+ bool shouldEnter (ASTNode Node ) {
190
247
SourceManager &SM = File.getASTContext ().SourceMgr ;
191
- if (SM.isBeforeInBuffer (End, Input .Start ))
248
+ if (SM.isBeforeInBuffer (End, Node. getSourceRange () .Start ))
192
249
return false ;
193
- if (SM.isBeforeInBuffer (Input .End , Start))
250
+ if (SM.isBeforeInBuffer (Node. getSourceRange () .End , Start))
194
251
return false ;
195
252
return true ;
196
253
}
197
254
198
- bool hasResult () {
199
- return Result.hasValue ();
200
- }
201
-
202
255
ResolvedRangeInfo getResult () {
203
256
if (Result.hasValue ())
204
257
return Result.getValue ();
205
258
return ResolvedRangeInfo (RangeKind::Invalid, Type (), getContent ());
206
259
}
207
260
261
+ private:
262
+ RangeMatchKind getRangeMatchKind (SourceRange Input) {
263
+ bool StartMatch = Input.Start == Start;
264
+ bool EndMatch = Input.End == End;
265
+ if (StartMatch && EndMatch)
266
+ return RangeMatchKind::RangeMatch;
267
+ else if (StartMatch)
268
+ return RangeMatchKind::StartMatch;
269
+ else if (EndMatch)
270
+ return RangeMatchKind::EndMatch;
271
+ else
272
+ return RangeMatchKind::NoneMatch;
273
+ }
274
+
208
275
StringRef getContent () {
209
276
SourceManager &SM = File.getASTContext ().SourceMgr ;
210
277
return CharSourceRange (SM, Start, Lexer::getLocForEndOfToken (SM, End)).str ();
@@ -217,45 +284,48 @@ RangeResolver::RangeResolver(SourceFile &File, SourceLoc Start, SourceLoc End) :
217
284
RangeResolver::~RangeResolver () { delete &Impl; }
218
285
219
286
bool RangeResolver::walkToExprPre (Expr *E) {
220
- if (!Impl.shouldEnter (E-> getSourceRange () ))
287
+ if (!Impl.shouldEnter (E))
221
288
return false ;
222
- if (Impl.isRangeMatch (E->getSourceRange ())) {
223
- Impl.Result = ResolvedRangeInfo (RangeKind::Expression, E->getType (),
224
- Impl.getContent ());
225
- }
289
+ Impl.analyze (E);
290
+ Impl.enter (E);
226
291
return !Impl.hasResult ();
227
292
}
228
293
229
294
bool RangeResolver::walkToStmtPre (Stmt *S) {
230
- if (!Impl.shouldEnter (S-> getSourceRange () ))
295
+ if (!Impl.shouldEnter (S))
231
296
return false ;
232
- if (Impl.isRangeMatch (S->getSourceRange ())) {
233
- Impl.Result = ResolvedRangeInfo (RangeKind::SingleStatement, Type (),
234
- Impl.getContent ());
235
- }
297
+ Impl.analyze (S);
298
+ Impl.enter (S);
236
299
return !Impl.hasResult ();
237
300
};
238
301
239
-
240
302
bool RangeResolver::walkToDeclPre (Decl *D, CharSourceRange Range) {
241
- return Impl.shouldEnter (D->getSourceRange ());
303
+ if (!Impl.shouldEnter (D))
304
+ return false ;
305
+ Impl.analyze (D);
306
+ Impl.enter (D);
307
+ return !Impl.hasResult ();
242
308
}
243
309
244
310
bool RangeResolver::walkToExprPost (Expr *E) {
311
+ Impl.leave ();
245
312
return !Impl.hasResult ();
246
313
}
247
314
248
315
bool RangeResolver::walkToStmtPost (Stmt *S) {
316
+ Impl.leave ();
249
317
return !Impl.hasResult ();
250
318
};
251
319
252
320
bool RangeResolver::walkToDeclPost (Decl *D) {
321
+ Impl.leave ();
253
322
return !Impl.hasResult ();
254
323
}
255
324
256
- ResolvedRangeInfo
257
- RangeResolver::resolve () {
325
+ ResolvedRangeInfo RangeResolver::resolve () {
326
+ Impl. enter ( ASTNode ());
258
327
walk (Impl.File );
328
+ Impl.leave ();
259
329
return Impl.getResult ();
260
330
}
261
331
0 commit comments