-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[CodeCompletion] Provide basic code completion support for Swift KeyPath. rdar://31768743 #9467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
270d355
f51ed73
120d11a
634d9b4
a4ce5e8
cc85745
db4b441
b05ce1c
49195d9
a9c06c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -525,6 +525,7 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) { | |
ParserResult<Expr> Parser::parseExprKeyPath() { | ||
// Consume '\'. | ||
SourceLoc backslashLoc = consumeToken(tok::backslash); | ||
llvm::SaveAndRestore<SourceLoc> slashLoc(SwiftKeyPathSlashLoc, backslashLoc); | ||
|
||
// FIXME: diagnostics | ||
ParserResult<Expr> rootResult, pathResult; | ||
|
@@ -538,6 +539,8 @@ ParserResult<Expr> Parser::parseExprKeyPath() { | |
} | ||
|
||
if (startsWithSymbol(Tok, '.')) { | ||
llvm::SaveAndRestore<Expr*> S(SwiftKeyPathRoot, rootResult.getPtrOrNull()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are not using SaveAndRestore, we are not able to use this part in parseExprPostfixSuffix. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, sorry I misread this. For some reason I didn't notice they were in completely different functions ,etc. |
||
|
||
// For uniformity, \.foo is parsed as if it were MAGIC.foo, so we need to | ||
// make sure the . is there, but parsing the ? in \.? as .? doesn't make | ||
// sense. This is all made more complicated by .?. being considered an | ||
|
@@ -1136,8 +1139,18 @@ Parser::parseExprPostfixSuffix(ParserResult<Expr> Result, bool isExprBasic, | |
|
||
// Handle "x.<tab>" for code completion. | ||
if (Tok.is(tok::code_complete)) { | ||
if (CodeCompletion && Result.isNonNull()) | ||
if (CodeCompletion && Result.isNonNull()) { | ||
if (InSwiftKeyPath) { | ||
Result = makeParserResult( | ||
new (Context) KeyPathExpr(SwiftKeyPathSlashLoc, Result.get(), | ||
nullptr)); | ||
} else if (SwiftKeyPathRoot) { | ||
Result = makeParserResult( | ||
new (Context) KeyPathExpr(SwiftKeyPathSlashLoc, SwiftKeyPathRoot, | ||
Result.get())); | ||
} | ||
CodeCompletion->completeDotExpr(Result.get(), /*DotLoc=*/TokLoc); | ||
} | ||
// Eat the code completion token because we handled it. | ||
consumeToken(tok::code_complete); | ||
Result.setHasCodeCompletion(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_1 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_2 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_3 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
|
||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_5 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_6 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_7 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_8 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_9 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_10 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
// RUN: %target-swift-ide-test -code-completion -source-filename %s -code-completion-token=PART_11 | %FileCheck %s -check-prefix=PERSON-MEMBER | ||
|
||
class Person { | ||
var name: String | ||
var friends: [Person] = [] | ||
var bestFriend: Person? = nil | ||
init(name: String) { | ||
self.name = name | ||
} | ||
func getName() -> String { return name } | ||
subscript(_ index: Int) -> Int { get { return 1} } | ||
} | ||
|
||
let keyPath1 = \Person.#^PART_1^# | ||
let keyPath2 = \Person.friends[0].#^PART_2^# | ||
let keyPath3 = \Person.friends[0].friends[0].friends[0].#^PART_3^# | ||
|
||
// FIXME: the optionality keypath should work after our compiler is ready. | ||
let keyPath4 = \Person.bestFriend?.#^PART_4^# | ||
let keyPath5 = \Person.friends.[0].friends[0].friends[0].#^PART_5^# | ||
let keyPath6 = \[Person].[0].#^PART_6^# | ||
let keyPath7 = \[Person].[0].friends[0].#^PART_7^# | ||
|
||
func foo1(_ p : Person) { | ||
_ = p[keyPath:\Person.#^PART_8^#] | ||
_ = p[keyPath:\Person.friends[0].#^PART_9^#] | ||
_ = p[keyPath:\[Person].[0].#^PART_10^#] | ||
_ = p[keyPath:\Person.friends.[0].friends[0].friends[0].#^PART_11^#] | ||
} | ||
|
||
// PERSON-MEMBER: Begin completions, 4 items | ||
// PERSON-MEMBER-NEXT: Decl[InstanceVar]/CurrNominal: name[#String#]; name=name | ||
// PERSON-MEMBER-NEXT: Decl[InstanceVar]/CurrNominal: friends[#[Person]#]; name=friends | ||
// PERSON-MEMBER-NEXT: Decl[InstanceVar]/CurrNominal: bestFriend[#Person?#]; name=bestFriend | ||
// PERSON-MEMBER-NEXT: Decl[Subscript]/CurrNominal: [{#Int#}][#Int#]; name=[Int] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use
backslashLoc
directly? It's not being modified.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This basically to save SwiftKeyPathSlashLoc in the parser context so parseExprPostfixSuffix can use it to create an instance of KeyPathExpr.