ruby-lsp-ree 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/CHANGELOG.md +19 -11
- data/Gemfile +6 -0
- data/Gemfile.lock +36 -1
- data/Rakefile +5 -1
- data/lib/ruby_lsp/ruby_lsp_ree/addon.rb +11 -5
- data/lib/ruby_lsp/ruby_lsp_ree/{completion_utils.rb → handlers/completion_handler.rb} +101 -27
- data/lib/ruby_lsp/ruby_lsp_ree/listeners/completion_listener.rb +49 -0
- data/lib/ruby_lsp/ruby_lsp_ree/{definition.rb → listeners/definition_listener.rb} +24 -8
- data/lib/ruby_lsp/ruby_lsp_ree/listeners/hover_listener.rb +65 -0
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_document.rb +42 -15
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_document_builder.rb +2 -0
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_link_node.rb +6 -1
- data/lib/ruby_lsp/ruby_lsp_ree/ree_indexing_enhancement.rb +2 -2
- data/lib/ruby_lsp/ruby_lsp_ree/ree_object_finder.rb +57 -8
- data/lib/ruby_lsp/ruby_lsp_ree/{ree_lsp_utils.rb → utils/ree_lsp_utils.rb} +3 -1
- data/lib/ruby_lsp_ree/version.rb +3 -5
- data/ruby-lsp-ree.gemspec +1 -1
- metadata +9 -7
- data/lib/ruby_lsp/ruby_lsp_ree/completion.rb +0 -108
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8eb134e8d6b0ac3bf5321789ed6617ea1347ee096b1e642f953885b398524030
|
|
4
|
+
data.tar.gz: 460f2cc171155affbafe236535604b116d0af15bbcf14c3925470a8ff3616211
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cf49632399253b97f3b3df77ae7767008141900552461de8bca6b7395ac0d48fa4dbc5a353d2245f50147d7d119059b3f4d5a3f55aa41ae4fd11521d58b7930d
|
|
7
|
+
data.tar.gz: 0f392c77bbe2bdee9e9f613bc856c1d93b9bb9a2c87a93078017388fb253b27325d244ba289b36c24ff7e71e9f72b4f9c11abb663a7a2f675b5a9661aae29554
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.3.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
## [
|
|
1
|
+
## [0.1.3] - 2025-02-21
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
- improved Go To Definition for ree object methods and imported constants
|
|
4
|
+
- support for :mapper objects
|
|
5
|
+
- support for :aggregate objects
|
|
6
|
+
- improved autocompletion for imported constants
|
|
7
|
+
- basic hover information for ree objects
|
|
4
8
|
|
|
5
|
-
-
|
|
9
|
+
## [0.1.2] - 2025-02-14
|
|
10
|
+
|
|
11
|
+
- support for :bean objects
|
|
12
|
+
- Go To Definition for imported constants
|
|
13
|
+
- use current (not saved) version of the document in autocomplete
|
|
14
|
+
- use current (not saved) version of the document in definition
|
|
15
|
+
- increase autocomplete list limits (affects short functions)
|
|
16
|
+
- improved const autocomplete
|
|
17
|
+
- improved ree errors handling
|
|
6
18
|
|
|
7
19
|
## [0.1.1] - 2025-02-10
|
|
8
20
|
|
|
@@ -21,12 +33,8 @@
|
|
|
21
33
|
- autocomplete for ree dao
|
|
22
34
|
- autocomplete for dao filters
|
|
23
35
|
|
|
24
|
-
## [0.1.
|
|
36
|
+
## [0.1.0] - 2025-01-31
|
|
25
37
|
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- use current (no saved) version of the document in definition
|
|
30
|
-
- increase autocomplete list limits (affects short functions)
|
|
31
|
-
- improved const autocomplete
|
|
32
|
-
- improved ree errors handling
|
|
38
|
+
- Initial release
|
|
39
|
+
|
|
40
|
+
## [Unreleased]
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,44 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
ruby-lsp-ree (0.1.
|
|
4
|
+
ruby-lsp-ree (0.1.3)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
+
diff-lcs (1.6.0)
|
|
10
|
+
language_server-protocol (3.17.0.4)
|
|
11
|
+
logger (1.6.6)
|
|
12
|
+
prism (1.3.0)
|
|
9
13
|
rake (13.2.1)
|
|
14
|
+
rbs (3.8.1)
|
|
15
|
+
logger
|
|
16
|
+
rspec (3.13.0)
|
|
17
|
+
rspec-core (~> 3.13.0)
|
|
18
|
+
rspec-expectations (~> 3.13.0)
|
|
19
|
+
rspec-mocks (~> 3.13.0)
|
|
20
|
+
rspec-core (3.13.3)
|
|
21
|
+
rspec-support (~> 3.13.0)
|
|
22
|
+
rspec-expectations (3.13.3)
|
|
23
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
24
|
+
rspec-support (~> 3.13.0)
|
|
25
|
+
rspec-mocks (3.13.2)
|
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
27
|
+
rspec-support (~> 3.13.0)
|
|
28
|
+
rspec-support (3.13.2)
|
|
29
|
+
ruby-lsp (0.23.11)
|
|
30
|
+
language_server-protocol (~> 3.17.0)
|
|
31
|
+
prism (>= 1.2, < 2.0)
|
|
32
|
+
rbs (>= 3, < 4)
|
|
33
|
+
sorbet-runtime (>= 0.5.10782)
|
|
34
|
+
sorbet (0.5.11835)
|
|
35
|
+
sorbet-static (= 0.5.11835)
|
|
36
|
+
sorbet-runtime (0.5.11835)
|
|
37
|
+
sorbet-static (0.5.11835-universal-darwin)
|
|
38
|
+
sorbet-static (0.5.11835-x86_64-linux)
|
|
39
|
+
sorbet-static-and-runtime (0.5.11835)
|
|
40
|
+
sorbet (= 0.5.11835)
|
|
41
|
+
sorbet-runtime (= 0.5.11835)
|
|
10
42
|
|
|
11
43
|
PLATFORMS
|
|
12
44
|
x86_64-darwin-23
|
|
@@ -14,7 +46,10 @@ PLATFORMS
|
|
|
14
46
|
|
|
15
47
|
DEPENDENCIES
|
|
16
48
|
rake (~> 13.0)
|
|
49
|
+
rspec
|
|
50
|
+
ruby-lsp
|
|
17
51
|
ruby-lsp-ree!
|
|
52
|
+
sorbet-static-and-runtime
|
|
18
53
|
|
|
19
54
|
BUNDLED WITH
|
|
20
55
|
2.6.3
|
data/Rakefile
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require "ruby_lsp/addon"
|
|
2
|
-
require_relative "
|
|
3
|
-
require_relative "
|
|
2
|
+
require_relative "listeners/definition_listener"
|
|
3
|
+
require_relative "listeners/completion_listener"
|
|
4
|
+
require_relative "listeners/hover_listener"
|
|
4
5
|
require_relative "ree_indexing_enhancement"
|
|
5
|
-
require_relative "ree_lsp_utils"
|
|
6
|
+
require_relative "utils/ree_lsp_utils"
|
|
6
7
|
require_relative "ree_formatter"
|
|
7
8
|
require_relative "parsing/parsed_document_builder"
|
|
8
9
|
|
|
@@ -25,12 +26,17 @@ module RubyLsp
|
|
|
25
26
|
|
|
26
27
|
def create_definition_listener(response_builder, uri, node_context, dispatcher)
|
|
27
28
|
index = @global_state.index
|
|
28
|
-
RubyLsp::Ree::
|
|
29
|
+
RubyLsp::Ree::DefinitionListener.new(response_builder, node_context, index, dispatcher, uri)
|
|
29
30
|
end
|
|
30
31
|
|
|
31
32
|
def create_completion_listener(response_builder, node_context, dispatcher, uri)
|
|
32
33
|
index = @global_state.index
|
|
33
|
-
RubyLsp::Ree::
|
|
34
|
+
RubyLsp::Ree::CompletionListener.new(response_builder, node_context, index, dispatcher, uri)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def create_hover_listener(response_builder, node_context, dispatcher)
|
|
38
|
+
index = @global_state.index
|
|
39
|
+
RubyLsp::Ree::HoverListener.new(response_builder, node_context, index, dispatcher)
|
|
34
40
|
end
|
|
35
41
|
end
|
|
36
42
|
end
|
|
@@ -1,11 +1,43 @@
|
|
|
1
|
-
require_relative "ree_lsp_utils"
|
|
1
|
+
require_relative "../utils/ree_lsp_utils"
|
|
2
|
+
require_relative "../ree_object_finder"
|
|
2
3
|
|
|
3
4
|
module RubyLsp
|
|
4
5
|
module Ree
|
|
5
|
-
|
|
6
|
+
class CompletionHandler
|
|
6
7
|
include Requests::Support::Common
|
|
7
8
|
include RubyLsp::Ree::ReeLspUtils
|
|
8
9
|
|
|
10
|
+
RECEIVER_OBJECT_TYPES = [:enum, :dao, :bean]
|
|
11
|
+
CANDIDATES_LIMIT = 100
|
|
12
|
+
|
|
13
|
+
def initialize(index, uri, node_context)
|
|
14
|
+
@index = index
|
|
15
|
+
@uri = uri
|
|
16
|
+
@node_context = node_context
|
|
17
|
+
@finder = ReeObjectFinder.new(@index)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def get_ree_receiver(receiver_node)
|
|
21
|
+
return if !receiver_node || !receiver_node.is_a?(Prism::CallNode)
|
|
22
|
+
|
|
23
|
+
@finder.find_objects_by_types(receiver_node.name.to_s, RECEIVER_OBJECT_TYPES).first
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def get_ree_object_methods_completions_items(ree_receiver, receiver_node, node)
|
|
27
|
+
location = receiver_node.location
|
|
28
|
+
|
|
29
|
+
case @finder.object_type(ree_receiver)
|
|
30
|
+
when :enum
|
|
31
|
+
get_enum_values_completion_items(ree_receiver, location)
|
|
32
|
+
when :bean
|
|
33
|
+
get_bean_methods_completion_items(ree_receiver, location)
|
|
34
|
+
when :dao
|
|
35
|
+
get_dao_filters_completion_items(ree_receiver, location)
|
|
36
|
+
else
|
|
37
|
+
[]
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
9
41
|
def get_bean_methods_completion_items(bean_obj, location)
|
|
10
42
|
bean_node = RubyLsp::Ree::ParsedDocumentBuilder.build_from_uri(bean_obj.uri, :bean)
|
|
11
43
|
|
|
@@ -107,34 +139,75 @@ module RubyLsp
|
|
|
107
139
|
end
|
|
108
140
|
end
|
|
109
141
|
|
|
110
|
-
def get_class_name_completion_items(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
142
|
+
def get_class_name_completion_items(node)
|
|
143
|
+
node_name = node.name.to_s
|
|
144
|
+
class_name_objects = @finder.search_class_objects(node_name)
|
|
145
|
+
|
|
146
|
+
return [] if class_name_objects.size == 0
|
|
147
|
+
|
|
148
|
+
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_ast(@node_context.parent, @uri)
|
|
149
|
+
|
|
150
|
+
imported_consts = []
|
|
151
|
+
not_imported_consts = []
|
|
152
|
+
|
|
153
|
+
class_name_objects.take(CANDIDATES_LIMIT).each do |full_class_name|
|
|
154
|
+
entries = @index[full_class_name]
|
|
155
|
+
|
|
156
|
+
entries.each do |entry|
|
|
157
|
+
class_name = full_class_name.split('::').last
|
|
158
|
+
package_name = package_name_from_uri(entry.uri)
|
|
159
|
+
file_name = File.basename(entry.uri.to_s)
|
|
160
|
+
|
|
161
|
+
matched_import = parsed_doc.find_import_for_package(class_name, package_name)
|
|
162
|
+
|
|
163
|
+
if matched_import
|
|
164
|
+
label_details = Interface::CompletionItemLabelDetails.new(
|
|
165
|
+
description: "imported from: :#{package_name}",
|
|
166
|
+
detail: ""
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
imported_consts << Interface::CompletionItem.new(
|
|
170
|
+
label: class_name,
|
|
171
|
+
label_details: label_details,
|
|
172
|
+
filter_text: class_name,
|
|
173
|
+
text_edit: Interface::TextEdit.new(
|
|
174
|
+
range: range_from_location(node.location),
|
|
175
|
+
new_text: class_name,
|
|
176
|
+
),
|
|
177
|
+
kind: Constant::CompletionItemKind::CLASS,
|
|
178
|
+
additional_text_edits: []
|
|
179
|
+
)
|
|
180
|
+
else
|
|
181
|
+
label_details = Interface::CompletionItemLabelDetails.new(
|
|
182
|
+
description: "from: :#{package_name}",
|
|
183
|
+
detail: " #{file_name}"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
not_imported_consts << Interface::CompletionItem.new(
|
|
187
|
+
label: class_name,
|
|
188
|
+
label_details: label_details,
|
|
189
|
+
filter_text: class_name,
|
|
190
|
+
text_edit: Interface::TextEdit.new(
|
|
191
|
+
range: range_from_location(node.location),
|
|
192
|
+
new_text: class_name,
|
|
193
|
+
),
|
|
194
|
+
kind: Constant::CompletionItemKind::CLASS,
|
|
195
|
+
additional_text_edits: get_additional_text_edits_for_constant(parsed_doc, class_name, package_name, entry)
|
|
196
|
+
)
|
|
197
|
+
end
|
|
198
|
+
end
|
|
134
199
|
end
|
|
200
|
+
|
|
201
|
+
imported_consts + not_imported_consts
|
|
135
202
|
end
|
|
136
203
|
|
|
137
|
-
def get_ree_objects_completions_items(
|
|
204
|
+
def get_ree_objects_completions_items(node)
|
|
205
|
+
ree_objects = @finder.search_objects(node.name.to_s, CANDIDATES_LIMIT)
|
|
206
|
+
|
|
207
|
+
return [] if ree_objects.size == 0
|
|
208
|
+
|
|
209
|
+
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_ast(@node_context.parent, @uri)
|
|
210
|
+
|
|
138
211
|
ree_objects.map do |ree_object|
|
|
139
212
|
ree_object_name = ree_object.name
|
|
140
213
|
package_name = package_name_from_uri(ree_object.uri)
|
|
@@ -254,6 +327,7 @@ module RubyLsp
|
|
|
254
327
|
end
|
|
255
328
|
|
|
256
329
|
range = get_range_for_fn_insert(parsed_doc, link_text)
|
|
330
|
+
return unless range
|
|
257
331
|
|
|
258
332
|
[
|
|
259
333
|
Interface::TextEdit.new(
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require_relative "../handlers/completion_handler"
|
|
2
|
+
|
|
3
|
+
module RubyLsp
|
|
4
|
+
module Ree
|
|
5
|
+
class CompletionListener
|
|
6
|
+
include Requests::Support::Common
|
|
7
|
+
|
|
8
|
+
CHARS_COUNT = 1
|
|
9
|
+
|
|
10
|
+
def initialize(response_builder, node_context, index, dispatcher, uri)
|
|
11
|
+
@response_builder = response_builder
|
|
12
|
+
@handler = RubyLsp::Ree::CompletionHandler.new(index, uri, node_context)
|
|
13
|
+
|
|
14
|
+
dispatcher.register(self, :on_call_node_enter)
|
|
15
|
+
dispatcher.register(self, :on_constant_read_node_enter)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def on_constant_read_node_enter(node)
|
|
19
|
+
node_name = node.name.to_s
|
|
20
|
+
return if node_name.size < CHARS_COUNT
|
|
21
|
+
|
|
22
|
+
completion_items = @handler.get_class_name_completion_items(node)
|
|
23
|
+
put_items_into_response(completion_items)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def on_call_node_enter(node)
|
|
27
|
+
completion_items = []
|
|
28
|
+
ree_receiver = @handler.get_ree_receiver(node.receiver)
|
|
29
|
+
|
|
30
|
+
if ree_receiver
|
|
31
|
+
completion_items = @handler.get_ree_object_methods_completions_items(ree_receiver, node.receiver, node)
|
|
32
|
+
else
|
|
33
|
+
return if node.receiver
|
|
34
|
+
return if node.name.to_s.size < CHARS_COUNT
|
|
35
|
+
|
|
36
|
+
completion_items = @handler.get_ree_objects_completions_items(node)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
put_items_into_response(completion_items)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def put_items_into_response(items)
|
|
43
|
+
items.each do |item|
|
|
44
|
+
@response_builder << item
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
require_relative "ree_lsp_utils"
|
|
2
|
-
require_relative "parsing/parsed_link_node"
|
|
1
|
+
require_relative "../utils/ree_lsp_utils"
|
|
2
|
+
require_relative "../parsing/parsed_link_node"
|
|
3
|
+
require_relative "../parsing/parsed_document_builder"
|
|
4
|
+
require_relative "../ree_object_finder"
|
|
3
5
|
|
|
4
6
|
module RubyLsp
|
|
5
7
|
module Ree
|
|
6
|
-
class
|
|
8
|
+
class DefinitionListener
|
|
7
9
|
include Requests::Support::Common
|
|
8
10
|
include RubyLsp::Ree::ReeLspUtils
|
|
9
11
|
|
|
@@ -18,13 +20,18 @@ module RubyLsp
|
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def on_constant_read_node_enter(node)
|
|
21
|
-
link_nodes = if @node_context.parent.is_a?(Prism::CallNode)
|
|
23
|
+
link_nodes = if @node_context.parent.is_a?(Prism::CallNode) && @node_context.parent.name == :link
|
|
22
24
|
# inside link node
|
|
23
25
|
link_node = RubyLsp::Ree::ParsedLinkNode.new(@node_context.parent)
|
|
24
26
|
link_node.parse_imports
|
|
25
27
|
[link_node]
|
|
26
28
|
else
|
|
27
|
-
parsed_doc =
|
|
29
|
+
parsed_doc = if @node_context.parent.is_a?(Prism::CallNode)
|
|
30
|
+
RubyLsp::Ree::ParsedDocumentBuilder.build_from_uri(@uri)
|
|
31
|
+
else
|
|
32
|
+
RubyLsp::Ree::ParsedDocumentBuilder.build_from_ast(@node_context.parent, @uri)
|
|
33
|
+
end
|
|
34
|
+
|
|
28
35
|
parsed_doc.link_nodes
|
|
29
36
|
end
|
|
30
37
|
|
|
@@ -63,11 +70,20 @@ module RubyLsp
|
|
|
63
70
|
message = node.message
|
|
64
71
|
return unless message
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
73
|
+
definition_uri = nil
|
|
74
|
+
|
|
75
|
+
if node.receiver
|
|
76
|
+
# ruby lsp handles such cases itself
|
|
77
|
+
return
|
|
78
|
+
else
|
|
79
|
+
definition_item = ReeObjectFinder.new(@index).find_object(message)
|
|
80
|
+
definition_uri = definition_item.uri.to_s
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
return unless definition_uri
|
|
68
84
|
|
|
69
85
|
@response_builder << Interface::Location.new(
|
|
70
|
-
uri:
|
|
86
|
+
uri: definition_uri,
|
|
71
87
|
range: Interface::Range.new(
|
|
72
88
|
start: Interface::Position.new(line: 0, character: 0),
|
|
73
89
|
end: Interface::Position.new(line: 0, character: 0),
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
require_relative "../ree_object_finder"
|
|
2
|
+
require_relative "../parsing/parsed_document_builder"
|
|
3
|
+
require_relative "../parsing/parsed_link_node"
|
|
4
|
+
require_relative "../utils/ree_lsp_utils"
|
|
5
|
+
|
|
6
|
+
module RubyLsp
|
|
7
|
+
module Ree
|
|
8
|
+
class HoverListener
|
|
9
|
+
include RubyLsp::Ree::ReeLspUtils
|
|
10
|
+
|
|
11
|
+
def initialize(response_builder, node_context, index, dispatcher)
|
|
12
|
+
@response_builder = response_builder
|
|
13
|
+
@node_context = node_context
|
|
14
|
+
@finder = ReeObjectFinder.new(index)
|
|
15
|
+
|
|
16
|
+
dispatcher.register(self, :on_call_node_enter)
|
|
17
|
+
dispatcher.register(self, :on_constant_read_node_enter)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def on_constant_read_node_enter(node)
|
|
21
|
+
# ree_object = @finder.search_classes(node.name.to_s).first
|
|
22
|
+
|
|
23
|
+
# $stderr.puts("ree_object #{ree_object.inspect}")
|
|
24
|
+
|
|
25
|
+
# return unless ree_object
|
|
26
|
+
|
|
27
|
+
# $stderr.puts("ree_object comm #{ree_object.comments.to_s}")
|
|
28
|
+
|
|
29
|
+
# @response_builder.push(ree_object.comments.to_s, category: :documentation)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def on_call_node_enter(node)
|
|
33
|
+
ree_object = @finder.find_object(node.name.to_s)
|
|
34
|
+
|
|
35
|
+
return unless ree_object
|
|
36
|
+
|
|
37
|
+
documentation = <<~DOC
|
|
38
|
+
Ree object, type: :#{@finder.object_type(ree_object)}
|
|
39
|
+
|
|
40
|
+
usage: #{node.name.to_s}#{get_detail_string(ree_object)}
|
|
41
|
+
|
|
42
|
+
package: #{package_name_from_uri(ree_object.uri)}
|
|
43
|
+
|
|
44
|
+
file: #{path_from_package_folder(ree_object.uri)}
|
|
45
|
+
DOC
|
|
46
|
+
|
|
47
|
+
$stderr.puts(documentation)
|
|
48
|
+
|
|
49
|
+
@response_builder.push(documentation, category: :documentation)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def get_detail_string(ree_object)
|
|
53
|
+
return '' if ree_object.signatures.size == 0
|
|
54
|
+
|
|
55
|
+
"(#{get_parameters_string(ree_object.signatures.first)})"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def get_parameters_string(signature)
|
|
59
|
+
return '' unless signature
|
|
60
|
+
|
|
61
|
+
signature.parameters.map(&:decorated_name).join(', ')
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -5,20 +5,17 @@ class RubyLsp::Ree::ParsedDocument
|
|
|
5
5
|
|
|
6
6
|
LINK_DSL_MODULE = 'Ree::LinkDSL'
|
|
7
7
|
|
|
8
|
-
attr_reader :ast, :package_name, :class_node, :fn_node, :
|
|
9
|
-
:link_nodes, :values, :action_node, :
|
|
10
|
-
:bean_node, :
|
|
8
|
+
attr_reader :ast, :package_name, :class_node, :fn_node, :class_includes,
|
|
9
|
+
:link_nodes, :values, :action_node, :dao_node, :filters,
|
|
10
|
+
:bean_node, :bean_methods, :mapper_node, :links_container_block_node, :aggregate_node
|
|
11
11
|
|
|
12
12
|
def initialize(ast)
|
|
13
13
|
@ast = ast
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def links_container_node
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def links_container_block_node
|
|
21
|
-
@fn_block_node || @action_block_node || @dao_block_node || @bean_block_node
|
|
17
|
+
# TODO don't use separate node, use one field for all and additional type field: links_container_node_type
|
|
18
|
+
@fn_node || @action_node || @dao_node || @bean_node || @mapper_node || @aggregate_node
|
|
22
19
|
end
|
|
23
20
|
|
|
24
21
|
def includes_link_dsl?
|
|
@@ -33,8 +30,24 @@ class RubyLsp::Ree::ParsedDocument
|
|
|
33
30
|
@link_nodes.map(&:name).include?(obj_name)
|
|
34
31
|
end
|
|
35
32
|
|
|
33
|
+
def find_link_node(name)
|
|
34
|
+
@link_nodes.detect{ _1.name == name }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def find_link_with_imported_object(name)
|
|
38
|
+
@link_nodes.detect do |link_node|
|
|
39
|
+
link_node.imports.include?(name)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def find_import_for_package(name, package_name)
|
|
44
|
+
@link_nodes.detect do |link_node|
|
|
45
|
+
link_node.imports.include?(name) && link_node.link_package_name == package_name
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
36
49
|
def has_blank_links_container?
|
|
37
|
-
links_container_node &&
|
|
50
|
+
links_container_node && !@links_container_block_node
|
|
38
51
|
end
|
|
39
52
|
|
|
40
53
|
def set_package_name(package_name)
|
|
@@ -49,28 +62,42 @@ class RubyLsp::Ree::ParsedDocument
|
|
|
49
62
|
return unless class_node
|
|
50
63
|
|
|
51
64
|
@fn_node ||= class_node.body.body.detect{ |node| node.name == :fn }
|
|
52
|
-
@
|
|
65
|
+
@links_container_block_node ||= @fn_node&.block
|
|
53
66
|
end
|
|
54
67
|
|
|
55
68
|
def parse_action_node
|
|
56
69
|
return unless class_node
|
|
57
70
|
|
|
58
71
|
@action_node ||= class_node.body.body.detect{ |node| node.name == :action }
|
|
59
|
-
@
|
|
72
|
+
@links_container_block_node ||= @action_node&.block
|
|
60
73
|
end
|
|
61
74
|
|
|
62
75
|
def parse_dao_node
|
|
63
76
|
return unless class_node
|
|
64
77
|
|
|
65
78
|
@dao_node ||= class_node.body.body.detect{ |node| node.name == :dao }
|
|
66
|
-
@
|
|
79
|
+
@links_container_block_node ||= @dao_node&.block
|
|
67
80
|
end
|
|
68
81
|
|
|
69
82
|
def parse_bean_node
|
|
70
83
|
return unless class_node
|
|
71
84
|
|
|
72
85
|
@bean_node ||= class_node.body.body.detect{ |node| node.name == :bean }
|
|
73
|
-
@
|
|
86
|
+
@links_container_block_node ||= @bean_node&.block
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def parse_mapper_node
|
|
90
|
+
return unless class_node
|
|
91
|
+
|
|
92
|
+
@mapper_node ||= class_node.body.body.detect{ |node| node.name == :mapper }
|
|
93
|
+
@links_container_block_node ||= @mapper_node&.block
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def parse_aggregate_node
|
|
97
|
+
return unless class_node
|
|
98
|
+
|
|
99
|
+
@aggregate_node ||= class_node.body.body.detect{ |node| node.name == :aggregate }
|
|
100
|
+
@links_container_block_node ||= @aggregate_node&.block
|
|
74
101
|
end
|
|
75
102
|
|
|
76
103
|
def parse_class_includes
|
|
@@ -89,8 +116,8 @@ class RubyLsp::Ree::ParsedDocument
|
|
|
89
116
|
def parse_links
|
|
90
117
|
return unless class_node
|
|
91
118
|
|
|
92
|
-
nodes = if links_container_node && links_container_block_node.body
|
|
93
|
-
links_container_block_node.body.body.select{ |node| node.name == :link }
|
|
119
|
+
nodes = if links_container_node && @links_container_block_node.body
|
|
120
|
+
@links_container_block_node.body.body.select{ |node| node.name == :link }
|
|
94
121
|
elsif class_includes.any?{ _1.name == LINK_DSL_MODULE }
|
|
95
122
|
class_node.body.body.select{ |node| node.name == :link }
|
|
96
123
|
else
|
|
@@ -13,7 +13,12 @@ class RubyLsp::Ree::ParsedLinkNode
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def link_package_name
|
|
16
|
-
|
|
16
|
+
case link_type
|
|
17
|
+
when :object_name
|
|
18
|
+
from_arg_value || document_package
|
|
19
|
+
when :file_path
|
|
20
|
+
@name.split('/').first
|
|
21
|
+
end
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
def location
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
require 'prism'
|
|
2
|
-
require_relative "ree_lsp_utils"
|
|
2
|
+
require_relative "utils/ree_lsp_utils"
|
|
3
3
|
|
|
4
4
|
module RubyLsp
|
|
5
5
|
module Ree
|
|
6
6
|
class ReeIndexingEnhancement < RubyIndexer::Enhancement
|
|
7
7
|
include RubyLsp::Ree::ReeLspUtils
|
|
8
8
|
|
|
9
|
-
REE_INDEXED_OBJECTS = [:fn, :enum, :action, :dao, :bean]
|
|
9
|
+
REE_INDEXED_OBJECTS = [:fn, :enum, :action, :dao, :bean, :mapper, :aggregate]
|
|
10
10
|
|
|
11
11
|
def on_call_node_enter(node)
|
|
12
12
|
return unless @listener.current_owner
|
|
@@ -7,9 +7,15 @@ module RubyLsp
|
|
|
7
7
|
ENUM_TYPE_STRING = 'type: :enum'
|
|
8
8
|
DAO_TYPE_STRING = 'type: :dao'
|
|
9
9
|
BEAN_TYPE_STRING = 'type: :bean'
|
|
10
|
+
MAPPER_TYPE_STRING = 'type: :mapper'
|
|
11
|
+
AGGREGATE_TYPE_STRING = 'type: :aggregate'
|
|
10
12
|
|
|
11
|
-
def
|
|
12
|
-
index
|
|
13
|
+
def initialize(index)
|
|
14
|
+
@index = index
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def search_objects(name, limit)
|
|
18
|
+
@index.prefix_search(name)
|
|
13
19
|
.take(MAX_LIMIT)
|
|
14
20
|
.flatten
|
|
15
21
|
.select{ _1.comments }
|
|
@@ -18,26 +24,69 @@ module RubyLsp
|
|
|
18
24
|
.take(limit)
|
|
19
25
|
end
|
|
20
26
|
|
|
21
|
-
def
|
|
22
|
-
|
|
27
|
+
def search_class_objects(name)
|
|
28
|
+
@index
|
|
29
|
+
.names
|
|
30
|
+
.select{ _1.split('::').last[0...name.size] == name}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def search_classes(name)
|
|
34
|
+
keys = search_class_objects(name)
|
|
35
|
+
@index.instance_variable_get(:@entries).values_at(*keys)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def find_object(name)
|
|
39
|
+
objects_by_name = @index[name]
|
|
40
|
+
return unless objects_by_name
|
|
41
|
+
|
|
42
|
+
objects_by_name.detect{ _1.comments.to_s.lines.first&.chomp == REE_OBJECT_STRING }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def find_objects_by_types(name, types)
|
|
46
|
+
objects_by_name = @index[name]
|
|
47
|
+
return [] unless objects_by_name
|
|
48
|
+
|
|
49
|
+
objects_by_name.select{ types.include?(object_type(_1)) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def find_enum(name)
|
|
53
|
+
objects_by_name = @index[name]
|
|
23
54
|
return unless objects_by_name
|
|
24
55
|
|
|
25
56
|
objects_by_name.detect{ _1.comments.lines[1]&.chomp == ENUM_TYPE_STRING }
|
|
26
57
|
end
|
|
27
58
|
|
|
28
|
-
def
|
|
29
|
-
objects_by_name = index[name]
|
|
59
|
+
def find_dao(name)
|
|
60
|
+
objects_by_name = @index[name]
|
|
30
61
|
return unless objects_by_name
|
|
31
62
|
|
|
32
63
|
objects_by_name.detect{ _1.comments.lines[1]&.chomp == DAO_TYPE_STRING }
|
|
33
64
|
end
|
|
34
65
|
|
|
35
|
-
def
|
|
36
|
-
objects_by_name = index[name]
|
|
66
|
+
def find_bean(index, name)
|
|
67
|
+
objects_by_name = @index[name]
|
|
37
68
|
return unless objects_by_name
|
|
38
69
|
|
|
39
70
|
objects_by_name.detect{ _1.comments.lines[1]&.chomp == BEAN_TYPE_STRING }
|
|
40
71
|
end
|
|
72
|
+
|
|
73
|
+
def object_type(ree_object)
|
|
74
|
+
# TODO rewrite to use string split
|
|
75
|
+
case ree_object.comments.lines[1]&.chomp
|
|
76
|
+
when DAO_TYPE_STRING
|
|
77
|
+
:dao
|
|
78
|
+
when BEAN_TYPE_STRING
|
|
79
|
+
:bean
|
|
80
|
+
when ENUM_TYPE_STRING
|
|
81
|
+
:enum
|
|
82
|
+
when MAPPER_TYPE_STRING
|
|
83
|
+
:mapper
|
|
84
|
+
when AGGREGATE_TYPE_STRING
|
|
85
|
+
:aggregate
|
|
86
|
+
else
|
|
87
|
+
nil
|
|
88
|
+
end
|
|
89
|
+
end
|
|
41
90
|
end
|
|
42
91
|
end
|
|
43
92
|
end
|
|
@@ -18,7 +18,7 @@ module RubyLsp
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def path_from_package_folder(uri)
|
|
21
|
-
uri_parts = uri.chomp(File.extname(uri)).split('/')
|
|
21
|
+
uri_parts = uri.to_s.chomp(File.extname(uri)).split('/')
|
|
22
22
|
|
|
23
23
|
package_folder_index = uri_parts.index('package')
|
|
24
24
|
return unless package_folder_index
|
|
@@ -49,6 +49,8 @@ module RubyLsp
|
|
|
49
49
|
elsif parsed_doc.includes_link_dsl?
|
|
50
50
|
fn_line = parsed_doc.link_nodes.first.location.start_line - 1
|
|
51
51
|
position = parsed_doc.link_nodes.first.location.start_column
|
|
52
|
+
else
|
|
53
|
+
return nil
|
|
52
54
|
end
|
|
53
55
|
|
|
54
56
|
Interface::Range.new(
|
data/lib/ruby_lsp_ree/version.rb
CHANGED
data/ruby-lsp-ree.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ require_relative "lib/ruby_lsp_ree/version"
|
|
|
4
4
|
|
|
5
5
|
Gem::Specification.new do |spec|
|
|
6
6
|
spec.name = "ruby-lsp-ree"
|
|
7
|
-
spec.version =
|
|
7
|
+
spec.version = RubyLsp::Ree::VERSION
|
|
8
8
|
spec.authors = ["Ruslan Gatiyatov"]
|
|
9
9
|
spec.email = ["ruslan.gatiyatov@gmail.com"]
|
|
10
10
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ruby-lsp-ree
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ruslan Gatiyatov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-02-
|
|
11
|
+
date: 2025-02-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: A Ruby LSP addon that adds extra editor functionality for Ree applications
|
|
14
14
|
email:
|
|
@@ -17,6 +17,7 @@ executables: []
|
|
|
17
17
|
extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
+
- ".ruby-version"
|
|
20
21
|
- CHANGELOG.md
|
|
21
22
|
- CODE_OF_CONDUCT.md
|
|
22
23
|
- Gemfile
|
|
@@ -25,16 +26,17 @@ files:
|
|
|
25
26
|
- README.md
|
|
26
27
|
- Rakefile
|
|
27
28
|
- lib/ruby_lsp/ruby_lsp_ree/addon.rb
|
|
28
|
-
- lib/ruby_lsp/ruby_lsp_ree/
|
|
29
|
-
- lib/ruby_lsp/ruby_lsp_ree/
|
|
30
|
-
- lib/ruby_lsp/ruby_lsp_ree/
|
|
29
|
+
- lib/ruby_lsp/ruby_lsp_ree/handlers/completion_handler.rb
|
|
30
|
+
- lib/ruby_lsp/ruby_lsp_ree/listeners/completion_listener.rb
|
|
31
|
+
- lib/ruby_lsp/ruby_lsp_ree/listeners/definition_listener.rb
|
|
32
|
+
- lib/ruby_lsp/ruby_lsp_ree/listeners/hover_listener.rb
|
|
31
33
|
- lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_document.rb
|
|
32
34
|
- lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_document_builder.rb
|
|
33
35
|
- lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_link_node.rb
|
|
34
36
|
- lib/ruby_lsp/ruby_lsp_ree/ree_formatter.rb
|
|
35
37
|
- lib/ruby_lsp/ruby_lsp_ree/ree_indexing_enhancement.rb
|
|
36
|
-
- lib/ruby_lsp/ruby_lsp_ree/ree_lsp_utils.rb
|
|
37
38
|
- lib/ruby_lsp/ruby_lsp_ree/ree_object_finder.rb
|
|
39
|
+
- lib/ruby_lsp/ruby_lsp_ree/utils/ree_lsp_utils.rb
|
|
38
40
|
- lib/ruby_lsp_ree.rb
|
|
39
41
|
- lib/ruby_lsp_ree/version.rb
|
|
40
42
|
- ruby-lsp-ree.gemspec
|
|
@@ -61,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
61
63
|
- !ruby/object:Gem::Version
|
|
62
64
|
version: '0'
|
|
63
65
|
requirements: []
|
|
64
|
-
rubygems_version: 3.
|
|
66
|
+
rubygems_version: 3.5.3
|
|
65
67
|
signing_key:
|
|
66
68
|
specification_version: 4
|
|
67
69
|
summary: Ruby LSP addon for Ree framework.
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
require_relative "ree_lsp_utils"
|
|
2
|
-
require_relative "completion_utils"
|
|
3
|
-
require_relative "ree_object_finder"
|
|
4
|
-
|
|
5
|
-
module RubyLsp
|
|
6
|
-
module Ree
|
|
7
|
-
class Completion
|
|
8
|
-
include Requests::Support::Common
|
|
9
|
-
include RubyLsp::Ree::ReeLspUtils
|
|
10
|
-
include RubyLsp::Ree::CompletionUtils
|
|
11
|
-
|
|
12
|
-
CHARS_COUNT = 1
|
|
13
|
-
CANDIDATES_LIMIT = 100
|
|
14
|
-
|
|
15
|
-
def initialize(response_builder, node_context, index, dispatcher, uri)
|
|
16
|
-
@response_builder = response_builder
|
|
17
|
-
@index = index
|
|
18
|
-
@uri = uri
|
|
19
|
-
@node_context = node_context
|
|
20
|
-
|
|
21
|
-
dispatcher.register(self, :on_call_node_enter)
|
|
22
|
-
dispatcher.register(self, :on_constant_read_node_enter)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def on_constant_read_node_enter(node)
|
|
26
|
-
node_name = node.name.to_s
|
|
27
|
-
return if node_name.size < CHARS_COUNT
|
|
28
|
-
|
|
29
|
-
class_name_objects = @index.instance_variable_get(:@entries).keys.select{ _1.split('::').last[0...node_name.size] == node_name}
|
|
30
|
-
return if class_name_objects.size == 0
|
|
31
|
-
|
|
32
|
-
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_ast(@node_context.parent, @uri)
|
|
33
|
-
|
|
34
|
-
completion_items = get_class_name_completion_items(class_name_objects, parsed_doc, node, @index, CANDIDATES_LIMIT)
|
|
35
|
-
put_items_into_response(completion_items)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def on_call_node_enter(node)
|
|
39
|
-
if receiver_is_enum?(node)
|
|
40
|
-
return enum_value_completion(node)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
if receiver_is_dao?(node)
|
|
44
|
-
return dao_filter_completion(node)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
if receiver_is_bean?(node)
|
|
48
|
-
return bean_method_completion(node)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
return if node.receiver
|
|
52
|
-
return if node.name.to_s.size < CHARS_COUNT
|
|
53
|
-
|
|
54
|
-
ree_objects = ReeObjectFinder.search_objects(@index, node.name.to_s, CANDIDATES_LIMIT)
|
|
55
|
-
|
|
56
|
-
return if ree_objects.size == 0
|
|
57
|
-
|
|
58
|
-
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_ast(@node_context.parent, @uri)
|
|
59
|
-
|
|
60
|
-
completion_items = get_ree_objects_completions_items(ree_objects, parsed_doc, node)
|
|
61
|
-
put_items_into_response(completion_items)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def receiver_is_enum?(node)
|
|
65
|
-
node.receiver && node.receiver.is_a?(Prism::CallNode) && ReeObjectFinder.find_enum(@index, node.receiver.name.to_s)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def receiver_is_dao?(node)
|
|
69
|
-
node.receiver && node.receiver.is_a?(Prism::CallNode) && ReeObjectFinder.find_dao(@index, node.receiver.name.to_s)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def receiver_is_bean?(node)
|
|
73
|
-
node.receiver && node.receiver.is_a?(Prism::CallNode) && ReeObjectFinder.find_bean(@index, node.receiver.name.to_s)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def enum_value_completion(node)
|
|
77
|
-
enum_obj = ReeObjectFinder.find_enum(@index, node.receiver.name.to_s)
|
|
78
|
-
location = node.receiver.location
|
|
79
|
-
|
|
80
|
-
completion_items = get_enum_values_completion_items(enum_obj, location)
|
|
81
|
-
put_items_into_response(completion_items)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def dao_filter_completion(node)
|
|
85
|
-
dao_obj = ReeObjectFinder.find_dao(@index, node.receiver.name.to_s)
|
|
86
|
-
location = node.receiver.location
|
|
87
|
-
|
|
88
|
-
completion_items = get_dao_filters_completion_items(dao_obj, location)
|
|
89
|
-
put_items_into_response(completion_items)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def bean_method_completion(node)
|
|
93
|
-
bean_obj = ReeObjectFinder.find_bean(@index, node.receiver.name.to_s)
|
|
94
|
-
location = node.receiver.location
|
|
95
|
-
|
|
96
|
-
completion_items = get_bean_methods_completion_items(bean_obj, location)
|
|
97
|
-
|
|
98
|
-
put_items_into_response(completion_items)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def put_items_into_response(items)
|
|
102
|
-
items.each do |item|
|
|
103
|
-
@response_builder << item
|
|
104
|
-
end
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|