glib-web 5.1.5 → 6.3.1
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/app/controllers/concerns/glib/json/ui.rb +10 -0
- data/app/controllers/glib/errors_controller.rb +57 -1
- data/app/helpers/glib/json_ui/action_builder/logics.rb +14 -0
- data/app/helpers/glib/json_ui/action_builder/windows.rb +20 -5
- data/app/helpers/glib/json_ui/json_logic_lint.rb +82 -0
- data/app/helpers/glib/json_ui/view_builder/panels.rb +14 -0
- data/app/views/json_ui/garage/test_page/fields_upload.json.jbuilder +1 -1
- data/app/views/json_ui/garage/test_page/form_dirty_hooks.json.jbuilder +31 -0
- data/app/views/json_ui/garage/test_page/form_dynamic_dirty.json.jbuilder +41 -0
- data/app/views/json_ui/garage/test_page/form_removed_field.json.jbuilder +55 -0
- data/app/views/json_ui/garage/test_page/form_removed_field_onload.json.jbuilder +34 -0
- data/app/views/json_ui/garage/test_page/form_touched_validation.json.jbuilder +35 -0
- data/app/views/json_ui/garage/test_page/logics_run.json.jbuilder +79 -0
- data/app/views/json_ui/garage/test_page/logics_run_multi_form.json.jbuilder +45 -0
- data/app/views/json_ui/garage/test_page/logics_set.json.jbuilder +19 -0
- data/app/views/json_ui/garage/test_page/panels_bulkEdit2.json.jbuilder +3 -0
- data/app/views/json_ui/garage/test_page/run_multiple.json.jbuilder +31 -0
- data/app/views/json_ui/garage/test_page/windows_reload.json.jbuilder +57 -0
- data/lib/glib/engine.rb +132 -0
- data/lib/glib/rubocop.rb +0 -1
- data/lib/glib/snapshot.rb +57 -12
- data/lib/glib/test/parallel_coverage.rb +16 -0
- data/lib/tasks/db.rake +6 -0
- metadata +12 -3
- data/lib/glib/rubocop/cops/multiline_method_call_style.rb +0 -250
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module RuboCop
|
|
4
|
-
module Cop
|
|
5
|
-
module Glib
|
|
6
|
-
# Enforces parentheses style for multi-line method calls with arguments.
|
|
7
|
-
#
|
|
8
|
-
# @example
|
|
9
|
-
# # bad
|
|
10
|
-
# page.footer padding: glib_json_padding_body, backgroundColor: '#b3bac2', childViews: ->(footer) do
|
|
11
|
-
# footer.h1 text: 'Footer'
|
|
12
|
-
# end
|
|
13
|
-
#
|
|
14
|
-
# # bad
|
|
15
|
-
# page.footer \
|
|
16
|
-
# padding: glib_json_padding_body,
|
|
17
|
-
# backgroundColor: '#b3bac2',
|
|
18
|
-
# childViews: ->(footer) do
|
|
19
|
-
# footer.h1 text: 'Footer'
|
|
20
|
-
# end
|
|
21
|
-
#
|
|
22
|
-
# # good
|
|
23
|
-
# page.footer(
|
|
24
|
-
# padding: glib_json_padding_body,
|
|
25
|
-
# backgroundColor: '#b3bac2',
|
|
26
|
-
# childViews: ->(footer) do
|
|
27
|
-
# footer.h1 text: 'Footer'
|
|
28
|
-
# end
|
|
29
|
-
# )
|
|
30
|
-
class MultilineMethodCallStyle < Base
|
|
31
|
-
extend AutoCorrector
|
|
32
|
-
|
|
33
|
-
MSG = 'Use parentheses style for multi-line method calls: ' \
|
|
34
|
-
'wrap arguments in parentheses and place each argument on its own line.'
|
|
35
|
-
|
|
36
|
-
def on_send(node)
|
|
37
|
-
return unless multi_line_call_with_args?(node)
|
|
38
|
-
return if proper_parentheses_style?(node)
|
|
39
|
-
return if proper_backslash_style?(node) && allow_backslash?
|
|
40
|
-
return if inside_correctable_parent?(node)
|
|
41
|
-
|
|
42
|
-
add_offense(node) do |corrector|
|
|
43
|
-
autocorrect(corrector, node)
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
alias on_csend on_send
|
|
48
|
-
|
|
49
|
-
private
|
|
50
|
-
|
|
51
|
-
def multi_line_call_with_args?(node)
|
|
52
|
-
node.multiline? && node.arguments.any?
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def allow_backslash?
|
|
56
|
-
# Allow backslash style without warnings when configured
|
|
57
|
-
# Set to true to allow both styles (but auto-correct will still convert to parentheses)
|
|
58
|
-
# Set to false to enforce parentheses style always
|
|
59
|
-
cop_config.fetch('AllowBackslashStyle', true)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def proper_backslash_style?(node)
|
|
63
|
-
source = processed_source.buffer.source
|
|
64
|
-
method_end_pos = node.loc.selector.end_pos
|
|
65
|
-
|
|
66
|
-
# Check if there's a backslash right after the method name
|
|
67
|
-
next_char_pos = method_end_pos
|
|
68
|
-
while next_char_pos < source.length && source[next_char_pos] == ' '
|
|
69
|
-
next_char_pos += 1
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
return false unless source[next_char_pos] == '\\'
|
|
73
|
-
|
|
74
|
-
# Check that each argument is on its own line
|
|
75
|
-
args = collect_arguments(node)
|
|
76
|
-
return false if args.empty?
|
|
77
|
-
|
|
78
|
-
args.each_cons(2) do |arg1, arg2|
|
|
79
|
-
return false if arg1.loc.line == arg2.loc.line
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
true
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def proper_parentheses_style?(node)
|
|
86
|
-
return false unless node.parenthesized?
|
|
87
|
-
|
|
88
|
-
# Check that first argument is on a new line after opening paren
|
|
89
|
-
first_arg = node.first_argument
|
|
90
|
-
return false if first_arg.loc.line == node.loc.selector.line
|
|
91
|
-
|
|
92
|
-
# Check that each argument is on its own line
|
|
93
|
-
args = collect_arguments(node)
|
|
94
|
-
return false if args.empty?
|
|
95
|
-
|
|
96
|
-
args.each_cons(2) do |arg1, arg2|
|
|
97
|
-
return false if arg1.loc.line == arg2.loc.line
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
# Check that closing paren is on its own line
|
|
101
|
-
source = processed_source.buffer.source
|
|
102
|
-
close_paren_pos = node.loc.end.begin_pos
|
|
103
|
-
line_start = source.rindex("\n", close_paren_pos) || 0
|
|
104
|
-
line_content = source[line_start...close_paren_pos].strip
|
|
105
|
-
|
|
106
|
-
return false unless line_content.empty?
|
|
107
|
-
|
|
108
|
-
true
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
def collect_arguments(node)
|
|
112
|
-
args = []
|
|
113
|
-
|
|
114
|
-
node.arguments.each do |arg|
|
|
115
|
-
if arg.hash_type?
|
|
116
|
-
# For hash arguments, treat each pair as a separate argument
|
|
117
|
-
arg.pairs.each { |pair| args << pair }
|
|
118
|
-
else
|
|
119
|
-
args << arg
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
args
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def inside_correctable_parent?(node)
|
|
127
|
-
# Check if this node is inside a block that belongs to a multi-line call
|
|
128
|
-
# that will also be corrected. If so, skip this node to avoid conflicts.
|
|
129
|
-
current = node.parent
|
|
130
|
-
|
|
131
|
-
while current
|
|
132
|
-
if current.send_type? || current.csend_type?
|
|
133
|
-
if multi_line_call_with_args?(current) && !proper_parentheses_style?(current)
|
|
134
|
-
return true
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
current = current.parent
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
false
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def autocorrect(corrector, node)
|
|
144
|
-
method_end_pos = node.loc.selector.end_pos
|
|
145
|
-
|
|
146
|
-
# Calculate indentation based on the node's actual column position
|
|
147
|
-
base_indent = node.loc.column
|
|
148
|
-
arg_indent = ' ' * (base_indent + 2)
|
|
149
|
-
|
|
150
|
-
# Build the new argument list
|
|
151
|
-
arg_parts = []
|
|
152
|
-
node.arguments.each do |arg|
|
|
153
|
-
next if arg.block_pass_type? # Skip block arguments like &block
|
|
154
|
-
|
|
155
|
-
if arg.hash_type?
|
|
156
|
-
arg.pairs.each do |pair|
|
|
157
|
-
# Re-indent pair if it contains a block
|
|
158
|
-
pair_source = reindent_pair_with_block(pair, arg_indent)
|
|
159
|
-
arg_parts << pair_source
|
|
160
|
-
end
|
|
161
|
-
else
|
|
162
|
-
arg_parts << arg.source
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
# Build the replacement with parentheses style
|
|
167
|
-
if arg_parts.any?
|
|
168
|
-
# Opening paren on same line as method, arguments on separate lines
|
|
169
|
-
replacement = "(\n#{arg_indent}" + arg_parts.join(",\n#{arg_indent}")
|
|
170
|
-
|
|
171
|
-
# If there's a block, add it on the last argument line
|
|
172
|
-
if node.block_literal?
|
|
173
|
-
block_source = reindent_block(node.block_literal, arg_indent)
|
|
174
|
-
replacement += " #{block_source}"
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
# Closing paren on its own line at base indentation
|
|
178
|
-
replacement += "\n#{' ' * base_indent})"
|
|
179
|
-
else
|
|
180
|
-
# No arguments, just the block (shouldn't happen for multi-line, but handle it)
|
|
181
|
-
replacement = if node.block_literal?
|
|
182
|
-
" #{node.block_literal.source}"
|
|
183
|
-
else
|
|
184
|
-
'()'
|
|
185
|
-
end
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
# Remove everything from method name to end of node
|
|
189
|
-
range = Parser::Source::Range.new(
|
|
190
|
-
processed_source.buffer,
|
|
191
|
-
method_end_pos,
|
|
192
|
-
node.source_range.end_pos
|
|
193
|
-
)
|
|
194
|
-
|
|
195
|
-
corrector.replace(range, replacement)
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def reindent_pair_with_block(pair, base_indent)
|
|
199
|
-
# Check if the pair's value is a block
|
|
200
|
-
return pair.source unless pair.value.block_type?
|
|
201
|
-
|
|
202
|
-
# Format: "key: ->(param) do ... end"
|
|
203
|
-
key_source = pair.key.source
|
|
204
|
-
block_source = reindent_block(pair.value, base_indent)
|
|
205
|
-
|
|
206
|
-
"#{key_source}: #{block_source}"
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
def reindent_block(block_node, base_indent)
|
|
210
|
-
# Get block source lines
|
|
211
|
-
source = block_node.source
|
|
212
|
-
lines = source.lines
|
|
213
|
-
|
|
214
|
-
return source if lines.length == 1 # Single line block, no reindent needed
|
|
215
|
-
|
|
216
|
-
# Find the current indentation of the block's first line
|
|
217
|
-
# (this is usually where "do" appears)
|
|
218
|
-
first_line = lines[0]
|
|
219
|
-
|
|
220
|
-
# Process the block:
|
|
221
|
-
# Line 0: "->(param) do" - keep as is
|
|
222
|
-
# Lines 1..-2: block body - re-indent to base_indent + 2
|
|
223
|
-
# Last line: "end" - indent to base_indent
|
|
224
|
-
|
|
225
|
-
result_lines = []
|
|
226
|
-
block_body_indent = base_indent + ' ' * 2
|
|
227
|
-
|
|
228
|
-
lines.each_with_index do |line, index|
|
|
229
|
-
if index == 0
|
|
230
|
-
# First line: "->(param) do"
|
|
231
|
-
result_lines << line.rstrip
|
|
232
|
-
elsif index == lines.length - 1
|
|
233
|
-
# Last line: "end"
|
|
234
|
-
result_lines << "#{base_indent}#{line.strip}"
|
|
235
|
-
else
|
|
236
|
-
# Body lines: re-indent
|
|
237
|
-
# Remove existing indentation and add new indentation
|
|
238
|
-
stripped = line.lstrip
|
|
239
|
-
next if stripped.empty? # Skip blank lines
|
|
240
|
-
|
|
241
|
-
result_lines << "#{block_body_indent}#{stripped.rstrip}"
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
|
|
245
|
-
result_lines.join("\n")
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
end
|
|
250
|
-
end
|