-
Notifications
You must be signed in to change notification settings - Fork 81
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
Support context receivers #400
Changes from 1 commit
8993576
14e5f1d
9c3d852
0694e1e
d9aeecd
8502fd5
e2fe9bd
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 |
---|---|---|
|
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.psi.KtCollectionLiteralExpression | |
import org.jetbrains.kotlin.psi.KtConstantExpression | ||
import org.jetbrains.kotlin.psi.KtConstructorDelegationCall | ||
import org.jetbrains.kotlin.psi.KtContainerNode | ||
import org.jetbrains.kotlin.psi.KtContextReceiverList | ||
import org.jetbrains.kotlin.psi.KtContinueExpression | ||
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry | ||
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration | ||
|
@@ -124,6 +125,7 @@ import org.jetbrains.kotlin.psi.psiUtil.children | |
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespace | ||
import org.jetbrains.kotlin.psi.psiUtil.startOffset | ||
import org.jetbrains.kotlin.psi.psiUtil.startsWithComment | ||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes | ||
|
||
/** An AST visitor that builds a stream of {@link Op}s to format. */ | ||
class KotlinInputAstVisitor( | ||
|
@@ -162,6 +164,7 @@ class KotlinInputAstVisitor( | |
builder.sync(function) | ||
builder.block(ZERO) { | ||
visitFunctionLikeExpression( | ||
function.getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST), | ||
function.modifierList, | ||
"fun", | ||
function.typeParameterList, | ||
|
@@ -282,6 +285,7 @@ class KotlinInputAstVisitor( | |
* list of supertypes. | ||
*/ | ||
private fun visitFunctionLikeExpression( | ||
contextReceiverList: KtContextReceiverList?, | ||
modifierList: KtModifierList?, | ||
keyword: String, | ||
typeParameters: KtTypeParameterList?, | ||
|
@@ -294,6 +298,9 @@ class KotlinInputAstVisitor( | |
typeOrDelegationCall: KtElement?, | ||
) { | ||
builder.block(ZERO) { | ||
if (contextReceiverList != null) { | ||
visitContextReceiverList(contextReceiverList) | ||
} | ||
if (modifierList != null) { | ||
visitModifierList(modifierList) | ||
} | ||
|
@@ -1372,6 +1379,7 @@ class KotlinInputAstVisitor( | |
|
||
builder.block(ZERO) { | ||
visitFunctionLikeExpression( | ||
null, | ||
accessor.modifierList, | ||
accessor.namePlaceholder.text, | ||
null, | ||
|
@@ -1533,6 +1541,7 @@ class KotlinInputAstVisitor( | |
|
||
val delegationCall = constructor.getDelegationCall() | ||
visitFunctionLikeExpression( | ||
constructor.getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST), | ||
constructor.modifierList, | ||
"constructor", | ||
null, | ||
|
@@ -1638,6 +1647,16 @@ class KotlinInputAstVisitor( | |
builder.forcedBreak() | ||
} | ||
|
||
/** Example `context(Logger, Raise<Error>)` */ | ||
override fun visitContextReceiverList(contextReceiverList: KtContextReceiverList) { | ||
builder.sync(contextReceiverList) | ||
builder.token("context") | ||
builder.token("(") | ||
visitEachCommaSeparated(contextReceiverList.contextReceivers()) | ||
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. visitEachCommaSeparated has parameters for enclosing parens, to handle some weird indentation cases. 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. Pushed a commit to use that, thank you for pointing that out! |
||
builder.token(")") | ||
builder.forcedBreak() | ||
} | ||
|
||
/** For example `@Magic private final` */ | ||
override fun visitModifierList(list: KtModifierList) { | ||
builder.sync(list) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -110,4 +110,25 @@ class TokenizerTest { | |
.containsExactly(0, -1, 1, 2, 3, -1, 4, -1, 5, 6, 7) | ||
.inOrder() | ||
} | ||
|
||
@Test | ||
fun `Context receivers are parsed correctly`() { | ||
val code = """ | ||
|class A { | ||
| context(Logger, Raise<Error>) | ||
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. What happens if the list of receivers is longer than the max line length? What happens if there's a trailing comma? What happens to comments inside the parens? 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.
That's a compile error giving
I've changed the test to include a comment, which also shows that the regular wrapping logic works as it goes over the test's max line length. 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. Thanks. It's very weird to me that trailing commas aren't accepted in the context receiver list. I suspect that's a bug in kotlinc, but nothing we can do right now. https://youtrack.jetbrains.com/issue/KT-59506/Trailing-commas-are-illegal-in-context-receiver-lists |
||
| fun test() {} | ||
|} | ||
|""".trimMargin().trimMargin() | ||
|
||
val file = Parser.parse(code) | ||
val tokenizer = Tokenizer(code, file) | ||
file.accept(tokenizer) | ||
|
||
assertThat(tokenizer.toks.map { it.originalText }) | ||
.containsExactly("class", " ", "A", " ", "{", "\n", " ", "context", "(", "Logger", ",", " ", "Raise", "<", "Error", ">", ")", "\n", " ", "fun", " ", "test", "(", ")", " ", "{", "}", "\n", "}") | ||
.inOrder() | ||
assertThat(tokenizer.toks.map { it.index }) | ||
.containsExactly(0, -1, 1, -1, 2, -1, -1, 3, 4, 5, 6, -1, 7, 8, 9, 10, 11, -1, -1, 12, -1, 13, 14, 15, -1, 16, 17, -1, 18) | ||
.inOrder() | ||
} | ||
} |
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.
I may have missed it, but there don't seem to be changes for context receivers on lambda parameters: