From 5264e9de326330e39c481811a276b9ac7d22d5ee Mon Sep 17 00:00:00 2001 From: Alejandro Isaza Date: Mon, 19 Aug 2019 11:43:45 -0700 Subject: [PATCH] Add option to not indent conditional compilation blocks --- Documentation/Configuration.md | 4 ++ .../Configuration.swift | 7 +++ .../TokenStreamCreator.swift | 16 ++++- .../IfConfigTests.swift | 61 +++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) diff --git a/Documentation/Configuration.md b/Documentation/Configuration.md index 5cfa2893..d6051572 100644 --- a/Documentation/Configuration.md +++ b/Documentation/Configuration.md @@ -59,6 +59,10 @@ top-level keys and values: If false (the default), arguments will be laid out horizontally first, with line breaks only being fired when the line length would be exceeded. +* `indentConditionalCompilationBlocks` _(boolean)_: Determines if + conditional compilation blocks are indented. If this setting is `false` the body + of `#if`, `#elseif`, and `#else` is not indented. Defaults to `true`. + > TODO: Add support for enabling/disabling specific syntax transformations in > the pipeline. diff --git a/Sources/SwiftFormatConfiguration/Configuration.swift b/Sources/SwiftFormatConfiguration/Configuration.swift index bddd6709..1824b86d 100644 --- a/Sources/SwiftFormatConfiguration/Configuration.swift +++ b/Sources/SwiftFormatConfiguration/Configuration.swift @@ -29,6 +29,7 @@ public class Configuration: Codable { case blankLineBetweenMembers case lineBreakBeforeControlFlowKeywords case lineBreakBeforeEachArgument + case indentConditionalCompilationBlocks case rules } @@ -87,6 +88,9 @@ public class Configuration: Codable { /// each argument, forcing the entire argument list to be laid out vertically. public var lineBreakBeforeEachArgument = false + /// Determines the indentation behavior for `#if`, `#elseif`, and `#else`. + public var indentConditionalCompilationBlocks = true + /// Constructs a Configuration with all default values. public init() { self.version = highestSupportedConfigurationVersion @@ -129,6 +133,8 @@ public class Configuration: Codable { ?? true self.lineBreakBeforeEachArgument = try container.decodeIfPresent(Bool.self, forKey: .lineBreakBeforeEachArgument) ?? true + self.indentConditionalCompilationBlocks + = try container.decodeIfPresent(Bool.self, forKey: .indentConditionalCompilationBlocks) ?? true self.rules = try container.decodeIfPresent([String: Bool].self, forKey: .rules) ?? [:] } @@ -145,6 +151,7 @@ public class Configuration: Codable { try container.encode( lineBreakBeforeControlFlowKeywords, forKey: .lineBreakBeforeControlFlowKeywords) try container.encode(lineBreakBeforeEachArgument, forKey: .lineBreakBeforeEachArgument) + try container.encode(indentConditionalCompilationBlocks, forKey: .indentConditionalCompilationBlocks) try container.encode(rules, forKey: .rules) } } diff --git a/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift b/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift index 4422c8b0..ff084f38 100644 --- a/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift +++ b/Sources/SwiftFormatPrettyPrint/TokenStreamCreator.swift @@ -843,16 +843,26 @@ private final class TokenStreamCreator: SyntaxVisitor { preconditionFailure() } + let breakKindOpen: BreakKind + let breakKindClose: BreakKind + if config.indentConditionalCompilationBlocks { + breakKindOpen = .open + breakKindClose = .close + } else { + breakKindOpen = .same + breakKindClose = .same + } + let tokenToOpenWith = node.condition?.lastToken ?? node.poundKeyword - after(tokenToOpenWith, tokens: .break(.open), .open) + after(tokenToOpenWith, tokens: .break(breakKindOpen), .open) // Unlike other code blocks, where we may want a single statement to be laid out on the same // line as a parent construct, the content of an `#if` block must always be on its own line; // the newline token inserted at the end enforces this. if let lastElemTok = node.elements.lastToken { - after(lastElemTok, tokens: .break(.close), .newline, .close) + after(lastElemTok, tokens: .break(breakKindClose), .newline, .close) } else { - before(tokenToOpenWith.nextToken, tokens: .break(.close), .newline, .close) + before(tokenToOpenWith.nextToken, tokens: .break(breakKindClose), .newline, .close) } return .visitChildren } diff --git a/Tests/SwiftFormatPrettyPrintTests/IfConfigTests.swift b/Tests/SwiftFormatPrettyPrintTests/IfConfigTests.swift index 2af99a02..11dc68ab 100644 --- a/Tests/SwiftFormatPrettyPrintTests/IfConfigTests.swift +++ b/Tests/SwiftFormatPrettyPrintTests/IfConfigTests.swift @@ -1,3 +1,5 @@ +import SwiftFormatConfiguration + public class IfConfigTests: PrettyPrintTestCase { public func testBasicIfConfig() { let input = @@ -56,6 +58,65 @@ public class IfConfigTests: PrettyPrintTestCase { assertPrettyPrintEqual(input: input, expected: expected, linelength: 45) } + public func testIfConfigNoIndentation() { + let input = + """ + #if someCondition + let a = 123 + let b = "abc" + #endif + + #if someCondition + let a = 123 + let b = "abc" + #else + let c = 456 + let d = "def" + #endif + + #if swift(>=4.0) + print("Stuff") + #endif + #if swift(>=4.0) + print("Stuff") + #elseif compiler(>=3.0) + print("More Stuff") + print("Another Line") + #endif + """ + + let expected = + """ + #if someCondition + let a = 123 + let b = "abc" + #endif + + #if someCondition + let a = 123 + let b = "abc" + #else + let c = 456 + let d = "def" + #endif + + #if swift(>=4.0) + print("Stuff") + #endif + #if swift(>=4.0) + print("Stuff") + #elseif compiler(>=3.0) + print("More Stuff") + print("Another Line") + #endif + + """ + + let config = Configuration() + config.indentConditionalCompilationBlocks = false + assertPrettyPrintEqual(input: input, expected: expected, linelength: 45, configuration: config) + } + public func testPoundIfAroundMembers() { let input = """