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
Integrate rubocop-daemon #10706
Integrate rubocop-daemon #10706
Conversation
55e0acc
to
44185e4
Compare
Hey, this is great @koic! Thank you for taking charge. I'm currently deep in Typescript land, but I'll let my team know and see if I can dig up a volunteer to try out the PR. One suggestion... I have a bit of experience responding to github issues with the vscode ruby plugin. I recommend adding some logging to help people debug problems that might arise. Stale daemons/pid, versioning issues, wrong |
@gurgeous Thank you for your advice. This PR is the starting point for minimal integration, and will continue to be adjusted and improved with subsequent patches. And, your comment at #9503 (reply in thread) is very helpful :-) |
I think the I'm also wondering whether it would be better to move the server commands to a dedicated "binary" - e.g. I like the general direction, but I think we (@rubocop/rubocop-core) should spend a bit of time thinking on/polishing the design instead of just integrating the existing project as is. |
It doesn't change, btw - RuboCop itself is licensed under the MIT license. |
The following is an example: | ||
|
||
```console | ||
% RUBOCOP_SERVER_PORT=98989 rubocop --start-daemon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally it's not a bad idea to be able to specify the host and port directly via command-line flags as well. That's part of the reason why I like a separate command for managing the server - otherwise we end with a ton of extra options in rubocop
itself.
We should also mark everything related to the server functionality as experimental and the APIs as private, so it's easy for us to adjust them in subsequent versions. I guess the CLI should stay stable, but we'll need some freedom to polish the internals. |
44185e4
to
a0ad50a
Compare
@bbatsov Thank you for the great comments! There are several topics about the discussion, so let's categorize them. License
Yes, the license is the same MIT. But with the addition of the original licensed author name. API stability
I completely agree and I also think it will take some time to polish. These new APIs are unstable, so I marked Terminology
I'm not sure whether NOTE: The Command line API design
Yeah, this is the most difficult... For example, some existing rubocop-daemon user seems to want to start the server with the Therefore, the integrated Here's a question. |
RuboCop server listen on 127.0.0.1:55772. | ||
``` | ||
|
||
NOTE: The `rubocop` command is executed using server server when server process is started. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
server server when server :-)
lib/rubocop/server/core.rb
Outdated
def start_server(host, port) | ||
@server = TCPServer.open(host, port) | ||
|
||
puts "RuboCop server listen on #{@server.addr[3]}:#{@server.addr[1]}." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better message would be "RuboCop server started/running/listening on ...".
I was thinking you'd be able to do |
a0ad50a
to
0e9ff55
Compare
Preparing to resolve rubocop#9503. This PR imports https://github.com/fohte/rubocop-daemon into RuboCop core. The rubocop-daemon's original license (MIT) is written at the beginning of the imported files.
86766a5
to
cb90369
Compare
I noticed this in one commit message:
I guess you meant to write |
ead7ca3
to
d4a42a2
Compare
Oops, you're right. That is a typo and is correctly |
356613b
to
cba6866
Compare
The integrated daemon feature is described in the docs/modules/ROOT/pages/usage/server.adoc included in this PR. ## Daemon options ```console % bundle exec rubocop --help (snip) Server Options: --[no-]server If the daemon process has not started yet, start the server process and execute inspection with server. Default is false. You can specify the daemon host and port with the $RUBOCOP_SERVER_HOST and the $RUBOCOP_SERVER_PORT environment variables. --restart-server Restart server process. --start-server Start server process. --stop-server Stop server process. --server-status Show server status. ``` The daemon mode `--daemon` is disabled by default because it is not yet stable as an integrated feature. ## Design note `RuboCop::Daemon::CLI`'s daemon options are not integrated into `RuboCop::CLI` and `RuboCop::Options`. Because `RuboCop::CLI` and `RuboCop::Options` classes have many dependencies and require the rubocop client (`exe/rubocop`) to make unnecessary `require '...'`. It's important to be lightweight because the daemon mode runs fast, so this design decided to have command line daemon options own (lightweight) option parse logic. And this design only exe/rubocop and lib/rubocop/options.rb files have changed, So almost all daemon code keep independent. NOTE: This feature cannot be used on JRuby and Windows that do not support fork.
cba6866
to
c76ff8d
Compare
I've solved this issue. I dive to ssh to GitHub Actions and found that there was unnecessary access to the server cache directory. Windows never starts the server, so it patched to avoid this process. runneradmin@fv-az252-858 MINGW64 /d/a/rubocop/rubocop
# ./exe/rubocop lib/rubocop.rb
C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:243:in `mkdir': Invalid argument @ dir_s_mkdir - C:/Users/runneradmin/.cache/rubocop_cache/server/:+a+rubocop+rubocop (Errno::EINVAL)
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:243:in `fu_mkdir'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:221:in `block (2 levels) in mkdir_p'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:219:in `reverse_each'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:219:in `block in mkdir_p'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:211:in `each'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/fileutils.rb:211:in `mkdir_p'
from C:/hostedtoolcache/windows/Ruby/3.1.2/x64/lib/ruby/3.1.0/pathname.rb:585:in `mkpath'
from D:/a/rubocop/rubocop/lib/rubocop/server/cache.rb:43:in `block in dir'
from <internal:kernel>:90:in `tap'
from D:/a/rubocop/rubocop/lib/rubocop/server/cache.rb:42:in `dir'
from D:/a/rubocop/rubocop/lib/rubocop/server.rb:28:in `running?'
from ./exe/rubocop:11:in `<main>' |
FYI, a benchmark comparison of
|
Epic difference! Let's take this brand new server for spin! |
I just spent a few hours trying out the new server. From the command line, it's easy to measure the speedup. I am mirroring the way the vscode rubocop extension launches: $ cat xxx.rb | time rubocop --stdin xxx.rb --force-exclusion --format json
...
0.66s user 0.22s system 87% cpu 1.008 total
$ rubocop --start-server
$ cat xxx.rb | time rubocop --stdin xxx.rb --force-exclusion --format json
...
0.10s user 0.12s system 43% cpu 0.503 total Awesome, great work @koic! Unfortunately I am having a lot of difficulty getting any kind of speedup from vscode. Formatting that same file in vscode seems to take around two seconds, regardless of whether or not I run
|
Pretty sure it's connecting to the server in the correct directory. I instrumented rubocop a bit... Anyway, this is a hairy problem and I totally understand people are hesitant to spend hours digging into it. A passing knowledge of vscode-rubocop, rubocop and possible vscode-ruby are all necessary. Plus a willingness to instrument and add temporary debug output. Vscode-ruby in particular is a beast to configure and really has to be disabled if you want to figure out what's happening with rubocop. Good luck :) |
Just came here to say: Thank you @koic! And thank you @fohte! I haven't tried this yet, but I'm really looking forward to switching to more stable and hopefully longer-term supported solution. I wanted to share my current setup for anyone interested: I'm using rubocop-daemon from within the VS Code through "[ruby]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "misogi.ruby-rubocop"
},
"ruby.rubocop.executePath": "/usr/local/bin/", I'm pretty sure my "rubocop" binary here is "rubocop-daemon-wrapper": > l /usr/local/bin/ | grep rubocop
.rwxr-xr-x 3.8k viktor 8 Oct 2021 rubocop
.rwxr-xr-x 3.8k viktor 6 Oct 2021 rubocop-daemon-wrapper It works great until I open a ruby project that's using different ruby version than the previously opened ruby project. |
Just chiming in to document a few more things. I finally ran some benchmarks on my machine (an M1). Here's what I learned:
There is also some undesirable behavior in the vscode rubocop extension. The default setup will run I am trying to pitch in a bit on the extension to get these issues documented and fixed. The original extension seems abandoned, but there's an active fork here - https://github.com/LoranKloeze/vscode-ruby-rubocop-revived. Also see - LoranKloeze/vscode-ruby-rubocop-revived#13 |
@gurgeous Might be a good idea to add a new ticket about potential performance improvements we can do for |
This PR has two parts committed. That is, the import part and the integration part of rubocop-daemon. Please keep these commits.
Part 1: Import rubocop-daemon
Preparing to resolve #9503.
This PR merges https://github.com/fohte/rubocop-daemon into RuboCop core.
The rubocop-daemon's original license (MIT) is written at the beginning of the imported files.
@fohte @gurgeous
Part 2: Integrate rubocop-daemon
The integrated daemon feature is described in the docs/modules/ROOT/pages/usage/server.adoc included in this PR.
Server options
The server mode
--server
is disabled by default because it is not yet stable as an integrated feature.Design note
RuboCop::Daemon::CLI
's daemon options are not integrated intoRuboCop::CLI
andRuboCop::Options
.Because
RuboCop::CLI
andRuboCop::Options
classes have many dependencies and require the rubocop client (exe/rubocop
) to make unnecessaryrequire '...'
.It's important to be lightweight because the daemon mode runs fast, so this design decided to have command line daemon options own (lightweight) option parse logic.
And this design only exe/rubocop and lib/rubocop/options.rb files have changed, So almost all daemon code keep independent.
NOTE: This feature cannot be used on JRuby and Windows that do not support fork.
Before submitting the PR make sure the following are checked:
[Fix #issue-number]
(if the related issue exists).master
(if not - rebase it).bundle exec rake default
. It executes all tests and runs RuboCop on its own code.{change_type}_{change_description}.md
if the new code introduces user-observable changes. See changelog entry format for details.