Skip to content

Commit ab257bb

Browse files
committed
[SourceKit] Move invocation of code completion second pass for TypeContextInfo from SoruceKit to CompletionInstance
The invocation of the code completion second pass should be implementation detail of `CompletionInstance`. Create a method on `CompletionInstance` that correctly invokes the second pass and just reutnrs the type context info results to the caller.
1 parent b6e03e3 commit ab257bb

File tree

6 files changed

+194
-128
lines changed

6 files changed

+194
-128
lines changed

include/swift/IDE/CancellableResult.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,36 @@ class CancellableResult {
140140
assert(getKind() == CancellableResultKind::Failure);
141141
return Error;
142142
}
143+
144+
/// If the result represents success, invoke \p Transform to asynchronously
145+
/// transform the wrapped result type and produce a new result type that is
146+
/// provided by the callback function passed to \p Transform. Afterwards call
147+
/// \p Handle with either the transformed value or the failure or cancelled
148+
/// result.
149+
/// The \c async part of the map means that the transform might happen
150+
/// asyncronously. This function does not introduce asynchronicity by itself.
151+
/// \p Transform might also invoke the callback synchronously.
152+
template <typename NewResultType>
153+
void
154+
mapAsync(llvm::function_ref<
155+
void(ResultType &,
156+
llvm::function_ref<void(CancellableResult<NewResultType>)>)>
157+
Transform,
158+
llvm::function_ref<void(CancellableResult<NewResultType>)> Handle) {
159+
switch (getKind()) {
160+
case CancellableResultKind::Success:
161+
Transform(getResult(), [&](CancellableResult<NewResultType> NewResult) {
162+
Handle(NewResult);
163+
});
164+
break;
165+
case CancellableResultKind::Failure:
166+
Handle(CancellableResult<NewResultType>::failure(getError()));
167+
break;
168+
case CancellableResultKind::Cancelled:
169+
Handle(CancellableResult<NewResultType>::cancelled());
170+
break;
171+
}
172+
}
143173
};
144174

145175
} // namespace ide

include/swift/IDE/CompletionInstance.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "swift/Frontend/Frontend.h"
1717
#include "swift/IDE/CancellableResult.h"
18+
#include "swift/IDE/TypeContextInfo.h"
1819
#include "llvm/ADT/Hashing.h"
1920
#include "llvm/ADT/IntrusiveRefCntPtr.h"
2021
#include "llvm/ADT/StringRef.h"
@@ -48,6 +49,14 @@ struct CompletionInstanceResult {
4849
bool DidFindCodeCompletionToken;
4950
};
5051

52+
/// The results returned from \c CompletionInstance::typeContextInfo.
53+
struct TypeContextInfoResult {
54+
/// The actual results. If empty, no results were found.
55+
ArrayRef<ide::TypeContextInfoItem> Results;
56+
/// Whether an AST was reused to produce the results.
57+
bool DidReuseAST;
58+
};
59+
5160
/// Manages \c CompilerInstance for completion like operations.
5261
class CompletionInstance {
5362
struct Options {
@@ -124,6 +133,14 @@ class CompletionInstance {
124133
DiagnosticConsumer *DiagC,
125134
llvm::function_ref<void(CancellableResult<CompletionInstanceResult>)>
126135
Callback);
136+
137+
void typeContextInfo(
138+
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
139+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
140+
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
141+
DiagnosticConsumer *DiagC,
142+
llvm::function_ref<void(CancellableResult<TypeContextInfoResult>)>
143+
Callback);
127144
};
128145

129146
} // namespace ide

lib/IDE/CompletionInstance.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,3 +655,59 @@ void swift::ide::CompletionInstance::performOperation(
655655
performNewOperation(ArgsHash, Invocation, FileSystem, completionBuffer,
656656
Offset, DiagC, Callback);
657657
}
658+
659+
void swift::ide::CompletionInstance::typeContextInfo(
660+
swift::CompilerInvocation &Invocation, llvm::ArrayRef<const char *> Args,
661+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
662+
llvm::MemoryBuffer *completionBuffer, unsigned int Offset,
663+
DiagnosticConsumer *DiagC,
664+
llvm::function_ref<void(CancellableResult<TypeContextInfoResult>)>
665+
Callback) {
666+
using ResultType = CancellableResult<TypeContextInfoResult>;
667+
668+
struct ConsumerToCallbackAdapter : public ide::TypeContextInfoConsumer {
669+
bool ReusingASTContext;
670+
llvm::function_ref<void(ResultType)> Callback;
671+
bool HandleResultsCalled = false;
672+
673+
ConsumerToCallbackAdapter(bool ReusingASTContext,
674+
llvm::function_ref<void(ResultType)> Callback)
675+
: ReusingASTContext(ReusingASTContext), Callback(Callback) {}
676+
677+
void handleResults(ArrayRef<ide::TypeContextInfoItem> Results) override {
678+
HandleResultsCalled = true;
679+
Callback(ResultType::success({Results, ReusingASTContext}));
680+
}
681+
};
682+
683+
performOperation(
684+
Invocation, Args, FileSystem, completionBuffer, Offset, DiagC,
685+
[&](CancellableResult<CompletionInstanceResult> CIResult) {
686+
CIResult.mapAsync<TypeContextInfoResult>(
687+
[](auto &Result, auto DeliverTransformed) {
688+
ConsumerToCallbackAdapter Consumer(Result.DidReuseAST,
689+
DeliverTransformed);
690+
std::unique_ptr<CodeCompletionCallbacksFactory> callbacksFactory(
691+
ide::makeTypeContextInfoCallbacksFactory(Consumer));
692+
693+
if (!Result.DidFindCodeCompletionToken) {
694+
// Deliver empty results if we didn't find a code completion
695+
// token.
696+
DeliverTransformed(
697+
ResultType::success({/*Results=*/{}, Result.DidReuseAST}));
698+
}
699+
700+
performCodeCompletionSecondPass(
701+
*Result.CI.getCodeCompletionFile(), *callbacksFactory);
702+
if (!Consumer.HandleResultsCalled) {
703+
// If we didn't receive a handleResult call from the second
704+
// pass, we didn't receive any results. To make sure
705+
// DeliverTransformed gets called exactly once, call it with
706+
// no results here.
707+
DeliverTransformed(
708+
ResultType::success({/*Results=*/{}, Result.DidReuseAST}));
709+
}
710+
},
711+
Callback);
712+
});
713+
}

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,12 +1000,12 @@ SwiftLangSupport::getFileSystem(const Optional<VFSOptions> &vfsOptions,
10001000
return llvm::vfs::getRealFileSystem();
10011001
}
10021002

1003-
void SwiftLangSupport::performCompletionLikeOperation(
1003+
void SwiftLangSupport::performWithParamsToCompletionLikeOperation(
10041004
llvm::MemoryBuffer *UnresolvedInputFile, unsigned Offset,
10051005
ArrayRef<const char *> Args,
10061006
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
1007-
llvm::function_ref<void(CancellableResult<CompletionInstanceResult>)>
1008-
Callback) {
1007+
llvm::function_ref<void(CancellableResult<CompletionLikeOperationParams>)>
1008+
PerformOperation) {
10091009
assert(FileSystem);
10101010

10111011
// Resolve symlinks for the input file; we resolve them for the input files
@@ -1050,21 +1050,43 @@ void SwiftLangSupport::performCompletionLikeOperation(
10501050
Invocation, Args, Diags, newBuffer->getBufferIdentifier(), FileSystem,
10511051
CompilerInvocationError);
10521052
if (CreatingInvocationFailed) {
1053-
Callback(CancellableResult<CompletionInstanceResult>::failure(
1053+
PerformOperation(CancellableResult<CompletionLikeOperationParams>::failure(
10541054
CompilerInvocationError));
10551055
return;
10561056
}
10571057
if (!Invocation.getFrontendOptions().InputsAndOutputs.hasInputs()) {
1058-
Callback(CancellableResult<CompletionInstanceResult>::failure(
1058+
PerformOperation(CancellableResult<CompletionLikeOperationParams>::failure(
10591059
"no input filenames specified"));
10601060
return;
10611061
}
10621062

10631063
// Pin completion instance.
10641064
auto CompletionInst = getCompletionInstance();
10651065

1066-
CompletionInst->performOperation(Invocation, Args, FileSystem,
1067-
newBuffer.get(), Offset, &CIDiags, Callback);
1066+
CompletionLikeOperationParams Params = {Invocation, newBuffer.get(),
1067+
&CIDiags};
1068+
PerformOperation(
1069+
CancellableResult<CompletionLikeOperationParams>::success(Params));
1070+
}
1071+
1072+
void SwiftLangSupport::performCompletionLikeOperation(
1073+
llvm::MemoryBuffer *UnresolvedInputFile, unsigned Offset,
1074+
ArrayRef<const char *> Args,
1075+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
1076+
llvm::function_ref<void(CancellableResult<CompletionInstanceResult>)>
1077+
Callback) {
1078+
performWithParamsToCompletionLikeOperation(
1079+
UnresolvedInputFile, Offset, Args, FileSystem,
1080+
[&](CancellableResult<CompletionLikeOperationParams> ParamsResult) {
1081+
ParamsResult.mapAsync<CompletionInstanceResult>(
1082+
[&](auto &CIParams, auto DeliverTransformed) {
1083+
getCompletionInstance()->performOperation(
1084+
CIParams.Invocation, Args, FileSystem,
1085+
CIParams.completionBuffer, Offset, CIParams.DiagC,
1086+
DeliverTransformed);
1087+
},
1088+
Callback);
1089+
});
10681090
}
10691091

10701092
CloseClangModuleFiles::~CloseClangModuleFiles() {

tools/SourceKit/lib/SwiftLang/SwiftLangSupport.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "SourceKit/Support/ThreadSafeRefCntPtr.h"
2121
#include "SourceKit/Support/Tracing.h"
2222
#include "SwiftInterfaceGenContext.h"
23+
#include "swift/AST/DiagnosticConsumer.h"
2324
#include "swift/Basic/ThreadSafeRefCounted.h"
2425
#include "swift/IDE/CancellableResult.h"
2526
#include "swift/IDE/CompletionInstance.h"
@@ -472,6 +473,23 @@ class SwiftLangSupport : public LangSupport {
472473
swift::ide::CancellableResult<swift::ide::CompletionInstanceResult>)>
473474
Callback);
474475

476+
/// The result returned from \c performWithParamsToCompletionLikeOperation.
477+
struct CompletionLikeOperationParams {
478+
swift::CompilerInvocation &Invocation;
479+
llvm::MemoryBuffer *completionBuffer;
480+
swift::DiagnosticConsumer *DiagC;
481+
};
482+
483+
/// Execute \p PerformOperation sychronously with the parameters necessary to
484+
/// invoke a completion-like operation on \c CompletionInstance.
485+
void performWithParamsToCompletionLikeOperation(
486+
llvm::MemoryBuffer *UnresolvedInputFile, unsigned Offset,
487+
ArrayRef<const char *> Args,
488+
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FileSystem,
489+
llvm::function_ref<
490+
void(swift::ide::CancellableResult<CompletionLikeOperationParams>)>
491+
PerformOperation);
492+
475493
//==========================================================================//
476494
// LangSupport Interface
477495
//==========================================================================//

0 commit comments

Comments
 (0)