herb 0.9.4-arm-linux-gnu → 0.9.6-arm-linux-gnu
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/config.yml +57 -21
- data/ext/herb/extension.c +8 -0
- data/ext/herb/extension_helpers.c +1 -0
- data/ext/herb/nodes.c +93 -55
- data/lib/herb/3.0/herb.so +0 -0
- data/lib/herb/3.1/herb.so +0 -0
- data/lib/herb/3.2/herb.so +0 -0
- data/lib/herb/3.3/herb.so +0 -0
- data/lib/herb/3.4/herb.so +0 -0
- data/lib/herb/4.0/herb.so +0 -0
- data/lib/herb/action_view/helper_registry.rb +8107 -0
- data/lib/herb/ast/nodes.rb +212 -78
- data/lib/herb/engine/compiler.rb +4 -6
- data/lib/herb/parser_options.rb +7 -2
- data/lib/herb/project.rb +2 -5
- data/lib/herb/version.rb +1 -1
- data/lib/herb/visitor.rb +8 -2
- data/sig/herb/action_view/helper_registry.rbs +1144 -0
- data/sig/herb/ast/nodes.rbs +85 -34
- data/sig/herb/parser_options.rbs +6 -2
- data/sig/herb/visitor.rbs +5 -2
- data/sig/serialized_ast_nodes.rbs +20 -9
- data/src/analyze/action_view/generated_handlers.c +355 -0
- data/src/analyze/action_view/generated_handlers.h +16 -0
- data/src/analyze/action_view/helper_registry.c +7244 -0
- data/src/analyze/action_view/image_tag.c +4 -31
- data/src/analyze/action_view/javascript_include_tag.c +1 -42
- data/src/analyze/action_view/javascript_tag.c +26 -40
- data/src/analyze/action_view/registry.c +2 -2
- data/src/analyze/action_view/tag_helper_node_builders.c +23 -2
- data/src/analyze/action_view/tag_helpers.c +61 -134
- data/src/analyze/action_view/turbo_frame_tag.c +1 -36
- data/src/analyze/analyze.c +28 -0
- data/src/analyze/analyze_helpers.c +406 -0
- data/src/analyze/builders.c +1 -0
- data/src/analyze/missing_end.c +16 -0
- data/src/analyze/parse_errors.c +3 -2
- data/src/analyze/postfix_conditionals.c +326 -0
- data/src/analyze/render_nodes.c +231 -35
- data/src/analyze/strict_locals.c +22 -338
- data/src/analyze/ternary_conditionals.c +265 -0
- data/src/analyze/transform.c +23 -2
- data/src/ast/ast_nodes.c +114 -57
- data/src/ast/ast_pretty_print.c +109 -25
- data/src/include/analyze/action_view/helper_registry.h +325 -0
- data/src/include/analyze/action_view/tag_helper_handler.h +3 -0
- data/src/include/analyze/action_view/tag_helper_node_builders.h +7 -0
- data/src/include/analyze/action_view/tag_helpers.h +0 -1
- data/src/include/analyze/helpers.h +18 -0
- data/src/include/analyze/postfix_conditionals.h +9 -0
- data/src/include/analyze/ternary_conditionals.h +15 -0
- data/src/include/ast/ast_nodes.h +27 -13
- data/src/include/parser/parser.h +1 -0
- data/src/include/version.h +1 -1
- data/src/parser/match_tags.c +37 -6
- data/src/parser.c +9 -0
- data/src/visitor.c +50 -7
- data/templates/java/org/herb/ast/HelperRegistry.java.erb +258 -0
- data/templates/javascript/packages/core/src/action-view-helpers.ts.erb +171 -0
- data/templates/javascript/packages/core/src/nodes.ts.erb +5 -1
- data/templates/lib/herb/action_view/helper_registry.rb.erb +288 -0
- data/templates/rust/src/action_view_helpers.rs.erb +154 -0
- data/templates/src/analyze/action_view/generated_handlers.c.erb +230 -0
- data/templates/src/analyze/action_view/generated_handlers.h.erb +12 -0
- data/templates/src/analyze/action_view/helper_registry.c.erb +114 -0
- data/templates/src/include/analyze/action_view/helper_registry.h.erb +82 -0
- data/templates/template.rb +338 -1
- metadata +19 -3
- data/src/analyze/action_view/content_tag.c +0 -78
- data/src/analyze/action_view/tag.c +0 -87
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
module Herb
|
|
2
|
+
module ActionView
|
|
3
|
+
module HelperType
|
|
4
|
+
<%- helpers.each do |helper| -%>
|
|
5
|
+
<%= helper.constant_name %> = :<%= helper.name %>
|
|
6
|
+
<%- end -%>
|
|
7
|
+
|
|
8
|
+
ALL = [
|
|
9
|
+
<%- helpers.each do |helper| -%>
|
|
10
|
+
<%= helper.constant_name %>,
|
|
11
|
+
<%- end -%>
|
|
12
|
+
].freeze #: Array[Symbol]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class HelperArgument
|
|
16
|
+
attr_reader :name #: String
|
|
17
|
+
attr_reader :position #: Integer
|
|
18
|
+
attr_reader :type #: String
|
|
19
|
+
attr_reader :default #: String?
|
|
20
|
+
attr_reader :description #: String
|
|
21
|
+
|
|
22
|
+
#: (String, Integer, String, bool, String?, bool, String) -> void
|
|
23
|
+
def initialize(name, position, type, optional, default, splat, description)
|
|
24
|
+
@name = name
|
|
25
|
+
@position = position
|
|
26
|
+
@type = type
|
|
27
|
+
@optional = optional
|
|
28
|
+
@default = default
|
|
29
|
+
@splat = splat
|
|
30
|
+
@description = description
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
#: () -> bool
|
|
34
|
+
def optional? = @optional
|
|
35
|
+
|
|
36
|
+
#: () -> bool
|
|
37
|
+
def splat? = @splat
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
class HelperOption
|
|
41
|
+
attr_reader :name #: String
|
|
42
|
+
attr_reader :type #: String
|
|
43
|
+
attr_reader :maps_to #: String?
|
|
44
|
+
attr_reader :description #: String
|
|
45
|
+
|
|
46
|
+
#: (String, String, String?, String) -> void
|
|
47
|
+
def initialize(name, type, maps_to, description)
|
|
48
|
+
@name = name
|
|
49
|
+
@type = type
|
|
50
|
+
@maps_to = maps_to
|
|
51
|
+
@description = description
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
#: () -> bool
|
|
55
|
+
def maps_to_data_attribute? = maps_to&.start_with?("data-") || false
|
|
56
|
+
|
|
57
|
+
#: () -> bool
|
|
58
|
+
def maps_to_aria_attribute? = maps_to&.start_with?("aria-") || false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class HelperImplicitAttribute
|
|
62
|
+
attr_reader :name #: String
|
|
63
|
+
attr_reader :source #: String
|
|
64
|
+
attr_reader :source_with_block #: String?
|
|
65
|
+
attr_reader :wrapper #: String
|
|
66
|
+
attr_reader :skip_wrapping_for #: Array[String]
|
|
67
|
+
|
|
68
|
+
#: (String, String, String?, String, Array[String]) -> void
|
|
69
|
+
def initialize(name, source, source_with_block, wrapper, skip_wrapping_for)
|
|
70
|
+
@name = name
|
|
71
|
+
@source = source
|
|
72
|
+
@source_with_block = source_with_block
|
|
73
|
+
@wrapper = wrapper
|
|
74
|
+
@skip_wrapping_for = skip_wrapping_for
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
class HelperEntry
|
|
79
|
+
attr_reader :name #: String
|
|
80
|
+
attr_reader :type #: Symbol
|
|
81
|
+
attr_reader :source #: String
|
|
82
|
+
attr_reader :gem #: String
|
|
83
|
+
attr_reader :output #: Symbol
|
|
84
|
+
attr_reader :visibility #: String
|
|
85
|
+
attr_reader :tag_name #: String?
|
|
86
|
+
attr_reader :detect_style #: Symbol
|
|
87
|
+
attr_reader :description #: String
|
|
88
|
+
attr_reader :signature #: String
|
|
89
|
+
attr_reader :documentation_url #: String
|
|
90
|
+
attr_reader :implicit_attribute #: HelperImplicitAttribute?
|
|
91
|
+
attr_reader :arguments #: Array[HelperArgument]
|
|
92
|
+
attr_reader :options #: Array[HelperOption]
|
|
93
|
+
attr_reader :special_behaviors #: Array[Symbol]
|
|
94
|
+
attr_reader :aliases #: Array[String]
|
|
95
|
+
|
|
96
|
+
#: (name: String, type: Symbol, source: String, gem: String, output: Symbol, visibility: String, tag_name: String?, is_void: bool, supports_block: bool, preferred_for_tag: bool, supported: bool, detect_style: Symbol, description: String, signature: String, documentation_url: String, implicit_attribute: HelperImplicitAttribute?, arguments: Array[HelperArgument], options: Array[HelperOption], special_behaviors: Array[Symbol], aliases: Array[String]) -> void
|
|
97
|
+
def initialize( # rubocop:disable Metrics/ParameterLists
|
|
98
|
+
name:, type:, source:, gem:, output:, visibility:, tag_name:, is_void:, supports_block:,
|
|
99
|
+
preferred_for_tag:, supported:, detect_style:, description:, signature:, documentation_url:,
|
|
100
|
+
implicit_attribute:, arguments:, options:, special_behaviors:, aliases:
|
|
101
|
+
)
|
|
102
|
+
@name = name
|
|
103
|
+
@type = type
|
|
104
|
+
@source = source
|
|
105
|
+
@gem = gem
|
|
106
|
+
@output = output
|
|
107
|
+
@visibility = visibility
|
|
108
|
+
@tag_name = tag_name
|
|
109
|
+
@is_void = is_void
|
|
110
|
+
@supports_block = supports_block
|
|
111
|
+
@preferred_for_tag = preferred_for_tag
|
|
112
|
+
@supported = supported
|
|
113
|
+
@detect_style = detect_style
|
|
114
|
+
@description = description
|
|
115
|
+
@signature = signature
|
|
116
|
+
@documentation_url = documentation_url
|
|
117
|
+
@implicit_attribute = implicit_attribute
|
|
118
|
+
@arguments = arguments
|
|
119
|
+
@options = options
|
|
120
|
+
@special_behaviors = special_behaviors
|
|
121
|
+
@aliases = aliases
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
#: () -> bool
|
|
125
|
+
def void? = @is_void
|
|
126
|
+
|
|
127
|
+
#: () -> bool
|
|
128
|
+
def supports_block? = @supports_block
|
|
129
|
+
|
|
130
|
+
#: () -> bool
|
|
131
|
+
def preferred_for_tag? = @preferred_for_tag
|
|
132
|
+
|
|
133
|
+
#: () -> bool
|
|
134
|
+
def supported? = @supported
|
|
135
|
+
|
|
136
|
+
#: () -> bool
|
|
137
|
+
def static_tag_name? = !@tag_name.nil?
|
|
138
|
+
|
|
139
|
+
#: () -> bool
|
|
140
|
+
def implicit_attribute? = !@implicit_attribute.nil?
|
|
141
|
+
|
|
142
|
+
#: () -> bool
|
|
143
|
+
def call_name_detect? = @detect_style == :call_name
|
|
144
|
+
|
|
145
|
+
#: () -> bool
|
|
146
|
+
def receiver_call_detect? = @detect_style == :receiver_call
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
module HelperRegistry
|
|
150
|
+
<%- helpers.each do |helper| -%>
|
|
151
|
+
<%= helper.constant_name %> = HelperEntry.new(
|
|
152
|
+
name: "<%= helper.name %>",
|
|
153
|
+
type: HelperType::<%= helper.constant_name %>,
|
|
154
|
+
source: "<%= helper.source %>",
|
|
155
|
+
gem: "<%= helper.gem %>",
|
|
156
|
+
output: :<%= helper.output %>,
|
|
157
|
+
visibility: "<%= helper.visibility %>",
|
|
158
|
+
tag_name: <%= helper.tag_name ? "\"#{helper.tag_name}\"" : "nil" %>,
|
|
159
|
+
is_void: <%= helper.void? %>,
|
|
160
|
+
supports_block: <%= helper.supports_block %>,
|
|
161
|
+
preferred_for_tag: <%= helper.preferred_for_tag %>,
|
|
162
|
+
supported: <%= helper.supported %>,
|
|
163
|
+
detect_style: :<%= helper.detect_style || "call_name" %>,
|
|
164
|
+
description: "<%= helper.escaped_description %>",
|
|
165
|
+
signature: "<%= helper.escaped_signature %>",
|
|
166
|
+
documentation_url: "<%= helper.documentation_url %>",
|
|
167
|
+
<%- if helper.implicit_attribute? -%>
|
|
168
|
+
implicit_attribute: HelperImplicitAttribute.new(
|
|
169
|
+
"<%= helper.implicit_attribute.name %>",
|
|
170
|
+
"<%= helper.implicit_attribute.source %>",
|
|
171
|
+
<%= helper.implicit_attribute.source_with_block ? "\"#{helper.implicit_attribute.source_with_block}\"" : "nil" %>,
|
|
172
|
+
"<%= helper.implicit_attribute.wrapper %>",
|
|
173
|
+
[<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>]
|
|
174
|
+
),
|
|
175
|
+
<%- else -%>
|
|
176
|
+
implicit_attribute: nil,
|
|
177
|
+
<%- end -%>
|
|
178
|
+
arguments: [
|
|
179
|
+
<%- helper.arguments.each do |arg| -%>
|
|
180
|
+
HelperArgument.new("<%= arg.name %>", <%= arg.position %>, "<%= arg.type_display %>", <%= arg.optional %>, <%= arg.default ? "\"#{arg.escaped_default}\"" : "nil" %>, <%= arg.splat %>, "<%= arg.escaped_description %>"),
|
|
181
|
+
<%- end -%>
|
|
182
|
+
],
|
|
183
|
+
options: [
|
|
184
|
+
<%- helper.options.each do |opt| -%>
|
|
185
|
+
HelperOption.new("<%= opt.name %>", "<%= opt.type_display %>", <%= opt.maps_to ? "\"#{opt.maps_to}\"" : "nil" %>, "<%= opt.escaped_description %>"),
|
|
186
|
+
<%- end -%>
|
|
187
|
+
],
|
|
188
|
+
special_behaviors: [<%= helper.special_behaviors.map { |b| ":#{b}" }.join(", ") %>],
|
|
189
|
+
aliases: [<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
190
|
+
).freeze #: HelperEntry
|
|
191
|
+
|
|
192
|
+
<%- end -%>
|
|
193
|
+
ENTRIES = {
|
|
194
|
+
<%- helpers.each do |helper| -%>
|
|
195
|
+
"<%= helper.name %>" => <%= helper.constant_name %>,
|
|
196
|
+
<%- helper.aliases.each do |alias_name| -%>
|
|
197
|
+
"<%= alias_name %>" => <%= helper.constant_name %>,
|
|
198
|
+
<%- end -%>
|
|
199
|
+
<%- end -%>
|
|
200
|
+
}.freeze #: Hash[String, HelperEntry]
|
|
201
|
+
|
|
202
|
+
BY_SOURCE = {
|
|
203
|
+
<%- helpers.each do |helper| -%>
|
|
204
|
+
"<%= helper.source %>" => <%= helper.constant_name %>,
|
|
205
|
+
<%- end -%>
|
|
206
|
+
}.freeze #: Hash[String, HelperEntry]
|
|
207
|
+
|
|
208
|
+
<%- helpers_by_tag = helpers.select(&:static_tag_name?).group_by(&:tag_name) -%>
|
|
209
|
+
|
|
210
|
+
BY_TAG_NAME = {
|
|
211
|
+
<%- helpers_by_tag.each do |tag_name, helpers| -%>
|
|
212
|
+
"<%= tag_name %>" => [<%= helpers.map(&:constant_name).join(", ") %>].freeze,
|
|
213
|
+
<%- end -%>
|
|
214
|
+
}.freeze #: Hash[String, Array[HelperEntry]]
|
|
215
|
+
|
|
216
|
+
class << self
|
|
217
|
+
#: (String) -> HelperEntry?
|
|
218
|
+
def get(name)
|
|
219
|
+
ENTRIES[name.to_s]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
#: (String) -> HelperEntry?
|
|
223
|
+
def find_by_source(source)
|
|
224
|
+
BY_SOURCE[source]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
#: () -> Array[HelperEntry]
|
|
228
|
+
def entries
|
|
229
|
+
ENTRIES.values
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
#: () { (HelperEntry) -> void } -> void
|
|
233
|
+
def each(&block)
|
|
234
|
+
entries.each(&block)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
#: (String) -> Array[HelperEntry]
|
|
238
|
+
def helpers_for_tag(tag_name)
|
|
239
|
+
BY_TAG_NAME[tag_name] || []
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
#: (String) -> HelperEntry?
|
|
243
|
+
def find_preferred_for_tag(tag_name)
|
|
244
|
+
helpers = BY_TAG_NAME[tag_name]
|
|
245
|
+
return nil unless helpers
|
|
246
|
+
|
|
247
|
+
helpers.find(&:preferred_for_tag?) || helpers.first
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
#: () -> Integer
|
|
251
|
+
def count
|
|
252
|
+
ENTRIES.size
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
#: (String) -> bool
|
|
256
|
+
def supported?(name)
|
|
257
|
+
entry = get(name)
|
|
258
|
+
entry&.supported? || false
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
#: (String) -> bool
|
|
262
|
+
def exists?(name)
|
|
263
|
+
ENTRIES.key?(name.to_s)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
#: () -> Array[HelperEntry]
|
|
267
|
+
def supported
|
|
268
|
+
entries.select(&:supported?)
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
#: (String) -> Array[HelperEntry]
|
|
272
|
+
def by_gem(gem_name)
|
|
273
|
+
entries.select { |entry| entry.gem == gem_name }
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
#: (Symbol) -> Array[HelperEntry]
|
|
277
|
+
def by_output(output)
|
|
278
|
+
entries.select { |entry| entry.output == output }
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
#: (String) -> Array[HelperEntry]
|
|
282
|
+
def by_module(module_name)
|
|
283
|
+
entries.select { |entry| entry.source.split("#").first.split("::").last == module_name }
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
2
|
+
pub enum HelperType {
|
|
3
|
+
<%- helpers.each do |helper| -%>
|
|
4
|
+
/// `<%= helper.name %>` — <%= helper.source %>
|
|
5
|
+
<%= helper.camel_case_name %>,
|
|
6
|
+
<%- end -%>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
impl HelperType {
|
|
10
|
+
pub fn as_str(&self) -> &'static str {
|
|
11
|
+
match self {
|
|
12
|
+
<%- helpers.each do |helper| -%>
|
|
13
|
+
HelperType::<%= helper.camel_case_name %> => "<%= helper.name %>",
|
|
14
|
+
<%- end -%>
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pub fn from_name(name: &str) -> Option<HelperType> {
|
|
19
|
+
match name {
|
|
20
|
+
<%- helpers.each do |helper| -%>
|
|
21
|
+
"<%= helper.name %>" => Some(HelperType::<%= helper.camel_case_name %>),
|
|
22
|
+
<%- end -%>
|
|
23
|
+
_ => None,
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#[derive(Debug, Clone)]
|
|
29
|
+
pub struct HelperArgument {
|
|
30
|
+
pub name: &'static str,
|
|
31
|
+
pub position: usize,
|
|
32
|
+
pub argument_type: &'static str,
|
|
33
|
+
pub optional: bool,
|
|
34
|
+
pub default: Option<&'static str>,
|
|
35
|
+
pub splat: bool,
|
|
36
|
+
pub description: &'static str,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#[derive(Debug, Clone)]
|
|
40
|
+
pub struct HelperOption {
|
|
41
|
+
pub name: &'static str,
|
|
42
|
+
pub option_type: &'static str,
|
|
43
|
+
pub maps_to: Option<&'static str>,
|
|
44
|
+
pub description: &'static str,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#[derive(Debug, Clone)]
|
|
48
|
+
pub struct HelperImplicitAttribute {
|
|
49
|
+
pub name: &'static str,
|
|
50
|
+
pub source: &'static str,
|
|
51
|
+
pub source_with_block: Option<&'static str>,
|
|
52
|
+
pub wrapper: &'static str,
|
|
53
|
+
pub skip_wrapping_for: &'static [&'static str],
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
#[derive(Debug, Clone)]
|
|
57
|
+
pub struct HelperEntry {
|
|
58
|
+
pub name: &'static str,
|
|
59
|
+
pub helper_type: HelperType,
|
|
60
|
+
pub source: &'static str,
|
|
61
|
+
pub gem: &'static str,
|
|
62
|
+
pub output: &'static str,
|
|
63
|
+
pub visibility: &'static str,
|
|
64
|
+
pub tag_name: Option<&'static str>,
|
|
65
|
+
pub is_void: bool,
|
|
66
|
+
pub supports_block: bool,
|
|
67
|
+
pub preferred_for_tag: bool,
|
|
68
|
+
pub supported: bool,
|
|
69
|
+
pub detect_style: &'static str,
|
|
70
|
+
pub description: &'static str,
|
|
71
|
+
pub signature: &'static str,
|
|
72
|
+
pub documentation_url: &'static str,
|
|
73
|
+
pub implicit_attribute: Option<&'static HelperImplicitAttribute>,
|
|
74
|
+
pub arguments: &'static [HelperArgument],
|
|
75
|
+
pub options: &'static [HelperOption],
|
|
76
|
+
pub special_behaviors: &'static [&'static str],
|
|
77
|
+
pub aliases: &'static [&'static str],
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
<%- helpers.each do |helper| -%>
|
|
81
|
+
<%- if helper.implicit_attribute? -%>
|
|
82
|
+
static <%= helper.constant_name %>_IMPLICIT_ATTR: HelperImplicitAttribute = HelperImplicitAttribute {
|
|
83
|
+
name: "<%= helper.implicit_attribute.name %>",
|
|
84
|
+
source: "<%= helper.implicit_attribute.source %>",
|
|
85
|
+
source_with_block: <%= helper.implicit_attribute.source_with_block ? "Some(\"#{helper.implicit_attribute.source_with_block}\")" : "None" %>,
|
|
86
|
+
wrapper: "<%= helper.implicit_attribute.wrapper %>",
|
|
87
|
+
skip_wrapping_for: &[<%= helper.implicit_attribute.skip_wrapping_for.map { |s| "\"#{s}\"" }.join(", ") %>],
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
<%- end -%>
|
|
91
|
+
<%- end -%>
|
|
92
|
+
|
|
93
|
+
static REGISTRY: [HelperEntry; <%= helpers.size %>] = [
|
|
94
|
+
<%- helpers.each do |helper| -%>
|
|
95
|
+
HelperEntry {
|
|
96
|
+
name: "<%= helper.name %>",
|
|
97
|
+
helper_type: HelperType::<%= helper.camel_case_name %>,
|
|
98
|
+
source: "<%= helper.source %>",
|
|
99
|
+
gem: "<%= helper.gem %>",
|
|
100
|
+
output: "<%= helper.output %>",
|
|
101
|
+
visibility: "<%= helper.visibility %>",
|
|
102
|
+
tag_name: <%= helper.tag_name ? "Some(\"#{helper.tag_name}\")" : "None" %>,
|
|
103
|
+
is_void: <%= helper.void? %>,
|
|
104
|
+
supports_block: <%= helper.supports_block %>,
|
|
105
|
+
preferred_for_tag: <%= helper.preferred_for_tag %>,
|
|
106
|
+
supported: <%= helper.supported %>,
|
|
107
|
+
detect_style: "<%= helper.detect_style || "call_name" %>",
|
|
108
|
+
description: "<%= helper.escaped_description %>",
|
|
109
|
+
signature: "<%= helper.escaped_signature %>",
|
|
110
|
+
documentation_url: "<%= helper.documentation_url %>",
|
|
111
|
+
implicit_attribute: <%= helper.implicit_attribute? ? "Some(&#{helper.constant_name}_IMPLICIT_ATTR)" : "None" %>,
|
|
112
|
+
arguments: &[
|
|
113
|
+
<%- helper.arguments.each do |arg| -%>
|
|
114
|
+
HelperArgument { name: "<%= arg.name %>", position: <%= arg.position %>, argument_type: "<%= arg.type_display %>", optional: <%= arg.optional %>, default: <%= arg.default ? "Some(\"#{arg.escaped_default}\")" : "None" %>, splat: <%= arg.splat %>, description: "<%= arg.escaped_description %>" },
|
|
115
|
+
<%- end -%>
|
|
116
|
+
],
|
|
117
|
+
options: &[
|
|
118
|
+
<%- helper.options.each do |opt| -%>
|
|
119
|
+
HelperOption { name: "<%= opt.name %>", option_type: "<%= opt.type_display %>", maps_to: <%= opt.maps_to ? "Some(\"#{opt.maps_to}\")" : "None" %>, description: "<%= opt.escaped_description %>" },
|
|
120
|
+
<%- end -%>
|
|
121
|
+
],
|
|
122
|
+
special_behaviors: &[<%= helper.special_behaviors.map { |b| "\"#{b}\"" }.join(", ") %>],
|
|
123
|
+
aliases: &[<%= helper.aliases.map { |a| "\"#{a}\"" }.join(", ") %>],
|
|
124
|
+
},
|
|
125
|
+
<%- end -%>
|
|
126
|
+
];
|
|
127
|
+
|
|
128
|
+
pub fn get(helper_type: HelperType) -> &'static HelperEntry {
|
|
129
|
+
®ISTRY[helper_type as usize]
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
pub fn find_by_name(name: &str) -> Option<&'static HelperEntry> {
|
|
133
|
+
REGISTRY.iter().find(|entry| entry.name == name)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
pub fn find_by_source(source: &str) -> Option<&'static HelperEntry> {
|
|
137
|
+
REGISTRY.iter().find(|entry| entry.source == source)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
pub fn helpers_for_tag(tag_name: &str) -> Vec<&'static HelperEntry> {
|
|
141
|
+
REGISTRY.iter().filter(|entry| entry.tag_name == Some(tag_name)).collect()
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
pub fn find_preferred_for_tag(tag_name: &str) -> Option<&'static HelperEntry> {
|
|
145
|
+
REGISTRY.iter().find(|entry| entry.tag_name == Some(tag_name) && entry.preferred_for_tag)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
pub fn entries() -> &'static [HelperEntry] {
|
|
149
|
+
®ISTRY
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
pub fn count() -> usize {
|
|
153
|
+
REGISTRY.len()
|
|
154
|
+
}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
#include "../../include/analyze/action_view/tag_helper_handler.h"
|
|
2
|
+
#include "../../include/lib/hb_allocator.h"
|
|
3
|
+
#include "../../include/lib/hb_string.h"
|
|
4
|
+
|
|
5
|
+
#include <prism.h>
|
|
6
|
+
#include <stdbool.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
<%- supported_helpers = helpers.select(&:supported?).reject(&:custom_transform?) -%>
|
|
10
|
+
// ==========================================================================
|
|
11
|
+
// Generated detect functions
|
|
12
|
+
// ==========================================================================
|
|
13
|
+
<%- supported_helpers.each do |helper| -%>
|
|
14
|
+
<%- if helper.call_name_detect? -%>
|
|
15
|
+
|
|
16
|
+
bool detect_<%= helper.safe_name %>(pm_call_node_t* call_node, pm_parser_t* parser) {
|
|
17
|
+
if (!call_node || !call_node->name) { return false; }
|
|
18
|
+
|
|
19
|
+
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
20
|
+
|
|
21
|
+
return constant && constant->length == <%= helper.name.length %> && strncmp((const char*) constant->start, "<%= helper.name %>", <%= helper.name.length %>) == 0;
|
|
22
|
+
}
|
|
23
|
+
<%- elsif helper.receiver_call_detect? -%>
|
|
24
|
+
|
|
25
|
+
bool detect_<%= helper.safe_name %>(pm_call_node_t* call_node, pm_parser_t* parser) {
|
|
26
|
+
if (!call_node || !call_node->receiver) { return false; }
|
|
27
|
+
if (call_node->receiver->type != PM_CALL_NODE) { return false; }
|
|
28
|
+
|
|
29
|
+
pm_call_node_t* receiver_node = (pm_call_node_t*) call_node->receiver;
|
|
30
|
+
if (!receiver_node->name) { return false; }
|
|
31
|
+
|
|
32
|
+
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, receiver_node->name);
|
|
33
|
+
|
|
34
|
+
return constant && constant->length == 3 && strncmp((const char*) constant->start, "tag", 3) == 0;
|
|
35
|
+
}
|
|
36
|
+
<%- end -%>
|
|
37
|
+
<%- end -%>
|
|
38
|
+
|
|
39
|
+
// ==========================================================================
|
|
40
|
+
// Generated extract_tag_name functions
|
|
41
|
+
// ==========================================================================
|
|
42
|
+
<%- supported_helpers.each do |helper| -%>
|
|
43
|
+
<%- if helper.tag_name -%>
|
|
44
|
+
|
|
45
|
+
static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
|
|
46
|
+
(void) _call_node;
|
|
47
|
+
(void) _parser;
|
|
48
|
+
|
|
49
|
+
return hb_allocator_strdup(allocator, "<%= helper.tag_name %>");
|
|
50
|
+
}
|
|
51
|
+
<%- elsif helper.name == "content_tag" -%>
|
|
52
|
+
|
|
53
|
+
static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
54
|
+
(void) parser;
|
|
55
|
+
|
|
56
|
+
if (!call_node || !call_node->arguments) { return NULL; }
|
|
57
|
+
|
|
58
|
+
pm_arguments_node_t* arguments = call_node->arguments;
|
|
59
|
+
if (!arguments->arguments.size) { return NULL; }
|
|
60
|
+
|
|
61
|
+
pm_node_t* first_argument = arguments->arguments.nodes[0];
|
|
62
|
+
|
|
63
|
+
if (first_argument->type == PM_STRING_NODE) {
|
|
64
|
+
pm_string_node_t* string_node = (pm_string_node_t*) first_argument;
|
|
65
|
+
size_t length = pm_string_length(&string_node->unescaped);
|
|
66
|
+
return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
|
|
67
|
+
} else if (first_argument->type == PM_SYMBOL_NODE) {
|
|
68
|
+
pm_symbol_node_t* symbol_node = (pm_symbol_node_t*) first_argument;
|
|
69
|
+
size_t length = pm_string_length(&symbol_node->unescaped);
|
|
70
|
+
return hb_allocator_strndup(allocator, (const char*) pm_string_source(&symbol_node->unescaped), length);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return NULL;
|
|
74
|
+
}
|
|
75
|
+
<%- elsif helper.name == "tag" -%>
|
|
76
|
+
|
|
77
|
+
extern bool is_ruby_introspection_method(hb_string_T method_name);
|
|
78
|
+
|
|
79
|
+
static char* extract_<%= helper.safe_name %>_tag_name(pm_call_node_t* call_node, pm_parser_t* parser, hb_allocator_T* allocator) {
|
|
80
|
+
if (!call_node || !call_node->name) { return NULL; }
|
|
81
|
+
|
|
82
|
+
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
83
|
+
if (!constant) { return NULL; }
|
|
84
|
+
|
|
85
|
+
if (is_ruby_introspection_method(hb_string_from_data((const char*) constant->start, constant->length))) { return NULL; }
|
|
86
|
+
|
|
87
|
+
char* name = hb_allocator_strndup(allocator, (const char*) constant->start, constant->length);
|
|
88
|
+
|
|
89
|
+
for (size_t i = 0; i < constant->length && name[i] != '\0'; i++) {
|
|
90
|
+
if (name[i] == '_') { name[i] = '-'; }
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return name;
|
|
94
|
+
}
|
|
95
|
+
<%- end -%>
|
|
96
|
+
<%- end -%>
|
|
97
|
+
|
|
98
|
+
// ==========================================================================
|
|
99
|
+
// Generated extract_content functions
|
|
100
|
+
// ==========================================================================
|
|
101
|
+
<%- supported_helpers.each do |helper| -%>
|
|
102
|
+
<%- content = helper.content -%>
|
|
103
|
+
<%- if content.nil? -%>
|
|
104
|
+
|
|
105
|
+
static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* _call_node, pm_parser_t* _parser, hb_allocator_T* _allocator) {
|
|
106
|
+
(void) _call_node;
|
|
107
|
+
(void) _parser;
|
|
108
|
+
(void) _allocator;
|
|
109
|
+
|
|
110
|
+
return NULL;
|
|
111
|
+
}
|
|
112
|
+
<%- elsif content.first_arg? -%>
|
|
113
|
+
|
|
114
|
+
static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* call_node, pm_parser_t* _parser, hb_allocator_T* allocator) {
|
|
115
|
+
(void) _parser;
|
|
116
|
+
|
|
117
|
+
if (!call_node || !call_node->arguments) { return NULL; }
|
|
118
|
+
|
|
119
|
+
pm_arguments_node_t* arguments = call_node->arguments;
|
|
120
|
+
if (!arguments->arguments.size) { return NULL; }
|
|
121
|
+
|
|
122
|
+
pm_node_t* first_argument = arguments->arguments.nodes[0];
|
|
123
|
+
|
|
124
|
+
<%- if content.skip_if_hash -%>
|
|
125
|
+
if (first_argument->type == PM_KEYWORD_HASH_NODE) { return NULL; }
|
|
126
|
+
<%- end -%>
|
|
127
|
+
|
|
128
|
+
if (first_argument->type == PM_STRING_NODE) {
|
|
129
|
+
pm_string_node_t* string_node = (pm_string_node_t*) first_argument;
|
|
130
|
+
size_t length = pm_string_length(&string_node->unescaped);
|
|
131
|
+
return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
size_t source_length = first_argument->location.end - first_argument->location.start;
|
|
135
|
+
return hb_allocator_strndup(allocator, (const char*) first_argument->location.start, source_length);
|
|
136
|
+
}
|
|
137
|
+
<%- elsif content.block_or_arg? -%>
|
|
138
|
+
|
|
139
|
+
static char* extract_<%= helper.safe_name %>_content(pm_call_node_t* call_node, pm_parser_t* <%= helper.receiver_call_detect? ? "parser" : "_parser" %>, hb_allocator_T* allocator) {
|
|
140
|
+
(void) <%= helper.receiver_call_detect? ? "parser" : "_parser" %>;
|
|
141
|
+
|
|
142
|
+
if (!call_node) { return NULL; }
|
|
143
|
+
|
|
144
|
+
<%- if helper.receiver_call_detect? -%>
|
|
145
|
+
if (call_node->name) {
|
|
146
|
+
pm_constant_t* constant = pm_constant_pool_id_to_constant(&parser->constant_pool, call_node->name);
|
|
147
|
+
|
|
148
|
+
if (constant && is_ruby_introspection_method(hb_string_from_data((const char*) constant->start, constant->length))) {
|
|
149
|
+
return NULL;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
<%- end -%>
|
|
153
|
+
|
|
154
|
+
char* block_content = extract_inline_block_content(call_node, allocator);
|
|
155
|
+
if (block_content) { return block_content; }
|
|
156
|
+
|
|
157
|
+
<%- arg_index = (content.arg_position || 1) - 1 -%>
|
|
158
|
+
|
|
159
|
+
<%- if content.arg_position -%>
|
|
160
|
+
if (call_node->arguments) {
|
|
161
|
+
pm_arguments_node_t* arguments = call_node->arguments;
|
|
162
|
+
|
|
163
|
+
if (arguments->arguments.size >= <%= content.arg_position %>) {
|
|
164
|
+
pm_node_t* argument = arguments->arguments.nodes[<%= arg_index %>];
|
|
165
|
+
|
|
166
|
+
<%- if content.skip_if_hash -%>
|
|
167
|
+
if (argument->type != PM_KEYWORD_HASH_NODE) {
|
|
168
|
+
<%- end -%>
|
|
169
|
+
|
|
170
|
+
if (argument->type == PM_STRING_NODE) {
|
|
171
|
+
pm_string_node_t* string_node = (pm_string_node_t*) argument;
|
|
172
|
+
size_t length = pm_string_length(&string_node->unescaped);
|
|
173
|
+
return hb_allocator_strndup(allocator, (const char*) pm_string_source(&string_node->unescaped), length);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
size_t source_length = argument->location.end - argument->location.start;
|
|
177
|
+
|
|
178
|
+
<%- if content.to_s_suffix_when_single -%>
|
|
179
|
+
if (arguments->arguments.size == 1 && argument->type != PM_NIL_NODE) {
|
|
180
|
+
const char* suffix = ".to_s";
|
|
181
|
+
size_t suffix_length = strlen(suffix);
|
|
182
|
+
size_t total_length = source_length + suffix_length;
|
|
183
|
+
char* ruby_expression = hb_allocator_alloc(allocator, total_length + 1);
|
|
184
|
+
|
|
185
|
+
memcpy(ruby_expression, (const char*) argument->location.start, source_length);
|
|
186
|
+
memcpy(ruby_expression + source_length, suffix, suffix_length);
|
|
187
|
+
ruby_expression[total_length] = '\0';
|
|
188
|
+
|
|
189
|
+
return ruby_expression;
|
|
190
|
+
}
|
|
191
|
+
<%- end -%>
|
|
192
|
+
|
|
193
|
+
return hb_allocator_strndup(allocator, (const char*) argument->location.start, source_length);
|
|
194
|
+
|
|
195
|
+
<%- if content.skip_if_hash -%>
|
|
196
|
+
}
|
|
197
|
+
<%- end -%>
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
<%- end -%>
|
|
201
|
+
|
|
202
|
+
return NULL;
|
|
203
|
+
}
|
|
204
|
+
<%- end -%>
|
|
205
|
+
<%- end -%>
|
|
206
|
+
|
|
207
|
+
// ==========================================================================
|
|
208
|
+
// Generated supports_block functions
|
|
209
|
+
// ==========================================================================
|
|
210
|
+
<%- supported_helpers.each do |helper| -%>
|
|
211
|
+
|
|
212
|
+
static bool <%= helper.safe_name %>_supports_block(void) {
|
|
213
|
+
return <%= helper.supports_block %>;
|
|
214
|
+
}
|
|
215
|
+
<%- end -%>
|
|
216
|
+
|
|
217
|
+
// ==========================================================================
|
|
218
|
+
// Generated handler structs
|
|
219
|
+
// ==========================================================================
|
|
220
|
+
<%- supported_helpers.each do |helper| -%>
|
|
221
|
+
|
|
222
|
+
const tag_helper_handler_T <%= helper.safe_name %>_handler = {
|
|
223
|
+
.name = "<%= helper.name %>",
|
|
224
|
+
.source = HB_STRING_LITERAL("<%= helper.source %>"),
|
|
225
|
+
.detect = detect_<%= helper.safe_name %>,
|
|
226
|
+
.extract_tag_name = extract_<%= helper.safe_name %>_tag_name,
|
|
227
|
+
.extract_content = extract_<%= helper.safe_name %>_content,
|
|
228
|
+
.supports_block = <%= helper.safe_name %>_supports_block,
|
|
229
|
+
};
|
|
230
|
+
<%- end -%>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#ifndef GENERATED_HANDLERS_H
|
|
2
|
+
#define GENERATED_HANDLERS_H
|
|
3
|
+
|
|
4
|
+
#include "../../include/analyze/action_view/tag_helper_handler.h"
|
|
5
|
+
|
|
6
|
+
<%- supported_helpers = helpers.select(&:supported?) -%>
|
|
7
|
+
<%- supported_helpers.each do |helper| -%>
|
|
8
|
+
<%- next if helper.custom_transform? -%>
|
|
9
|
+
extern const tag_helper_handler_T <%= helper.safe_name %>_handler;
|
|
10
|
+
<%- end -%>
|
|
11
|
+
|
|
12
|
+
#endif
|