@@ -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;
@@ -5913,21 +5986,126 @@ static void
5913
5986
addKeyword (CodeCompletionResultSink &Sink, StringRef Name,
5914
5987
CodeCompletionKeywordKind Kind, StringRef TypeAnnotation = " " ,
5915
5988
CodeCompletionResult::ExpectedTypeRelation TypeRelation =
5916
- CodeCompletionResult::ExpectedTypeRelation::NotApplicable) {
5989
+ CodeCompletionResult::ExpectedTypeRelation::NotApplicable,
5990
+ CodeCompletionFlair Flair = {}) {
5917
5991
CodeCompletionResultBuilder Builder (Sink,
5918
5992
CodeCompletionResult::ResultKind::Keyword,
5919
5993
SemanticContextKind::None, {});
5920
5994
Builder.setKeywordKind (Kind);
5921
5995
Builder.addKeyword (Name);
5996
+ Builder.addFlair (Flair);
5922
5997
if (!TypeAnnotation.empty ())
5923
5998
Builder.addTypeAnnotation (TypeAnnotation);
5924
5999
Builder.setExpectedTypeRelation (TypeRelation);
5925
6000
}
5926
6001
5927
- static void addDeclKeywords (CodeCompletionResultSink &Sink,
6002
+ static void addDeclKeywords (CodeCompletionResultSink &Sink, DeclContext *DC,
5928
6003
bool IsConcurrencyEnabled) {
6004
+ auto isTypeDeclIntroducer = [](CodeCompletionKeywordKind Kind,
6005
+ Optional<DeclAttrKind> DAK) -> bool {
6006
+ switch (Kind) {
6007
+ case CodeCompletionKeywordKind::kw_protocol:
6008
+ case CodeCompletionKeywordKind::kw_class:
6009
+ case CodeCompletionKeywordKind::kw_struct:
6010
+ case CodeCompletionKeywordKind::kw_enum:
6011
+ case CodeCompletionKeywordKind::kw_extension:
6012
+ return true ;
6013
+ case CodeCompletionKeywordKind::None:
6014
+ if (DAK && *DAK == DeclAttrKind::DAK_Actor) {
6015
+ return true ;
6016
+ }
6017
+ break ;
6018
+ default :
6019
+ break ;
6020
+ }
6021
+ return false ;
6022
+ };
6023
+ auto isTopLevelOnlyDeclIntroducer = [](CodeCompletionKeywordKind Kind,
6024
+ Optional<DeclAttrKind> DAK) -> bool {
6025
+ switch (Kind) {
6026
+ case CodeCompletionKeywordKind::kw_operator:
6027
+ case CodeCompletionKeywordKind::kw_precedencegroup:
6028
+ case CodeCompletionKeywordKind::kw_import:
6029
+ case CodeCompletionKeywordKind::kw_protocol:
6030
+ case CodeCompletionKeywordKind::kw_extension:
6031
+ return true ;
6032
+ default :
6033
+ return false ;
6034
+ }
6035
+ };
6036
+
6037
+ auto getFlair = [&](CodeCompletionKeywordKind Kind,
6038
+ Optional<DeclAttrKind> DAK) -> CodeCompletionFlair {
6039
+ if (isCodeCompletionAtTopLevel (DC) &&
6040
+ !DC->getParentSourceFile ()->isScriptMode ()) {
6041
+ // Type decls are common in library file top-level.
6042
+ if (isTypeDeclIntroducer (Kind, DAK))
6043
+ return CodeCompletionFlairBit::CommonKeywordAtCurrentPosition;
6044
+ }
6045
+ if (isa<ProtocolDecl>(DC)) {
6046
+ // Protocols cannot have nested type decls (other than 'typealias').
6047
+ if (isTypeDeclIntroducer (Kind, DAK))
6048
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6049
+ }
6050
+ if (DC->isTypeContext ()) {
6051
+ // Top-level only decls are invalid in type context.
6052
+ if (isTopLevelOnlyDeclIntroducer (Kind, DAK))
6053
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6054
+ }
6055
+ if (isCompletionDeclContextLocalContext (DC)) {
6056
+ // Local type decl are valid, but not common.
6057
+ if (isTypeDeclIntroducer (Kind, DAK))
6058
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6059
+
6060
+ // Top-level only decls are invalid in function body.
6061
+ if (isTopLevelOnlyDeclIntroducer (Kind, DAK))
6062
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6063
+
6064
+ // 'init', 'deinit' and 'subscript' are invalid in function body.
6065
+ // Access control modifiers are invalid in function body.
6066
+ switch (Kind) {
6067
+ case CodeCompletionKeywordKind::kw_init:
6068
+ case CodeCompletionKeywordKind::kw_deinit:
6069
+ case CodeCompletionKeywordKind::kw_subscript:
6070
+ case CodeCompletionKeywordKind::kw_private:
6071
+ case CodeCompletionKeywordKind::kw_fileprivate:
6072
+ case CodeCompletionKeywordKind::kw_internal:
6073
+ case CodeCompletionKeywordKind::kw_public:
6074
+ case CodeCompletionKeywordKind::kw_static:
6075
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6076
+
6077
+ default :
6078
+ break ;
6079
+ }
6080
+
6081
+ // These modifiers are invalid for decls in function body.
6082
+ if (DAK) {
6083
+ switch (*DAK) {
6084
+ case DeclAttrKind::DAK_Lazy:
6085
+ case DeclAttrKind::DAK_Final:
6086
+ case DeclAttrKind::DAK_Infix:
6087
+ case DeclAttrKind::DAK_Frozen:
6088
+ case DeclAttrKind::DAK_Prefix:
6089
+ case DeclAttrKind::DAK_Postfix:
6090
+ case DeclAttrKind::DAK_Dynamic:
6091
+ case DeclAttrKind::DAK_Override:
6092
+ case DeclAttrKind::DAK_Optional:
6093
+ case DeclAttrKind::DAK_Required:
6094
+ case DeclAttrKind::DAK_Convenience:
6095
+ case DeclAttrKind::DAK_AccessControl:
6096
+ case DeclAttrKind::DAK_Nonisolated:
6097
+ return CodeCompletionFlairBit::RareKeywordAtCurrentPosition;
6098
+
6099
+ default :
6100
+ break ;
6101
+ }
6102
+ }
6103
+ }
6104
+ return None;
6105
+ };
6106
+
5929
6107
auto AddDeclKeyword = [&](StringRef Name, CodeCompletionKeywordKind Kind,
5930
- Optional<DeclAttrKind> DAK) {
6108
+ Optional<DeclAttrKind> DAK) {
5931
6109
if (Name == " let" || Name == " var" ) {
5932
6110
// Treat keywords that could be the start of a pattern specially.
5933
6111
return ;
@@ -5936,17 +6114,22 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink,
5936
6114
// FIXME: This should use canUseAttributeOnDecl.
5937
6115
5938
6116
// Remove user inaccessible keywords.
5939
- if (DAK.hasValue () && DeclAttribute::isUserInaccessible (*DAK)) return ;
6117
+ if (DAK.hasValue () && DeclAttribute::isUserInaccessible (*DAK))
6118
+ return ;
5940
6119
5941
6120
// Remove keywords only available when concurrency is enabled.
5942
6121
if (DAK.hasValue () && !IsConcurrencyEnabled &&
5943
6122
DeclAttribute::isConcurrencyOnly (*DAK))
5944
6123
return ;
5945
6124
5946
- addKeyword (Sink, Name, Kind);
6125
+ addKeyword (
6126
+ Sink, Name, Kind, /* TypeAnnotation=*/ " " ,
6127
+ /* TypeRelation=*/ CodeCompletionResult::ExpectedTypeRelation::NotApplicable,
6128
+ getFlair (Kind, DAK));
5947
6129
};
5948
6130
5949
- #define DECL_KEYWORD (kw ) AddDeclKeyword(#kw, CodeCompletionKeywordKind::kw_##kw, None);
6131
+ #define DECL_KEYWORD (kw ) \
6132
+ AddDeclKeyword (#kw, CodeCompletionKeywordKind::kw_##kw, None);
5950
6133
#include " swift/Syntax/TokenKinds.def"
5951
6134
5952
6135
// Context-sensitive keywords.
@@ -5960,7 +6143,6 @@ static void addDeclKeywords(CodeCompletionResultSink &Sink,
5960
6143
#define CONTEXTUAL_SIMPLE_DECL_ATTR (KW, CLASS, ...) CONTEXTUAL_CASE(KW, CLASS)
5961
6144
#include < swift/AST/Attr.def>
5962
6145
#undef CONTEXTUAL_CASE
5963
-
5964
6146
}
5965
6147
5966
6148
static void addStmtKeywords (CodeCompletionResultSink &Sink, bool MaybeFuncBody) {
@@ -6064,7 +6246,8 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
6064
6246
LLVM_FALLTHROUGH;
6065
6247
}
6066
6248
case CompletionKind::StmtOrExpr:
6067
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency );
6249
+ addDeclKeywords (Sink, CurDeclContext,
6250
+ Context.LangOpts .EnableExperimentalConcurrency );
6068
6251
addStmtKeywords (Sink, MaybeFuncBody);
6069
6252
LLVM_FALLTHROUGH;
6070
6253
case CompletionKind::ReturnStmtExpr:
@@ -6132,7 +6315,8 @@ void CodeCompletionCallbacksImpl::addKeywords(CodeCompletionResultSink &Sink,
6132
6315
.Default (false );
6133
6316
}) != ParsedKeywords.end ();
6134
6317
if (!HasDeclIntroducer) {
6135
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency );
6318
+ addDeclKeywords (Sink, CurDeclContext,
6319
+ Context.LangOpts .EnableExperimentalConcurrency );
6136
6320
addLetVarKeywords (Sink);
6137
6321
}
6138
6322
break ;
@@ -6948,15 +7132,17 @@ void CodeCompletionCallbacksImpl::doneParsing() {
6948
7132
6949
7133
if (CurDeclContext->isTypeContext ()) {
6950
7134
// Override completion (CompletionKind::NominalMemberBeginning).
6951
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency );
7135
+ addDeclKeywords (Sink, CurDeclContext,
7136
+ Context.LangOpts .EnableExperimentalConcurrency );
6952
7137
addLetVarKeywords (Sink);
6953
7138
SmallVector<StringRef, 0 > ParsedKeywords;
6954
7139
CompletionOverrideLookup OverrideLookup (Sink, Context, CurDeclContext,
6955
7140
ParsedKeywords, SourceLoc ());
6956
7141
OverrideLookup.getOverrideCompletions (SourceLoc ());
6957
7142
} else {
6958
7143
// Global completion (CompletionKind::PostfixExprBeginning).
6959
- addDeclKeywords (Sink, Context.LangOpts .EnableExperimentalConcurrency );
7144
+ addDeclKeywords (Sink, CurDeclContext,
7145
+ Context.LangOpts .EnableExperimentalConcurrency );
6960
7146
addStmtKeywords (Sink, MaybeFuncBody);
6961
7147
addSuperKeyword (Sink);
6962
7148
addLetVarKeywords (Sink);
0 commit comments