Skip to content

Commit 3c2433c

Browse files
committed
[CodeCompletion] Prioritize call argument pattern
struct Foo { init(_ arg1: String, arg2: Int) {} init(label: Int) {} } func test(strVal: String) { _ = Foo(<HERE>) } In this case, 'strVal' was prioritized because it can use as an argument for 'init(_:arg2:)'. However, argument labels are almost always preferable, and if the user actually want 'strVal', they can input a few characters to get it at the top. So we should always prioritize call argument patterns. rdar://77188260
1 parent fe9a290 commit 3c2433c

File tree

7 files changed

+65
-19
lines changed

7 files changed

+65
-19
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,7 @@ class CodeCompletionResult {
613613
unsigned AssociatedKind : 8;
614614
unsigned KnownOperatorKind : 6;
615615
unsigned SemanticContext : 3;
616+
unsigned IsArgumentLabels : 1;
616617
unsigned NotRecommended : 4;
617618
unsigned IsSystem : 1;
618619

@@ -637,14 +638,15 @@ class CodeCompletionResult {
637638
///
638639
/// \note The caller must ensure \c CodeCompletionString outlives this result.
639640
CodeCompletionResult(ResultKind Kind, SemanticContextKind SemanticContext,
640-
unsigned NumBytesToErase,
641+
bool IsArgumentLabels, unsigned NumBytesToErase,
641642
CodeCompletionString *CompletionString,
642643
ExpectedTypeRelation TypeDistance,
643644
CodeCompletionOperatorKind KnownOperatorKind =
644645
CodeCompletionOperatorKind::None,
645646
StringRef BriefDocComment = StringRef())
646647
: Kind(Kind), KnownOperatorKind(unsigned(KnownOperatorKind)),
647648
SemanticContext(unsigned(SemanticContext)),
649+
IsArgumentLabels(unsigned(IsArgumentLabels)),
648650
NotRecommended(unsigned(NotRecommendedReason::None)),
649651
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
650652
BriefDocComment(BriefDocComment), TypeDistance(TypeDistance) {
@@ -664,12 +666,13 @@ class CodeCompletionResult {
664666
/// \note The caller must ensure \c CodeCompletionString outlives this result.
665667
CodeCompletionResult(CodeCompletionKeywordKind Kind,
666668
SemanticContextKind SemanticContext,
667-
unsigned NumBytesToErase,
669+
bool IsArgumentLabels, unsigned NumBytesToErase,
668670
CodeCompletionString *CompletionString,
669671
ExpectedTypeRelation TypeDistance,
670672
StringRef BriefDocComment = StringRef())
671673
: Kind(Keyword), KnownOperatorKind(0),
672674
SemanticContext(unsigned(SemanticContext)),
675+
IsArgumentLabels(unsigned(IsArgumentLabels)),
673676
NotRecommended(unsigned(NotRecommendedReason::None)),
674677
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
675678
BriefDocComment(BriefDocComment), TypeDistance(TypeDistance) {
@@ -683,11 +686,12 @@ class CodeCompletionResult {
683686
/// \note The caller must ensure \c CodeCompletionString outlives this result.
684687
CodeCompletionResult(CodeCompletionLiteralKind LiteralKind,
685688
SemanticContextKind SemanticContext,
686-
unsigned NumBytesToErase,
689+
bool IsArgumentLabels, unsigned NumBytesToErase,
687690
CodeCompletionString *CompletionString,
688691
ExpectedTypeRelation TypeDistance)
689692
: Kind(Literal), KnownOperatorKind(0),
690693
SemanticContext(unsigned(SemanticContext)),
694+
IsArgumentLabels(unsigned(IsArgumentLabels)),
691695
NotRecommended(unsigned(NotRecommendedReason::None)),
692696
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
693697
TypeDistance(TypeDistance) {
@@ -702,7 +706,7 @@ class CodeCompletionResult {
702706
/// arguments outlive this result, typically by storing them in the same
703707
/// \c CodeCompletionResultSink as the result itself.
704708
CodeCompletionResult(SemanticContextKind SemanticContext,
705-
unsigned NumBytesToErase,
709+
bool IsArgumentLabels, unsigned NumBytesToErase,
706710
CodeCompletionString *CompletionString,
707711
const Decl *AssociatedDecl, StringRef ModuleName,
708712
CodeCompletionResult::NotRecommendedReason NotRecReason,
@@ -712,6 +716,7 @@ class CodeCompletionResult {
712716
enum ExpectedTypeRelation TypeDistance)
713717
: Kind(ResultKind::Declaration), KnownOperatorKind(0),
714718
SemanticContext(unsigned(SemanticContext)),
719+
IsArgumentLabels(unsigned(IsArgumentLabels)),
715720
NotRecommended(unsigned(NotRecReason)),
716721
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
717722
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
@@ -728,9 +733,9 @@ class CodeCompletionResult {
728733
getOperatorKind() != CodeCompletionOperatorKind::None);
729734
}
730735

731-
// FIXME:
736+
// Used by deserialization.
732737
CodeCompletionResult(SemanticContextKind SemanticContext,
733-
unsigned NumBytesToErase,
738+
bool IsArgumentLabels, unsigned NumBytesToErase,
734739
CodeCompletionString *CompletionString,
735740
CodeCompletionDeclKind DeclKind, bool IsSystem,
736741
StringRef ModuleName,
@@ -743,6 +748,7 @@ class CodeCompletionResult {
743748
: Kind(ResultKind::Declaration),
744749
KnownOperatorKind(unsigned(KnownOperatorKind)),
745750
SemanticContext(unsigned(SemanticContext)),
751+
IsArgumentLabels(unsigned(IsArgumentLabels)),
746752
NotRecommended(unsigned(NotRecReason)), IsSystem(IsSystem),
747753
NumBytesToErase(NumBytesToErase), CompletionString(CompletionString),
748754
ModuleName(ModuleName), BriefDocComment(BriefDocComment),
@@ -805,6 +811,10 @@ class CodeCompletionResult {
805811
return static_cast<SemanticContextKind>(SemanticContext);
806812
}
807813

814+
bool isArgumentLabels() const {
815+
return static_cast<bool>(IsArgumentLabels);
816+
}
817+
808818
bool isNotRecommended() const {
809819
return getNotRecommendedReason() != NotRecommendedReason::None;
810820
}

lib/IDE/CodeCompletion.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,31 +1294,31 @@ CodeCompletionResult *CodeCompletionResultBuilder::takeResult() {
12941294
}
12951295

12961296
return new (*Sink.Allocator) CodeCompletionResult(
1297-
SemanticContext, NumBytesToErase, CCS, AssociatedDecl, ModuleName,
1298-
NotRecReason, copyString(*Sink.Allocator, BriefComment),
1297+
SemanticContext, IsArgumentLabels, NumBytesToErase, CCS, AssociatedDecl,
1298+
ModuleName, NotRecReason, copyString(*Sink.Allocator, BriefComment),
12991299
copyAssociatedUSRs(*Sink.Allocator, AssociatedDecl),
13001300
copyArray(*Sink.Allocator, CommentWords), ExpectedTypeRelation);
13011301
}
13021302

13031303
case CodeCompletionResult::ResultKind::Keyword:
13041304
return new (*Sink.Allocator)
13051305
CodeCompletionResult(
1306-
KeywordKind, SemanticContext, NumBytesToErase,
1306+
KeywordKind, SemanticContext, IsArgumentLabels, NumBytesToErase,
13071307
CCS, ExpectedTypeRelation,
13081308
copyString(*Sink.Allocator, BriefDocComment));
13091309

13101310
case CodeCompletionResult::ResultKind::BuiltinOperator:
13111311
case CodeCompletionResult::ResultKind::Pattern:
13121312
return new (*Sink.Allocator) CodeCompletionResult(
1313-
Kind, SemanticContext, NumBytesToErase, CCS, ExpectedTypeRelation,
1314-
CodeCompletionOperatorKind::None,
1313+
Kind, SemanticContext, IsArgumentLabels, NumBytesToErase, CCS,
1314+
ExpectedTypeRelation, CodeCompletionOperatorKind::None,
13151315
copyString(*Sink.Allocator, BriefDocComment));
13161316

13171317
case CodeCompletionResult::ResultKind::Literal:
13181318
assert(LiteralKind.hasValue());
13191319
return new (*Sink.Allocator)
1320-
CodeCompletionResult(*LiteralKind, SemanticContext, NumBytesToErase,
1321-
CCS, ExpectedTypeRelation);
1320+
CodeCompletionResult(*LiteralKind, SemanticContext, IsArgumentLabels,
1321+
NumBytesToErase, CCS, ExpectedTypeRelation);
13221322
}
13231323

13241324
llvm_unreachable("Unhandled CodeCompletionResult in switch.");
@@ -2895,6 +2895,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28952895
: CodeCompletionResult::ResultKind::Pattern,
28962896
SemanticContext ? *SemanticContext : getSemanticContextKind(AFD),
28972897
expectedTypeContext);
2898+
Builder.setIsArgumentLabels();
28982899
if (AFD) {
28992900
Builder.setAssociatedDecl(AFD);
29002901
setClangDeclKeywords(AFD, Pairs, Builder);

lib/IDE/CodeCompletionCache.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,15 +228,16 @@ static bool readCachedModule(llvm::MemoryBuffer *in,
228228
CodeCompletionResult *result = nullptr;
229229
if (kind == CodeCompletionResult::Declaration) {
230230
result = new (*V.Sink.Allocator) CodeCompletionResult(
231-
context, numBytesToErase, string, declKind, isSystem, moduleName,
232-
notRecommended, briefDocComment,
231+
context, /*IsArgumentLabels=*/false, numBytesToErase, string,
232+
declKind, isSystem, moduleName, notRecommended, briefDocComment,
233233
copyArray(*V.Sink.Allocator, ArrayRef<StringRef>(assocUSRs)),
234234
copyArray(*V.Sink.Allocator,
235235
ArrayRef<std::pair<StringRef, StringRef>>(declKeywords)),
236236
CodeCompletionResult::Unknown, opKind);
237237
} else {
238238
result = new (*V.Sink.Allocator)
239-
CodeCompletionResult(kind, context, numBytesToErase, string,
239+
CodeCompletionResult(kind, context, /*IsArgumentLabels=*/false,
240+
numBytesToErase, string,
240241
CodeCompletionResult::NotApplicable, opKind);
241242
}
242243

@@ -340,6 +341,7 @@ static void writeCachedModule(llvm::raw_ostream &out,
340341
{
341342
endian::Writer LE(results, little);
342343
for (CodeCompletionResult *R : V.Sink.Results) {
344+
assert(!R->isArgumentLabels() && "Argument labels should not be cached");
343345
// FIXME: compress bitfield
344346
LE.write(static_cast<uint8_t>(R->getKind()));
345347
if (R->getKind() == CodeCompletionResult::Declaration)

lib/IDE/CodeCompletionResultBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class CodeCompletionResultBuilder {
8787
ExpectedTypeContext declTypeContext;
8888
CodeCompletionResult::ExpectedTypeRelation ExpectedTypeRelation =
8989
CodeCompletionResult::Unknown;
90+
bool IsArgumentLabels = false;
9091
bool Cancelled = false;
9192
ArrayRef<std::pair<StringRef, StringRef>> CommentWords;
9293
CodeCompletionResult::NotRecommendedReason NotRecReason =
@@ -154,6 +155,10 @@ class CodeCompletionResultBuilder {
154155
SemanticContext = Kind;
155156
}
156157

158+
void setIsArgumentLabels(bool Flag = true) {
159+
IsArgumentLabels = Flag;
160+
}
161+
157162
void
158163
setExpectedTypeRelation(CodeCompletionResult::ExpectedTypeRelation relation) {
159164
ExpectedTypeRelation = relation;

test/SourceKit/CodeComplete/complete_sort_order.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,3 +220,26 @@ func test7() {
220220
// CASE_0: caseSensitiveCheck
221221
// CASE_0: CaseSensitiveCheck(
222222
// CASE_0: ]
223+
224+
// RUN: %complete-test -tok=CALLARG_1 %s | %FileCheck %s -check-prefix=CALLARG
225+
// RUN: %complete-test -tok=CALLARG_2 %s | %FileCheck %s -check-prefix=CALLARG
226+
func test8() {
227+
struct CallArgumentTest {
228+
init(_ arg: String) {}
229+
init(label arg: Int) {}
230+
func argTest(_ arg: String) {}
231+
func argTest(label arg: Int) {}
232+
}
233+
var stringVal: String = "";
234+
var intVal: Int = 1
235+
236+
_ = CallArgumentTest(#^CALLARG_1^#)
237+
func methodTest(obj: CallArgumentTest) {
238+
obj.argTest(#^CALLARG_2^#)
239+
}
240+
// CALLARG: (arg: String)
241+
// CALLARG: (label: Int)
242+
// CALLARG: stringVal
243+
// CALLARG: String
244+
// CALLARG: intVal
245+
}

tools/SourceKit/lib/SwiftLang/CodeCompletionOrganizer.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ bool SourceKit::CodeCompletion::addCustomCompletions(
158158
CodeCompletion::SwiftResult swiftResult(
159159
CodeCompletion::SwiftResult::ResultKind::Pattern,
160160
SemanticContextKind::ExpressionSpecific,
161-
/*NumBytesToErase=*/0, completionString,
161+
/*IsArgumentLabels=*/false, /*NumBytesToErase=*/0, completionString,
162162
CodeCompletionResult::ExpectedTypeRelation::Unknown);
163163

164164
CompletionBuilder builder(sink, swiftResult);
@@ -666,6 +666,9 @@ static ResultBucket getResultBucket(Item &item, bool hasRequiredTypes,
666666
!skipMetaGroups)
667667
return ResultBucket::ExpressionSpecific;
668668

669+
if (completion->isArgumentLabels() && !skipMetaGroups)
670+
return ResultBucket::ExpressionSpecific;
671+
669672
if (completion->isOperator())
670673
return ResultBucket::Operator;
671674

@@ -1167,13 +1170,15 @@ Completion *CompletionBuilder::finish() {
11671170

11681171
if (current.getKind() == SwiftResult::Declaration) {
11691172
base = SwiftResult(
1170-
semanticContext, current.getNumBytesToErase(), completionString,
1173+
semanticContext, current.isArgumentLabels(),
1174+
current.getNumBytesToErase(), completionString,
11711175
current.getAssociatedDeclKind(), current.isSystem(),
11721176
current.getModuleName(), current.getNotRecommendedReason(),
11731177
current.getBriefDocComment(), current.getAssociatedUSRs(),
11741178
current.getDeclKeywords(), typeRelation, opKind);
11751179
} else {
11761180
base = SwiftResult(current.getKind(), semanticContext,
1181+
current.isArgumentLabels(),
11771182
current.getNumBytesToErase(), completionString,
11781183
typeRelation, opKind);
11791184
}

tools/SourceKit/lib/SwiftLang/SwiftCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ static void transformAndForwardResults(
912912
CodeCompletionString::create(innerSink.allocator, chunks);
913913
CodeCompletion::SwiftResult paren(
914914
CodeCompletion::SwiftResult::ResultKind::BuiltinOperator,
915-
SemanticContextKind::ExpressionSpecific,
915+
SemanticContextKind::ExpressionSpecific, /*IsArgumentLabels=*/false,
916916
exactMatch ? exactMatch->getNumBytesToErase() : 0, completionString,
917917
CodeCompletionResult::ExpectedTypeRelation::NotApplicable);
918918

0 commit comments

Comments
 (0)