@@ -381,6 +381,9 @@ namespace {
381
381
};
382
382
383
383
unsigned LineNumber;
384
+ // The line number displayed to the user. This may differ from the actual
385
+ // line number if #sourceLocation is used.
386
+ unsigned DisplayLineNumber;
384
387
std::string LineText;
385
388
SmallVector<Message, 1 > Messages;
386
389
SmallVector<Highlight, 1 > Highlights;
@@ -448,8 +451,10 @@ namespace {
448
451
}
449
452
450
453
public:
451
- AnnotatedLine (unsigned LineNumber, StringRef LineText)
452
- : LineNumber(LineNumber), LineText(LineText) {}
454
+ AnnotatedLine (unsigned LineNumber, unsigned DisplayLineNumber,
455
+ StringRef LineText)
456
+ : LineNumber(LineNumber), DisplayLineNumber(DisplayLineNumber),
457
+ LineText (LineText) {}
453
458
454
459
unsigned getLineNumber () { return LineNumber; }
455
460
@@ -469,7 +474,7 @@ namespace {
469
474
}
470
475
471
476
void render (unsigned LineNumberIndent, raw_ostream &Out) {
472
- printNumberedGutter (LineNumber , LineNumberIndent, Out);
477
+ printNumberedGutter (DisplayLineNumber , LineNumberIndent, Out);
473
478
474
479
// Determine if the line is all-ASCII. This will determine a number of
475
480
// later formatting decisions.
@@ -628,21 +633,25 @@ namespace {
628
633
// / diagnostic message. This is printed alongside the file path so it can be
629
634
// / parsed by editors and other tooling.
630
635
SourceLoc PrimaryLoc;
636
+ // / Whether the excerpt is from a virtual file (e.g. one introduced using
637
+ // / #sourceLocation).
638
+ bool FromVirtualFile;
631
639
std::vector<AnnotatedLine> AnnotatedLines;
632
640
633
641
// / Return the AnnotatedLine for a given SourceLoc, creating it if it
634
642
// / doesn't already exist.
635
643
AnnotatedLine &lineForLoc (SourceLoc Loc) {
636
- // FIXME: This call to `getLineAndColumn ` is expensive.
637
- unsigned lineNo = SM.getLineAndColumn (Loc). first ;
638
- AnnotatedLine newLine (lineNo, " " );
644
+ // FIXME: This call to `getLineNumber ` is expensive.
645
+ unsigned lineNo = SM.getLineNumber (Loc);
646
+ AnnotatedLine newLine (lineNo, 0 , " " );
639
647
auto iter =
640
648
std::lower_bound (AnnotatedLines.begin (), AnnotatedLines.end (),
641
649
newLine, [](AnnotatedLine l1, AnnotatedLine l2) {
642
650
return l1.getLineNumber () < l2.getLineNumber ();
643
651
});
644
652
if (iter == AnnotatedLines.end () || iter->getLineNumber () != lineNo) {
645
653
newLine.LineText = SM.getLineString (BufferID, lineNo);
654
+ newLine.DisplayLineNumber = SM.getLineAndColumn (Loc).first ;
646
655
return *AnnotatedLines.insert (iter, newLine);
647
656
} else {
648
657
return *iter;
@@ -658,10 +667,8 @@ namespace {
658
667
659
668
void lineRangesForRange (CharSourceRange Range,
660
669
SmallVectorImpl<CharSourceRange> &LineRanges) {
661
- // FIXME: The calls to `getLineAndColumn` and `getLocForLineCol` are
662
- // expensive.
663
- unsigned startLineNo = SM.getLineAndColumn (Range.getStart ()).first ;
664
- unsigned endLineNo = SM.getLineAndColumn (Range.getEnd ()).first ;
670
+ unsigned startLineNo = SM.getLineNumber (Range.getStart ());
671
+ unsigned endLineNo = SM.getLineNumber (Range.getEnd ());
665
672
666
673
if (startLineNo == endLineNo) {
667
674
LineRanges.push_back (Range);
@@ -687,10 +694,19 @@ namespace {
687
694
LineRanges.push_back (CharSourceRange (SM, lastLineStart, Range.getEnd ()));
688
695
}
689
696
697
+ void printLineEllipsis (raw_ostream &Out) {
698
+ Out.changeColor (ColoredStream::Colors::CYAN, true );
699
+ Out << llvm::formatv (" {0}...\n " ,
700
+ llvm::fmt_repeat (" " , getPreferredLineNumberIndent ()));
701
+ Out.resetColor ();
702
+ }
703
+
690
704
public:
691
705
AnnotatedFileExcerpt (SourceManager &SM, unsigned BufferID,
692
706
SourceLoc PrimaryLoc)
693
- : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) {}
707
+ : SM(SM), BufferID(BufferID), PrimaryLoc(PrimaryLoc) {
708
+ FromVirtualFile = SM.isLocInVirtualFile (PrimaryLoc);
709
+ }
694
710
695
711
unsigned getPreferredLineNumberIndent () {
696
712
// The lines are already in sorted ascending order, and we render one line
@@ -734,13 +750,14 @@ namespace {
734
750
auto primaryLineAndColumn = SM.getLineAndColumn (PrimaryLoc);
735
751
Out.changeColor (ColoredStream::Colors::CYAN);
736
752
Out << std::string (lineNumberIndent + 1 , ' =' ) << " "
737
- << SM.getIdentifierForBuffer (BufferID ) << " :"
753
+ << SM.getDisplayNameForLoc (PrimaryLoc ) << " :"
738
754
<< primaryLineAndColumn.first << " :" << primaryLineAndColumn.second
739
755
<< " " << std::string (lineNumberIndent + 1 , ' =' ) << " \n " ;
740
756
Out.resetColor ();
741
757
742
- // Print one extra line at the top for context.
743
- if (AnnotatedLines.front ().getLineNumber () > 1 )
758
+ // Print one extra line at the top for context, so long as this isn't an
759
+ // excerpt from a virtual file.
760
+ if (AnnotatedLines.front ().getLineNumber () > 1 && !FromVirtualFile)
744
761
printNumberedLine (SM, BufferID,
745
762
AnnotatedLines.front ().getLineNumber () - 1 ,
746
763
lineNumberIndent, Out);
@@ -754,14 +771,18 @@ namespace {
754
771
for (auto line = AnnotatedLines.begin () + 1 ; line != AnnotatedLines.end ();
755
772
++line) {
756
773
unsigned lineNumber = line->getLineNumber ();
757
- if (lineNumber - lastLineNumber > maxIntermediateLines) {
774
+ if (FromVirtualFile) {
775
+ // Don't print intermediate lines in virtual files, as they may not
776
+ // make sense in context. Instead, just print an ellipsis between them
777
+ // if they're not consecutive in the actual source file.
778
+ if (lineNumber - lastLineNumber > 1 ) {
779
+ printLineEllipsis (Out);
780
+ }
781
+ } else if (lineNumber - lastLineNumber > maxIntermediateLines) {
758
782
// Use an ellipsis to denote an ommitted part of the file.
759
783
printNumberedLine (SM, BufferID, lastLineNumber + 1 , lineNumberIndent,
760
784
Out);
761
- Out.changeColor (ColoredStream::Colors::CYAN);
762
- Out << llvm::formatv (" {0}...\n " ,
763
- llvm::fmt_repeat (" " , lineNumberIndent));
764
- Out.resetColor ();
785
+ printLineEllipsis (Out);
765
786
printNumberedLine (SM, BufferID, lineNumber - 1 , lineNumberIndent,
766
787
Out);
767
788
} else {
@@ -774,11 +795,14 @@ namespace {
774
795
line->render (lineNumberIndent, Out);
775
796
lastLineNumber = lineNumber;
776
797
}
777
- // Print one extra line at the bottom for context.
778
- printNumberedLine (
779
- SM, BufferID,
780
- AnnotatedLines[AnnotatedLines.size () - 1 ].getLineNumber () + 1 ,
781
- lineNumberIndent, Out);
798
+ // Print one extra line at the bottom for context, so long as the excerpt
799
+ // isn't from a virtual file.
800
+ if (!FromVirtualFile) {
801
+ printNumberedLine (
802
+ SM, BufferID,
803
+ AnnotatedLines[AnnotatedLines.size () - 1 ].getLineNumber () + 1 ,
804
+ lineNumberIndent, Out);
805
+ }
782
806
}
783
807
};
784
808
} // end anonymous namespace
@@ -788,14 +812,17 @@ namespace swift {
788
812
// / complete diagnostic message.
789
813
class AnnotatedSourceSnippet {
790
814
SourceManager &SM;
791
- std::map<unsigned , AnnotatedFileExcerpt> FileExcerpts;
815
+ std::map<StringRef , AnnotatedFileExcerpt> FileExcerpts;
792
816
SmallVector<std::pair<DiagnosticKind, std::string>, 1 >
793
817
UnknownLocationMessages;
794
818
795
819
AnnotatedFileExcerpt &excerptForLoc (SourceLoc Loc) {
820
+ StringRef bufName = SM.getDisplayNameForLoc (Loc);
796
821
unsigned bufID = SM.findBufferContainingLoc (Loc);
797
- FileExcerpts.emplace (bufID, AnnotatedFileExcerpt (SM, bufID, Loc));
798
- return FileExcerpts.find (bufID)->second ;
822
+ // Use the buffer display name as the key in the excerpt map instead of the
823
+ // buffer identifier to respect #sourceLocation directives.
824
+ FileExcerpts.emplace (bufName, AnnotatedFileExcerpt (SM, bufID, Loc));
825
+ return FileExcerpts.find (bufName)->second ;
799
826
}
800
827
801
828
public:
0 commit comments