-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
unused_import produces false positive when only operators from a module are used #2737
Comments
Yeah, we're aware of this but haven't been able to come up with any workarounds. Can you think of a way to identify when operators are used from a given module? |
What's interesting is that by querying a {
"key.annotated_decl": "<Declaration>static func + (lhs: <Type usr=\"s:Sq\">Optional</Type><<Type usr=\"s:s4Voida\">Void</Type>>, rhs: <Type usr=\"s:Sq\">Optional</Type><<Type usr=\"s:s4Voida\">Void</Type>>)</Declaration>",
"key.containertypeusr": "$Ss4VoidaSgmD",
"key.fully_annotated_decl": "<decl.function.operator.infix><syntaxtype.keyword>static</syntaxtype.keyword> <syntaxtype.keyword>func</syntaxtype.keyword> <decl.name>+ </decl.name>(<decl.var.parameter><decl.var.parameter.name>lhs</decl.var.parameter.name>: <decl.var.parameter.type><ref.enum usr=\"s:Sq\">Optional</ref.enum><<ref.typealias usr=\"s:s4Voida\">Void</ref.typealias>></decl.var.parameter.type></decl.var.parameter>, <decl.var.parameter><decl.var.parameter.name>rhs</decl.var.parameter.name>: <decl.var.parameter.type><ref.enum usr=\"s:Sq\">Optional</ref.enum><<ref.typealias usr=\"s:s4Voida\">Void</ref.typealias>></decl.var.parameter.type></decl.var.parameter>)</decl.function.operator.infix>",
"key.groupname": "Optional",
"key.kind": "source.lang.swift.ref.function.operator.infix",
"key.modulename": "Extensions",
"key.name": "+(_:_:)",
"key.related_decls": [
{
"key.annotated_decl": "<RelatedName usr=\"s:SF1poiyxx_xtFZ\">+ (_: Self, _: Self) -> Self</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sf1poiyS2f_SftFZ\">+ (_: Float, _: Float) -> Float</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sd1poiyS2d_SdtFZ\">+ (_: Double, _: Double) -> Double</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s7Float80V1poiyA2B_ABtFZ\">+ (_: Float80, _: Float80) -> Float80</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sj1poiyxx_xtFZ\">+ (_: Self, _: Self) -> Self</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:SjsE1popyxxFZ\">+(_:)</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sz1poiyxx_xtFZ\">+ (_: Self, _: Self) -> Self</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s5UInt8V1poiyA2B_ABtFZ\">+ (_: UInt8, _: UInt8) -> UInt8</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s4Int8V1poiyA2B_ABtFZ\">+ (_: Int8, _: Int8) -> Int8</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s6UInt16V1poiyA2B_ABtFZ\">+ (_: UInt16, _: UInt16) -> UInt16</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s5Int16V1poiyA2B_ABtFZ\">+ (_: Int16, _: Int16) -> Int16</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s6UInt32V1poiyA2B_ABtFZ\">+ (_: UInt32, _: UInt32) -> UInt32</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s5Int32V1poiyA2B_ABtFZ\">+ (_: Int32, _: Int32) -> Int32</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s6UInt64V1poiyA2B_ABtFZ\">+ (_: UInt64, _: UInt64) -> UInt64</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:s5Int64V1poiyA2B_ABtFZ\">+ (_: Int64, _: Int64) -> Int64</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Su1poiyS2u_SutFZ\">+ (_: UInt, _: UInt) -> UInt</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Si1poiyS2i_SitFZ\">+ (_: Int, _: Int) -> Int</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:SmsE1poiyxx_qd__tSTRd__7ElementQyd__ABRtzlFZ\">+ <Other>(_: Self, _: Other) -> Self where Other : Sequence, Self.Element == Other.Element</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:SmsE1poiyxqd___xtSTRd__7ElementQyd__ABRtzlFZ\">+ <Other>(_: Other, _: Self) -> Self where Other : Sequence, Self.Element == Other.Element</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:SmsE1poiyxx_qd__tSmRd__7ElementQyd__ABRtzlFZ\">+ <Other>(_: Self, _: Other) -> Self where Other : RangeReplaceableCollection, Self.Element == Other.Element</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sxss8_PointerRzrlE1poiyxx_6StrideSxQztFZ\">+ (_: Self, _: Self.Stride) -> Self</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:Sxss8_PointerRzrlE1poiyx6StrideSxQz_xtFZ\">+ (_: Self.Stride, _: Self) -> Self</RelatedName>"
},
{
"key.annotated_decl": "<RelatedName usr=\"s:SS1poiyS2S_SStFZ\">+ (_: String, _: String) -> String</RelatedName>"
}
],
"key.typename": "<Wrapped> (Optional<Wrapped>.Type) -> (Optional<Wrapped>, Optional<Wrapped>) -> ()",
"key.typeusr": "$SyyxSg_AAtcD",
"key.usr": "s:Sq10ExtensionsE1poiyyxSg_ACtFZ"
} but the token for the operator is missing in the |
Nice find! 👏 I'm not sure if I'd consider this a SourceKit bug, since it seems like it may be omitting this by design. However, maybe we can find a way to get the operators used in a given file, maybe using |
This seems like it might be a viable solution! |
Thanks so much for looking into this @Biboran! |
…perators are invoked
…perators are invoked
…e module are used (#2840) As was discussed #2737, I utilized the `indexsource` request to look up the operators and fetch the cursorInfo per operator. In the implementation I refrained from using `usr` to look up the operator because SourceKit [doesn't support](https://github.com/apple/swift/blob/5add16804272b4df917da15c46eb6f28d826d656/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp#L1799) fetching cursorInfo by `usr` when it comes from C (but it can still be fetched by offset). I also made [an alternative implementation](master...biboran:fix-unused-imports-for-operators-alternative) which uses the `indexsource` request instead of the `editor.open`. It seems to work with the unit tests but I am not 100% sure it doesn't introduce a regression since there is no oss-check for analyzer rules. I also updated [the example](https://github.com/biboran/synthax-bug-example) to better reflect the original issue in case you want to test the changes manually
Fixed in #2840 🎉 |
New Issue Checklist
Describe the bug
UnusedImportRule
produces a false positive result when a file that imports a certain module uses only the operators defined by the imported module.It seems that the
File.synthaxMap
property doesn't contain the operators and thus thecursorInfo
for the operator is never queried.Environment
I made an example repo which reproduces the bug. Here is how to run it.
Build the library and invoke swiftlint:
xcodebuild -project ./synthax-bug.xcodeproj -scheme synthax-bug-Package > xcodebuild.log swiftlint analyze ./Sources/MainLib/MainLib.swift --compiler-log-path ./xcodebuild.log
A warning of unused import should appear even though the
MainLib
uses an overload of a + operator. Using any other function from theExtensions
module dismisses the violation.The text was updated successfully, but these errors were encountered: