Skip to content
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

Provide a way to add prefix to statements or control flows before newline #1504

Open
mscheong01 opened this issue Mar 29, 2023 · 1 comment

Comments

@mscheong01
Copy link

Is your feature request related to a problem? Please describe.
When generating code that includes constructor invocation, we come across the need to end the control flow with },, not just }
ex)

val some = SomeClass(
    name = if ( // some condition ) {
        "a"
    } else {
        "b"
    },
    age = 10,
)

we could do

funSpecBuilder
    ~
    .endControlFlow()
    .addStatement(",")
    ~
    .build()

but this would end up as:

}
,

Describe the solution you'd like
solutions were proposed by maintainers here:
#1503 (comment)
another solution that could maybe work without breaking change is add a withPrefix = "" parameter to FunSpec.Builder.endControlFlow

@JakeWharton
Copy link
Member

So as written I think this is an X-Y problem. What you want is reasonable, but I don't think it's as simple as allowing you to append a comma.

For one, the control flow API and the statement API are designed for Java and not Kotlin. Problems like this are fighting the fact that the API was inherited from a heavily statement-based language whereas Kotlin is heavily expression-based.

I think we need to step back and evaluate what the code body APIs look like from a more fundamental stance and potentially overhaul them completely.

The right way to emit the given example is a statement invoking the constructor of a type with an argument list composed of a series of expressions. You can do this today but it's a little more verbose than it needs to be.

Next, the question is how do you build expressions for syntactical elements like if/else and when. The wrong way that we're forced to use today is through the control flow API, but that API assumes too much. You can already see we've corrupted it today by using it for trailing lambdas and their argument names.

Much of the existing API is used because it gets you visually close to the output you want but doesn't correlate semantically to the type of syntax you're actually emitting. And then when mismatches happen we get issues like this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants