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
10 changes: 10 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ on:
branches: [main, master]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: '4.0'
bundler-cache: true
- run: bundle exec rubocop

test:
runs-on: ubuntu-latest
strategy:
Expand Down
5 changes: 5 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
inherit_gem:
rubocop-shopify: rubocop.yml

AllCops:
SuggestExtensions: false
8 changes: 7 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }

# Specify your gem's dependencies in ast_transform.gemspec
gemspec

# Transitive dependency of rubocop: parallel >= 2 requires Ruby >= 3.3, but we
# still support 3.2. Drop this pin when our Ruby floor moves to 3.3.
gem "parallel", "< 2", require: false
27 changes: 27 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ GEM
diff-lcs (1.6.2)
docile (1.4.1)
io-console (0.8.2)
json (2.21.1)
language_server-protocol (3.17.0.6)
lint_roller (1.1.0)
method_source (1.1.0)
minitest (5.27.0)
minitest-reporters (1.7.1)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
parallel (1.28.0)
parser (3.3.10.2)
ast (~> 2.4.1)
racc
Expand All @@ -32,16 +36,37 @@ GEM
method_source (~> 1.0)
reline (>= 0.6.0)
racc (1.8.1)
rainbow (3.1.1)
rake (13.3.1)
regexp_parser (2.12.0)
reline (0.6.3)
io-console (~> 0.5)
rubocop (1.88.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (>= 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.50.0)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-shopify (2.18.0)
rubocop (~> 1.62)
ruby-progressbar (1.13.0)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.13.2)
simplecov_json_formatter (0.1.4)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
unparser (0.8.1)
diff-lcs (~> 1.6)
parser (>= 3.3.0)
Expand All @@ -56,8 +81,10 @@ DEPENDENCIES
bundler (>= 2.1)
minitest (~> 5.14)
minitest-reporters (~> 1.4)
parallel (< 2)
pry (>= 0.14)
rake (~> 13.0)
rubocop-shopify (~> 2.18)
simplecov (~> 0.22)

BUNDLED WITH
Expand Down
15 changes: 8 additions & 7 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
# frozen_string_literal: true
require 'bundler/gem_tasks'
require 'rake/testtask'

require "bundler/gem_tasks"
require "rake/testtask"

Rake::TestTask.new(:test) do |t|
# Ensure we load test_loader first for ASTTransform.install
filepath = File.expand_path('test/test_loader.rb', __dir__)
filepath = File.expand_path("test/test_loader.rb", __dir__)
t.ruby_opts << "-r #{filepath}"
t.warning = false

t.libs << 'test'
t.libs << 'lib'
t.test_files = FileList['test/**/*_test.rb']
t.libs << "test"
t.libs << "lib"
t.test_files = FileList["test/**/*_test.rb"]
end

task :default => :test
task default: :test
27 changes: 15 additions & 12 deletions ast_transform.gemspec
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# frozen_string_literal: true

lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
Expand All @@ -9,28 +10,30 @@ Gem::Specification.new do |spec|
spec.authors = ["Jean-Philippe Duchesne"]
spec.email = ["jpduchesne89@gmail.com"]

spec.summary = 'An AST transformation framework.'
spec.summary = "An AST transformation framework."
spec.description = spec.summary
spec.homepage = "https://github.com/rspockframework/ast-transform"
spec.license = "MIT"
spec.files = `git ls-files -z`.split("\x0").reject do |f|
spec.files = %x(git ls-files -z).split("\x0").reject do |f|
f.match(%r{^(test|spec|features)/})
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.required_ruby_version = '>= 3.2'
spec.required_ruby_version = ">= 3.2"

# Development dependencies
spec.add_development_dependency "bundler", ">= 2.1"
spec.add_development_dependency "rake", "~> 13.0"
spec.add_development_dependency "minitest", "~> 5.14"
spec.add_development_dependency "minitest-reporters", "~> 1.4"
spec.add_development_dependency "pry", ">= 0.14"
spec.add_development_dependency "simplecov", "~> 0.22"
spec.add_development_dependency("bundler", ">= 2.1")
spec.add_development_dependency("minitest", "~> 5.14")
spec.add_development_dependency("minitest-reporters", "~> 1.4")
spec.add_development_dependency("pry", ">= 0.14")
spec.add_development_dependency("rake", "~> 13.0")
# rubocop-shopify >= 3.0 requires Ruby >= 3.3; bump alongside our own floor.
spec.add_development_dependency("rubocop-shopify", "~> 2.18")
spec.add_development_dependency("simplecov", "~> 0.22")

# Runtime dependencies
spec.add_runtime_dependency "parser", ">= 3.0"
spec.add_runtime_dependency "prism", ">= 1.5"
spec.add_runtime_dependency "unparser", ">= 0.6"
spec.add_runtime_dependency("parser", ">= 3.0")
spec.add_runtime_dependency("prism", ">= 1.5")
spec.add_runtime_dependency("unparser", ">= 0.6")
end
1 change: 1 addition & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "bundler/setup"
require "ast_transform"
Expand Down
11 changes: 11 additions & 0 deletions dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: ast_transform
commands:
up:
desc: Install gems
run: bundle install
test:
desc: Run this repo's tests
run: bundle exec rake test
style:
desc: Run RuboCop
run: bundle exec rubocop
26 changes: 11 additions & 15 deletions lib/ast_transform.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# frozen_string_literal: true

require "ast_transform/version"
require 'ast_transform/instruction_sequence'
require 'ast_transform/instruction_sequence/mixin'
require 'ast_transform/instruction_sequence/bootsnap_mixin'
require "ast_transform/instruction_sequence"
require "ast_transform/instruction_sequence/mixin"
require "ast_transform/instruction_sequence/bootsnap_mixin"

module ASTTransform
DEFAULT_OUTPUT_PATH = Pathname.new("").join("tmp", "ast_transform").to_s
Expand All @@ -19,22 +19,18 @@ def acronym(acronym)
end

def install
@installed ||= begin
if defined?(Bootsnap) && ASTTransform::InstructionSequence.using_bootsnap_compilation?
class << Bootsnap::CompileCache::ISeq
prepend ::ASTTransform::InstructionSequence::BootsnapMixin
end
else
class << RubyVM::InstructionSequence
prepend ::ASTTransform::InstructionSequence::Mixin
end
@installed ||= if defined?(Bootsnap) && ASTTransform::InstructionSequence.using_bootsnap_compilation?
class << Bootsnap::CompileCache::ISeq
prepend ::ASTTransform::InstructionSequence::BootsnapMixin
end
else
class << RubyVM::InstructionSequence
prepend ::ASTTransform::InstructionSequence::Mixin
end
end
end

def output_path=(path)
@output_path = path
end
attr_writer :output_path

def output_path
@output_path || DEFAULT_OUTPUT_PATH
Expand Down
3 changes: 2 additions & 1 deletion lib/ast_transform/abstract_transformation.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'ast_transform/transformation_helper'

require "ast_transform/transformation_helper"

module ASTTransform
class AbstractTransformation < Parser::AST::Processor
Expand Down
5 changes: 3 additions & 2 deletions lib/ast_transform/instruction_sequence.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

module ASTTransform
module InstructionSequence
class << self
Expand All @@ -22,12 +23,12 @@ def source_to_transformed_iseq(source, source_path)
def write_pathname(file_path)
project_path = File.expand_path("")
relative_source_file_pathname = Pathname.new(file_path).relative_path_from(Pathname.new(project_path))
Pathname.new("").join(project_path, 'tmp', 'ast_transform', relative_source_file_pathname)
Pathname.new("").join(project_path, "tmp", "ast_transform", relative_source_file_pathname)
end

def write(string, pathname)
FileUtils.mkdir_p(pathname.dirname)
File.open(pathname, 'w') do |file|
File.open(pathname, "w") do |file|
file.write(string)
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/ast_transform/instruction_sequence/bootsnap_mixin.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# frozen_string_literal: true

require 'ast_transform/transformer'
require 'ast_transform/instruction_sequence/mixin_utils'
require 'pathname'
require "ast_transform/transformer"
require "ast_transform/instruction_sequence/mixin_utils"
require "pathname"

module ASTTransform
module InstructionSequence
Expand All @@ -14,7 +14,7 @@ def input_to_storage(source, source_path)
iseq = ASTTransform::InstructionSequence.source_to_transformed_iseq(source, source_path)
iseq.to_binary
rescue SyntaxError
raise ::Bootsnap::CompileCache::Uncompilable, 'syntax error'
raise ::Bootsnap::CompileCache::Uncompilable, "syntax error"
end
end
end
Expand Down
11 changes: 6 additions & 5 deletions lib/ast_transform/instruction_sequence/mixin.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# frozen_string_literal: true
require 'pathname'
require 'ast_transform/transformer'
require 'ast_transform/transformation'
require 'ast_transform/instruction_sequence/mixin_utils'

require "pathname"
require "ast_transform/transformer"
require "ast_transform/transformation"
require "ast_transform/instruction_sequence/mixin_utils"

module ASTTransform
module InstructionSequence
Expand All @@ -15,7 +16,7 @@ def load_iseq(source_path)
# 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.include?('transform!'.b)
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
2 changes: 1 addition & 1 deletion lib/ast_transform/instruction_sequence/mixin_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module MixinUtils
class << self
def try_super(target, method_sym, *args, &block)
super_method = target.method(method_sym).super_method
super_method ? super_method.call(*args, &block) : nil
super_method&.call(*args, &block)
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/ast_transform/kwargs_builder.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

require 'prism/translation/parser'
require "prism/translation/parser"

module ASTTransform
# Extends the default Prism parser builder to distinguish keyword arguments
Expand Down
10 changes: 7 additions & 3 deletions lib/ast_transform/source_map.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# frozen_string_literal: true
require 'parser'

require "parser"

module ASTTransform
class SourceMap
Expand Down Expand Up @@ -28,7 +29,9 @@ def for_file_path(file_path)
private

def source_maps
@@source_maps ||= {}
# Class instance var (not @@): read/written only through this method
# inside class << self, and SourceMap has no subclasses to share with.
@source_maps ||= {}
end
end

Expand Down Expand Up @@ -97,7 +100,7 @@ def extract_source_map_data(node, indexes)
#
# @return [Hash] A Hash containing line numbers from executed code to source code.
def build_source_map
(1..line_count).each.with_object({}) {|it, hash| hash[it] = source_line(it) }
(1..line_count).each.with_object({}) { |it, hash| hash[it] = source_line(it) }
end

# Retrieves the source line for the given +line_number+ in the executed code.
Expand Down Expand Up @@ -226,6 +229,7 @@ def dig_last_valid_node(node, indexes)
def dig_node(node, indexes)
indexes.inject(node) do |node, index|
return nil unless node.is_a?(Parser::AST::Node)

node.children[index]
end
end
Expand Down
Loading
Loading