@@ -2028,27 +2028,6 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2028
2028
addTypeAnnotation (Builder, VarType);
2029
2029
}
2030
2030
2031
- void addParameters (CodeCompletionResultBuilder &Builder,
2032
- const ParameterList *params) {
2033
- bool NeedComma = false ;
2034
- for (auto ¶m : *params) {
2035
- if (NeedComma)
2036
- Builder.addComma ();
2037
- NeedComma = true ;
2038
-
2039
- Type type = param->getInterfaceType ();
2040
- if (param->isVariadic ())
2041
- type = ParamDecl::getVarargBaseTy (type);
2042
-
2043
- auto isIUO =
2044
- param->getAttrs ().hasAttribute <ImplicitlyUnwrappedOptionalAttr>();
2045
-
2046
- Builder.addCallParameter (param->getArgumentName (), type,
2047
- param->isVariadic (), /* Outermost*/ true ,
2048
- param->isInOut (), isIUO, param->isAutoClosure ());
2049
- }
2050
- }
2051
-
2052
2031
static bool hasInterestingDefaultValues (const AbstractFunctionDecl *func) {
2053
2032
if (!func) return false ;
2054
2033
@@ -2064,99 +2043,98 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2064
2043
return false ;
2065
2044
}
2066
2045
2067
- // Returns true if any content was added to Builder.
2068
- bool addParamPatternFromFunction (CodeCompletionResultBuilder &Builder,
2069
- const AnyFunctionType *AFT,
2070
- const AbstractFunctionDecl *AFD,
2071
- bool includeDefaultArgs = true ) {
2072
-
2073
- const ParameterList *BodyParams = nullptr ;
2074
- const ParamDecl *SelfDecl = nullptr ;
2075
-
2076
- if (AFD) {
2077
- BodyParams = AFD->getParameters ();
2078
-
2079
- // FIXME: Hack because we don't know which parameter list we're
2080
- // actually working with.
2081
- const unsigned expectedNumParams = AFT->getParams ().size ();
2082
- if (expectedNumParams != BodyParams->size ()) {
2083
- BodyParams = nullptr ;
2084
-
2085
- // Adjust to the "self" list if that is present, otherwise give up.
2086
- if (expectedNumParams == 1 && AFD->getImplicitSelfDecl ())
2087
- SelfDecl = AFD->getImplicitSelfDecl ();
2088
- BodyParams = nullptr ;
2089
- }
2090
- }
2046
+ // / Build argument patterns for calling. Returns \c true if any content was
2047
+ // / added to \p Builder. If \p declParams is non-empty, the size must match
2048
+ // / with \p typeParams.
2049
+ bool addCallArgumentPatterns (CodeCompletionResultBuilder &Builder,
2050
+ ArrayRef<AnyFunctionType::Param> typeParams,
2051
+ ArrayRef<const ParamDecl *> declParams,
2052
+ bool includeDefaultArgs = true ) {
2053
+ assert (declParams.empty () || typeParams.size () == declParams.size ());
2091
2054
2092
2055
bool modifiedBuilder = false ;
2093
2056
2094
2057
// Determine whether we should skip this argument because it is defaulted.
2095
- auto shouldSkipArg = [&](unsigned i) -> bool {
2096
- if (!BodyParams || i >= BodyParams->size ())
2058
+ auto shouldSkipArg = [&](const ParamDecl *PD) -> bool {
2059
+ switch (PD->getDefaultArgumentKind ()) {
2060
+ case DefaultArgumentKind::None:
2097
2061
return false ;
2098
2062
2099
- switch (BodyParams->get (i)->getDefaultArgumentKind ()) {
2100
- case DefaultArgumentKind::None:
2101
- return false ;
2102
-
2103
- case DefaultArgumentKind::Normal:
2104
- case DefaultArgumentKind::Inherited:
2105
- case DefaultArgumentKind::NilLiteral:
2106
- case DefaultArgumentKind::EmptyArray:
2107
- case DefaultArgumentKind::EmptyDictionary:
2108
- return !includeDefaultArgs;
2109
-
2110
- case DefaultArgumentKind::File:
2111
- case DefaultArgumentKind::Line:
2112
- case DefaultArgumentKind::Column:
2113
- case DefaultArgumentKind::Function:
2114
- case DefaultArgumentKind::DSOHandle:
2115
- // Skip parameters that are defaulted to source location or other
2116
- // caller context information. Users typically don't want to specify
2117
- // these parameters.
2118
- return true ;
2063
+ case DefaultArgumentKind::Normal:
2064
+ case DefaultArgumentKind::Inherited:
2065
+ case DefaultArgumentKind::NilLiteral:
2066
+ case DefaultArgumentKind::EmptyArray:
2067
+ case DefaultArgumentKind::EmptyDictionary:
2068
+ return !includeDefaultArgs;
2069
+
2070
+ case DefaultArgumentKind::File:
2071
+ case DefaultArgumentKind::Line:
2072
+ case DefaultArgumentKind::Column:
2073
+ case DefaultArgumentKind::Function:
2074
+ case DefaultArgumentKind::DSOHandle:
2075
+ // Skip parameters that are defaulted to source location or other
2076
+ // caller context information. Users typically don't want to specify
2077
+ // these parameters.
2078
+ return true ;
2119
2079
}
2120
2080
2121
2081
llvm_unreachable (" Unhandled DefaultArgumentKind in switch." );
2122
2082
};
2123
2083
2124
2084
bool NeedComma = false ;
2125
2085
// Iterate over each parameter.
2126
- for (unsigned i = 0 , e = AFT->getParams ().size (); i != e; ++i) {
2127
- // If we should skip this argument, do so.
2128
- if (shouldSkipArg (i)) continue ;
2086
+ for (unsigned i = 0 ; i != typeParams.size (); ++i) {
2087
+ auto &typeParam = typeParams[i];
2129
2088
2130
- const auto &Param = AFT->getParams ()[i];
2131
- auto ParamType = Param.isVariadic ()
2132
- ? ParamDecl::getVarargBaseTy (Param.getPlainType ())
2133
- : Param.getPlainType ();
2089
+ Identifier argName;
2090
+ Identifier bodyName;
2091
+ bool isIUO = false ;
2134
2092
2135
- if (NeedComma)
2136
- Builder.addComma ();
2137
- if (BodyParams || SelfDecl) {
2138
- auto *PD = (BodyParams ? BodyParams->get (i) : SelfDecl);
2139
-
2140
- // If we have a local name for the parameter, pass in that as well.
2141
- auto argName = PD->getArgumentName ();
2142
- auto bodyName = PD->getName ();
2143
- auto isIUO =
2144
- PD->getAttrs ().hasAttribute <ImplicitlyUnwrappedOptionalAttr>();
2145
- Builder.addCallParameter (argName, bodyName, ParamType,
2146
- Param.isVariadic (), /* TopLevel*/ true ,
2147
- Param.isInOut (), isIUO, Param.isAutoClosure ());
2093
+ if (!declParams.empty ()) {
2094
+ auto *PD = declParams[i];
2095
+ if (shouldSkipArg (PD))
2096
+ continue ;
2097
+ argName = PD->getArgumentName ();
2098
+ bodyName = PD->getParameterName ();
2099
+ isIUO = PD->getAttrs ().hasAttribute <ImplicitlyUnwrappedOptionalAttr>();
2148
2100
} else {
2149
- Builder.addCallParameter (
2150
- Param.getLabel (), ParamType, Param.isVariadic (), /* TopLevel*/ true ,
2151
- Param.isInOut (), /* isIUO*/ false , Param.isAutoClosure ());
2101
+ isIUO = false ;
2102
+ argName = typeParam.getLabel ();
2152
2103
}
2104
+
2105
+ bool isVariadic = typeParam.isVariadic ();
2106
+ bool isInOut = typeParam.isInOut ();
2107
+ bool isAutoclosure = typeParam.isAutoClosure ();
2108
+ Type paramTy = typeParam.getPlainType ();
2109
+ if (isVariadic)
2110
+ paramTy = ParamDecl::getVarargBaseTy (paramTy);
2111
+
2112
+ if (NeedComma)
2113
+ Builder.addComma ();
2114
+
2115
+ Builder.addCallParameter (argName, bodyName, paramTy, isVariadic,
2116
+ /* TopLevel*/ true , isInOut, isIUO,
2117
+ isAutoclosure);
2118
+
2153
2119
modifiedBuilder = true ;
2154
2120
NeedComma = true ;
2155
2121
}
2156
-
2157
2122
return modifiedBuilder;
2158
2123
}
2159
2124
2125
+ // / Build argument patterns for calling. Returns \c true if any content was
2126
+ // / added to \p Builder. If \p Params is non-nullptr, \F
2127
+ bool addCallArgumentPatterns (CodeCompletionResultBuilder &Builder,
2128
+ const AnyFunctionType *AFT,
2129
+ const ParameterList *Params,
2130
+ bool includeDefaultArgs = true ) {
2131
+ ArrayRef<const ParamDecl *> declParams;
2132
+ if (Params)
2133
+ declParams = Params->getArray ();
2134
+ return addCallArgumentPatterns (Builder, AFT->getParams (), declParams,
2135
+ includeDefaultArgs);
2136
+ }
2137
+
2160
2138
static void addThrows (CodeCompletionResultBuilder &Builder,
2161
2139
const AnyFunctionType *AFT,
2162
2140
const AbstractFunctionDecl *AFD) {
@@ -2226,13 +2204,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2226
2204
2227
2205
void addFunctionCallPattern (const AnyFunctionType *AFT,
2228
2206
const AbstractFunctionDecl *AFD = nullptr ) {
2229
- if (AFD)
2230
- foundFunction (AFD);
2231
- else
2232
- foundFunction (AFT);
2233
2207
2234
2208
// Add the pattern, possibly including any default arguments.
2235
- auto addPattern = [&](bool includeDefaultArgs = true ) {
2209
+ auto addPattern = [&](ArrayRef<const ParamDecl *> declParams = {},
2210
+ bool includeDefaultArgs = true ) {
2236
2211
// FIXME: to get the corect semantic context we need to know how lookup
2237
2212
// would have found the declaration AFD. For now, just choose a reasonable
2238
2213
// default, it's most likely to be CurrentModule or CurrentNominal.
@@ -2244,7 +2219,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2244
2219
else
2245
2220
Builder.addAnnotatedLeftParen ();
2246
2221
2247
- bool anyParam = addParamPatternFromFunction (Builder, AFT, AFD, includeDefaultArgs);
2222
+ bool anyParam = addCallArgumentPatterns (Builder, AFT->getParams (),
2223
+ declParams, includeDefaultArgs);
2248
2224
2249
2225
if (HaveLParen && !anyParam) {
2250
2226
// Empty result, don't add it.
@@ -2268,10 +2244,49 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2268
2244
addTypeAnnotation (Builder, AFT->getResult ());
2269
2245
};
2270
2246
2271
- if (hasInterestingDefaultValues (AFD))
2272
- addPattern (/* includeDefaultArgs*/ false );
2273
- addPattern ();
2247
+ if (!AFD || !AFD->hasInterfaceType () ||
2248
+ !AFD->getInterfaceType ()->is <AnyFunctionType>()) {
2249
+ // Probably, calling closure type expression.
2250
+ foundFunction (AFT);
2251
+ addPattern ();
2252
+ return ;
2253
+ } else {
2254
+ // Calling function or method.
2255
+ foundFunction (AFD);
2256
+
2257
+ // FIXME: Hack because we don't know we are calling instance
2258
+ // method or not. There's invariant that funcTy is derived from AFD.
2259
+ // Only if we are calling instance method on meta type, AFT is still
2260
+ // curried. So we should be able to detect that by comparing curried level
2261
+ // of AFT and the interface type of AFD.
2262
+ auto getCurriedLevel = [](const AnyFunctionType *funcTy) -> unsigned {
2263
+ unsigned level = 0 ;
2264
+ while ((funcTy = funcTy->getResult ()->getAs <AnyFunctionType>()))
2265
+ ++level;
2266
+ return level;
2267
+ };
2268
+ bool isImplicitlyCurriedInstanceMethod =
2269
+ (AFD->hasImplicitSelfDecl () &&
2270
+ getCurriedLevel (AFT) ==
2271
+ getCurriedLevel (
2272
+ AFD->getInterfaceType ()->castTo <AnyFunctionType>()) &&
2273
+ // NOTE: shouldn't be necessary, but just in case curried level check
2274
+ // is insufficient.
2275
+ AFT->getParams ().size () == 1 &&
2276
+ AFT->getParams ()[0 ].getLabel ().empty ());
2277
+
2278
+ if (isImplicitlyCurriedInstanceMethod) {
2279
+ addPattern ({AFD->getImplicitSelfDecl ()}, /* includeDefaultArgs=*/ true );
2280
+ } else {
2281
+ if (hasInterestingDefaultValues (AFD))
2282
+ addPattern (AFD->getParameters ()->getArray (),
2283
+ /* includeDefaultArgs=*/ false );
2284
+ addPattern (AFD->getParameters ()->getArray (),
2285
+ /* includeDefaultArgs=*/ true );
2286
+ }
2287
+ }
2274
2288
}
2289
+
2275
2290
bool isImplicitlyCurriedInstanceMethod (const AbstractFunctionDecl *FD) {
2276
2291
switch (Kind) {
2277
2292
case LookupKind::ValueExpr:
@@ -2359,17 +2374,16 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2359
2374
auto AFT = FunctionType->castTo <AnyFunctionType>();
2360
2375
if (IsImplicitlyCurriedInstanceMethod) {
2361
2376
Builder.addLeftParen ();
2362
- auto SelfParam = AFT->getParams ()[0 ];
2363
- Builder.addCallParameter (Ctx.Id_self , SelfParam.getPlainType (),
2364
- /* IsVarArg*/ false , /* TopLevel*/ true ,
2365
- SelfParam.isInOut (),
2366
- /* isIUO*/ false , /* isAutoClosure*/ false );
2377
+ addCallArgumentPatterns (Builder, AFT->getParams (),
2378
+ {FD->getImplicitSelfDecl ()},
2379
+ includeDefaultArgs);
2367
2380
Builder.addRightParen ();
2368
2381
} else if (trivialTrailingClosure) {
2369
2382
Builder.addBraceStmtWithCursor (" { code }" );
2370
2383
} else {
2371
2384
Builder.addLeftParen ();
2372
- addParamPatternFromFunction (Builder, AFT, FD, includeDefaultArgs);
2385
+ addCallArgumentPatterns (Builder, AFT, FD->getParameters (),
2386
+ includeDefaultArgs);
2373
2387
Builder.addRightParen ();
2374
2388
addThrows (Builder, AFT, FD);
2375
2389
}
@@ -2465,8 +2479,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2465
2479
else
2466
2480
Builder.addAnnotatedLeftParen ();
2467
2481
2468
- bool anyParam = addParamPatternFromFunction (Builder, ConstructorType, CD,
2469
- includeDefaultArgs);
2482
+ bool anyParam = addCallArgumentPatterns (
2483
+ Builder, ConstructorType, CD-> getParameters (), includeDefaultArgs);
2470
2484
2471
2485
if (HaveLParen && !anyParam) {
2472
2486
// Empty result, don't add it.
@@ -2549,7 +2563,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2549
2563
}
2550
2564
2551
2565
Builder.addLeftBracket ();
2552
- addParameters (Builder, SD->getIndices ());
2566
+ addCallArgumentPatterns (Builder,
2567
+ getTypeOfMember (SD)->castTo <AnyFunctionType>(),
2568
+ SD->getIndices (), true );
2553
2569
Builder.addRightBracket ();
2554
2570
2555
2571
// Add a type annotation.
@@ -2666,6 +2682,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2666
2682
Builder.setAssociatedDecl (EED);
2667
2683
setClangDeclKeywords (EED, Pairs, Builder);
2668
2684
addLeadingDot (Builder);
2685
+
2669
2686
Builder.addTextChunk (EED->getName ().str ());
2670
2687
2671
2688
// Enum element is of function type; (Self.type) -> Self or
@@ -2676,8 +2693,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2676
2693
2677
2694
if (EnumType->is <FunctionType>()) {
2678
2695
Builder.addLeftParen ();
2679
- addParamPatternFromFunction (Builder, EnumType->castTo <FunctionType>(),
2680
- nullptr );
2696
+ addCallArgumentPatterns (Builder, EnumType->castTo <FunctionType>(),
2697
+ EED-> getParameterList () );
2681
2698
Builder.addRightParen ();
2682
2699
2683
2700
// Extract result as the enum type.
0 commit comments