diff --git a/.github/workflows/publish_docs.yml b/.github/workflows/publish_docs.yml index 7f55c76752..c7a5fb0d38 100644 --- a/.github/workflows/publish_docs.yml +++ b/.github/workflows/publish_docs.yml @@ -16,6 +16,7 @@ jobs: uses: ruby/setup-ruby@v1 with: bundler-cache: true + working-directory: ./jekyll - name: Configure git run: | @@ -23,13 +24,8 @@ jobs: git config user.email github-actions@github.com - name: Generate documentation - run: bundle exec rake rdoc - - - name: Copy README images to the docs folder - run: | - mkdir docs/vscode - cp vscode/icon.png docs/vscode/icon.png - cp -R vscode/extras docs/vscode/ + working-directory: ./jekyll + run: bundle exec jekyll build - name: Commit to gh-pages run: | diff --git a/.rubocop.yml b/.rubocop.yml index 36a502e575..6575a465f6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -20,6 +20,7 @@ AllCops: - "features/**/*" - "test/fixtures/**/*" - "test/expectations/**/*" + - "jekyll/**/*" Minitest/AssertPredicate: Enabled: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a77640bb6..19fb189a0d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,15 @@ # CONTRIBUTING +## Contributing to documentation + +Ruby LSP uses [Jekyll](https://jekyllrb.com/) to generate the documentation, whose source lives under the `/jekyll` folder. + +```shell +cd jekyll +bundle install +bundle exec jekyll serve # Builds the site and serves it at http://localhost:4000/ruby-lsp +``` + ## Testing changes ### Tracing LSP requests and responses diff --git a/Gemfile b/Gemfile index 3c76abd004..dde501c4d1 100644 --- a/Gemfile +++ b/Gemfile @@ -27,5 +27,12 @@ group :development do # sorbet-static is not available on Windows. We also skip Tapioca since it depends on sorbet-static-and-runtime gem "sorbet-static-and-runtime" gem "tapioca", "~> 0.16", require: false + + # We only need to use Jekyll with CRuby + gem "jekyll", "~> 4.3.3" + gem "jekyll-feed", "~> 0.12" + + # Theme + gem "just-the-docs", "~> 0.10.0" end end diff --git a/Gemfile.lock b/Gemfile.lock index 99c7a8c341..c1edbac1ba 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -18,63 +18,125 @@ PATH GEM remote: https://rubygems.org/ specs: + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) ansi (1.5.0) ast (2.4.2) + bigdecimal (3.1.8) builder (3.3.0) + colorator (1.1.0) + concurrent-ruby (1.3.4) debug (1.9.2) irb (~> 1.10) reline (>= 0.3.8) - docile (1.4.0) + docile (1.4.1) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) erubi (1.13.0) + eventmachine (1.2.7) + ffi (1.17.0-arm64-darwin) + forwardable-extended (2.6.0) + google-protobuf (4.28.1-arm64-darwin) + bigdecimal + rake (>= 13) + http_parser.rb (0.8.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) io-console (0.7.2) - irb (1.12.0) - rdoc + irb (1.14.0) + rdoc (>= 4.0.0) reline (>= 0.4.2) + jekyll (4.3.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-feed (0.17.0) + jekyll (>= 3.7, < 5.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) json (2.7.2) + just-the-docs (0.10.0) + jekyll (>= 3.8.5) + jekyll-include-cache + jekyll-seo-tag (>= 2.0) + rake (>= 12.3.1) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) language_server-protocol (3.17.0.3) - logger (1.6.0) + liquid (4.0.4) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + logger (1.6.1) + mercenary (0.4.0) minitest (5.25.1) minitest-reporters (1.7.1) ansi builder minitest (>= 5.0) ruby-progressbar - mocha (2.3.0) + mocha (2.4.5) ruby2_keywords (>= 0.0.5) netrc (0.11.0) parallel (1.26.3) - parser (3.3.4.2) + parser (3.3.5.0) ast (~> 2.4.1) racc + pathutil (0.16.2) + forwardable-extended (~> 2.6) prettier_print (1.2.1) prism (1.0.0) psych (5.1.2) stringio + public_suffix (6.0.1) racc (1.8.1) rainbow (3.1.1) rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) rbi (0.2.0) prism (~> 1.0) sorbet-runtime (>= 0.5.9204) rbs (3.5.3) logger regexp_parser (2.9.2) - reline (0.5.0) + reline (0.5.10) io-console (~> 0.5) - rexml (3.3.6) - strscan - rubocop (1.65.1) + rexml (3.3.7) + rouge (4.3.0) + rubocop (1.66.1) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 2.4, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.31.1, < 2.0) + rubocop-ast (>= 1.32.2, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.32.1) + rubocop-ast (1.32.3) parser (>= 3.3.1.0) rubocop-md (1.2.2) rubocop (>= 1.0) @@ -89,27 +151,28 @@ GEM rubocop (>= 1) ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) + safe_yaml (1.0.5) + sass-embedded (1.78.0-arm64-darwin) + google-protobuf (~> 4.27) simplecov (0.22.0) docile (~> 1.1) simplecov-html (~> 0.11) simplecov_json_formatter (~> 0.1) - simplecov-html (0.12.3) + simplecov-html (0.13.1) simplecov_json_formatter (0.1.4) - sorbet (0.5.11551) - sorbet-static (= 0.5.11551) - sorbet-runtime (0.5.11551) - sorbet-static (0.5.11551-universal-darwin) - sorbet-static (0.5.11551-x86_64-linux) - sorbet-static-and-runtime (0.5.11551) - sorbet (= 0.5.11551) - sorbet-runtime (= 0.5.11551) + sorbet (0.5.11558) + sorbet-static (= 0.5.11558) + sorbet-runtime (0.5.11558) + sorbet-static (0.5.11558-universal-darwin) + sorbet-static-and-runtime (0.5.11558) + sorbet (= 0.5.11558) + sorbet-runtime (= 0.5.11558) spoom (1.4.2) erubi (>= 1.10.0) prism (>= 0.28.0) sorbet-static-and-runtime (>= 0.5.10187) thor (>= 0.19.2) - stringio (3.1.0) - strscan (3.1.0) + stringio (3.1.1) syntax_tree (6.2.0) prettier_print (>= 1.2.0) tapioca (0.16.2) @@ -121,23 +184,25 @@ GEM spoom (>= 1.2.0) thor (>= 1.2.0) yard-sorbet + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) thor (1.3.2) unicode-display_width (2.5.0) - yard (0.9.36) + webrick (1.8.1) + yard (0.9.37) yard-sorbet (0.9.0) sorbet-runtime yard PLATFORMS - arm64-darwin - x64-mingw-ucrt - x64-mingw32 - x86_64-darwin - x86_64-linux + arm64-darwin-23 DEPENDENCIES bundler (~> 2.5) debug (~> 1.9) + jekyll (~> 4.3.3) + jekyll-feed (~> 0.12) + just-the-docs (~> 0.10.0) minitest (~> 5.25) minitest-reporters (~> 1.7) mocha (~> 2.3) @@ -157,4 +222,4 @@ DEPENDENCIES tapioca (~> 0.16) BUNDLED WITH - 2.5.10 + 2.5.11 diff --git a/README.md b/README.md index 6283b6eb06..1f8d6ad60d 100644 --- a/README.md +++ b/README.md @@ -15,119 +15,9 @@ experience to Ruby developers using modern standards for cross-editor features, Want to discuss Ruby developer experience? Consider joining the public [Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q). -## Features +## Getting Started -![Ruby LSP demo](vscode/extras/ruby_lsp_demo.gif) - -The Ruby LSP features include - -- Semantic highlighting -- Symbol search and code outline -- RuboCop errors and warnings (diagnostics) -- Format on save (with RuboCop or Syntax Tree) -- Format on type -- Debugging support -- Running and debugging tests through VS Code's UI -- Go to definition for classes, modules, constants and required files -- Showing documentation on hover for classes, modules and constants -- Completion for classes, modules, constants and require paths -- Fuzzy search classes, modules and constants anywhere in the project and its dependencies (workspace symbol) - -As of July 2024, Ruby LSP has received significant enhancements to its code navigation features. For an in-depth look at these improvements, including video demonstrations, check out this [article](https://railsatscale.com/2024-07-18-mastering-ruby-code-navigation-major-enhancements-in-ruby-lsp-2024/). Despite these advancements, we plan to continue enhancing its code navigation support even further. You can follow our progress on this [GitHub issue](https://github.com/Shopify/ruby-lsp/issues/899). - -See complete information about features [here](https://shopify.github.io/ruby-lsp/RubyLsp/Requests.html). - -If you experience issues, please see the [troubleshooting -guide](https://github.com/Shopify/ruby-lsp/blob/main/TROUBLESHOOTING.md). - -## Usage - -### With VS Code - -If using VS Code, all you have to do is install the [Ruby LSP -extension](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) to get the extra features in the -editor. Do not install the `ruby-lsp` gem manually. - -For more information on using and configuring the extension, see [vscode/README.md](vscode/README.md). - -### With other editors - -See [editors](EDITORS.md) for community instructions on setting up the Ruby LSP, which current includes Emacs, Neovim, Sublime Text, and Zed. - -The gem can be installed by doing -```shell -gem install ruby-lsp -``` - -and the language server can be launched running `ruby-lsp` (without bundle exec in order to properly hook into your -project's dependencies). - -### Documentation - -See the [documentation](https://shopify.github.io/ruby-lsp) for more in-depth details about the -[supported features](https://shopify.github.io/ruby-lsp/RubyLsp/Requests.html). - -For creating rich themes for Ruby using the semantic highlighting information, see the [semantic highlighting -documentation](SEMANTIC_HIGHLIGHTING.md). - -### Configuring code indexing - -By default, the Ruby LSP indexes all Ruby files defined in the current project and all of its dependencies, including -default gems, except for - -- Gems that only appear under the `:development` group -- All Ruby files under `test/**/*.rb` - -This behaviour can be overridden and tuned. Learn how to configure it [for VS Code](vscode/README.md#Indexing-Configuration) or [for other editors](EDITORS.md#Indexing-Configuration). - -Note that indexing-dependent behavior, such as definition, hover, completion or workspace symbol will be impacted by -the configuration changes. - -The older approach of using a `.index.yml` file has been deprecated and will be removed in a future release. - -```yaml -# Exclude files based on a given pattern. Often used to exclude test files or fixtures -excluded_patterns: - - "**/spec/**/*.rb" - -# Include files based on a given pattern. Can be used to index Ruby files that use different extensions -included_patterns: - - "**/bin/*" - -# Exclude gems by name. If a gem is never referenced in the project's code and is only used as a tool, excluding it will -# speed up indexing and reduce the amount of results in features like definition or completion -excluded_gems: - - rubocop - - pathname - -# Include gems by name. Normally used to include development gems that are excluded by default -included_gems: - - prism -``` - -### Addons - -The Ruby LSP provides an addon system that allows other gems to enhance the base functionality with more editor -features. This is the mechanism that powers addons like - -- [Ruby LSP Rails](https://github.com/Shopify/ruby-lsp-rails) -- [Ruby LSP RSpec](https://github.com/st0012/ruby-lsp-rspec) -- [Ruby LSP rubyfmt](https://github.com/jscharf/ruby-lsp-rubyfmt) - -Additionally, some tools may include a Ruby LSP addon directly, like - -- [Standard Ruby (from v1.39.1)](https://github.com/standardrb/standard/wiki/IDE:-vscode#using-ruby-lsp) - -Other community driven addons can be found in [rubygems](https://rubygems.org/search?query=name%3A+ruby-lsp) by -searching for the `ruby-lsp` prefix. - -For instructions on how to create addons, see the [addons documentation](ADDONS.md). - -## Learn More - -* [RubyConf 2022: Improving the development experience with language servers](https://www.youtube.com/watch?v=kEfXPTm1aCI) ([Vinicius Stock](https://github.com/vinistock)) -* [Remote Ruby: Ruby Language Server with Vinicius Stock](https://remoteruby.com/221) -* [RubyKaigi 2023: Code indexing - How language servers understand our code](https://www.youtube.com/watch?v=ks3tQojSJLU) ([Vinicius Stock](https://github.com/vinistock)) +Please refer to the official [documentation](https://shopify.github.io/ruby-lsp) for more information about [installation and usage](https://shopify.github.io/ruby-lsp#usage) and [supported features](https://shopify.github.io/ruby-lsp#features). ## Contributing diff --git a/jekyll/.gitignore b/jekyll/.gitignore new file mode 100644 index 0000000000..f40fbd8ba5 --- /dev/null +++ b/jekyll/.gitignore @@ -0,0 +1,5 @@ +_site +.sass-cache +.jekyll-cache +.jekyll-metadata +vendor diff --git a/jekyll/404.html b/jekyll/404.html new file mode 100644 index 0000000000..086a5c9ea9 --- /dev/null +++ b/jekyll/404.html @@ -0,0 +1,25 @@ +--- +permalink: /404.html +layout: default +--- + + + +
Page not found :(
+The requested page could not be found.
++ +
+ +The Ruby LSP is an implementation of the [language server protocol](https://microsoft.github.io/language-server-protocol/) +for Ruby, used to improve rich features in editors. It is a part of a wider goal to provide a state-of-the-art +experience to Ruby developers using modern standards for cross-editor features, documentation and debugging. + +Want to discuss Ruby developer experience? Consider joining the public +[Ruby DX Slack workspace](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q). + +## Table of Contents + +- [Usage](#usage) + - [With VS Code](#with-vs-code) + - [With other editors](#with-other-editors) +- [Addons](#addons) +- [Features](#features) + - [Hover](#hover) + - [Go-to-Definition](#go-to-definition) + - [Completion](#completion) + - [Signature Help](#signature-help) + - [Code Navigation in `.erb` Files](#code-navigation-in-erb-files) +- [Experimental Features](#experimental-features) + - [Ancestors Hierarchy Request](#ancestors-hierarchy-request) + - [Guess Type](#guess-type) +- [Configuration](#configuration) + - [Configuring code indexing](#configuring-code-indexing) +- [Additional Resources](#additional-resources) + +## Usage + +### With VS Code + +If using VS Code, all you have to do is install the [Ruby LSP +extension](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) to get the extra features in the +editor. Do not install the `ruby-lsp` gem manually. + +For more information on using and configuring the extension, see the extension's [README.md](https://github.com/Shopify/ruby-lsp/blob/main/vscode/README.md). + +### With other editors + +See [editors](https://github.com/Shopify/ruby-lsp/blob/main/EDITORS.md) for community instructions on setting up the Ruby LSP, which current includes Emacs, Neovim, Sublime Text, and Zed. + +The gem can be installed by doing + +```shell +gem install ruby-lsp +``` + +and the language server can be launched running `ruby-lsp` (without bundle exec in order to properly hook into your +project's dependencies). + +## Addons + +The Ruby LSP provides an addon system that allows other gems to enhance the base functionality with more editor +features. This is the mechanism that powers addons like + +- [Ruby LSP Rails](https://github.com/Shopify/ruby-lsp-rails) +- [Ruby LSP RSpec](https://github.com/st0012/ruby-lsp-rspec) +- [Ruby LSP rubyfmt](https://github.com/jscharf/ruby-lsp-rubyfmt) + +Additionally, some tools may include a Ruby LSP addon directly, like + +- [Standard Ruby (from v1.39.1)](https://github.com/standardrb/standard/wiki/IDE:-vscode#using-ruby-lsp) + +Other community driven addons can be found in [rubygems](https://rubygems.org/search?query=name%3A+ruby-lsp) by +searching for the `ruby-lsp` prefix. + +For instructions on how to create addons, see the [addons documentation](https://github.com/Shopify/ruby-lsp/blob/main/ADDONS.md). + +## Features + +### Hover + +The hover feature displays comments or documentation for the target constant or method when the cursor hovers over them. + +In VS Code, if you hover while pressing `Command`, it will also send a `definition` request to locate the possible target sources. And it will display the target's source code if only one source is located (e.g., the class is not reopened in multiple places). + + + +### Go-to-Definition + +Go-to-definition allows users to navigate to the target constant or method's definition, +whether they're defined in your project or its dependencies. + +This feature can be triggered by one of the following methods: + +- `Right click` on the target, and then select `Go to Definition` +- Placing the cursor on the target, and then hit `F12` +- `Command + click` the target + +**With One Definition:** + +Users are taken directly to the source. + + + +**With Multiple Definitions:** + +Users see a dropdown with all the sources, along with a preview window on the side. + + + +### Completion + +The completion feature provides users with completion candidates when the text they type matches certain indexed components. This helps speed up coding by reducing the need to type out full method names or constants. +It also allows developers to discover constants or methods that are available to them. + + + +### Signature Help + +Signature help often appears right after users finish typing a method, providing hints about the method's parameters. This feature is invaluable for understanding the expected arguments and improving code accuracy. + + + +### Code Navigation in `.erb` Files + +Code navigation features, like hover, go-to-definition, completion, and signature help, are supported in `.erb` files. + + + +## Experimental Features + +Ruby LSP also provides experimental features that are not enabled by default. If you have feedback about these features, +you can let us know in the [DX Slack](https://join.slack.com/t/ruby-dx/shared_invite/zt-2c8zjlir6-uUDJl8oIwcen_FS_aA~b6Q) or by [creating an issue](https://github.com/Shopify/ruby-lsp/issues/new). + +### Ancestors Hierarchy Request + +The ancestors hierarchy request feature aims to provide a better understanding of the inheritance hierarchy within your Ruby code. This feature helps developers trace the lineage of their classes and modules, making it easier to: + +- Visualize the inheritance hierarchy of classes and modules. +- Quickly navigate through the inheritance chain. + + + +#### Why Is It Experimental? + +This feature is supported by the [Type Hierarchy Supertypes LSP request](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#typeHierarchy_supertypes). During implementation, we encountered some ambiguities when applying it to Ruby. For example: + +- Should the list include only classes (pure inheritance chain), or should it include modules too (current behavior)? +- How should the inheritance chain of singleton classes be triggered and displayed? +- If a class or module is reopened multiple times, it will appear multiple times in the list. In real-world applications, this can make the list very long. + +We created [an issue](https://github.com/microsoft/language-server-protocol/issues/1984) to seek clarification from the LSP maintainers. We will adjust this feature's design and behavior based on their response and your feedback. + +### Guess Type + +The guess type feature is an experimental addition to Ruby LSP that attempts to identify the type of a receiver based on its identifier name. This helps improve code completion and navigation by providing type information. + +This feature is disabled by default but can be enabled with the `rubyLsp.enableExperimentalFeatures` setting in VS Code. + +#### How It Works + +Ruby LSP guesses the type of a variable by matching its identifier name to a class. For example, a variable named `user` would be assigned the `User` type if such a class exists: + +```ruby +user.name # Guessed to be of type `User` +@post.like! # Guessed to be of type `Post` +``` + +By guessing the types of variables, Ruby LSP can expand the code navigation features to even more cases. + +#### Important Notes + +- Identifiers are not ideal for complex type annotations and can be easily misled by non-matching names. +- We do NOT recommend renaming identifiers just to make this feature work. + +For more information, please refer to the [documentation](https://github.com/Shopify/ruby-lsp/blob/main/DESIGN_AND_ROADMAP.md#guessed-types). + +## Configuration + +### Configuring code indexing + +By default, the Ruby LSP indexes all Ruby files defined in the current project and all of its dependencies, including +default gems, except for + +- Gems that only appear under the `:development` group +- All Ruby files under `test/**/*.rb` + +This behaviour can be overridden and tuned. Learn how to configure it [for VS Code](https://github.com/Shopify/ruby-lsp/tree/main/vscode#indexing-configuration). + +Note that indexing-dependent behavior, such as definition, hover, completion or workspace symbol will be impacted by +the configuration changes. + +The older approach of using a `.index.yml` file has been deprecated and will be removed in a future release. + +```yaml +# Exclude files based on a given pattern. Often used to exclude test files or fixtures +excluded_patterns: + - "**/spec/**/*.rb" + +# Include files based on a given pattern. Can be used to index Ruby files that use different extensions +included_patterns: + - "**/bin/*" + +# Exclude gems by name. If a gem is never referenced in the project's code and is only used as a tool, excluding it will +# speed up indexing and reduce the amount of results in features like definition or completion +excluded_gems: + - rubocop + - pathname + +# Include gems by name. Normally used to include development gems that are excluded by default +included_gems: + - prism +``` + +## Additional Resources + +* [RubyConf 2022: Improving the development experience with language servers](https://www.youtube.com/watch?v=kEfXPTm1aCI) ([Vinicius Stock](https://github.com/vinistock)) +* [Remote Ruby: Ruby Language Server with Vinicius Stock](https://remoteruby.com/221) +* [RubyKaigi 2023: Code indexing - How language servers understand our code](https://www.youtube.com/watch?v=ks3tQojSJLU) ([Vinicius Stock](https://github.com/vinistock)) diff --git a/sorbet/config b/sorbet/config index 255ce1452e..8e0371cb5b 100644 --- a/sorbet/config +++ b/sorbet/config @@ -4,4 +4,5 @@ --ignore=tmp/ --ignore=test/fixtures/ --ignore=test/expectations/ +--ignore=jekyll/ --enable-experimental-requires-ancestor