realm / SwiftLint

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

Support Xcode Fix-Its #27

Open soffes opened 9 years ago

soffes commented 9 years ago

Not sure if you can provide fix its, but that would be super cool. For some rules (i.e. whitespace only on a line) it would be pretty easy to figure out what to change. Obviously for stuff like as! you shouldn't suggest one.

aarondaub commented 9 years ago

Related: #5

soffes commented 9 years ago

Closing dupe. Sorry.

aarondaub commented 9 years ago

@soffes I actually don't think this is necessarily a dupe as it's a subset. It might make sense to implement this and not #5.

jpsim commented 9 years ago

You're right, not a dupe! Do you happen to know if Xcode exposes an API to provide fix-its?

So far, we've been able to avoid making an Xcode plugin and I'd love to continue that in the future :smile:

soffes commented 9 years ago

Not sure. Hopefully there's a way without it :)

segiddins commented 9 years ago

Pretty sure the fix-it's come from the errors/warnings themselves (I.e. The text)

jpsim commented 9 years ago

@segiddins do you know what the format should be to suggest a fix-it to Xcode?

julien-c commented 9 years ago

It would be very useful even if it's just a cli command for now: swiftlint fix

jpsim commented 9 years ago

@julien-c I think you're confusing "Xcode Fix-Its" (this issue), with #5 (the ability to automatically correct violations).

jpsim commented 9 years ago

More info on Xcode Fix-Its can be found in Apple's documentation: https://developer.apple.com/library/ios/recipes/xcode_help-source_editor/chapters/Fix-it.html

segiddins commented 9 years ago

According to people on the dev tools team, there's no public way to add new fix-its

jpsim commented 9 years ago

Then the private way it will be!

masters3d commented 8 years ago

@segiddins what is the private way to add fix-it?

The new xcode 8 extensions are interesting but probably not applicable here. Using and Extending the Xcode Source Editor at min20 they start talking about extensions

jpsim commented 8 years ago

what is the private way to add fix-it?

Xcode Plugins, and no, Xcode Source Extensions don't expose a way to do that, so this would have to be done in an Alcatraz-style Xcode plugin.

SDGGiesbrecht commented 7 years ago

I’ve tried to get this to work in my own project to no avail.

It is easy enough to output the same syntax as swift build (roughly the same as Clang). The problem is that Xcode ignores them in “run script” build phases.

If you add a “run script” build phase with...

swift build

...none of the errors will have fix‐its, even where the build log has defined them.

Note: By “Fix‐It”, I mean the ability to click on the yellow triangle for a suggestion and the ability to do “Fix All in Scope” or ⌃⌥⌘F.

If anyone knows of a way of tricking Xcode into running a shell script within a “compile sources” build phase, I think that would get us most of the way toward a solution.

jpsim commented 7 years ago

If anyone knows of a way of tricking Xcode into running a shell script within a “compile sources” build phase, I think that would get us most of the way toward a solution.

I think you could set up an external build system target and have that as a target dependency to your current target.

image

image

image

SDGGiesbrecht commented 7 years ago

I think you could set up an external build system target...

@jpsim, it was a great idea. Unfortunately when I tried it (with swift build) there were still no fix‐its, just plain errors. Xcode apparently does not parse the output of external build targets for fix‐its either.

masters3d commented 7 years ago

Sounds like the swift compiler generates the fixits? https://www.mail-archive.com/swift-evolution@swift.org/msg23204.html

"FYI, this fixit is entirely generated by the swift compiler, not Xcode. The swift compiler is fully open source and generally welcomes well formed patches.

-Chris"

SDGGiesbrecht commented 7 years ago

FYI, this fixit is entirely generated by the swift compiler, not Xcode.

@masters3d, yes, the Swift compiler defines the locations and replacements of the fix‐its. The output of swift build (visible in the Xcode build log) contains entries like this:

/Users/JohnDoe/Project/Sources/Module/File.swift:2:9: warning: initialization of immutable value 'x' was never used; consider replacing with assignment to '_' or removing it
    let x = 0
    ~~~~^
    _

The ^ marks the location (as well as the line and column :2:9), the ~s mark the replacement range, and the _ is the suggested replacement.

The problem is that Xcode is responsible for actually implementing the fix‐it with clickable yellow triangles and ⌃⌥⌘F.

When Xcode runs swift during a “compile sources” phase, it parses the output looking for fix‐its and implements them. However, when the same swift command is run...

...Xcode parses the output looking for errors but does not try looking for fix‐its, effectively ignoring all but the first line of the example above.

That is why mimicking the fix‐its produced by swift, would probably work within a “compile sources” phase, but would be ignored by Xcode anywhere else.


I thought of replacing the swift executable with a custom executable that does its own thing and then calls the real swift. It would probably work, but that kind of hack has a nefarious feel to it.

jpsim commented 7 years ago

I thought of replacing the swift executable with a custom executable that does its own thing and then calls the real swift. It would probably work, but that kind of hack has a nefarious feel to it.

Was going to say this too. Not too nefarious (actually very similar to how swiftenv works), and certainly not as messy as Xcode plugins of yore.

jpsim commented 7 years ago

It might actually be possible to render fix-its from external build phases: https://clang.llvm.org/docs/UsersManual.html#cmdoption-fdiagnostics-parseable-fixits

I'm not sure because I haven't been able to get anything in that format or variations thereof to display in Xcode.

SDGGiesbrecht commented 7 years ago

It might actually be possible to render fix-its from external build phases [...]

Probably the easiest test is to have something that generates fix‐its when Xcode builds it in a normal build phase (using clang). Then add an external build phase that tells clang to do the same thing. That will tell us whether Xcode is even listening for them.

The same test failed for me when I was trying it with swift instead of clang.

@jpsim, thanks for thinking more about it. Keep us posted if you make any progress.

kastiglione commented 4 years ago

Hello old issue,

I thought of replacing the swift executable with a custom executable that does its own thing and then calls the real swift. It would probably work, but that kind of hack has a nefarious feel to it.

You can do this in a less invasive way by setting SWIFT_EXEC in the build settings. You could create a wrapper script that calls both swiftc and calls swiftlint.

To make this work, swiftlint would need two features:

  1. Generate parseable output, see Swift's docs/DriverParseableOutput.rst
  2. Generate a diagnostics file (.dia), and include that path in the parseable output

I'm not sure where the diagnostic file format is documented.

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had any recent activity. Please comment to prevent this issue from being closed. Thank you for your contributions!

sethfri commented 2 years ago

I haven't found docs yet for the .dia file format, but here's the code in Clang responsible for reading .dia files. Should be able to reverse engineer from this worst case:

https://clang.llvm.org/doxygen/SerializedDiagnosticReader_8cpp_source.html

sethfri commented 2 years ago

And here's the code responsible for writing .dia files, which might be more helpful:

https://clang.llvm.org/doxygen/SerializedDiagnosticPrinter_8cpp_source.html