@@ -137,6 +137,8 @@ def skip_quoted_string(content:, index:)
137137 def string_literal_at ( content :, index :)
138138 return "'''" if content [ index , 3 ] == "'''"
139139 return '"""' if content [ index , 3 ] == '"""'
140+ return "$/" if content [ index , 2 ] == "$/"
141+ return "/" if content [ index , 1 ] == "/" && slashy_string_start? ( content : content , index : index )
140142 return "'" if content [ index , 1 ] == "'"
141143 return '"' if content [ index , 1 ] == '"'
142144
@@ -145,6 +147,9 @@ def string_literal_at(content:, index:)
145147
146148 sig { params ( content : String , start_index : Integer , quote : String ) . returns ( Integer ) }
147149 def advance_after_string ( content :, start_index :, quote :)
150+ return advance_after_dollar_slashy_string ( content : content , start_index : start_index ) if quote == "$/"
151+ return advance_after_slashy_string ( content : content , start_index : start_index ) if quote == "/"
152+
148153 index = T . let ( start_index , Integer )
149154
150155 while index < content . length
@@ -168,6 +173,67 @@ def advance_after_string(content:, start_index:, quote:)
168173 content . length
169174 end
170175
176+ sig { params ( content : String , start_index : Integer ) . returns ( Integer ) }
177+ def advance_after_slashy_string ( content :, start_index :)
178+ index = T . let ( start_index , Integer )
179+
180+ while index < content . length
181+ if content [ index , 1 ] == "\\ "
182+ index += 2
183+ next
184+ end
185+
186+ return index + 1 if content [ index , 1 ] == "/"
187+
188+ index += 1
189+ end
190+
191+ content . length
192+ end
193+
194+ sig { params ( content : String , start_index : Integer ) . returns ( Integer ) }
195+ def advance_after_dollar_slashy_string ( content :, start_index :)
196+ index = T . let ( start_index , Integer )
197+
198+ while index < content . length
199+ return index + 2 if content [ index , 2 ] == "/$"
200+
201+ if content [ index , 1 ] == "$"
202+ index += 2
203+ next
204+ end
205+
206+ index += 1
207+ end
208+
209+ content . length
210+ end
211+
212+ sig { params ( content : String , index : Integer ) . returns ( T ::Boolean ) }
213+ def slashy_string_start? ( content :, index :)
214+ return false if content [ index , 2 ] == "//"
215+ return false if content [ index , 2 ] == "/*"
216+
217+ previous = previous_non_whitespace_character ( content : content , index : index )
218+ return true unless previous
219+
220+ !!( previous =~ /[=(:,!?&|\[ {;]/ )
221+ end
222+
223+ sig { params ( content : String , index : Integer ) . returns ( T . nilable ( String ) ) }
224+ def previous_non_whitespace_character ( content :, index :)
225+ cursor = T . let ( index - 1 , Integer )
226+
227+ while cursor >= 0
228+ character = T . must ( content [ cursor ] )
229+ return character unless character . match? ( /\s / )
230+
231+ cursor -= 1
232+ end
233+
234+ nil
235+ end
236+
171237 sig { params ( quote : String ) . returns ( T ::Boolean ) }
172238 def triple_quote? ( quote )
173239 quote . length == 3
0 commit comments