sorbet_view 0.17.1 → 0.18.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 241f449c7d85bd172dd1f14e69f2dd3c3baf9a2590d932a81437bcb7256697e9
4
- data.tar.gz: 486cc137199d7a8e0fbda04baf528f139abd43585870108305ca9ece45f99a6e
3
+ metadata.gz: 017d85569d51f043ad35ece80c0782cd08055a7c2cdbef352e251ef6731edb09
4
+ data.tar.gz: 868bbd6562e38ca92e892948cd08a16e069656c864738e9e9605e6951e96e25a
5
5
  SHA512:
6
- metadata.gz: 78b9b224b0c202d58ab0f707f9333d8972298b11b707e735efd8f8da58eb93b21c24061f5a2b6fc0ea2fb207e2840df83351b6759a4ae8372d84391a390813c7
7
- data.tar.gz: faf509cd68a7f7eb35f2e826a3bdc514681afad57e8900ce079269b58ec4d5321d5cba66e1aee7199f8eeb59eec0a58cf97bcc0440e142e351a0ea846f618a22
6
+ metadata.gz: de2c968505b5f8b727aa4fa8f07486639786b608ae464e10eac6d11fc121c594e5e3e11962b54e5900efee3fe37acd17a2df3645f2133bed8739844464c4777f
7
+ data.tar.gz: 729aea79089ee0b7f2e1d7780ea0fd4bda21857d32b43df6d2f9fbe114de76e32534da5eacb98d3f2adc6e8927608ebb4c6624087e0a711dfbc550288a4f22a0
@@ -117,17 +117,19 @@ module SorbetView
117
117
 
118
118
  lines << " #{stripped}"
119
119
 
120
- # Build mapping entry
120
+ # Build mapping entry — for the first line we already advanced past
121
+ # leading whitespace in the adapter; for subsequent lines, use the
122
+ # actual indent of the source line so the template column matches.
121
123
  template_start_col = if i == 0
122
124
  seg.column
123
125
  else
124
- 0
126
+ code_line.length - code_line.lstrip.length
125
127
  end
126
128
 
127
129
  mapping_entries << SourceMap::MappingEntry.new(
128
130
  template_range: SourceMap::Range.new(
129
131
  start: SourceMap::Position.new(line: seg.line + i, column: template_start_col),
130
- end_: SourceMap::Position.new(line: seg.line + i, column: template_start_col + code_line.strip.length)
132
+ end_: SourceMap::Position.new(line: seg.line + i, column: template_start_col + stripped.length)
131
133
  ),
132
134
  ruby_range: SourceMap::Range.new(
133
135
  start: SourceMap::Position.new(line: ruby_line, column: 4),
@@ -93,8 +93,18 @@ module SorbetView
93
93
  sig { params(path: String, config: Configuration).returns(String) }
94
94
  def path_to_class_name(path, config)
95
95
  relative = strip_input_dir(path, config)
96
- basename = File.basename(relative).sub(/\..*$/, '') # strip all extensions
96
+ filename = File.basename(relative)
97
+ filename_parts = filename.split('.')
98
+
99
+ basename = T.must(filename_parts.first)
97
100
  basename = basename.delete_prefix('_') # strip partial prefix
101
+
102
+ # With 3+ parts (e.g. show.html.erb → [show, html, erb]), the last is the
103
+ # template handler and the middle parts are format/variant extensions.
104
+ # Nest them as sub-classes so show.html.erb and show.turbo_stream.erb
105
+ # don't collide as the same class name.
106
+ format_parts = filename_parts.length >= 3 ? T.must(filename_parts[1..-2]) : []
107
+
98
108
  dir = File.dirname(relative)
99
109
 
100
110
  parts = if dir == '.'
@@ -103,6 +113,8 @@ module SorbetView
103
113
  dir.split('/') + [basename]
104
114
  end
105
115
 
116
+ parts += format_parts
117
+
106
118
  parts.map { |p| camelize(p) }.join('::')
107
119
  end
108
120
 
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module SorbetView
5
- VERSION = '0.17.1'
5
+ VERSION = '0.18.0'
6
6
  end
@@ -258,21 +258,51 @@ module Tapioca
258
258
  end
259
259
  end
260
260
 
261
- # 2) Each action's template class includes the helper module and controller-specific helper modules
261
+ # 2) Each action's template class includes the helper module and controller-specific helper modules.
262
+ # Templates compile to format-nested classes (e.g. Users::Show::Html, Users::Show::TurboStream),
263
+ # so emit RBI for each format variant found on disk. Falls back to the action-base class
264
+ # when no format-suffixed templates exist.
262
265
  actions = controller.action_methods.to_a
263
266
  actions.each do |action_name|
264
267
  next unless action_name.match?(/\A[a-zA-Z_][a-zA-Z0-9_]*\z/)
265
268
 
266
- class_name = "SorbetView::Generated::#{parts.join('::')}::#{camelize(action_name)}"
267
- create_class_from_path(class_name) do |klass|
268
- klass.create_include(helper_module_name) if helper_module_name
269
- controller_helper_modules.each do |mod_name|
270
- klass.create_include("::#{mod_name}")
269
+ base_class_name = "SorbetView::Generated::#{parts.join('::')}::#{camelize(action_name)}"
270
+ format_suffixes = find_template_format_suffixes(path, action_name.to_s)
271
+ class_names = format_suffixes.empty? ? [base_class_name] : format_suffixes.map { |fs| "#{base_class_name}::#{fs}" }
272
+
273
+ class_names.each do |class_name|
274
+ create_class_from_path(class_name) do |klass|
275
+ klass.create_include(helper_module_name) if helper_module_name
276
+ controller_helper_modules.each do |mod_name|
277
+ klass.create_include("::#{mod_name}")
278
+ end
271
279
  end
272
280
  end
273
281
  end
274
282
  end
275
283
 
284
+ # Scan view dirs for format suffixes of a given action's templates.
285
+ # e.g. ["Html", "TurboStream"] for show.html.erb + show.turbo_stream.erb.
286
+ # Templates with no format (e.g. show.erb) contribute no suffix — for those,
287
+ # callers fall back to the action-base class name.
288
+ sig { params(controller_path: String, action_name: String).returns(T::Array[String]) }
289
+ def find_template_format_suffixes(controller_path, action_name)
290
+ suffixes = T.let([], T::Array[String])
291
+
292
+ resolve_view_dirs.each do |vd|
293
+ Dir.glob(File.join(vd, controller_path, "#{action_name}.*")).each do |file|
294
+ fname_parts = File.basename(file).split('.')
295
+ next unless fname_parts.first == action_name
296
+ next unless fname_parts.length >= 3
297
+
298
+ middle_parts = T.must(fname_parts[1..-2])
299
+ suffixes << middle_parts.map { |p| camelize(p) }.join('::')
300
+ end
301
+ end
302
+
303
+ suffixes.uniq
304
+ end
305
+
276
306
  # Returns [[method_name, params, return_type], ...]
277
307
  sig { params(controller: T.untyped).returns(T::Array[T.untyped]) }
278
308
  def extract_helper_methods(controller)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet_view
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.1
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - kazuma