mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
"""
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
@@ -1,4 +0,0 @@
|
||||
let x = /*
|
||||
|
||||
*/
|
||||
func foo() {}
|
||||
@@ -1,12 +0,0 @@
|
||||
let a = "value"
|
||||
let x = """
|
||||
|
||||
\(
|
||||
a
|
||||
)
|
||||
|
||||
|
||||
|
||||
func foo () -> String {
|
||||
return "foo"
|
||||
}
|
||||
@@ -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: ],
|
||||
|
||||
@@ -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: ],
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user