Skip to content

Commit 0cfc56e

Browse files
authored
[SourceKit] If diagnostics are 'stale' for a particular snapshot then ignore them and only return the syntactic parser diagnostics (#10388)
This makes sure that diagnostics returned for a particular state of source buffer are consistent and accurate. rdar://32769873
1 parent 531c2e8 commit 0cfc56e

File tree

12 files changed

+335
-189
lines changed

12 files changed

+335
-189
lines changed

test/SourceKit/CursorInfo/rdar_18677108-2.swift.response

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
key.filepath: rdar_18677108-2-a.swift,
66
key.severity: source.diagnostic.severity.error,
77
key.description: "expected ')' in expression list",
8-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
8+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
99
key.diagnostics: [
1010
{
1111
key.line: 5,
@@ -22,7 +22,7 @@
2222
key.filepath: rdar_18677108-2-a.swift,
2323
key.severity: source.diagnostic.severity.error,
2424
key.description: "expected '}' at end of brace statement",
25-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
25+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
2626
key.diagnostics: [
2727
{
2828
key.line: 4,
@@ -39,7 +39,7 @@
3939
key.filepath: rdar_18677108-2-a.swift,
4040
key.severity: source.diagnostic.severity.error,
4141
key.description: "expected '}' in class",
42-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
42+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
4343
key.diagnostics: [
4444
{
4545
key.line: 2,

test/SourceKit/Sema/sema_diag_after_edit_fixit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ let a = 0; let b = 0 }; unresolved
44
// Test that offsets of diagnostic ranges and fixits get updated correctly after the edit request
55

66
// RUN: %sourcekitd-test -req=open %s -- %s == -req=print-diags %s \
7-
// RUN: == -req=edit -pos=2:1 -replace="_" -length=5 %s -print-raw-response \
7+
// RUN: == -req=edit -pos=2:1 -replace="_" -length=5 %s == -req=print-diags %s \
88
// RUN: | %FileCheck %s
99

1010
// CHECK: key.line: 2,

test/SourceKit/Sema/sema_playground.swift.response

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
key.filepath: sema_playground.swift,
1313
key.severity: source.diagnostic.severity.error,
1414
key.description: "expected numeric value following '$'",
15-
key.diagnostic_stage: source.diagnostic.stage.swift.parse
15+
key.diagnostic_stage: source.diagnostic.stage.swift.sema
1616
}
1717
]

test/SourceKit/SyntaxMapData/diags.swift.response

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
key.filepath: parse_error.swift,
77
key.severity: source.diagnostic.severity.error,
88
key.description: "expected '(' in argument list of function declaration",
9-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
9+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
1010
key.fixits: [
1111
{
1212
key.offset: 26,
@@ -37,7 +37,7 @@
3737
key.filepath: parse_error.swift,
3838
key.severity: source.diagnostic.severity.error,
3939
key.description: "expected '(' in argument list of function declaration",
40-
key.diagnostic_stage: source.diagnostic.stage.swift.parse,
40+
key.diagnostic_stage: source.diagnostic.stage.swift.sema,
4141
key.fixits: [
4242
{
4343
key.offset: 29,

tools/SourceKit/include/SourceKit/Core/Context.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class Context {
3535
public:
3636
Context(StringRef RuntimeLibPath,
3737
llvm::function_ref<
38-
std::unique_ptr<LangSupport>(Context &)> LangSupportFactoryFn);
38+
std::unique_ptr<LangSupport>(Context &)> LangSupportFactoryFn,
39+
bool shouldDispatchNotificationsOnMain = true);
3940
~Context();
4041

4142
StringRef getRuntimeLibPath() const { return RuntimeLibPath; }

tools/SourceKit/include/SourceKit/Core/NotificationCenter.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define LLVM_SOURCEKIT_CORE_NOTIFICATIONCENTER_H
1515

1616
#include "SourceKit/Core/LLVM.h"
17+
#include "llvm/Support/Mutex.h"
1718
#include <functional>
1819
#include <vector>
1920

@@ -23,9 +24,14 @@ typedef std::function<void(StringRef DocumentName)>
2324
DocumentUpdateNotificationReceiver;
2425

2526
class NotificationCenter {
27+
bool DispatchToMain;
2628
std::vector<DocumentUpdateNotificationReceiver> DocUpdReceivers;
29+
mutable llvm::sys::Mutex Mtx;
2730

2831
public:
32+
explicit NotificationCenter(bool dispatchToMain);
33+
~NotificationCenter();
34+
2935
void addDocumentUpdateNotificationReceiver(
3036
DocumentUpdateNotificationReceiver Receiver);
3137

tools/SourceKit/lib/Core/Context.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ using namespace SourceKit;
1818

1919
SourceKit::Context::Context(StringRef RuntimeLibPath,
2020
llvm::function_ref<std::unique_ptr<LangSupport>(Context &)>
21-
LangSupportFactoryFn) : RuntimeLibPath(RuntimeLibPath),
22-
NotificationCtr(new NotificationCenter()) {
21+
LangSupportFactoryFn,
22+
bool shouldDispatchNotificationsOnMain) : RuntimeLibPath(RuntimeLibPath),
23+
NotificationCtr(new NotificationCenter(shouldDispatchNotificationsOnMain)) {
2324
// Should be called last after everything is initialized.
2425
SwiftLang = LangSupportFactoryFn(*this);
2526
}

tools/SourceKit/lib/Core/NotificationCenter.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,33 @@
1515

1616
using namespace SourceKit;
1717

18+
NotificationCenter::NotificationCenter(bool dispatchToMain)
19+
: DispatchToMain(dispatchToMain) {
20+
}
21+
NotificationCenter::~NotificationCenter() {}
22+
1823
void NotificationCenter::addDocumentUpdateNotificationReceiver(
1924
DocumentUpdateNotificationReceiver Receiver) {
2025

21-
WorkQueue::dispatchOnMain([this, Receiver]{
22-
DocUpdReceivers.push_back(Receiver);
23-
});
26+
llvm::sys::ScopedLock L(Mtx);
27+
DocUpdReceivers.push_back(Receiver);
2428
}
2529

2630
void NotificationCenter::postDocumentUpdateNotification(
2731
StringRef DocumentName) const {
28-
29-
std::string DocName = DocumentName;
30-
WorkQueue::dispatchOnMain([this, DocName]{
31-
for (auto &Fn : DocUpdReceivers)
32-
Fn(DocName);
33-
});
32+
33+
std::vector<DocumentUpdateNotificationReceiver> recvs;
34+
{
35+
llvm::sys::ScopedLock L(Mtx);
36+
recvs = DocUpdReceivers;
37+
}
38+
std::string docName = DocumentName;
39+
auto sendNote = [recvs, docName]{
40+
for (auto &Fn : recvs)
41+
Fn(docName);
42+
};
43+
if (DispatchToMain)
44+
WorkQueue::dispatchOnMain(sendNote);
45+
else
46+
sendNote();
3447
}

0 commit comments

Comments
 (0)