nicklockwood / SwiftFormat

A command-line tool and Xcode Extension for formatting Swift code
MIT License
7.83k stars 635 forks source link

[Bug] Unexpected `--ifdef no-indent` behavior on SwiftUI modifiers #1332

Open davdroman opened 1 year ago

davdroman commented 1 year ago

I have this piece of SwiftUI code:

import SwiftUI

struct Example: View {
    var body: some View {
        Text("Example")
            .frame(maxWidth: 500, alignment: .leading)
            #if !os(tvOS)
            .font(.system(size: 14, design: .monospaced))
            #endif
            .padding(10)
    }
}

When running SwiftFormat 0.50.6 with --ifdef no-indent I get:

import SwiftUI

struct Example: View {
    var body: some View {
        Text("Example")
            .frame(maxWidth: 500, alignment: .leading)
        #if !os(tvOS)
            .font(.system(size: 14, design: .monospaced))
        #endif
            .padding(10)
    }
}

... whereas I would expect no changes to be made.

As a side note, I was hoping to just be able to disable ifdef as a rule altogether but I don't believe this is possible given it doesn't have a valid name to pass onto --disable.

nicklockwood commented 1 year ago

This is as-designed, but I'm not sure if it's desirable behavior or not. no-indent means to not indent the code inside the ifdef, rather than the ifdef statement itself. I guess an additional preserve option to preserve the relative position of the statement as-is might be a good idea?

--ifdef is just a configuration option for the indent rule, so the only way to disable it is with --disable indent. You could do that for just this file or section using // swiftformat:disable indent.

davdroman commented 1 year ago

I guess an additional preserve option to preserve the relative position of the statement as-is might be a good idea?

I could definitely use something like that.

You could do that for just this file or section using // swiftformat:disable indent.

Neat! Thanks 🙂

JUSTINMKAUFMAN commented 1 year ago

Similar (same?) issue, where, for example, this:

.toolbar {
    ToolbarItem(placement: {
        #if os(iOS)
        .cancellationAction
        #else
        .automatic
        #endif
    }()) { ... }
}

...gets formatted to this:

.toolbar {
    ToolbarItem(placement: {
        #if os(iOS)
            .cancellationAction
        #else
            .automatic
        #endif
    }()) { ... }
}

Would a solution be to allow for specifying the size of the indent in the ifdef configuration option? Presumably if I could pass --ifdef double-indent or --ifdef align-with-code then it would not make any changes to the original code.

Just a thought - thanks for your work on this great tool!

gillesguillemin commented 1 year ago

We're seeing the same issues as @JUSTINMKAUFMAN, primarily for SwiftUI modifiers, and seemingly semi-randomly (sometimes it doesn't add pesky indents, sometimes it does, without any obvious reason).