Skip to content

Commit 1855e1a

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
1 parent 3602f1a commit 1855e1a

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)
@@ -6477,10 +6479,54 @@ static void addConditionalCompilationFlags(ASTContext &Ctx,
64776479
}
64786480
}
64796481

6482+
static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
6483+
CompletionKind Kind, DeclContext *DC) {
6484+
auto isExprKeyword = [](const CodeCompletionResult *result) {
6485+
if (result->getKind() != CodeCompletionResult::ResultKind::Keyword)
6486+
return false;
6487+
switch (result->getKeywordKind()) {
6488+
#define POUND_DIRECTIVE_KEYWORD(kw)
6489+
#define POUND_CONFIG(kw)
6490+
#define POUND_KEYWORD(kw) case CodeCompletionKeywordKind::pound_##kw:
6491+
#include "swift/Syntax/TokenKinds.def"
6492+
return true;
6493+
default:
6494+
return false;
6495+
}
6496+
};
6497+
for (CodeCompletionResult *result : results) {
6498+
auto flair = result->getFlair();
6499+
6500+
// Starting a statement with a protocol name is not common. So protocol
6501+
// names at non-type name position are "rare".
6502+
if (result->getKind() == CodeCompletionResult::ResultKind::Declaration &&
6503+
result->getAssociatedDeclKind() == CodeCompletionDeclKind::Protocol &&
6504+
Kind != CompletionKind::TypeSimpleBeginning &&
6505+
Kind != CompletionKind::TypeIdentifierWithoutDot &&
6506+
Kind != CompletionKind::TypeIdentifierWithDot &&
6507+
Kind != CompletionKind::TypeDeclResultBeginning &&
6508+
Kind != CompletionKind::GenericRequirement) {
6509+
flair |= CodeCompletionFlairBit::RareTypeAtCurrentPosition;
6510+
}
6511+
6512+
// Starting a statement at top-level in non-script files is invalid.
6513+
if (Kind == CompletionKind::StmtOrExpr &&
6514+
isCodeCompletionAtTopLevel(DC) &&
6515+
!DC->getParentSourceFile()->isScriptMode() &&
6516+
(result->getKind() == CodeCompletionResult::ResultKind::Declaration ||
6517+
result->getKind() == CodeCompletionResult::ResultKind::Literal ||
6518+
isExprKeyword(result))) {
6519+
flair |= CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope;
6520+
}
6521+
result->setFlair(flair);
6522+
}
6523+
}
6524+
64806525
static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
64816526
CompletionLookup &Lookup,
6482-
SourceFile &SF,
6527+
DeclContext *DC,
64836528
CodeCompletionConsumer &Consumer) {
6529+
auto &SF = *DC->getParentSourceFile();
64846530
llvm::SmallPtrSet<Identifier, 8> seenModuleNames;
64856531
std::vector<RequestedCachedModule> RequestedModules;
64866532

@@ -6591,12 +6637,10 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
65916637
Lookup.RequestedCachedResults.clear();
65926638
CompletionContext.typeContextKind = Lookup.typeContextKind();
65936639

6594-
// Use the current SourceFile as the DeclContext so that we can use it to
6595-
// perform qualified lookup, and to get the correct visibility for
6596-
// @testable imports.
6597-
DeclContext *DCForModules = &SF;
6598-
Consumer.handleResultsAndModules(CompletionContext, RequestedModules,
6599-
DCForModules);
6640+
postProcessResults(CompletionContext.getResultSink().Results,
6641+
CompletionContext.CodeCompletionKind, DC);
6642+
6643+
Consumer.handleResultsAndModules(CompletionContext, RequestedModules, DC);
66006644
}
66016645

66026646
void deliverUnresolvedMemberResults(
@@ -6634,8 +6678,8 @@ void deliverUnresolvedMemberResults(
66346678
}
66356679
Lookup.getUnresolvedMemberCompletions(Result.ExpectedTy);
66366680
}
6637-
SourceFile *SF = DC->getParentSourceFile();
6638-
deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
6681+
6682+
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
66396683
}
66406684

66416685
void deliverDotExprResults(
@@ -6675,8 +6719,7 @@ void deliverDotExprResults(
66756719
Lookup.getValueExprCompletions(Result.BaseTy, Result.BaseDecl);
66766720
}
66776721

6678-
SourceFile *SF = DC->getParentSourceFile();
6679-
deliverCompletionResults(CompletionCtx, Lookup, *SF, Consumer);
6722+
deliverCompletionResults(CompletionCtx, Lookup, DC, Consumer);
66806723
}
66816724

66826725
bool CodeCompletionCallbacksImpl::trySolverCompletion(bool MaybeFuncBody) {
@@ -7306,7 +7349,7 @@ void CodeCompletionCallbacksImpl::doneParsing() {
73067349
break;
73077350
}
73087351

7309-
deliverCompletionResults(CompletionContext, Lookup, P.SF, Consumer);
7352+
deliverCompletionResults(CompletionContext, Lookup, CurDeclContext, Consumer);
73107353
}
73117354

73127355
void PrintingCodeCompletionConsumer::handleResults(
@@ -7382,16 +7425,17 @@ void swift::ide::lookupCodeCompletionResultsFromModule(
73827425
CompletionLookup Lookup(targetSink, module->getASTContext(), SF);
73837426
Lookup.lookupExternalModuleDecls(module, accessPath, needLeadingDot);
73847427
}
7385-
7386-
void swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
7387-
CodeCompletionResultSink &sourceSink,
7388-
bool onlyTypes,
7389-
bool onlyPrecedenceGroups) {
7428+
ArrayRef<CodeCompletionResult *>
7429+
swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
7430+
CodeCompletionResultSink &sourceSink,
7431+
bool onlyTypes,
7432+
bool onlyPrecedenceGroups) {
73907433

73917434
// We will be adding foreign results (from another sink) into TargetSink.
73927435
// TargetSink should have an owning pointer to the allocator that keeps the
73937436
// results alive.
73947437
targetSink.ForeignAllocators.push_back(sourceSink.Allocator);
7438+
auto startSize = targetSink.Results.size();
73957439

73967440
if (onlyTypes) {
73977441
std::copy_if(sourceSink.Results.begin(), sourceSink.Results.end(),
@@ -7441,12 +7485,21 @@ void swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
74417485
sourceSink.Results.begin(),
74427486
sourceSink.Results.end());
74437487
}
7488+
7489+
return llvm::makeArrayRef(targetSink.Results.data() + startSize,
7490+
targetSink.Results.size() - startSize);
74447491
}
74457492

74467493
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
74477494
CodeCompletionContext &context,
74487495
ArrayRef<RequestedCachedModule> requestedModules,
7449-
DeclContext *DCForModules) {
7496+
DeclContext *DC) {
7497+
7498+
// Use the current SourceFile as the DeclContext so that we can use it to
7499+
// perform qualified lookup, and to get the correct visibility for
7500+
// @testable imports.
7501+
DeclContext *DCForModules = DC->getParentSourceFile();
7502+
74507503
for (auto &R : requestedModules) {
74517504
// FIXME(thread-safety): lock the whole AST context. We might load a
74527505
// module.
@@ -7462,8 +7515,9 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
74627515
context.Cache.set(R.Key, *V);
74637516
}
74647517
assert(V.hasValue());
7465-
copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7466-
R.OnlyTypes, R.OnlyPrecedenceGroups);
7518+
auto newItems = copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7519+
R.OnlyTypes, R.OnlyPrecedenceGroups);
7520+
postProcessResults(newItems, context.CodeCompletionKind, DC);
74677521
}
74687522

74697523
handleResults(context.takeResults());

0 commit comments

Comments
 (0)