@@ -1185,8 +1185,6 @@ void CodeCompletionString::getName(raw_ostream &OS) const {
1185
1185
}
1186
1186
}
1187
1187
}
1188
- assert ((TextSize > 0 ) &&
1189
- " code completion string should have non-empty name!" );
1190
1188
}
1191
1189
1192
1190
void CodeCompletionContext::sortCompletionResults (
@@ -1348,6 +1346,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
1348
1346
void completeTypeIdentifierWithDot (IdentTypeRepr *ITR) override ;
1349
1347
void completeTypeIdentifierWithoutDot (IdentTypeRepr *ITR) override ;
1350
1348
1349
+ void completeCaseStmtKeyword () override ;
1351
1350
void completeCaseStmtBeginning () override ;
1352
1351
void completeCaseStmtDotPrefix () override ;
1353
1352
void completeDeclAttrKeyword (Decl *D, bool Sil, bool Param) override ;
@@ -1823,6 +1822,32 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1823
1822
llvm_unreachable (" unhandled kind" );
1824
1823
}
1825
1824
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
+
1826
1851
void addLeadingDot (CodeCompletionResultBuilder &Builder) {
1827
1852
if (NeedOptionalUnwrap) {
1828
1853
Builder.setNumBytesToErase (NumBytesToEraseForOptionalUnwrap);
@@ -1995,7 +2020,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
1995
2020
VD->shouldHideFromEditor ())
1996
2021
return ;
1997
2022
1998
- StringRef Name = VD->getName (). get ();
2023
+ Identifier Name = VD->getName ();
1999
2024
assert (!Name.empty () && " name should not be empty" );
2000
2025
2001
2026
CommandWordsPairs Pairs;
@@ -2005,15 +2030,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2005
2030
getSemanticContext (VD, Reason), ExpectedTypes);
2006
2031
Builder.setAssociatedDecl (VD);
2007
2032
addLeadingDot (Builder);
2008
- Builder. addTextChunk ( Name);
2033
+ addValueBaseName (Builder, Name);
2009
2034
setClangDeclKeywords (VD, Pairs, Builder);
2010
2035
2011
2036
if (!VD->hasValidSignature ())
2012
2037
return ;
2013
2038
2014
2039
// Add a type annotation.
2015
2040
Type VarType = getTypeOfMember (VD);
2016
- if (VD-> getName () != Ctx.Id_self && VD->isInOut ()) {
2041
+ if (Name != Ctx.Id_self && VD->isInOut ()) {
2017
2042
// It is useful to show inout for function parameters.
2018
2043
// But for 'self' it is just noise.
2019
2044
VarType = InOutType::get (VarType);
@@ -2222,14 +2247,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2222
2247
else
2223
2248
Builder.addAnnotatedLeftParen ();
2224
2249
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);
2233
2252
2234
2253
// The rparen matches the lparen here so that we insert both or neither.
2235
2254
if (!HaveLParen)
@@ -2319,7 +2338,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2319
2338
return ;
2320
2339
foundFunction (FD);
2321
2340
2322
- StringRef Name = FD->getName (). get ();
2341
+ Identifier Name = FD->getName ();
2323
2342
assert (!Name.empty () && " name should not be empty" );
2324
2343
2325
2344
Type FunctionType = getTypeOfMember (FD);
@@ -2350,7 +2369,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2350
2369
setClangDeclKeywords (FD, Pairs, Builder);
2351
2370
Builder.setAssociatedDecl (FD);
2352
2371
addLeadingDot (Builder);
2353
- Builder. addTextChunk ( Name);
2372
+ addValueBaseName (Builder, Name);
2354
2373
if (IsDynamicLookup)
2355
2374
Builder.addDynamicLookupMethodCallTail ();
2356
2375
else if (FD->getAttrs ().hasAttribute <OptionalAttr>())
@@ -2475,14 +2494,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2475
2494
else
2476
2495
Builder.addAnnotatedLeftParen ();
2477
2496
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);
2486
2499
2487
2500
// The rparen matches the lparen here so that we insert both or neither.
2488
2501
if (!HaveLParen)
@@ -2680,8 +2693,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2680
2693
Builder.setAssociatedDecl (EED);
2681
2694
setClangDeclKeywords (EED, Pairs, Builder);
2682
2695
addLeadingDot (Builder);
2683
-
2684
- Builder.addTextChunk (EED->getName ().str ());
2696
+ addValueBaseName (Builder, EED->getName ());
2685
2697
2686
2698
// Enum element is of function type; (Self.type) -> Self or
2687
2699
// (Self.Type) -> (Args...) -> Self.
@@ -2705,7 +2717,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2705
2717
void addKeyword (StringRef Name, Type TypeAnnotation = Type(),
2706
2718
SemanticContextKind SK = SemanticContextKind::None,
2707
2719
CodeCompletionKeywordKind KeyKind
2708
- = CodeCompletionKeywordKind::None) {
2720
+ = CodeCompletionKeywordKind::None,
2721
+ unsigned NumBytesToErase = 0) {
2709
2722
CodeCompletionResultBuilder Builder (
2710
2723
Sink,
2711
2724
CodeCompletionResult::ResultKind::Keyword, SK, ExpectedTypes);
@@ -2714,6 +2727,8 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2714
2727
Builder.setKeywordKind (KeyKind);
2715
2728
if (TypeAnnotation)
2716
2729
addTypeAnnotation (Builder, TypeAnnotation);
2730
+ if (NumBytesToErase > 0 )
2731
+ Builder.setNumBytesToErase (NumBytesToErase);
2717
2732
}
2718
2733
2719
2734
void addKeyword (StringRef Name, StringRef TypeAnnotation,
@@ -2759,7 +2774,7 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
2759
2774
2760
2775
// Base name
2761
2776
addLeadingDot (Builder);
2762
- Builder. addTextChunk ( AFD->getBaseName (). userFacingName ());
2777
+ addValueBaseName (Builder, AFD->getBaseName ());
2763
2778
2764
2779
// Add the argument labels.
2765
2780
auto ArgLabels = AFD->getFullName ().getArgumentNames ();
@@ -3600,6 +3615,15 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3600
3615
return false ;
3601
3616
}
3602
3617
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
+
3603
3627
// Enum element decls can always be referenced by implicit member
3604
3628
// expression.
3605
3629
if (isa<EnumElementDecl>(VD))
@@ -3670,6 +3694,14 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3670
3694
// If this is optional type, perform completion for the object type.
3671
3695
// i.e. 'let _: Enum??? = .enumMember' is legal.
3672
3696
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);
3673
3705
}
3674
3706
getUnresolvedMemberCompletions (T);
3675
3707
}
@@ -4417,6 +4449,11 @@ void CodeCompletionCallbacksImpl::completeTypeIdentifierWithoutDot(
4417
4449
CurDeclContext = P.CurDeclContext ;
4418
4450
}
4419
4451
4452
+ void CodeCompletionCallbacksImpl::completeCaseStmtKeyword () {
4453
+ Kind = CompletionKind::CaseStmtKeyword;
4454
+ CurDeclContext = P.CurDeclContext ;
4455
+ }
4456
+
4420
4457
void CodeCompletionCallbacksImpl::completeCaseStmtBeginning () {
4421
4458
assert (!InEnumElementRawValue);
4422
4459
@@ -4598,6 +4635,11 @@ static void addStmtKeywords(CodeCompletionResultSink &Sink, bool MaybeFuncBody)
4598
4635
#include " swift/Syntax/TokenKinds.def"
4599
4636
}
4600
4637
4638
+ static void addCaseStmtKeywords (CodeCompletionResultSink &Sink) {
4639
+ addKeyword (Sink, " case" , CodeCompletionKeywordKind::kw_case);
4640
+ addKeyword (Sink, " default" , CodeCompletionKeywordKind::kw_default);
4641
+ }
4642
+
4601
4643
static void addLetVarKeywords (CodeCompletionResultSink &Sink) {
4602
4644
addKeyword (Sink, " let" , CodeCompletionKeywordKind::kw_let);
4603
4645
addKeyword (Sink, " var" , CodeCompletionKeywordKind::kw_var);
@@ -4687,6 +4729,10 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
4687
4729
addAnyTypeKeyword (Sink);
4688
4730
break ;
4689
4731
4732
+ case CompletionKind::CaseStmtKeyword:
4733
+ addCaseStmtKeywords (Sink);
4734
+ break ;
4735
+
4690
4736
case CompletionKind::PostfixExpr:
4691
4737
case CompletionKind::PostfixExprParen:
4692
4738
case CompletionKind::SuperExpr:
@@ -4954,19 +5000,30 @@ void CodeCompletionCallbacksImpl::doneParsing() {
4954
5000
bool OnRoot = !KPE->getComponents ().front ().isValid ();
4955
5001
Lookup.setIsSwiftKeyPathExpr (OnRoot);
4956
5002
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) {
4961
5020
// KeyPath expr with '?' (e.g. '\Ty.[0].prop?.another').
4962
5021
// Althogh expected type is optional, we should unwrap it because it's
4963
5022
// unwrapped.
4964
- ParsedType = ParsedType ->getOptionalObjectType ();
5023
+ baseType = baseType ->getOptionalObjectType ();
4965
5024
}
4966
5025
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);
4970
5027
break ;
4971
5028
}
4972
5029
@@ -5189,12 +5246,13 @@ void CodeCompletionCallbacksImpl::doneParsing() {
5189
5246
}
5190
5247
}
5191
5248
break ;
5192
- case CompletionKind::AfterIfStmtElse:
5193
- // Handled earlier by keyword completions.
5194
- break ;
5195
5249
case CompletionKind::PrecedenceGroup:
5196
5250
Lookup.getPrecedenceGroupCompletions (SyntxKind);
5197
5251
break ;
5252
+ case CompletionKind::AfterIfStmtElse:
5253
+ case CompletionKind::CaseStmtKeyword:
5254
+ // Handled earlier by keyword completions.
5255
+ break ;
5198
5256
}
5199
5257
5200
5258
for (auto &Request: Lookup.RequestedCachedResults ) {
0 commit comments