Skip to content

Commit f539d33

Browse files
authored
Merge pull request #36774 from ahoppen/pr/complete-generic-constructor
[CodeComplete] Complete argument labels in generic initializer
2 parents eefe93e + f965488 commit f539d33

File tree

3 files changed

+49
-11
lines changed

3 files changed

+49
-11
lines changed

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,9 @@ static bool collectPossibleCalleesForApply(
653653
} else if (auto CRCE = dyn_cast<ConstructorRefCallExpr>(fnExpr)) {
654654
collectPossibleCalleesByQualifiedLookup(
655655
DC, CRCE->getArg(), DeclNameRef::createConstructor(), candidates);
656+
} else if (auto TE = dyn_cast<TypeExpr>(fnExpr)) {
657+
collectPossibleCalleesByQualifiedLookup(
658+
DC, TE, DeclNameRef::createConstructor(), candidates);
656659
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(fnExpr)) {
657660
collectPossibleCalleesForUnresolvedMember(DC, UME, candidates);
658661
}
@@ -806,23 +809,37 @@ static bool getPositionInParams(DeclContext &DC, Expr *Args, Expr *CCExpr,
806809
}
807810

808811
// Look for a matching parameter label.
809-
bool FoundLabelMatch = false;
812+
bool AdvancedPosInParams = false;
810813
for (unsigned i = PosInParams; i < Params.size(); ++i) {
811814
if (Params[i].getLabel() == ArgName) {
812815
// We have found a label match. Advance the position in the params
813816
// to point to the param after the one with this label.
814817
PosInParams = i + 1;
815-
FoundLabelMatch = true;
818+
AdvancedPosInParams = true;
816819
if (Params[i].isVariadic()) {
817820
LastParamWasVariadic = true;
818821
}
819822
break;
820823
}
821824
}
822825

823-
if (!FoundLabelMatch) {
824-
// We haven't found a matching argument label. Assume the current one is
825-
// named incorrectly and advance by one.
826+
bool IsTrailingClosure =
827+
PosInArgs >= tuple->getNumElements() - tuple->getNumTrailingElements();
828+
if (!AdvancedPosInParams && IsTrailingClosure) {
829+
// If the argument is a trailing closure, it can't match non-function
830+
// parameters. Advance to the next function parameter.
831+
for (unsigned i = PosInParams; i < Params.size(); ++i) {
832+
if (Params[i].getParameterType()->is<FunctionType>()) {
833+
PosInParams = i + 1;
834+
AdvancedPosInParams = true;
835+
break;
836+
}
837+
}
838+
}
839+
840+
if (!AdvancedPosInParams) {
841+
// We haven't performed any special advance logic. Assume the argument
842+
// and parameter match, so advance PosInParams by 1.
826843
++PosInParams;
827844
}
828845
}

test/IDE/complete_call_arg.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,3 +888,14 @@ func testCompleteLabelAfterVararg() {
888888
// COMPLETE_MEMBER_IN_VARARG: End completions
889889
}
890890
}
891+
892+
func testGenericConstructor() {
893+
public struct TextField<Label> {
894+
init(label: String, text: String) {}
895+
}
896+
897+
_ = TextField(label: "Encoded", #^GENERIC_INITIALIZER^#)
898+
// GENERIC_INITIALIZER: Begin completions, 1 item
899+
// GENERIC_INITIALIZER-DAG: Pattern/ExprSpecific: {#text: String#}[#String#]
900+
// GENERIC_INITIALIZER: End completions
901+
}

test/IDE/complete_multiple_trailingclosure.swift

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_2 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_2
1414
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_SAMELINE_3 | %FileCheck %s -check-prefix=INIT_REQUIRED_SAMELINE_3
1515
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_REQUIRED_NEWLINE_3 | %FileCheck %s -check-prefix=INIT_REQUIRED_NEWLINE_3
16-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_1 | %FileCheck %s -check-prefix=INIT_FALLBACK
17-
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_2 | %FileCheck %s -check-prefix=INIT_FALLBACK
16+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_1 | %FileCheck %s -check-prefix=INIT_FALLBACK_1
17+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INIT_FALLBACK_2 | %FileCheck %s -check-prefix=INIT_FALLBACK_2
1818
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_SAMELINE | %FileCheck %s -check-prefix=MEMBERDECL_SAMELINE
1919
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=MEMBERDECL_NEWLINE | %FileCheck %s -check-prefix=MEMBERDECL_NEWLINE
2020
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=INITIALIZED_VARDECL_SAMELINE | %FileCheck %s -check-prefix=INITIALIZED_VARDECL_SAMELINE
@@ -201,15 +201,25 @@ func testFallbackPostfix() {
201201
let _ = MyStruct4 {
202202
1
203203
} #^INIT_FALLBACK_1^#
204-
// INIT_FALLBACK: Begin completions, 2 items
205-
// INIT_FALLBACK-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#];
206-
// INIT_FALLBACK-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4<Int>#];
207-
// INIT_FALLBACK: End completions
204+
// FIXME: We shouldn't be suggesting arg3 here because the second initializer
205+
// doesn't match the already-provided parameters (missing `name` label argument
206+
// and closure does not return `String`). However, we are not type-checking at
207+
// the stage at which we complete argument labels, so we can't rule it out for
208+
// now (SR-14450).
209+
// INIT_FALLBACK_1: Begin completions, 3 items
210+
// INIT_FALLBACK_1-DAG: Pattern/ExprSpecific: {#arg3: () -> _ {|}#}[#() -> _#]
211+
// INIT_FALLBACK_1-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#];
212+
// INIT_FALLBACK_1-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4<Int>#];
213+
// INIT_FALLBACK_1: End completions
208214
let _ = MyStruct4(name: "test") {
209215
""
210216
} arg3: {
211217
1
212218
} #^INIT_FALLBACK_2^#
219+
// INIT_FALLBACK_2: Begin completions, 2 items
220+
// INIT_FALLBACK_2-DAG: Decl[InstanceMethod]/CurrNominal: .testStructMethod()[#Void#];
221+
// INIT_FALLBACK_2-DAG: Keyword[self]/CurrNominal: .self[#MyStruct4<Int>#];
222+
// INIT_FALLBACK_2: End completions
213223
}
214224

215225
protocol P {

0 commit comments

Comments
 (0)