ruby-lsp 0.0.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -0
  3. data/.rubocop.yml +25 -0
  4. data/CHANGELOG.md +35 -0
  5. data/Gemfile +10 -6
  6. data/Gemfile.lock +63 -16
  7. data/README.md +41 -0
  8. data/Rakefile +8 -1
  9. data/VERSION +1 -1
  10. data/bin/console +19 -0
  11. data/bin/tapioca +29 -0
  12. data/dev.yml +3 -0
  13. data/exe/ruby-lsp +19 -4
  14. data/lib/ruby-lsp.rb +2 -1
  15. data/lib/ruby_lsp/cli.rb +13 -5
  16. data/lib/ruby_lsp/document.rb +43 -14
  17. data/lib/ruby_lsp/handler.rb +107 -37
  18. data/lib/ruby_lsp/internal.rb +7 -0
  19. data/lib/ruby_lsp/requests/base_request.rb +18 -5
  20. data/lib/ruby_lsp/requests/code_actions.rb +20 -8
  21. data/lib/ruby_lsp/requests/diagnostics.rb +25 -7
  22. data/lib/ruby_lsp/requests/document_highlight.rb +113 -0
  23. data/lib/ruby_lsp/requests/document_symbol.rb +56 -16
  24. data/lib/ruby_lsp/requests/folding_ranges.rb +70 -34
  25. data/lib/ruby_lsp/requests/formatting.rb +24 -14
  26. data/lib/ruby_lsp/requests/selection_ranges.rb +18 -4
  27. data/lib/ruby_lsp/requests/semantic_highlighting.rb +187 -34
  28. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +16 -3
  29. data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +61 -0
  30. data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +50 -0
  31. data/lib/ruby_lsp/requests/support/selection_range.rb +4 -0
  32. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +24 -3
  33. data/lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb +6 -0
  34. data/lib/ruby_lsp/requests.rb +13 -1
  35. data/lib/ruby_lsp/store.rb +20 -3
  36. data/rakelib/check_docs.rake +34 -6
  37. data/ruby-lsp.gemspec +7 -5
  38. data/sorbet/config +4 -0
  39. data/sorbet/rbi/.rubocop.yml +8 -0
  40. data/sorbet/rbi/gems/ansi@1.5.0.rbi +338 -0
  41. data/sorbet/rbi/gems/ast@2.4.2.rbi +522 -0
  42. data/sorbet/rbi/gems/builder@3.2.4.rbi +418 -0
  43. data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
  44. data/sorbet/rbi/gems/debug@1.5.0.rbi +1273 -0
  45. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +867 -0
  46. data/sorbet/rbi/gems/io-console@0.5.11.rbi +8 -0
  47. data/sorbet/rbi/gems/irb@1.4.1.rbi +376 -0
  48. data/sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi +7325 -0
  49. data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
  50. data/sorbet/rbi/gems/minitest-reporters@1.5.0.rbi +612 -0
  51. data/sorbet/rbi/gems/minitest@5.15.0.rbi +994 -0
  52. data/sorbet/rbi/gems/parallel@1.22.1.rbi +163 -0
  53. data/sorbet/rbi/gems/parser@3.1.2.0.rbi +3968 -0
  54. data/sorbet/rbi/gems/prettier_print@0.1.0.rbi +734 -0
  55. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  56. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +227 -0
  57. data/sorbet/rbi/gems/rake@13.0.6.rbi +1853 -0
  58. data/sorbet/rbi/gems/rbi@0.0.14.rbi +2337 -0
  59. data/sorbet/rbi/gems/regexp_parser@2.5.0.rbi +1854 -0
  60. data/sorbet/rbi/gems/reline@0.3.1.rbi +1274 -0
  61. data/sorbet/rbi/gems/rexml@3.2.5.rbi +3852 -0
  62. data/sorbet/rbi/gems/rubocop-ast@1.18.0.rbi +4180 -0
  63. data/sorbet/rbi/gems/rubocop-minitest@0.20.0.rbi +1369 -0
  64. data/sorbet/rbi/gems/rubocop-rake@0.6.0.rbi +246 -0
  65. data/sorbet/rbi/gems/rubocop-shopify@2.6.0.rbi +8 -0
  66. data/sorbet/rbi/gems/rubocop-sorbet@0.6.8.rbi +652 -0
  67. data/sorbet/rbi/gems/rubocop@1.30.0.rbi +36729 -0
  68. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +732 -0
  69. data/sorbet/rbi/gems/spoom@1.1.11.rbi +1600 -0
  70. data/sorbet/rbi/gems/syntax_tree@2.7.1.rbi +6777 -0
  71. data/sorbet/rbi/gems/tapioca@0.8.1.rbi +1972 -0
  72. data/sorbet/rbi/gems/thor@1.2.1.rbi +2921 -0
  73. data/sorbet/rbi/gems/unicode-display_width@2.1.0.rbi +27 -0
  74. data/sorbet/rbi/gems/unparser@0.6.5.rbi +2789 -0
  75. data/sorbet/rbi/gems/webrick@1.7.0.rbi +1779 -0
  76. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +289 -0
  77. data/sorbet/rbi/gems/yard@0.9.27.rbi +13048 -0
  78. data/sorbet/rbi/shims/fiddle.rbi +4 -0
  79. data/sorbet/rbi/shims/hash.rbi +6 -0
  80. data/sorbet/rbi/shims/rdoc.rbi +4 -0
  81. data/sorbet/tapioca/config.yml +13 -0
  82. data/sorbet/tapioca/require.rb +7 -0
  83. metadata +62 -13
  84. data/lib/ruby_lsp/requests/rubocop_request.rb +0 -49
  85. data/shipit.production.yml +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58ed87185da0a5d1da74b10f1525f1ca1341f1001f3a4cbdf2b086dd93750ad9
4
- data.tar.gz: 1210f736e4cd8450cbe1e1d796dbd22a889c244c6ea5902bc6082f3791064ddc
3
+ metadata.gz: f81baa8f09011e5130c955c4c5d2a33583379b0b073caee556719b874efc320e
4
+ data.tar.gz: 55a664f923d93bda9ddb06624303f889123496c672c46b31ea71c629cfa96a81
5
5
  SHA512:
6
- metadata.gz: a1ed47a3e4d53dbf5250beaa98b3095c89099e67829f2ecac3149b34ecc87ae579c67ed6cd67035ee9930c0fffa0db6c0d4fdc3c3398520196005b180f28ea6f
7
- data.tar.gz: 18d07a7c5426fa8cfad11cfab44dbabf05fd3a1352f1bf9272b04fb35c78f0bb0b4860dd4b7bbfda89efb9cfa99fc3ef77fbb679ff2b21bbd4cffb3c53a14bd5
6
+ metadata.gz: 8a872f34699bfaa4f955c714c4e49eed52e87b009afc0a642d0ad434956f6a14690188ad9c359cc7aadd53e96fbd0d5d320e00aa263265e1ce3d3e369e8bd124
7
+ data.tar.gz: 06444ea3e08b961445db6cb1a9093fc322b40ddf47daa00deb09a77f3b114014be8f525d7d391430b578b7916042bf345759d113c74e41a8ea51d65791abe69c
@@ -17,9 +17,15 @@ jobs:
17
17
  with:
18
18
  ruby-version: ${{ matrix.ruby }}
19
19
  bundler-cache: true
20
+
20
21
  - name: Check if documentation is up to date
21
22
  run: bundle exec rake check_docs
23
+
24
+ - name: Typecheck
25
+ run: bundle exec srb tc
26
+
22
27
  - name: Lint Ruby files
23
28
  run: bin/rubocop
29
+
24
30
  - name: Run tests
25
31
  run: bin/test
data/.rubocop.yml CHANGED
@@ -1,6 +1,11 @@
1
1
  inherit_gem:
2
2
  rubocop-shopify: rubocop.yml
3
3
 
4
+ require:
5
+ - rubocop-sorbet
6
+ - rubocop-minitest
7
+ - rubocop-rake
8
+
4
9
  AllCops:
5
10
  NewCops: disable
6
11
  SuggestExtensions: false
@@ -8,7 +13,27 @@ AllCops:
8
13
  Exclude:
9
14
  - "vendor/**/*"
10
15
  - "features/**/*"
16
+ - "test/fixtures/**/*"
11
17
 
12
18
  Naming/FileName:
13
19
  Exclude:
14
20
  - "lib/ruby-lsp.rb"
21
+
22
+ Sorbet/FalseSigil:
23
+ Enabled: false
24
+
25
+ Sorbet/TrueSigil:
26
+ Enabled: true
27
+ Include:
28
+ - "test/**/*.rb"
29
+ Exclude:
30
+ - "**/*.rake"
31
+ - "lib/**/*.rb"
32
+
33
+ Sorbet/StrictSigil:
34
+ Enabled: true
35
+ Include:
36
+ - "lib/**/*.rb"
37
+ Exclude:
38
+ - "**/*.rake"
39
+ - "test/**/*.rb"
data/CHANGELOG.md CHANGED
@@ -6,6 +6,41 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.2.0]
10
+
11
+ - Add semantic token for keyword and keyword rest params (https://github.com/Shopify/ruby-lsp/pull/142)
12
+ - Return error responses on exceptions (https://github.com/Shopify/ruby-lsp/pull/160)
13
+ - Sanitize home directory for telemetry (https://github.com/Shopify/ruby-lsp/pull/171)
14
+ - Avoid adding semantic tokens for special methods (https://github.com/Shopify/ruby-lsp/pull/162)
15
+ - Properly respect excluded files in RuboCop requests (https://github.com/Shopify/ruby-lsp/pull/173)
16
+ - Clear diagnostics when closing files (https://github.com/Shopify/ruby-lsp/pull/174)
17
+ - Avoid pushing ranges for single line partial ranges (https://github.com/Shopify/ruby-lsp/pull/185)
18
+ - Change folding ranges to include closing tokens (https://github.com/Shopify/ruby-lsp/pull/181)
19
+ - Remove RuboCop dependency and fallback to SyntaxTree formatting (https://github.com/Shopify/ruby-lsp/pull/184)
20
+
21
+ ## [0.1.0]
22
+
23
+ - Implement token modifiers in SemanticTokenEncoder ([#112](https://github.com/Shopify/ruby-lsp/pull/112))
24
+ - Add semantic token for name in a method definition ([#133](https://github.com/Shopify/ruby-lsp/pull/133))
25
+ - Add semantic highighting for def endless and singleton method names ([#134](https://github.com/Shopify/ruby-lsp/pull/134))
26
+ - Add semantic token for keyword self ([#137](https://github.com/Shopify/ruby-lsp/pull/137))
27
+ - Add semantic token for constants ([#138](https://github.com/Shopify/ruby-lsp/pull/138))
28
+ - Improve error handling + fix formatting hanging issue ([#149](https://github.com/Shopify/ruby-lsp/pull/149))
29
+ - Set the minimum syntax_tree version to 2.4 ([#151](https://github.com/Shopify/ruby-lsp/pull/151))
30
+
31
+ ## [0.0.4]
32
+
33
+ - Add basic document highlight (https://github.com/Shopify/ruby-lsp/pull/91)
34
+ - Add error telemetry (https://github.com/Shopify/ruby-lsp/pull/100)
35
+ - Always push telemetry events from the server (https://github.com/Shopify/ruby-lsp/pull/109)
36
+ - Fix multibyte character handling (https://github.com/Shopify/ruby-lsp/pull/122)
37
+ - Add Sorbet to the Ruby LSP (https://github.com/Shopify/ruby-lsp/pull/119, https://github.com/Shopify/ruby-lsp/pull/123)
38
+
39
+ ## [0.0.3]
40
+
41
+ - Fixed code actions return hanging
42
+ - Moved to incremental text synchronization
43
+ - Added syntax error resiliency
9
44
 
10
45
  ## [0.0.2]
11
46
 
data/Gemfile CHANGED
@@ -4,11 +4,15 @@ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
 
7
- gem "debug", "~> 1.5"
8
- gem "minitest", "~> 5.15"
7
+ gem "debug", "~> 1.5", require: false
8
+ gem "minitest", "~> 5.16"
9
9
  gem "minitest-reporters", "~> 1.5"
10
10
  gem "rake", "~> 13.0"
11
- gem "rubocop-shopify", "~> 2.6"
12
- gem "rubocop-minitest", "~> 0.19.1"
13
- gem "rubocop-rake", "~> 0.6.0"
14
- gem "yard", "~> 0.9"
11
+ gem "rubocop", ">= 1.0.0"
12
+ gem "rubocop-shopify", "~> 2.8", require: false
13
+ gem "rubocop-minitest", "~> 0.20.1", require: false
14
+ gem "rubocop-rake", "~> 0.6.0", require: false
15
+ gem "rubocop-sorbet", "~> 0.6", require: false
16
+ gem "sorbet-static-and-runtime"
17
+ gem "tapioca", "~> 0.8", require: false
18
+ gem "yard", "~> 0.9", require: false
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ruby-lsp (0.0.3)
4
+ ruby-lsp (0.2.0)
5
5
  language_server-protocol
6
- rubocop (>= 1.0)
7
- syntax_tree (>= 2.3)
6
+ sorbet-runtime
7
+ syntax_tree (>= 2.4)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
@@ -12,14 +12,18 @@ GEM
12
12
  ansi (1.5.0)
13
13
  ast (2.4.2)
14
14
  builder (3.2.4)
15
+ coderay (1.1.3)
15
16
  debug (1.5.0)
16
17
  irb (>= 1.3.6)
17
18
  reline (>= 0.2.7)
19
+ diff-lcs (1.5.0)
18
20
  io-console (0.5.11)
19
21
  irb (1.4.1)
20
22
  reline (>= 0.3.0)
23
+ json (2.6.2)
21
24
  language_server-protocol (3.16.0.3)
22
- minitest (5.15.0)
25
+ method_source (1.0.0)
26
+ minitest (5.16.2)
23
27
  minitest-reporters (1.5.0)
24
28
  ansi
25
29
  builder
@@ -29,36 +33,75 @@ GEM
29
33
  parser (3.1.2.0)
30
34
  ast (~> 2.4.1)
31
35
  prettier_print (0.1.0)
36
+ pry (0.14.1)
37
+ coderay (~> 1.1)
38
+ method_source (~> 1.0)
32
39
  rainbow (3.1.1)
33
40
  rake (13.0.6)
34
- regexp_parser (2.4.0)
41
+ rbi (0.0.15)
42
+ ast
43
+ parser (>= 2.6.4.0)
44
+ sorbet-runtime (>= 0.5.9204)
45
+ unparser
46
+ regexp_parser (2.5.0)
35
47
  reline (0.3.1)
36
48
  io-console (~> 0.5)
37
49
  rexml (3.2.5)
38
- rubocop (1.29.1)
50
+ rubocop (1.31.1)
51
+ json (~> 2.3)
39
52
  parallel (~> 1.10)
40
53
  parser (>= 3.1.0.0)
41
54
  rainbow (>= 2.2.2, < 4.0)
42
55
  regexp_parser (>= 1.8, < 3.0)
43
56
  rexml (>= 3.2.5, < 4.0)
44
- rubocop-ast (>= 1.17.0, < 2.0)
57
+ rubocop-ast (>= 1.18.0, < 2.0)
45
58
  ruby-progressbar (~> 1.7)
46
59
  unicode-display_width (>= 1.4.0, < 3.0)
47
60
  rubocop-ast (1.18.0)
48
61
  parser (>= 3.1.1.0)
49
- rubocop-minitest (0.19.1)
62
+ rubocop-minitest (0.20.1)
50
63
  rubocop (>= 0.90, < 2.0)
51
64
  rubocop-rake (0.6.0)
52
65
  rubocop (~> 1.0)
53
- rubocop-shopify (2.6.0)
54
- rubocop (~> 1.29)
66
+ rubocop-shopify (2.8.0)
67
+ rubocop (~> 1.31)
68
+ rubocop-sorbet (0.6.11)
69
+ rubocop (>= 0.90.0)
55
70
  ruby-progressbar (1.11.0)
56
- syntax_tree (2.7.1)
71
+ sorbet (0.5.10139)
72
+ sorbet-static (= 0.5.10139)
73
+ sorbet-runtime (0.5.10139)
74
+ sorbet-static (0.5.10139-universal-darwin-21)
75
+ sorbet-static (0.5.10139-x86_64-linux)
76
+ sorbet-static-and-runtime (0.5.10139)
77
+ sorbet (= 0.5.10139)
78
+ sorbet-runtime (= 0.5.10139)
79
+ spoom (1.1.11)
80
+ sorbet (>= 0.5.9204)
81
+ sorbet-runtime (>= 0.5.9204)
82
+ thor (>= 0.19.2)
83
+ syntax_tree (2.8.0)
57
84
  prettier_print
58
- unicode-display_width (2.1.0)
85
+ tapioca (0.8.3)
86
+ bundler (>= 1.17.3)
87
+ parallel (>= 1.21.0)
88
+ pry (>= 0.12.2)
89
+ rbi (~> 0.0.0, >= 0.0.14)
90
+ sorbet-static-and-runtime (>= 0.5.9204)
91
+ spoom (~> 1.1.0, >= 1.1.11)
92
+ thor (>= 1.2.0)
93
+ yard-sorbet
94
+ thor (1.2.1)
95
+ unicode-display_width (2.2.0)
96
+ unparser (0.6.5)
97
+ diff-lcs (~> 1.3)
98
+ parser (>= 3.1.0)
59
99
  webrick (1.7.0)
60
- yard (0.9.27)
100
+ yard (0.9.28)
61
101
  webrick (~> 1.7.0)
102
+ yard-sorbet (0.6.1)
103
+ sorbet-runtime (>= 0.5)
104
+ yard (>= 0.9)
62
105
 
63
106
  PLATFORMS
64
107
  arm64-darwin-21
@@ -66,13 +109,17 @@ PLATFORMS
66
109
 
67
110
  DEPENDENCIES
68
111
  debug (~> 1.5)
69
- minitest (~> 5.15)
112
+ minitest (~> 5.16)
70
113
  minitest-reporters (~> 1.5)
71
114
  rake (~> 13.0)
72
- rubocop-minitest (~> 0.19.1)
115
+ rubocop (>= 1.0.0)
116
+ rubocop-minitest (~> 0.20.1)
73
117
  rubocop-rake (~> 0.6.0)
74
- rubocop-shopify (~> 2.6)
118
+ rubocop-shopify (~> 2.8)
119
+ rubocop-sorbet (~> 0.6)
75
120
  ruby-lsp!
121
+ sorbet-static-and-runtime
122
+ tapioca (~> 0.8)
76
123
  yard (~> 0.9)
77
124
 
78
125
  BUNDLED WITH
data/README.md CHANGED
@@ -17,6 +17,9 @@ end
17
17
  If using VS Code, install the [Ruby LSP plugin](https://github.com/Shopify/vscode-ruby-lsp) to get the extra features in
18
18
  the editor.
19
19
 
20
+ See the [documentation](https://shopify.github.io/ruby-lsp) for
21
+ [supported features](https://shopify.github.io/ruby-lsp/RubyLsp/Requests.html).
22
+
20
23
  ## Contributing
21
24
 
22
25
  Bug reports and pull requests are welcome on GitHub at https://github.com/Shopify/ruby-lsp.
@@ -25,6 +28,44 @@ are expected to adhere to the
25
28
  [Contributor Covenant](https://github.com/Shopify/ruby-lsp/blob/main/CODE_OF_CONDUCT.md)
26
29
  code of conduct.
27
30
 
31
+ ### Expectation testing
32
+
33
+ To simplify the way we run tests over different pieces of Ruby code, we use a custom expectations test framework against a set of Ruby fixtures.
34
+
35
+ To add a new fixture to the expectations test suite:
36
+
37
+ 1. Add a new fixture `my_fixture.rb` file under `test/fixtures`
38
+ 2. (optional) Add new expectations under `test/expectations/$HANDLER` for the request handlers you're concerned by
39
+ 3. Profit by running `bin/test test/requests/$HANDLER_expectations_test my_fixture`
40
+ * Handlers for which you added expectations will be checked with `assert_expectations`
41
+ * Handlers without expectations will be ran against your new test to check that nothing breaks
42
+
43
+ To add a new expectations test runner for a new request handler:
44
+
45
+ 1. Add a new file under `test/requests/$HANDLER_expectations_test.rb` that subclasses `ExpectationsTestRunner` and calls `expectations_tests $HANDLER, "$EXPECTATIONS_DIR"` where: `$HANDLER` is the fully qualified name or your handler class and `$EXPECTATIONS_DIR` is the directory name where you want to store the expectation files.
46
+
47
+ ```rb
48
+ # frozen_string_literal: true
49
+
50
+ require "test_helper"
51
+ require "expectations/expectations_test_runner"
52
+
53
+ class $HANDLERExpectationsTest < ExpectationsTestRunner
54
+ expectations_tests RubyLsp::Requests::$HANDLER, "$EXPECTATIONS_DIR"
55
+ end
56
+ ```
57
+
58
+ 2. (optional) Override the `run_expectations` and `assert_expectations` methods if needed. See the different request handler expectations runners under `test/requests/*_expectations_test.rb` for examples.
59
+
60
+ 4. (optional) Add new fixtures for your handler under `test/fixtures`
61
+
62
+ 5. (optional) Add new expectations under `test/expectations/$HANDLER`
63
+ * No need to write the expectations by hand, just run the test with an empty expectation file and copy from the output.
64
+
65
+ 7. Profit by running, `bin/test test/expectations_test $HANDLER`
66
+ * Tests with expectations will be checked with `assert_expectations`
67
+ * Tests without expectations will be ran against your new $HANDLER to check that nothing breaks
68
+
28
69
  ## Debugging
29
70
 
30
71
  ### Tracing LSP requests and responses
data/Rakefile CHANGED
@@ -11,7 +11,14 @@ Rake::TestTask.new(:test) do |t|
11
11
  end
12
12
 
13
13
  YARD::Rake::YardocTask.new do |t|
14
- t.options = ["--markup", "markdown", "--output-dir", "docs"]
14
+ t.options = [
15
+ "--markup",
16
+ "markdown",
17
+ "--output-dir",
18
+ "docs",
19
+ "--asset",
20
+ "misc",
21
+ ]
15
22
  end
16
23
 
17
24
  require "rubocop/rake_task"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.2.0
data/bin/console ADDED
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+ # typed: strict
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require_relative "../lib/ruby_lsp/internal"
7
+ require "irb"
8
+
9
+ extend T::Sig
10
+
11
+ sig { params(source: String).returns(RubyLsp::Document) }
12
+ def new_doc(source)
13
+ RubyLsp::Document.new(source)
14
+ end
15
+
16
+ @source = T.let(File.read(File.expand_path("../lib/ruby_lsp/handler.rb", __dir__)), String)
17
+ @document = T.let(new_doc(@source), RubyLsp::Document)
18
+
19
+ IRB.start(__FILE__)
data/bin/tapioca ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'tapioca' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("tapioca", "tapioca")
data/dev.yml CHANGED
@@ -10,6 +10,9 @@ up:
10
10
  commands:
11
11
  server: exe/ruby-lsp
12
12
  style: bin/rubocop
13
+ typecheck:
14
+ aliases: ["tc"]
15
+ run: "bundle exec srb tc"
13
16
  test:
14
17
  syntax:
15
18
  argument: file
data/exe/ruby-lsp CHANGED
@@ -1,8 +1,23 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require "syntax_tree"
5
- require "ruby-lsp"
6
- require "ruby_lsp/cli"
4
+ require "sorbet-runtime"
7
5
 
8
- RubyLsp::Cli.start(ARGV)
6
+ begin
7
+ T::Configuration.default_checked_level = :never
8
+ # Suppresses call validation errors
9
+ T::Configuration.call_validation_error_handler = ->(*) {}
10
+ # Suppresses errors caused by T.cast, T.let, T.must, etc.
11
+ T::Configuration.inline_type_error_handler = ->(*) {}
12
+ # Suppresses errors caused by incorrect parameter ordering
13
+ T::Configuration.sig_validation_error_handler = ->(*) {}
14
+ rescue
15
+ # Need this rescue so that if another gem has
16
+ # already set the checked level by the time we
17
+ # get to it, we don't fail outright.
18
+ nil
19
+ end
20
+
21
+ require_relative "../lib/ruby_lsp/internal"
22
+
23
+ RubyLsp::Cli.start
data/lib/ruby-lsp.rb CHANGED
@@ -1,5 +1,6 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
4
- VERSION = File.read(File.expand_path("../VERSION", __dir__)).strip
5
+ VERSION = T.let(File.read(File.expand_path("../VERSION", __dir__)).strip, String)
5
6
  end
data/lib/ruby_lsp/cli.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "language_server-protocol"
@@ -6,7 +7,10 @@ require_relative "handler"
6
7
 
7
8
  module RubyLsp
8
9
  module Cli
9
- def self.start(_argv)
10
+ extend T::Sig
11
+
12
+ sig { void }
13
+ def self.start
10
14
  handler = RubyLsp::Handler.new
11
15
 
12
16
  handler.config do
@@ -14,7 +18,6 @@ module RubyLsp
14
18
  store.clear
15
19
  initialization_options = request.dig(:params, :initializationOptions)
16
20
 
17
- configure_options(initialization_options)
18
21
  respond_with_capabilities(initialization_options.fetch(:enabledFeatures, []))
19
22
  end
20
23
 
@@ -23,7 +26,7 @@ module RubyLsp
23
26
  store.push_edits(uri, request.dig(:params, :contentChanges))
24
27
 
25
28
  send_diagnostics(uri)
26
- nil
29
+ RubyLsp::Handler::VOID
27
30
  end
28
31
 
29
32
  on("textDocument/didOpen") do |request|
@@ -32,14 +35,15 @@ module RubyLsp
32
35
  store.set(uri, text)
33
36
 
34
37
  send_diagnostics(uri)
35
- nil
38
+ RubyLsp::Handler::VOID
36
39
  end
37
40
 
38
41
  on("textDocument/didClose") do |request|
39
42
  uri = request.dig(:params, :textDocument, :uri)
40
43
  store.delete(uri)
44
+ clear_diagnostics(uri)
41
45
 
42
- nil
46
+ RubyLsp::Handler::VOID
43
47
  end
44
48
 
45
49
  on("textDocument/documentSymbol") do |request|
@@ -65,6 +69,10 @@ module RubyLsp
65
69
  respond_with_formatting(request.dig(:params, :textDocument, :uri))
66
70
  end
67
71
 
72
+ on("textDocument/documentHighlight") do |request|
73
+ respond_with_document_highlight(request.dig(:params, :textDocument, :uri), request.dig(:params, :position))
74
+ end
75
+
68
76
  on("textDocument/codeAction") do |request|
69
77
  range = request.dig(:params, :range)
70
78
  start_line = range.dig(:start, :line)
@@ -1,32 +1,54 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
- require "strscan"
4
-
5
4
  module RubyLsp
6
5
  class Document
7
- attr_reader :tree, :source, :syntax_error_edits
6
+ extend T::Sig
7
+
8
+ PositionShape = T.type_alias { { line: Integer, character: Integer } }
9
+ RangeShape = T.type_alias { { start: PositionShape, end: PositionShape } }
10
+ EditShape = T.type_alias { { range: RangeShape, text: String } }
11
+
12
+ sig { returns(SyntaxTree::Node) }
13
+ attr_reader :tree
14
+
15
+ sig { returns(String) }
16
+ attr_reader :source
8
17
 
18
+ sig { returns(T::Array[EditShape]) }
19
+ attr_reader :syntax_error_edits
20
+
21
+ sig { params(source: String).void }
9
22
  def initialize(source)
10
- @tree = SyntaxTree.parse(source)
11
- @cache = {}
12
- @syntax_error_edits = []
23
+ @tree = T.let(SyntaxTree.parse(source), SyntaxTree::Node)
24
+ @cache = T.let({}, T::Hash[Symbol, T.untyped])
25
+ @syntax_error_edits = T.let([], T::Array[EditShape])
13
26
  @source = source
14
- @parsable_source = source.dup
27
+ @parsable_source = T.let(source.dup, String)
15
28
  end
16
29
 
30
+ sig { params(other: Document).returns(T::Boolean) }
17
31
  def ==(other)
18
32
  @source == other.source
19
33
  end
20
34
 
21
- def cache_fetch(request_name)
35
+ sig do
36
+ type_parameters(:T)
37
+ .params(
38
+ request_name: Symbol,
39
+ block: T.proc.params(document: Document).returns(T.type_parameter(:T))
40
+ ).returns(T.type_parameter(:T))
41
+ end
42
+ def cache_fetch(request_name, &block)
22
43
  cached = @cache[request_name]
23
44
  return cached if cached
24
45
 
25
- result = yield(self)
46
+ result = block.call(self)
26
47
  @cache[request_name] = result
27
48
  result
28
49
  end
29
50
 
51
+ sig { params(edits: T::Array[EditShape]).void }
30
52
  def push_edits(edits)
31
53
  # Apply the edits on the real source
32
54
  edits.each { |edit| apply_edit(@source, edit[:range], edit[:text]) }
@@ -40,12 +62,14 @@ module RubyLsp
40
62
  update_parsable_source(edits)
41
63
  end
42
64
 
65
+ sig { returns(T::Boolean) }
43
66
  def syntax_errors?
44
67
  @syntax_error_edits.any?
45
68
  end
46
69
 
47
70
  private
48
71
 
72
+ sig { params(edits: T::Array[EditShape]).void }
49
73
  def update_parsable_source(edits)
50
74
  # If the new edits caused a syntax error, make all edits blank spaces and line breaks to adjust the line and
51
75
  # column numbers. This is attempt to make the document parsable while partial edits are being applied
@@ -61,6 +85,7 @@ module RubyLsp
61
85
  # If we can't parse the source even after emptying the edits, then just fallback to the previous source
62
86
  end
63
87
 
88
+ sig { params(source: String, range: RangeShape, text: String).void }
64
89
  def apply_edit(source, range, text)
65
90
  scanner = Scanner.new(source)
66
91
  start_position = scanner.find_position(range[:start])
@@ -70,20 +95,24 @@ module RubyLsp
70
95
  end
71
96
 
72
97
  class Scanner
98
+ extend T::Sig
99
+
100
+ sig { params(source: String).void }
73
101
  def initialize(source)
102
+ @current_line = T.let(0, Integer)
103
+ @pos = T.let(0, Integer)
74
104
  @source = source
75
- @scanner = StringScanner.new(source)
76
- @current_line = 0
77
105
  end
78
106
 
107
+ sig { params(position: PositionShape).returns(Integer) }
79
108
  def find_position(position)
80
- # Move the string scanner counting line breaks until we reach the right line
81
109
  until @current_line == position[:line]
82
- @scanner.scan_until(/\R/)
110
+ @pos += 1 until /\R/.match?(@source[@pos])
111
+ @pos += 1
83
112
  @current_line += 1
84
113
  end
85
114
 
86
- @scanner.pos + position[:character]
115
+ @pos + position[:character]
87
116
  end
88
117
  end
89
118
  end