One of the goals of swift-driver is to adopt a library-based architecture for better integration with build tooling. To that end, I've recently been doing some refactoring so that even simple invocations like swift --version are modeled as driver jobs. This means library clients no longer need to worry about the driver spawning processes they cannot control. Instead, a library client which doesn't want to use the built-in job execution functionality can just obtain a list of jobs and run them on its own if it wants to, for example, do something unusual with stdout.
--help doesn't fit into this model today, because the driver is responsible for printing it directly. This isn't an insurmountable issue, we could just move it's handling out of the SwiftDriver library and into the swift-driver binary itself. However, I had an idea after coming across SR-11900, which suggested potentially introducing a swift-help executable which would fit in with existing subcommand handling and support swift help.
In short, I think we should consider adding writing a swift-help in Swift as part of the swift-driver project, and use it to entirely replace help handling in the compiler sooner rather than later. The benefits are:
We'd gain experience integrating a swift package product in compiler toolchains with minimal impact on day-to-day development. Anything we learned could then be applied to swift-driver later on. No bootstrapping would be needed since the help text isn't needed to build the compiler.
swift help becomes a supported subcommand
It solves my immediate problem (admittedly not a strong justification)
We could delete a little bit of C++ from the frontend
The main downside I see is that it seems a little silly to exec another process just to print help info.
I'd be interested in hearing other's opinions!
cc @JhonnyBillM who's been doing some work in this area and @Douglas_Gregor who might have some thoughts on this.
This is an interesting idea. I like how it addresses the problem that SwiftDriver should only produce jobs (not exec anything or directly produce output). Does this bring any benefits to developers using Swift? I mean, swift help would presumably print the same dump of driver options that it does today, but would this be a stepping stone toward something more useful?
Off the top of my head, there’s a few things we could do in this area:
Use, for example swift help RangeReplaceableCollection to access standard library docs. It’s currently hard to access a local copy of these on non-macOS platforms.
It’s still early days, but it could be an alternative way to access diagnostic documentation content (swift help nominal-types)
it might be a good starting point to experiment with localized tooling.
None of these require the functionality is written in Swift, but splitting it from the front end does add some flexibility to experiment without cluttering the C++ driver. Whether it justifies the added build system complexity, I don’t know.
Having quick command-line access to the SourceKit request that grabs the docs for a type/property/function/other decl and prints nicely formatted man-page-like output would be fantastic.
And since the driver could take additional command line flags like framework/import search paths, it seems like it would be straightforward for this to work for any module by default, not just the standard library, as long as you tell it where to find things.
I love the idea of building a CLI for documentation queries, but it doesn't seem like that should be the same command that people use to discover how to use the various swift ___ utilities. Maybe something like swift doc RangeReplaceableCollection and swift doc --module MyModule MyCustomType could provide that functionality?
That was my thought as well. Overloading help to be used in both swift help build and swift help some-build-error and swift help Result would be too much. However, I do think help could be expanded to cover both commands and command output messages, like errors. And I'm always a fan of writing more of the tooling in Swift itself.
That's a valid point, I may have accidentally divided this discussion by recommending documentation integration. It sounds like swift-doc is definitely something people want, whereas the value of a swift-help tool is debatable.
I think swift-doc should be explored independently of swift-driver, probably as it's own package that might depend on some of the sourcekit-lsp infrastructure. If there's enough interest in that maybe I'll set up a repo that could eventually be contributed back to the swift project.
I haven't decided what to do about help-handling yet, but I've at least been convinced I shouldn't try to shoehorn docs into it.
It's pretty rough at the moment, but I had a little time to throw together a prototype of what a swift-doc might look like (repo @ GitHub - owenv/swift-doc: Experimental Swift tool for doc generation via symbol graph dumps). It's powered by the new swift-symbolgraph-extract tool which can read all of the information needed for docs directly from a serialized module. Right now, it's possible to type swift doc RangeReplaceableCollection and get:
[Protocol] RangeReplaceableCollection
• Conforms to Collection
• Conforms to Sequence
======================
A collection that supports replacement of an arbitrary subrange of elements
with the elements of another collection.
...
...
...
The output format of swift-symbolgraph-extract isn't stable yet so this is kind of fragile at the moment, but I think it could eventually be a pretty good solution to the problem of documentation queries.
I wonder, though - could we maybe build this functionality on top of SourceKit-LSP? That project already builds an index for your code (using IndexStoreDB), it knows how to do autocomplete and fuzzy search, integrates with clangd for C/C++/Obj-C support, and may even get support for syntax highlighting in the future (it's not part of LSP right now, though). I suppose it also has a more stable interface than swift-symbolgraph-extract.
I think it makes a whole lot of sense to approach this as a CLI to some editor/SourceKit-LSP functionality. There are other useful actions that could be supported, too - for example, we could implement "Jump to Definition" with a CLI. Perhaps something like swift show MyProtocol could open an editor at the file/line where that symbol is declared.