Unexpected wrapping when using onePerLine on call parameters
I want function call parameters to wrap one per line if the call line gets longer than 120 characters.
For example:
foo(red, yellow + green, blue); // Assuming this breaks line length
Should become:
foo(
red,
yellow + green,
blue
);
So I used the following hxformat file:
{
"wrapping": {
"maxLineLength": 120,
"callParameter": {
"defaultWrap": "fillLine",
"rules": [
{
"conditions": [
{
"cond": "lineLength >= n",
"value": 120
}
],
"type": "onePerLine"
}
]
},
"functionSignature": {
"defaultWrap": "fillLine",
"rules": [
{
"conditions": [
{
"cond": "lineLength >= n",
"value": 120
}
],
"type": "onePerLine"
}
]
}
},
"whitespace": {
"colonPolicy": "after",
"typeHintColonPolicy": "after"
}
}
Which seems to work great, until I came across this file (here trimmed down for repro):
class MeshChunkTask extends Task {
public override function run(context: TaskContext) {
var meshingVoxelBuffer = meshingVoxelBufferPerThread[context.threadIndex];
meshingVoxelBuffer.fill(0);
var srcI = 0;
for (rcz in -1...2) {
for (rcy in -1...2) {
for (rcx in -1...2) {
var src = chunks[srcI];
srcI += 1;
if (src != null) {
meshingVoxelBuffer.paste(src.voxels,
rcx * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcy * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcz * Constants.CHUNK_SIZE
+ Mesher.PAD);
src.releaseShared();
}
}
}
}
outputPrim = Mesher.build(meshingVoxelBuffer);
outputList.push(this);
}
}
The call to paste( is not formatted the way I expected. I expected the first parameter to be on the next line, but it is on the first. Also, I expected the expression of each parameter to be on one line, but instead they are getting further broken up at the + operators. They don't even break line length on their own.
No matter how I rearrange this code (not changing what it does), it keeps formatting like above.
It still reproduces as this simple function:
function foo() {
meshingVoxelBuffer.paste(src.voxels,
rcx * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcy * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcz * Constants.CHUNK_SIZE
+ Mesher.PAD);
}
Now something curious, if I remove + Mesher.PAD from the last parameter, it suddenly formats as I expect:
meshingVoxelBuffer.paste(
src.voxels,
rcx * Constants.CHUNK_SIZE + Mesher.PAD,
rcy * Constants.CHUNK_SIZE + Mesher.PAD,
rcz * Constants.CHUNK_SIZE
);
But if I add it back... it breaks.
meshingVoxelBuffer.paste(src.voxels,
rcx * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcy * Constants.CHUNK_SIZE
+ Mesher.PAD,
rcz * Constants.CHUNK_SIZE
+ Mesher.PAD);
I think the issue here is, that there are multiple competing wrapping rules at play. one is callParameter and the other is opAddSubChain. if you set opAddSubChain to noWrap you should see the results you are expecting. obviously you might have code that wants (or needs) opAddSubChain to happen, so you'll have to formulate rules that only apply to those places.
unfortunately formatter doesn't have a way of weighting wrapping types, or selecting the "best" one in cases where multiple wrapping rules apply.
I see, I had a suspicion opAddSubChain was involved but didn't find the right configuration for making it work. I was trying fillLine instead of noWrap and it still broke in a different way:
meshingVoxelBuffer.paste(src.voxels,
rcx * Constants.CHUNK_SIZE +
Mesher.PAD,
rcy * Constants.CHUNK_SIZE + Mesher.PAD,
rcz * Constants.CHUNK_SIZE +
Mesher.PAD
);
Not sure why it would still do this, because there is space to fill the line, it's not reaching the limit.
But using noWrap does what I expect. Though I'll probably have to discover where it falls short eventually.
(I wish comments were allowed to explain why I add this in the hxformat file)
Not sure why it would still do this, because there is space to fill the line, it's not reaching the limit.
when applying rules or when figuring out what rules to apply, formatter works with an in-memory representation of your code. before checking wrapping rules your paste call is all in one line. and in cases where multiple wrapping types apply to the same section of code each type doesn't necessarily look at wrapping done by previous rules. they basically see one line of code that exceeds 160 characters and select the first rule entry that matches all criteria.
But using
noWrapdoes what I expect. Though I'll probably have to discover where it falls short eventually. (I wish comments were allowed to explain why I add this in the hxformat file)
git blame works quite well, but I agree that allowing comments in hxformat.json would be a nice feature to have.