mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[CodeCompletion] Support a narrow case for producing trailing closures directly
This adds a narrow special case in code-completion for control-flow-like methods such as DispatchQueue().sync that are () -> (), to add a new completion where the trailing closure is immediately expanded rather than having to invoke placeholder expansion as a second step. rdar://problem/26628804
This commit is contained in:
@@ -1175,8 +1175,6 @@ void CodeCompletionString::getName(raw_ostream &OS) const {
|
||||
if (FirstTextChunk.hasValue()) {
|
||||
for (auto C : getChunks().slice(*FirstTextChunk)) {
|
||||
using ChunkKind = Chunk::ChunkKind;
|
||||
if (C.getKind() == ChunkKind::BraceStmtWithCursor)
|
||||
break;
|
||||
|
||||
bool shouldPrint = !C.isAnnotation();
|
||||
switch (C.getKind()) {
|
||||
@@ -1565,6 +1563,29 @@ protocolForLiteralKind(CodeCompletionLiteralKind kind) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether funcType has a single argument (not including defaulted arguments)
|
||||
/// that is of type () -> ().
|
||||
static bool hasTrivialTrailingClosure(const FuncDecl *FD,
|
||||
AnyFunctionType *funcType) {
|
||||
unsigned level = FD->isInstanceMember() ? 1 : 0;
|
||||
auto Args = decomposeParamType(funcType->getInput(), FD, level);
|
||||
bool OneArg = Args.size() == 1;
|
||||
if (Args.size() > 1) {
|
||||
unsigned NonDefault =
|
||||
std::count_if(Args.begin(), Args.end() - 1, [](const CallArgParam &P) {
|
||||
return !P.HasDefaultArgument;
|
||||
});
|
||||
|
||||
OneArg = NonDefault == 0;
|
||||
}
|
||||
|
||||
if (OneArg)
|
||||
if (auto Fn = Args.back().Ty->getAs<AnyFunctionType>())
|
||||
return Fn->getInput()->isVoid() && Fn->getResult()->isVoid();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Build completions by doing visible decl lookup from a context.
|
||||
class CompletionLookup final : public swift::VisibleDeclConsumer {
|
||||
CodeCompletionResultSink &Sink;
|
||||
@@ -2361,8 +2382,15 @@ public:
|
||||
if (FirstIndex != 0 && !FunctionType->is<ErrorType>())
|
||||
FunctionType = FunctionType->castTo<AnyFunctionType>()->getResult();
|
||||
|
||||
bool trivialTrailingClosure = false;
|
||||
if (!IsImplicitlyCurriedInstanceMethod && !FunctionType->is<ErrorType>()) {
|
||||
trivialTrailingClosure = hasTrivialTrailingClosure(
|
||||
FD, FunctionType->castTo<AnyFunctionType>());
|
||||
}
|
||||
|
||||
// Add the method, possibly including any default arguments.
|
||||
auto addMethodImpl = [&](bool includeDefaultArgs = true) {
|
||||
auto addMethodImpl = [&](bool includeDefaultArgs = true,
|
||||
bool trivialTrailingClosure = false) {
|
||||
CommandWordsPairs Pairs;
|
||||
CodeCompletionResultBuilder Builder(
|
||||
Sink, CodeCompletionResult::ResultKind::Declaration,
|
||||
@@ -2395,6 +2423,8 @@ public:
|
||||
Builder.addCallParameter(Ctx.Id_self, FirstInputType,
|
||||
/*IsVarArg*/ false, true);
|
||||
Builder.addRightParen();
|
||||
} else if (trivialTrailingClosure) {
|
||||
Builder.addBraceStmtWithCursor(" { code }");
|
||||
} else {
|
||||
Builder.addLeftParen();
|
||||
auto AFT = FunctionType->castTo<AnyFunctionType>();
|
||||
@@ -2427,6 +2457,10 @@ public:
|
||||
hasInterestingDefaultValues(FD)) {
|
||||
addMethodImpl(/*includeDefaultArgs*/ false);
|
||||
}
|
||||
if (trivialTrailingClosure) {
|
||||
addMethodImpl(/*includeDefaultArgs=*/false,
|
||||
/*trivialTrailingClosure=*/true);
|
||||
}
|
||||
addMethodImpl();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user