Skip to content

Commit

Permalink
Fix ignore-unparsable-files flag so that it works.
Browse files Browse the repository at this point in the history
The flag was broken after SwiftSyntax switched how it represents unsupported syntax nodes, from Unknown* type nodes to Missing* nodes. Now the tool exits early whenever there are parsing diagnostics, and `--ignore-unparsable-files` disables emitting those diagnostics. Regardless of the flag's value, the formatter won't try to operate on a file with any parsing diagnostics.
  • Loading branch information
dylansturg committed Oct 12, 2022
1 parent a8e6e6f commit 49f8ee3
Show file tree
Hide file tree
Showing 9 changed files with 29 additions and 133 deletions.
8 changes: 0 additions & 8 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,6 @@ let package = Package(
]
),

.testTarget(
name: "SwiftFormatTests",
dependencies: [
"SwiftFormat",
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax"),
]
),
.testTarget(
name: "SwiftFormatConfigurationTests",
dependencies: ["SwiftFormatConfiguration"]
Expand Down
6 changes: 5 additions & 1 deletion Sources/SwiftFormat/Parsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ func parseAndEmitDiagnostics(
let sourceFile =
try operatorTable.foldAll(Parser.parse(source: source)) { _ in }.as(SourceFileSyntax.self)!

let diagnostics = ParseDiagnosticsGenerator.diagnostics(for: sourceFile)
if let parsingDiagnosticHandler = parsingDiagnosticHandler {
let expectedConverter =
SourceLocationConverter(file: url?.path ?? "<unknown>", tree: sourceFile)
let diagnostics = ParseDiagnosticsGenerator.diagnostics(for: sourceFile)
for diagnostic in diagnostics {
let location = diagnostic.location(converter: expectedConverter)
parsingDiagnosticHandler(diagnostic, location)
}
}

guard diagnostics.isEmpty else {
throw SwiftFormatError.fileContainsInvalidSyntax
}

return sourceFile
}
2 changes: 1 addition & 1 deletion Sources/SwiftFormat/SwiftFormatError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ public enum SwiftFormatError: Error {
case isDirectory

/// The file contains invalid or unrecognized Swift syntax and cannot be handled safely.
case fileContainsInvalidSyntax(position: AbsolutePosition)
case fileContainsInvalidSyntax
}
4 changes: 0 additions & 4 deletions Sources/SwiftFormat/SwiftFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,6 @@ public final class SwiftFormatter {
syntax: SourceFileSyntax, operatorTable: OperatorTable,
assumingFileURL url: URL?, source: String?, to outputStream: inout Output
) throws {
if let position = _firstInvalidSyntaxPosition(in: Syntax(syntax)) {
throw SwiftFormatError.fileContainsInvalidSyntax(position: position)
}

let assumedURL = url ?? URL(fileURLWithPath: "source")
let context = Context(
configuration: configuration, operatorTable: operatorTable, findingConsumer: findingConsumer,
Expand Down
4 changes: 0 additions & 4 deletions Sources/SwiftFormat/SwiftLinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,6 @@ public final class SwiftLinter {
assumingFileURL url: URL,
source: String?
) throws {
if let position = _firstInvalidSyntaxPosition(in: Syntax(syntax)) {
throw SwiftFormatError.fileContainsInvalidSyntax(position: position)
}

let context = Context(
configuration: configuration, operatorTable: operatorTable, findingConsumer: findingConsumer,
fileURL: url, sourceFileSyntax: syntax, source: source, ruleNameCache: ruleNameCache)
Expand Down
75 changes: 0 additions & 75 deletions Sources/SwiftFormat/SyntaxValidatingVisitor.swift

This file was deleted.

18 changes: 12 additions & 6 deletions Sources/swift-format/Frontend/FormatFrontend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

import Foundation
import SwiftDiagnostics
import SwiftFormat
import SwiftFormatConfiguration
import SwiftSyntax
Expand Down Expand Up @@ -39,6 +40,13 @@ class FormatFrontend: Frontend {
return
}

let diagnosticHandler: (Diagnostic, SourceLocation) -> () = { (diagnostic, location) in
guard !self.lintFormatOptions.ignoreUnparsableFiles else {
// No diagnostics should be emitted in this mode.
return
}
self.diagnosticsEngine.consumeParserDiagnostic(diagnostic, location)
}
var stdoutStream = FileHandleTextOutputStream(FileHandle.standardOutput)
do {
if inPlace {
Expand All @@ -47,7 +55,7 @@ class FormatFrontend: Frontend {
source: source,
assumingFileURL: url,
to: &buffer,
parsingDiagnosticHandler: diagnosticsEngine.consumeParserDiagnostic)
parsingDiagnosticHandler: diagnosticHandler)

if buffer != source {
let bufferData = buffer.data(using: .utf8)! // Conversion to UTF-8 cannot fail
Expand All @@ -58,13 +66,13 @@ class FormatFrontend: Frontend {
source: source,
assumingFileURL: url,
to: &stdoutStream,
parsingDiagnosticHandler: diagnosticsEngine.consumeParserDiagnostic)
parsingDiagnosticHandler: diagnosticHandler)
}
} catch SwiftFormatError.fileNotReadable {
diagnosticsEngine.emitError(
"Unable to format \(url.relativePath): file is not readable or does not exist.")
return
} catch SwiftFormatError.fileContainsInvalidSyntax(let position) {
} catch SwiftFormatError.fileContainsInvalidSyntax {
guard !lintFormatOptions.ignoreUnparsableFiles else {
guard !inPlace else {
// For in-place mode, nothing is expected to stdout and the file shouldn't be modified.
Expand All @@ -73,9 +81,7 @@ class FormatFrontend: Frontend {
stdoutStream.write(source)
return
}
let location = SourceLocationConverter(file: url.path, source: source).location(for: position)
diagnosticsEngine.emitError(
"file contains invalid or unrecognized Swift syntax.", location: location)
// Otherwise, relevant diagnostics about the problematic nodes have been emitted.
return
} catch {
diagnosticsEngine.emitError("Unable to format \(url.relativePath): \(error)")
Expand Down
17 changes: 11 additions & 6 deletions Sources/swift-format/Frontend/LintFrontend.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

import Foundation
import SwiftDiagnostics
import SwiftFormat
import SwiftFormatConfiguration
import SwiftSyntax
Expand All @@ -32,20 +33,24 @@ class LintFrontend: Frontend {
do {
try linter.lint(
source: source,
assumingFileURL: url,
parsingDiagnosticHandler: diagnosticsEngine.consumeParserDiagnostic)
assumingFileURL: url) { (diagnostic, location) in
guard !self.lintFormatOptions.ignoreUnparsableFiles else {
// No diagnostics should be emitted in this mode.
return
}
self.diagnosticsEngine.consumeParserDiagnostic(diagnostic, location)
}

} catch SwiftFormatError.fileNotReadable {
diagnosticsEngine.emitError(
"Unable to lint \(url.relativePath): file is not readable or does not exist.")
return
} catch SwiftFormatError.fileContainsInvalidSyntax(let position) {
} catch SwiftFormatError.fileContainsInvalidSyntax {
guard !lintFormatOptions.ignoreUnparsableFiles else {
// The caller wants to silently ignore this error.
return
}
let location = SourceLocationConverter(file: url.path, source: source).location(for: position)
diagnosticsEngine.emitError(
"file contains invalid or unrecognized Swift syntax.", location: location)
// Otherwise, relevant diagnostics about the problematic nodes have been emitted.
return
} catch {
diagnosticsEngine.emitError("Unable to lint \(url.relativePath): \(error)")
Expand Down
28 changes: 0 additions & 28 deletions Tests/SwiftFormatTests/SyntaxValidatingVisitorTests.swift

This file was deleted.

0 comments on commit 49f8ee3

Please sign in to comment.