realm / SwiftLint

A tool to enforce Swift style and conventions.
https://realm.github.io/SwiftLint
MIT License
18.68k stars 2.22k forks source link

optional_data_string_conversion throws error #5845

Open HHuckebein opened 1 week ago

HHuckebein commented 1 week ago

New Issue Checklist

Bug Description

When using the code below, SwiftLint 0.57.0 reports an error like this Optional Data -> String Conversion Violation: Prefer failable String(data:encoding:) initializer when converting Data to String (optional_data_string_conversion)

but following the advice leads to Value of optional type 'String?' must be unwrapped to a value of type 'String'.

// This triggers a violation:
    var description: String {
        do {
            let data = try encode()
            return String(decoding: data, as: UTF8.self)
        } catch {
            return error.message.description
        }
    }

Mention the command or other SwiftLint integration method that caused the issue. Include stack traces or command output.

None

Environment

disabled_rules:

opt_in_rules:
- collection_alignment
#- conditional_returns_on_newline
- convenience_type
- empty_count
- empty_string
- fallthrough
- fatal_error_message
- file_header
- file_name
- file_name_no_space
- first_where
- flatmap_over_map_reduce
- for_where
- force_unwrapping
- identical_operands
- implicit_return
- implicitly_unwrapped_optional
- is_disjoint
- joined_default_parameter
- legacy_multiple
- legacy_random
- last_where
- lower_acl_than_parent
- modifier_order
- multiline_parameters
- overridden_super_call
- prefixed_toplevel_constant
- prefer_zero_over_explicit_init
- private_action
- private_outlet
- static_operator
- strict_fileprivate
- toggle_bool
#- trailing_closure
- unavailable_function
- unowned_variable_capture
- unneeded_parentheses_in_closure_argument
- untyped_error_in_catch
- yoda_condition

analyzer_rules:
- unused_declaration
- unused_import

excluded: # paths to ignore during linting.
- Frameworks
- Products
- Recovered References
- Carthage
- packages/*/Package.swift
- Packages/*/Package.swift

- packages/*/Tests/
- Packages/*/Tests/

# Default rule configuration
cyclomatic_complexity:
    ignores_case_statements: true

empty_count:
    only_after_dot: true

function_parameter_count: 6

function_body_length: 80

identifier_name:
    allowed_symbols: _ # Is used for private property definitions
    max_length: 50

    excluded:
        - id
        - at
        - on
        - to
        - cc
        - i
        - ok
        - no
        - qa
        - ID
        - xl
        - d1
        - d2
        - tr
        - vc
        - up
        - by

large_tuple: # warn user when using 4 values in tuple, give error if there are 5
- 3

line_length: 200

nesting:
    type_level: 3

type_body_length: 270

type_name:
    max_length: 60
    excluded:
    - AX
    - LS

# Opt-in rule configuration
file_name:
 excluded:
 - "BundleConfig_Root.swift"
 - "BundleConfig_Root+Extension.swift"
 - "BundleConfig_Insurance.swift"
 - "BundleConfig_Insurance+Extension.swift"

file_header:
 required_pattern: |
                    \/\/
                    \/\/ Copyright \(c\) *******\. All rights reserved\.
                    \/\/

Are you using nested configurations? If so, paste their relative paths and respective contents.

SimplyDanny commented 1 week ago

That's the idea of the rule. It asks you to use the failable initializer to make you think about the error case. Your current code will just fail at runtime in case data cannot be converted.

HHuckebein commented 1 week ago

The object created by try encode() is non-optional and String(decoding: data, as: UTF8.self) is a non-failing initializer.

SimplyDanny commented 2 days ago

String(decoding: data, as: UTF8.self)

String(decoding: data, as: UTF8.self) may panic at runtime if data cannot be represented as UTF-8.