File: vscode-extension.markdown

package info (click to toggle)
ruby-ruby-lsp 0.26.7-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 27,676 kB
  • sloc: ruby: 35,294; javascript: 29; sh: 7; makefile: 4
file content (485 lines) | stat: -rw-r--r-- 19,024 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
---
layout: default
title: VS Code extension
nav_order: 5
parent: Ruby LSP
---

# Ruby LSP

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.

## Features

<video src="images/ruby_lsp_demo.mp4" width="100%" controls>
Sorry, your browser doesn't support embedded videos. This video provides a quick overview of Ruby LSP features inside VS Code.
</video>

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
- Showing documentation on hover
- Completion
- Fuzzy search declarations anywhere in the project (workspace symbol)
- Running Rails generators from the UI

See complete information about features [here](https://shopify.github.io/ruby-lsp).

If you experience issues, please see the [troubleshooting
guide](troubleshooting).

### [Experimental] GitHub Copilot chat agent

For users of Copilot, the Ruby LSP contributes a Ruby agent for AI assisted development of Ruby applications. Below you
can find the documentation of each command for the Ruby agent. For information about how to interact with Copilot Chat,
check [VS Code's official documentation](https://code.visualstudio.com/docs/copilot/copilot-chat).

#### Design command

The `@ruby /design` command is intended to be a domain driven design expert to help users model concepts for their Rails
applications. Users should describe what type of application they are building and which concept they are trying to
model. The command will read their Rails application's schema and use their prompt, previous interactions and the schema
information to provide suggestions of how to design the application. For example,

```
@ruby /design I'm working on a web application for schools.
How do I model courses? And how do they relate to students?
```

The output is a suggested schema for courses including relationships with users. In the chat window, two buttons will appear: `Generate with Rails`, which invokes the Rails generators to create the models suggested, and `Revert previous generation`, which will delete files generated by a previous click in the generate button.

As with most LLM chat functionality, suggestions may not be fully accurate, especially in the first iteration. Users can
continue chatting with the `@ruby` agent to fine tune the suggestions given, before deciding to move forward with
generation.

If you have feedback about this feature, you can let us know in the [DX Slack](invite) or by [creating an issue](https://github.com/Shopify/ruby-lsp/issues/new).

## Usage

Search for `Shopify.ruby-lsp` in the extensions tab and click install.

By default, the Ruby LSP will generate a `.ruby-lsp` directory with a composed bundle that includes the server gem.
Additionally, it will attempt to use available version managers to select the correct Ruby version for any given
project. Refer to configuration for more options.

### Commands

Available commands are listed below and can always be found by searching for the `Ruby LSP` prefix in the command
palette (Default hotkey: CMD + SHIFT + P).

| Command                              | Description                                             |
| ------------------------------------ | ------------------------------------------------------- |
| Ruby LSP: Start                      | Start the Ruby LSP server                               |
| Ruby LSP: Restart                    | Restart the Ruby LSP server                             |
| Ruby LSP: Stop                       | Stop the Ruby LSP server                                |
| Ruby LSP: Update language server gem | Updates the `ruby-lsp` server gem to the latest version |

### Snippets

This extension provides convenience snippets for common Ruby constructs, such as blocks, classes, methods or even unit
test boilerplates. Find the full list [here](https://github.com/Shopify/ruby-lsp/blob/main/vscode/snippets.json).

### Configuration

#### Enable or disable features

The Ruby LSP allows disabling specific features. To do so, open the
language status center right next to the language mode Ruby and select `Manage` right next to enabled features.

![Ruby LSP status center](images/ruby_lsp_status_center.png)

#### Ruby version managers

To boot the server properly, the Ruby LSP uses a version manager to activate the right environment variables that point
Bundler to the Ruby and gem paths. This is especially necessary when switching between projects that use different Ruby
versions - since those paths change and need to be reactivated.

By default, the Ruby LSP will attempt to automatically determine which version manager it should use, checking which
ones are available (`auto` option). If that fails, then the version manager must be manually configured. You can do so
by clicking `Change version manager` in the language status center or by changing your VS Code user settings.

```jsonc
// Available options are
// "auto" (select version manager automatically)
// "none" (do not use a version manager)
// "custom" (use rubyLsp.customRubyCommand for finding/activating Ruby)
// "asdf"
// "chruby"
// "rbenv"
// "rvm"
// "shadowenv"
// "mise"
{
  "rubyLsp.rubyVersionManager": {
    "identifier": "chruby",
  },
}
```

To make sure that the Ruby LSP can find the version manager scripts, make sure that they are loaded in the shell's
configuration script (e.g.: ~/.bashrc, ~/.zshrc) and that the SHELL environment variable is set and pointing to the
default shell.

{: .note }
> For manager-specific notes, setting up custom activation for managers not listed above and community-contributed
> examples, please see [version managers](version-managers).

#### Configuring a formatter

The tool to be used for formatting files can be configured with the following setting.

```jsonc
// Available options
//    auto: automatically detect the formatter based on the app's bundle (default)
//    none: do not use a formatter (disables format on save and related diagnostics)
//    all other options are the name of the formatter (e.g.: rubocop or syntax_tree)
"rubyLsp.formatter": "auto"
```

#### Ruby version requirement

By default, the Ruby LSP uses the current project's Ruby version and bundle. This allows the LSP to index the correct
gem versions, and to ensure formatting behavior is consistent with CI.

The Ruby LSP and its main dependency [Prism](https://github.com/ruby/prism) (the new Ruby parser) both follow the same
policy, which is to support only Ruby versions that are not beyond their end-of-life.

If you're working on a project with an older Ruby version, it might be possible to install older versions of the server
gem to get support for older rubies, but that might also involve using older versions of the VS Code extension - since
some functionality requires implementations in both client and server.

The other alternative is to use a custom Gemfile separate from the project with a different Ruby version. Notice that
certain functionality may be degraded or require manual configuration, since the Ruby LSP will not be able to inspect
the project's real bundle to discover dependencies. Please see the instructions below.

#### Using a custom Gemfile

If you are working on a project using an older version of Ruby not supported by Ruby LSP, then you may specify a
separate `Gemfile` for development tools.

**Note**: when using this, gems will not be installed automatically and neither will `ruby-lsp` upgrades.

Create a directory to store the composed bundle outside of the project that uses the old Ruby version. Inside that
directory, add your preferred version manager configuration to select a supported Ruby version. For example, if using
`chruby`, it would look like this:

```shell
# the/directory/.ruby-version

3.2.2
```

Create a `Gemfile` for development tools inside that directory.

```ruby
# the/directory/Gemfile

source "https://rubygems.org"

gem "ruby-lsp"
gem "rubocop"
```

{: .note }
> Take in mind that formatters, linters and their extensions should be included in the custom gemfile; you might need to add more gems than the ones shown above.
> e.g: If you are using rubocop, you would also need to add them:

```ruby
gem "rubocop-packaging"
gem "rubocop-performance"
gem "rubocop-rspec"
gem "rubocop-shopify"
gem "rubocop-thread_safety"
```

Run `bundle install` inside that directory to generate a lockfile. After the directory contains the custom `Gemfile` and
the version manager configuration, use the following configuration in VS Code to point the Ruby LSP to that `Gemfile`.

```jsonc
{
  "rubyLsp.bundleGemfile": "../../path/to/the/directory/Gemfile",
}
```

{: .note }
> `rubyLsp.bundleGemfile` can be a relative or absolute path.

#### Configuring VS Code debugger

To configure the VS Code debugger, you can use the "Debug: Add configuration..." command to create a `launch.json` file
in the `.vscode` directory of your project.

This command would generate the following configuration:

```jsonc
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "ruby_lsp",
      "name": "Debug",
      "request": "launch",
      "program": "ruby ${file}",
    },
    {
      "type": "ruby_lsp",
      "request": "launch",
      "name": "Debug test file",
      "program": "ruby -Itest ${relativeFile}",
    },
    {
      "type": "ruby_lsp",
      "request": "attach",
      "name": "Attach to existing server",
    },
  ],
}
```

### Debugging live processes

Instead of launching a process to debug every time, you may want to attach the VS Code debugger to an existing process, such as a Rails server. Follow these instructions to do so.

Install `debug` gem. Verify by running `bundle exec rdbg -v`

Run your application with the debugger attached, so that the extension can connect to it.

```shell
bundle exec rdbg -O -n -c -- bin/rails server -p 3000
```

For better integrated rails tests support also install `ruby-lsp-rails` gem.

#### VS Code configurations

In addition to the Ruby LSP's own configuration, there are some VS Code settings that may need to be changed to get the
most of the Ruby LSP. These settings are not specific to the Ruby LSP, but they impact all language servers and take
precedence over any other configurations.

These are the settings that may impact the Ruby LSP's behavior and their explanations.

```jsonc
{
  // All of these settings are scoped only to the Ruby language
  "[ruby]": {
    "editor.defaultFormatter": "Shopify.ruby-lsp", // Use the Ruby LSP as the default formatter
    "editor.formatOnSave": true, // Format files automatically when saving
    "editor.tabSize": 2, // Use 2 spaces for indentation
    "editor.insertSpaces": true, // Use spaces and not tabs for indentation
    "editor.semanticHighlighting.enabled": true, // Enable semantic highlighting
    "editor.formatOnType": true, // Enable formatting while typing
  },
}
```

### Multi-root workspaces

Multi-root workspaces are VS Code's way to allow users to organize a single repository into multiple distinct concerns.
Notice that this does not necessarily match the concept of a project. For example, a web application with separate
directories for its frontend and backend may be conceptually considered as a single project, but you can still configure
the frontend and backend directories to be different workspaces.

The advantage of adopting this configuration is that VS Code and all extensions are informed about which directories
should be considered as possible workspace roots. Instead of having to configure each extension or tool individually so
they are aware of your project structure, you only have to do that once for the entire repository.

Some examples of functionality that benefits from multi-root workspaces:

- Extensions that have to integrate with project dependencies (Gemfile, package.json), such as debuggers, language
  servers, formatters and other tools, are informed about where to search for these files (allowing for automatic
  detection)
- If `launch.json` configurations are placed inside a workspace, VS Code will know to launch them from the appropriate
  directory ([Ruby LSP example](https://github.com/Shopify/ruby-lsp/blob/main/vscode/.vscode/launch.json)), without
  requiring you to specify the `cwd`
- When opening a terminal, VS Code will offer to open the terminal on all configured workspaces

The Ruby LSP supports multi-root workspaces by spawning a separate language server for each one of them. This strategy
is preferred over a single language server that supports multiple workspaces because each workspace could be using a
different Ruby version and completely different gems - which would be impossible to support in a single Ruby process.

What matters to properly spawn the Ruby LSP is knowing where the main Gemfile of each workspace inside of the same
repository is.

#### Example configurations

{: .note }
> To make sure Ruby LSP works well with your multi-root workspace project, please
> read through the instructions below and configure it following the examples.
> After configuring, do not forget to tell VS Code to open the workspace from the
> code-workspace file

Consider a project where the top level of the repository is a Rails application and a sub-directory called `frontend`
contains a React application that implements the frontend layer.

```
my_project/
  frontend/
  Gemfile
  Gemfile.lock
  config.ru
  super_awesome_project.code-workspace
```

A possible configuration for the `super_awesome_project` would be this:

```jsonc
{
  "folders": [
    // At the top level of the repository, we have the Rails application
    {
      "name": "rails",
      "path": ".",
    },
    // Inside the frontend directory, we have the React frontend
    {
      "name": "react",
      "path": "frontend",
    },
  ],
  "settings": {
    // To avoid having VS Code display the same files twice, we can simply exclude the frontend sub-directory. This
    // means it will only show up as a separate workspace
    "files.exclude": {
      "frontend": true,
    },
  },
}
```

Now consider a monorepo where both the client and the server are under sub-directories.

```
my_project/
  client/
  server/
    Gemfile
    Gemfile.lock
  super_awesome_project.code-workspace
```

In this case, we can configure the workspaces as:

```jsonc
{
  "folders": [
    // Both parts of the project (client and server) are inside sub-directories. But since the top level might contain
    // some documentation or build files, we still want it to show up
    {
      "name": "awesome_project",
      "path": ".",
    },
    // Inside the client directory, we have the client part of the project
    {
      "name": "client",
      "path": "client",
    },
    // Inside the server directory, we have the server part of the project
    {
      "name": "server",
      "path": "server",
    },
  ],
  "settings": {
    // We don't want to show duplicates, so we hide the directories that are already showing up as workspaces
    "files.exclude": {
      "server": true,
      "client": true,
    },
  },
}
```

For more information, read VS Code's [workspace documentation](https://code.visualstudio.com/docs/editor/workspaces) and
[multi-root workspace documentation](https://code.visualstudio.com/docs/editor/workspaces#_multiroot-workspaces).

### Developing on containers

The Ruby LSP is a detached language server, which means it's a background process that runs separately from the VS Code
instance. To provide its functionality, the Ruby LSP must be running in the same place where your project files exist
and dependencies are installed.

VS Code supports connecting to containers out of the box, which makes all editor features work seamlessly. That includes
language servers, the integrated terminal, etc. The VS Code documentation has instructions on how to develop on
containers locally or remotely. Please check the following resources before opening an issue:

- [Developing inside a Container](https://code.visualstudio.com/docs/devcontainers/containers)
- [Advanced container configuration](https://code.visualstudio.com/remote/advancedcontainers/overview)

Please note that only Docker is officially supported as a backend by the Dev Container extension. <sup>[1](https://code.visualstudio.com/remote/advancedcontainers/docker-options)</sup>

## Telemetry

The Ruby LSP does not collect any telemetry by default, but it supports hooking up to a private metrics service if
desired. This can be useful if you'd like to understand adoption, performance or catch errors of the Ruby LSP within
your team or company.

To collect metrics, another VS Code extension (typically a private one) should define the command
`getTelemetrySenderObject`. This command should return an object that implements the
[vscode.TelemetrySender](https://code.visualstudio.com/api/references/vscode-api#TelemetrySender) interface, thus
defining where data and error reports should be sent to. For example:

```typescript
// Your private VS Code extension

class Telemetry implements vscode.TelemetrySender {
  constructor() {
    // Initialize some API service or whatever is needed to collect metrics
  }

  sendEventData(eventName: string, data: EventData): void {
    // Send events to some API or accumulate them to be sent in batch when `flush` is invoked by VS Code
  }

  sendErrorData(error: Error, data?: Record<string, any> | undefined): void {
    // Send errors to some API or accumulate them to be sent in batch when `flush` is invoked by VS Code
  }

  async flush() {
    // Optional function to flush accumulated events and errors
  }
}

export async function activate(context: vscode.ExtensionContext) {
  const telemetry = new Telemetry();
  await telemetry.activate();

  // Register the command that the Ruby LSP will search for to hook into
  context.subscriptions.push(
    vscode.commands.registerCommand("getTelemetrySenderObject", () => {
      return telemetry;
    }),
  );
}
```

## Formatting

When `rubyLsp.formatter` is set to `auto`, Ruby LSP tries to determine which formatter to use.

If the bundle has a **direct** dependency on a supported formatter, such as `rubocop` or `syntax_tree`, that will be used.
Otherwise, formatting will be disabled and you will need add one to the bundle. Using globally installed formatters or
linters is not supported, they must in your Gemfile or gemspec.

## Indexing Configuration

To configure indexing, pass a JSON hash as part of the Ruby LSP configuration, for example:

```jsonc
// PROJECT/.vscode/settings.json
{
  "rubyLsp.indexing": {
    "excludedPatterns": ["**/test/**/*.rb"],
    "includedPatterns": ["**/bin/**/*"],
    "excludedGems": ["rubocop", "rubocop-performance"],
    "excludedMagicComments": ["compiled:true"],
  },
}
```