realm / SwiftLint

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

Check function calling inside functions using `custom_rules` #3500

Open maximbilan opened 3 years ago

maximbilan commented 3 years ago

New Issue Checklist

Describe the bug

I use custom_rule to show warnings for all @IBAction functions which don't call handleActionButton function inside these functions and it doesn't work correctly. In that case, SwiftLint doesn't work correctly.

Here is the custom rule:

custom_rules:
  button_action_tracking:
    name: "Button Action Tracking"
    regex: "@IBAction\\s+func\\s.*\\s(?!.*handleButtonAction)\\s"
    message: "Don't forget to call `handleButtonAction` inside the method"
    severity: warning

Input:

class Test {

    @IBOutlet weak var button1: UIButton!
    @IBOutlet weak var button2: UIButton!
    @IBOutlet weak var button3: UIButton!

    func handleButtonAction(with button: UIButton) {
    }

    @IBAction func button1Tapped() {
        handleButtonAction(with: button2)
    }

    @IBAction func button2Tapped() {
    }

    @IBAction func button3Tapped() {
    }

}

Linting:

$ swiftlint lint --path file1.swift
Loading configuration from '.swiftlint.yml'
Linting Swift files at path file1.swift
Linting 'file.swift' (1/1)
file1.swift:10:5: warning: Button Action Tracking Violation: Don't forget to call `handleButtonAction` inside the method (button_action_tracking)
file1.swift:20:1: warning: Trailing Newline Violation: Files should have a single trailing newline. (trailing_newline)
file1.swift:2:1: warning: Trailing Whitespace Violation: Lines should not have trailing whitespace. (trailing_whitespace)
Done linting! Found 3 violations, 0 serious in 1 file.

However, SwiftLint highlights the first function instead of the second and third.

Expected behavior

https://regex101.com/r/TdkiNC/32

Screen Shot 2021-01-22 at 10 52 43

Environment

excluded:
  - Pods
  - vendor

disabled_rules:
  - line_length
  - identifier_name
  - function_parameter_count

force_cast: warning
force_try: warning
cyclomatic_complexity:
  error: 40
type_body_length:
  error: 1000
function_body_length:
  error: 200
file_length:
  error: 1600

custom_rules:
  button_action_tracking:
    name: "Button Action Tracking"
    regex: "@IBAction\\s+func\\s.*\\s(?!.*handleButtonAction)\\s"
    message: "Don't forget to call `handleButtonAction` inside the method"
    severity: warning
coolbnjmn commented 3 years ago

For what it's worth, this looks related to a couple issues that were never resolved and closed for staleness: https://github.com/realm/SwiftLint/issues/2677 https://github.com/realm/SwiftLint/issues/2040

vladimir-bebeshko commented 3 years ago

are there plans to fix this?

stonko1994 commented 2 years ago

I had a similar issue and after some digging into SwiftLint I found out that the problem is the new-line matching.

When a custom rule is applied, SwiftLint passes the whole content of the file as a single-line to the NSRegularExpression.

See: https://github.com/realm/SwiftLint/blob/2408839be3b312bfbbb81811f2fde29d2d485fac/Source/SwiftLintFramework/Extensions/SwiftLintFile%2BRegex.swift#L107-L110


I made my regex work after changing the regex to also work with a single line input.