CHGenerator/WebsiteGenerator/Generic/ErrorOutput.swift
Christoph Hagen 2e6542225f Improve error printing
Improve path printing

Update comment
2022-08-25 00:11:24 +02:00

154 lines
4.9 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
final class ErrorOutput {
private enum LogLevel: String {
case error = "ERROR"
case warning = "WARNING"
case info = "INFO"
}
init() {
}
private func add(_ type: LogLevel, item: ContentError) {
let errorText: String
if let err = item.error {
errorText = ", Error: \(err.localizedDescription)"
} else {
errorText = ""
}
print("[\(type.rawValue)] \(item.reason), Source: \(item.source)\(errorText)")
}
func add(error: ContentError) {
add(.error, item: error)
}
func add(error reason: String, source: String, error: Error? = nil) {
add(error: .init(reason: reason, source: source, error: error))
}
func add(warning: ContentError) {
add(.warning, item: warning)
}
func add(warning reason: String, source: String, error: Error? = nil) {
add(warning: .init(reason: reason, source: source, error: error))
}
func add(info: ContentError) {
add(.info, item: info)
}
func add(info reason: String, source: String, error: Error? = nil) {
add(info: .init(reason: reason, source: source, error: error))
}
@discardableResult
func unused<T, R>(_ value: Optional<T>, _ name: String, source: String) -> Optional<R> {
if value != nil {
add(info: "Unused property '\(name)'", source: source)
}
return nil
}
func unknown(property: String, source: String) {
add(info: "Unknown property '\(property)'", source: source)
}
func required<T>(_ value: Optional<T>, name: String, source: String) -> Optional<T> {
guard let value = value else {
add(error: "Missing property '\(name)'", source: source)
return nil
}
return value
}
func unexpected<T>(_ value: Optional<T>, name: String, source: String) -> Optional<T> {
if let value = value {
add(error: "Unexpected property '\(name)' = '\(value)'", source: source)
return nil
}
return nil
}
func missing(_ file: String, requiredBy source: String) {
print("[ERROR] Missing file '\(file)' required by \(source)")
}
func failedToOpen(_ file: String, requiredBy source: String, error: Error?) {
print("[ERROR] Failed to open file '\(file)' required by \(source): \(error?.localizedDescription ?? "No error provided")")
}
func state(_ raw: String?, source: String) -> PageState {
guard let raw = raw else {
return .standard
}
guard let state = PageState(rawValue: raw) else {
add(warning: "Invalid 'state' '\(raw)', using 'standard'", source: source)
return .standard
}
return state
}
func thumbnailStyle(_ raw: String?, source: String) -> ThumbnailStyle {
guard let raw = raw else {
return .large
}
guard let style = ThumbnailStyle(rawValue: raw) else {
add(warning: "Invalid 'thumbnailStyle' '\(raw)', using 'large'", source: source)
return .large
}
return style
}
func linkPreviewThumbnail(customFile: String?, for language: String, in folder: URL, source: String) -> String? {
if let customFile = customFile {
#warning("Allow absolute urls for link preview thumbnails")
let customFileUrl = folder.appendingPathComponent(customFile)
guard customFileUrl.exists else {
missing(customFile, requiredBy: "property 'linkPreviewImage' in metadata of \(source)")
return nil
}
return customFile
}
guard let thumbnail = Element.findThumbnail(for: language, in: folder) else {
// Link preview images are not necessarily required
return nil
}
return thumbnail
}
func moreLinkText(_ elementText: String?, parent parentText: String?, source: String) -> String {
if let elementText = elementText {
return elementText
}
let standard = Element.LocalizedMetadata.moreLinkDefaultText
guard let parentText = parentText, parentText != standard else {
add(error: "Missing property 'moreLinkText'", source: source)
return standard
}
return parentText
}
func date(from string: String?, property: String, source: String) -> Date? {
guard let string = string else {
return nil
}
guard let date = ErrorOutput.metadataDate.date(from: string) else {
add(warning: "Invalid date string '\(string)' for property '\(property)'", source: source)
return nil
}
return date
}
private static let metadataDate: DateFormatter = {
let df = DateFormatter()
df.dateFormat = "dd.MM.yy"
return df
}()
}