Skip to content

Commit 152370e

Browse files
committed
[sourcekit] Refactor notification handling layering
This refactors notification handling so that the XPC service and InProc library pass in their notification handler callback. This fixes a layering issue where the sourcekitd libraries could not be linked dynamically due to the missing symbols.
1 parent 4dab4c2 commit 152370e

File tree

8 files changed

+229
-108
lines changed

8 files changed

+229
-108
lines changed

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

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

1616
#include "SourceKit/Core/LLVM.h"
17+
#include "SourceKit/Support/Tracing.h"
18+
#include "SourceKit/Support/UIdent.h"
1719
#include "llvm/Support/Mutex.h"
1820
#include <functional>
1921
#include <vector>
2022

2123
namespace SourceKit {
2224

25+
struct DiagnosticEntryInfo;
26+
2327
typedef std::function<void(StringRef DocumentName)>
2428
DocumentUpdateNotificationReceiver;
2529

30+
typedef std::function<void(uint64_t CompileID, trace::OperationKind,
31+
const trace::SwiftInvocation &)>
32+
CompileWillStartNotificationReceiver;
33+
typedef std::function<void(uint64_t CompileID, trace::OperationKind,
34+
ArrayRef<DiagnosticEntryInfo>)>
35+
CompileDidFinishNotificationReceiver;
36+
2637
class NotificationCenter {
2738
bool DispatchToMain;
2839
std::vector<DocumentUpdateNotificationReceiver> DocUpdReceivers;
40+
std::vector<std::function<void(void)>> TestReceivers;
41+
std::vector<std::function<void(void)>> SemaEnabledReceivers;
42+
std::vector<CompileWillStartNotificationReceiver> CompileWillStartReceivers;
43+
std::vector<CompileDidFinishNotificationReceiver> CompileDidFinishReceivers;
2944
mutable llvm::sys::Mutex Mtx;
3045

3146
public:
@@ -34,8 +49,23 @@ class NotificationCenter {
3449

3550
void addDocumentUpdateNotificationReceiver(
3651
DocumentUpdateNotificationReceiver Receiver);
52+
void addTestNotificationReceiver(std::function<void(void)> Receiver);
53+
void addSemaEnabledNotificationReceiver(std::function<void(void)> Receiver);
54+
void addCompileWillStartNotificationReceiver(
55+
CompileWillStartNotificationReceiver Receiver);
56+
void addCompileDidFinishNotificationReceiver(
57+
CompileDidFinishNotificationReceiver Receiver);
3758

3859
void postDocumentUpdateNotification(StringRef DocumentName) const;
60+
void postTestNotification() const;
61+
void postSemaEnabledNotification() const;
62+
void
63+
postCompileWillStartNotification(uint64_t CompileID,
64+
trace::OperationKind OpKind,
65+
const trace::SwiftInvocation &Inv) const;
66+
void postCompileDidFinishNotification(
67+
uint64_t CompileID, trace::OperationKind OpKind,
68+
ArrayRef<DiagnosticEntryInfo> Diagnostics) const;
3969
};
4070

4171
} // namespace SourceKit

tools/SourceKit/lib/Core/NotificationCenter.cpp

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "SourceKit/Core/NotificationCenter.h"
14+
#include "SourceKit/Core/LangSupport.h"
1415
#include "SourceKit/Support/Concurrency.h"
1516

1617
using namespace SourceKit;
@@ -27,21 +28,64 @@ void NotificationCenter::addDocumentUpdateNotificationReceiver(
2728
DocUpdReceivers.push_back(Receiver);
2829
}
2930

31+
void NotificationCenter::addTestNotificationReceiver(
32+
std::function<void(void)> Receiver) {
33+
llvm::sys::ScopedLock L(Mtx);
34+
TestReceivers.push_back(std::move(Receiver));
35+
}
36+
void NotificationCenter::addSemaEnabledNotificationReceiver(
37+
std::function<void(void)> Receiver) {
38+
llvm::sys::ScopedLock L(Mtx);
39+
SemaEnabledReceivers.push_back(std::move(Receiver));
40+
}
41+
void NotificationCenter::addCompileWillStartNotificationReceiver(
42+
CompileWillStartNotificationReceiver Receiver) {
43+
llvm::sys::ScopedLock L(Mtx);
44+
CompileWillStartReceivers.push_back(std::move(Receiver));
45+
}
46+
void NotificationCenter::addCompileDidFinishNotificationReceiver(
47+
CompileDidFinishNotificationReceiver Receiver) {
48+
llvm::sys::ScopedLock L(Mtx);
49+
CompileDidFinishReceivers.push_back(std::move(Receiver));
50+
}
51+
52+
#define POST_NOTIFICATION(Receivers, Args...) \
53+
do { \
54+
decltype(Receivers) recvs; \
55+
{ \
56+
llvm::sys::ScopedLock L(Mtx); \
57+
recvs = Receivers; \
58+
} \
59+
auto sendNote = [=] { \
60+
for (auto &Fn : recvs) \
61+
Fn(Args); \
62+
}; \
63+
if (DispatchToMain) \
64+
WorkQueue::dispatchOnMain(sendNote); \
65+
else \
66+
sendNote(); \
67+
} while (0)
68+
3069
void NotificationCenter::postDocumentUpdateNotification(
3170
StringRef DocumentName) const {
32-
33-
std::vector<DocumentUpdateNotificationReceiver> recvs;
34-
{
35-
llvm::sys::ScopedLock L(Mtx);
36-
recvs = DocUpdReceivers;
37-
}
3871
std::string docName = DocumentName.str();
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();
72+
POST_NOTIFICATION(DocUpdReceivers, docName);
73+
}
74+
void NotificationCenter::postTestNotification() const {
75+
POST_NOTIFICATION(TestReceivers, );
76+
}
77+
void NotificationCenter::postSemaEnabledNotification() const {
78+
POST_NOTIFICATION(SemaEnabledReceivers, );
79+
}
80+
void NotificationCenter::postCompileWillStartNotification(
81+
uint64_t CompileID, trace::OperationKind OpKind,
82+
const trace::SwiftInvocation &Inv) const {
83+
trace::SwiftInvocation inv(Inv);
84+
POST_NOTIFICATION(CompileWillStartReceivers, CompileID, OpKind, inv);
85+
}
86+
void NotificationCenter::postCompileDidFinishNotification(
87+
uint64_t CompileID, trace::OperationKind OpKind,
88+
ArrayRef<DiagnosticEntryInfo> Diagnostics) const {
89+
std::vector<DiagnosticEntryInfo> diags(Diagnostics);
90+
POST_NOTIFICATION(CompileDidFinishReceivers, CompileID, OpKind, diags);
4791
}

tools/SourceKit/tools/sourcekitd/bin/InProc/sourcekitdInProc.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "sourcekitd/Internal.h"
1414

1515
#include "SourceKit/Support/Concurrency.h"
16+
#include "SourceKit/Support/Logging.h"
1617
#include "SourceKit/Support/UIdent.h"
1718

1819
#include "llvm/ADT/SmallString.h"
@@ -36,6 +37,8 @@ static llvm::sys::Mutex GlobalHandlersMtx;
3637
static sourcekitd_uid_handler_t UidMappingHandler;
3738
static sourcekitd_str_from_uid_handler_t StrFromUidMappingHandler;
3839

40+
static void postNotification(sourcekitd_response_t Notification);
41+
3942
void
4043
sourcekitd_set_uid_handler(sourcekitd_uid_handler_t handler) {
4144
llvm::sys::ScopedLock L(GlobalHandlersMtx);
@@ -106,20 +109,36 @@ static void getToolchainPrefixPath(llvm::SmallVectorImpl<char> &Path) {
106109
#endif
107110
}
108111

109-
std::string sourcekitd::getRuntimeLibPath() {
112+
static std::string getRuntimeLibPath() {
110113
llvm::SmallString<128> libPath;
111114
getToolchainPrefixPath(libPath);
112115
llvm::sys::path::append(libPath, "lib");
113116
return libPath.str().str();
114117
}
115118

116-
std::string sourcekitd::getDiagnosticDocumentationPath() {
119+
static std::string getDiagnosticDocumentationPath() {
117120
llvm::SmallString<128> docPath;
118121
getToolchainPrefixPath(docPath);
119122
llvm::sys::path::append(docPath, "share", "doc", "swift", "diagnostics");
120123
return docPath.str().str();
121124
}
122125

126+
void sourcekitd_initialize(void) {
127+
if (sourcekitd::initializeClient()) {
128+
LOG_INFO_FUNC(High, "initializing");
129+
sourcekitd::initializeService(getRuntimeLibPath(),
130+
getDiagnosticDocumentationPath(),
131+
postNotification);
132+
}
133+
}
134+
135+
void sourcekitd_shutdown(void) {
136+
if (sourcekitd::shutdownClient()) {
137+
LOG_INFO_FUNC(High, "shutting down");
138+
sourcekitd::shutdownService();
139+
}
140+
}
141+
123142
void sourcekitd::set_interrupted_connection_handler(
124143
llvm::function_ref<void()> handler) {
125144
}
@@ -179,7 +198,7 @@ sourcekitd_set_notification_handler(sourcekitd_response_receiver_t receiver) {
179198
});
180199
}
181200

182-
void sourcekitd::postNotification(sourcekitd_response_t Notification) {
201+
void postNotification(sourcekitd_response_t Notification) {
183202
WorkQueue::dispatchOnMain([=]{
184203
if (!NotificationReceiver) {
185204
sourcekitd_response_dispose(Notification);

tools/SourceKit/tools/sourcekitd/bin/XPC/Client/sourcekitd.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ static void handleInternalUIDRequest(xpc_object_t XVal,
240240

241241
static void handleInterruptedConnection(xpc_object_t event, xpc_connection_t conn);
242242

243-
void sourcekitd::initialize() {
243+
static void initializeXPCClient() {
244244
assert(!GlobalConn);
245245
GlobalConn = xpc_connection_create(SOURCEKIT_XPCSERVICE_IDENTIFIER, nullptr);
246246

@@ -309,9 +309,19 @@ void sourcekitd::initialize() {
309309
xpc_connection_resume(GlobalConn);
310310
}
311311

312-
void sourcekitd::shutdown() {
313-
assert(GlobalConn);
314-
xpc_connection_cancel(GlobalConn);
312+
void sourcekitd_initialize(void) {
313+
if (sourcekitd::initializeClient()) {
314+
LOG_INFO_FUNC(High, "initializing");
315+
initializeXPCClient();
316+
}
317+
}
318+
319+
void sourcekitd_shutdown(void) {
320+
if (sourcekitd::shutdownClient()) {
321+
LOG_INFO_FUNC(High, "shutting down");
322+
assert(GlobalConn);
323+
xpc_connection_cancel(GlobalConn);
324+
}
315325
}
316326

317327
static xpc_connection_t getGlobalConnection() {

tools/SourceKit/tools/sourcekitd/bin/XPC/Service/XPCService.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ using namespace sourcekitd;
3232

3333
static xpc_connection_t MainConnection = nullptr;
3434

35-
void sourcekitd::postNotification(sourcekitd_response_t Notification) {
35+
static void postNotification(sourcekitd_response_t Notification) {
3636
xpc_connection_t peer = MainConnection;
3737
if (!peer)
3838
goto done;
@@ -208,14 +208,14 @@ static void getToolchainPrefixPath(llvm::SmallVectorImpl<char> &Path) {
208208
llvm::sys::path::remove_filename(Path);
209209
}
210210

211-
std::string sourcekitd::getRuntimeLibPath() {
211+
static std::string getRuntimeLibPath() {
212212
llvm::SmallString<128> path;
213213
getToolchainPrefixPath(path);
214214
llvm::sys::path::append(path, "lib");
215215
return path.str().str();
216216
}
217217

218-
std::string sourcekitd::getDiagnosticDocumentationPath() {
218+
static std::string getDiagnosticDocumentationPath() {
219219
llvm::SmallString<128> path;
220220
getToolchainPrefixPath(path);
221221
llvm::sys::path::append(path, "share", "doc", "swift", "diagnostics");
@@ -341,7 +341,8 @@ static void fatal_error_handler(void *user_data, const std::string& reason,
341341
int main(int argc, const char *argv[]) {
342342
llvm::install_fatal_error_handler(fatal_error_handler, 0);
343343
sourcekitd::enableLogging("sourcekit-serv");
344-
sourcekitd::initialize();
344+
sourcekitd::initializeService(
345+
getRuntimeLibPath(), getDiagnosticDocumentationPath(), postNotification);
345346

346347
// Increase the file descriptor limit.
347348
// FIXME: Portability ?

tools/SourceKit/tools/sourcekitd/include/sourcekitd/Internal.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,23 @@ class RequestDict {
149149
Optional<int64_t> getOptionalInt64(SourceKit::UIdent Key);
150150
};
151151

152-
void initialize();
153-
void shutdown();
152+
/// Initialize the service. Must be called before attempting to handle requests.
153+
/// \param runtimeLibPath The path to the toolchain's library directory.
154+
/// \param diagnosticDocumentationPath The path to diagnostics documentation.
155+
/// \param postNotification Callback to post a notification.
156+
void initializeService(
157+
llvm::StringRef runtimeLibPath, llvm::StringRef diagnosticDocumentationPath,
158+
std::function<void(sourcekitd_response_t)> postNotification);
159+
/// Shutdown the service.
160+
void shutdownService();
161+
162+
/// Initialize the sourcekitd client library. Returns true if this is the first
163+
/// time it is initialized.
164+
bool initializeClient();
165+
/// Shutdown the sourcekitd client. Returns true if this is the last active
166+
/// client and the service should be shutdown.
167+
bool shutdownClient();
168+
154169
void set_interrupted_connection_handler(llvm::function_ref<void()> handler);
155170

156171
typedef std::function<void(sourcekitd_response_t)> ResponseReceiver;
@@ -165,17 +180,10 @@ sourcekitd_response_t createErrorRequestFailed(llvm::StringRef Description);
165180
sourcekitd_response_t createErrorRequestInterrupted(llvm::StringRef Descr);
166181
sourcekitd_response_t createErrorRequestCancelled();
167182

168-
/// Send notification object.
169-
/// The ownership of the object is transferred to the function.
170-
void postNotification(sourcekitd_response_t Notification);
171-
172183
// The client & service have their own implementations for these.
173184
sourcekitd_uid_t SKDUIDFromUIdent(SourceKit::UIdent UID);
174185
SourceKit::UIdent UIdentFromSKDUID(sourcekitd_uid_t uid);
175186

176-
std::string getRuntimeLibPath();
177-
std::string getDiagnosticDocumentationPath();
178-
179187
void writeEscaped(llvm::StringRef Str, llvm::raw_ostream &OS);
180188

181189
static inline sourcekitd_variant_t makeNullVariant() {

0 commit comments

Comments
 (0)