dgutov / robe

Code navigation, documentation lookup and completion for Ruby
584 stars 37 forks source link

Can't jump to the nested module's class in `enh-ruby-mode`, but ruby-mode works #136

Open zw963 opened 2 years ago

zw963 commented 2 years ago

Following is a example:

module Types
  module UserQuery
    class UserQueryType < Types::BaseObject
      field :current_user, resolver: Types::UserQuery::Resolvers::CurrentUserResolver # case 1
      field :current_user, resolver: Resolvers::CurrentUserResolver  # case 2
  end
end

above case 1 and case 2 field have same effect.

When cursor on the case 1 CurrentUserResolver, robe jump feature is works!

But.

When cursour on the case 2 CurrentUserResolver, will tip Can't find the locatin. but code case 2 actually is working code, totally same as case 1, because Resolvers::CurrentUserResolver is under namespaced module, module Types => module => UserQuery => Resolvers::CurrentUserResolver

I can reproduce this on ruby 3.1.0 with inf-ruby newest master.

Thank you.


Added:

CurrentUserResolver defined like this,

class Types::UserQuery::Resolvers::CurrentUserResolver < Resolvers::Base
end

though, i consider this should not the reason, because another class define like this, not work too.

module Types
  module UserQuery
    class UserNameType
    end
  end
end

And, i use rails 6, autoloading feature use zeitwerk.

zw963 commented 2 years ago

BTW, this never be a issue anyway, because i prefer write the full name in this cause, like this:

module Types
  module UserQuery
    class UserQueryType < Types::BaseObject
     field :user_info, resolver: Types::UserQuery::Resolvers::UserInfoResolver
      field :current_user, resolver: Types::UserQuery::Resolvers::CurrentUserResolver
      field :current_user_wallet, resolver: Types::UserQuery::Resolvers::CurrentUserWalletResolver
  end
end

And, i define class like this too.

class Types::UserQuery::Resolvers::CurrentUserWalletResolver
end

because even if no robe or TAGS, i can find out where this class defined and used very easy with grep full name. like this: Types::UserQuery::Resolvers::CurrentUserWalletResolver.


But, my co-worker prefer less is better, it always prefer write code like this:

module Types
  module UserQuery
    class UserQueryType < Types::BaseObject
     field :user_info, resolver: Resolvers::UserInfoResolver
      field :current_user, resolver: Resolvers::CurrentUserResolver
      field :current_user_wallet, resolver: Resolvers::CurrentUserWalletResolver
  end
end

and define class like this:

module Types
  module UserQuery
    module Resolvers
     class CurrentUserWalletResolver
     end
end

If use like this, we can't use robe to skip the actually definition position, so, i just curious, if is was possible to support this.

dgutov commented 2 years ago

Hi!

Please clarify: do you both use ruby-mode, or enh-ruby-mode?

zw963 commented 2 years ago

Hi!

Please clarify: do you both use ruby-mode, or enh-ruby-mode?

Not sure, actually, i only use enh-ruby-mode for a long time, current major-mode is enh-ruby-mode too. but, i am not sure if emacs builtin ruby-mode was loaded before.

dgutov commented 2 years ago

Could you try the same scenario with ruby-mode first, too?

zw963 commented 2 years ago

Could you try the same scenario with ruby-mode first, too?

Yes, it works.

it can jump from

field :user_info, resolver: Resolvers::UserInfoResolver

to

class Types::UserQuery::Resolvers::UserInfoResolver < Resolvers::Base
end

In fact, i found inf-ruby always require ruby-mode, so, it only not work when enable enh-ruby-mode.

zw963 commented 2 years ago

Maybe i should switch back to builtin ruby-mode, anyway, some of advantage of enh-ruby-mode was exists on solargraph when use with lsp (though, i disable it), and @zenspider is busy, enh-ruby-mode not updated almost one year.

Which mode you use for ruby programming?

zw963 commented 2 years ago

i can reproduce on a very simple config, following is log:

Debugger entered--Lisp error: (error "Can’t find the location")
  error("Can't find the location")
  robe-jump-to-module(#("Resolvers::UserInfoResolver" 0 9 (font-lock-face font-lock-type-face fontified t) 9 11 (font-lock-face enh-ruby-op-face fontified t) 11 27 (font-lock-face font-lock-type-face fontified t)))
  robe-jump(nil)
  funcall-interactively(robe-jump nil)
  command-execute(robe-jump)
zw963 commented 2 years ago

consider check this: https://github.com/zenspider/enhanced-ruby-mode/issues/182

dgutov commented 2 years ago

i can reproduce on a very simple config, following is log:

Only with enh-ruby-mode, right?

I'm guessing it's rather because of this much older issue: https://github.com/zenspider/enhanced-ruby-mode/issues/156, which I originally filed as https://github.com/zenspider/enhanced-ruby-mode/issues/96.

While admittedly robe is doing something a little unusual (using add-log-current-defun-function as a method to determine the current calling context), it shouldn't take 5 years to fix.

some of advantage of enh-ruby-mode was exists on solargraph when use with lsp

Is there some advantage when used together with LSP? I'm not aware of any.

IIUC people have been using it because of some different indentation behavior in certain examples. And maybe some differences in syntax coloring, though I don't know which.

Which mode you use for ruby programming?

I use ruby-mode. I'm maintaining it, after all.

zw963 commented 2 years ago

Only with enh-ruby-mode, right?

Yes.

Is there some advantage when used together with LSP? I'm not aware of any.

  1. it have auto complete/jump to function feature, but it should not better than robe-company.
  2. it have flycheck, but, that just use rubocop, i used to use it.
  3. it have formatter feature, but, i guess, that just ruby mode sexp format.
  4. i remember lsp can support semantic tokens, it can give better highlight feature than ruby-mode, i guess this is what you said IIUC people used, but, lsp semantic tokens a little slower since i used it long time ago.(monthly), in fact, i consider enh-ruby-mode give better highlight too, even load large .rb file more quickly then ruby-mode, that was the reason i keep use enh-ruby-mode.
  5. ruby dap (debug feature) never works for me, maybe ruby 3.1.0 new built debugger feature can improve on this.

the advantage is, lsp use static analyze, it not need start a REPL to make those feature available. i consider ruby will give better support for lsp the next few years as said by @matz, in fact, we have seen many improvement since ruby 3.1.0.

but, the shortcoming is same, when open ruby-lsp first time, it will spend 4~5 seconds to open a ruby buffer because static analyze, i guess.

Anyway, in fact, i never use lsp-ruby for a long time use, not so useful, but, it very very awesome for use Strong type language, like dart, go, rust, it almost can not do anything no lsp if you ever use it.

zw963 commented 2 years ago

I use ruby-mode. I'm maintaining it, after all.

I will try to switch back to ruby-mode, BTW, where is the official repo of ruby-mode? i never saw it on https://github.com/ruby

dgutov commented 2 years ago

i consider enh-ruby-mode give better highlight too, even load large .rb file more quickly then ruby-mode, that was the reason i keep use enh-ruby-mode

That's interesting. I should compare it sometime.

As for the rest, I was asking for reasons to use enh-ruby-mode, not about LSP. They are not tied together: you can just as well use LSP with ruby-mode.

where is the official repo of ruby-mode?

It lived inside https://github.com/ruby/ruby/tree/master/misc originally, but about a decade ago it was contributed to Emacs, and has been living it its official repo ever since.

zw963 commented 2 years ago

As for the rest, I was asking for reasons to use enh-ruby-mode

  1. more better highlight.
  2. more better performance when open and edit a large rb file.

it was contributed to Emacs, and has been living it its official repo ever since.

What you said official repo is https://git.savannah.gnu.org/git/emacs.git/, right?

I know ruby-mode was builtin, and Richard Stallman give @matz a award for the contribute of emacs.

i just curious how you maintain ruby-mode.el, and where i can create issue or discuss about it.

dgutov commented 2 years ago

more better highlight

Any particular examples?

What you said official repo is https://git.savannah.gnu.org/git/emacs.git/, right?

Yup. And I have commit access.

and Richard Stallman give @matz a award for the contribute of emacs.

Not for Emacs, just for Ruby (the award was for contributing to free software).

and where i can create issue or discuss about it

You do that with M-x report-emacs-bug.

zw963 commented 2 years ago

Let us try with https://raw.githubusercontent.com/ruby/irb/master/lib/irb.rb + VS Code theme.

left: ruby-mode, right: enh-ruby-mode.

image

Okay, because i never use builtin ruby-mode for very long time, it looks like almost same for now, i guess ruby-mode get a great improvement for UI and others.

dgutov commented 2 years ago

:+1:

because i never use builtin ruby-mode for very long time

It must have really been a while, because there have been no recent changes in that area.

And as for better performance with opening/editing large files, reports with examples are also welcome. There are limits in what I can do obviously, but I'll be sure to take a look.

zw963 commented 2 years ago

We can test on this the biggest file which builtin on ruby 3.1.0

markdown.rb.gz

I use emacs daemon mode, and start a new frame before open it.

When i use ruby-mode, it spent 7.89 seconds to show and render the buffer correct on my laptop.

when i use enh-ruby-mode, it spent 7.08 seconds, though, because enh-ruby maybe show me buffer within 3 seconds, but no highlight, still need wait until 7 seconds to render correct, that give me a wrong intuition, enh-ruby more quickly.

In fact, i consider ruby-mode is more better for now, because when editing on this big file, use enh-ruby-mode if very lag because i guess it have to load ripper to render it again, i remember, when i start to use enh-ruby, it give more better syntax error tips and indent on some cases, but, i can't give you a example for now, maybe all just a misunderstand. and, and some feature not so useful because we have flycheck + rubocop etc.

I use emacs 28.0.91, i guess if some great improvement to xref, native json, native compile make ruby better?.

And as saw on previous screenshot, ruby-mode even render more accurately because enh-ruby-mode highlight using keyword in string.

anyway, i come back to ruby-mode, no find any issue for now.

zw963 commented 2 years ago

BTW, if you are the ruby-mode committer, i have a feature request, in fact, i want to request this for a long time.

In the ruby-mode source code, we can saw a comment like following:

image

Yes, for now, there is a person ask for it, that is me, i hope we can have it.

In fact, i always write { block like this:

  1. if we have block args, i prefer no space after {, like this. [1,2,3].each {|x| p x }
  2. if we are no block args, i prefer with space, ater {, like this: 3.times { puts 'hello' }

So, every time, i use ruby mode, i have to hack my own function, the only changes is. replace (insert "{ ") with (insert "{").

dgutov commented 2 years ago

When i use ruby-mode, it spent 7.89 seconds to show and render the buffer correct on my laptop

That is odd: I have tried reproducing this, and it (the file you have attached) opens pretty much instantly. Scrolls to the bottom pretty much instantly as well, certainly doesn't take several seconds. You might want to benchmark that process with the native profiler.

In fact, i consider ruby-mode is more better for now, because when editing on this big file, use enh-ruby-mode if very lag because i guess it have to load ripper to render it again, i remember, when i start to use enh-ruby, it give more better syntax error tips and indent on some cases, but, i can't give you a example for now, maybe all just a misunderstand

It is likely possible to bring enh-ruby-mode to the same level of performance as ruby-mode (Ruby itself is not slower than Elisp: should really be faster); but that would take effort I'd rather put into the built-in mode.

some feature not so useful because we have flycheck + rubocop etc

Right.

I use emacs 28.0.91, i guess if some great improvement to xref, native json, native compile make ruby better?

I use Emacs 29, but it's not native-compiled. And ruby-mode doesn't use xref or json. :shrug:

And its version of ruby-mode is the same as in Emacs 28.

dgutov commented 2 years ago

if we have block args, i prefer no space after {, like this. [1,2,3].each {|x| p x }

That's a pretty odd convention IMHO. Does Rubocop have a corresponding rule setting?

Anyway, it shouldn't be too hard to add such user option. Will you M-x report-emacs-bug about it? No need to be too verbose in the description, you can link to this discussion.

zw963 commented 2 years ago

Hi, @dgutov , because we are talking about the difference about ruby-mode and enh-ruby-mode in this thread, let me report some of them here after use ruby-mode a while.

  1. ruby-mode render some file not correct. you can see a sample file at: https://github.com/rmosolgo/graphql-ruby/blob/master/lib/graphql/schema/argument.rb#L88

as you can see in following screenshot, enh-ruby-mode (right side) render correct, but left, no.

image

  1. Another issue is indent.

First, i have one more question, what is the means of ruby-use-smie ? i have no idea of this, i only know if i don't want deep indent, i must set this as nil. (it default is t), and we set this variable as obsolete as of 28.1, but, it not give clue what is the default behavior when emacs 28.1 released.

Okay, continue describe my indent issue, i don't like deep indent, so, i have to try disable all related config like this:

  (setq ruby-use-smie nil)
  (setq ruby-deep-arglist nil)
  (setq ruby-deep-indent-paren nil)
  (setq ruby-deep-indent-paren-style nil)

image

But, as you can see, ruby-mode not indent correct (left window), and rubocop give some advice too, then enh-ruby-mode always indent correct.

zw963 commented 2 years ago

That's a pretty odd convention IMHO. Does Rubocop have a corresponding rule setting?

Sorry for missing this message, Yes, please check https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Layout/SpaceInsideBlockBraces, i disable it when i use rubocop.

BTW: i request this issue on report-emacs-bug seveal days ago.

zw963 commented 2 years ago

BTW: for https://github.com/dgutov/robe/issues/136#issuecomment-1020823932 issue 2, if i remove the parenthesis mark, indent work well when use default indent config (that is, keep ruby-use-smie as default t).

image

though, rubocop warn me to add a parenthesis to avoid misunderstood the block part belongs to which.

Parenthesize the param friends[3].moments.map {|x| [x.content, x.created_at.to_s] } to make sure that the block will be associated with the friends[3].moments.map method call. [Lint/AmbiguousBlockAssociation]

dgutov commented 2 years ago

Sorry for missing this message, Yes, please check https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Layout/SpaceInsideBlockBraces, i disable it when i use rubocop.

Right. You can customize the specific option: SpaceBeforeBlockParameters.

BTW: i request this issue on report-emacs-bug seveal days ago.

Thanks. Did you miss the reply on the bug tracker? I've added said option a week ago: https://debbugs.gnu.org/53321

dgutov commented 2 years ago

because we are talking about the difference about ruby-mode and enh-ruby-mode in this thread, let me report some of them here after use ruby-mode a while.

These are also reports for the bug tracker. But if you insist on keeping them here in the comments, oh well.

You have touched on a couple of old (and relatively difficult) issues, especially the first one, with recursive nesting of literals through interpolations. I'll see what I can do now.

zw963 commented 2 years ago

Thanks. Did you miss the reply on the bug tracker? I've added said option a week ago: https://debbugs.gnu.org/53321

Sorry, miss it because my emacs email client still not working, :smile:

i am now testing it with copy ruby-mode.el from master branch to emacs-28 branch, it works as expected for now after set ruby-toggle-block-space-before-parameters to nil, i removed my own hacked functions for now, thank you.

zw963 commented 2 years ago

Hi, @dgutov i don't know why, my emacs-report-bug seem like not work anymore, so i report a ruby-mode bug here.

Following code will cause indentation issue, because the double splat |**args| in the block parameter.

e.g.

def resolve(**args)
  members = proc do |**args|
p(**args)                               # indentation error
end                                       #  indentation error
member.call(**args)             # indentation error
end

But rubocop can format above code correctly.

In fact, when my cursor on the def, when i eval forward-sexp(C-M-f), it should be jump to after the last end.

But, instead, it jump to following location (please see screenshot)

image

if change double splat to single splat in block parameter, will get correct indentation.

def resolve(**args)
  members = proc do |*args|
    p(**args)
  end
  member.call(**args)
end

ruby version

3.1.0

emacs version

I use emacs mode which built on Emacs 28.1 release branch code.

GNU Emacs 28.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.17.6) of 2022-04-05

dgutov commented 2 years ago

@zw963 Hi! Thanks for the report. Should be fixed now in 39646c822b, on the master branch.

Emacs 28.1 has been released already, but I'll add ruby-mode to GNU ELPA in some foreseeable future.

Regarding your "emacs-report-bug seem like not work anymore", what does the problem look like?

zw963 commented 2 years ago

Regarding your "emacs-report-bug seem like not work anymore", what does the problem look like?

Or, i find the issue caused by not correct config of mu4e, sorry for confusing.

Emacs 28.1 has been released already, but I'll add ruby-mode to GNU ELPA in some foreseeable future.

Cool, thank you.