sorbet_view 0.17.0 → 0.17.2

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: 330016607634f904162184802a0fb8efa933da90179b192b1e3113a296ccf113
4
- data.tar.gz: 1770334f364c5eae2b56ffe15ce222f157cc8eb7c53a94e371f8d4103a91a8fb
3
+ metadata.gz: 858b6bd700e41b846fc44258e8a702bb8f32f25d952a3c64c1468500619c92f0
4
+ data.tar.gz: 4bbe6e97e5726844fd6135fcb148d486d01c196e33e4c1ef200f088fb79ed1a0
5
5
  SHA512:
6
- metadata.gz: f2381a372dc8ebb770e7e73e978a2af499d1e83ea2664a55d4e9657b0a7296118edbaa5150867a72caa667d0121a21a9da153266377f0f93d1d167a0409efefc
7
- data.tar.gz: 185f3fed2527ddc2a7011550c0d1a2b7a21872164949ddbd5a74fee9627fa7fc1397e7bf80ba4477e1b20626cbd320c123dc83a5e5a6e6a0848c32f41319538c
6
+ metadata.gz: 48c1d98ade67fdb02c84c7650c985fe97ba35e38bdd7973fdb2586bfc4cd89e4fd654435cf5d3e9f8d6b07129cf2573ac76b10c4a857db3f919e92333a6b6b79
7
+ data.tar.gz: fb8bd91ca32e0473c1a533adbf3211d4c75ddbd8283bfc980ac9497c24acb3548efd7007d13d8ae771667753fbaec1951a4215a0cf94592a959c56770288710e
@@ -97,13 +97,14 @@ module SorbetView
97
97
  return unless node.respond_to?(:content) && node.content
98
98
 
99
99
  content_token = node.content
100
- code = content_token.value.to_s.strip
100
+ raw_value = content_token.value.to_s
101
+ code = raw_value.strip
101
102
  return if code.empty?
102
103
 
103
- # Herb lines are 1-based, we use 0-based
104
+ # Herb lines are 1-based, we use 0-based; raw content begins right after
105
+ # the opening tag, so advance past leading whitespace stripped from `code`.
104
106
  loc = content_token.location
105
- line = loc.start.line - 1
106
- column = loc.start.column
107
+ line, column = advance_past_leading_whitespace(raw_value, loc.start.line - 1, loc.start.column)
107
108
 
108
109
  tag = node.respond_to?(:tag_opening) ? node.tag_opening.value.to_s : '<%'
109
110
  type = case tag
@@ -120,10 +121,12 @@ module SorbetView
120
121
  return unless node.respond_to?(:content) && node.content
121
122
 
122
123
  loc = node.content.location
124
+ raw_value = node.content.value.to_s
125
+ line, column = advance_past_leading_whitespace(raw_value, loc.start.line - 1, loc.start.column)
123
126
  segments << RubySegment.new(
124
127
  code: 'end',
125
- line: loc.start.line - 1,
126
- column: loc.start.column,
128
+ line: line,
129
+ column: column,
127
130
  type: :statement
128
131
  )
129
132
  end
@@ -137,14 +140,16 @@ module SorbetView
137
140
  source.scan(INDICATOR_PATTERN) do
138
141
  match = T.must(Regexp.last_match)
139
142
  indicator = match[1] || ''
140
- code = (match[2] || '').strip
143
+ raw_code = match[2] || ''
144
+ code = raw_code.strip
141
145
  offset = T.must(match.begin(0))
142
146
 
143
147
  next if code.empty?
144
148
 
145
149
  line, column = offset_to_line_column(line_offsets, offset)
146
150
  tag_prefix_len = 2 + indicator.length
147
- code_column = column + tag_prefix_len
151
+ content_column = column + tag_prefix_len
152
+ code_line, code_column = advance_past_leading_whitespace(raw_code, line, content_column)
148
153
 
149
154
  type = case indicator
150
155
  when '#' then :comment
@@ -152,7 +157,7 @@ module SorbetView
152
157
  else :statement
153
158
  end
154
159
 
155
- segments << RubySegment.new(code: code, line: line, column: code_column, type: type)
160
+ segments << RubySegment.new(code: code, line: code_line, column: code_column, type: type)
156
161
  end
157
162
 
158
163
  segments
@@ -173,6 +178,23 @@ module SorbetView
173
178
  column = offset - (line_offsets[line] || 0)
174
179
  [line, column]
175
180
  end
181
+
182
+ # Returns the (line, column) of the first non-whitespace char in raw_value,
183
+ # given the position where raw_value begins. Used so that stripping leading
184
+ # whitespace from ERB content does not desync the segment's start position.
185
+ sig { params(raw_value: String, line: Integer, column: Integer).returns([Integer, Integer]) }
186
+ def advance_past_leading_whitespace(raw_value, line, column)
187
+ leading = raw_value[/\A\s*/] || ''
188
+ return [line, column] if leading.empty?
189
+
190
+ newlines = leading.count("\n")
191
+ if newlines == 0
192
+ [line, column + leading.length]
193
+ else
194
+ last_nl = T.must(leading.rindex("\n"))
195
+ [line + newlines, leading.length - last_nl - 1]
196
+ end
197
+ end
176
198
  end
177
199
  end
178
200
  end
@@ -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),
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module SorbetView
5
- VERSION = '0.17.0'
5
+ VERSION = '0.17.2'
6
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sorbet_view
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.17.0
4
+ version: 0.17.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - kazuma
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2026-04-04 00:00:00.000000000 Z
10
+ date: 2026-04-22 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: herb
@@ -118,7 +118,6 @@ files:
118
118
  - lib/sorbet_view/source_map/source_map.rb
119
119
  - lib/sorbet_view/version.rb
120
120
  - lib/tapioca/dsl/compilers/sorbet_view.rb
121
- - sorbet_view.gemspec
122
121
  - vscode/.gitignore
123
122
  - vscode/.vscode/launch.json
124
123
  - vscode/.vscodeignore
data/sorbet_view.gemspec DELETED
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'lib/sorbet_view/version'
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = 'sorbet_view'
7
- spec.version = SorbetView::VERSION
8
- spec.authors = ['kazuma']
9
- spec.summary = 'Sorbet type-checking for Rails view templates'
10
- spec.description = 'Extracts Ruby code from view templates (ERB, etc.) for Sorbet type-checking, with LSP support'
11
- spec.homepage = 'https://github.com/kazzix14/sorbet_view'
12
- spec.license = 'MIT'
13
- spec.required_ruby_version = '>= 3.2'
14
-
15
- spec.metadata['rubygems_mfa_required'] = 'true'
16
- spec.metadata['homepage_uri'] = spec.homepage
17
- spec.metadata['source_code_uri'] = spec.homepage
18
-
19
- spec.files = Dir.chdir(__dir__) do
20
- `git ls-files -z`.split("\x0").reject do |f|
21
- (File.expand_path(f) == __FILE__) ||
22
- f.start_with?(*%w[bin/ test/ spec/ features/ .git .github Gemfile])
23
- end
24
- end
25
- spec.bindir = 'exe'
26
- spec.executables = ['sv']
27
- spec.require_paths = ['lib']
28
-
29
- spec.add_dependency 'herb'
30
- spec.add_dependency 'listen', '~> 3.0'
31
- spec.add_dependency 'psych'
32
- spec.add_dependency 'sorbet-runtime'
33
- spec.add_dependency 'srb_lens', '~> 0.5.1'
34
- end