19
19
#include " swift/IDE/CommentConversion.h"
20
20
#include " swift/IDE/Utils.h"
21
21
#include " swift/Markup/XMLUtils.h"
22
+ #include " swift/Subsystems.h"
22
23
23
24
#include " clang/AST/ASTContext.h"
24
25
#include " clang/AST/DeclObjC.h"
@@ -225,9 +226,11 @@ void ResolvedRangeInfo::print(llvm::raw_ostream &OS) {
225
226
OS << " </Type>\n " ;
226
227
}
227
228
228
- OS << " <Context>" ;
229
- printContext (OS, RangeContext);
230
- OS << " </Context>\n " ;
229
+ if (RangeContext) {
230
+ OS << " <Context>" ;
231
+ printContext (OS, RangeContext);
232
+ OS << " </Context>\n " ;
233
+ }
231
234
232
235
if (!HasSingleEntry) {
233
236
OS << " <Entry>Multi</Entry>\n " ;
@@ -341,6 +344,9 @@ struct RangeResolver::Implementation {
341
344
ContainedInRange (ContainedInRange) {}
342
345
};
343
346
347
+ std::vector<Token> AllTokens;
348
+ Token &StartTok;
349
+ Token &EndTok;
344
350
SourceLoc Start;
345
351
SourceLoc End;
346
352
StringRef Content;
@@ -412,43 +418,6 @@ struct RangeResolver::Implementation {
412
418
return true ;
413
419
}
414
420
415
- static SourceLoc getNonwhitespaceLocBefore (SourceManager &SM,
416
- unsigned BufferID,
417
- unsigned Offset) {
418
- CharSourceRange entireRange = SM.getRangeForBuffer (BufferID);
419
- StringRef Buffer = SM.extractText (entireRange);
420
-
421
- const char *BufStart = Buffer.data ();
422
- if (Offset >= Buffer.size ())
423
- return SourceLoc ();
424
-
425
- for (unsigned Off = Offset; Off != 0 ; Off --) {
426
- if (!clang::isWhitespace (*(BufStart + Off))) {
427
- return SM.getLocForOffset (BufferID, Off);
428
- }
429
- }
430
- return clang::isWhitespace (*BufStart) ? SourceLoc () :
431
- SM.getLocForOffset (BufferID, 0 );
432
- }
433
-
434
- static SourceLoc getNonwhitespaceLocAfter (SourceManager &SM,
435
- unsigned BufferID,
436
- unsigned Offset) {
437
- CharSourceRange entireRange = SM.getRangeForBuffer (BufferID);
438
- StringRef Buffer = SM.extractText (entireRange);
439
-
440
- const char *BufStart = Buffer.data ();
441
- if (Offset >= Buffer.size ())
442
- return SourceLoc ();
443
-
444
- for (unsigned Off = Offset; Off < Buffer.size (); Off ++) {
445
- if (!clang::isWhitespace (*(BufStart + Off))) {
446
- return SM.getLocForOffset (BufferID, Off);
447
- }
448
- }
449
- return SourceLoc ();
450
- }
451
-
452
421
DeclContext *getImmediateContext () {
453
422
for (auto It = ContextStack.rbegin (); It != ContextStack.rend (); It ++) {
454
423
if (auto *DC = It->Parent .getAsDeclContext ())
@@ -457,9 +426,14 @@ struct RangeResolver::Implementation {
457
426
return static_cast <DeclContext*>(&File);
458
427
}
459
428
460
- Implementation (SourceFile &File, SourceLoc Start, SourceLoc End) :
461
- File(File), Ctx(File.getASTContext()), SM(Ctx.SourceMgr), Start(Start),
462
- End(End), Content(getContent()) {}
429
+ Implementation (SourceFile &File, std::vector<Token> AllTokens,
430
+ unsigned StartIdx, unsigned EndIdx) :
431
+ File(File), Ctx(File.getASTContext()), SM(Ctx.SourceMgr),
432
+ AllTokens(AllTokens), StartTok(AllTokens[StartIdx]), EndTok(AllTokens[EndIdx]),
433
+ Start(StartTok.getLoc()), End(EndTok.getLoc()),
434
+ Content(getContent()) {
435
+ assert (Start.isValid () && End.isValid ());
436
+ }
463
437
464
438
public:
465
439
bool hasResult () { return Result.hasValue (); }
@@ -490,14 +464,33 @@ struct RangeResolver::Implementation {
490
464
unsigned Length) {
491
465
SourceManager &SM = File.getASTContext ().SourceMgr ;
492
466
unsigned BufferId = File.getBufferID ().getValue ();
493
- SourceLoc StartLoc = Implementation::getNonwhitespaceLocAfter (SM, BufferId,
494
- StartOff);
495
- SourceLoc EndLoc = Implementation::getNonwhitespaceLocBefore (SM, BufferId,
496
- StartOff + Length - 1 );
497
- StartLoc = Lexer::getLocForStartOfToken (SM, StartLoc);
498
- EndLoc = Lexer::getLocForStartOfToken (SM, EndLoc);
499
- return StartLoc.isInvalid () || EndLoc.isInvalid () ? nullptr :
500
- new Implementation (File, StartLoc, EndLoc);
467
+
468
+ LangOptions Opts = File.getASTContext ().LangOpts ;
469
+ Opts.AttachCommentsToDecls = true ;
470
+ std::vector<Token> AllTokens = tokenize (Opts, SM, BufferId, 0 , 0 , false );
471
+ auto TokenComp = [&](Token &LHS, SourceLoc Loc) {
472
+ return SM.isBeforeInBuffer (LHS.getLoc (), Loc);
473
+ };
474
+
475
+ SourceLoc StartRaw = SM.getLocForOffset (BufferId, StartOff);
476
+ SourceLoc EndRaw = SM.getLocForOffset (BufferId, StartOff + Length);
477
+
478
+ // This points to the first token after or on the start loc.
479
+ auto StartIt = std::lower_bound (AllTokens.begin (), AllTokens.end (), StartRaw,
480
+ TokenComp);
481
+ // This points to the first token after or on the end loc;
482
+ auto EndIt = std::lower_bound (AllTokens.begin (), AllTokens.end (), EndRaw,
483
+ TokenComp);
484
+ // Erroneous case.
485
+ if (StartIt == AllTokens.end () || EndIt == AllTokens.begin ())
486
+ return nullptr ;
487
+
488
+ // The start token is inclusive.
489
+ unsigned StartIdx = StartIt - AllTokens.begin ();
490
+
491
+ // The end token is exclusive.
492
+ unsigned EndIdx = EndIt - 1 - AllTokens.begin ();
493
+ return new Implementation (File, std::move (AllTokens), StartIdx, EndIdx);
501
494
}
502
495
503
496
static Implementation *createInstance (SourceFile &File, SourceLoc Start,
@@ -728,7 +721,9 @@ struct RangeResolver::Implementation {
728
721
729
722
StringRef getContent () {
730
723
SourceManager &SM = File.getASTContext ().SourceMgr ;
731
- return CharSourceRange (SM, Start, Lexer::getLocForEndOfToken (SM, End)).str ();
724
+ return CharSourceRange (SM, StartTok.hasComment () ?
725
+ StartTok.getCommentStart () : StartTok.getLoc (),
726
+ Lexer::getLocForEndOfToken (SM, End)).str ();
732
727
}
733
728
};
734
729
0 commit comments