castwide / solargraph

A Ruby language server.
https://solargraph.org
MIT License
1.89k stars 159 forks source link

Rails support #87

Open philevans opened 6 years ago

philevans commented 6 years ago

I know Rails support is only partial at the moment, but I have installed the Solargraph gem, and am using the VSCode extension, and when I am in a Rails application, I am not getting any Rails-related completions/suggestions whatsoever.

I don't even get a suggestion for the "Rails" class. I just want to make sure I am not getting the wrong end of the stick in terms of what amount of Rails support Solargraph actually has? Solargraph itself is working fine - I am getting standard Ruby suggestions no problem.

castwide commented 6 years ago

There are a couple of things you can try.

  1. Make sure you have gem documentation installed by running yard gems.

  2. Add a .solargraph.yml file to the app's root directory (you can generate a default one by running solargraph config) and make the following change to the require section:

    require:
    - actioncable
    - actionmailer
    - actionpack
    - actionview
    - activejob
    - activemodel
    - activerecord
    - activestorage
    - activesupport

That should get you closer, but it's still far from perfect. Improving Rails support has been on the roadmap for a while. The amount of runtime magic involved makes it challenging, but I have some updates in the works that should help.

andersennl commented 5 years ago

I hope it's fine if I add my thoughts here. First of all, thanks for your work! I've found this thread after noticing that Solargraph wouldn't know how to handle a goto definition click on has_many :users, where I'd expect it to open the User class. I'm not sure how much runtime magic is involved here but having this would be a big improvement.

tvallois commented 5 years ago

Hi, any news on this?

Is there any dedicated branch for Rails where we could help you to implement it?

castwide commented 5 years ago

Solargraph's YARD support is at a point where some of the missing Rails intellisense can be filled with a small @!parse directive. I created a gist for it here: https://gist.github.com/castwide/28b349566a223dfb439a337aea29713e

I'm looking for ways to improve it, including ways to make it easy to install and maintain. Any suggestions are welcome.

mathieushopify commented 5 years ago

@castwide Using the gist above, it works well in many cases... thank you! However, in the 'activesupport' gem, there is a method blank? which is not getting picked up... is there a workaround? (.gem/ruby/2.5.3/gems/activesupport-5.2.2.1/lib/active_support/core_ext/object/blank.rb)

castwide commented 5 years ago

@mathieushopify It works in circumstances where a type can be inferred:

obj = Object.new
obj.b # <= suggests blank?

str = 'str'
str.b # <= suggests blank?

If those don't work, make sure you have the latest gem version (0.33.0 was released this morning) and run yard gems to make sure they're documented.

Completion won't work on on unknown types, which is unfortunately the status of most of the Rails API; for example, completion will suggest ApplicationRecord.find, but doesn't know what type find returns, so it won't make any suggestions for methods chained to it.

mathieushopify commented 5 years ago

Makes sense, thanks for the prompt reply! :-)

dgutov commented 5 years ago

@castwide Don't most types inherit from Object, though?

Although the lack of completions it can be a useful indicator that the type is in not inferred. "Some completions" is not always better than "no completions".

castwide commented 5 years ago

@dgutov Yeah, my personal preference is for undefined types to return no completions instead of assuming Object. It's less ambiguous about whether a type was detected.

If anyone finds it more useful to assume Object for untagged methods, we might be able to make it a configuration option.

castwide commented 5 years ago

Version 0.34.0 introduces some new features that should add some improvements to Rails support.

Quick Start

  1. Install the latest Solargraph gem.
  2. Run solargraph bundle from your Rails app's root directory.
  3. Add the most recent version of this file: https://gist.github.com/castwide/28b349566a223dfb439a337aea29713e

How It Works

Known Issues

minkir014 commented 5 years ago

When you intend to fix this issue?

Using go-to-definition on a symbol with custom documentation should open the correct file, but it always goes to the first line. (Go-to-definition on other gems still works correctly.)

I think it should go to the correct line.

mathieushopify commented 5 years ago

@castwide thanks for the update!

dirksierd commented 5 years ago

Great stuff! Thanks!

minkir014 commented 5 years ago

@castwide can you tell me that if that was an ordinary work or it have an issue??

castwide commented 5 years ago

@minkir014 I'm sorry, I don't know what you mean.

castwide commented 5 years ago

Gem 0.34.1 fixes some issues that occurred in certain bundler environments.

minkir014 commented 5 years ago

As I know about go to definition that it must go to a certain line that the class or any other thing is defined and you said

Using go-to-definition on a symbol with custom documentation should open the correct file, but it always goes to the first line. (Go-to-definition on other gems still works correctly.)

That means that some gems have problems with go to definition. So, when do you intend to fix this issue???

castwide commented 5 years ago

@minkir014 I don't know when it will be fixed because I don't even know what the root cause is. When the RdocToYard component generates an RDoc store, all the code objects have nil line numbers.

minkir014 commented 5 years ago

You could file an issue against RdocToYard gem. It maybe a problem with it.

tvallois commented 5 years ago

Is there a way to manage models values with Solargraph? E.g for the User model, to have autocompletion on user.id, user.created_at, etc...

castwide commented 5 years ago

@tvallois I'm working on a Rails convention that should be able to map model attributes from the database schema.

Right now the only other option is to document them yourself, e.g., with the @!attribute directive:

class User < ActiveRecord::Base
  # @!attribute id
  #   @return [Integer]
  # @!attribute name
  #   @return [String]
end
Zeko369 commented 5 years ago

@castwide Hey, I was thinking of building a script that uses annotations built by annotate gem to add types to models. You said that you're working on something similar? Have you pushed any code towards that? I would like to help and start building it myself if you haven't :man_technologist:

# == Schema Information
#
# Table name: groups
#
#  id           :bigint(8)        not null, primary key
#  name         :string
#  created_at   :datetime         not null
#  updated_at   :datetime         not null
#  namespace_id :bigint(8)        indexed
#

class Group < ApplicationRecord
  # @!attribute id
  #   @return [Integer]
  # @!attribute name
  #   @return [String]
  # @!attribute created_at
  #   @return [Date]
  # @!attribute updated_at
  #   @return [Date]
  # @!attribute namespace_id
  #   @return [Integer]

  ...
end
castwide commented 5 years ago

@Zeko369 I don't have anything substantial. If you can build something, that would be awesome. I'm not sure how integration will work yet, but we can worry about those details after we have a working implementation.

Samsinite commented 5 years ago

@Zeko369 I would be happy to collaborate on this as well.

tvallois commented 4 years ago

hi @castwide , I'm working on an implementation to generate yard documentation for models with annotate_models gem however when i have an attribute like:

# @!attribute generating
#   @return [TrueClass]
#   @return [FalseClass]

Solargraph only return TrueClass on the autocompletion. Is it a bug or normal behavior?

castwide commented 4 years ago

That's a known limitation. When you have multiple return tags, it should report all the types, but right now it only processes the first one. It works correctly if you add multiple types to a single tag, e.g., @return [TrueClass, FalseClass]. Support for multiple tags is on the roadmap. It's been a low priority, but it shouldn't be difficult.

In this case, you might prefer to use @return [Boolean] instead. It's not a real class, but YARD conveniently understands it.

romu70 commented 4 years ago
2\. solargraph bundle

Sorry for this really newbie question, but where is located the rails.rbfile? I'm trying to diagnose why I always have the message

Starting the Solargraph language server

Thanks.

Zeko369 commented 4 years ago

@romu70 Create a rails.rb file in the root of your project add do something like this https://gist.github.com/castwide/28b349566a223dfb439a337aea29713e

romu70 commented 4 years ago

Thanks @Zeko369 . Is this normal all the text in this file is commented out?

castwide commented 4 years ago

Having all the text commented is normal, yes. It uses YARD directives to augment the API maps without affecting real code.

The rails.rb file should be a temporary solution while we hammer out the details for proper Rails support. Eventually I'd like to have a plugin that automatically fills the gaps in the Rails API, similar to how the Solargraph core provides overrides for the Ruby stdlib and a "convention" for Gemfiles.

romu70 commented 4 years ago

Ok thanks. I restarted my VSCode, but I'm still getting the permanent message "Starting the Solargraph language server"

taylorthurlow commented 4 years ago

Ok thanks. I restarted my VSCode, but I'm still getting the permanent message "Starting the Solargraph language server"

Try running solargraph stdio to start a server in your console, rather than vscode starting it for you. It should be easier to debug any issues it has starting that way.

castwide commented 4 years ago

@romu70 A few other things to help you troubleshoot:

  1. Make sure you're using the latest version of Solargraph (currently v0.38.5)
  2. Check if you have any errors in the developer console (Help -> Toggle Developer Tools)
  3. Run solargraph scan -v to check for problems mapping your project (https://solargraph.org/guides/scanning-workspaces)
romu70 commented 4 years ago

Thanks for the help.

  1. I run 0.38.5
  2. In the dev tools, I get 5 warnings about the syntax grammar overrides, and one error related to Ruby (not sure if it is related to Solargraph tough):

Error: Unable to read file (EntryNotFound (FileSystemError): Error: ENOENT: no such file or directory, open '/Users/romu/.vscode/extensions/rebornix.ruby-0.26.0/language-configuration-ruby.json')

  1. solargraph scan -vprocessed 27727 pins in 16.6 seconds (approx).
castwide commented 4 years ago

That error comes from the main Ruby extension. Their repo has an issue for it.

Since the scan seems okay, you might be encountering a bug in starting or connecting to the language server. If the problem persists, please start a new issue for it, and I'll try to help you continue troubleshooting.

romu70 commented 4 years ago

I tried to get this file and put it into the rebornix folder shown in the error message.

Now, no more error.

Screenshot 2020-02-11 at 20 33 14

And it seems to work correctly.

Screenshot 2020-02-11 at 20 36 18

Even if, I've still the message in the status bar.

Screenshot 2020-02-11 at 20 36 54

So I do confirm the problem was the language-configuration-ruby.json file was missing.

qortex commented 4 years ago

Is there a known way to gracefully handle has_many-like constructs?

I currently use:

# @!attribute members
#   @return [ActiveRecord::Associations::CollectionProxy]
has_many :members,
         through: :organizations_users,
         source: :user

But really what would be awesome would be something like ActiveRecord::Associations::CollectionProxy<Users::User>, like an array. So that accesses to the elements have type information.

immerrr commented 4 years ago

Seeing a bit of a strange behaviour here with Solargraph 0.39.8. I have a pretty standard application_record.rb file:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

When I try to find definition of ActiveRecord::Base, solargraph finds the active_record/base.rb file, but does not navigate to the ActiveRecord::Base class itself.

I'm also not seeing model magic methods, like where and so on, even though I have the tweaks from https://gist.github.com/castwide/28b349566a223dfb439a337aea29713e under config/solargraph.rb.

Could these two things be related?

castwide commented 4 years ago

@immerrr

  1. There's a known issue with the custom documentation generated for Rails gems. The first step is to build RDoc documentation, and for some reason this process drops line numbers. I'm working on a fix, but can't provide an ETA yet.
  2. Is the config directory (or, at least, the config/solargraph.rb file) included in your .solargraph.yml configuration?
immerrr commented 4 years ago

re: 2: solargraph.yml is the default one, that includes

include:
- "**/*.rb"

I suppose that means config/solargraph.rb should be included. Any way I can confirm that with more certainty?

castwide commented 4 years ago

I suppose that means config/solargraph.rb should be included. Any way I can confirm that with more certainty?

@immerrr Hmm, that's a good candidate for an enhancement. One workaround is to add a line like Class CanYouSeeMe; end to it and see if CanYouSeeMe is a completion suggestion in other files.

Have you tried running solargraph bundle from your project's root?

hellola commented 4 years ago

I commented this on the wrong issue, hopefully nobody gets spammed. I've also been struggling getting the ActiveRecord to work well with solargraph. I'm not sure if I'm missing anything crucial. I've followed all the rails related help I could find. I made a small generator using activerecord reflections, here is the gist It just generates classes with yard / solargraph comments in them. @Zeko369 @tvallois @qortex @castwide

castwide commented 4 years ago

@immerrr Update on the line number issue. There's a fix in the master branch that will be included in the next patch release.

castwide commented 4 years ago

The fix for line numbers is released in v0.39.9. You might need to run solargraph bundle --rebuild to regenerate cached documentation.

immerrr commented 4 years ago

Just tried that out, failed with NoMethodError:

$ solargraph bundle --rebuild
Documenting rake 13.0.1
Documenting concurrent-ruby 1.1.6
Documenting aasm 4.12.3
Documenting i18n 1.8.2
Documenting minitest 5.10.3
Documenting thread_safe 0.3.6
Documenting tzinfo 1.2.7
Documenting activesupport 5.0.7.2
Caching custom documentation for activesupport 5.0.7.2
Traceback (most recent call last):
    20: from /home/immerrr/.rvm/gems/ruby-2.5.8/bin/ruby_executable_hooks:24:in `<main>'
    19: from /home/immerrr/.rvm/gems/ruby-2.5.8/bin/ruby_executable_hooks:24:in `eval'
    18: from /home/immerrr/.rvm/gems/ruby-2.5.8/bin/solargraph:23:in `<main>'
    17: from /home/immerrr/.rvm/gems/ruby-2.5.8/bin/solargraph:23:in `load'
    16: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/bin/solargraph:5:in `<top (required)>'
    15: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/thor-1.0.1/lib/thor/base.rb:485:in `start'
    14: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'
    13: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'
    12: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'
    11: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/shell.rb:193:in `bundle'
    10: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/documentor.rb:26:in `document'
     9: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/documentor.rb:26:in `each_pair'
     8: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/documentor.rb:44:in `block in document'
     7: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:17:in `run'
     6: from /home/immerrr/.rvm/rubies/ruby-2.5.8/lib/ruby/2.5.0/tmpdir.rb:93:in `mktmpdir'
     5: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:20:in `block in run'
     4: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:20:in `chdir'
     3: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:34:in `block (2 levels) in run'
     2: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:34:in `each'
     1: from /home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:41:in `block (3 levels) in run'
/home/immerrr/.rvm/gems/ruby-2.5.8/gems/solargraph-0.39.9/lib/solargraph/yard_map/rdoc_to_yard.rb:112:in `commentary': undefined method `parts' for #<String:0x0000000004d19cd8> (NoMethodError)
castwide commented 4 years ago

Just tried that out, failed with NoMethodError:

That's weird. I'm sure I've never seen that attribute be a String before.

Fixed and released in v0.39.10.

ferdaber commented 4 years ago

Adding the gist seems to crash solargraph when running solargraph scan. It seems to be failing at the parse directive (removing it solves the issue), although it could be affecting any directive:

bundle exec solargraph scan
Traceback (most recent call last):
        25: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/bin/ruby_executable_hooks:24:in `<main>'
        24: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/bin/ruby_executable_hooks:24:in `eval'
        23: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/bin/solargraph:23:in `<main>'
        22: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/bin/solargraph:23:in `load'
        21: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/bin/solargraph:5:in `<top (required)>'
        20: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/thor-1.0.1/lib/thor/base.rb:485:in `start'
        19: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/thor-1.0.1/lib/thor.rb:392:in `dispatch'
        18: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/thor-1.0.1/lib/thor/invocation.rb:127:in `invoke_command'
        17: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/thor-1.0.1/lib/thor/command.rb:27:in `run'
        16: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/shell.rb:171:in `scan'
        15: from /Users/ferdaber.rvm/rubies/ruby-2.7.1/lib/ruby/2.7.0/benchmark.rb:293:in `measure'
        14: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/shell.rb:172:in `block in scan'
        13: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/api_map.rb:170:in `load'
        12: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/api_map.rb:67:in `catalog'
        11: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/api_map.rb:67:in `each'
        10: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/api_map.rb:85:in `block in catalog'
         9: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map.rb:156:in `map'
         8: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:50:in `map'
         7: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:27:in `map'
         6: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:203:in `process_comment_directives'
         5: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:203:in `each'
         4: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:206:in `block in process_comment_directives'
         3: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:69:in `process_comment'
         2: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:69:in `each'
         1: from /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:72:in `block in process_comment'
            /Users/ferdaber.rvm/gems/ruby-2.7.1@ferdaber/gems/solargraph-0.39.10/lib/solargraph/source_map/mapper.rb:158:in `process_directive': undefined method `strip' for nil:NilClass (NoMethodError)
castwide commented 4 years ago

I'm working on a fix. For now the workaround is to remove the comments above the @!parse directive. See also #329.

castwide commented 4 years ago

Fix released in v0.39.11.

iftheshoefritz commented 4 years ago

Here is my latest gist for documenting AR attributes and relations on models, heavily influenced/plagiarized from other gists in this issue: https://gist.github.com/iftheshoefritz/7a195eb5676bb790cdbff91ab7d42f31. It generates files in config/yard, one per class, and my editor is now doing autocomplete nicely based on them.

Now I'm trying to look at how to go to definition. My editor takes me to the generated YARD files instead of to the original model source. I'm wondering if there is any way to get YARD to point readers to a location in a different file for the original source?

I'm guessing that solargraph bundle behaves similarly to this? Assuming it doesn't actually alter gem source but actually generates separate docs and has some record of the real source location. How does Solargraph do this?