From 2b94443b56ace90bde8e89ffc755ebbb3e2719c5 Mon Sep 17 00:00:00 2001 From: Sven Weidauer Date: Wed, 30 Dec 2020 13:35:21 +0100 Subject: [PATCH] SwiftLint --- .swiftlint.yml | 193 ++++++++++++++++++ ....swift => StringProtocol+Extensions.swift} | 0 .../Generators/AndroidGenerator.swift | 7 +- .../Generators/AssetCatalogGenerator.swift | 8 +- .../Generators/HTMLGenerator.swift | 82 +++++--- Sources/LibMakeColors/MakeColors.swift | 21 +- Sources/LibMakeColors/Model/Color.swift | 45 ++-- ...Parser.swift => Scanner+ColorParser.swift} | 46 +++-- Tests/MakeColorsTests/ColorParserTest.swift | 12 +- 9 files changed, 320 insertions(+), 94 deletions(-) create mode 100644 .swiftlint.yml rename Sources/LibMakeColors/Extensions/{String+Extensions.swift => StringProtocol+Extensions.swift} (100%) rename Sources/LibMakeColors/Model/{Parser.swift => Scanner+ColorParser.swift} (93%) diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..ff4d15b --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,193 @@ +excluded: + - .build + +disabled_rules: + - opening_brace + - trailing_comma + +nesting: + type_level: + warning: 3 + error: 6 + +opt_in_rules: + - array_init + - attributes + - block_based_kvo + - class_delegate_protocol + - closing_brace + - closure_body_length + - closure_end_indentation + - closure_parameter_position + - closure_spacing + - collection_alignment + - colon + - comma + - comment_spacing + - compiler_protocol_init + - computed_accessors_order + - contains_over_filter_count + - contains_over_filter_is_empty + - contains_over_first_not_nil + - contains_over_range_nil_comparison + - control_statement + - convenience_type + - custom_rules + - cyclomatic_complexity + - deployment_target + - discarded_notification_center_observer + - discouraged_direct_init + - discouraged_object_literal + - discouraged_optional_boolean + - discouraged_optional_collection + - duplicate_enum_cases + - duplicate_imports + - dynamic_inline + - empty_collection_literal + - empty_count + - empty_enum_arguments + - empty_parameters + - empty_parentheses_with_trailing_closure + - empty_string + - empty_xctest_method + - enum_case_associated_values_count + - expiring_todo + - explicit_init + - explicit_self + - extension_access_modifier + - fallthrough + - fatal_error_message + - file_header + - file_length + - file_name + - file_name_no_space + - first_where + - flatmap_over_map_reduce + - for_where + - force_cast + - force_try + - force_unwrapping + - function_body_length + - function_default_parameter_at_end + - function_parameter_count + - generic_type_name + - identical_operands + - identifier_name + - implicit_getter + - implicit_return + - implicitly_unwrapped_optional + - inclusive_language + - inert_defer + - is_disjoint + - joined_default_parameter + - large_tuple + - last_where + - leading_whitespace + - legacy_cggeometry_functions + - legacy_constant + - legacy_constructor + - legacy_hashing + - legacy_multiple + - legacy_nsgeometry_functions + - legacy_random +# - let_var_whitespace # We actually want this, but it currently gets confused with property wrappers. + - line_length + - literal_expression_end_indentation + - lower_acl_than_parent + - mark + - missing_docs + - modifier_order + - multiline_arguments + - multiline_arguments_brackets + - multiline_function_chains + - multiline_literal_brackets + - multiline_parameters + - multiline_parameters_brackets + - multiple_closures_with_trailing_closure + - nesting + - no_fallthrough_only + - no_grouping_extension + - no_space_in_method_call + - notification_center_detachment + - nslocalizedstring_key + - nslocalizedstring_require_bundle + - nsobject_prefer_isequal + - number_separator + - object_literal + - operator_usage_whitespace + - operator_whitespace + - optional_enum_case_matching + - orphaned_doc_comment + - overridden_super_call + - override_in_extension + - pattern_matching_keywords + - prefer_self_type_over_type_of_self + - prefer_zero_over_explicit_init + - private_action + - private_outlet + - private_over_fileprivate + - private_unit_test + - prohibited_super_call + - protocol_property_accessors_order + - quick_discouraged_call + - quick_discouraged_focused_test + - quick_discouraged_pending_test + - raw_value_for_camel_cased_codable_enum + - reduce_boolean + - reduce_into + - redundant_discardable_let + - redundant_nil_coalescing + - redundant_objc_attribute + - redundant_optional_initialization + - redundant_set_access_control + - redundant_string_enum_value + - redundant_type_annotation + - redundant_void_return + - required_enum_case + - return_arrow_whitespace + - shorthand_operator + - single_test_class + - sorted_first_last + - sorted_imports + - statement_position + - static_operator + - strict_fileprivate + - strong_iboutlet + - superfluous_disable_command + - switch_case_alignment + - switch_case_on_newline + - syntactic_sugar + - test_case_accessibility + - todo + - toggle_bool + - trailing_closure + - trailing_newline + - trailing_semicolon + - trailing_whitespace + - type_body_length + - type_name + - unavailable_function + - unneeded_break_in_switch + - unneeded_parentheses_in_closure_argument + - unowned_variable_capture + - untyped_error_in_catch + - unused_capture_list + - unused_closure_parameter + - unused_control_flow_label + - unused_declaration + - unused_enumerated + - unused_import + - unused_optional_binding + - unused_setter_value + - valid_ibinspectable + - vertical_parameter_alignment + - vertical_parameter_alignment_on_call + - vertical_whitespace + - vertical_whitespace_between_cases + - vertical_whitespace_closing_braces + - vertical_whitespace_opening_braces + - void_return + - weak_delegate + - xct_specific_matcher + - xctfail_message + - yoda_condition diff --git a/Sources/LibMakeColors/Extensions/String+Extensions.swift b/Sources/LibMakeColors/Extensions/StringProtocol+Extensions.swift similarity index 100% rename from Sources/LibMakeColors/Extensions/String+Extensions.swift rename to Sources/LibMakeColors/Extensions/StringProtocol+Extensions.swift diff --git a/Sources/LibMakeColors/Generators/AndroidGenerator.swift b/Sources/LibMakeColors/Generators/AndroidGenerator.swift index e9c309f..cf80010 100644 --- a/Sources/LibMakeColors/Generators/AndroidGenerator.swift +++ b/Sources/LibMakeColors/Generators/AndroidGenerator.swift @@ -23,8 +23,11 @@ final class AndroidGenerator: Generator { let value: String switch color { - case let .color(colorValue): value = colorValue.description - case let .reference(ref): value = "@color/\(prefix)\(ref.camelCasePathToSnakeCase())" + case let .color(colorValue): + value = colorValue.description + + case let .reference(ref): + value = "@color/\(prefix)\(ref.camelCasePathToSnakeCase())" } xml += """ diff --git a/Sources/LibMakeColors/Generators/AssetCatalogGenerator.swift b/Sources/LibMakeColors/Generators/AssetCatalogGenerator.swift index ee277ce..3be34f9 100644 --- a/Sources/LibMakeColors/Generators/AssetCatalogGenerator.swift +++ b/Sources/LibMakeColors/Generators/AssetCatalogGenerator.swift @@ -60,10 +60,10 @@ private extension Color { "color" : { "color-space" : "srgb", "components" : { - "alpha" : "\(Float(a) / 256)", - "blue" : "0x\(String(b, radix: 16))", - "green" : "0x\(String(g, radix: 16))", - "red" : "0x\(String(r, radix: 16))" + "alpha" : "\(Float(alpha) / 256)", + "blue" : "0x\(String(blue, radix: 16))", + "green" : "0x\(String(green, radix: 16))", + "red" : "0x\(String(red, radix: 16))" } }, "idiom" : "universal" diff --git a/Sources/LibMakeColors/Generators/HTMLGenerator.swift b/Sources/LibMakeColors/Generators/HTMLGenerator.swift index 9900f3e..393900c 100644 --- a/Sources/LibMakeColors/Generators/HTMLGenerator.swift +++ b/Sources/LibMakeColors/Generators/HTMLGenerator.swift @@ -2,6 +2,45 @@ import Foundation final class HTMLGenerator: Generator { static let defaultExtension = "html" + + static let head = """ + + + + + + + + + + + + + + + """ + let context: Context init(context: Context) { @@ -9,52 +48,27 @@ final class HTMLGenerator: Generator { } func generate(data: [String: ColorDef]) throws -> FileWrapper { - var html = """ - - - - -
 NameValue
- - - - - - - - - - """ + var html = Self.head for (key, color) in data.sorted() { let actualColor = try data.resolve(key) let value: String switch color { - case let .reference(name): value = """ + case let .reference(name): + value = """ \(name.insertCamelCaseSeparators())
\(actualColor) """ - case .color: value = actualColor.description + + case .color: + value = actualColor.description } html += """ - + diff --git a/Sources/LibMakeColors/MakeColors.swift b/Sources/LibMakeColors/MakeColors.swift index 00bceb1..b125ec4 100644 --- a/Sources/LibMakeColors/MakeColors.swift +++ b/Sources/LibMakeColors/MakeColors.swift @@ -2,18 +2,18 @@ import ArgumentParser import Foundation private struct GeneratorOption: EnumerableFlag, CustomStringConvertible { - let type: Generator.Type - - var description: String { - type.option - } - static let allCases: [GeneratorOption] = [ .init(type: AssetCatalogGenerator.self), .init(type: AndroidGenerator.self), .init(type: HTMLGenerator.self), ] + let type: Generator.Type + + var description: String { + type.option + } + static func == (lhs: GeneratorOption, rhs: GeneratorOption) -> Bool { lhs.type == rhs.type } @@ -53,9 +53,12 @@ public final class MakeColors: ParsableCommand, Context { for (key, color) in data.sorted() { let resolved = try data.resolve(key) switch color { - case .color: print(key.insertCamelCaseSeparators(), resolved, separator: ": ") - case let .reference(r): print( - "\(key.insertCamelCaseSeparators()) (@\(r.insertCamelCaseSeparators()))", + case .color: + print(key.insertCamelCaseSeparators(), resolved, separator: ": ") + + case let .reference(referenced): + print( + "\(key.insertCamelCaseSeparators()) (@\(referenced.insertCamelCaseSeparators()))", resolved, separator: ": " ) diff --git a/Sources/LibMakeColors/Model/Color.swift b/Sources/LibMakeColors/Model/Color.swift index ee08acf..ef2030e 100644 --- a/Sources/LibMakeColors/Model/Color.swift +++ b/Sources/LibMakeColors/Model/Color.swift @@ -1,23 +1,27 @@ struct Color: CustomStringConvertible, Equatable { - let r, g, b, a: UInt8 + let red: UInt8 + let green: UInt8 + let blue: UInt8 + let alpha: UInt8 - init(r: UInt8, g: UInt8, b: UInt8, a: UInt8 = 0xFF) { - self.r = r - self.g = g - self.b = b - self.a = a + init(red: UInt8, green: UInt8, blue: UInt8, alpha: UInt8 = 0xFF) { + self.red = red + self.green = green + self.blue = blue + self.alpha = alpha } - init?(_ array: [UInt8]) { - guard array.count >= 3 else { return nil } - r = array[0] - g = array[1] - b = array[2] - a = array.count >= 4 ? array[3] : 0xFF + init(_ array: [UInt8]) { + precondition(array.count == 3 || array.count == 4) + red = array[0] + green = array[1] + blue = array[2] + alpha = array.count == 4 ? array[3] : 0xFF } var description: String { - a != 0xFF ? String(format: "#%02X%02X%02X%02X", r, g, b, a) : String(format: "#%02X%02X%02X", r, g, b) + let alphaSuffix = alpha != 0xFF ? String(format: "%02X", alpha) : "" + return String(format: "#%02X%02X%02X%@", red, green, blue, alphaSuffix) } } @@ -49,11 +53,16 @@ extension Dictionary where Key == String, Value == ColorDef { sorted(by: Self.compare) } - static func compare(_ a: (String, ColorDef), _ b: (String, ColorDef)) -> Bool { - switch (a, b) { - case ((_, .color), (_, .reference)): return true - case ((_, .reference), (_, .color)): return false - case let ((left, _), (right, _)): return left.localizedStandardCompare(right) == .orderedAscending + static func compare(_ lhs: (String, ColorDef), _ rhs: (String, ColorDef)) -> Bool { + switch (lhs, rhs) { + case ((_, .color), (_, .reference)): + return true + + case ((_, .reference), (_, .color)): + return false + + case let ((left, _), (right, _)): + return left.localizedStandardCompare(right) == .orderedAscending } } } diff --git a/Sources/LibMakeColors/Model/Parser.swift b/Sources/LibMakeColors/Model/Scanner+ColorParser.swift similarity index 93% rename from Sources/LibMakeColors/Model/Parser.swift rename to Sources/LibMakeColors/Model/Scanner+ColorParser.swift index ae1e86e..3d56246 100644 --- a/Sources/LibMakeColors/Model/Parser.swift +++ b/Sources/LibMakeColors/Model/Scanner+ColorParser.swift @@ -1,26 +1,6 @@ import Foundation -private extension CharacterSet { - static let hex = CharacterSet(charactersIn: "0123456789abcdef") - static let name = alphanumerics.union(CharacterSet(charactersIn: "_/")) -} - -private extension Collection { - func chunks(size: Int) -> UnfoldSequence { - sequence(state: startIndex) { state -> SubSequence? in - guard state != endIndex else { return nil } - let next = index(state, offsetBy: size, limitedBy: endIndex) ?? endIndex - defer { state = next } - return self[state.. Bool { - scanString(s) != nil - } - func color() -> Color? { if string("#"), let digits = scanCharacters(from: .hex) { switch digits.count { @@ -34,7 +14,8 @@ extension Scanner { let digits = digits.chunks(size: 2).compactMap { UInt8($0, radix: 16) } return Color(digits) - default: return nil + default: + return nil } } @@ -110,6 +91,7 @@ extension Scanner { return result } + // swiftlint:disable:next discouraged_optional_collection func commaSeparated() -> [UInt8]? { var result: [UInt8] = [] repeat { @@ -121,3 +103,25 @@ extension Scanner { return result } } + +private extension Scanner { + func string(_ string: String) -> Bool { + scanString(string) != nil + } +} + +private extension CharacterSet { + static let hex = CharacterSet(charactersIn: "0123456789abcdef") + static let name = alphanumerics.union(CharacterSet(charactersIn: "_/")) +} + +private extension Collection { + func chunks(size: Int) -> UnfoldSequence { + sequence(state: startIndex) { state -> SubSequence? in + guard state != endIndex else { return nil } + let next = index(state, offsetBy: size, limitedBy: endIndex) ?? endIndex + defer { state = next } + return self[state..
 NameValue
   +   + \(key.insertCamelCaseSeparators()) \(value)