Skip to content

Commit 0cc35b2

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 5053380 commit 0cc35b2

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
@@ -660,7 +660,7 @@ class SwiftDocumentSemanticInfo :
660660
}
661661

662662
private:
663-
std::vector<SwiftSemanticToken> takeSemanticTokens(
663+
std::vector<SwiftSemanticToken> getSemanticTokens(
664664
ImmutableTextSnapshotRef NewSnapshot);
665665

666666
Optional<std::vector<DiagnosticEntryInfo>> getSemanticDiagnostics(
@@ -763,26 +763,28 @@ void SwiftDocumentSemanticInfo::readSemanticInfo(
763763

764764
llvm::sys::ScopedLock L(Mtx);
765765

766-
Tokens = takeSemanticTokens(NewSnapshot);
766+
Tokens = getSemanticTokens(NewSnapshot);
767767
Diags = getSemanticDiagnostics(NewSnapshot, ParserDiags);
768768
}
769769

770770
std::vector<SwiftSemanticToken>
771-
SwiftDocumentSemanticInfo::takeSemanticTokens(
771+
SwiftDocumentSemanticInfo::getSemanticTokens(
772772
ImmutableTextSnapshotRef NewSnapshot) {
773773

774774
llvm::sys::ScopedLock L(Mtx);
775775

776776
if (SemaToks.empty())
777777
return {};
778778

779+
auto result = SemaToks;
780+
779781
// Adjust the position of the tokens.
780782
TokSnapshot->foreachReplaceUntil(NewSnapshot,
781783
[&](ReplaceImmutableTextUpdateRef Upd) -> bool {
782-
if (SemaToks.empty())
784+
if (result.empty())
783785
return false;
784786

785-
auto ReplaceBegin = std::lower_bound(SemaToks.begin(), SemaToks.end(),
787+
auto ReplaceBegin = std::lower_bound(result.begin(), result.end(),
786788
Upd->getByteOffset(),
787789
[&](const SwiftSemanticToken &Tok, unsigned StartOffset) -> bool {
788790
return Tok.ByteOffset+Tok.Length < StartOffset;
@@ -792,7 +794,7 @@ SwiftDocumentSemanticInfo::takeSemanticTokens(
792794
if (Upd->getLength() == 0) {
793795
ReplaceEnd = ReplaceBegin;
794796
} else {
795-
ReplaceEnd = std::upper_bound(ReplaceBegin, SemaToks.end(),
797+
ReplaceEnd = std::upper_bound(ReplaceBegin, result.end(),
796798
Upd->getByteOffset() + Upd->getLength(),
797799
[&](unsigned EndOffset, const SwiftSemanticToken &Tok) -> bool {
798800
return EndOffset < Tok.ByteOffset;
@@ -803,14 +805,14 @@ SwiftDocumentSemanticInfo::takeSemanticTokens(
803805
int Delta = InsertLen - Upd->getLength();
804806
if (Delta != 0) {
805807
for (std::vector<SwiftSemanticToken>::iterator
806-
I = ReplaceEnd, E = SemaToks.end(); I != E; ++I)
808+
I = ReplaceEnd, E = result.end(); I != E; ++I)
807809
I->ByteOffset += Delta;
808810
}
809-
SemaToks.erase(ReplaceBegin, ReplaceEnd);
811+
result.erase(ReplaceBegin, ReplaceEnd);
810812
return true;
811813
});
812814

813-
return std::move(SemaToks);
815+
return result;
814816
}
815817

816818
Optional<std::vector<DiagnosticEntryInfo>>

0 commit comments

Comments
 (0)