Skip to content

Commit 5869b40

Browse files
committed
[CodeCompletion] Don't modify CodeCompletionResult in place for cached results
Instead, allocate new `CodeCompletionResult` in the current sink. (cherry picked from commit f553826)
1 parent 55590e0 commit 5869b40

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) {
@@ -6497,9 +6515,16 @@ static void addConditionalCompilationFlags(ASTContext &Ctx,
64976515
}
64986516
}
64996517

6500-
static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
6501-
CompletionKind Kind, DeclContext *DC) {
6502-
for (CodeCompletionResult *result : results) {
6518+
/// Add flairs to the each item in \p results .
6519+
///
6520+
/// If \p Sink is passed, the pointer of the each result may be replaced with a
6521+
/// pointer to the new item allocated in \p Sink.
6522+
/// If \p Sink is nullptr, the pointee of each result may be modified in place.
6523+
static void postProcessResults(MutableArrayRef<CodeCompletionResult *> results,
6524+
CompletionKind Kind, DeclContext *DC,
6525+
CodeCompletionResultSink *Sink) {
6526+
for (CodeCompletionResult *&result : results) {
6527+
bool modified = false;
65036528
auto flair = result->getFlair();
65046529

65056530
// Starting a statement with a protocol name is not common. So protocol
@@ -6512,15 +6537,27 @@ static void postProcessResults(ArrayRef<CodeCompletionResult *> results,
65126537
Kind != CompletionKind::TypeDeclResultBeginning &&
65136538
Kind != CompletionKind::GenericRequirement) {
65146539
flair |= CodeCompletionFlairBit::RareTypeAtCurrentPosition;
6540+
modified = true;
65156541
}
65166542

65176543
// Starting a statement at top-level in non-script files is invalid.
65186544
if (Kind == CompletionKind::StmtOrExpr &&
65196545
result->getKind() == CodeCompletionResult::ResultKind::Declaration &&
65206546
isCodeCompletionAtTopLevelOfLibraryFile(DC)) {
65216547
flair |= CodeCompletionFlairBit::ExpressionAtNonScriptOrMainFileScope;
6548+
modified = true;
6549+
}
6550+
6551+
if (!modified)
6552+
continue;
6553+
6554+
if (Sink) {
6555+
// Replace the result with a new result with the flair.
6556+
result = result->withFlair(flair, *Sink);
6557+
} else {
6558+
// 'Sink' == nullptr means the result is modifiable in place.
6559+
result->setFlair(flair);
65226560
}
6523-
result->setFlair(flair);
65246561
}
65256562
}
65266563

@@ -6640,7 +6677,8 @@ static void deliverCompletionResults(CodeCompletionContext &CompletionContext,
66406677
CompletionContext.typeContextKind = Lookup.typeContextKind();
66416678

66426679
postProcessResults(CompletionContext.getResultSink().Results,
6643-
CompletionContext.CodeCompletionKind, DC);
6680+
CompletionContext.CodeCompletionKind, DC,
6681+
/*Sink=*/nullptr);
66446682

66456683
Consumer.handleResultsAndModules(CompletionContext, RequestedModules, DC);
66466684
}
@@ -7424,7 +7462,8 @@ void swift::ide::lookupCodeCompletionResultsFromModule(
74247462
CompletionLookup Lookup(targetSink, module->getASTContext(), SF);
74257463
Lookup.lookupExternalModuleDecls(module, accessPath, needLeadingDot);
74267464
}
7427-
ArrayRef<CodeCompletionResult *>
7465+
7466+
MutableArrayRef<CodeCompletionResult *>
74287467
swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
74297468
CodeCompletionResultSink &sourceSink,
74307469
bool onlyTypes,
@@ -7485,8 +7524,8 @@ swift::ide::copyCodeCompletionResults(CodeCompletionResultSink &targetSink,
74857524
sourceSink.Results.end());
74867525
}
74877526

7488-
return llvm::makeArrayRef(targetSink.Results.data() + startSize,
7489-
targetSink.Results.size() - startSize);
7527+
return llvm::makeMutableArrayRef(targetSink.Results.data() + startSize,
7528+
targetSink.Results.size() - startSize);
74907529
}
74917530

74927531
void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
@@ -7515,9 +7554,11 @@ void SimpleCachingCodeCompletionConsumer::handleResultsAndModules(
75157554
context.Cache.set(R.Key, *V);
75167555
}
75177556
assert(V.hasValue());
7518-
auto newItems = copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7519-
R.OnlyTypes, R.OnlyPrecedenceGroups);
7520-
postProcessResults(newItems, context.CodeCompletionKind, DC);
7557+
auto newItems =
7558+
copyCodeCompletionResults(context.getResultSink(), (*V)->Sink,
7559+
R.OnlyTypes, R.OnlyPrecedenceGroups);
7560+
postProcessResults(newItems, context.CodeCompletionKind, DC,
7561+
&context.getResultSink());
75217562
}
75227563

75237564
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)