From a86eaccdf24a41f5e3af4a74be95a30ca6d0dbaf Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 30 Jun 2020 13:47:48 -0700 Subject: [PATCH 1/2] [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 --- .../Sema/sema_annotations_saved.swift | 10 +++ .../sema_annotations_saved.swift.response | 66 +++++++++++++++++++ tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp | 20 +++--- 3 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 test/SourceKit/Sema/sema_annotations_saved.swift create mode 100644 test/SourceKit/Sema/sema_annotations_saved.swift.response diff --git a/test/SourceKit/Sema/sema_annotations_saved.swift b/test/SourceKit/Sema/sema_annotations_saved.swift new file mode 100644 index 0000000000000..bed64baf6e210 --- /dev/null +++ b/test/SourceKit/Sema/sema_annotations_saved.swift @@ -0,0 +1,10 @@ +func foo() {} +foo() + +// RUN: %sourcekitd-test -req=open %s -- %s \ +// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \ +// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \ +// RUN: == -req=edit -pos=3:1 -replace="foo()" -length=0 %s \ +// RUN: == -req=edit -offset=0 -replace="" -length=0 %s \ +// RUN: == -req=edit -offset=0 -replace="" -length=0 %s > %t.response +// RUN: diff -u %s.response %t.response diff --git a/test/SourceKit/Sema/sema_annotations_saved.swift.response b/test/SourceKit/Sema/sema_annotations_saved.swift.response new file mode 100644 index 0000000000000..300f041a04396 --- /dev/null +++ b/test/SourceKit/Sema/sema_annotations_saved.swift.response @@ -0,0 +1,66 @@ +{ + key.annotations: [ + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 14, + key.length: 3 + } + ], + key.diagnostic_stage: source.diagnostic.stage.swift.sema, + key.syntaxmap: [ + ], + key.substructure: [ + ] +} +{ + key.annotations: [ + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 14, + key.length: 3 + } + ], + key.diagnostic_stage: source.diagnostic.stage.swift.sema, + key.syntaxmap: [ + ], + key.substructure: [ + ] +} +{ + key.annotations: [ + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 14, + key.length: 3 + }, + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 20, + key.length: 3 + } + ], + key.diagnostic_stage: source.diagnostic.stage.swift.sema, + key.syntaxmap: [ + ], + key.substructure: [ + ] +} +{ + key.annotations: [ + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 14, + key.length: 3 + }, + { + key.kind: source.lang.swift.ref.function.free, + key.offset: 20, + key.length: 3 + } + ], + key.diagnostic_stage: source.diagnostic.stage.swift.sema, + key.syntaxmap: [ + ], + key.substructure: [ + ] +} diff --git a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp index 336417b300ecb..68943da63c200 100644 --- a/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp +++ b/tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp @@ -659,7 +659,7 @@ class SwiftDocumentSemanticInfo : } private: - std::vector takeSemanticTokens( + std::vector getSemanticTokens( ImmutableTextSnapshotRef NewSnapshot); Optional> getSemanticDiagnostics( @@ -760,12 +760,12 @@ void SwiftDocumentSemanticInfo::readSemanticInfo( llvm::sys::ScopedLock L(Mtx); - Tokens = takeSemanticTokens(NewSnapshot); + Tokens = getSemanticTokens(NewSnapshot); Diags = getSemanticDiagnostics(NewSnapshot, ParserDiags); } std::vector -SwiftDocumentSemanticInfo::takeSemanticTokens( +SwiftDocumentSemanticInfo::getSemanticTokens( ImmutableTextSnapshotRef NewSnapshot) { llvm::sys::ScopedLock L(Mtx); @@ -773,13 +773,15 @@ SwiftDocumentSemanticInfo::takeSemanticTokens( if (SemaToks.empty()) return {}; + auto result = SemaToks; + // Adjust the position of the tokens. TokSnapshot->foreachReplaceUntil(NewSnapshot, [&](ReplaceImmutableTextUpdateRef Upd) -> bool { - if (SemaToks.empty()) + if (result.empty()) return false; - auto ReplaceBegin = std::lower_bound(SemaToks.begin(), SemaToks.end(), + auto ReplaceBegin = std::lower_bound(result.begin(), result.end(), Upd->getByteOffset(), [&](const SwiftSemanticToken &Tok, unsigned StartOffset) -> bool { return Tok.ByteOffset+Tok.Length < StartOffset; @@ -789,7 +791,7 @@ SwiftDocumentSemanticInfo::takeSemanticTokens( if (Upd->getLength() == 0) { ReplaceEnd = ReplaceBegin; } else { - ReplaceEnd = std::upper_bound(ReplaceBegin, SemaToks.end(), + ReplaceEnd = std::upper_bound(ReplaceBegin, result.end(), Upd->getByteOffset() + Upd->getLength(), [&](unsigned EndOffset, const SwiftSemanticToken &Tok) -> bool { return EndOffset < Tok.ByteOffset; @@ -800,14 +802,14 @@ SwiftDocumentSemanticInfo::takeSemanticTokens( int Delta = InsertLen - Upd->getLength(); if (Delta != 0) { for (std::vector::iterator - I = ReplaceEnd, E = SemaToks.end(); I != E; ++I) + I = ReplaceEnd, E = result.end(); I != E; ++I) I->ByteOffset += Delta; } - SemaToks.erase(ReplaceBegin, ReplaceEnd); + result.erase(ReplaceBegin, ReplaceEnd); return true; }); - return std::move(SemaToks); + return result; } Optional> From 223b5ed4e374b095ba7ac884730e3810d3e28581 Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 30 Jun 2020 16:08:32 -0700 Subject: [PATCH 2/2] [test] use %diff to fix Windows test --- test/SourceKit/Sema/sema_annotations_saved.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SourceKit/Sema/sema_annotations_saved.swift b/test/SourceKit/Sema/sema_annotations_saved.swift index bed64baf6e210..ac2269488d0aa 100644 --- a/test/SourceKit/Sema/sema_annotations_saved.swift +++ b/test/SourceKit/Sema/sema_annotations_saved.swift @@ -7,4 +7,4 @@ foo() // RUN: == -req=edit -pos=3:1 -replace="foo()" -length=0 %s \ // RUN: == -req=edit -offset=0 -replace="" -length=0 %s \ // RUN: == -req=edit -offset=0 -replace="" -length=0 %s > %t.response -// RUN: diff -u %s.response %t.response +// RUN: %diff -u %s.response %t.response