Skip to content

Commit 2024751

Browse files
committed
[CodeCompletion] Add flairs to cached items
* Starting a statement with a protocol name is rare * Starting a statemnet at top-level of non-script file is invalid rdar://77934897 (cherry picked from commit 1855e1a)
1 parent b9a389e commit 2024751

9 files changed

+267
-93
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,13 @@ enum class CodeCompletionFlairBit: uint8_t {
424424

425425
/// E.g. type decl introducer ('enum', 'class', etc.) in a function body.
426426
RareKeywordAtCurrentPosition = 1 << 4,
427+
428+
/// E.g. protocol names at an expression position.
429+
RareTypeAtCurrentPosition = 1 << 5,
430+
431+
/// E.g. referencing a type, function, etc… at top level position in a non
432+
/// script/main.swift file
433+
ExpressionAtNonScriptOrMainFileScope = 1 << 6,
427434
};
428435

429436
using CodeCompletionFlair = OptionSet<CodeCompletionFlairBit>;
@@ -807,6 +814,10 @@ class CodeCompletionResult {
807814
return static_cast<CodeCompletionFlair>(Flair);
808815
}
809816

817+
void setFlair(CodeCompletionFlair flair) {
818+
Flair = unsigned(flair.toRaw());
819+
}
820+
810821
bool isNotRecommended() const {
811822
return getNotRecommendedReason() != NotRecommendedReason::None;
812823
}
@@ -961,7 +972,7 @@ class CodeCompletionConsumer {
961972
virtual void
962973
handleResultsAndModules(CodeCompletionContext &context,
963974
ArrayRef<RequestedCachedModule> requestedModules,
964-
DeclContext *DCForModules) = 0;
975+
DeclContext *DC) = 0;
965976
};
966977

967978
/// A simplified code completion consumer interface that clients can use to get
@@ -1017,11 +1028,12 @@ void lookupCodeCompletionResultsFromModule(CodeCompletionResultSink &targetSink,
10171028
const DeclContext *currDeclContext);
10181029

10191030
/// Copy code completion results from \p sourceSink to \p targetSink, possibly
1020-
/// restricting by \p onlyTypes.
1021-
void copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
1022-
CodeCompletionResultSink &sourceSink,
1023-
bool onlyTypes,
1024-
bool onlyPrecedenceGroups);
1031+
/// restricting by \p onlyTypes. Returns copied results in \p targetSink.
1032+
ArrayRef<CodeCompletionResult *>
1033+
copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
1034+
CodeCompletionResultSink &sourceSink,
1035+
bool onlyTypes,
1036+
bool onlyPrecedenceGroups);
10251037

10261038
} // end namespace ide
10271039
} // end namespace swift

lib/IDE/CodeCompletion.cpp

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ void CodeCompletionResult::printPrefix(raw_ostream &OS) const {
743743
PRINT_FLAIR(ArgumentLabels, "ArgLabels");
744744
PRINT_FLAIR(CommonKeywordAtCurrentPosition, "CommonKeyword")
745745
PRINT_FLAIR(RareKeywordAtCurrentPosition, "RareKeyword")
746+
PRINT_FLAIR(RareTypeAtCurrentPosition, "RareType")
747+
PRINT_FLAIR(ExpressionAtNonScriptOrMainFileScope, "ExprAtFileScope")
746748
Prefix.append("]");
747749
}
748750
if (NotRecommended)
@@ -6457,10 +6459,54 @@ static void addConditionalCompilationFlags(ASTContext &Ctx,
64576459
}
64586460
}
64596461

6462+
static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
6463+
CompletionKind Kind, DeclContext *DC) {
6464+
auto isExprKeyword = [](const CodeCompletionResult *result) {
6465+
if (result->getKind() != CodeCompletionResult::ResultKind::Keyword)
6466+
return false;
6467+
switch (result->getKeywordKind()) {
6468+
#define POUND_DIRECTIVE_KEYWORD(kw)
6469+
#define POUND_CONFIG(kw)
6470+
#define POUND_KEYWORD(kw) case CodeCompletionKeywordKind::pound_##kw:
6471+
#include "swift/Syntax/TokenKinds.def"
6472+
return true;
6473+
default:
6474+
return false;
6475+
}
6476+
};
6477+
for (CodeCompletionResult *result : results) {
6478+
auto flair = result->getFlair();
6479+
6480+
// Starting a statement with a protocol name is not common. So protocol
6481+
// names at non-type name position are "rare".
6482+
if (result->getKind() == CodeCompletionResult::ResultKind::Declaration &&
6483+
result->getAssociatedDeclKind() == CodeCompletionDeclKind::Protocol &&
6484+
Kind != CompletionKind::TypeSimpleBeginning &&
6485+
Kind != CompletionKind::TypeIdentifierWithoutDot &&
6486+
Kind != CompletionKind::TypeIdentifierWithDot &&
6487+
Kind != CompletionKind::TypeDeclResultBeginning &&
6488+
Kind != CompletionKind::GenericRequirement) {
6489+
flair |= CodeCompletionFlairBit::RareTypeAtCurrentPosition;
6490+
}
6491+
6492+
// Starting a statement at top-level in non-script files is invalid.
6493+
if (Kind == CompletionKind::StmtOrExpr &&
6494+
isCodeCompletionAtTopLevel(DC) &&
6495+
!DC->getParentSourceFile()->isScriptMode() &&
6496+
(result->getKind() == CodeCompletionResult::ResultKind::Declaration ||
6497+
result->getKind() == CodeCompletionResult::ResultKind::Literal ||
6498+
isExprKeyword(result))) {
6499+
flair |= CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope;
6500+
}
6501+
result->setFlair(flair);
6502+
}
6503+
}
6504+
64606505
static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
64616506
CompletionLookup &Lookup,
6462-
SourceFile &SF,
6507+
DeclContext *DC,
64636508
CodeCompletionConsumer &Consumer) {
6509+
auto &SF = *DC->getParentSourceFile();
64646510
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
64656511
std::vector<RequestedCachedModule> RequestedModules;
64666512

@@ -6571,12 +6617,10 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
65716617
Lookup.RequestedCachedResults.clear();
65726618
CompletionContext.typeContextKind = Lookup.typeContextKind();
65736619

6574-
// Use the current SourceFile as the DeclContext so that we can use it to
6575-
// perform qualified lookup, and to get the correct visibility for
6576-
// @testable imports.
6577-
DeclContext *DCForModules = &SF;
6578-
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
6579-
DCForModules);
6620+
postProcessResults(CompletionContext.getResultSink().Results,
6621+
CompletionContext.CodeCompletionKind, DC);
6622+
6623+
Consumer.handleResultsAndModules(CompletionContext, RequestedModules, DC);
65806624
}
65816625

65826626
void deliverUnresolvedMemberResults(
@@ -6614,8 +6658,8 @@ void deliverUnresolvedMemberResults(
66146658
}
66156659
Lookup.getUnresolvedMemberCompletions(Result.ExpectedTy);
66166660
}
6617-
SourceFile *SF = DC->getParentSourceFile();
6618-
deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
6661+
6662+
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
66196663
}
66206664

66216665
void deliverDotExprResults(
@@ -6655,8 +6699,7 @@ void deliverDotExprResults(
66556699
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
66566700
}
66576701

6658-
SourceFile *SF = DC->getParentSourceFile();
6659-
deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
6702+
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
66606703
}
66616704

66626705
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
@@ -7284,7 +7327,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
72847327
break;
72857328
}
72867329

7287-
deliverCompletionResults(CompletionContext, Lookup, P.SF, Consumer);
7330+
deliverCompletionResults(CompletionContext, Lookup, CurDeclContext, Consumer);
72887331
}
72897332

72907333
void PrintingCodeCompletionConsumer::handleResults(
@@ -7360,16 +7403,17 @@ void swift::ide::lookupCodeCompletionResultsFromModule(
73607403
CompletionLookup Lookup(targetSink, module->getASTContext(), SF);
73617404
Lookup.lookupExternalModuleDecls(module, accessPath, needLeadingDot);
73627405
}
7363-
7364-
void swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
7365-
CodeCompletionResultSink &sourceSink,
7366-
bool onlyTypes,
7367-
bool onlyPrecedenceGroups) {
7406+
ArrayRef<CodeCompletionResult *>
7407+
swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
7408+
CodeCompletionResultSink &sourceSink,
7409+
bool onlyTypes,
7410+
bool onlyPrecedenceGroups) {
73687411

73697412
// We will be adding foreign results (from another sink) into TargetSink.
73707413
// TargetSink should have an owning pointer to the allocator that keeps the
73717414
// results alive.
73727415
targetSink.ForeignAllocators.push_back(sourceSink.Allocator);
7416+
auto startSize = targetSink.Results.size();
73737417

73747418
if (onlyTypes) {
73757419
std::copy_if(sourceSink.Results.begin(), sourceSink.Results.end(),
@@ -7419,12 +7463,21 @@ void swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
74197463
sourceSink.Results.begin(),
74207464
sourceSink.Results.end());
74217465
}
7466+
7467+
return llvm::makeArrayRef(targetSink.Results.data() + startSize,
7468+
targetSink.Results.size() - startSize);
74227469
}
74237470

74247471
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
74257472
CodeCompletionContext &context,
74267473
ArrayRef<RequestedCachedModule> requestedModules,
7427-
DeclContext *DCForModules) {
7474+
DeclContext *DC) {
7475+
7476+
// Use the current SourceFile as the DeclContext so that we can use it to
7477+
// perform qualified lookup, and to get the correct visibility for
7478+
// @testable imports.
7479+
DeclContext *DCForModules = DC->getParentSourceFile();
7480+
74287481
for (auto &R : requestedModules) {
74297482
// FIXME(thread-safety): lock the whole AST context. We might load a
74307483
// module.
@@ -7440,8 +7493,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
74407493
context.Cache.set(R.Key, *V);
74417494
}
74427495
assert(V.hasValue());
7443-
copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7444-
R.OnlyTypes, R.OnlyPrecedenceGroups);
7496+
auto newItems = copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7497+
R.OnlyTypes, R.OnlyPrecedenceGroups);
7498+
postProcessResults(newItems, context.CodeCompletionKind, DC);
74457499
}
74467500

74477501
handleResults(context.takeResults());

0 commit comments

Comments
 (0)