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.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/glib/json/ui.rb +10 -0
  3. data/app/controllers/glib/errors_controller.rb +57 -1
  4. data/app/helpers/glib/json_ui/action_builder/logics.rb +14 -0
  5. data/app/helpers/glib/json_ui/action_builder/windows.rb +20 -5
  6. data/app/helpers/glib/json_ui/json_logic_lint.rb +82 -0
  7. data/app/helpers/glib/json_ui/view_builder/panels.rb +14 -0
  8. data/app/views/json_ui/garage/test_page/fields_upload.json.jbuilder +1 -1
  9. data/app/views/json_ui/garage/test_page/form_dirty_hooks.json.jbuilder +31 -0
  10. data/app/views/json_ui/garage/test_page/form_dynamic_dirty.json.jbuilder +41 -0
  11. data/app/views/json_ui/garage/test_page/form_removed_field.json.jbuilder +55 -0
  12. data/app/views/json_ui/garage/test_page/form_removed_field_onload.json.jbuilder +34 -0
  13. data/app/views/json_ui/garage/test_page/form_touched_validation.json.jbuilder +35 -0
  14. data/app/views/json_ui/garage/test_page/logics_run.json.jbuilder +79 -0
  15. data/app/views/json_ui/garage/test_page/logics_run_multi_form.json.jbuilder +45 -0
  16. data/app/views/json_ui/garage/test_page/logics_set.json.jbuilder +19 -0
  17. data/app/views/json_ui/garage/test_page/panels_bulkEdit2.json.jbuilder +3 -0
  18. data/app/views/json_ui/garage/test_page/run_multiple.json.jbuilder +31 -0
  19. data/app/views/json_ui/garage/test_page/windows_reload.json.jbuilder +57 -0
  20. data/lib/glib/engine.rb +132 -0
  21. data/lib/glib/rubocop.rb +0 -1
  22. data/lib/glib/snapshot.rb +57 -12
  23. data/lib/glib/test/parallel_coverage.rb +16 -0
  24. data/lib/tasks/db.rake +6 -0
  25. metadata +12 -3
  26. 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