|
@@ -100,14 +100,52 @@ void WhitespaceManager::calculateLineBreakInformation() {
|
|
|
Changes[0].PreviousEndOfTokenColumn = 0;
|
|
|
Change *LastOutsideTokenChange = &Changes[0];
|
|
|
for (unsigned i = 1, e = Changes.size(); i != e; ++i) {
|
|
|
- unsigned OriginalWhitespaceStart =
|
|
|
- SourceMgr.getFileOffset(Changes[i].OriginalWhitespaceRange.getBegin());
|
|
|
- unsigned PreviousOriginalWhitespaceEnd = SourceMgr.getFileOffset(
|
|
|
- Changes[i - 1].OriginalWhitespaceRange.getEnd());
|
|
|
- Changes[i - 1].TokenLength = OriginalWhitespaceStart -
|
|
|
- PreviousOriginalWhitespaceEnd +
|
|
|
- Changes[i].PreviousLinePostfix.size() +
|
|
|
- Changes[i - 1].CurrentLinePrefix.size();
|
|
|
+ SourceLocation OriginalWhitespaceStart =
|
|
|
+ Changes[i].OriginalWhitespaceRange.getBegin();
|
|
|
+ SourceLocation PreviousOriginalWhitespaceEnd =
|
|
|
+ Changes[i - 1].OriginalWhitespaceRange.getEnd();
|
|
|
+ unsigned OriginalWhitespaceStartOffset =
|
|
|
+ SourceMgr.getFileOffset(OriginalWhitespaceStart);
|
|
|
+ unsigned PreviousOriginalWhitespaceEndOffset =
|
|
|
+ SourceMgr.getFileOffset(PreviousOriginalWhitespaceEnd);
|
|
|
+ assert(PreviousOriginalWhitespaceEndOffset <=
|
|
|
+ OriginalWhitespaceStartOffset);
|
|
|
+ const char *const PreviousOriginalWhitespaceEndData =
|
|
|
+ SourceMgr.getCharacterData(PreviousOriginalWhitespaceEnd);
|
|
|
+ StringRef Text(PreviousOriginalWhitespaceEndData,
|
|
|
+ SourceMgr.getCharacterData(OriginalWhitespaceStart) -
|
|
|
+ PreviousOriginalWhitespaceEndData);
|
|
|
+ // Usually consecutive changes would occur in consecutive tokens. This is
|
|
|
+ // not the case however when analyzing some preprocessor runs of the
|
|
|
+ // annotated lines. For example, in this code:
|
|
|
+ //
|
|
|
+ // #if A // line 1
|
|
|
+ // int i = 1;
|
|
|
+ // #else B // line 2
|
|
|
+ // int i = 2;
|
|
|
+ // #endif // line 3
|
|
|
+ //
|
|
|
+ // one of the runs will produce the sequence of lines marked with line 1, 2
|
|
|
+ // and 3. So the two consecutive whitespace changes just before '// line 2'
|
|
|
+ // and before '#endif // line 3' span multiple lines and tokens:
|
|
|
+ //
|
|
|
+ // #else B{change X}[// line 2
|
|
|
+ // int i = 2;
|
|
|
+ // ]{change Y}#endif // line 3
|
|
|
+ //
|
|
|
+ // For this reason, if the text between consecutive changes spans multiple
|
|
|
+ // newlines, the token length must be adjusted to the end of the original
|
|
|
+ // line of the token.
|
|
|
+ auto NewlinePos = Text.find_first_of('\n');
|
|
|
+ if (NewlinePos == StringRef::npos) {
|
|
|
+ Changes[i - 1].TokenLength = OriginalWhitespaceStartOffset -
|
|
|
+ PreviousOriginalWhitespaceEndOffset +
|
|
|
+ Changes[i].PreviousLinePostfix.size() +
|
|
|
+ Changes[i - 1].CurrentLinePrefix.size();
|
|
|
+ } else {
|
|
|
+ Changes[i - 1].TokenLength =
|
|
|
+ NewlinePos + Changes[i - 1].CurrentLinePrefix.size();
|
|
|
+ }
|
|
|
|
|
|
// If there are multiple changes in this token, sum up all the changes until
|
|
|
// the end of the line.
|