Skip to content

Commit e48fe8c

Browse files
authored
Merge pull request #40351 from bnbarham/annotate-default-args
[CodeComplete] Markup default arguments
2 parents ad7abdc + 65ef802 commit e48fe8c

12 files changed

+192
-147
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@ class CodeCompletionStringChunk {
174174
/// Argument type tag for annotated results.
175175
CallArgumentTypeBegin,
176176

177+
/// Added if the argument has a default value.
178+
CallArgumentDefaultBegin,
179+
177180
/// System type name.
178181
TypeIdSystem,
179182

@@ -252,6 +255,7 @@ class CodeCompletionStringChunk {
252255
Kind == ChunkKind::GenericParameterBegin ||
253256
Kind == ChunkKind::OptionalBegin ||
254257
Kind == ChunkKind::CallArgumentTypeBegin ||
258+
Kind == ChunkKind::CallArgumentDefaultBegin ||
255259
Kind == ChunkKind::TypeAnnotationBegin ||
256260
Kind == ChunkKind::ParameterDeclBegin ||
257261
Kind == ChunkKind::ParameterDeclTypeBegin ||
@@ -958,6 +962,9 @@ struct CodeCompletionResultSink {
958962
/// Whether to perform "call pettern heuristics".
959963
bool enableCallPatternHeuristics = false;
960964

965+
/// Whether to include an item without any default arguments.
966+
bool addCallWithNoDefaultArgs = true;
967+
961968
std::vector<CodeCompletionResult *> Results;
962969

963970
/// A single-element cache for module names stored in Allocator, keyed by a
@@ -1050,6 +1057,13 @@ class CodeCompletionContext {
10501057
return CurrentResults.enableCallPatternHeuristics;
10511058
}
10521059

1060+
void setAddCallWithNoDefaultArgs(bool flag) {
1061+
CurrentResults.addCallWithNoDefaultArgs = flag;
1062+
}
1063+
bool addCallWithNoDefaultArgs() const {
1064+
return CurrentResults.addCallWithNoDefaultArgs;
1065+
}
1066+
10531067
/// Allocate a string owned by the code completion context.
10541068
StringRef copyString(StringRef Str);
10551069

include/swift/IDE/CodeCompletionCache.h

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
#ifndef SWIFT_IDE_CODE_COMPLETIONCACHE_H
1414
#define SWIFT_IDE_CODE_COMPLETIONCACHE_H
1515

16-
#include "swift/IDE/CodeCompletion.h"
1716
#include "swift/Basic/ThreadSafeRefCounted.h"
17+
#include "swift/IDE/CodeCompletion.h"
18+
#include "llvm/ADT/Hashing.h"
1819
#include "llvm/ADT/IntrusiveRefCntPtr.h"
1920
#include "llvm/Support/Chrono.h"
2021
#include <system_error>
@@ -43,17 +44,19 @@ class CodeCompletionCache {
4344
bool ForTestableLookup;
4445
bool ForPrivateImportLookup;
4546
bool AddInitsInToplevel;
47+
bool AddCallWithNoDefaultArgs;
4648
bool Annotated;
4749

4850
friend bool operator==(const Key &LHS, const Key &RHS) {
4951
return LHS.ModuleFilename == RHS.ModuleFilename &&
50-
LHS.ModuleName == RHS.ModuleName &&
51-
LHS.AccessPath == RHS.AccessPath &&
52-
LHS.ResultsHaveLeadingDot == RHS.ResultsHaveLeadingDot &&
53-
LHS.ForTestableLookup == RHS.ForTestableLookup &&
54-
LHS.ForPrivateImportLookup == RHS.ForPrivateImportLookup &&
55-
LHS.AddInitsInToplevel == RHS.AddInitsInToplevel &&
56-
LHS.Annotated == RHS.Annotated;
52+
LHS.ModuleName == RHS.ModuleName &&
53+
LHS.AccessPath == RHS.AccessPath &&
54+
LHS.ResultsHaveLeadingDot == RHS.ResultsHaveLeadingDot &&
55+
LHS.ForTestableLookup == RHS.ForTestableLookup &&
56+
LHS.ForPrivateImportLookup == RHS.ForPrivateImportLookup &&
57+
LHS.AddInitsInToplevel == RHS.AddInitsInToplevel &&
58+
LHS.AddCallWithNoDefaultArgs == RHS.AddCallWithNoDefaultArgs &&
59+
LHS.Annotated == RHS.Annotated;
5760
}
5861
};
5962

@@ -110,23 +113,18 @@ template<>
110113
struct DenseMapInfo<swift::ide::CodeCompletionCache::Key> {
111114
using KeyTy = swift::ide::CodeCompletionCache::Key;
112115
static inline KeyTy getEmptyKey() {
113-
return KeyTy{"", "", {}, false, false, false, false, false};
116+
return KeyTy{"", "", {}, false, false, false, false, false, false};
114117
}
115118
static inline KeyTy getTombstoneKey() {
116-
return KeyTy{"", "", {}, true, false, false, false, false};
119+
return KeyTy{"", "", {}, true, false, false, false, false, false};
117120
}
118121
static unsigned getHashValue(const KeyTy &Val) {
119-
size_t H = 0;
120-
H ^= std::hash<std::string>()(Val.ModuleFilename);
121-
H ^= std::hash<std::string>()(Val.ModuleName);
122-
for (auto Piece : Val.AccessPath)
123-
H ^= std::hash<std::string>()(Piece);
124-
H ^= std::hash<bool>()(Val.ResultsHaveLeadingDot);
125-
H ^= std::hash<bool>()(Val.ForTestableLookup);
126-
H ^= std::hash<bool>()(Val.ForPrivateImportLookup);
127-
H ^= std::hash<bool>()(Val.AddInitsInToplevel);
128-
H ^= std::hash<bool>()(Val.Annotated);
129-
return static_cast<unsigned>(H);
122+
return llvm::hash_combine(
123+
Val.ModuleFilename, Val.ModuleName,
124+
llvm::hash_combine_range(Val.AccessPath.begin(), Val.AccessPath.end()),
125+
Val.ResultsHaveLeadingDot, Val.ForTestableLookup,
126+
Val.ForPrivateImportLookup, Val.AddInitsInToplevel,
127+
Val.AddCallWithNoDefaultArgs, Val.Annotated);
130128
}
131129
static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) {
132130
return LHS == RHS;

lib/IDE/CodeCompletion.cpp

Lines changed: 64 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ void CodeCompletionString::print(raw_ostream &OS) const {
218218
case ChunkKind::DeclResultTypeClauseBegin:
219219
case ChunkKind::ParameterDeclTypeBegin:
220220
case ChunkKind::AttributeAndModifierListBegin:
221+
case ChunkKind::CallArgumentDefaultBegin:
221222
assert(I->getNestingLevel() == PrevNestingLevel + 1);
222223
closeTags.emplace_back("");
223224
break;
@@ -293,6 +294,7 @@ void CodeCompletionString::dump() const {
293294
CASE(DeclAttrParamColon)
294295
CASE(CallArgumentType)
295296
CASE(CallArgumentTypeBegin)
297+
CASE(CallArgumentDefaultBegin)
296298
CASE(TypeIdSystem)
297299
CASE(TypeIdUser)
298300
CASE(CallArgumentClosureType)
@@ -910,8 +912,8 @@ class CodeCompletionStringPrinter : public ASTPrinter {
910912

911913
void CodeCompletionResultBuilder::addCallArgument(
912914
Identifier Name, Identifier LocalName, Type Ty, Type ContextTy,
913-
bool IsVarArg, bool IsInOut, bool IsIUO, bool isAutoClosure,
914-
bool useUnderscoreLabel, bool isLabeledTrailingClosure) {
915+
bool IsVarArg, bool IsInOut, bool IsIUO, bool IsAutoClosure,
916+
bool UseUnderscoreLabel, bool IsLabeledTrailingClosure, bool HasDefault) {
915917
++CurrentNestingLevel;
916918
using ChunkKind = CodeCompletionString::Chunk::ChunkKind;
917919

@@ -952,7 +954,7 @@ void CodeCompletionResultBuilder::addCallArgument(
952954
escapeKeyword(Name.str(), false, EscapedKeyword));
953955
addChunkWithTextNoCopy(
954956
CodeCompletionString::Chunk::ChunkKind::CallArgumentColon, ": ");
955-
} else if (useUnderscoreLabel) {
957+
} else if (UseUnderscoreLabel) {
956958
addChunkWithTextNoCopy(
957959
CodeCompletionString::Chunk::ChunkKind::CallArgumentName, "_");
958960
addChunkWithTextNoCopy(
@@ -978,7 +980,7 @@ void CodeCompletionResultBuilder::addCallArgument(
978980
// If the parameter is of the type @autoclosure ()->output, then the
979981
// code completion should show the parameter of the output type
980982
// instead of the function type ()->output.
981-
if (isAutoClosure) {
983+
if (IsAutoClosure) {
982984
// 'Ty' may be ErrorType.
983985
if (auto funcTy = Ty->getAs<FunctionType>())
984986
Ty = funcTy->getResult();
@@ -1004,6 +1006,12 @@ void CodeCompletionResultBuilder::addCallArgument(
10041006
addChunkWithText(ChunkKind::CallArgumentType, TypeName);
10051007
}
10061008

1009+
if (HasDefault) {
1010+
withNestedGroup(ChunkKind::CallArgumentDefaultBegin, []() {
1011+
// Possibly add the actual value in the future
1012+
});
1013+
}
1014+
10071015
// Look through optional types and type aliases to find out if we have
10081016
// function type.
10091017
Ty = Ty->lookThroughAllOptionalTypes();
@@ -1020,7 +1028,7 @@ void CodeCompletionResultBuilder::addCallArgument(
10201028
if (ContextTy)
10211029
PO.setBaseType(ContextTy);
10221030

1023-
if (isLabeledTrailingClosure) {
1031+
if (IsLabeledTrailingClosure) {
10241032
// Expand the closure body.
10251033
SmallString<32> buffer;
10261034
llvm::raw_svector_ostream OS(buffer);
@@ -1062,6 +1070,7 @@ void CodeCompletionResultBuilder::addCallArgument(
10621070

10631071
if (IsVarArg)
10641072
addEllipsis();
1073+
10651074
--CurrentNestingLevel;
10661075
}
10671076

@@ -1414,6 +1423,7 @@ Optional<unsigned> CodeCompletionString::getFirstTextChunkIndex(
14141423
case ChunkKind::CallArgumentColon:
14151424
case ChunkKind::CallArgumentTypeBegin:
14161425
case ChunkKind::CallArgumentType:
1426+
case ChunkKind::CallArgumentDefaultBegin:
14171427
case ChunkKind::CallArgumentClosureType:
14181428
case ChunkKind::CallArgumentClosureExpr:
14191429
case ChunkKind::ParameterDeclTypeBegin:
@@ -2746,25 +2756,33 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27462756
Builder.addFlair(CodeCompletionFlairBit::ExpressionSpecific);
27472757
}
27482758

2749-
static bool hasInterestingDefaultValues(const AbstractFunctionDecl *func) {
2750-
if (!func) return false;
2759+
static bool hasInterestingDefaultValue(const ParamDecl *param) {
2760+
if (!param)
2761+
return false;
27512762

2752-
for (auto param : *func->getParameters()) {
2753-
switch (param->getDefaultArgumentKind()) {
2754-
case DefaultArgumentKind::Normal:
2755-
case DefaultArgumentKind::NilLiteral:
2756-
case DefaultArgumentKind::EmptyArray:
2757-
case DefaultArgumentKind::EmptyDictionary:
2758-
case DefaultArgumentKind::StoredProperty:
2759-
case DefaultArgumentKind::Inherited: // FIXME: include this?
2760-
return true;
2763+
switch (param->getDefaultArgumentKind()) {
2764+
case DefaultArgumentKind::Normal:
2765+
case DefaultArgumentKind::NilLiteral:
2766+
case DefaultArgumentKind::EmptyArray:
2767+
case DefaultArgumentKind::EmptyDictionary:
2768+
case DefaultArgumentKind::StoredProperty:
2769+
case DefaultArgumentKind::Inherited:
2770+
return true;
27612771

2762-
case DefaultArgumentKind::None:
2772+
case DefaultArgumentKind::None:
27632773
#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
2764-
case DefaultArgumentKind::NAME:
2774+
case DefaultArgumentKind::NAME:
27652775
#include "swift/AST/MagicIdentifierKinds.def"
2766-
break;
2767-
}
2776+
return false;
2777+
}
2778+
}
2779+
2780+
bool addItemWithoutDefaultArgs(const AbstractFunctionDecl *func) {
2781+
if (!func || !Sink.addCallWithNoDefaultArgs)
2782+
return false;
2783+
for (auto param : *func->getParameters()) {
2784+
if (hasInterestingDefaultValue(param))
2785+
return true;
27682786
}
27692787
return false;
27702788
}
@@ -2780,52 +2798,27 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27802798
assert(declParams.empty() || typeParams.size() == declParams.size());
27812799

27822800
bool modifiedBuilder = false;
2783-
2784-
// Determine whether we should skip this argument because it is defaulted.
2785-
auto shouldSkipArg = [&](const ParamDecl *PD) -> bool {
2786-
switch (PD->getDefaultArgumentKind()) {
2787-
case DefaultArgumentKind::None:
2788-
return false;
2789-
2790-
case DefaultArgumentKind::Normal:
2791-
case DefaultArgumentKind::StoredProperty:
2792-
case DefaultArgumentKind::Inherited:
2793-
case DefaultArgumentKind::NilLiteral:
2794-
case DefaultArgumentKind::EmptyArray:
2795-
case DefaultArgumentKind::EmptyDictionary:
2796-
return !includeDefaultArgs;
2797-
2798-
#define MAGIC_IDENTIFIER(NAME, STRING, SYNTAX_KIND) \
2799-
case DefaultArgumentKind::NAME:
2800-
#include "swift/AST/MagicIdentifierKinds.def"
2801-
// Skip parameters that are defaulted to source location or other
2802-
// caller context information. Users typically don't want to specify
2803-
// these parameters.
2804-
return true;
2805-
}
2806-
2807-
llvm_unreachable("Unhandled DefaultArgumentKind in switch.");
2808-
};
2809-
2810-
bool NeedComma = false;
2801+
bool needComma = false;
28112802
// Iterate over each parameter.
28122803
for (unsigned i = 0; i != typeParams.size(); ++i) {
28132804
auto &typeParam = typeParams[i];
28142805

2815-
Identifier argName;
2806+
Identifier argName = typeParam.getLabel();
28162807
Identifier bodyName;
28172808
bool isIUO = false;
2818-
2809+
bool hasDefault = false;
28192810
if (!declParams.empty()) {
2820-
auto *PD = declParams[i];
2821-
if (shouldSkipArg(PD))
2811+
const ParamDecl *PD = declParams[i];
2812+
hasDefault = PD->isDefaultArgument();
2813+
// Skip default arguments if we're either not including them or they
2814+
// aren't interesting
2815+
if (hasDefault &&
2816+
(!includeDefaultArgs || !hasInterestingDefaultValue(PD)))
28222817
continue;
2818+
28232819
argName = PD->getArgumentName();
28242820
bodyName = PD->getParameterName();
28252821
isIUO = PD->isImplicitlyUnwrappedOptional();
2826-
} else {
2827-
isIUO = false;
2828-
argName = typeParam.getLabel();
28292822
}
28302823

28312824
bool isVariadic = typeParam.isVariadic();
@@ -2835,21 +2828,22 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
28352828
if (isVariadic)
28362829
paramTy = ParamDecl::getVarargBaseTy(paramTy);
28372830

2838-
if (NeedComma)
2839-
Builder.addComma();
28402831
Type contextTy;
28412832
if (auto typeContext = CurrDeclContext->getInnermostTypeContext())
28422833
contextTy = typeContext->getDeclaredTypeInContext();
28432834

2835+
if (needComma)
2836+
Builder.addComma();
28442837
Builder.addCallArgument(argName, bodyName,
28452838
eraseArchetypes(paramTy, genericSig), contextTy,
28462839
isVariadic, isInOut, isIUO, isAutoclosure,
2847-
/*useUnderscoreLabel=*/false,
2848-
/*isLabeledTrailingClosure=*/false);
2840+
/*UseUnderscoreLabel=*/false,
2841+
/*IsLabeledTrailingClosure=*/false, hasDefault);
28492842

28502843
modifiedBuilder = true;
2851-
NeedComma = true;
2844+
needComma = true;
28522845
}
2846+
28532847
return modifiedBuilder;
28542848
}
28552849

@@ -3085,7 +3079,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
30853079
if (isImplicitlyCurriedInstanceMethod) {
30863080
addPattern({AFD->getImplicitSelfDecl()}, /*includeDefaultArgs=*/true);
30873081
} else {
3088-
if (hasInterestingDefaultValues(AFD))
3082+
if (addItemWithoutDefaultArgs(AFD))
30893083
addPattern(AFD->getParameters()->getArray(),
30903084
/*includeDefaultArgs=*/false);
30913085
addPattern(AFD->getParameters()->getArray(),
@@ -3289,7 +3283,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
32893283
if (trivialTrailingClosure)
32903284
addMethodImpl(/*includeDefaultArgs=*/false,
32913285
/*trivialTrailingClosure=*/true);
3292-
if (hasInterestingDefaultValues(FD))
3286+
if (addItemWithoutDefaultArgs(FD))
32933287
addMethodImpl(/*includeDefaultArgs=*/false);
32943288
addMethodImpl(/*includeDefaultArgs=*/true);
32953289
}
@@ -3379,8 +3373,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
33793373
}
33803374
};
33813375

3382-
if (ConstructorType && hasInterestingDefaultValues(CD))
3383-
addConstructorImpl(/*includeDefaultArgs*/ false);
3376+
if (ConstructorType && addItemWithoutDefaultArgs(CD))
3377+
addConstructorImpl(/*includeDefaultArgs=*/false);
33843378
addConstructorImpl();
33853379
}
33863380

@@ -4732,9 +4726,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
47324726
Builder.addCallArgument(Arg->getLabel(), Identifier(),
47334727
Arg->getPlainType(), ContextType,
47344728
Arg->isVariadic(), Arg->isInOut(),
4735-
/*isIUO=*/false, Arg->isAutoClosure(),
4736-
/*useUnderscoreLabel=*/true,
4737-
isLabeledTrailingClosure);
4729+
/*IsIUO=*/false, Arg->isAutoClosure(),
4730+
/*UseUnderscoreLabel=*/true,
4731+
isLabeledTrailingClosure, /*HasDefault=*/false);
47384732
Builder.addFlair(CodeCompletionFlairBit::ArgumentLabels);
47394733
auto Ty = Arg->getPlainType();
47404734
if (Arg->isInOut()) {
@@ -6660,8 +6654,8 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
66606654
AccessLevel::Internal, TheModule,
66616655
SourceFile::ImportQueryKind::PrivateOnly),
66626656
CompletionContext.getAddInitsToTopLevel(),
6663-
CompletionContext.getAnnotateResult(),
6664-
};
6657+
CompletionContext.addCallWithNoDefaultArgs(),
6658+
CompletionContext.getAnnotateResult()};
66656659

66666660
using PairType = llvm::DenseSet<swift::ide::CodeCompletionCache::Key,
66676661
llvm::DenseMapInfo<CodeCompletionCache::Key>>::iterator;
@@ -7555,6 +7549,7 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
75557549
Sink.addInitsToTopLevel = context.getAddInitsToTopLevel();
75567550
Sink.enableCallPatternHeuristics = context.getCallPatternHeuristics();
75577551
Sink.includeObjectLiterals = context.includeObjectLiterals();
7552+
Sink.addCallWithNoDefaultArgs = context.addCallWithNoDefaultArgs();
75587553
lookupCodeCompletionResultsFromModule(
75597554
(*V)->Sink, R.TheModule, R.Key.AccessPath,
75607555
R.Key.ResultsHaveLeadingDot, SF);

0 commit comments

Comments
 (0)