Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/ast_transform/instruction_sequence.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def source_to_transformed_iseq(source, source_path)
rewritten_source = transformer.transform_file_source(source, source_path, rewritten_file_pathname.to_s)
write(rewritten_source, rewritten_file_pathname)

RubyVM::InstructionSequence.compile(rewritten_source, rewritten_file_pathname.to_s, rewritten_file_pathname.to_s)
RubyVM::InstructionSequence.compile(rewritten_source, source_path, source_path)
end

def write_pathname(file_path)
Expand Down
7 changes: 5 additions & 2 deletions lib/ast_transform/instruction_sequence/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ module Mixin
def load_iseq(source_path)
return ASTTransform::MixinUtils.try_super(self, :load_iseq, source_path) if source_path == __FILE__

source = File.read(source_path)
# Binary read avoids encoding errors during the fast-path check below.
# Downstream (Prism, RubyVM::InstructionSequence) handle encoding natively
# via magic comments, so we never need to set it ourselves.
source = File.binread(source_path)

return ASTTransform::MixinUtils.try_super(self, :load_iseq, source_path) unless source =~ /transform!/
return ASTTransform::MixinUtils.try_super(self, :load_iseq, source_path) unless source.include?('transform!'.b)

ASTTransform::InstructionSequence.source_to_transformed_iseq(source, source_path)
end
Expand Down
1 change: 1 addition & 0 deletions lib/ast_transform/source_map.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class << self
# @return [void]
def register_source_map(source_map)
source_maps[source_map.transformed_file_path] = source_map
source_maps[source_map.source_file_path] = source_map

nil
end
Expand Down
65 changes: 65 additions & 0 deletions test/ast_transform/instruction_sequence_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require 'test_helper'
require 'tempfile'
require 'ast_transform/instruction_sequence'
require 'ast_transform/instruction_sequence/mixin'
require 'ast_transform/transformation'

module ASTTransform
class InstructionSequenceTest < Minitest::Test
extend ASTTransform::Declarative

class ClassWithMixin
include ASTTransform::InstructionSequence::Mixin
end

def setup
@loader = ClassWithMixin.new
end

test "compiled iseq reports original source path" do
source = "1 + 2\n"
source_path = File.expand_path("test/fixtures/dummy.rb")

iseq = ASTTransform::InstructionSequence.source_to_transformed_iseq(source, source_path)

assert_equal source_path, iseq.path,
"ISeq should report the original source path, not the tmp/ rewritten path"
end

test "source_to_transformed_iseq handles binary-encoded source" do
source = "# café résumé\n1 + 2\n".dup.force_encoding('ASCII-8BIT')
source_path = File.expand_path("test/fixtures/encoding_test.rb")

iseq = ASTTransform::InstructionSequence.source_to_transformed_iseq(source, source_path)

assert_equal source_path, iseq.path
end

test "load_iseq skips non-ASCII files without transform!" do
tmpfile = Tempfile.new(['non_ascii', '.rb'])
tmpfile.write("# café résumé\nx = 1\n")
tmpfile.close

iseq = @loader.load_iseq(tmpfile.path)

assert_nil iseq
ensure
tmpfile&.unlink
end

test "load_iseq processes non-ASCII files with transform! without encoding errors" do
tmpfile = Tempfile.new(['non_ascii_transform', '.rb'])
tmpfile.write("# café résumé\nx = 1\n# transform!\n")
tmpfile.close

iseq = @loader.load_iseq(tmpfile.path)

assert_instance_of RubyVM::InstructionSequence, iseq
assert_equal tmpfile.path, iseq.path
ensure
tmpfile&.unlink
end
end
end
14 changes: 14 additions & 0 deletions test/ast_transform/source_map_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ def run(node)
assert_equal 1, source_map.line(2)
end

test "source map is retrievable by source file path" do
transformer = ASTTransform::Transformer.new

source = <<~HEREDOC
method_call
HEREDOC

transformer.transform_file_source(source, '/original/path.rb', '/transformed/path.rb')

source_map = ASTTransform::SourceMap.for_file_path('/original/path.rb')
refute_nil source_map, "source map should be retrievable by source file path"
assert_equal '/original/path.rb', source_map.source_file_path
end

test "#line returns nil when transformation creates nodes that don't contain previous nodes" do
transformation = Class.new(ASTTransform::AbstractTransformation) do
def run(node)
Expand Down