Revert "[SyntaxColor] Improve highligting of multiline strings"

This reverts commit 86d0fc37bc.
This was causing a performance regression.

Resolves rdar://problem/32434045
This commit is contained in:
Nathan Hawes
2017-05-26 16:46:03 -07:00
parent e43084cb50
commit e5426ecfa5
9 changed files with 81 additions and 435 deletions

View File

@@ -81,11 +81,6 @@ public:
else if (Line >= StartLine + Length) {
Length = Line - StartLine + 1;
}
else if (Line < StartLine) {
unsigned Delta = StartLine - Line;
StartLine -= Delta;
Length += Delta;
}
}
};

View File

@@ -206,13 +206,6 @@ SyntaxModelContext::SyntaxModelContext(SourceFile &SrcFile)
break;
}
case tok::unknown:
if (Tok.getText().startswith("\"")) {
// invalid string literal
Kind = SyntaxNodeKind::String;
break;
}
continue;
default:
continue;
}

View File

@@ -227,15 +227,6 @@ func f(x: Int) -> Int {
// CHECK: <str>"This is string </str>\<anchor>(</anchor>genFn({(a:<type>Int</type> -> <type>Int</type>) <kw>in</kw> a})<anchor>)</anchor><str> interpolation"</str>
"This is string \(genFn({(a:Int -> Int) in a})) interpolation"
// CHECK: <str>"This is unterminated</str>
"This is unterminated
// CHECK: <str>"This in unterminated with ignored \( "interpolation" ) in it</str>
"This in unterminated with ignored \( "interpolation" ) in it
// CHECK: <str>"This is terminated with \( invalid interpolation" + "in it"</str>
"This is terminated with \( invalid interpolation" + "in it"
// CHECK: <str>"""
// CHECK-NEXT: This is a multiline string.
// CHECK-NEXT: """</str>
@@ -245,15 +236,9 @@ func f(x: Int) -> Int {
// CHECK: <str>"""
// CHECK-NEXT: This is a multiline</str>\<anchor>(</anchor> <str>"interpolated"</str> <anchor>)</anchor><str>string
// CHECK-NEXT: </str>\<anchor>(</anchor>
// CHECK-NEXT: <str>"inner"</str>
// CHECK-NEXT: <anchor>)</anchor><str>
// CHECK-NEXT: """</str>
"""
This is a multiline\( "interpolated" )string
\(
"inner"
)
"""
}

View File

@@ -1,17 +0,0 @@
// RUN: %target-swift-ide-test -syntax-coloring -source-filename %s | %FileCheck %s
// RUN: %target-swift-ide-test -syntax-coloring -typecheck -source-filename %s | %FileCheck %s
// XFAIL: broken_std_regex
// CHECK: <kw>let</kw> x = <str>"""
// CHECK-NEXT: This is an unterminated
// CHECK-NEXT: \( "multiline" )
// CHECK-NEXT: string followed by code
// CHECK-NEXT: ""
// CHECK-NEXT: func foo() {}
// CHECK-NEXT: </str>
let x = """
This is an unterminated
\( "multiline" )
string followed by code
""
func foo() {}

View File

@@ -1,4 +0,0 @@
let x = /*
*/
func foo() {}

View File

@@ -1,12 +0,0 @@
let a = "value"
let x = """
\(
a
)
func foo () -> String {
return "foo"
}

View File

@@ -1,69 +0,0 @@
// RUN: %sourcekitd-test -req=open -print-raw-response %S/Inputs/syntaxmap-edit-block-comment.swift == -req=edit -print-raw-response %S/Inputs/syntaxmap-edit-block-comment.swift -pos=3:2 -replace=" " -length=1 == -req=edit -print-raw-response %S/Inputs/syntaxmap-edit-block-comment.swift -pos=3:2 -replace="/" -length=1 | %sed_clean > %t.response
// RUN: %FileCheck -input-file=%t.response %s
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 0,
// CHECK-NEXT: key.length: 29,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 0,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 4,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.comment,
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 15,
// CHECK-NEXT: key.length: 4
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 20,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 21,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.comment,
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 21
// CHECK-NEXT: }
// CHECK-NEXT: ],
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 21,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.comment,
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 15,
// CHECK-NEXT: key.length: 4
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 20,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: }
// CHECK-NEXT: ],

View File

@@ -1,154 +0,0 @@
// RUN: %sourcekitd-test -req=open -print-raw-response %S/Inputs/syntaxmap-edit-multiline-string.swift == -req=edit -print-raw-response %S/Inputs/syntaxmap-edit-multiline-string.swift -pos=8:1 -replace='"""' -length=3 == -req=edit -print-raw-response %S/Inputs/syntaxmap-edit-multiline-string.swift -pos=6:2 -replace=')' -length=1 == -req=edit -print-raw-response %S/Inputs/syntaxmap-edit-multiline-string.swift -pos=2:10 -replace=' ' -length=1 | %sed_clean > %t.response
// RUN: %FileCheck -input-file=%t.response %s
// Original file contents
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 0,
// CHECK-NEXT: key.length: 84,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 0,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 4,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 8,
// CHECK-NEXT: key.length: 7
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 16,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 20,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 24,
// CHECK-NEXT: key.length: 60
// CHECK-NEXT: }
// CHECK-NEXT: ],
// After terminating the multiline string
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 24,
// CHECK-NEXT: key.length: 60,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 24,
// CHECK-NEXT: key.length: 5
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string_interpolation_anchor,
// CHECK-NEXT: key.offset: 30,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 32,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string_interpolation_anchor,
// CHECK-NEXT: key.offset: 34,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 35,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 43,
// CHECK-NEXT: key.length: 4
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 48,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.typeidentifier,
// CHECK-NEXT: key.offset: 58,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 69,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 76,
// CHECK-NEXT: key.length: 5
// CHECK-NEXT: }
// CHECK-NEXT: ],
// After adding a character after the interpolation
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 34,
// CHECK-NEXT: key.length: 9,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string_interpolation_anchor,
// CHECK-NEXT: key.offset: 34,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 35,
// CHECK-NEXT: key.length: 6
// CHECK-NEXT: }
// CHECK-NEXT: ],
// After replacing the middle opening quote with a space
// CHECK: {{^}}{
// CHECK-NEXT: key.offset: 16,
// CHECK-NEXT: key.length: 68,
// CHECK-NEXT: key.diagnostic_stage: source.diagnostic.stage.swift.parse,
// CHECK-NEXT: key.syntaxmap: [
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.keyword,
// CHECK-NEXT: key.offset: 16,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 20,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 24,
// CHECK-NEXT: key.length: 3
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.identifier,
// CHECK-NEXT: key.offset: 32,
// CHECK-NEXT: key.length: 1
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: key.kind: source.lang.swift.syntaxtype.string,
// CHECK-NEXT: key.offset: 38,
// CHECK-NEXT: key.length: 46
// CHECK-NEXT: }
// CHECK-NEXT: ],

View File

@@ -293,20 +293,6 @@ public:
return false;
}
bool matchesAnyTokenOnLine(unsigned Line, const SwiftSyntaxToken &Token) const {
assert(Line > 0);
if (Lines.size() < Line)
return false;
unsigned LineOffset = Line - 1;
for (auto &Tok: Lines[LineOffset]) {
if (Tok.Column == Token.Column && Tok.Length == Token.Length
&& Tok.Kind == Token.Kind)
return true;
}
return false;
}
void addTokenForLine(unsigned Line, const SwiftSyntaxToken &Token) {
assert(Line > 0);
if (Lines.size() < Line) {
@@ -346,17 +332,12 @@ public:
}
}
void clearLineRange(unsigned StartLine, unsigned EndLine, unsigned StartColumn = 0) {
assert (StartLine > 0 && EndLine >= StartLine);
auto LineIndex = StartLine - 1;
if (StartColumn > 0) {
auto &LineToks = Lines[LineIndex++];
while (!LineToks.empty() && LineToks.back().Column >= StartColumn)
LineToks.pop_back();
}
for (; LineIndex < Lines.size() && LineIndex < EndLine; ++LineIndex) {
Lines[LineIndex].clear();
void clearLineRange(unsigned StartLine, unsigned Length) {
assert(StartLine > 0);
unsigned LineOffset = StartLine - 1;
for (unsigned Line = LineOffset; Line < LineOffset + Length
&& Line < Lines.size(); ++Line) {
Lines[Line].clear();
}
}
@@ -1251,79 +1232,15 @@ public:
};
class SwiftEditorSyntaxWalker: public ide::SyntaxModelWalker {
struct RangeToken : SwiftSyntaxToken {
unsigned Line;
unsigned EndLine;
unsigned Offset;
RangeToken(SyntaxNodeKind Kind, unsigned Offset, unsigned Length,
unsigned Line, unsigned Column, unsigned EndLine) :
SwiftSyntaxToken(Column, Length, Kind), Line(Line), EndLine(EndLine),
Offset(Offset) {}
};
SwiftSyntaxMap &SyntaxMap;
LineRange EditedLineRange;
SwiftEditorCharRange &AffectedRange;
unsigned OrigAffectedRangeEnd;
SourceManager &SrcManager;
EditorConsumer &Consumer;
unsigned BufferID;
SwiftDocumentStructureWalker DocStructureWalker;
std::vector<EditorConsumerSyntaxMapEntry> ConsumerSyntaxMap;
std::vector<RangeToken> QueuedTokens;
unsigned NestingLevel = 0;
RangeToken getToken(SyntaxNode Node) {
SourceLoc StartLoc = Node.Range.getStart();
auto StartLineAndColumn = SrcManager.getLineAndColumn(StartLoc);
auto EndLineAndColumn = SrcManager.getLineAndColumn(Node.Range.getEnd());
auto EndLine = EndLineAndColumn.first;
if (EndLineAndColumn.second == 1) {
--EndLine;
}
return {
Node.Kind,
/*Offset=*/ SrcManager.getLocOffsetInBuffer(StartLoc, BufferID),
/*Length=*/ Node.Range.getByteLength(),
/*Line=*/ StartLineAndColumn.first,
/*Column=*/ StartLineAndColumn.second,
EndLine
};
}
void addSyntaxMapEntry(const RangeToken Token) {
if (NestingLevel > 1) {
SyntaxMap.mergeTokenForLine(Token.Line, Token);
} else {
SyntaxMap.addTokenForLine(Token.Line, Token);
}
UIdent Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Token.Kind);
if (NestingLevel > 1) {
assert(!ConsumerSyntaxMap.empty());
auto &Last = ConsumerSyntaxMap.back();
mergeSplitRanges(Last.Offset, Last.Length, Token.Offset, Token.Length,
[&](unsigned BeforeOff, unsigned BeforeLen,
unsigned AfterOff, unsigned AfterLen) {
auto LastKind = Last.Kind;
ConsumerSyntaxMap.pop_back();
if (BeforeLen)
ConsumerSyntaxMap.emplace_back(BeforeOff, BeforeLen,
LastKind);
ConsumerSyntaxMap.emplace_back(Token.Offset,
Token.Length, Kind);
if (AfterLen)
ConsumerSyntaxMap.emplace_back(AfterOff, AfterLen,
LastKind);
});
} else {
ConsumerSyntaxMap.emplace_back(Token.Offset, Token.Length, Kind);
}
}
public:
SwiftEditorSyntaxWalker(SwiftSyntaxMap &SyntaxMap,
LineRange EditedLineRange,
@@ -1331,9 +1248,8 @@ public:
SourceManager &SrcManager, EditorConsumer &Consumer,
unsigned BufferID)
: SyntaxMap(SyntaxMap), EditedLineRange(EditedLineRange),
AffectedRange(AffectedRange),
OrigAffectedRangeEnd(AffectedRange.first + AffectedRange.second),
SrcManager(SrcManager), Consumer(Consumer), BufferID(BufferID),
AffectedRange(AffectedRange), SrcManager(SrcManager), Consumer(Consumer),
BufferID(BufferID),
DocStructureWalker(SrcManager, BufferID, Consumer) { }
bool walkToNodePre(SyntaxNode Node) override {
@@ -1341,83 +1257,96 @@ public:
return DocStructureWalker.walkToNodePre(Node);
++NestingLevel;
RangeToken Token = getToken(Node);
SourceLoc StartLoc = Node.Range.getStart();
auto StartLineAndColumn = SrcManager.getLineAndColumn(StartLoc);
auto EndLineAndColumn = SrcManager.getLineAndColumn(Node.Range.getEnd());
unsigned StartLine = StartLineAndColumn.first;
unsigned EndLine = EndLineAndColumn.second > 1 ? EndLineAndColumn.first
: EndLineAndColumn.first - 1;
unsigned Offset = SrcManager.getByteDistance(
SrcManager.getLocForBufferStart(BufferID), StartLoc);
// Note that the length can span multiple lines.
unsigned Length = Node.Range.getByteLength();
SwiftSyntaxToken Token(StartLineAndColumn.second, Length,
Node.Kind);
if (EditedLineRange.isValid()) {
if (Token.Line < EditedLineRange.startLine()) {
if (Token.EndLine < EditedLineRange.startLine()
&& SyntaxMap.matchesAnyTokenOnLine(Token.Line, Token)) {
// 1: We start before the edited range and we have this token already
// so don't process or report it.
if (StartLine < EditedLineRange.startLine()) {
if (EndLine < EditedLineRange.startLine()) {
// We're entirely before the edited range, no update needed.
return true;
}
// 2: The edit was inside this token, or made it appear (e.g. tokens
// inside a multiline string interpolation when the string is
// closed). Extend the edited range to include it, clear out the old
// syntax map entries, and update the the affected range to start
// here.
EditedLineRange.extendToIncludeLine(Token.Line);
EditedLineRange.extendToIncludeLine(Token.EndLine);
SyntaxMap.clearLineRange(Token.Line, EditedLineRange.endLine(), Token.Column);
// This token starts before the edited range, but doesn't end before it,
// we need to adjust edited line range and clear the affected syntax map
// line range.
unsigned AdjLineCount = EditedLineRange.startLine() - StartLine;
EditedLineRange.setRange(StartLine, AdjLineCount
+ EditedLineRange.lineCount());
SyntaxMap.clearLineRange(StartLine, AdjLineCount);
// Bring the start of the affected range back to this offset
unsigned AdjCharCount = AffectedRange.first - Token.Offset;
// Also adjust the affected char range accordingly.
unsigned AdjCharCount = AffectedRange.first - Offset;
AffectedRange.first -= AdjCharCount;
AffectedRange.second += AdjCharCount;
}
else if (Token.Offset > AffectedRange.first + AffectedRange.second) {
// 4: We're after the Edited range and affected range. Check we're still
// in sync.
if (SyntaxMap.matchesAnyTokenOnLine(Token.Line, Token)) {
// 4a: We're in sync. No need to process the token now, but we may
// still need to later if we see differences. That can happen if
// the edit restored the opening quotes of a multiline string
// literal and this token is in an interpolation this token is
// in sync, but there will be a new string token later.
QueuedTokens.push_back(Token);
else if (Offset > AffectedRange.first + AffectedRange.second) {
// We're passed the affected range and already synced up, just return.
return true;
}
// 4b: We're out of sync again. Process any tokens we queued up,
// clearing out the existing syntax map tokens before hand and
// restore the end of the affected range back to its original state
// (the end of the buffer).
auto &FromToken = QueuedTokens.empty() ? Token : QueuedTokens.front();
EditedLineRange.extendToIncludeLine(Token.EndLine);
SyntaxMap.clearLineRange(FromToken.Line, Token.EndLine);
for (auto &QueuedToken: QueuedTokens)
addSyntaxMapEntry(QueuedToken);
AffectedRange.second = OrigAffectedRangeEnd - AffectedRange.first;
}
else if (Token.Line > EditedLineRange.endLine()) {
// 3: We're after the edited line range but not the affected range,
// check if we're in sync.
if (SyntaxMap.matchesFirstTokenOnLine(Token.Line, Token)) {
// 3a: We're synced up so don't process or report this token.
// Tentatively update the end of the affected range and queue the
// token in case we fall out of sync again later.
else if (StartLine > EditedLineRange.endLine()) {
// We're after the edited line range, let's test if we're synced up.
if (SyntaxMap.matchesFirstTokenOnLine(StartLine, Token)) {
// We're synced up, mark the affected range and return.
AffectedRange.second =
Token.Offset - (Token.Column - 1) - AffectedRange.first;
QueuedTokens.push_back(Token);
Offset - (StartLineAndColumn.second - 1) - AffectedRange.first;
return true;
}
// 3b: We're not synced up, continue replacing syntax map data on
// this line.
EditedLineRange.extendToIncludeLine(Token.EndLine);
SyntaxMap.clearLineRange(Token.Line, Token.EndLine);
}
else if (Token.EndLine > Token.Line) {
// We're in the edited range and this token spans multiple lines. Make
// sure to replace syntax map data for the affected lines.
EditedLineRange.extendToIncludeLine(Token.EndLine);
SyntaxMap.clearLineRange(Token.Line, Token.EndLine, Token.Column);
}
// We're not synced up, continue replacing syntax map data on this line.
SyntaxMap.clearLineRange(StartLine, 1);
EditedLineRange.extendToIncludeLine(StartLine);
}
addSyntaxMapEntry(std::move(Token));
if (EndLine > StartLine) {
// The token spans multiple lines, make sure to replace syntax map data
// for affected lines.
EditedLineRange.extendToIncludeLine(EndLine);
unsigned LineCount = EndLine - StartLine + 1;
SyntaxMap.clearLineRange(StartLine, LineCount);
}
}
// Add the syntax map token.
if (NestingLevel > 1)
SyntaxMap.mergeTokenForLine(StartLine, Token);
else
SyntaxMap.addTokenForLine(StartLine, Token);
// Add consumer entry.
unsigned ByteOffset = SrcManager.getLocOffsetInBuffer(Node.Range.getStart(),
BufferID);
UIdent Kind = SwiftLangSupport::getUIDForSyntaxNodeKind(Node.Kind);
if (NestingLevel > 1) {
assert(!ConsumerSyntaxMap.empty());
auto &Last = ConsumerSyntaxMap.back();
mergeSplitRanges(Last.Offset, Last.Length, ByteOffset, Length,
[&](unsigned BeforeOff, unsigned BeforeLen,
unsigned AfterOff, unsigned AfterLen) {
auto LastKind = Last.Kind;
ConsumerSyntaxMap.pop_back();
if (BeforeLen)
ConsumerSyntaxMap.emplace_back(BeforeOff, BeforeLen, LastKind);
ConsumerSyntaxMap.emplace_back(ByteOffset, Length, Kind);
if (AfterLen)
ConsumerSyntaxMap.emplace_back(AfterOff, AfterLen, LastKind);
});
}
else
ConsumerSyntaxMap.emplace_back(ByteOffset, Length, Kind);
return true;
}