Skip to content

Commit f553826

Browse files
committed
[CodeCompletion] Don't modify CodeCompletionResult in place for cached results
Instead, allocate new `CodeCompletionResult` in the current sink.
1 parent 5d5b93d commit f553826

File tree

3 files changed

+107
-12
lines changed

3 files changed

+107
-12
lines changed

include/swift/IDE/CodeCompletion.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ namespace ide {
4040
class CodeCompletionCache;
4141
class CodeCompletionContext;
4242
class CodeCompletionResultBuilder;
43+
struct CodeCompletionResultSink;
4344
struct RequestedCachedModule;
4445

4546
/// A routine to remove code completion tokens from code completion
@@ -760,6 +761,12 @@ class CodeCompletionResult {
760761
getOperatorKind() != CodeCompletionOperatorKind::None);
761762
}
762763

764+
/// Copy this result to \p Sink with \p newFlair . Note that this does NOT
765+
/// copy the value of \c CompletionString , \c AssociatedUSRs etc. it only
766+
/// copies the pointers to them.
767+
CodeCompletionResult *withFlair(CodeCompletionFlair newFlair,
768+
CodeCompletionResultSink &Sink);
769+
763770
ResultKind getKind() const { return static_cast<ResultKind>(Kind); }
764771

765772
CodeCompletionDeclKind getAssociatedDeclKind() const {
@@ -815,6 +822,7 @@ class CodeCompletionResult {
815822
return static_cast<CodeCompletionFlair>(Flair);
816823
}
817824

825+
/// Modify "flair" of this result *in place*.
818826
void setFlair(CodeCompletionFlair flair) {
819827
Flair = unsigned(flair.toRaw());
820828
}
@@ -1030,7 +1038,7 @@ void lookupCodeCompletionResultsFromModule(CodeCompletionResultSink &targetSink,
10301038

10311039
/// Copy code completion results from \p sourceSink to \p targetSink, possibly
10321040
/// restricting by \p onlyTypes. Returns copied results in \p targetSink.
1033-
ArrayRef<CodeCompletionResult *>
1041+
MutableArrayRef<CodeCompletionResult *>
10341042
copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
10351043
CodeCompletionResultSink &sourceSink,
10361044
bool onlyTypes,

lib/IDE/CodeCompletion.cpp

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,24 @@ void CodeCompletionResult::dump() const {
801801
llvm::errs() << "\n";
802802
}
803803

804+
CodeCompletionResult *
805+
CodeCompletionResult::withFlair(CodeCompletionFlair newFlair,
806+
CodeCompletionResultSink &Sink) {
807+
if (Kind == ResultKind::Declaration) {
808+
return new (*Sink.Allocator) CodeCompletionResult(
809+
getSemanticContext(), newFlair, getNumBytesToErase(),
810+
getCompletionString(), getAssociatedDeclKind(), isSystem(),
811+
getModuleName(), getNotRecommendedReason(), getBriefDocComment(),
812+
getAssociatedUSRs(), getDeclKeywords(), getExpectedTypeRelation(),
813+
isOperator() ? getOperatorKind() : CodeCompletionOperatorKind::None);
814+
} else {
815+
return new (*Sink.Allocator) CodeCompletionResult(
816+
getKind(), getSemanticContext(), newFlair, getNumBytesToErase(),
817+
getCompletionString(), getExpectedTypeRelation(),
818+
isOperator() ? getOperatorKind() : CodeCompletionOperatorKind::None);
819+
}
820+
}
821+
804822
void CodeCompletionResultBuilder::withNestedGroup(
805823
CodeCompletionString::Chunk::ChunkKind Kind,
806824
llvm::function_ref<void()> body) {
@@ -6517,9 +6535,16 @@ static void addConditionalCompilationFlags(ASTContext &Ctx,
65176535
}
65186536
}
65196537

6520-
static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
6521-
CompletionKind Kind, DeclContext *DC) {
6522-
for (CodeCompletionResult *result : results) {
6538+
/// Add flairs to the each item in \p results .
6539+
///
6540+
/// If \p Sink is passed, the pointer of the each result may be replaced with a
6541+
/// pointer to the new item allocated in \p Sink.
6542+
/// If \p Sink is nullptr, the pointee of each result may be modified in place.
6543+
static void postProcessResults(MutableArrayRef<CodeCompletionResult *> results,
6544+
CompletionKind Kind, DeclContext *DC,
6545+
CodeCompletionResultSink *Sink) {
6546+
for (CodeCompletionResult *&result : results) {
6547+
bool modified = false;
65236548
auto flair = result->getFlair();
65246549

65256550
// Starting a statement with a protocol name is not common. So protocol
@@ -6532,15 +6557,27 @@ static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
65326557
Kind != CompletionKind::TypeDeclResultBeginning &&
65336558
Kind != CompletionKind::GenericRequirement) {
65346559
flair |= CodeCompletionFlairBit::RareTypeAtCurrentPosition;
6560+
modified = true;
65356561
}
65366562

65376563
// Starting a statement at top-level in non-script files is invalid.
65386564
if (Kind == CompletionKind::StmtOrExpr &&
65396565
result->getKind() == CodeCompletionResult::ResultKind::Declaration &&
65406566
isCodeCompletionAtTopLevelOfLibraryFile(DC)) {
65416567
flair |= CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope;
6568+
modified = true;
6569+
}
6570+
6571+
if (!modified)
6572+
continue;
6573+
6574+
if (Sink) {
6575+
// Replace the result with a new result with the flair.
6576+
result = result->withFlair(flair, *Sink);
6577+
} else {
6578+
// 'Sink' == nullptr means the result is modifiable in place.
6579+
result->setFlair(flair);
65426580
}
6543-
result->setFlair(flair);
65446581
}
65456582
}
65466583

@@ -6660,7 +6697,8 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
66606697
CompletionContext.typeContextKind = Lookup.typeContextKind();
66616698

66626699
postProcessResults(CompletionContext.getResultSink().Results,
6663-
CompletionContext.CodeCompletionKind, DC);
6700+
CompletionContext.CodeCompletionKind, DC,
6701+
/*Sink=*/nullptr);
66646702

66656703
Consumer.handleResultsAndModules(CompletionContext, RequestedModules, DC);
66666704
}
@@ -7446,7 +7484,8 @@ void swift::ide::lookupCodeCompletionResultsFromModule(
74467484
CompletionLookup Lookup(targetSink, module->getASTContext(), SF);
74477485
Lookup.lookupExternalModuleDecls(module, accessPath, needLeadingDot);
74487486
}
7449-
ArrayRef<CodeCompletionResult *>
7487+
7488+
MutableArrayRef<CodeCompletionResult *>
74507489
swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
74517490
CodeCompletionResultSink &sourceSink,
74527491
bool onlyTypes,
@@ -7507,8 +7546,8 @@ swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
75077546
sourceSink.Results.end());
75087547
}
75097548

7510-
return llvm::makeArrayRef(targetSink.Results.data() + startSize,
7511-
targetSink.Results.size() - startSize);
7549+
return llvm::makeMutableArrayRef(targetSink.Results.data() + startSize,
7550+
targetSink.Results.size() - startSize);
75127551
}
75137552

75147553
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
@@ -7537,9 +7576,11 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
75377576
context.Cache.set(R.Key, *V);
75387577
}
75397578
assert(V.hasValue());
7540-
auto newItems = copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7541-
R.OnlyTypes, R.OnlyPrecedenceGroups);
7542-
postProcessResults(newItems, context.CodeCompletionKind, DC);
7579+
auto newItems =
7580+
copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7581+
R.OnlyTypes, R.OnlyPrecedenceGroups);
7582+
postProcessResults(newItems, context.CodeCompletionKind, DC,
7583+
&context.getResultSink());
75437584
}
75447585

75457586
handleResults(context.takeResults());

test/IDE/complete_flair_cache.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// %empty-directory(%t)
2+
// %empty-directory(%t.ccp)
3+
4+
// Repeat twice to ensure the cache file is not affected by the flair.
5+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -parse-as-library -filecheck %raw-FileCheck -completion-output-dir %t -completion-cache-path=%t.ccp
6+
// RUN: %target-swift-ide-test -batch-code-completion -source-filename %s -parse-as-library -filecheck %raw-FileCheck -completion-output-dir %t -completion-cache-path=%t.ccp
7+
8+
struct MyStruct {}
9+
protocol MyProtocol {}
10+
11+
func testType() {
12+
let a: #^TYPE^#
13+
// TYPE: Begin completions
14+
// TYPE-NOT: Keyword[import]
15+
// TYPE-NOT: Keyword[struct]
16+
// TYPE-NOT: Keyword[defer]
17+
// TYPE-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
18+
// TYPE-DAG: Decl[Protocol]/CurrModule: MyProtocol[#MyProtocol#]; name=MyProtocol
19+
// TYPE-DAG: Decl[Protocol]/OtherModule[Swift]/IsSystem: IteratorProtocol[#IteratorProtocol#]; name=IteratorProtocol
20+
// TYPE-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem: Int[#Int#]; name=Int
21+
// TYPE: End completions
22+
}
23+
24+
func testType() {
25+
#^EXPR^#
26+
// EXPR: Begin completions
27+
// EXPR-DAG: Keyword[import]/None/Flair[RareKeyword]: import; name=import
28+
// EXPR-DAG: Keyword[struct]/None/Flair[RareKeyword]: struct; name=struct
29+
// EXPR-DAG: Keyword[defer]/None: defer; name=defer
30+
// EXPR-DAG: Decl[Struct]/CurrModule: MyStruct[#MyStruct#]; name=MyStruct
31+
// EXPR-DAG: Decl[Protocol]/CurrModule/Flair[RareType]: MyProtocol[#MyProtocol#]; name=MyProtocol
32+
// EXPR-DAG: Decl[Protocol]/OtherModule[Swift]/Flair[RareType]/IsSystem: IteratorProtocol[#IteratorProtocol#]; name=IteratorProtocol
33+
// EXPR-DAG: Decl[Struct]/OtherModule[Swift]/IsSystem: Int[#Int#]; name=Int
34+
// EXPR: End completions
35+
}
36+
37+
#^TOPLEVEL^#
38+
// TOPLEVEL: Begin completions
39+
// TOPLEVEL-DAG: Keyword[import]/None: import; name=import
40+
// TOPLEVEL-DAG: Keyword[struct]/None/Flair[CommonKeyword]: struct; name=struct
41+
// TOPLEVEL-DAG: Keyword[defer]/None/Flair[ExprAtFileScope]: defer; name=defer
42+
// TOPLEVEL-DAG: Decl[Struct]/CurrModule/Flair[ExprAtFileScope]: MyStruct[#MyStruct#]; name=MyStruct
43+
// TOPLEVEL-DAG: Decl[Protocol]/CurrModule/Flair[RareType,ExprAtFileScope]: MyProtocol[#MyProtocol#]; name=MyProtocol
44+
// TOPLEVEL-DAG: Decl[Protocol]/OtherModule[Swift]/Flair[RareType,ExprAtFileScope]/IsSystem: IteratorProtocol[#IteratorProtocol#]; name=IteratorProtocol
45+
// TOPLEVEL-DAG: Decl[Struct]/OtherModule[Swift]/Flair[ExprAtFileScope]/IsSystem: Int[#Int#]; name=Int
46+
// TOPLEVEL: End completions

0 commit comments

Comments
 (0)