$ swiftlint autocorrect --path Foo.swift
Correcting Swift files at path Foo.swift
Correcting 'Foo.swift' (1/1)
Foo.swift:4:21 Corrected Colon
Foo.swift:4:21 Corrected Colon
Done correcting 1 files!
swiftlint version
to be sure)? 0.25.0 does not find anything to autocorrect (due to #2050), however anything after dddb0f6 shows the issuewhitelist_rules:
- colon
xcode-select -p
)? 9.2class Foo {
#if false
#else
let bar = ["key" : "value"]
#endif
}
autocorrect
$ swiftlint autocorrect --path Foo.swift
Correcting Swift files at path Foo.swift
Correcting 'Foo.swift' (1/1)
Foo.swift:4:21 Corrected Colon
Foo.swift:4:21 Corrected Colon
Done correcting 1 files!
The duplicate correction ends up truncating the dictionary such that it doesn't compile. The amount of truncation is always equal to the number of extra spaces between the end of the key and the colon.
class Foo {
#if false
#else
let bar = ["key": lue"]
#endif
}
The issue is only reproducible with a dictionary literal, replacing the 4th line with
let bar : String = ""
or
func bar(arg : String) {}
works as expected.
Removing the preprocessor macros entirely also fixes the issue, but this isn't possible in the real world case that uncovered this bug.
As best I can tell SourceKitten is getting confused by the preprocessor macros but only in the dictionary literal case. Examining file.structure
in ColonRule.correctionRanges(in:)
shows two identical entries, which causes swiftlint to emit two corrections at the same location.
structure output
{
"key.diagnostic_stage" : "source.diagnostic.stage.swift.parse",
"key.length" : 84,
"key.offset" : 0,
"key.substructure" : [
{
"key.accessibility" : "source.lang.swift.accessibility.internal",
"key.bodylength" : 70,
"key.bodyoffset" : 11,
"key.kind" : "source.lang.swift.decl.class",
"key.length" : 82,
"key.name" : "Foo",
"key.namelength" : 3,
"key.nameoffset" : 6,
"key.offset" : 0,
"key.runtime_name" : "_TtC8__main__3Foo",
"key.substructure" : [
{
"key.accessibility" : "source.lang.swift.accessibility.internal",
"key.kind" : "source.lang.swift.decl.var.instance",
"key.length" : 29,
"key.name" : "bar",
"key.namelength" : 3,
"key.nameoffset" : 44,
"key.offset" : 40
},
{
"key.bodylength" : 17,
"key.bodyoffset" : 51,
"key.elements" : [
{
"key.kind" : "source.lang.swift.structure.elem.expr",
"key.length" : 5,
"key.offset" : 51
},
{
"key.kind" : "source.lang.swift.structure.elem.expr",
"key.length" : 7,
"key.offset" : 61
}
],
"key.kind" : "source.lang.swift.expr.dictionary",
"key.length" : 19,
"key.namelength" : 0,
"key.nameoffset" : 0,
"key.offset" : 50
},
{
"key.accessibility" : "source.lang.swift.accessibility.internal",
"key.kind" : "source.lang.swift.decl.var.instance",
"key.length" : 29,
"key.name" : "bar",
"key.namelength" : 3,
"key.nameoffset" : 44,
"key.offset" : 40
},
{
"key.bodylength" : 17,
"key.bodyoffset" : 51,
"key.elements" : [
{
"key.kind" : "source.lang.swift.structure.elem.expr",
"key.length" : 5,
"key.offset" : 51
},
{
"key.kind" : "source.lang.swift.structure.elem.expr",
"key.length" : 7,
"key.offset" : 61
}
],
"key.kind" : "source.lang.swift.expr.dictionary",
"key.length" : 19,
"key.namelength" : 0,
"key.nameoffset" : 0,
"key.offset" : 50
}
]
}
]
}
@jszumski It looks like we can workaround this by uniquing the violations before correcting.
But SourceKit shouldn't return two identical entries as well. Can you please file a bug in Swift's JIRA?
Actually, this looks fixed already on Swift 4.1, so no need to file a bug 馃挴
Thanks for the quick turn around!