Skip to content

Commit a86eacc

Browse files
committed
[sourcekit] Retain semantic annotations across queries
Do not remove semantic annotations, so that if a client sends multiple magic replacetext 0, 0, "" requests they will all return the same result. This makes sourcekitd more robust around providing semantic highlighting if the editor may make multiple queries for document update. rdar://64904029
1 parent 5c27465 commit a86eacc

File tree

3 files changed

+87
-9
lines changed

3 files changed

+87
-9
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func foo() {}
2+
foo()
3+
4+
// RUN: %sourcekitd-test -req=open %s -- %s \
5+
// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \
6+
// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \
7+
// RUN: == -req=edit -pos=3:1 -replace="foo()" -length=0 %s \
8+
// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \
9+
// RUN: == -req=edit -offset=0 -replace="" -length=0 %s > %t.response
10+
// RUN: diff -u %s.response %t.response
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
key.annotations: [
3+
{
4+
key.kind: source.lang.swift.ref.function.free,
5+
key.offset: 14,
6+
key.length: 3
7+
}
8+
],
9+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
10+
key.syntaxmap: [
11+
],
12+
key.substructure: [
13+
]
14+
}
15+
{
16+
key.annotations: [
17+
{
18+
key.kind: source.lang.swift.ref.function.free,
19+
key.offset: 14,
20+
key.length: 3
21+
}
22+
],
23+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
24+
key.syntaxmap: [
25+
],
26+
key.substructure: [
27+
]
28+
}
29+
{
30+
key.annotations: [
31+
{
32+
key.kind: source.lang.swift.ref.function.free,
33+
key.offset: 14,
34+
key.length: 3
35+
},
36+
{
37+
key.kind: source.lang.swift.ref.function.free,
38+
key.offset: 20,
39+
key.length: 3
40+
}
41+
],
42+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
43+
key.syntaxmap: [
44+
],
45+
key.substructure: [
46+
]
47+
}
48+
{
49+
key.annotations: [
50+
{
51+
key.kind: source.lang.swift.ref.function.free,
52+
key.offset: 14,
53+
key.length: 3
54+
},
55+
{
56+
key.kind: source.lang.swift.ref.function.free,
57+
key.offset: 20,
58+
key.length: 3
59+
}
60+
],
61+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
62+
key.syntaxmap: [
63+
],
64+
key.substructure: [
65+
]
66+
}

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ class SwiftDocumentSemanticInfo :
659659
}
660660

661661
private:
662-
std::vector<SwiftSemanticToken> takeSemanticTokens(
662+
std::vector<SwiftSemanticToken> getSemanticTokens(
663663
ImmutableTextSnapshotRef NewSnapshot);
664664

665665
Optional<std::vector<DiagnosticEntryInfo>> getSemanticDiagnostics(
@@ -760,26 +760,28 @@ void SwiftDocumentSemanticInfo::readSemanticInfo(
760760

761761
llvm::sys::ScopedLock L(Mtx);
762762

763-
Tokens = takeSemanticTokens(NewSnapshot);
763+
Tokens = getSemanticTokens(NewSnapshot);
764764
Diags = getSemanticDiagnostics(NewSnapshot, ParserDiags);
765765
}
766766

767767
std::vector<SwiftSemanticToken>
768-
SwiftDocumentSemanticInfo::takeSemanticTokens(
768+
SwiftDocumentSemanticInfo::getSemanticTokens(
769769
ImmutableTextSnapshotRef NewSnapshot) {
770770

771771
llvm::sys::ScopedLock L(Mtx);
772772

773773
if (SemaToks.empty())
774774
return {};
775775

776+
auto result = SemaToks;
777+
776778
// Adjust the position of the tokens.
777779
TokSnapshot->foreachReplaceUntil(NewSnapshot,
778780
[&](ReplaceImmutableTextUpdateRef Upd) -> bool {
779-
if (SemaToks.empty())
781+
if (result.empty())
780782
return false;
781783

782-
auto ReplaceBegin = std::lower_bound(SemaToks.begin(), SemaToks.end(),
784+
auto ReplaceBegin = std::lower_bound(result.begin(), result.end(),
783785
Upd->getByteOffset(),
784786
[&](const SwiftSemanticToken &Tok, unsigned StartOffset) -> bool {
785787
return Tok.ByteOffset+Tok.Length < StartOffset;
@@ -789,7 +791,7 @@ SwiftDocumentSemanticInfo::takeSemanticTokens(
789791
if (Upd->getLength() == 0) {
790792
ReplaceEnd = ReplaceBegin;
791793
} else {
792-
ReplaceEnd = std::upper_bound(ReplaceBegin, SemaToks.end(),
794+
ReplaceEnd = std::upper_bound(ReplaceBegin, result.end(),
793795
Upd->getByteOffset() + Upd->getLength(),
794796
[&](unsigned EndOffset, const SwiftSemanticToken &Tok) -> bool {
795797
return EndOffset < Tok.ByteOffset;
@@ -800,14 +802,14 @@ SwiftDocumentSemanticInfo::takeSemanticTokens(
800802
int Delta = InsertLen - Upd->getLength();
801803
if (Delta != 0) {
802804
for (std::vector<SwiftSemanticToken>::iterator
803-
I = ReplaceEnd, E = SemaToks.end(); I != E; ++I)
805+
I = ReplaceEnd, E = result.end(); I != E; ++I)
804806
I->ByteOffset += Delta;
805807
}
806-
SemaToks.erase(ReplaceBegin, ReplaceEnd);
808+
result.erase(ReplaceBegin, ReplaceEnd);
807809
return true;
808810
});
809811

810-
return std::move(SemaToks);
812+
return result;
811813
}
812814

813815
Optional<std::vector<DiagnosticEntryInfo>>

0 commit comments

Comments
 (0)