nicklockwood / SwiftFormat

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

conditionalAssignment bug with compiler directives (#if) #1582

Closed honghaoz closed 8 months ago

honghaoz commented 8 months ago

Hi, I encountered an issue with the conditionalAssignment rule (Swift 5.9)

For example, for the following code:

  public enum ButtonState: Equatable {

    case normal
    case pressed // highlighted
    case selected
    case disabled // inactive
    #if os(macOS)
    case hovered
    #endif
  }

  func foo(buttonState: ButtonState) -> Int {
    let str: String
    let number: Int
    switch buttonState {
      #if os(macOS)
      case .normal,
          .hovered:
        str = "1"
        number = 1
      #else
      case .normal:
        str = "1"
        number = 1
      #endif

      case .pressed:
        str = "1"
        number = 1

      case .selected:
        return -1

      case .disabled:
        return -1
    }

    return 0
  }

After formatting, it changes to:

  func foo(buttonState: ButtonState) -> Int {
    let str: String
    let number: Int = switch buttonState {
    #if os(macOS)
    case .normal,
         .hovered:
      str = "1"
      number = 1
    #else
    case .normal:
      str = "1"
      number = 1
    #endif

    case .pressed:
      str = "1"
      number = 1

    case .selected:
      return -1

    case .disabled:
      return -1
    }

    return 0
  }

which won't compile anymore.

Reproducible on On Xcode 15.0.1 (Swift 5.9), SwiftFormat 0.52.9

nicklockwood commented 8 months ago

FYI @calda I've fixed this for now by just disabling the rule for switch statements containing conditional compilation logic. A proper fix would check for returns or assignments inside the conditional compilation blocks, but that seemed a little too complex and risky for a quick fix.

nicklockwood commented 8 months ago

@honghaoz fixed in 0.52.10

calda commented 8 months ago

Thank you! I think this is a reasonable strategy. As one example off the top of my head the organizeDeclarations rule also doesn’t modify code within conditional complication blocks, since it adds complexity.