@@ -1185,8 +1185,6 @@ void CodeCompletionString::getName(raw_ostream &OS) const {
11851185 }
11861186 }
11871187 }
1188- assert ((TextSize > 0 ) &&
1189- " code completion string should have non-empty name!" );
11901188}
11911189
11921190void CodeCompletionContext::sortCompletionResults (
@@ -1348,6 +1346,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13481346 void completeTypeIdentifierWithDot (IdentTypeRepr *ITR) override ;
13491347 void completeTypeIdentifierWithoutDot (IdentTypeRepr *ITR) override ;
13501348
1349+ void completeCaseStmtKeyword () override ;
13511350 void completeCaseStmtBeginning () override ;
13521351 void completeCaseStmtDotPrefix () override ;
13531352 void completeDeclAttrKeyword (Decl *D, bool Sil, bool Param) override ;
@@ -1823,6 +1822,32 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
18231822 llvm_unreachable (" unhandled kind" );
18241823 }
18251824
1825+ void addValueBaseName (CodeCompletionResultBuilder &Builder,
1826+ DeclBaseName Name) {
1827+ auto NameStr = Name.userFacingName ();
1828+ bool shouldEscapeKeywords;
1829+ if (Name.isSpecial ()) {
1830+ // Special names (i.e. 'init') are always displayed as its user facing
1831+ // name.
1832+ shouldEscapeKeywords = false ;
1833+ } else if (ExprType) {
1834+ // After dot. User can write any keyword after '.' except for `init` and
1835+ // `self`. E.g. 'func `init`()' must be called by 'expr.`init`()'.
1836+ shouldEscapeKeywords = NameStr == " self" || NameStr == " init" ;
1837+ } else {
1838+ // As primary expresson. We have to escape almost every keywords except
1839+ // for 'self' and 'Self'.
1840+ shouldEscapeKeywords = NameStr != " self" && NameStr != " Self" ;
1841+ }
1842+
1843+ if (!shouldEscapeKeywords) {
1844+ Builder.addTextChunk (NameStr);
1845+ } else {
1846+ SmallString<16 > buffer;
1847+ Builder.addTextChunk (Builder.escapeKeyword (NameStr, true , buffer));
1848+ }
1849+ }
1850+
18261851 void addLeadingDot (CodeCompletionResultBuilder &Builder) {
18271852 if (NeedOptionalUnwrap) {
18281853 Builder.setNumBytesToErase (NumBytesToEraseForOptionalUnwrap);
@@ -1995,7 +2020,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
19952020 VD->shouldHideFromEditor ())
19962021 return ;
19972022
1998- StringRef Name = VD->getName (). get ();
2023+ Identifier Name = VD->getName ();
19992024 assert (!Name.empty () && " name should not be empty" );
20002025
20012026 CommandWordsPairs Pairs;
@@ -2005,15 +2030,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
20052030 getSemanticContext (VD, Reason), ExpectedTypes);
20062031 Builder.setAssociatedDecl (VD);
20072032 addLeadingDot (Builder);
2008- Builder. addTextChunk ( Name);
2033+ addValueBaseName (Builder, Name);
20092034 setClangDeclKeywords (VD, Pairs, Builder);
20102035
20112036 if (!VD->hasValidSignature ())
20122037 return ;
20132038
20142039 // Add a type annotation.
20152040 Type VarType = getTypeOfMember (VD);
2016- if (VD-> getName () != Ctx.Id_self && VD->isInOut ()) {
2041+ if (Name != Ctx.Id_self && VD->isInOut ()) {
20172042 // It is useful to show inout for function parameters.
20182043 // But for 'self' it is just noise.
20192044 VarType = InOutType::get (VarType);
@@ -2222,14 +2247,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
22222247 else
22232248 Builder.addAnnotatedLeftParen ();
22242249
2225- bool anyParam = addCallArgumentPatterns (Builder, AFT->getParams (),
2226- declParams, includeDefaultArgs);
2227-
2228- if (HaveLParen && !anyParam) {
2229- // Empty result, don't add it.
2230- Builder.cancel ();
2231- return ;
2232- }
2250+ addCallArgumentPatterns (Builder, AFT->getParams (), declParams,
2251+ includeDefaultArgs);
22332252
22342253 // The rparen matches the lparen here so that we insert both or neither.
22352254 if (!HaveLParen)
@@ -2319,7 +2338,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
23192338 return ;
23202339 foundFunction (FD);
23212340
2322- StringRef Name = FD->getName (). get ();
2341+ Identifier Name = FD->getName ();
23232342 assert (!Name.empty () && " name should not be empty" );
23242343
23252344 Type FunctionType = getTypeOfMember (FD);
@@ -2350,7 +2369,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
23502369 setClangDeclKeywords (FD, Pairs, Builder);
23512370 Builder.setAssociatedDecl (FD);
23522371 addLeadingDot (Builder);
2353- Builder. addTextChunk ( Name);
2372+ addValueBaseName (Builder, Name);
23542373 if (IsDynamicLookup)
23552374 Builder.addDynamicLookupMethodCallTail ();
23562375 else if (FD->getAttrs ().hasAttribute <OptionalAttr>())
@@ -2475,14 +2494,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
24752494 else
24762495 Builder.addAnnotatedLeftParen ();
24772496
2478- bool anyParam = addCallArgumentPatterns (
2479- Builder, ConstructorType, CD->getParameters (), includeDefaultArgs);
2480-
2481- if (HaveLParen && !anyParam) {
2482- // Empty result, don't add it.
2483- Builder.cancel ();
2484- return ;
2485- }
2497+ addCallArgumentPatterns (Builder, ConstructorType, CD->getParameters (),
2498+ includeDefaultArgs);
24862499
24872500 // The rparen matches the lparen here so that we insert both or neither.
24882501 if (!HaveLParen)
@@ -2680,8 +2693,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
26802693 Builder.setAssociatedDecl (EED);
26812694 setClangDeclKeywords (EED, Pairs, Builder);
26822695 addLeadingDot (Builder);
2683-
2684- Builder.addTextChunk (EED->getName ().str ());
2696+ addValueBaseName (Builder, EED->getName ());
26852697
26862698 // Enum element is of function type; (Self.type) -> Self or
26872699 // (Self.Type) -> (Args...) -> Self.
@@ -2705,7 +2717,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27052717 void addKeyword (StringRef Name, Type TypeAnnotation = Type(),
27062718 SemanticContextKind SK = SemanticContextKind::None,
27072719 CodeCompletionKeywordKind KeyKind
2708- = CodeCompletionKeywordKind::None) {
2720+ = CodeCompletionKeywordKind::None,
2721+ unsigned NumBytesToErase = 0) {
27092722 CodeCompletionResultBuilder Builder (
27102723 Sink,
27112724 CodeCompletionResult::ResultKind::Keyword, SK, ExpectedTypes);
@@ -2714,6 +2727,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27142727 Builder.setKeywordKind (KeyKind);
27152728 if (TypeAnnotation)
27162729 addTypeAnnotation (Builder, TypeAnnotation);
2730+ if (NumBytesToErase > 0 )
2731+ Builder.setNumBytesToErase (NumBytesToErase);
27172732 }
27182733
27192734 void addKeyword (StringRef Name, StringRef TypeAnnotation,
@@ -2759,7 +2774,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
27592774
27602775 // Base name
27612776 addLeadingDot (Builder);
2762- Builder. addTextChunk ( AFD->getBaseName (). userFacingName ());
2777+ addValueBaseName (Builder, AFD->getBaseName ());
27632778
27642779 // Add the argument labels.
27652780 auto ArgLabels = AFD->getFullName ().getArgumentNames ();
@@ -3600,6 +3615,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36003615 return false ;
36013616 }
36023617
3618+ if (T->getOptionalObjectType () &&
3619+ VD->getModuleContext ()->isStdlibModule ()) {
3620+ // In optional context, ignore '.init(<some>)', 'init(nilLiteral:)',
3621+ if (isa<ConstructorDecl>(VD))
3622+ return false ;
3623+ // TODO: Ignore '.some(<Wrapped>)' and '.none' too *in expression
3624+ // context*. They are useful in pattern context though.
3625+ }
3626+
36033627 // Enum element decls can always be referenced by implicit member
36043628 // expression.
36053629 if (isa<EnumElementDecl>(VD))
@@ -3670,6 +3694,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
36703694 // If this is optional type, perform completion for the object type.
36713695 // i.e. 'let _: Enum??? = .enumMember' is legal.
36723696 getUnresolvedMemberCompletions (objT->lookThroughAllOptionalTypes ());
3697+
3698+ // Add 'nil' keyword with erasing '.' instruction.
3699+ unsigned bytesToErase = 0 ;
3700+ auto &SM = CurrDeclContext->getASTContext ().SourceMgr ;
3701+ if (DotLoc.isValid ())
3702+ bytesToErase = SM.getByteDistance (DotLoc, SM.getCodeCompletionLoc ());
3703+ addKeyword (" nil" , T, SemanticContextKind::ExpressionSpecific,
3704+ CodeCompletionKeywordKind::kw_nil, bytesToErase);
36733705 }
36743706 getUnresolvedMemberCompletions (T);
36753707 }
@@ -4417,6 +4449,11 @@ void CodeCompletionCallbacksImpl::completeTypeIdentifierWithoutDot(
44174449 CurDeclContext = P.CurDeclContext ;
44184450}
44194451
4452+ void CodeCompletionCallbacksImpl::completeCaseStmtKeyword () {
4453+ Kind = CompletionKind::CaseStmtKeyword;
4454+ CurDeclContext = P.CurDeclContext ;
4455+ }
4456+
44204457void CodeCompletionCallbacksImpl::completeCaseStmtBeginning () {
44214458 assert (!InEnumElementRawValue);
44224459
@@ -4598,6 +4635,11 @@ static void addStmtKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody)
45984635#include " swift/Syntax/TokenKinds.def"
45994636}
46004637
4638+ static void addCaseStmtKeywords (CodeCompletionResultSink &Sink) {
4639+ addKeyword (Sink, " case" , CodeCompletionKeywordKind::kw_case);
4640+ addKeyword (Sink, " default" , CodeCompletionKeywordKind::kw_default);
4641+ }
4642+
46014643static void addLetVarKeywords (CodeCompletionResultSink &Sink) {
46024644 addKeyword (Sink, " let" , CodeCompletionKeywordKind::kw_let);
46034645 addKeyword (Sink, " var" , CodeCompletionKeywordKind::kw_var);
@@ -4687,6 +4729,10 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
46874729 addAnyTypeKeyword (Sink);
46884730 break ;
46894731
4732+ case CompletionKind::CaseStmtKeyword:
4733+ addCaseStmtKeywords (Sink);
4734+ break ;
4735+
46904736 case CompletionKind::PostfixExpr:
46914737 case CompletionKind::PostfixExprParen:
46924738 case CompletionKind::SuperExpr:
@@ -4954,19 +5000,30 @@ void CodeCompletionCallbacksImpl::doneParsing() {
49545000 bool OnRoot = !KPE->getComponents ().front ().isValid ();
49555001 Lookup.setIsSwiftKeyPathExpr (OnRoot);
49565002
4957- auto ParsedType = BGT->getGenericArgs ()[1 ];
4958- auto Components = KPE->getComponents ();
4959- if (Components.back ().getKind () ==
4960- KeyPathExpr::Component::Kind::OptionalWrap) {
5003+ Type baseType = BGT->getGenericArgs ()[OnRoot ? 0 : 1 ];
5004+ if (OnRoot && baseType->is <UnresolvedType>()) {
5005+ // Infer the root type of the keypath from the context type.
5006+ ExprContextInfo ContextInfo (CurDeclContext, ParsedExpr);
5007+ for (auto T : ContextInfo.getPossibleTypes ()) {
5008+ if (auto unwrapped = T->getOptionalObjectType ())
5009+ T = unwrapped;
5010+ if (!T->getAnyNominal () || !T->getAnyNominal ()->getKeyPathTypeKind () ||
5011+ T->hasUnresolvedType () || !T->is <BoundGenericType>())
5012+ continue ;
5013+ // Use the first KeyPath context type found.
5014+ baseType = T->castTo <BoundGenericType>()->getGenericArgs ()[0 ];
5015+ break ;
5016+ }
5017+ }
5018+ if (!OnRoot && KPE->getComponents ().back ().getKind () ==
5019+ KeyPathExpr::Component::Kind::OptionalWrap) {
49615020 // KeyPath expr with '?' (e.g. '\Ty.[0].prop?.another').
49625021 // Althogh expected type is optional, we should unwrap it because it's
49635022 // unwrapped.
4964- ParsedType = ParsedType ->getOptionalObjectType ();
5023+ baseType = baseType ->getOptionalObjectType ();
49655024 }
49665025
4967- // The second generic type argument of KeyPath<Root, Value> should be
4968- // the value we pull code completion results from.
4969- Lookup.getValueExprCompletions (ParsedType);
5026+ Lookup.getValueExprCompletions (baseType);
49705027 break ;
49715028 }
49725029
@@ -5189,12 +5246,13 @@ void CodeCompletionCallbacksImpl::doneParsing() {
51895246 }
51905247 }
51915248 break ;
5192- case CompletionKind::AfterIfStmtElse:
5193- // Handled earlier by keyword completions.
5194- break ;
51955249 case CompletionKind::PrecedenceGroup:
51965250 Lookup.getPrecedenceGroupCompletions (SyntxKind);
51975251 break ;
5252+ case CompletionKind::AfterIfStmtElse:
5253+ case CompletionKind::CaseStmtKeyword:
5254+ // Handled earlier by keyword completions.
5255+ break ;
51985256 }
51995257
52005258 for (auto &Request: Lookup.RequestedCachedResults ) {
0 commit comments