Allow to set a target syntax version (or use non-current ruby syntax)
I'd like to be able to set the ruby target version via the solargraph config file. My personal use case is that I have an old ruby 2.7 project that I constantly work with, but cannot upgrade to ruby 3. I'd like to continue to be able to use the latest solargraph with this project, but as of 0.53, its not possible.
My proposal is the following:
- Add
ruby_versionto the.solargraph.yml - Not concern solargraph with version detection - though this could be done in a later version
- Not concern solargraph with module resolution - the gems can be installed on the version that solargraph runs under
The only thing that ruby_version would do is just set the parser to parse that version's syntax
Opinions?
(We'd need to load that ruby's internal docs though, so hm)
Makes sense to me! I like that your PR defaults to current behavior of using the running Ruby version, and agreed that being sneakier looking at .ruby-version et al in the workplace could be a later step.
One thing you might consider as a follow-up (forgive me if you've already mentioned this as a direction) - you'll see newly added stdlib and core methods, as the RBS doesn't differentiate. You mentioned that as a concern for your use case. Currently the RBS gem provides as follows:
The Target Version
The standard library signatures targets the latest release of Ruby. (3.2 as of 2023.) The library code targets non-EOL versions of Ruby. (>= 3.0 as of 2023.)
https://github.com/ruby/rbs/?tab=readme-ov-file#the-target-version
So this is a problem for 3.x versions as well. An approach to consider is to use something like the old RDoc parsing code to pull the untyped method signatures, then reject RBS core/stdlib definitions not found. Something akin to what's done in Solargraph::GemPins.combine(): https://github.com/castwide/solargraph/blob/master/lib/solargraph/gem_pins.rb#L48-L74
Hey @apiology & @castwide, I'm continuing to work on this, trying to follow @apiology's idea on merging docs. Please let me know if I am being silly here or not, but I think a cheap & dirty way of doing this is to use some scraping magic & scrape the lists at the bottom-ish of https://ruby-doc.org/core-2.7.1/ to reject RBS pins. The HTML contains all the info needed - a list f instance methods, a list of class methods & a list of classes. Trouble is, it doesn't contain params or return types, but we may be able to rely on RBS for figuring those out? Of course there are some params that change and get added/removed as the language changes (eg. clone's freeze kw arg), but imo its a minor imperfection and this method is rather fast so...
What are your opinions on this approach?
Yep! Using the old info to determine what methods exist, and trimming down the rbs collection information based on it sounds perfect.
We used to pull RDoc for core and stdlib functions, which is a little more intentionally machine-readable - here's the old code I found:
- https://github.com/castwide/solargraph/blob/v0.48.0/lib/solargraph/yard_map.rb#L29-L42
- https://github.com/castwide/solargraph/blob/v0.48.0/lib/solargraph/yard_map.rb#L359-L377
- https://github.com/castwide/solargraph/blob/v0.48.0/lib/solargraph/yard_map/core_docs.rb
- https://github.com/castwide/solargraph/blob/v0.48.0/lib/solargraph/yard_map/rdoc_to_yard.rb
The CoreGen module handled generation of YARD documentation from Ruby source. Solargraph also depended on CoreFills and StdlibFills to add missing documentation.
Another option: if we use the above generated YARD to populate an ApiMap, we should be able to convert it to an RBS file that we can ship with the gem.