Comments (13)
I prefer option 1 for the ones you presented.
But also, if it's formatted differently, I'd go with option 3.
For example:
list.asSequence()
.map { i ->
i * 2
}
.also {
println(it)
}
from ktfmt.
@JavierSegoviaCordoba - GitHub Discussions enabled
from ktfmt.
@hick209, there is indeed no dilemma in the case where the lambda call is not the first one in the chain, since it then looks similar to your example (4 spaces, not 2 though).
from ktfmt.
This is relevant again now that we're looking into placing the closing paren on the next line when formatting using --google-style
.
Option 4
doIt(
foo1,
foo2,
foo3
).doThat()
.foo()
.bar(
foo1,
foo2,
foo3
).doThat(
foo1,
foo2,
foo3
)
To me this looks bad because some lines start with a dot, some with closing parent.
Option 5
doIt(
foo1,
foo2,
foo3
)
.doThat()
.foo()
.bar(
foo1,
foo2,
foo3
)
.doThat(
foo1,
foo2,
foo3
)
It's wasteful for the first call.
Option 6
doIt(
foo1,
foo2,
foo3
)
.doThat()
.foo()
.bar(
foo1,
foo2,
foo3
)
.doThat(
foo1,
foo2,
foo3
)
This makes it easy to miss that we have a chain here at all.
Kotlin source code has a bit of Option 4 and a bit of Option 5:
FunctionDescriptor toStringDescriptor = receiverClassDescriptor.getUnsubstitutedMemberScope()
…
.filter(
f -> f.getValueParameters().size() == 0
&& KotlinBuiltIns.isString(f.getReturnType())
&& f.getDispatchReceiverParameter() != null
&& f.getExtensionReceiverParameter() == null
)
.findFirst()
.orElseThrow(() -> new AssertionError("'toString' not found in member scope of " + receiverClassDescriptor));
but,
SimpleFunctionDescriptorImpl.create(
classDescriptor, Annotations.EMPTY, Name.identifier(name), CallableMemberDescriptor.Kind.DECLARATION,
funDescriptor.source
).apply {
initialize(
null,
…
)
}
and even
StackValue.field(
AsmTypes.OBJECT_TYPE, Type.getObjectType(v.thisName), languageVersionSettings.dataFieldName(), false,
StackValue.LOCAL_0
).store(StackValue.local(1, AsmTypes.OBJECT_TYPE), codegen.v)
(what is this)
cc @bethcutler
from ktfmt.
I'm not sure what cases these options would trigger in. I would prefer same line as long as everything fits on the same line:
doIt(
foo1,
foo2,
foo3
).doThat().foo().bar(foo1)
And in fact I like the look of single chained calls like this:
doIt(
foo1,
foo2,
foo3
).doThat(
foo1,
foo2
).bar(
foo1,
foo2
)
So maybe the option I prefer the most is
Option 7
doIt(
foo1,
foo2,
foo3
).doThat().foo().bar(
foo1,
foo2,
foo3
).member.method(argument)
Having to choose from the above options, I would probably prefer 4 or 5, but only in exceptional cases where the chained calls can't fit on the same line as the closing paren.
from ktfmt.
We try to maintain the Rectangle rule, so I think Option 5 is the way to go.
The RFC commit 675edab implements it.
from ktfmt.
Currently I am seeing a floating dot some times but it feels pretty unnatural.
Is that intended or just a bug?
from ktfmt.
@JavierSegoviaCordoba can you give an example?
from ktfmt.
@cgrushko sorry about my late response but I am waiting until I can reproduce it again, but no luck until now :/
Can you enable GitHub discussions? I was thinking of opening an issue about Jetpack Compose formatting and should be great to do in Discussions instead of opening it as an issue :)
from ktfmt.
@cgrushko .dropLastWhile
is correct?
val changelogToWrite =
buildString {
filteredChangelog.onEachIndexed { index, line ->
when {
h1Regex.matches(line) -> appendLine("$line\n")
h2Regex.matches(line) -> appendLine("$line")
h3Regex.matches(line) &&
filteredChangelog.size != index + 1 &&
!h3Regex.matches(filteredChangelog[index + 1]) -> appendLine("\n$line\n")
else -> appendLine(line)
}
}
}
.dropLastWhile { it.isWhitespace() } + " \n"
I think this should be
val changelogToWrite =
buildString {
filteredChangelog.onEachIndexed { index, line ->
when {
h1Regex.matches(line) -> appendLine("$line\n")
h2Regex.matches(line) -> appendLine("$line")
h3Regex.matches(line) &&
filteredChangelog.size != index + 1 &&
!h3Regex.matches(filteredChangelog[index + 1]) -> appendLine("\n$line\n")
else -> appendLine(line)
}
}
}
.dropLastWhile { it.isWhitespace() } + " \n"
from ktfmt.
I think that in order to be consistent with Option 5, the lambda passed to buildString should be indented extra 4 spaces, and so the floating dot stops floating.
from ktfmt.
But it is not looking strange for you? I think the second one is more readable, the first one can lead to thinking that dropLastWhile
is for filteredChangelog...
instead of buildString
from ktfmt.
Closing this as it's an old discussion and @davidtorosyan has made significant contributions on this space that might have met some of the concerns raised here.
Feel free to reopen if you feel there's more to be discussed here
from ktfmt.
Related Issues (20)
- Android Studio / IDEA plugin yields different results than running ktfmt HOT 11
- Treat trailing Elvis operator as part of a call chain HOT 2
- Adding target jar to releases HOT 2
- Weird lambda formatting when wrapping long line HOT 3
- Intellij Plugin set to Google (internal) always removes trailing commas HOT 1
- Lambdas following a statement can be treated as lambda arguments, breaking syntax HOT 1
- No artifacts were released for v0.48 and v0.49 HOT 4
- Trailing comma gets removed if there is only one parameter and it is formatted to be on its own line HOT 2
- ktfmt doesn't seem to work in IJ 2024.1.1 HOT 6
- Is ktfmt used on itself? HOT 5
- Misspelled flags in CLI can cause user data loss HOT 1
- How can I config Intellij plugin? HOT 2
- error: did not generate token "context" HOT 3
- Google style with trailing comma does not use maxWidth correctly HOT 1
- Nested function calls with named parameters is incredibly difficult to read and results in unnecessary nesting HOT 8
- ktfmt 0.51 incompatible with Spotless Gradle plugin HOT 2
- Consider providing a binary jar HOT 7
- ver 1.1.0.51 update breaks ktfmt intellij plugin setting screen if style is "Dropbox" HOT 2
- IDEA plugin v1.1.0.51 with Kotlinlang formats incorrectly HOT 3
- Unexpected change in Kotlinlang formatting HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ktfmt.