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
Switch to using YARP as the parser #41
Conversation
This parser is going to be backend for Syntax Tree soon anyway, so we may as well start using it. It comes with much increased speed and much reduced memory.
…mespaces Now, that `Class/ModuleDefiniton#namespace` is an array of constants we need another way of comparing and matching namespaces. That's why this commit introcudes `Class/ModuleDefiniton#qualified_namespace` so we can compare and match the namespaces as strings.
Wow... this is great! Thank you so much, Kevin! Now I kinda feel sorry that you had to refactor my undocumented and untested Hackathon code 🙈 I manually tested most of the app-functionality, and the speed difference is actually crazy as it's really noticeable while browsing. Super awesome! Going through your changes, I really appreciate the fixes you've implemented, they are spot on! 🙏🏼 Also the way you've revamped the Visitor/Analyzer with the added comments is great, feels much better compared to what I had! Your insights for future improvements are gold!
I think returning
I would be interested to know if you happen to have an example at hand to show how that might look like in Ruby code. I would assume something like the case described in #20?
Agreed, this is a good point. Right now the use of
Yeah, that's a tricky one. I guess you could detect the
Yeah, I wasn't 100% sure how to approach this. I left this out for now, especially since we also have
Oh yeah, I've also been thinking about this. The solution with storing it on the I'm super happy with the outcome of this pull request! From my perspective this is mergeable as-is, thank you! |
You can have really (almost) anything as the receiver of a method definition. So for example: def foo.bar; end
def @foo.bar; end
def @@foo.bar; end
def $foo.bar; end
def Foo.bar; end
def ::Foo.bar; end
def Foo::Foo.bar; end
def __FILE__.bar; end
def self.bar; end
def (foo + foo).bar; end
Here as well, you can have almost anything with a class << foo; end
class << @foo; end
class << @@foo; end
class << $foo; end
class << Foo; end
class << ::Foo; end
class << Foo::Foo; end
class << __FILE__; end
class << self.foo; end
class << (foo + foo); end
I don't think having zeitwerk makes this impossible. If anything it's helpful to have zeitwerk find all of the files for you. Either way to build the graph you'd have to walk through each file. It's difficult because |
Thanks for the added context! All of this seems reasonable and I kinda doubt that YARD/RDoc are able to handle all of these cases as well. I guess focusing on the most common use-cases should be good enough for 95%+ of the cases. There is anyway no way to statically analyze all the meta-programming one could do in Ruby. |
I am working on something like this in Tapioca. I have it roughly working, but it is not fully usable yet. If it does end up working, it would not matter if a gem is using Zeitwerk or not, and the implementation could be reusable so that gem.sh can use it as well. Btw, Tapioca, as a concept, does a lot of things that are similar to what gem.sh does. After all, at the core of it, it is a tool that takes in a gem and extracts a Ruby interface file for it, which, if you squint is basically documentation for the gem. It would be nice to find other ways to collaborate between the two projects, and I am happy to share more about some of our experiences trying to get runtime code loading from gems just right (hint: in the general, it is impossible to load all of a gem's code). |
I'd be interested in a gem that exposes a RubyGem as a model that I can pull into a documentation project I have in the works similar to gem.sh. @marcoroth and I briefly talked about this on Twitter. @paracycle how far off do you feel your project is from landing in a gem? It's tempting to move all the Gem parsing/modeling code from this repo into If we're keeping count, that's 3 projects that would want to share this functionality 🙃 |
This parser is going to be backend for Syntax Tree soon anyway, so we may as well start using it. It comes with much increased speed and much reduced memory.
As a part of this commit, I've changed a little bit and fixed a couple of bugs:
foo + bar # comment
) were being grabbed up, so I removed that.class Foo::Bar; end
. That's been fixed.module Foo; class ::Bar::Baz; end; end
, so that's been fixed.class Foo < bar; end
. At the moment I changed it to just returnnil
for a superclass, but you might want a placeholder that says "we couldn't figure it out" or something to that effect.include foo
.A couple of things I noticed that would be good for future work:
class << self
), so a lot of your methods are going to be attached to the wrong object.require
s from the main gem require as opposed to looping through every file. Otherwise you might end up with a lack of information about necessary includes/extends. A topographical sort would be your friend here.Root
object that you can attach those things to instead.Sorry this is such a big PR. I tried to keep things 1:1 as much as I could to make it easier to review. Happy to discuss or explain anything you might have questions about.