Skip to content

Commit e255bac

Browse files
committed
[code-completion] Fix type context for single-expression implicit getter
This adds an implicit body so that we can dig out the return type context the same way as a normal function. For now, we are also treating the first expression in a multi-statement implicit getter body the same way; we'll need to refactor how we complete in accessors to differentiate those cases.
1 parent b14cd91 commit e255bac

File tree

6 files changed

+30
-12
lines changed

6 files changed

+30
-12
lines changed

include/swift/Parse/CodeCompletionCallbacks.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ class CodeCompletionCallbacks {
180180
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) {};
181181

182182
/// Complete at the beginning of accessor in a accessor block.
183-
virtual void completeAccessorBeginning() {};
183+
virtual void completeAccessorBeginning(CodeCompletionExpr *E) {};
184184

185185
/// Complete the keyword in attribute, for instance, @available.
186186
virtual void completeDeclAttrKeyword(Decl *D, bool Sil, bool Param) {};

lib/IDE/CodeCompletion.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13731373
void completeInPrecedenceGroup(SyntaxKind SK) override;
13741374
void completeNominalMemberBeginning(
13751375
SmallVectorImpl<StringRef> &Keywords, SourceLoc introducerLoc) override;
1376-
void completeAccessorBeginning() override;
1376+
void completeAccessorBeginning(CodeCompletionExpr *E) override;
13771377

13781378
void completePoundAvailablePlatform() override;
13791379
void completeImportDecl(std::vector<std::pair<Identifier, SourceLoc>> &Path) override;
@@ -4588,9 +4588,11 @@ void CodeCompletionCallbacksImpl::completeNominalMemberBeginning(
45884588
CurDeclContext = P.CurDeclContext;
45894589
}
45904590

4591-
void CodeCompletionCallbacksImpl::completeAccessorBeginning() {
4591+
void CodeCompletionCallbacksImpl::completeAccessorBeginning(
4592+
CodeCompletionExpr *E) {
45924593
Kind = CompletionKind::AccessorBeginning;
45934594
CurDeclContext = P.CurDeclContext;
4595+
CodeCompleteTokenExpr = E;
45944596
}
45954597

45964598
static bool isDynamicLookup(Type T) {
@@ -5157,8 +5159,12 @@ void CodeCompletionCallbacksImpl::doneParsing() {
51575159
}
51585160

51595161
case CompletionKind::AccessorBeginning: {
5160-
if (isa<AccessorDecl>(ParsedDecl))
5162+
if (isa<AccessorDecl>(ParsedDecl)) {
5163+
ExprContextInfo ContextInfo(CurDeclContext, CodeCompleteTokenExpr);
5164+
Lookup.setExpectedTypes(ContextInfo.getPossibleTypes(),
5165+
ContextInfo.isSingleExpressionBody());
51615166
DoPostfixExprBeginning();
5167+
}
51625168
break;
51635169
}
51645170

lib/Parse/ParseDecl.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4492,20 +4492,30 @@ ParserStatus Parser::parseGetSet(ParseDeclOptions Flags,
44924492

44934493
if (Tok.is(tok::code_complete)) {
44944494
if (CodeCompletion) {
4495+
CodeCompletionExpr *CCE = nullptr;
44954496
if (IsFirstAccessor && !parsingLimitedSyntax) {
44964497
// If CC token is the first token after '{', it might be implicit
44974498
// getter. Set up dummy accessor as the decl context to populate
44984499
// 'self' decl.
4500+
4501+
// FIXME: if there is already code inside the body, we should fall
4502+
// through to parseImplicitGetter and handle the completion there so
4503+
// that we can differentiate a single-expression body from the first
4504+
// expression in a multi-statement body.
44994505
auto getter = createAccessorFunc(
45004506
accessors.LBLoc, /*ValueNamePattern*/ nullptr, GenericParams,
45014507
Indices, ElementTy, StaticLoc, Flags, AccessorKind::Get,
45024508
storage, this, /*AccessorKeywordLoc*/ SourceLoc());
4509+
CCE = new (Context) CodeCompletionExpr(Tok.getLoc());
4510+
getter->setBody(BraceStmt::create(Context, Tok.getLoc(),
4511+
ASTNode(CCE), Tok.getLoc(),
4512+
/*implicit*/ true));
45034513
accessors.add(getter);
45044514
CodeCompletion->setParsedDecl(getter);
45054515
} else {
45064516
CodeCompletion->setParsedDecl(storage);
45074517
}
4508-
CodeCompletion->completeAccessorBeginning();
4518+
CodeCompletion->completeAccessorBeginning(CCE);
45094519
}
45104520
consumeToken(tok::code_complete);
45114521
accessorHasCodeCompletion = true;

test/IDE/complete_accessor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@
135135
// NO_OBSERVER-NOT: willSet
136136
// NO_OBSERVER-NOT: didSet
137137

138-
// WITH_GLOBAL: Decl[GlobalVar]/CurrModule: globalValue[#String#];
138+
// WITH_GLOBAL: Decl[GlobalVar]/CurrModule{{(/TypeRelation\[Identical\])?}}: globalValue[#String#];
139139
// NO_GLOBAL-NOT: globalValue;
140140

141141
// WITH_SELF: Decl[LocalVar]/Local: self[#{{.+}}#]; name=self

test/IDE/complete_crashes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ while true {
6767
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=GENERIC_PARAM_AND_ASSOC_TYPE | %FileCheck %s -check-prefix=GENERIC_PARAM_AND_ASSOC_TYPE
6868
struct CustomGenericCollection<Key> : ExpressibleByDictionaryLiteral {
6969
// GENERIC_PARAM_AND_ASSOC_TYPE: Begin completions
70-
// GENERIC_PARAM_AND_ASSOC_TYPE-DAG: Decl[InstanceVar]/CurrNominal: count[#Int#]; name=count
70+
// GENERIC_PARAM_AND_ASSOC_TYPE-DAG: Decl[InstanceVar]/CurrNominal/TypeRelation[Identical]: count[#Int#]; name=count
7171
// GENERIC_PARAM_AND_ASSOC_TYPE-DAG: Decl[GenericTypeParam]/Local: Key[#Key#]; name=Key
7272
// GENERIC_PARAM_AND_ASSOC_TYPE-DAG: Decl[TypeAlias]/CurrNominal: Value[#CustomGenericCollection<Key>.Value#]; name=Value
7373
// GENERIC_PARAM_AND_ASSOC_TYPE: End completions

test/IDE/complete_single_expression_return.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@
2222
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorUnresolved | %FileCheck %s -check-prefix=TestSingleExprAccessorUnresolved
2323
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestNonSingleExprAccessorUnresolved | %FileCheck %s -check-prefix=TestNonSingleExprAccessorUnresolved
2424
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprLocalAccessorUnresolved | %FileCheck %s -check-prefix=TestSingleExprAccessorUnresolved
25-
// FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorGlobal | %FileCheck %s -check-prefix=TestSingleExprAccessorGlobal
25+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorGlobal | %FileCheck %s -check-prefix=TestSingleExprAccessorGlobal
2626
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestNonSingleExprAccessorGlobal | %FileCheck %s -check-prefix=TestNonSingleExprAccessorGlobal
2727
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorGetUnresolved | %FileCheck %s -check-prefix=TestSingleExprAccessorUnresolved
2828
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorSetUnresolved | %FileCheck %s -check-prefix=TestSingleExprAccessorSetUnresolved
29-
// FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorGetGlobal | %FileCheck %s -check-prefix=TestSingleExprAccessorGlobal
29+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprAccessorGetGlobal | %FileCheck %s -check-prefix=TestSingleExprAccessorGlobal
3030

3131
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprSubscriptRet | %FileCheck %s -check-prefix=TestSingleExprSubscriptRet
3232
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprSubscript | %FileCheck %s -check-prefix=TestSingleExprSubscript
3333
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprSubscriptUnresolved | %FileCheck %s -check-prefix=TestSingleExprSubscriptUnresolved
3434
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestNonSingleExprSubscriptUnresolved | %FileCheck %s -check-prefix=TestNonSingleExprSubscriptUnresolved
35-
// FIXME: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprSubscriptGlobal | %FileCheck %s -check-prefix=TestSingleExprSubscriptGlobal
35+
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=TestSingleExprSubscriptGlobal | %FileCheck %s -check-prefix=TestSingleExprSubscriptGlobal
3636

3737
// MARK: Single-expression closures
3838

@@ -418,9 +418,11 @@ struct TestNonSingleExprAccessorGlobal {
418418
#^TestNonSingleExprAccessorGlobal^#
419419
return 42
420420
}
421+
421422
// TestNonSingleExprAccessorGlobal: Begin completions
422423
// TestNonSingleExprAccessorGlobal-DAG: Decl[InstanceMethod]/CurrNominal: str()[#String#];
423-
// TestNonSingleExprAccessorGlobal-DAG: Decl[InstanceMethod]/CurrNominal: int()[#Int#];
424+
// FIXME: should should not have type context.
425+
// TestNonSingleExprAccessorGlobal-DAG: Decl[InstanceMethod]/CurrNominal/TypeRelation[Identical]: int()[#Int#];
424426
// TestNonSingleExprAccessorGlobal-DAG: Decl[InstanceMethod]/CurrNominal: void()[#Void#];
425427
// TestNonSingleExprAccessorGlobal: End completions
426428
}
@@ -443,7 +445,7 @@ struct TestSingleExprAccessorGetGlobal {
443445
func str() -> String { return "" }
444446
func int() -> Int { return 0 }
445447

446-
var test: MyEnum {
448+
var test: Int {
447449
get {
448450
#^TestSingleExprAccessorGetGlobal^#
449451
}

0 commit comments

Comments
 (0)