Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance schema hover link to jump to the right table #212

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

faraazahmad
Copy link

@faraazahmad faraazahmad commented Dec 18, 2023

Add a SchemaCollector class that expects schema.rb AST and stores the location for all the defined tables.

For issue #52

@faraazahmad faraazahmad requested a review from a team as a code owner December 18, 2023 14:24
@faraazahmad
Copy link
Author

I have signed the CLA!

Copy link

@wbhouston wbhouston left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @faraazahmad! I was looking through the issues and #52 caught my attention. This looks like a great start to me! Although I'm not a maintainer, so that doesn't carry much weight.

I used part of your code and implemented the remaining steps to include the table location in the schema hover link. If you're interested, I opened a PR in my forked repository that is working for me locally. I didn't include any tests, and I'm new to sorbet so the type assertions are probably wrong.

Best regards!

Comment on lines 23 to 29
node.block.body.child_nodes.each do |child_node|
next unless child_node.is_a?(Prism::CallNode)
next unless child_node.name == :create_table

table_name = child_node.arguments.child_nodes.first.content
@tables[table_name.classify] = child_node.location
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not necessary to traverse the nodes directly within a Prism::Visitor. Per the documentation:

  def visit_call_node(node)
    if node.name == "foo"
      # Do something with the node
    end

    # Call super so that the visitor continues walking the tree
    super
  end

So this could be restructured to look like:

def visit_call_node(node)
  if node.name == 'create_table'
    # ensure the first argument is a string node and store the location
  end

  super
end

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @wbhouston! Thank you for these changes, they look great to me! Feel free to commit these changes to this PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@faraazahmad it won't be possible for @wbhouston to push to your branch.

Copy link
Contributor

@andyw8 andyw8 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wbhouston I tried your PR and it seems to work well. I do have some feedback, but I'd like if you can first work with @faraazahmad to get the work into a single PR against Shopify/ruby-lsp-rails. I'll ensure you are both credited if it is merged.

@faraazahmad
Copy link
Author

Thanks @andyw8 ! I'll add those changes in my fork

@andyw8
Copy link
Contributor

andyw8 commented Jan 16, 2024

Hi @faraazahmad, I tried the latest version and it seems to not be jumping to the line in schema.rb. (it was working when I tried on @wbhouston's branch previously). Could you check it please?

sig { void }
def parse_schema
parse_result = Prism::parse_file(schema_path)
return unless parse_result.success?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this check if necessary. The schema.rb file is generated, so normally it would always be valid Ruby. But in addition to that, Prism is error tolerant, so even if it cannot parse the entire file, it will still return a partial AST, which we can use to find tables.

module Rails
class SchemaCollector < Prism::Visitor
extend T::Sig
extend T::Generic
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably doesn't need to be generic.

Comment on lines 45 to 48
project_root = T.let(
Bundler.with_unbundled_env { Bundler.default_gemfile }.dirname,
Pathname,
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be passing this as an argument from client. Otherwise, we end up with the same information in two separate places, which is likely to get out of sync.

lib/ruby_lsp/ruby_lsp_rails/hover.rb Outdated Show resolved Hide resolved
Co-authored-by: Vinicius Stock <vinistock@users.noreply.github.com>
@faraazahmad
Copy link
Author

Hey thanks for the reviews! And sorry about the delay I've been busy with a couple of things I'll try and finish this soon

@faraazahmad
Copy link
Author

@vinistock I've made the changes as needed, but I'm unable to figure out a Sorbet issue. Since, SchemaCollector now requires a constructor argument,

https://github.com/Shopify/ruby-lsp-rails/pull/212/files#diff-7fa7e03da0e012e6c49f2299b22c01b2c3ae6229f62c66ab7a8a52aaf3d03a22R21-R25 errors out

@andyw8
Copy link
Contributor

andyw8 commented Jan 29, 2024

@faraazahmad I pushed a commit to your branch to address the typing and linting issues. I tried locally and it seems to be working well, but I'll let you confirm before merging.


require "test_helper"

SCHEMA_FILE = <<~RUBY
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this into SchemaCollectorTest so that it's not defined globally.

@andyw8
Copy link
Contributor

andyw8 commented Jan 29, 2024

Let's also update the PR title to be more descriptive for when it appears in the release notes.

@faraazahmad faraazahmad changed the title Add schema collector Enhance schema hover link to jump to the right table Jan 31, 2024
@andyw8
Copy link
Contributor

andyw8 commented Feb 9, 2024

Reminder for myself: Check how this performs for apps with a high number of tables, e.g. Core.

super()

@tables = T.let({}, T::Hash[String, Prism::Location])
@schema_path = T.let(project_root.join("db", "schema.rb").to_s, String)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite right as some apps use structure.sql instead.

If you search you'll see we use schema_dump_path elsewhere to get the path.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means this collector will need to communicate with the server. The path for the schema is unlikely to change, so maybe there's room for a refactor where we fetch the schema path once and reuse it here and in hover.

Maybe we can move forward with this and simply not populate anything if db/schema.rb doesn't exist? That way we can provide the feature for schema users and enhance it later.

super()

@tables = T.let({}, T::Hash[String, Prism::Location])
@schema_path = T.let(project_root.join("db", "schema.rb").to_s, String)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means this collector will need to communicate with the server. The path for the schema is unlikely to change, so maybe there's room for a refactor where we fetch the schema path once and reuse it here and in hover.

Maybe we can move forward with this and simply not populate anything if db/schema.rb doesn't exist? That way we can provide the feature for schema users and enhance it later.

lib/ruby_lsp/ruby_lsp_rails/hover.rb Outdated Show resolved Hide resolved
Co-authored-by: Vinicius Stock <vinistock@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants