From e6192b2c3d92e7d8c9c476acfa808e241900d687 Mon Sep 17 00:00:00 2001 From: gibachan Date: Wed, 21 Jun 2023 21:52:37 +0900 Subject: [PATCH 1/4] Format tree itself instead of its description --- Tests/SwiftBasicFormatTest/BasicFormatTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 26f80e9606a..091d84b31bb 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -351,7 +351,7 @@ final class BasicFormatTest: XCTestCase { let body = decl.cast(FunctionDeclSyntax.self).body! assertFormatted( - source: body.formatted().description, + tree: body, expected: """ { print(1) @@ -372,7 +372,7 @@ final class BasicFormatTest: XCTestCase { let body = decl.cast(StructDeclSyntax.self).memberBlock.members.first!.decl.cast(FunctionDeclSyntax.self).body! assertFormatted( - source: body.formatted().description, + tree: body, expected: """ { print(1) From 1622dc6c0fe21840cfe4245a186b20dec7ab1fe4 Mon Sep 17 00:00:00 2001 From: gibachan Date: Wed, 21 Jun 2023 21:53:08 +0900 Subject: [PATCH 2/4] Respect indentation in the line for sub tree in BasicFormat --- Sources/SwiftBasicFormat/BasicFormat.swift | 22 ++++++++++ .../SwiftBasicFormat/Syntax+Extensions.swift | 40 +++++++++++++++++++ .../MissingNodesError.swift | 2 + .../ParseDiagnosticsGenerator.swift | 25 ------------ .../BasicFormatTests.swift | 2 +- 5 files changed, 65 insertions(+), 26 deletions(-) create mode 100644 Sources/SwiftBasicFormat/Syntax+Extensions.swift diff --git a/Sources/SwiftBasicFormat/BasicFormat.swift b/Sources/SwiftBasicFormat/BasicFormat.swift index 0a297cf9417..592a645605a 100644 --- a/Sources/SwiftBasicFormat/BasicFormat.swift +++ b/Sources/SwiftBasicFormat/BasicFormat.swift @@ -150,6 +150,18 @@ open class BasicFormat: SyntaxRewriter { // MARK: - Customization points + /// If we are formatting a subtree and the line that the initial token occurs on is indented, + /// use that line indentation for the first token in the subtree to format. + /// + /// For example, when formatting only the code block in the following, + /// then the opening `{` should be indented by four spaces. + /// ``` + /// func test() { + /// print(1) + /// } + /// ``` + open var inferInitialTokenIndentaiton: Bool { true } + /// Whether a leading newline on `token` should be added. open func requiresIndent(_ node: some SyntaxProtocol) -> Bool { return node.requiresIndent @@ -413,6 +425,16 @@ open class BasicFormat: SyntaxRewriter { anchorPoints[token] = currentIndentationLevel } + if inferInitialTokenIndentaiton + && isInitialToken + && token.presence == .present + { + let indentationOfLine = token.indentationOfLine + if token.leadingTrivia.pieces.suffix(indentationOfLine.pieces.count) != indentationOfLine.pieces { + leadingTrivia += indentationOfLine + } + } + // Add a trailing space to the token unless // - it already ends with a whitespace or // - the next token will start starts with a newline after the rewrite diff --git a/Sources/SwiftBasicFormat/Syntax+Extensions.swift b/Sources/SwiftBasicFormat/Syntax+Extensions.swift new file mode 100644 index 00000000000..305f7925176 --- /dev/null +++ b/Sources/SwiftBasicFormat/Syntax+Extensions.swift @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2023 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import SwiftSyntax + +public extension TokenSyntax { + /// The indentation of this token + /// + /// In contrast to `indentationOfLine`, this does not walk to previous tokens to + /// find the indentation of the line this token occurs on. + private var indentation: Trivia? { + let previous = self.previousToken(viewMode: .sourceAccurate) + return ((previous?.trailingTrivia ?? []) + leadingTrivia).indentation(isOnNewline: false) + } + + /// Returns the indentation of the line this token occurs on + var indentationOfLine: Trivia { + var token: TokenSyntax = self + if let indentation = token.indentation { + return indentation + } + while let previous = token.previousToken(viewMode: .sourceAccurate) { + token = previous + if let indentation = token.indentation { + return indentation + } + } + + return [] + } +} diff --git a/Sources/SwiftParserDiagnostics/MissingNodesError.swift b/Sources/SwiftParserDiagnostics/MissingNodesError.swift index 5e636859ffb..83a45e825ce 100644 --- a/Sources/SwiftParserDiagnostics/MissingNodesError.swift +++ b/Sources/SwiftParserDiagnostics/MissingNodesError.swift @@ -22,6 +22,8 @@ fileprivate func findCommonAncestor(_ nodes: [Syntax]) -> Syntax? { } class NoNewlinesFormat: BasicFormat { + override var inferInitialTokenIndentaiton: Bool { false } + override func requiresNewline(between first: TokenSyntax?, and second: TokenSyntax?) -> Bool { return false } diff --git a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift index e97226405e0..f408e92c26e 100644 --- a/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift +++ b/Sources/SwiftParserDiagnostics/ParseDiagnosticsGenerator.swift @@ -51,31 +51,6 @@ fileprivate func getTokens(between first: TokenSyntax, and second: TokenSyntax) } fileprivate extension TokenSyntax { - /// The indentation of this token - /// - /// In contrast to `indentation`, this does not walk to previous tokens to - /// find the indentation of the line this token occurs on. - private var indentation: Trivia? { - let previous = self.previousToken(viewMode: .sourceAccurate) - return ((previous?.trailingTrivia ?? []) + leadingTrivia).indentation(isOnNewline: false) - } - - /// Returns the indentation of the line this token occurs on - var indentationOfLine: Trivia { - var token: TokenSyntax = self - if let indentation = token.indentation { - return indentation - } - while let previous = token.previousToken(viewMode: .sourceAccurate) { - token = previous - if let indentation = token.indentation { - return indentation - } - } - - return [] - } - /// Assuming this token is a `poundAvailableKeyword` or `poundUnavailableKeyword` /// returns the opposite keyword. var negatedAvailabilityKeyword: TokenSyntax { diff --git a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift index 091d84b31bb..ea1a8a79d3d 100644 --- a/Tests/SwiftBasicFormatTest/BasicFormatTests.swift +++ b/Tests/SwiftBasicFormatTest/BasicFormatTests.swift @@ -374,7 +374,7 @@ final class BasicFormatTest: XCTestCase { assertFormatted( tree: body, expected: """ - { + { print(1) } """ From 73a21a831be0b4cd8bccb11668c642e51f23bf0a Mon Sep 17 00:00:00 2001 From: gibachan Date: Tue, 11 Jul 2023 20:36:02 +0900 Subject: [PATCH 3/4] Add reference to Syntax+Extensions.swift --- Sources/SwiftBasicFormat/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Sources/SwiftBasicFormat/CMakeLists.txt b/Sources/SwiftBasicFormat/CMakeLists.txt index c83ff4e1db7..75a90fac1a5 100644 --- a/Sources/SwiftBasicFormat/CMakeLists.txt +++ b/Sources/SwiftBasicFormat/CMakeLists.txt @@ -9,6 +9,7 @@ add_swift_host_library(SwiftBasicFormat BasicFormat.swift generated/BasicFormat+Extensions.swift + Syntax+Extensions.swift SyntaxProtocol+Formatted.swift Trivia+FormatExtensions.swift ) From 30bfccdc9097a926e068bd839a4b79efc1e7d277 Mon Sep 17 00:00:00 2001 From: gibachan Date: Tue, 11 Jul 2023 20:48:39 +0900 Subject: [PATCH 4/4] Fix access control --- Sources/SwiftBasicFormat/Syntax+Extensions.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftBasicFormat/Syntax+Extensions.swift b/Sources/SwiftBasicFormat/Syntax+Extensions.swift index 305f7925176..ec48e36a0b0 100644 --- a/Sources/SwiftBasicFormat/Syntax+Extensions.swift +++ b/Sources/SwiftBasicFormat/Syntax+Extensions.swift @@ -12,7 +12,7 @@ import SwiftSyntax -public extension TokenSyntax { +extension TokenSyntax { /// The indentation of this token /// /// In contrast to `indentationOfLine`, this does not walk to previous tokens to @@ -23,7 +23,7 @@ public extension TokenSyntax { } /// Returns the indentation of the line this token occurs on - var indentationOfLine: Trivia { + public var indentationOfLine: Trivia { var token: TokenSyntax = self if let indentation = token.indentation { return indentation