More error reporting improvements

This commit is contained in:
Nick Lockwood
2017-01-06 19:12:24 +00:00
parent f5b57b2b7a
commit b26f00a63c
3 changed files with 46 additions and 35 deletions
+30 -20
View File
@@ -92,14 +92,15 @@ extension FileHandle: TextOutputStream {
}
}
func printErrors(_ errors: [FormatError]) {
func printWarnings(_ errors: [Error]) {
var stderr = FileHandle.standardError
for error in errors {
print("error: \(error)", to: &stderr)
print("warning: \(error)", to: &stderr)
}
}
func processArguments(_ args: [String]) {
var errors = [Error]()
do {
// Get options
let args = try preprocessArguments(args, commandLineArguments)
@@ -149,15 +150,18 @@ func processArguments(_ args: [String]) {
let time = timeEvent {
(filesParsed, filesChecked, options, errors) = inferOptions(from: inferURL)
}
printErrors(errors)
printWarnings(errors)
if filesParsed == 0 {
throw FormatError.parsing("failed to to infer options")
}
print("options inferred from \(filesParsed)/\(filesChecked) files in \(time)")
print("")
print(commandLineArguments(for: options).map({ "--\($0) \($1)" }).joined(separator: " "))
print("")
return
} else {
throw FormatError.options("--inferoptions argument was not a valid path")
}
return
}
// Get input path(s)
@@ -174,7 +178,6 @@ func processArguments(_ args: [String]) {
// Get cache path
var cacheURL: URL?
var errors = [FormatError]()
let defaultCacheFileName = "swiftformat.cache"
let manager = FileManager.default
func setDefaultCacheURL() {
@@ -185,7 +188,7 @@ func processArguments(_ args: [String]) {
try manager.createDirectory(at: cacheDirectory, withIntermediateDirectories: true, attributes: nil)
cacheURL = cacheDirectory.appendingPathComponent(defaultCacheFileName)
} catch {
errors.append(FormatError.writing("failed to create cache directory at: \(cacheDirectory.path)"))
errors.append(FormatError.writing("failed to create cache directory at \(cacheDirectory.path)"))
}
} else {
errors.append(FormatError.reading("failed to find cache directory at ~/Library/Caches"))
@@ -194,7 +197,7 @@ func processArguments(_ args: [String]) {
if let cache = args["cache"] {
switch cache {
case "":
throw FormatError.options("--cache option expects a value.")
throw FormatError.options("--cache option expects a value")
case "ignore":
break
case "clear":
@@ -203,13 +206,13 @@ func processArguments(_ args: [String]) {
do {
try manager.removeItem(at: cacheURL)
} catch {
errors.append(FormatError.writing("failed to delete cache file at: \(cacheURL.path)"))
errors.append(FormatError.writing("failed to delete cache file at \(cacheURL.path)"))
}
}
default:
cacheURL = expandPath(cache)
guard cacheURL != nil else {
throw FormatError.options("unsupported --cache value: \(cache).")
throw FormatError.options("unsupported --cache value `\(cache)`")
}
var isDirectory: ObjCBool = false
if manager.fileExists(atPath: cacheURL!.path, isDirectory: &isDirectory) && isDirectory.boolValue {
@@ -224,6 +227,7 @@ func processArguments(_ args: [String]) {
if inputURLs.count == 0 {
var input: String?
var finished = false
var fatalError: Error?
DispatchQueue.global(qos: .userInitiated).async {
while let line = readLine(strippingNewline: false) {
input = (input ?? "") + line
@@ -236,16 +240,14 @@ func processArguments(_ args: [String]) {
try output.write(to: outputURL, atomically: true, encoding: String.Encoding.utf8)
print("swiftformat completed successfully")
} catch {
throw FormatError.writing("failed to write file: \(outputURL.path)")
throw FormatError.writing("failed to write file \(outputURL.path)")
}
} else {
// Write to stdout
print(output)
}
} catch let error as FormatError {
errors.append(error)
} catch {
errors.append(FormatError.writing("unknown error: \(error)"))
fatalError = error
}
}
finished = true
@@ -255,8 +257,11 @@ func processArguments(_ args: [String]) {
while start.timeIntervalSinceNow > -0.01 {}
// If no input received by now, assume none is coming
if input != nil {
while !finished && start.timeIntervalSinceNow > -30 {}
printErrors(errors)
while !finished && start.timeIntervalSinceNow > -30 {
if let fatalError = fatalError {
throw fatalError
}
}
} else {
showHelp()
}
@@ -277,15 +282,20 @@ func processArguments(_ args: [String]) {
fileOptions: fileOptions,
cacheURL: cacheURL
)
errors += _errors
errors += _errors as [Error]
}
printWarnings(errors)
if filesChecked == 0 {
let inputPaths = inputURLs.map({ $0.path }).joined(separator: ", ")
throw FormatError.options("no eligible files found at \(inputPaths)")
}
printErrors(errors)
print("swiftformat completed. \(filesWritten)/\(filesChecked) files updated in \(time)")
} catch let error as FormatError {
printErrors([error])
} catch {
printErrors([FormatError.options("unknown error: \(error)")])
printWarnings(errors)
// Fatal error
var stderr = FileHandle.standardError
print("error: \(error)", to: &stderr)
}
}
Binary file not shown.
+16 -15
View File
@@ -91,9 +91,9 @@ public func enumerateSwiftFiles(withInputURL inputURL: URL,
guard let resourceValues = try? inputURL.resourceValues(forKeys: Set(keys)) else {
if manager.fileExists(atPath: inputURL.path) {
onComplete { throw FormatError.reading("failed to read attributes for: \(inputURL.path)") }
onComplete { throw FormatError.reading("failed to read attributes for \(inputURL.path)") }
} else {
onComplete { throw FormatError.reading("file not found: \(inputURL.path)") }
onComplete { throw FormatError.reading("file not found at \(inputURL.path)") }
}
return
}
@@ -104,7 +104,7 @@ public func enumerateSwiftFiles(withInputURL inputURL: URL,
} else if resourceValues.isDirectory == true {
guard let files = try? manager.contentsOfDirectory(
at: inputURL, includingPropertiesForKeys: keys, options: .skipsHiddenFiles) else {
onComplete { throw FormatError.reading("failed to read contents of directory at: \(inputURL.path)") }
onComplete { throw FormatError.reading("failed to read contents of directory at \(inputURL.path)") }
return
}
for url in files {
@@ -200,14 +200,14 @@ func inferOptions(from inputURL: URL) -> (Int, Int, FormatOptions, [FormatError]
guard let input = try? String(contentsOf: inputURL) else {
return {
filesChecked += 1
errors.append(FormatError.reading("failed to read file: \(inputURL.path)"))
errors.append(FormatError.reading("failed to read file \(inputURL.path)"))
}
}
let _tokens = tokenize(input)
if let error = parsingError(for: _tokens), case .parsing(let string) = error {
return {
filesChecked += 1
errors.append(FormatError.parsing("\(string) in file: \(inputURL.path)"))
errors.append(FormatError.parsing("\(string) in \(inputURL.path)"))
}
}
return {
@@ -239,7 +239,11 @@ func processInput(_ inputURLs: [URL],
for inputURL in inputURLs {
guard let resourceValues = try? inputURL.resourceValues(
forKeys: Set([.isDirectoryKey, .isAliasFileKey, .isSymbolicLinkKey])) else {
errors.append(FormatError.reading("failed to read attributes for: \(inputURL.path)"))
if FileManager.default.fileExists(atPath: inputURL.path) {
errors.append(FormatError.reading("failed to read attributes for \(inputURL.path)"))
} else {
errors.append(FormatError.reading("file not found at \(inputURL.path)"))
}
continue
}
if !fileOptions.followSymlinks &&
@@ -256,7 +260,7 @@ func processInput(_ inputURLs: [URL],
guard let input = try? String(contentsOf: inputURL) else {
return {
filesChecked += 1 // TODO: should this count?
throw FormatError.reading("failed to read file: \(inputURL.path)")
throw FormatError.reading("failed to read file \(inputURL.path)")
}
}
let cacheKey: String = {
@@ -282,7 +286,7 @@ func processInput(_ inputURLs: [URL],
} catch {
return {
filesChecked += 1
throw FormatError.writing("failed to create directory at: \(outputURL.path), \(error)")
throw FormatError.writing("failed to create directory at \(outputURL.path), \(error)")
}
}
} else if output == input {
@@ -302,13 +306,13 @@ func processInput(_ inputURLs: [URL],
} catch {
return {
filesChecked += 1
throw FormatError.writing("failed to write file: \(outputURL.path), \(error)")
throw FormatError.writing("failed to write file \(outputURL.path), \(error)")
}
}
} catch FormatError.parsing(let string) {
return {
filesChecked += 1
throw FormatError.parsing("\(string) in file: \(inputURL.path)")
throw FormatError.parsing("\(string) in \(inputURL.path)")
}
} catch {
return {
@@ -318,15 +322,12 @@ func processInput(_ inputURLs: [URL],
}
}
}
if filesChecked == 0 {
let inputPaths = inputURLs.map({ $0.path }).joined(separator: ", ")
errors.append(FormatError.options("no eligible files found at: \(inputPaths)"))
} else {
if filesChecked > 0 {
// Save cache
if let cache = cache, let cacheURL = cacheURL, let cacheDirectory = cacheDirectory {
if !(cache as NSDictionary).write(to: cacheURL, atomically: true) {
if FileManager.default.fileExists(atPath: cacheDirectory.path) {
errors.append(FormatError.writing("failed to write cache file at: \(cacheURL.path)"))
errors.append(FormatError.writing("failed to write cache file at \(cacheURL.path)"))
} else {
errors.append(FormatError.reading("specified cache file directory does not exist: \(cacheDirectory.path)"))
}