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
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.
But for some of us it lowers the barrier to contributing significantly
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.
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:
• 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.
That is a really nice POC!
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
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.