From 6256a89e38584c3580f5e00a1ef779bd6d9e358a Mon Sep 17 00:00:00 2001 From: Matthias Zenger <matthias@objecthub.net> Date: Sat, 13 May 2023 00:19:52 +0200 Subject: [PATCH] Make some more protocols public. Refactor error data types. Provide better error descriptions. --- CLFormat.xcodeproj/project.pbxproj | 18 ++- Sources/CLFormat/CLControlError.swift | 66 +++++++++ Sources/CLFormat/CLControlParser.swift | 39 ------ Sources/CLFormat/CLFormat.swift | 12 +- Sources/CLFormat/CLFormatError.swift | 126 ++++++++++++++++++ .../CLFormat/StandardDirectiveSpecifier.swift | 70 ---------- 6 files changed, 212 insertions(+), 119 deletions(-) create mode 100644 Sources/CLFormat/CLControlError.swift create mode 100644 Sources/CLFormat/CLFormatError.swift diff --git a/CLFormat.xcodeproj/project.pbxproj b/CLFormat.xcodeproj/project.pbxproj index 849fa2b..7de90d0 100644 --- a/CLFormat.xcodeproj/project.pbxproj +++ b/CLFormat.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ CC2FF5FB29D8C8F500AD0BC6 /* Optional.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC2FF5FA29D8C8F500AD0BC6 /* Optional.swift */; }; CC4CDDE329E47B8300C5E9C6 /* MarkdownKit in Frameworks */ = {isa = PBXBuildFile; productRef = CC4CDDE229E47B8300C5E9C6 /* MarkdownKit */; }; + CC7D4B722A0EE9BB0066BA94 /* CLControlError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7D4B712A0EE9BB0066BA94 /* CLControlError.swift */; }; + CC7D4B742A0EEB010066BA94 /* CLFormatError.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7D4B732A0EEB010066BA94 /* CLFormatError.swift */; }; CCB5F0F629C1455B00587140 /* CLFormat.docc in Sources */ = {isa = PBXBuildFile; fileRef = CCB5F0F529C1455B00587140 /* CLFormat.docc */; }; CCB5F0FC29C1455B00587140 /* CLFormat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CCB5F0F229C1455B00587140 /* CLFormat.framework */; }; CCB5F10129C1455B00587140 /* CLFormatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB5F10029C1455B00587140 /* CLFormatTests.swift */; }; @@ -61,6 +63,8 @@ CC2FF5FA29D8C8F500AD0BC6 /* Optional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Optional.swift; sourceTree = "<group>"; }; CC7D4AF129E9E5980066BA94 /* DIRECTIVES.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = DIRECTIVES.md; sourceTree = "<group>"; }; CC7D4B6A2A0B73880066BA94 /* CLFormatTool.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = CLFormatTool.entitlements; sourceTree = SOURCE_ROOT; }; + CC7D4B712A0EE9BB0066BA94 /* CLControlError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CLControlError.swift; sourceTree = "<group>"; }; + CC7D4B732A0EEB010066BA94 /* CLFormatError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CLFormatError.swift; sourceTree = "<group>"; }; CCB5F0D029C1148900587140 /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = "<group>"; }; CCB5F0D229C114D300587140 /* Number.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Number.swift; sourceTree = "<group>"; }; CCB5F0D429C114F600587140 /* NumberFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NumberFormat.swift; sourceTree = "<group>"; }; @@ -150,8 +154,10 @@ CCB5F0DA29C1156400587140 /* Modifiers.swift */, CCB5F0DC29C1157C00587140 /* Arguments.swift */, CCB5F0DE29C115A500587140 /* CLControl.swift */, + CC7D4B712A0EE9BB0066BA94 /* CLControlError.swift */, CCB5F0E029C115C400587140 /* CLControlParser.swift */, CCB5F12229C7974B00587140 /* CLFormatConfig.swift */, + CC7D4B732A0EEB010066BA94 /* CLFormatError.swift */, CCB5F0E229C115E600587140 /* StandardDirectiveSpecifier.swift */, CCB5F0E429C1160700587140 /* CLFormat.swift */, CCB5F0F429C1455B00587140 /* CLFormat.h */, @@ -317,11 +323,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + CC7D4B742A0EEB010066BA94 /* CLFormatError.swift in Sources */, CCB5F11329C1475F00587140 /* Currency.swift in Sources */, CCB5F11429C1475F00587140 /* Arguments.swift in Sources */, CCB5F12329C7974B00587140 /* CLFormatConfig.swift in Sources */, CC2FF5FB29D8C8F500AD0BC6 /* Optional.swift in Sources */, CCB5F10C29C1475F00587140 /* Parameters.swift in Sources */, + CC7D4B722A0EE9BB0066BA94 /* CLControlError.swift in Sources */, CCB5F11029C1475F00587140 /* StandardDirectiveSpecifier.swift in Sources */, CCB5F0F629C1455B00587140 /* CLFormat.docc in Sources */, CCB5F10E29C1475F00587140 /* CLControl.swift in Sources */, @@ -417,7 +425,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.6; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; @@ -472,7 +481,8 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 12.6; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; @@ -497,7 +507,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@loader_path/Frameworks", @@ -539,7 +549,7 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_NSHumanReadableCopyright = ""; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = ( "@executable_path/Frameworks", "@loader_path/Frameworks", diff --git a/Sources/CLFormat/CLControlError.swift b/Sources/CLFormat/CLControlError.swift new file mode 100644 index 0000000..3246543 --- /dev/null +++ b/Sources/CLFormat/CLControlError.swift @@ -0,0 +1,66 @@ +// +// CLControlError.swift +// CLFormat +// +// Created by Matthias Zenger on 12/05/2023. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +// + +import Foundation + +/// +/// Enumeration encapsulating all parsing errors for the built-in directive parsers. +/// +public enum CLControlError: LocalizedError, CustomStringConvertible { + case prematureEndOfControl + case duplicateModifier(String) + case malformedParameter + case malformedNumericParameter(String) + case malformedDirectiveSyntax(String, String) + case malformedDirective(String) + case misplacedDirective(String) + case unsupportedDirective(String) + case unknownDirective(String) + + public var description: String { + switch self { + case .prematureEndOfControl: + return "premature end of control" + case .duplicateModifier(let mod): + return "duplicate modifier \(mod)" + case .malformedParameter: + return "malformed parameter" + case .malformedNumericParameter(let param): + return "malformed numeric parameter: \(param)" + case .malformedDirectiveSyntax(let name, let dirs): + return "malformed \(name) syntax \(dirs)" + case .malformedDirective(let dir): + return "malformed directive \(dir)" + case .misplacedDirective(let dir): + return "directive \(dir) in unsupported place" + case .unsupportedDirective(let dir): + return "unsupported directive \(dir)" + case .unknownDirective(let dir): + return "unknown directive \(dir)" + } + } + + public var errorDescription: String? { + return self.description + } + + public var failureReason: String? { + return "syntax error in control string" + } +} diff --git a/Sources/CLFormat/CLControlParser.swift b/Sources/CLFormat/CLControlParser.swift index 1044eb3..840480a 100644 --- a/Sources/CLFormat/CLControlParser.swift +++ b/Sources/CLFormat/CLControlParser.swift @@ -195,42 +195,3 @@ public enum ParseResult { return .exit(Directive(parameters: parameters, modifiers: modifiers, specifier: spec)) } } - -/// -/// Enumeration encapsulating all parsing errors for the built-in directive -/// parsers. -/// -public enum CLControlError: Error, CustomStringConvertible { - case prematureEndOfControl - case duplicateModifier(String) - case malformedParameter - case malformedNumericParameter(String) - case malformedDirectiveSyntax(String, String) - case malformedDirective(String) - case misplacedDirective(String) - case unsupportedDirective(String) - case unknownDirective(String) - - public var description: String { - switch self { - case .prematureEndOfControl: - return "premature end of control" - case .duplicateModifier(let mod): - return "duplicate modifier \(mod)" - case .malformedParameter: - return "malformed parameter" - case .malformedNumericParameter(let param): - return "malformed numeric parameter: \(param)" - case .malformedDirectiveSyntax(let name, let dirs): - return "malformed \(name) syntax \(dirs)" - case .malformedDirective(let dir): - return "malformed directive \(dir)" - case .misplacedDirective(let dir): - return "directive \(dir) in unsupported place" - case .unsupportedDirective(let dir): - return "unsupported directive \(dir)" - case .unknownDirective(let dir): - return "unknown directive \(dir)" - } - } -} diff --git a/Sources/CLFormat/CLFormat.swift b/Sources/CLFormat/CLFormat.swift index 173ba37..1a99922 100644 --- a/Sources/CLFormat/CLFormat.swift +++ b/Sources/CLFormat/CLFormat.swift @@ -20,16 +20,16 @@ import Foundation -protocol CLFormatConvertible { +public protocol CLFormatConvertible { var clformatDescription: String { get } } -protocol DebugCLFormatConvertible { +public protocol DebugCLFormatConvertible { var clformatDebugDescription: String { get } } extension Array: CLFormatConvertible where Element: CLFormatConvertible { - var clformatDescription: String { + public var clformatDescription: String { var res = "[" var sep = "" for element in self { @@ -41,7 +41,7 @@ extension Array: CLFormatConvertible where Element: CLFormatConvertible { } extension Array: DebugCLFormatConvertible where Element: DebugCLFormatConvertible { - var clformatDebugDescription: String { + public var clformatDebugDescription: String { var res = "[" var sep = "" for element in self { @@ -53,7 +53,7 @@ extension Array: DebugCLFormatConvertible where Element: DebugCLFormatConvertibl } extension Optional: CLFormatConvertible, DebugCLFormatConvertible { - var clformatDescription: String { + public var clformatDescription: String { switch self { case .none: return "nil" @@ -68,7 +68,7 @@ extension Optional: CLFormatConvertible, DebugCLFormatConvertible { } } - var clformatDebugDescription: String { + public var clformatDebugDescription: String { switch self { case .none: return "nil" diff --git a/Sources/CLFormat/CLFormatError.swift b/Sources/CLFormat/CLFormatError.swift new file mode 100644 index 0000000..47e7f82 --- /dev/null +++ b/Sources/CLFormat/CLFormatError.swift @@ -0,0 +1,126 @@ +// +// CLFormatError.swift +// CLFormat +// +// Created by Matthias Zenger on 12/05/2023. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +// implied. See the License for the specific language governing +// permissions and limitations under the License. +// + +import Foundation + +/// +/// Enumeration encapsulating all formatting errors for the built-in directives. +/// +public enum CLFormatError: LocalizedError, CustomStringConvertible { + case malformedDirective(String) + case unsupportedDirective(String) + case argumentOutOfRange(Int, Int) + case missingArgument + case expectedNumberArgument(Int, Any) + case expectedSequenceArgument(Int, Any) + case cannotUseArgumentAsParameter(Int, Any) + case missingNumberParameter(Int) + case expectedNumberParameter(Int, Any?) + case expectedPositiveNumberParameter(Int, Any?) + case missingCharacterParameter(Int) + case expectedCharacterParameter(Int, Any?) + case missingSequenceParameter(Int) + case expectedSequenceParameter(Int, Any?) + case cannotRepresentNumber(Number, Int) + + public var description: String { + switch self { + case .malformedDirective(let dir): + return "malformed directive \(dir) in control string" + case .unsupportedDirective(let dir): + return "unsupported directive \(dir) in control string" + case .argumentOutOfRange(let i, let n): + return "cannot access argument \(i); only \(n) arguments in total" + case .missingArgument: + return "missing argument" + case .expectedNumberArgument(let n, let arg): + return "expected argument \(n) to be a number; instead it is \(arg)" + case .expectedSequenceArgument(let n, let arg): + return "expected argument \(n) to be a sequence; instead it is \(arg)" + case .cannotUseArgumentAsParameter(let n, let arg): + return "cannot use argument \(n) as parameter: \(arg)" + case .missingNumberParameter(let n): + return "missing number parameter \(n)" + case .expectedNumberParameter(let n, let param): + if let param = param { + return "expected parameter \(n) to be a number, instead it is \(param)" + } else { + return "expected parameter \(n) to be a number, instead it is nil" + } + case .expectedPositiveNumberParameter(let n, let param): + if let param = param { + return "expected parameter \(n) to be a non-negative number, instead it is \(param)" + } else { + return "expected parameter \(n) to be a non-negative number, instead it is nil" + } + case .missingCharacterParameter(let n): + return "missing character parameter \(n)" + case .expectedCharacterParameter(let n, let param): + if let param = param { + return "expected parameter \(n) to be a character, instead it is \(param)" + } else { + return "expected parameter \(n) to be a character, instead it is nil" + } + case .missingSequenceParameter(let n): + return "missing sequence parameter \(n)" + case .expectedSequenceParameter(let n, let param): + if let param = param { + return "expected parameter \(n) to be a sequence, instead it is \(param)" + } else { + return "expected parameter \(n) to be a sequence, instead it is nil" + } + case .cannotRepresentNumber(let num, let radix): + return "cannot represent \(num) with radix \(radix)" + } + } + + public var errorDescription: String? { + return self.description + } + + public var failureReason: String? { + switch self { + case .malformedDirective(_): + return "illegal combination of directive parameters" + case .unsupportedDirective(_): + return "implementation limitation" + case .argumentOutOfRange(_, _): + return "illegal argument" + case .missingArgument: + return "too few arguments" + case .expectedNumberArgument(_, _): + return "argument is expected to be a number" + case .expectedSequenceArgument(_, _): + return "argument is expected to be a sequence" + case .cannotUseArgumentAsParameter(_, _): + return "illegal argument" + case .missingNumberParameter(_), + .missingCharacterParameter(_), + .missingSequenceParameter(_): + return "missing parameter" + case .expectedNumberParameter(_, _), + .expectedPositiveNumberParameter(_, _), + .expectedCharacterParameter(_, _), + .expectedSequenceParameter(_, _): + return "wrong parameter type" + case .cannotRepresentNumber(_, _): + return "illegal radix" + } + } +} diff --git a/Sources/CLFormat/StandardDirectiveSpecifier.swift b/Sources/CLFormat/StandardDirectiveSpecifier.swift index 37299a3..5964cf1 100644 --- a/Sources/CLFormat/StandardDirectiveSpecifier.swift +++ b/Sources/CLFormat/StandardDirectiveSpecifier.swift @@ -828,73 +828,3 @@ public enum StandardDirectiveSpecifier: DirectiveSpecifier { } } } - -public enum CLFormatError: Error, CustomStringConvertible { - case malformedDirective(String) - case unsupportedDirective(String) - case argumentOutOfRange(Int, Int) - case missingArgument - case expectedNumberArgument(Int, Any) - case expectedSequenceArgument(Int, Any) - case cannotUseArgumentAsParameter(Int, Any) - case missingNumberParameter(Int) - case expectedNumberParameter(Int, Any?) - case expectedPositiveNumberParameter(Int, Any?) - case missingCharacterParameter(Int) - case expectedCharacterParameter(Int, Any?) - case missingSequenceParameter(Int) - case expectedSequenceParameter(Int, Any?) - case cannotRepresentNumber(Number, Int) - - public var description: String { - switch self { - case .malformedDirective(let dir): - return "malformed directive \(dir) in control string" - case .unsupportedDirective(let dir): - return "unsupported directive \(dir) in control string" - case .argumentOutOfRange(let i, let n): - return "cannot access argument \(i); only \(n) arguments in total" - case .missingArgument: - return "missing argument" - case .expectedNumberArgument(let n, let arg): - return "expected argument \(n) to be a number; instead it is \(arg)" - case .expectedSequenceArgument(let n, let arg): - return "expected argument \(n) to be a sequence; instead it is \(arg)" - case .cannotUseArgumentAsParameter(let n, let arg): - return "cannot use argument \(n) as parameter: \(arg)" - case .missingNumberParameter(let n): - return "missing number parameter \(n)" - case .expectedNumberParameter(let n, let param): - if let param = param { - return "expected parameter \(n) to be a number, instead it is \(param)" - } else { - return "expected parameter \(n) to be a number, instead it is nil" - } - case .expectedPositiveNumberParameter(let n, let param): - if let param = param { - return "expected parameter \(n) to be a non-negative number, instead it is \(param)" - } else { - return "expected parameter \(n) to be a non-negative number, instead it is nil" - } - case .missingCharacterParameter(let n): - return "missing character parameter \(n)" - case .expectedCharacterParameter(let n, let param): - if let param = param { - return "expected parameter \(n) to be a character, instead it is \(param)" - } else { - return "expected parameter \(n) to be a character, instead it is nil" - } - case .missingSequenceParameter(let n): - return "missing sequence parameter \(n)" - case .expectedSequenceParameter(let n, let param): - if let param = param { - return "expected parameter \(n) to be a sequence, instead it is \(param)" - } else { - return "expected parameter \(n) to be a sequence, instead it is nil" - } - case .cannotRepresentNumber(let num, let radix): - return "cannot represent \(num) with radix \(radix)" - } - } -} -