Skip to content

Commit 5cfa5c1

Browse files
authored
Feature/better parsing (#131)
* Update dependencies and enhance scope parsing functionality - Bump prism to version 1.8.0 and update other gem versions in Gemfile.lock. - Modify location hash generation in code_file.rb to include column information. - Change refresh_scopes_if_needed to perform a full refresh in project_manager.rb. - Refactor code_file_spec.rb to improve test structure and add tests for location ranges. * Fix the string thing
1 parent af5c96f commit 5cfa5c1

5 files changed

Lines changed: 109 additions & 34 deletions

File tree

Gemfile.lock

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ PATH
99
fuzzy_match
1010
json
1111
ostruct
12-
prism
12+
prism (>= 1.8.0)
1313
sqlite3
1414

1515
GEM
1616
remote: https://rubygems.org/
1717
specs:
18-
activemodel (8.1.1)
19-
activesupport (= 8.1.1)
20-
activerecord (8.1.1)
21-
activemodel (= 8.1.1)
22-
activesupport (= 8.1.1)
18+
activemodel (8.1.2)
19+
activesupport (= 8.1.2)
20+
activerecord (8.1.2)
21+
activemodel (= 8.1.2)
22+
activesupport (= 8.1.2)
2323
timeout (>= 0.4.0)
24-
activesupport (8.1.1)
24+
activesupport (8.1.2)
2525
base64
2626
bigdecimal
2727
concurrent-ruby (~> 1.0, >= 1.3.1)
@@ -111,7 +111,7 @@ GEM
111111
pp (0.6.3)
112112
prettyprint
113113
prettyprint (0.2.0)
114-
prism (1.7.0)
114+
prism (1.8.0)
115115
pry (0.16.0)
116116
coderay (~> 1.1)
117117
method_source (~> 1.0)
@@ -126,7 +126,7 @@ GEM
126126
rb-inotify (0.11.1)
127127
ffi (~> 1.0)
128128
rb-readline (0.5.5)
129-
rdoc (7.0.3)
129+
rdoc (7.1.0)
130130
erb
131131
psych (>= 4.0.0)
132132
tsort
@@ -160,7 +160,7 @@ GEM
160160
rubocop-rake (0.7.1)
161161
lint_roller (~> 1.1)
162162
rubocop (>= 1.72.1)
163-
rubocop-rspec (3.8.0)
163+
rubocop-rspec (3.9.0)
164164
lint_roller (~> 1.1)
165165
rubocop (~> 1.81)
166166
ruby-progressbar (1.13.0)
@@ -175,7 +175,7 @@ GEM
175175
sqlite3 (2.9.0-aarch64-linux-musl)
176176
stringio (3.2.0)
177177
sync (0.5.0)
178-
thor (1.4.0)
178+
thor (1.5.0)
179179
timeout (0.6.0)
180180
tins (1.51.0)
181181
bigdecimal
@@ -213,9 +213,9 @@ DEPENDENCIES
213213
simplecov_json_formatter
214214

215215
CHECKSUMS
216-
activemodel (8.1.1) sha256=8b7e2496b9e333ced06248c16a43217b950192c98e0fe3aa117eee21501c6fbd
217-
activerecord (8.1.1) sha256=e32c3a03e364fd803498eb4150c21bedc995aa83bc27122a94d480ab1dcb3d17
218-
activesupport (8.1.1) sha256=5e92534e8d0c8b8b5e6b16789c69dbea65c1d7b752269f71a39422e9546cea67
216+
activemodel (8.1.2) sha256=e21358c11ce68aed3f9838b7e464977bc007b4446c6e4059781e1d5c03bcf33e
217+
activerecord (8.1.2) sha256=acfbe0cadfcc50fa208011fe6f4eb01cae682ebae0ef57145ba45380c74bcc44
218+
activesupport (8.1.2) sha256=88842578ccd0d40f658289b0e8c842acfe9af751afee2e0744a7873f50b6fdae
219219
amatch (0.6.0) sha256=247996bdce87754a42ed38ce8b22a4b8162e1699a8d353bc36bc96b544bd509d
220220
ansi (1.5.0) sha256=5408253274e33d9d27d4a98c46d2998266fd51cba58a7eb9d08f50e57ed23592
221221
ast (2.4.3) sha256=954615157c1d6a382bc27d690d973195e79db7f55e9765ac7c481c60bdb4d383
@@ -258,7 +258,7 @@ CHECKSUMS
258258
parser (3.3.10.0) sha256=ce3587fa5cc55a88c4ba5b2b37621b3329aadf5728f9eafa36bbd121462aabd6
259259
pp (0.6.3) sha256=2951d514450b93ccfeb1df7d021cae0da16e0a7f95ee1e2273719669d0ab9df6
260260
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
261-
prism (1.7.0) sha256=10062f734bf7985c8424c44fac382ac04a58124ea3d220ec3ba9fe4f2da65103
261+
prism (1.8.0) sha256=84453a16ef5530ea62c5f03ec16b52a459575ad4e7b9c2b360fd8ce2c39c1254
262262
pry (0.16.0) sha256=d76c69065698ed1f85e717bd33d7942c38a50868f6b0673c636192b3d1b6054e
263263
psych (5.3.1) sha256=eb7a57cef10c9d70173ff74e739d843ac3b2c019a003de48447b2963d81b1974
264264
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
@@ -267,7 +267,7 @@ CHECKSUMS
267267
rb-fsevent (0.11.2) sha256=43900b972e7301d6570f64b850a5aa67833ee7d87b458ee92805d56b7318aefe
268268
rb-inotify (0.11.1) sha256=a0a700441239b0ff18eb65e3866236cd78613d6b9f78fea1f9ac47a85e47be6e
269269
rb-readline (0.5.5) sha256=9e9bd7e198bdef0822c46902f6c592b882c1f9777894a4c3dcf5b320824a8793
270-
rdoc (7.0.3) sha256=dfe3d0981d19b7bba71d9dbaeb57c9f4e3a7a4103162148a559c4fc687ea81f9
270+
rdoc (7.1.0) sha256=494899df0706c178596ca6e1d50f1b7eb285a9b2aae715be5abd742734f17363
271271
readline (0.0.4) sha256=6138eef17be2b98298b672c3ea63bf9cb5158d401324f26e1e84f235879c1d6a
272272
regexp_parser (2.11.3) sha256=ca13f381a173b7a93450e53459075c9b76a10433caadcb2f1180f2c741fc55a4
273273
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
@@ -276,7 +276,7 @@ CHECKSUMS
276276
rubocop-minitest (0.38.2) sha256=5a9dfb5a538973d0601aa51e59637d3998bb8df81233edf1ff421504c6280068
277277
rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
278278
rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d
279-
rubocop-rspec (3.8.0) sha256=28440dccb3f223a9938ca1f946bd3438275b8c6c156dab909e2cb8bc424cab33
279+
rubocop-rspec (3.9.0) sha256=8fa70a3619408237d789aeecfb9beef40576acc855173e60939d63332fdb55e2
280280
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
281281
ruby_language_server (0.9.3)
282282
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
@@ -287,7 +287,7 @@ CHECKSUMS
287287
sqlite3 (2.9.0-aarch64-linux-musl) sha256=56a35cb2d70779afc2ac191baf2c2148242285ecfed72f9b021218c5c4917913
288288
stringio (3.2.0) sha256=c37cb2e58b4ffbd33fe5cd948c05934af997b36e0b6ca6fdf43afa234cf222e1
289289
sync (0.5.0) sha256=668356cc07c59ac7ed9ecf34fec3929831f179c07adb1f3e1c3b7a1609a638fd
290-
thor (1.4.0) sha256=8763e822ccb0f1d7bee88cde131b19a65606657b847cc7b7b4b82e772bcd8a3d
290+
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
291291
timeout (0.6.0) sha256=6d722ad619f96ee383a0c557ec6eb8c4ecb08af3af62098a0be5057bf00de1af
292292
tins (1.51.0) sha256=9f83c534bfca23973c5e641308828d71d5ffa79fc32c0ef90996efa699d0696f
293293
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f

lib/ruby_language_server/code_file.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def tags
7171
scope_hash = {
7272
name: scope.name,
7373
kind:,
74-
location: Location.hash(uri, scope.top_line)
74+
location: Location.hash(uri, scope.top_line, scope.column, scope.bottom_line)
7575
}
7676
container_name = ancestor_scope_name(scope)
7777
scope_hash[:containerName] = container_name unless container_name.blank?
@@ -82,7 +82,7 @@ def tags
8282
{
8383
name:,
8484
kind: SYMBOL_KIND[:constant],
85-
location: Location.hash(uri, variable.line - 1),
85+
location: Location.hash(uri, variable.line - 1, variable.column),
8686
containerName: variable.scope.name
8787
}
8888
end

lib/ruby_language_server/project_manager.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ def scan_all_project_files
115115
begin
116116
ActiveRecord::Base.connection_pool.with_connection do |_connection|
117117
update_document_content(host_uri, text)
118-
code_file_for_uri(host_uri).refresh_scopes_if_needed(shallow: true)
118+
code_file_for_uri(host_uri).refresh_scopes_if_needed(shallow: false)
119119
end
120120
rescue StandardError => e
121121
RubyLanguageServer.logger.warn("Error updating: #{e}\n#{e.backtrace * "\n"}")

spec/lib/ruby_language_server/code_file_spec.rb

Lines changed: 67 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,8 @@
55

66
describe RubyLanguageServer::CodeFile do
77
describe 'CodeFile' do
8-
it 'must init' do
9-
RubyLanguageServer::CodeFile.build('uri', "class Foo\nend\n")
10-
end
11-
12-
describe 'tags' do
13-
let(:source) do
14-
<<-SOURCE
8+
let(:source) do
9+
<<~SOURCE
1510
class Foo
1611
def self.foo_class_method
1712
end
@@ -22,14 +17,19 @@ def foo_method
2217
end
2318
FOO_CONSTANT = 1
2419
end
25-
SOURCE
26-
end
20+
SOURCE
21+
end
2722

28-
let(:tags) { code_file(source).tags }
23+
def code_file(text)
24+
RubyLanguageServer::CodeFile.build('uri', text)
25+
end
2926

30-
def code_file(text)
31-
RubyLanguageServer::CodeFile.build('uri', text)
32-
end
27+
it 'must init' do
28+
RubyLanguageServer::CodeFile.build('uri', "class Foo\nend\n")
29+
end
30+
31+
describe 'tags' do
32+
let(:tags) { code_file(source).tags }
3333

3434
it 'should find classes' do
3535
code_file = code_file("class Foo\nend\n")
@@ -72,6 +72,60 @@ def code_file(text)
7272
tag = tags.detect { |t| t[:name] == 'initialize' }
7373
assert_equal(9, tag[:kind])
7474
end
75+
76+
describe 'location ranges' do
77+
let(:cf) { code_file(source) }
78+
79+
it 'should have correct start and end lines for a simple class' do
80+
tag = cf.tags.detect { |t| t[:name] == 'Foo' }
81+
82+
# Line numbers are 0-indexed in LSP
83+
expected_range = {
84+
start: { line: 0, character: 0 },
85+
end: { line: 9, character: 0 }
86+
}
87+
assert_equal(expected_range, tag[:location][:range])
88+
end
89+
90+
it 'should have correct start and end lines for a method' do
91+
tag = cf.tags.detect { |t| t[:name] == 'foo_method' }
92+
93+
expected_range = {
94+
start: { line: 5, character: 2 },
95+
end: { line: 7, character: 2 }
96+
}
97+
assert_equal(expected_range, tag[:location][:range])
98+
end
99+
100+
it 'should have correct start and end lines for multiple methods' do
101+
foo_tag = cf.tags.detect { |t| t[:name] == 'Foo' }
102+
foo_class_method_tag = cf.tags.detect { |t| t[:name] == 'foo_class_method' }
103+
initialize_tag = cf.tags.detect { |t| t[:name] == 'initialize' }
104+
foo_method_tag = cf.tags.detect { |t| t[:name] == 'foo_method' }
105+
106+
expected_foo_range = {
107+
start: { line: 0, character: 0 },
108+
end: { line: 9, character: 0 }
109+
}
110+
expected_foo_class_method_range = {
111+
start: { line: 1, character: 2 },
112+
end: { line: 2, character: 2 }
113+
}
114+
expected_initialize_range = {
115+
start: { line: 3, character: 2 },
116+
end: { line: 4, character: 2 }
117+
}
118+
expected_foo_method_range = {
119+
start: { line: 5, character: 2 },
120+
end: { line: 7, character: 2 }
121+
}
122+
123+
assert_equal(expected_foo_range, foo_tag[:location][:range])
124+
assert_equal(expected_foo_class_method_range, foo_class_method_tag[:location][:range])
125+
assert_equal(expected_initialize_range, initialize_tag[:location][:range])
126+
assert_equal(expected_foo_method_range, foo_method_tag[:location][:range])
127+
end
128+
end
75129
end
76130
end
77131
end

spec/lib/ruby_language_server/scope_parser_spec.rb

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,26 @@ module Baz
253253
assert_equal(0, bar.children.size, "Bar should have no children")
254254
end
255255
end
256+
257+
describe 'module with single constant' do
258+
before do
259+
@parser = RubyLanguageServer::ScopeParser.new(<<-RUBY)
260+
module MyModule
261+
MY_CONSTANT = 42
262+
end
263+
RUBY
264+
end
265+
266+
it 'should have the constant as a variable child of the module' do
267+
my_module = @parser.root_scope.children.first
268+
assert_equal('MyModule', my_module.name)
269+
assert_equal(:module, my_module.type, "MyModule should be a module")
270+
271+
# The constant should be a variable within the module scope
272+
constant_vars = my_module.variables
273+
assert_equal(1, constant_vars.size, "MyModule should have 1 constant variable")
274+
assert_equal('MY_CONSTANT', constant_vars.first.name, "The constant should be named MY_CONSTANT")
275+
end
276+
end
256277
end
257278
end

0 commit comments

Comments
 (0)