ruby-lsp-ree 0.1.13 → 0.1.14
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/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +16 -1
- data/lib/ruby_lsp/ruby_lsp_ree/addon.rb +8 -1
- data/lib/ruby_lsp/ruby_lsp_ree/formatters/base_formatter.rb +4 -3
- data/lib/ruby_lsp/ruby_lsp_ree/formatters/missing_error_contracts_formatter.rb +13 -4
- data/lib/ruby_lsp/ruby_lsp_ree/formatters/missing_error_definitions_formatter.rb +8 -3
- data/lib/ruby_lsp/ruby_lsp_ree/formatters/missing_error_locales_formatter.rb +1 -0
- data/lib/ruby_lsp/ruby_lsp_ree/formatters/unused_links_formatter.rb +56 -0
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_base_document.rb +4 -0
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_class_document.rb +29 -2
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_link_node.rb +34 -2
- data/lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_method_node.rb +27 -3
- data/lib/ruby_lsp/ruby_lsp_ree/ree_dsl_parser.rb +39 -0
- data/lib/ruby_lsp/ruby_lsp_ree/ree_formatter.rb +11 -4
- data/lib/ruby_lsp/ruby_lsp_ree/ree_source_editor.rb +68 -0
- data/lib/ruby_lsp_ree/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72573c4b291dbdfd4ed45bc81625bfc2dbc97839cdee93214e3af5358dfb8572
|
4
|
+
data.tar.gz: 82849950d1fa5a0c7eb95f17b2417b97136df143bc871f2ce44e869e2a7c9721
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5aba139740ca71509e49885a4135cbc838fd1ce444b2525d15962126f558c09448caa1478a8df33669d223169e081901b87d8d12464ebd1555825735f8d95ec7
|
7
|
+
data.tar.gz: 3e9673f5830791ce62a5dfbcb4e74cec6e3cd774fdfe7e447d9090cb4ae2063d881395bf39086e8158b697492f4e88eb68f35c55cd2b742fcba28d516075e853
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## [0.1.14] - 2025-04-15
|
2
|
+
|
3
|
+
- do not create error definition for defined class
|
4
|
+
- added formatter config settings
|
5
|
+
- formatter: remove unused imports
|
6
|
+
- fixed adding `throws` section to contract without parentheses
|
7
|
+
|
1
8
|
## [0.1.13] - 2025-04-04
|
2
9
|
|
3
10
|
- Go To Definition for action and serializers in routes
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -10,6 +10,8 @@ Ree addon for Ruby LSP
|
|
10
10
|
If everything was installed successfully, you should see Ree in the list of Ruby LSP addons.
|
11
11
|
(In VS Code click `{}` brackets in the bottom right corner)
|
12
12
|
|
13
|
+
## Formatter
|
14
|
+
|
13
15
|
To use ree_formatter, add the following line into your `settings.json` file (e.g. `.vscode/settings.json`)
|
14
16
|
```json
|
15
17
|
"rubyLsp.formatter": "ree_formatter"
|
@@ -20,6 +22,18 @@ To use diagnostics, add the following line into your `settings.json` file (e.g.
|
|
20
22
|
"rubyLsp.linters": ["ree_formatter"]
|
21
23
|
```
|
22
24
|
|
25
|
+
To switch off/on formatter features, use Ruby LSP addon settings:
|
26
|
+
```json
|
27
|
+
"rubyLsp.addonSettings": {
|
28
|
+
"Ree Addon": {
|
29
|
+
"formatter": {
|
30
|
+
"MissingErrorLocalesFormatter": false
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
```
|
35
|
+
available formatters: `SortLinksFormatter`, `MissingErrorDefinitionsFormatter`, `MissingErrorContractsFormatter`, `MissingErrorLocalesFormatter`, `UnusedLinksFormatter`
|
36
|
+
|
23
37
|
## Functions
|
24
38
|
|
25
39
|
- autocomplete for Ree objects
|
@@ -28,4 +42,5 @@ To use diagnostics, add the following line into your `settings.json` file (e.g.
|
|
28
42
|
- sort links on document save or format (with ree_formatter enabled)
|
29
43
|
- missing error locales detection
|
30
44
|
- Go To Definition for Ree objects
|
31
|
-
- hover information for Ree objects and error locales
|
45
|
+
- hover information for Ree objects and error locales
|
46
|
+
- Ree templates support
|
@@ -15,10 +15,17 @@ module RubyLsp
|
|
15
15
|
class Addon < ::RubyLsp::Addon
|
16
16
|
def activate(global_state, message_queue)
|
17
17
|
@global_state = global_state
|
18
|
+
@settings = global_state.settings_for_addon(name) || {}
|
19
|
+
|
18
20
|
@message_queue = message_queue
|
19
21
|
@template_applicator = RubyLsp::Ree::ReeTemplateApplicator.new
|
22
|
+
|
23
|
+
global_state.register_formatter("ree_formatter", RubyLsp::Ree::ReeFormatter.new(
|
24
|
+
@message_queue,
|
25
|
+
@settings[:formatter],
|
26
|
+
@global_state.index
|
27
|
+
))
|
20
28
|
|
21
|
-
global_state.register_formatter("ree_formatter", RubyLsp::Ree::ReeFormatter.new(@message_queue))
|
22
29
|
register_additional_file_watchers(global_state, message_queue)
|
23
30
|
end
|
24
31
|
|
@@ -1,12 +1,13 @@
|
|
1
1
|
module RubyLsp
|
2
2
|
module Ree
|
3
3
|
class BaseFormatter
|
4
|
-
def self.call(source, uri, message_queue)
|
5
|
-
new(message_queue).call(source, uri)
|
4
|
+
def self.call(source, uri, message_queue, index)
|
5
|
+
new(message_queue, index).call(source, uri)
|
6
6
|
end
|
7
7
|
|
8
|
-
def initialize(message_queue)
|
8
|
+
def initialize(message_queue, index)
|
9
9
|
@message_queue = message_queue
|
10
|
+
@index = index
|
10
11
|
end
|
11
12
|
|
12
13
|
def call(source, uri)
|
@@ -5,7 +5,7 @@ module RubyLsp
|
|
5
5
|
class MissingErrorContractsFormatter < BaseFormatter
|
6
6
|
def call(source, _uri)
|
7
7
|
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_source(source)
|
8
|
-
return source if !parsed_doc || !parsed_doc.
|
8
|
+
return source if !parsed_doc || !parsed_doc.has_root_class?
|
9
9
|
|
10
10
|
parsed_doc.parse_error_definitions
|
11
11
|
parsed_doc.parse_instance_methods
|
@@ -40,10 +40,19 @@ module RubyLsp
|
|
40
40
|
source_lines[line] = source_lines[line][0..position] + ", #{missed_errors.join(', ')}\n"
|
41
41
|
end
|
42
42
|
else
|
43
|
-
|
44
|
-
|
43
|
+
if doc_instance_method.contract_in_parentheses?
|
44
|
+
position = doc_instance_method.contract_node_end_position
|
45
|
+
line = doc_instance_method.contract_node_end_line
|
45
46
|
|
46
|
-
|
47
|
+
source_lines[line] = source_lines[line][0..position] + ".throws(#{missed_errors.join(', ')})\n"
|
48
|
+
else
|
49
|
+
contract_end_position = doc_instance_method.contract_node_contract_end_position
|
50
|
+
start_line = doc_instance_method.contract_node_start_line
|
51
|
+
end_line = doc_instance_method.contract_node_end_line
|
52
|
+
|
53
|
+
source_lines[start_line] = source_lines[start_line][0..contract_end_position] + "(" + source_lines[start_line][contract_end_position+1..-1].lstrip
|
54
|
+
source_lines[end_line] = source_lines[end_line].chomp + ").throws(#{missed_errors.join(', ')})\n"
|
55
|
+
end
|
47
56
|
end
|
48
57
|
|
49
58
|
source_lines.join
|
@@ -7,13 +7,18 @@ module RubyLsp
|
|
7
7
|
|
8
8
|
def call(source, _uri)
|
9
9
|
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_source(source)
|
10
|
-
return source if !parsed_doc || !parsed_doc.
|
10
|
+
return source if !parsed_doc || !parsed_doc.has_root_class?
|
11
11
|
|
12
12
|
parsed_doc.parse_error_definitions
|
13
13
|
parsed_doc.parse_instance_methods
|
14
14
|
parsed_doc.parse_links
|
15
|
+
parsed_doc.parse_defined_classes
|
16
|
+
parsed_doc.parse_defined_consts
|
15
17
|
|
16
|
-
|
18
|
+
existing_error_classes = parsed_doc.error_definition_names +
|
19
|
+
parsed_doc.imported_constants +
|
20
|
+
parsed_doc.defined_classes +
|
21
|
+
parsed_doc.defined_consts
|
17
22
|
|
18
23
|
missed_errors = []
|
19
24
|
parsed_doc.doc_instance_methods.each do |doc_instance_method|
|
@@ -21,7 +26,7 @@ module RubyLsp
|
|
21
26
|
|
22
27
|
raised_errors = doc_instance_method.raised_errors_nested
|
23
28
|
|
24
|
-
missed_errors += raised_errors -
|
29
|
+
missed_errors += raised_errors - existing_error_classes
|
25
30
|
end
|
26
31
|
|
27
32
|
missed_errors = missed_errors.uniq.reject{ Object.const_defined?(_1) }
|
@@ -10,6 +10,7 @@ module RubyLsp
|
|
10
10
|
|
11
11
|
def call(source, uri)
|
12
12
|
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_source(source)
|
13
|
+
return source if !parsed_doc || !parsed_doc.has_root_class?
|
13
14
|
|
14
15
|
locales_folder = package_locales_folder_path(get_uri_path(uri))
|
15
16
|
return source if !locales_folder || !File.directory?(locales_folder)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'base_formatter'
|
2
|
+
require_relative '../ree_source_editor'
|
3
|
+
require_relative '../ree_dsl_parser'
|
4
|
+
|
5
|
+
module RubyLsp
|
6
|
+
module Ree
|
7
|
+
class UnusedLinksFormatter < BaseFormatter
|
8
|
+
include RubyLsp::Ree::ReeLspUtils
|
9
|
+
|
10
|
+
def call(source, _uri)
|
11
|
+
parsed_doc = RubyLsp::Ree::ParsedDocumentBuilder.build_from_source(source)
|
12
|
+
return source if !parsed_doc
|
13
|
+
|
14
|
+
parsed_doc.parse_links
|
15
|
+
|
16
|
+
editor = RubyLsp::Ree::ReeSourceEditor.new(source)
|
17
|
+
dsl_parser = RubyLsp::Ree::ReeDslParser.new(parsed_doc, @index)
|
18
|
+
|
19
|
+
links_count = parsed_doc.link_nodes.size
|
20
|
+
|
21
|
+
removed_links = 0
|
22
|
+
|
23
|
+
parsed_doc.link_nodes.each do |link_node|
|
24
|
+
removed_imports = 0
|
25
|
+
|
26
|
+
if link_node.has_import_section?
|
27
|
+
link_node.imports.each do |link_import|
|
28
|
+
# TODO extract condition
|
29
|
+
next if editor.contains_link_import_usage?(link_node, link_import) || dsl_parser.contains_object_usage?(link_import)
|
30
|
+
|
31
|
+
editor.remove_link_import(link_node, link_import)
|
32
|
+
removed_imports += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
if link_node.imports.size == removed_imports
|
36
|
+
editor.remove_link_import_arg(link_node)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO extract condition
|
41
|
+
next if editor.contains_link_usage?(link_node) || link_node.imports.size > removed_imports || dsl_parser.contains_object_usage?(link_node.name)
|
42
|
+
|
43
|
+
editor.remove_link(link_node)
|
44
|
+
removed_links += 1
|
45
|
+
end
|
46
|
+
|
47
|
+
if removed_links == links_count
|
48
|
+
parsed_doc.parse_links_container_node
|
49
|
+
editor.remove_link_block(parsed_doc.links_container_node, parsed_doc.links_container_block_node)
|
50
|
+
end
|
51
|
+
|
52
|
+
editor.source
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -10,7 +10,8 @@ class RubyLsp::Ree::ParsedClassDocument < RubyLsp::Ree::ParsedBaseDocument
|
|
10
10
|
|
11
11
|
attr_reader :class_node, :class_includes,
|
12
12
|
:values, :filters, :bean_methods, :links_container_block_node, :error_definitions,
|
13
|
-
:error_definition_names, :doc_instance_methods, :links_container_node
|
13
|
+
:error_definition_names, :doc_instance_methods, :links_container_node,
|
14
|
+
:defined_classes, :defined_consts
|
14
15
|
|
15
16
|
def initialize(ast, package_name = nil)
|
16
17
|
super
|
@@ -37,6 +38,10 @@ class RubyLsp::Ree::ParsedClassDocument < RubyLsp::Ree::ParsedBaseDocument
|
|
37
38
|
@class_includes.any?{ node_name(_1) == ROUTES_DSL_MODULE }
|
38
39
|
end
|
39
40
|
|
41
|
+
def includes_ree_dsl?
|
42
|
+
ree_dsls.size > 0
|
43
|
+
end
|
44
|
+
|
40
45
|
def includes_linked_constant?(const_name)
|
41
46
|
@link_nodes.map(&:imports).flatten.include?(const_name)
|
42
47
|
end
|
@@ -106,7 +111,7 @@ class RubyLsp::Ree::ParsedClassDocument < RubyLsp::Ree::ParsedBaseDocument
|
|
106
111
|
|
107
112
|
@link_nodes = nodes.map do |link_node|
|
108
113
|
link_node = RubyLsp::Ree::ParsedLinkNode.new(link_node, package_name)
|
109
|
-
link_node.parse_imports
|
114
|
+
link_node.parse_imports # TODO move parse imports inside link_node constructor
|
110
115
|
link_node
|
111
116
|
end
|
112
117
|
end
|
@@ -179,6 +184,24 @@ class RubyLsp::Ree::ParsedClassDocument < RubyLsp::Ree::ParsedBaseDocument
|
|
179
184
|
@error_definition_names = @error_definitions.map(&:name)
|
180
185
|
end
|
181
186
|
|
187
|
+
def parse_defined_classes
|
188
|
+
@defined_classes = []
|
189
|
+
return unless has_body?
|
190
|
+
|
191
|
+
@defined_classes = class_node.body.body
|
192
|
+
.select{ _1.is_a?(Prism::ClassNode) }
|
193
|
+
.map(&:name)
|
194
|
+
end
|
195
|
+
|
196
|
+
def parse_defined_consts
|
197
|
+
@defined_consts = []
|
198
|
+
return unless has_body?
|
199
|
+
|
200
|
+
@defined_consts += class_node.body.body
|
201
|
+
.select{ _1.is_a?(Prism::ConstantWriteNode) }
|
202
|
+
.map(&:name)
|
203
|
+
end
|
204
|
+
|
182
205
|
def class_name
|
183
206
|
class_node.constant_path.name.to_s
|
184
207
|
end
|
@@ -199,4 +222,8 @@ class RubyLsp::Ree::ParsedClassDocument < RubyLsp::Ree::ParsedBaseDocument
|
|
199
222
|
def imported_constants
|
200
223
|
@link_nodes.map(&:imports).flatten.map(&:to_sym)
|
201
224
|
end
|
225
|
+
|
226
|
+
def ree_dsls
|
227
|
+
@class_includes.select{ node_name(_1).downcase.match?(/ree/) && node_name(_1).downcase.match?(/dsl/)}
|
228
|
+
end
|
202
229
|
end
|
@@ -81,6 +81,27 @@ class RubyLsp::Ree::ParsedLinkNode
|
|
81
81
|
!!import_arg
|
82
82
|
end
|
83
83
|
|
84
|
+
def first_arg_location
|
85
|
+
@node.arguments.arguments.first.location
|
86
|
+
end
|
87
|
+
|
88
|
+
def import_block_open_location
|
89
|
+
if object_name_type?
|
90
|
+
import_arg.value.opening_loc
|
91
|
+
else
|
92
|
+
import_arg.opening_loc
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def import_block_close_location
|
97
|
+
# TODO maybe use two classes for link types
|
98
|
+
if object_name_type?
|
99
|
+
import_arg.value.closing_loc
|
100
|
+
else
|
101
|
+
import_arg.closing_loc
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
84
105
|
private
|
85
106
|
|
86
107
|
def last_arg
|
@@ -100,9 +121,12 @@ class RubyLsp::Ree::ParsedLinkNode
|
|
100
121
|
|
101
122
|
if object_name_type?
|
102
123
|
return [] unless import_arg
|
103
|
-
|
124
|
+
import_body = import_arg.value.body.body.first
|
125
|
+
parse_object_link_multiple_imports(import_body)
|
104
126
|
elsif last_arg.is_a?(Prism::LambdaNode)
|
105
|
-
[last_arg.body
|
127
|
+
return [] unless last_arg.body
|
128
|
+
import_body = last_arg.body.body.first
|
129
|
+
parse_object_link_multiple_imports(import_body)
|
106
130
|
else
|
107
131
|
return []
|
108
132
|
end
|
@@ -110,4 +134,12 @@ class RubyLsp::Ree::ParsedLinkNode
|
|
110
134
|
$stderr.puts("can't parse imports: #{e.message}")
|
111
135
|
return []
|
112
136
|
end
|
137
|
+
|
138
|
+
def parse_object_link_multiple_imports(import_body)
|
139
|
+
if import_body.is_a?(Prism::CallNode)
|
140
|
+
parse_object_link_multiple_imports(import_body.receiver) + [import_body.arguments.arguments.first.name.to_s]
|
141
|
+
else
|
142
|
+
[import_body.name.to_s]
|
143
|
+
end
|
144
|
+
end
|
113
145
|
end
|
@@ -82,6 +82,18 @@ class RubyLsp::Ree::ParsedMethodNode
|
|
82
82
|
def contract_node_end_line
|
83
83
|
@contract_node.location.end_line - 1
|
84
84
|
end
|
85
|
+
|
86
|
+
def contract_node_start_line
|
87
|
+
@contract_node.location.start_line - 1
|
88
|
+
end
|
89
|
+
|
90
|
+
def contract_node_contract_end_position
|
91
|
+
@contract_node.message_loc.end_column - 1
|
92
|
+
end
|
93
|
+
|
94
|
+
def contract_in_parentheses?
|
95
|
+
@contract_node.opening == '(' && @contract_node.closing == ')'
|
96
|
+
end
|
85
97
|
|
86
98
|
def parse_nested_local_methods(local_methods)
|
87
99
|
unless @method_node.body
|
@@ -91,9 +103,9 @@ class RubyLsp::Ree::ParsedMethodNode
|
|
91
103
|
|
92
104
|
method_body = get_method_body(@method_node)
|
93
105
|
|
94
|
-
local_method_names = local_methods.map(&:name)
|
95
106
|
call_nodes = parse_body_call_objects(method_body)
|
96
|
-
|
107
|
+
call_expressions = parse_body_call_expressions(method_body)
|
108
|
+
call_node_names = call_nodes.map(&:name) + call_expressions
|
97
109
|
|
98
110
|
@nested_local_methods = local_methods.select{ call_node_names.include?(_1.name) }
|
99
111
|
@nested_local_methods.each{ _1.parse_nested_local_methods(local_methods) }
|
@@ -107,7 +119,7 @@ class RubyLsp::Ree::ParsedMethodNode
|
|
107
119
|
call_nodes << node
|
108
120
|
elsif node.respond_to?(:statements)
|
109
121
|
call_nodes += parse_body_call_objects(node.statements.body)
|
110
|
-
elsif node.respond_to?(:block) && node.block
|
122
|
+
elsif node.respond_to?(:block) && node.block && node.block.is_a?(Prism::BlockNode)
|
111
123
|
call_nodes += parse_body_call_objects(get_method_body(node.block))
|
112
124
|
end
|
113
125
|
end
|
@@ -115,6 +127,18 @@ class RubyLsp::Ree::ParsedMethodNode
|
|
115
127
|
call_nodes
|
116
128
|
end
|
117
129
|
|
130
|
+
def parse_body_call_expressions(node_body)
|
131
|
+
call_expressions = []
|
132
|
+
|
133
|
+
node_body.each do |node|
|
134
|
+
if node.respond_to?(:block) && node.block && node.block.is_a?(Prism::BlockArgumentNode) && node.block.expression.is_a?(Prism::SymbolNode)
|
135
|
+
call_expressions << node.block.expression.unescaped.to_sym
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
call_expressions
|
140
|
+
end
|
141
|
+
|
118
142
|
def get_method_body(node)
|
119
143
|
if node.body.is_a?(Prism::BeginNode)
|
120
144
|
node.body.statements.body
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module RubyLsp
|
2
|
+
module Ree
|
3
|
+
class ReeDslParser
|
4
|
+
include RubyLsp::Ree::ReeLspUtils
|
5
|
+
|
6
|
+
attr_reader :parsed_doc
|
7
|
+
|
8
|
+
def initialize(parsed_doc, index)
|
9
|
+
@parsed_doc = parsed_doc
|
10
|
+
@index = index
|
11
|
+
end
|
12
|
+
|
13
|
+
def contains_object_usage?(obj_name)
|
14
|
+
return false unless @index
|
15
|
+
return false unless parsed_doc.includes_ree_dsl?
|
16
|
+
|
17
|
+
parsed_doc.ree_dsls.any? do |ree_dsl|
|
18
|
+
ree_dsl_contains_object_usage?(ree_dsl.name, obj_name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def ree_dsl_contains_object_usage?(dsl_name, obj_name)
|
25
|
+
dsl_objects = @index[dsl_name]
|
26
|
+
return unless dsl_objects
|
27
|
+
|
28
|
+
uris = dsl_objects.map(&:uri)
|
29
|
+
|
30
|
+
uris.any?{ file_contains_object_usage?(_1, obj_name) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def file_contains_object_usage?(file_uri, obj_name)
|
34
|
+
file_content = File.read(file_uri.path.to_s)
|
35
|
+
file_content.match?(/\W#{obj_name}\W/)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,6 +2,7 @@ require_relative 'formatters/sort_links_formatter'
|
|
2
2
|
require_relative 'formatters/missing_error_definitions_formatter'
|
3
3
|
require_relative 'formatters/missing_error_contracts_formatter'
|
4
4
|
require_relative 'formatters/missing_error_locales_formatter'
|
5
|
+
require_relative 'formatters/unused_links_formatter'
|
5
6
|
|
6
7
|
module RubyLsp
|
7
8
|
module Ree
|
@@ -12,8 +13,10 @@ module RubyLsp
|
|
12
13
|
|
13
14
|
MISSING_LOCALE_PLACEHOLDER = '_MISSING_LOCALE_'
|
14
15
|
|
15
|
-
def initialize(message_queue)
|
16
|
+
def initialize(message_queue, settings, index = nil)
|
16
17
|
@message_queue = message_queue
|
18
|
+
@settings = settings || {}
|
19
|
+
@index = index
|
17
20
|
end
|
18
21
|
|
19
22
|
def run_formatting(uri, document)
|
@@ -23,10 +26,14 @@ module RubyLsp
|
|
23
26
|
RubyLsp::Ree::SortLinksFormatter,
|
24
27
|
RubyLsp::Ree::MissingErrorDefinitionsFormatter,
|
25
28
|
RubyLsp::Ree::MissingErrorContractsFormatter,
|
26
|
-
RubyLsp::Ree::MissingErrorLocalesFormatter
|
27
|
-
|
29
|
+
RubyLsp::Ree::MissingErrorLocalesFormatter,
|
30
|
+
RubyLsp::Ree::UnusedLinksFormatter,
|
31
|
+
].select do |formatter|
|
32
|
+
formatter_name = formatter.name.split('::').last.to_sym
|
33
|
+
@settings[formatter_name] != false
|
34
|
+
end
|
28
35
|
|
29
|
-
formatters.reduce(source){ |s, formatter| formatter.call(s, uri, @message_queue) }
|
36
|
+
formatters.reduce(source){ |s, formatter| formatter.call(s, uri, @message_queue, @index) }
|
30
37
|
rescue => e
|
31
38
|
$stderr.puts("error in ree_formatter: #{e.message} : #{e.backtrace.first}")
|
32
39
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module RubyLsp
|
2
|
+
module Ree
|
3
|
+
class ReeSourceEditor
|
4
|
+
include RubyLsp::Ree::ReeLspUtils
|
5
|
+
|
6
|
+
attr_reader :source_lines
|
7
|
+
|
8
|
+
def initialize(source)
|
9
|
+
@source_lines = source.lines
|
10
|
+
end
|
11
|
+
|
12
|
+
def source
|
13
|
+
@source_lines.join
|
14
|
+
end
|
15
|
+
|
16
|
+
def contains_link_usage?(link_node)
|
17
|
+
source_lines_except_link = source_lines[0...(link_node.location.start_line-1)] + source_lines[(link_node.location.end_line)..-1]
|
18
|
+
source_lines_except_link.any?{ |source_line| source_line.match?(/\W#{link_node.name}\W/)}
|
19
|
+
end
|
20
|
+
|
21
|
+
def contains_link_import_usage?(link_node, link_import)
|
22
|
+
source_lines_except_link = source_lines[0...(link_node.location.start_line-1)] + source_lines[(link_node.location.end_line)..-1]
|
23
|
+
source_lines_except_link.any?{ |source_line| source_line.match?(/\W#{link_import}\W/)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove_link(link_node)
|
27
|
+
set_empty_lines!(link_node.location.start_line-1, link_node.location.end_line-1)
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove_link_import(link_node, link_import)
|
31
|
+
imports_str = link_node.imports.reject{ _1 == link_import}.join(' & ')
|
32
|
+
|
33
|
+
block_start_col = link_node.import_block_open_location.start_column
|
34
|
+
block_line = link_node.import_block_open_location.start_line-1
|
35
|
+
block_end_line = link_node.import_block_close_location.end_line-1
|
36
|
+
|
37
|
+
source_lines[block_line] = source_lines[block_line][0..block_start_col] + " #{imports_str} }\n"
|
38
|
+
set_empty_lines!(block_line+1, block_end_line)
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_link_import_arg(link_node)
|
42
|
+
link_line = link_node.location.start_line - 1
|
43
|
+
link_end_line = link_node.location.end_line - 1
|
44
|
+
link_name_end = link_node.first_arg_location.end_column - 1
|
45
|
+
|
46
|
+
source_lines[link_line] = source_lines[link_line][0..link_name_end] + "\n"
|
47
|
+
set_empty_lines!(link_line+1, link_end_line)
|
48
|
+
end
|
49
|
+
|
50
|
+
def remove_link_block(links_container_node, links_container_block_node)
|
51
|
+
return source_lines unless links_container_block_node
|
52
|
+
|
53
|
+
link_container_start_line = links_container_node.location.start_line-1
|
54
|
+
link_container_end_line = links_container_node.location.end_line-1
|
55
|
+
block_start = links_container_block_node.location.start_column-1
|
56
|
+
|
57
|
+
source_lines[link_container_start_line] = source_lines[link_container_start_line][0..block_start] + "\n"
|
58
|
+
set_empty_lines!(link_container_start_line+1, link_container_end_line)
|
59
|
+
end
|
60
|
+
|
61
|
+
def set_empty_lines!(start_line, end_line)
|
62
|
+
(start_line .. end_line).each do |i|
|
63
|
+
source_lines[i] = ''
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/ruby_lsp_ree/version.rb
CHANGED
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.14
|
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-04-
|
11
|
+
date: 2025-04-15 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:
|
@@ -31,6 +31,7 @@ files:
|
|
31
31
|
- lib/ruby_lsp/ruby_lsp_ree/formatters/missing_error_definitions_formatter.rb
|
32
32
|
- lib/ruby_lsp/ruby_lsp_ree/formatters/missing_error_locales_formatter.rb
|
33
33
|
- lib/ruby_lsp/ruby_lsp_ree/formatters/sort_links_formatter.rb
|
34
|
+
- lib/ruby_lsp/ruby_lsp_ree/formatters/unused_links_formatter.rb
|
34
35
|
- lib/ruby_lsp/ruby_lsp_ree/handlers/completion_handler.rb
|
35
36
|
- lib/ruby_lsp/ruby_lsp_ree/handlers/const_additional_text_edits_creator.rb
|
36
37
|
- lib/ruby_lsp/ruby_lsp_ree/handlers/definition_handler.rb
|
@@ -48,10 +49,12 @@ files:
|
|
48
49
|
- lib/ruby_lsp/ruby_lsp_ree/parsing/parsed_rspec_document.rb
|
49
50
|
- lib/ruby_lsp/ruby_lsp_ree/ree_constants.rb
|
50
51
|
- lib/ruby_lsp/ruby_lsp_ree/ree_context.rb
|
52
|
+
- lib/ruby_lsp/ruby_lsp_ree/ree_dsl_parser.rb
|
51
53
|
- lib/ruby_lsp/ruby_lsp_ree/ree_formatter.rb
|
52
54
|
- lib/ruby_lsp/ruby_lsp_ree/ree_indexing_enhancement.rb
|
53
55
|
- lib/ruby_lsp/ruby_lsp_ree/ree_object_finder.rb
|
54
56
|
- lib/ruby_lsp/ruby_lsp_ree/ree_rename_handler.rb
|
57
|
+
- lib/ruby_lsp/ruby_lsp_ree/ree_source_editor.rb
|
55
58
|
- lib/ruby_lsp/ruby_lsp_ree/ree_template_applicator.rb
|
56
59
|
- lib/ruby_lsp/ruby_lsp_ree/utils/ree_locale_utils.rb
|
57
60
|
- lib/ruby_lsp/ruby_lsp_ree/utils/ree_lsp_utils.rb
|