@@ -741,6 +741,8 @@ void CodeCompletionResult::printPrefix(raw_ostream &OS) const {
741
741
PRINT_FLAIR (ExpressionSpecific, " ExprSpecific" );
742
742
PRINT_FLAIR (SuperChain, " SuperChain" );
743
743
PRINT_FLAIR (ArgumentLabels, " ArgLabels" );
744
+ PRINT_FLAIR (CommonKeywordAtCurrentPosition, " CommonKeyword" )
745
+ PRINT_FLAIR (RareKeywordAtCurrentPosition, " RareKeyword" )
744
746
Prefix.append (" ]" );
745
747
}
746
748
if (NotRecommended)
@@ -1540,6 +1542,12 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
1540
1542
CodeCompletionResult::ResultKind::Keyword,
1541
1543
SemanticContextKind::CurrentNominal,
1542
1544
{});
1545
+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(CurDeclContext)) {
1546
+ if (AFD->getOverriddenDecl () != nullptr ) {
1547
+ Builder.addFlair (CodeCompletionFlairBit::CommonKeywordAtCurrentPosition);
1548
+ }
1549
+ }
1550
+
1543
1551
Builder.setKeywordKind (CodeCompletionKeywordKind::kw_super);
1544
1552
Builder.addKeyword (" super" );
1545
1553
Builder.addTypeAnnotation (ST, PrintOptions ());
@@ -1822,6 +1830,71 @@ static bool canDeclContextHandleAsync(const DeclContext *DC) {
1822
1830
return false ;
1823
1831
}
1824
1832
1833
+ // / Returns \c true only if the completion is happening for top-level
1834
+ // / declrarations. i.e.:
1835
+ // /
1836
+ // / if condition {
1837
+ // / #false#
1838
+ // / }
1839
+ // / expr.#false#
1840
+ // /
1841
+ // / #true#
1842
+ // /
1843
+ // / struct S {
1844
+ // / #false#
1845
+ // / func foo() {
1846
+ // / #false#
1847
+ // / }
1848
+ // / }
1849
+ static bool isCodeCompletionAtTopLevel (DeclContext *DC) {
1850
+ if (DC->isModuleScopeContext ())
1851
+ return true ;
1852
+
1853
+ // CC token at top-level is parsed as an expression. If the only element
1854
+ // body of the TopLevelCodeDecl is a CodeCompletionExpr without a base
1855
+ // expression, the user might be writing a top-level declaration.
1856
+ if (TopLevelCodeDecl *TLCD = dyn_cast<TopLevelCodeDecl>(DC)) {
1857
+ auto body = TLCD->getBody ();
1858
+ if (!body || body->empty ())
1859
+ return true ;
1860
+ if (body->getElements ().size () > 1 )
1861
+ return false ;
1862
+ auto expr = body->getFirstElement ().dyn_cast <Expr *>();
1863
+ if (!expr)
1864
+ return false ;
1865
+ if (CodeCompletionExpr *CCExpr = dyn_cast<CodeCompletionExpr>(expr)) {
1866
+ if (CCExpr->getBase () == nullptr )
1867
+ return true ;
1868
+ }
1869
+ }
1870
+
1871
+ return false ;
1872
+ }
1873
+
1874
+ // / Returns \c true if the completion is happening in local context such as
1875
+ // / inside function bodies. i.e.:
1876
+ // /
1877
+ // / if condition {
1878
+ // / #true#
1879
+ // / }
1880
+ // / expr.#true#
1881
+ // /
1882
+ // / #false#
1883
+ // /
1884
+ // / struct S {
1885
+ // / #false#
1886
+ // / func foo() {
1887
+ // / #true#
1888
+ // / }
1889
+ // / }
1890
+ static bool isCompletionDeclContextLocalContext (DeclContext *DC) {
1891
+ if (!DC->isLocalContext ())
1892
+ return false ;
1893
+ if (isCodeCompletionAtTopLevel (DC))
1894
+ return false ;
1895
+ return true ;
1896
+ }
1897
+
1825
1898
// / Build completions by doing visible decl lookup from a context.
1826
1899
class CompletionLookup final : public swift::VisibleDeclConsumer {
1827
1900
CodeCompletionResultSink &Sink;
@@ -5925,22 +5998,127 @@ static void
5925
5998
addKeyword (CodeCompletionResultSink &Sink, StringRef Name,
5926
5999
CodeCompletionKeywordKind Kind, StringRef TypeAnnotation = " " ,
5927
6000
CodeCompletionResult::ExpectedTypeRelation TypeRelation =
5928
- CodeCompletionResult::ExpectedTypeRelation::NotApplicable) {
6001
+ CodeCompletionResult::ExpectedTypeRelation::NotApplicable,
6002
+ CodeCompletionFlair Flair = {}) {
5929
6003
CodeCompletionResultBuilder Builder (Sink,
5930
6004
CodeCompletionResult::ResultKind::Keyword,
5931
6005
SemanticContextKind::None, {});
5932
6006
Builder.setKeywordKind (Kind);
5933
6007
Builder.addKeyword (Name);
6008
+ Builder.addFlair (Flair);
5934
6009
if (!TypeAnnotation.empty ())
5935
6010
Builder.addTypeAnnotation (TypeAnnotation);
5936
6011
Builder.setExpectedTypeRelation (TypeRelation);
5937
6012
}
5938
6013
5939
- static void addDeclKeywords (CodeCompletionResultSink &Sink,
6014
+ static void addDeclKeywords (CodeCompletionResultSink &Sink, DeclContext *DC,
5940
6015
bool IsConcurrencyEnabled,
5941
6016
bool IsDistributedEnabled) {
6017
+ auto isTypeDeclIntroducer = [](CodeCompletionKeywordKind Kind,
6018
+ Optional<DeclAttrKind> DAK) -> bool {
6019
+ switch (Kind) {
6020
+ case CodeCompletionKeywordKind::kw_protocol:
6021
+ case CodeCompletionKeywordKind::kw_class:
6022
+ case CodeCompletionKeywordKind::kw_struct:
6023
+ case CodeCompletionKeywordKind::kw_enum:
6024
+ case CodeCompletionKeywordKind::kw_extension:
6025
+ return true ;
6026
+ case CodeCompletionKeywordKind::None:
6027
+ if (DAK && *DAK == DeclAttrKind::DAK_Actor) {
6028
+ return true ;
6029
+ }
6030
+ break ;
6031
+ default :
6032
+ break ;
6033
+ }
6034
+ return false ;
6035
+ };
6036
+ auto isTopLevelOnlyDeclIntroducer = [](CodeCompletionKeywordKind Kind,
6037
+ Optional<DeclAttrKind> DAK) -> bool {
6038
+ switch (Kind) {
6039
+ case CodeCompletionKeywordKind::kw_operator:
6040
+ case CodeCompletionKeywordKind::kw_precedencegroup:
6041
+ case CodeCompletionKeywordKind::kw_import:
6042
+ case CodeCompletionKeywordKind::kw_protocol:
6043
+ case CodeCompletionKeywordKind::kw_extension:
6044
+ return true ;
6045
+ default :
6046
+ return false ;
6047
+ }
6048
+ };
6049
+
6050
+ auto getFlair = [&](CodeCompletionKeywordKind Kind,
6051
+ Optional<DeclAttrKind> DAK) -> CodeCompletionFlair {
6052
+ if (isCodeCompletionAtTopLevel (DC) &&
6053
+ !DC->getParentSourceFile ()->isScriptMode ()) {
6054
+ // Type decls are common in library file top-level.
6055
+ if (isTypeDeclIntroducer (Kind, DAK))
6056
+ return CodeCompletionFlairBit::CommonKeywordAtCurrentPosition;
6057
+ }
6058
+ if (isa<ProtocolDecl>(DC)) {
6059
+ // Protocols cannot have nested type decls (other than 'typealias').
6060
+ if (isTypeDeclIntroducer (Kind, DAK))
6061
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6062
+ }
6063
+ if (DC->isTypeContext ()) {
6064
+ // Top-level only decls are invalid in type context.
6065
+ if (isTopLevelOnlyDeclIntroducer (Kind, DAK))
6066
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6067
+ }
6068
+ if (isCompletionDeclContextLocalContext (DC)) {
6069
+ // Local type decl are valid, but not common.
6070
+ if (isTypeDeclIntroducer (Kind, DAK))
6071
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6072
+
6073
+ // Top-level only decls are invalid in function body.
6074
+ if (isTopLevelOnlyDeclIntroducer (Kind, DAK))
6075
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6076
+
6077
+ // 'init', 'deinit' and 'subscript' are invalid in function body.
6078
+ // Access control modifiers are invalid in function body.
6079
+ switch (Kind) {
6080
+ case CodeCompletionKeywordKind::kw_init:
6081
+ case CodeCompletionKeywordKind::kw_deinit:
6082
+ case CodeCompletionKeywordKind::kw_subscript:
6083
+ case CodeCompletionKeywordKind::kw_private:
6084
+ case CodeCompletionKeywordKind::kw_fileprivate:
6085
+ case CodeCompletionKeywordKind::kw_internal:
6086
+ case CodeCompletionKeywordKind::kw_public:
6087
+ case CodeCompletionKeywordKind::kw_static:
6088
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6089
+
6090
+ default :
6091
+ break ;
6092
+ }
6093
+
6094
+ // These modifiers are invalid for decls in function body.
6095
+ if (DAK) {
6096
+ switch (*DAK) {
6097
+ case DeclAttrKind::DAK_Lazy:
6098
+ case DeclAttrKind::DAK_Final:
6099
+ case DeclAttrKind::DAK_Infix:
6100
+ case DeclAttrKind::DAK_Frozen:
6101
+ case DeclAttrKind::DAK_Prefix:
6102
+ case DeclAttrKind::DAK_Postfix:
6103
+ case DeclAttrKind::DAK_Dynamic:
6104
+ case DeclAttrKind::DAK_Override:
6105
+ case DeclAttrKind::DAK_Optional:
6106
+ case DeclAttrKind::DAK_Required:
6107
+ case DeclAttrKind::DAK_Convenience:
6108
+ case DeclAttrKind::DAK_AccessControl:
6109
+ case DeclAttrKind::DAK_Nonisolated:
6110
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6111
+
6112
+ default :
6113
+ break ;
6114
+ }
6115
+ }
6116
+ }
6117
+ return None;
6118
+ };
6119
+
5942
6120
auto AddDeclKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind,
5943
- Optional<DeclAttrKind> DAK) {
6121
+ Optional<DeclAttrKind> DAK) {
5944
6122
if (Name == " let" || Name == " var" ) {
5945
6123
// Treat keywords that could be the start of a pattern specially.
5946
6124
return ;
@@ -5949,7 +6127,8 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink,
5949
6127
// FIXME: This should use canUseAttributeOnDecl.
5950
6128
5951
6129
// Remove user inaccessible keywords.
5952
- if (DAK.hasValue () && DeclAttribute::isUserInaccessible (*DAK)) return ;
6130
+ if (DAK.hasValue () && DeclAttribute::isUserInaccessible (*DAK))
6131
+ return ;
5953
6132
5954
6133
// Remove keywords only available when concurrency is enabled.
5955
6134
if (DAK.hasValue () && !IsConcurrencyEnabled &&
@@ -5961,10 +6140,14 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink,
5961
6140
DeclAttribute::isDistributedOnly (*DAK))
5962
6141
return ;
5963
6142
5964
- addKeyword (Sink, Name, Kind);
6143
+ addKeyword (
6144
+ Sink, Name, Kind, /* TypeAnnotation=*/ " " ,
6145
+ /* TypeRelation=*/ CodeCompletionResult::ExpectedTypeRelation::NotApplicable,
6146
+ getFlair (Kind, DAK));
5965
6147
};
5966
6148
5967
- #define DECL_KEYWORD (kw ) AddDeclKeyword(#kw, CodeCompletionKeywordKind::kw_##kw, None);
6149
+ #define DECL_KEYWORD (kw ) \
6150
+ AddDeclKeyword (#kw, CodeCompletionKeywordKind::kw_##kw, None);
5968
6151
#include " swift/Syntax/TokenKinds.def"
5969
6152
5970
6153
// Context-sensitive keywords.
@@ -5978,7 +6161,6 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink,
5978
6161
#define CONTEXTUAL_SIMPLE_DECL_ATTR (KW, CLASS, ...) CONTEXTUAL_CASE(KW, CLASS)
5979
6162
#include < swift/AST/Attr.def>
5980
6163
#undef CONTEXTUAL_CASE
5981
-
5982
6164
}
5983
6165
5984
6166
static void addStmtKeywords (CodeCompletionResultSink &Sink, bool MaybeFuncBody) {
@@ -6082,7 +6264,9 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
6082
6264
LLVM_FALLTHROUGH;
6083
6265
}
6084
6266
case CompletionKind::StmtOrExpr:
6085
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency , Context.LangOpts .EnableExperimentalDistributed );
6267
+ addDeclKeywords (Sink, CurDeclContext,
6268
+ Context.LangOpts .EnableExperimentalConcurrency ,
6269
+ Context.LangOpts .EnableExperimentalDistributed );
6086
6270
addStmtKeywords (Sink, MaybeFuncBody);
6087
6271
LLVM_FALLTHROUGH;
6088
6272
case CompletionKind::ReturnStmtExpr:
@@ -6150,7 +6334,9 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
6150
6334
.Default (false );
6151
6335
}) != ParsedKeywords.end ();
6152
6336
if (!HasDeclIntroducer) {
6153
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency , Context.LangOpts .EnableExperimentalDistributed );
6337
+ addDeclKeywords (Sink, CurDeclContext,
6338
+ Context.LangOpts .EnableExperimentalConcurrency ,
6339
+ Context.LangOpts .EnableExperimentalDistributed );
6154
6340
addLetVarKeywords (Sink);
6155
6341
}
6156
6342
break ;
@@ -6966,15 +7152,19 @@ void CodeCompletionCallbacksImpl::doneParsing() {
6966
7152
6967
7153
if (CurDeclContext->isTypeContext ()) {
6968
7154
// Override completion (CompletionKind::NominalMemberBeginning).
6969
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency , Context.LangOpts .EnableExperimentalDistributed );
7155
+ addDeclKeywords (Sink, CurDeclContext,
7156
+ Context.LangOpts .EnableExperimentalConcurrency ,
7157
+ Context.LangOpts .EnableExperimentalDistributed );
6970
7158
addLetVarKeywords (Sink);
6971
7159
SmallVector<StringRef, 0 > ParsedKeywords;
6972
7160
CompletionOverrideLookup OverrideLookup (Sink, Context, CurDeclContext,
6973
7161
ParsedKeywords, SourceLoc ());
6974
7162
OverrideLookup.getOverrideCompletions (SourceLoc ());
6975
7163
} else {
6976
7164
// Global completion (CompletionKind::PostfixExprBeginning).
6977
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency , Context.LangOpts .EnableExperimentalDistributed );
7165
+ addDeclKeywords (Sink, CurDeclContext,
7166
+ Context.LangOpts .EnableExperimentalConcurrency ,
7167
+ Context.LangOpts .EnableExperimentalDistributed );
6978
7168
addStmtKeywords (Sink, MaybeFuncBody);
6979
7169
addSuperKeyword (Sink);
6980
7170
addLetVarKeywords (Sink);
0 commit comments