ruby-lsp 0.0.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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