realm / SwiftLint

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

[unused_declaration] Unused class/struct is not detected if it conforms to a protocol in extension #5550

Closed vakhidbetrakhmadov closed 2 months ago

vakhidbetrakhmadov commented 2 months ago

New Issue Checklist

Describe the bug

When a class/struct is not used anywhere but has conformance to a protocol in extension, it's not detected as unused by unused_declaration analyzer rule, while when conformance to a protocol is in declaration, it is detected as unused.

Complete output when running SwiftLint, including the stack trace and command used
# // Foo.swift
#
# protocol Foo {}

# // FooImpl.swift
# 
# final class FooImpl {}
#
# extension FooImpl: Foo {}

$ mint run realm/SwiftLint@0.54.0 analyze --compiler-log-path outputs/xcodebuild.log

Analyzing Swift files in current working directory
Collecting 'FooImpl.swift' (1/2)
Collecting 'Foo.swift' (2/2)
Analyzing 'FooImpl.swift' (1/2)
Analyzing 'Foo.swift' (2/2)
Done analyzing! Found 0 violations, 0 serious in 2 files.

# // Goo.swift
#
# protocol Goo {}

# // GooImpl.swift
# 
# final class GooImpl: Goo {}

$ mint run realm/SwiftLint@0.54.0 analyze --compiler-log-path outputs/xcodebuild.log

Analyzing Swift files in current working directory
Collecting 'Goo.swift' (1/2)
Collecting 'GooImpl.swift' (2/2)
Analyzing 'Goo.swift' (1/2)
Analyzing 'GooImpl.swift' (2/2)
/Users/vakhid.betrakhmadov/Developer/swift-compilation-database/Sources/ModuleA/GooImpl.swift:1:13: error: Unused Declaration Violation: Declarations should be referenced at least once within all files linted (unused_declaration)
Done analyzing! Found 1 violation, 1 serious in 2 files.
make: *** [swiftlint] Error 2

Environment

0.54.0

Homebrew, mint

analyzer_rules:
  - unused_declaration

unused_declaration:
  include_public_and_open: false

No

Xcode 15.2 Build version 15C500b

https://github.com/vakhidbetrakhmadov/swift-compilation-database

$ make swiftlint

rm -rf Example.xcodeproj
rm -rf outputs
mkdir outputs
mint run yonaskolb/XcodeGen@2.40.1
⚙️  Generating plists...
⚙️  Generating project...
⚙️  Writing project...
Created project at /Users/vakhid.betrakhmadov/Developer/swift-compilation-database/Example.xcodeproj
xcodebuild \
                -project Example.xcodeproj \
                -scheme "ModuleA" \
                -destination generic/platform=MacOS \
                clean build \
                > outputs/xcodebuild.log
mint run realm/SwiftLint@0.54.0 analyze --compiler-log-path outputs/xcodebuild.log
Analyzing Swift files in current working directory
Collecting 'FooImpl.swift' (1/4)
Collecting 'Goo.swift' (2/4)
Collecting 'Foo.swift' (3/4)
Collecting 'GooImpl.swift' (4/4)
Analyzing 'FooImpl.swift' (1/4)
Analyzing 'Goo.swift' (2/4)
Analyzing 'Foo.swift' (3/4)
Analyzing 'GooImpl.swift' (4/4)
/Users/vakhid.betrakhmadov/Developer/swift-compilation-database/Sources/ModuleA/GooImpl.swift:1:13: error: Unused Declaration Violation: Declarations should be referenced at least once within all files linted (unused_declaration)
Done analyzing! Found 1 violation, 1 serious in 4 files.
make: *** [swiftlint] Error 2

This sample project demonstrates how a class/struct that is not used anywhere but has conformance to a protocol in extension is not detected as unused by unused_declaration analyzer rule (FooImpl), while a class/struct that is not used anywhere but conforms to a protocol in its declaration is (GooImpl).