@@ -286,6 +286,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
286
286
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
287
287
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
288
288
DiagnosticConsumer *DiagC,
289
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
289
290
llvm::function_ref<void (CancellableResult<CompletionInstanceResult>)>
290
291
Callback) {
291
292
llvm::PrettyStackTraceString trace (
@@ -338,6 +339,7 @@ bool CompletionInstance::performCachedOperationIfPossible(
338
339
std::unique_ptr<ASTContext> tmpCtx (
339
340
ASTContext::get (langOpts, typeckOpts, silOpts, searchPathOpts, clangOpts,
340
341
symbolOpts, tmpSM, tmpDiags));
342
+ tmpCtx->CancellationFlag = CancellationFlag;
341
343
registerParseRequestFunctions (tmpCtx->evaluator );
342
344
registerIDERequestFunctions (tmpCtx->evaluator );
343
345
registerTypeCheckerRequestFunctions (tmpCtx->evaluator );
@@ -502,12 +504,18 @@ bool CompletionInstance::performCachedOperationIfPossible(
502
504
// The diagnostic engine is keeping track of state which might modify
503
505
// parsing and type checking behaviour. Clear the flags.
504
506
CI.getDiags ().resetHadAnyError ();
507
+ CI.getASTContext ().CancellationFlag = CancellationFlag;
505
508
506
509
if (DiagC)
507
510
CI.addDiagnosticConsumer (DiagC);
508
511
509
- Callback (CancellableResult<CompletionInstanceResult>::success (
510
- {CI, /* reusingASTContext=*/ true , /* DidFindCodeCompletionToken=*/ true }));
512
+ if (CancellationFlag && CancellationFlag->load (std::memory_order_relaxed)) {
513
+ Callback (CancellableResult<CompletionInstanceResult>::cancelled ());
514
+ } else {
515
+ Callback (CancellableResult<CompletionInstanceResult>::success (
516
+ {CI, /* reusingASTContext=*/ true ,
517
+ /* DidFindCodeCompletionToken=*/ true }));
518
+ }
511
519
512
520
if (DiagC)
513
521
CI.removeDiagnosticConsumer (DiagC);
@@ -523,11 +531,13 @@ void CompletionInstance::performNewOperation(
523
531
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
524
532
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
525
533
DiagnosticConsumer *DiagC,
534
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
526
535
llvm::function_ref<void (CancellableResult<CompletionInstanceResult>)>
527
536
Callback) {
528
537
llvm::PrettyStackTraceString trace (" While performing new completion" );
529
538
530
- auto isCachedCompletionRequested = ArgsHash.hasValue ();
539
+ // If ArgsHash is None we shouldn't cache the compiler instance.
540
+ bool ShouldCacheCompilerInstance = ArgsHash.hasValue ();
531
541
532
542
auto TheInstance = std::make_unique<CompilerInstance>();
533
543
@@ -536,7 +546,6 @@ void CompletionInstance::performNewOperation(
536
546
Invocation.getFrontendOptions ().IntermoduleDependencyTracking =
537
547
IntermoduleDepTrackingMode::ExcludeSystem;
538
548
539
- bool DidFindCodeCompletionToken = false ;
540
549
{
541
550
auto &CI = *TheInstance;
542
551
if (DiagC)
@@ -557,6 +566,7 @@ void CompletionInstance::performNewOperation(
557
566
" failed to setup compiler instance" ));
558
567
return ;
559
568
}
569
+ CI.getASTContext ().CancellationFlag = CancellationFlag;
560
570
registerIDERequestFunctions (CI.getASTContext ().evaluator );
561
571
562
572
// If we're expecting a standard library, but there either isn't one, or it
@@ -570,19 +580,32 @@ void CompletionInstance::performNewOperation(
570
580
571
581
CI.performParseAndResolveImportsOnly ();
572
582
573
- DidFindCodeCompletionToken = CI.getCodeCompletionFile ()
574
- ->getDelayedParserState ()
575
- ->hasCodeCompletionDelayedDeclState ();
576
-
577
- Callback (CancellableResult<CompletionInstanceResult>::success (
578
- {CI, /* ReuisingASTContext=*/ false , DidFindCodeCompletionToken}));
583
+ bool DidFindCodeCompletionToken = CI.getCodeCompletionFile ()
584
+ ->getDelayedParserState ()
585
+ ->hasCodeCompletionDelayedDeclState ();
586
+ ShouldCacheCompilerInstance &= DidFindCodeCompletionToken;
587
+
588
+ auto CancellationFlag = CI.getASTContext ().CancellationFlag ;
589
+ if (CancellationFlag && CancellationFlag->load (std::memory_order_relaxed)) {
590
+ Callback (CancellableResult<CompletionInstanceResult>::cancelled ());
591
+ // The completion instance may be in an invalid state when it's been
592
+ // cancelled. Don't cache it.
593
+ ShouldCacheCompilerInstance = false ;
594
+ } else {
595
+ Callback (CancellableResult<CompletionInstanceResult>::success (
596
+ {CI, /* ReuisingASTContext=*/ false , DidFindCodeCompletionToken}));
597
+ if (CancellationFlag &&
598
+ CancellationFlag->load (std::memory_order_relaxed)) {
599
+ ShouldCacheCompilerInstance = false ;
600
+ }
601
+ }
579
602
}
580
603
581
604
// Cache the compiler instance if fast completion is enabled.
582
605
// If we didn't find a code compleiton token, we can't cache the instance
583
606
// because performCachedOperationIfPossible wouldn't have an old code
584
607
// completion state to compare the new one to.
585
- if (isCachedCompletionRequested && DidFindCodeCompletionToken )
608
+ if (ShouldCacheCompilerInstance )
586
609
cacheCompilerInstance (std::move (TheInstance), *ArgsHash);
587
610
}
588
611
@@ -623,20 +646,9 @@ void swift::ide::CompletionInstance::performOperation(
623
646
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
624
647
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
625
648
DiagnosticConsumer *DiagC,
649
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
626
650
llvm::function_ref<void (CancellableResult<CompletionInstanceResult>)>
627
651
Callback) {
628
-
629
- // Always disable source location resolutions from .swiftsourceinfo file
630
- // because they're somewhat heavy operations and aren't needed for completion.
631
- Invocation.getFrontendOptions ().IgnoreSwiftSourceInfo = true ;
632
-
633
- // Disable to build syntax tree because code-completion skips some portion of
634
- // source text. That breaks an invariant of syntax tree building.
635
- Invocation.getLangOptions ().BuildSyntaxTree = false ;
636
-
637
- // We don't need token list.
638
- Invocation.getLangOptions ().CollectParsedToken = false ;
639
-
640
652
// Compute the signature of the invocation.
641
653
llvm::hash_code ArgsHash (0 );
642
654
for (auto arg : Args)
@@ -647,32 +659,48 @@ void swift::ide::CompletionInstance::performOperation(
647
659
std::lock_guard<std::mutex> lock (mtx);
648
660
649
661
if (performCachedOperationIfPossible (ArgsHash, FileSystem, completionBuffer,
650
- Offset, DiagC, Callback)) {
662
+ Offset, DiagC, CancellationFlag,
663
+ Callback)) {
651
664
// We were able to reuse a cached AST. Callback has already been invoked
652
665
// and we don't need to build a new AST. We are done.
653
666
return ;
654
667
}
655
668
669
+ // Always disable source location resolutions from .swiftsourceinfo file
670
+ // because they're somewhat heavy operations and aren't needed for completion.
671
+ Invocation.getFrontendOptions ().IgnoreSwiftSourceInfo = true ;
672
+
673
+ // Disable to build syntax tree because code-completion skips some portion of
674
+ // source text. That breaks an invariant of syntax tree building.
675
+ Invocation.getLangOptions ().BuildSyntaxTree = false ;
676
+
677
+ // We don't need token list.
678
+ Invocation.getLangOptions ().CollectParsedToken = false ;
679
+
656
680
performNewOperation (ArgsHash, Invocation, FileSystem, completionBuffer,
657
- Offset, DiagC, Callback);
681
+ Offset, DiagC, CancellationFlag, Callback);
658
682
}
659
683
660
684
void swift::ide::CompletionInstance::codeComplete (
661
685
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
662
686
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
663
687
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
664
688
DiagnosticConsumer *DiagC, ide::CodeCompletionContext &CompletionContext,
689
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
665
690
llvm::function_ref<void (CancellableResult<CodeCompleteResult>)> Callback) {
666
691
using ResultType = CancellableResult<CodeCompleteResult>;
667
692
668
693
struct ConsumerToCallbackAdapter
669
694
: public SimpleCachingCodeCompletionConsumer {
670
695
SwiftCompletionInfo SwiftContext;
696
+ std::shared_ptr<std::atomic<bool >> CancellationFlag;
671
697
llvm::function_ref<void (ResultType)> Callback;
672
698
bool HandleResultsCalled = false ;
673
699
674
- ConsumerToCallbackAdapter (llvm::function_ref<void (ResultType)> Callback)
675
- : Callback(Callback) {}
700
+ ConsumerToCallbackAdapter (
701
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
702
+ llvm::function_ref<void (ResultType)> Callback)
703
+ : CancellationFlag(CancellationFlag), Callback(Callback) {}
676
704
677
705
void setContext (swift::ASTContext *context,
678
706
const swift::CompilerInvocation *invocation,
@@ -685,20 +713,28 @@ void swift::ide::CompletionInstance::codeComplete(
685
713
686
714
void handleResults (CodeCompletionContext &context) override {
687
715
HandleResultsCalled = true ;
688
- MutableArrayRef<CodeCompletionResult *> Results = context.takeResults ();
689
- assert (SwiftContext.swiftASTContext );
690
- Callback (ResultType::success ({Results, SwiftContext}));
716
+ if (CancellationFlag &&
717
+ CancellationFlag->load (std::memory_order_relaxed)) {
718
+ Callback (ResultType::cancelled ());
719
+ } else {
720
+ MutableArrayRef<CodeCompletionResult *> Results = context.takeResults ();
721
+ assert (SwiftContext.swiftASTContext );
722
+ Callback (ResultType::success ({Results, SwiftContext}));
723
+ }
691
724
}
692
725
};
693
726
694
727
performOperation (
695
728
Invocation, Args, FileSystem, completionBuffer, Offset, DiagC,
729
+ CancellationFlag,
696
730
[&](CancellableResult<CompletionInstanceResult> CIResult) {
697
731
CIResult.mapAsync <CodeCompleteResult>(
698
- [&CompletionContext](auto &Result, auto DeliverTransformed) {
732
+ [&CompletionContext, &CancellationFlag](auto &Result,
733
+ auto DeliverTransformed) {
699
734
CompletionContext.ReusingASTContext = Result.DidReuseAST ;
700
735
CompilerInstance &CI = Result.CI ;
701
- ConsumerToCallbackAdapter Consumer (DeliverTransformed);
736
+ ConsumerToCallbackAdapter Consumer (CancellationFlag,
737
+ DeliverTransformed);
702
738
703
739
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory (
704
740
ide::makeCodeCompletionCallbacksFactory (CompletionContext,
@@ -737,32 +773,43 @@ void swift::ide::CompletionInstance::typeContextInfo(
737
773
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
738
774
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
739
775
DiagnosticConsumer *DiagC,
776
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
740
777
llvm::function_ref<void (CancellableResult<TypeContextInfoResult>)>
741
778
Callback) {
742
779
using ResultType = CancellableResult<TypeContextInfoResult>;
743
780
744
781
struct ConsumerToCallbackAdapter : public ide ::TypeContextInfoConsumer {
745
782
bool ReusingASTContext;
783
+ std::shared_ptr<std::atomic<bool >> CancellationFlag;
746
784
llvm::function_ref<void (ResultType)> Callback;
747
785
bool HandleResultsCalled = false ;
748
786
749
- ConsumerToCallbackAdapter (bool ReusingASTContext,
750
- llvm::function_ref<void (ResultType)> Callback)
751
- : ReusingASTContext(ReusingASTContext), Callback(Callback) {}
787
+ ConsumerToCallbackAdapter (
788
+ bool ReusingASTContext,
789
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
790
+ llvm::function_ref<void (ResultType)> Callback)
791
+ : ReusingASTContext(ReusingASTContext),
792
+ CancellationFlag (CancellationFlag), Callback(Callback) {}
752
793
753
794
void handleResults (ArrayRef<ide::TypeContextInfoItem> Results) override {
754
795
HandleResultsCalled = true ;
755
- Callback (ResultType::success ({Results, ReusingASTContext}));
796
+ if (CancellationFlag &&
797
+ CancellationFlag->load (std::memory_order_relaxed)) {
798
+ Callback (ResultType::cancelled ());
799
+ } else {
800
+ Callback (ResultType::success ({Results, ReusingASTContext}));
801
+ }
756
802
}
757
803
};
758
804
759
805
performOperation (
760
806
Invocation, Args, FileSystem, completionBuffer, Offset, DiagC,
807
+ CancellationFlag,
761
808
[&](CancellableResult<CompletionInstanceResult> CIResult) {
762
809
CIResult.mapAsync <TypeContextInfoResult>(
763
- [](auto &Result, auto DeliverTransformed) {
764
- ConsumerToCallbackAdapter Consumer (Result. DidReuseAST ,
765
- DeliverTransformed);
810
+ [&CancellationFlag ](auto &Result, auto DeliverTransformed) {
811
+ ConsumerToCallbackAdapter Consumer (
812
+ Result. DidReuseAST , CancellationFlag, DeliverTransformed);
766
813
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory (
767
814
ide::makeTypeContextInfoCallbacksFactory (Consumer));
768
815
@@ -793,33 +840,45 @@ void swift::ide::CompletionInstance::conformingMethodList(
793
840
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
794
841
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
795
842
DiagnosticConsumer *DiagC, ArrayRef<const char *> ExpectedTypeNames,
843
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
796
844
llvm::function_ref<void (CancellableResult<ConformingMethodListResults>)>
797
845
Callback) {
798
846
using ResultType = CancellableResult<ConformingMethodListResults>;
799
847
800
848
struct ConsumerToCallbackAdapter
801
849
: public swift::ide::ConformingMethodListConsumer {
802
850
bool ReusingASTContext;
851
+ std::shared_ptr<std::atomic<bool >> CancellationFlag;
803
852
llvm::function_ref<void (ResultType)> Callback;
804
853
bool HandleResultsCalled = false ;
805
854
806
- ConsumerToCallbackAdapter (bool ReusingASTContext,
807
- llvm::function_ref<void (ResultType)> Callback)
808
- : ReusingASTContext(ReusingASTContext), Callback(Callback) {}
855
+ ConsumerToCallbackAdapter (
856
+ bool ReusingASTContext,
857
+ std::shared_ptr<std::atomic<bool >> CancellationFlag,
858
+ llvm::function_ref<void (ResultType)> Callback)
859
+ : ReusingASTContext(ReusingASTContext),
860
+ CancellationFlag (CancellationFlag), Callback(Callback) {}
809
861
810
862
void handleResult (const ide::ConformingMethodListResult &result) override {
811
863
HandleResultsCalled = true ;
812
- Callback (ResultType::success ({&result, ReusingASTContext}));
864
+ if (CancellationFlag &&
865
+ CancellationFlag->load (std::memory_order_relaxed)) {
866
+ Callback (ResultType::cancelled ());
867
+ } else {
868
+ Callback (ResultType::success ({&result, ReusingASTContext}));
869
+ }
813
870
}
814
871
};
815
872
816
873
performOperation (
817
874
Invocation, Args, FileSystem, completionBuffer, Offset, DiagC,
875
+ CancellationFlag,
818
876
[&](CancellableResult<CompletionInstanceResult> CIResult) {
819
877
CIResult.mapAsync <ConformingMethodListResults>(
820
- [&ExpectedTypeNames](auto &Result, auto DeliverTransformed) {
821
- ConsumerToCallbackAdapter Consumer (Result.DidReuseAST ,
822
- DeliverTransformed);
878
+ [&ExpectedTypeNames, &CancellationFlag](auto &Result,
879
+ auto DeliverTransformed) {
880
+ ConsumerToCallbackAdapter Consumer (
881
+ Result.DidReuseAST , CancellationFlag, DeliverTransformed);
823
882
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory (
824
883
ide::makeConformingMethodListCallbacksFactory (
825
884
ExpectedTypeNames, Consumer));
0 commit comments