@@ -36,6 +36,10 @@ using namespace llvm;
36
36
using namespace sourcekitd_test ;
37
37
38
38
static int handleTestInvocation (ArrayRef<const char *> Args, TestOptions &InitOpts);
39
+ static bool handleResponse (sourcekitd_response_t Resp, const TestOptions &Opts,
40
+ const std::string &SourceFile,
41
+ std::unique_ptr<llvm::MemoryBuffer> SourceBuf,
42
+ TestOptions *InitOpts);
39
43
static void printCursorInfo (sourcekitd_variant_t Info, StringRef Filename,
40
44
llvm::raw_ostream &OS);
41
45
static void printDocInfo (sourcekitd_variant_t Info, StringRef Filename);
@@ -156,6 +160,18 @@ static SourceKit::Semaphore semaSemaphore(0);
156
160
static sourcekitd_response_t semaResponse;
157
161
static const char *semaName;
158
162
163
+ namespace {
164
+ struct AsyncResponseInfo {
165
+ SourceKit::Semaphore semaphore{0 };
166
+ sourcekitd_response_t response = nullptr ;
167
+ TestOptions options;
168
+ std::string sourceFilename;
169
+ std::unique_ptr<llvm::MemoryBuffer> sourceBuffer;
170
+ };
171
+ }
172
+
173
+ static std::vector<AsyncResponseInfo> asyncResponses;
174
+
159
175
static int skt_main (int argc, const char **argv);
160
176
161
177
int main (int argc, const char **argv) {
@@ -265,17 +281,32 @@ static int skt_main(int argc, const char **argv) {
265
281
}
266
282
if (i == Args.size ())
267
283
break ;
268
- int ret = handleTestInvocation (Args.slice (0 , i), InitOpts);
269
- if (ret) {
284
+ if (int ret = handleTestInvocation (Args.slice (0 , i), InitOpts)) {
270
285
sourcekitd_shutdown ();
271
286
return ret;
272
287
}
273
288
Args = Args.slice (i+1 );
274
289
}
275
290
276
- int ret = handleTestInvocation (Args, InitOpts);
291
+ if (int ret = handleTestInvocation (Args, InitOpts)) {
292
+ sourcekitd_shutdown ();
293
+ return ret;
294
+ }
295
+
296
+ for (auto &info : asyncResponses) {
297
+ if (info.semaphore .wait (60 * 1000 )) {
298
+ llvm::report_fatal_error (" async request timed out" );
299
+ }
300
+
301
+ if (handleResponse (info.response , info.options , info.sourceFilename ,
302
+ std::move (info.sourceBuffer ), nullptr )) {
303
+ sourcekitd_shutdown ();
304
+ return 1 ;
305
+ }
306
+ }
307
+
277
308
sourcekitd_shutdown ();
278
- return ret ;
309
+ return 0 ;
279
310
}
280
311
281
312
static inline const char *getInterfaceGenDocumentName () {
@@ -665,8 +696,45 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
665
696
Opts.HeaderPath .c_str ());
666
697
}
667
698
668
- sourcekitd_request_description_dump (Req);
669
- sourcekitd_response_t Resp = sourcekitd_send_request_sync (Req);
699
+ if (Opts.PrintRequest )
700
+ sourcekitd_request_description_dump (Req);
701
+
702
+ if (!Opts.isAsyncRequest ) {
703
+ sourcekitd_response_t Resp = sourcekitd_send_request_sync (Req);
704
+ sourcekitd_request_release (Req);
705
+ return handleResponse (Resp, Opts, SourceFile, std::move (SourceBuf),
706
+ &InitOpts)
707
+ ? 1
708
+ : 0 ;
709
+ } else {
710
+ #if SOURCEKITD_HAS_BLOCKS
711
+ AsyncResponseInfo info;
712
+ info.options = Opts;
713
+ info.sourceFilename = std::move (SourceFile);
714
+ info.sourceBuffer = std::move (SourceBuf);
715
+ unsigned respIndex = asyncResponses.size ();
716
+ asyncResponses.push_back (std::move (info));
717
+
718
+ sourcekitd_send_request (Req, nullptr , ^(sourcekitd_response_t resp) {
719
+ auto &info = asyncResponses[respIndex];
720
+ info.response = resp;
721
+ info.semaphore .signal (); // Ready to be handled!
722
+ });
723
+
724
+ #else
725
+ llvm::report_fatal_error (
726
+ " -async not supported when sourcekitd is built without blocks support" );
727
+ #endif
728
+
729
+ sourcekitd_request_release (Req);
730
+ return 0 ;
731
+ }
732
+ }
733
+
734
+ static bool handleResponse (sourcekitd_response_t Resp, const TestOptions &Opts,
735
+ const std::string &SourceFile,
736
+ std::unique_ptr<llvm::MemoryBuffer> SourceBuf,
737
+ TestOptions *InitOpts) {
670
738
bool KeepResponseAlive = false ;
671
739
bool IsError = sourcekitd_response_is_error (Resp);
672
740
if (IsError) {
@@ -742,8 +810,10 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
742
810
743
811
case SourceKitRequest::InterfaceGenOpen:
744
812
// Just initialize the options for the subsequent request.
745
- InitOpts.SourceFile = getInterfaceGenDocumentName ();
746
- InitOpts.SourceText =
813
+ assert (!Opts.isAsyncRequest && InitOpts &&
814
+ " async interface-gen-open is not supported" );
815
+ InitOpts->SourceFile = getInterfaceGenDocumentName ();
816
+ InitOpts->SourceText =
747
817
sourcekitd_variant_dictionary_get_string (Info, KeySourceText);
748
818
break ;
749
819
@@ -832,7 +902,6 @@ static int handleTestInvocation(ArrayRef<const char *> Args,
832
902
833
903
if (!KeepResponseAlive)
834
904
sourcekitd_response_dispose (Resp);
835
- sourcekitd_request_release (Req);
836
905
return IsError;
837
906
}
838
907
0 commit comments