From b4094844ebd6707b7e613fb2f13fb639584c2391 Mon Sep 17 00:00:00 2001 From: Franklin Hu Date: Fri, 8 Mar 2024 10:07:08 -0800 Subject: [PATCH 1/3] Add pre-push hook --- bin/pre-push | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 bin/pre-push diff --git a/bin/pre-push b/bin/pre-push new file mode 100755 index 0000000..c5986ef --- /dev/null +++ b/bin/pre-push @@ -0,0 +1,5 @@ +#!/bin/bash + +bundle exec rake test +bundle exec rubocop --parallel + From af4ab917505836c0c1af6cb4a1ec5ee2abb3fd4a Mon Sep 17 00:00:00 2001 From: Franklin Hu Date: Fri, 8 Mar 2024 10:08:01 -0800 Subject: [PATCH 2/3] Fix single quotes --- .rubocop.yml | 2 +- Gemfile | 8 +++--- Rakefile | 6 ++-- bin/console | 6 ++-- exe/sorbet_erb | 3 +- lib/sorbet_erb.rb | 31 ++++++++++----------- lib/sorbet_erb/code_extractor.rb | 18 ++++-------- lib/sorbet_erb/version.rb | 2 +- sorbet_erb.gemspec | 30 ++++++++++---------- test/code_extractor_test.rb | 48 ++++++++++++++++---------------- test/test_helper.rb | 6 ++-- test/test_sorbet_erb.rb | 2 +- 12 files changed, 76 insertions(+), 86 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index e3462a7..98e3cbb 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -3,7 +3,7 @@ AllCops: Style/StringLiterals: Enabled: true - EnforcedStyle: double_quotes + EnforcedStyle: single_quotes Style/StringLiteralsInInterpolation: Enabled: true diff --git a/Gemfile b/Gemfile index 81b90ae..b5ca513 100644 --- a/Gemfile +++ b/Gemfile @@ -1,12 +1,12 @@ # frozen_string_literal: true -source "https://rubygems.org" +source 'https://rubygems.org' # Specify your gem's dependencies in sorbet_erb.gemspec gemspec -gem "rake", "~> 13.0" +gem 'rake', '~> 13.0' -gem "minitest", "~> 5.16" +gem 'minitest', '~> 5.16' -gem "rubocop", "~> 1.21" +gem 'rubocop', '~> 1.21' diff --git a/Rakefile b/Rakefile index 2bf771f..ea495fe 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,11 @@ # frozen_string_literal: true -require "bundler/gem_tasks" -require "minitest/test_task" +require 'bundler/gem_tasks' +require 'minitest/test_task' Minitest::TestTask.create -require "rubocop/rake_task" +require 'rubocop/rake_task' RuboCop::RakeTask.new diff --git a/bin/console b/bin/console index d8b0031..5c622c3 100755 --- a/bin/console +++ b/bin/console @@ -1,11 +1,11 @@ #!/usr/bin/env ruby # frozen_string_literal: true -require "bundler/setup" -require "sorbet_erb" +require 'bundler/setup' +require 'sorbet_erb' # You can add fixtures and/or initialization code here to make experimenting # with your gem easier. You can also use a different console, if you like. -require "irb" +require 'irb' IRB.start(__FILE__) diff --git a/exe/sorbet_erb b/exe/sorbet_erb index 7475859..568f97b 100755 --- a/exe/sorbet_erb +++ b/exe/sorbet_erb @@ -1,7 +1,6 @@ #! /usr/bin/env ruby # frozen_string_literal: true -require_relative "../lib/sorbet_erb" +require_relative '../lib/sorbet_erb' SorbetErb.start(ARGV) - diff --git a/lib/sorbet_erb.rb b/lib/sorbet_erb.rb index e1764ce..c696ab4 100644 --- a/lib/sorbet_erb.rb +++ b/lib/sorbet_erb.rb @@ -4,11 +4,10 @@ require 'fileutils' require 'pathname' -require_relative "sorbet_erb/code_extractor" -require_relative "sorbet_erb/version" +require_relative 'sorbet_erb/code_extractor' +require_relative 'sorbet_erb/version' module SorbetErb - USAGE = <<~END Usage: sorbet_erb input_dir output_dir input_dir - where to scan for ERB files @@ -29,40 +28,39 @@ def body<%= locals %> END def self.extract_rb_from_erb(path, output_dir) - puts "Clearing output directory" + puts 'Clearing output directory' FileUtils.rm_rf(output_dir) puts "Extracting ruby from erb: #{path} -> #{output_dir}" - Dir.glob(File.join(path, "**", "*.erb")).each do |p| + Dir.glob(File.join(path, '**', '*.erb')).each do |p| puts "Processing #{p}" pathname = Pathname.new(p) extractor = CodeExtractor.new lines, locals = extractor.extract(File.read(p)) - if pathname.basename.to_s.start_with?("_") && locals.nil? - # Partials must use strict locals - next - else - locals ||= "()" - end + next if pathname.basename.to_s.start_with?('_') && locals.nil? + + # Partials must use strict locals + + locals ||= '()' rel_output_dir = File.join( output_dir, - pathname.dirname.relative_path_from(path), + pathname.dirname.relative_path_from(path) ) FileUtils.mkdir_p(rel_output_dir) output_path = File.join( rel_output_dir, - "#{pathname.basename}.generated.rb", + "#{pathname.basename}.generated.rb" ) erb = ERB.new(ERB_TEMPLATE) - File.open(output_path, "w") do |f| + File.open(output_path, 'w') do |f| result = erb.result_with_hash( class_suffix: SecureRandom.hex(6), locals: locals, - lines: lines, + lines: lines ) f.write(result) end @@ -74,10 +72,9 @@ def self.start(argv) output = argv[1] if input.nil? || output.nil? - $stderr.puts USAGE + warn USAGE exit(1) end SorbetErb.extract_rb_from_erb(input, output) end end - diff --git a/lib/sorbet_erb/code_extractor.rb b/lib/sorbet_erb/code_extractor.rb index 313e565..5172450 100644 --- a/lib/sorbet_erb/code_extractor.rb +++ b/lib/sorbet_erb/code_extractor.rb @@ -5,26 +5,23 @@ module SorbetErb class CodeExtractor - def initialize - end + def initialize; end def extract(input) buffer = Parser::Source::Buffer.new('(buffer)') buffer.source = input parser = BetterHtml::Parser.new(buffer) - output = "" - p = CodeProcessor.new p.process(parser.ast) - return p.output, p.locals + [p.output, p.locals] end end class CodeProcessor include AST::Processor::Mixin - LOCALS_PREFIX = "locals: " + LOCALS_PREFIX = 'locals: ' attr_accessor :output, :locals @@ -43,16 +40,14 @@ def on_erb(node) indicator_node = node.children.compact.find { |c| c.type == :indicator } code_node = node.children.compact.find { |c| c.type == :code } - if indicator_node.nil? - return process(code_node) - end + return process(code_node) if indicator_node.nil? indicator = indicator_node.children.first case indicator - when "#" + when '#' # Ignore comments if it's not strict locals code_text = code_node.children.first.strip - return if !code_text.start_with?(LOCALS_PREFIX) + return unless code_text.start_with?(LOCALS_PREFIX) # No need to parse the locals @locals = code_text.delete_prefix(LOCALS_PREFIX).strip @@ -66,4 +61,3 @@ def on_code(node) end end end - diff --git a/lib/sorbet_erb/version.rb b/lib/sorbet_erb/version.rb index 72f546d..cf35793 100644 --- a/lib/sorbet_erb/version.rb +++ b/lib/sorbet_erb/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module SorbetErb - VERSION = "0.1.0" + VERSION = '0.1.0' end diff --git a/sorbet_erb.gemspec b/sorbet_erb.gemspec index e27e765..557e40c 100644 --- a/sorbet_erb.gemspec +++ b/sorbet_erb.gemspec @@ -1,23 +1,23 @@ # frozen_string_literal: true -require_relative "lib/sorbet_erb/version" +require_relative 'lib/sorbet_erb/version' Gem::Specification.new do |spec| - spec.name = "sorbet_erb" + spec.name = 'sorbet_erb' spec.version = SorbetErb::VERSION - spec.authors = ["Franklin Hu"] - spec.email = ["franklin@thisisfranklin.com"] + spec.authors = ['Franklin Hu'] + spec.email = ['franklin@thisisfranklin.com'] - spec.summary = "Extracts Ruby code from ERB files for Sorbet" - spec.description = "Extracts Ruby code from ERB files so you can run Sorbet over them" - spec.homepage = "https://github.com/franklinhu/sorbet_erb" - spec.required_ruby_version = ">= 2.6.0" + spec.summary = 'Extracts Ruby code from ERB files for Sorbet' + spec.description = 'Extracts Ruby code from ERB files so you can run Sorbet over them' + spec.homepage = 'https://github.com/franklinhu/sorbet_erb' + spec.required_ruby_version = '>= 2.6.0' - spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'" + spec.metadata['allowed_push_host'] = "TODO: Set to your gem server 'https://example.com'" - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["changelog_uri"] = spec.homepage + spec.metadata['homepage_uri'] = spec.homepage + spec.metadata['source_code_uri'] = spec.homepage + spec.metadata['changelog_uri'] = spec.homepage # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. @@ -27,9 +27,9 @@ Gem::Specification.new do |spec| f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile]) end end - spec.bindir = "exe" + spec.bindir = 'exe' spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] + spec.require_paths = ['lib'] - spec.add_dependency "better_html", "~> 2.0.2" + spec.add_dependency 'better_html', '~> 2.0.2' end diff --git a/test/code_extractor_test.rb b/test/code_extractor_test.rb index b42ca4b..a1d16a1 100644 --- a/test/code_extractor_test.rb +++ b/test/code_extractor_test.rb @@ -1,65 +1,65 @@ # frozen_string_literal: true -require "test_helper" +require 'test_helper' class CodeExtractorTest < Minitest::Spec it 'handles erb' do test_cases = [ { - name: "normal code", + name: 'normal code', input: <<~END,
<% value -%>
END output: [ - " value ", + ' value ' ], - locals: nil, + locals: nil }, { - name: "expression", + name: 'expression', input: <<~END, <%= @something %> END output: [ - " @something ", + ' @something ' ], - locals: nil, + locals: nil }, { - name: "comment", + name: 'comment', input: <<~END, - <%# comment %> + <%# comment %> END output: [], - locals: nil, + locals: nil }, { - name: "for loop", + name: 'for loop', input: <<~END, - <% collection.each do |item| %> - <%= item.name %> - <% end %> + <% collection.each do |item| %> + <%= item.name %> + <% end %> END output: [ - " collection.each do |item| ", - " item.name ", - " end ", + ' collection.each do |item| ', + ' item.name ', + ' end ' ], - locals: nil, + locals: nil }, { - name: "strict locals - no defaults", + name: 'strict locals - no defaults', input: <<~END, - <%# locals: (a:, b:) %> - <%= a %> + <%# locals: (a:, b:) %> + <%= a %> END output: [ - " a ", + ' a ' ], - locals: "(a:, b:)", - }, + locals: '(a:, b:)' + } ] test_cases.each do |tc| e = SorbetErb::CodeExtractor.new diff --git a/test/test_helper.rb b/test/test_helper.rb index 688545e..1f00c09 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -$LOAD_PATH.unshift File.expand_path("../lib", __dir__) -require "sorbet_erb" +$LOAD_PATH.unshift File.expand_path('../lib', __dir__) +require 'sorbet_erb' -require "minitest/autorun" +require 'minitest/autorun' diff --git a/test/test_sorbet_erb.rb b/test/test_sorbet_erb.rb index 9c95a67..270f799 100644 --- a/test/test_sorbet_erb.rb +++ b/test/test_sorbet_erb.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -require "test_helper" +require 'test_helper' class TestSorbetErb < Minitest::Test def test_that_it_has_a_version_number From da39d8a542c7bf3d16524eb3bbb4fe769366b1ec Mon Sep 17 00:00:00 2001 From: Franklin Hu Date: Fri, 8 Mar 2024 10:16:40 -0800 Subject: [PATCH 3/3] Fix rubocop --- .rubocop.yml | 13 +++++++++++++ lib/sorbet_erb.rb | 8 ++++---- test/code_extractor_test.rb | 20 ++++++++++---------- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 98e3cbb..5fb9870 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,9 @@ AllCops: TargetRubyVersion: 2.6 +Style/Documentation: + Enabled: false + Style/StringLiterals: Enabled: true EnforcedStyle: single_quotes @@ -11,3 +14,13 @@ Style/StringLiteralsInInterpolation: Layout/LineLength: Max: 120 + +Metrics/AbcSize: + Enabled: false + +Metrics/BlockLength: + Enabled: false + +Metrics/MethodLength: + Enabled: false + diff --git a/lib/sorbet_erb.rb b/lib/sorbet_erb.rb index c696ab4..40c5eb5 100644 --- a/lib/sorbet_erb.rb +++ b/lib/sorbet_erb.rb @@ -8,13 +8,13 @@ require_relative 'sorbet_erb/version' module SorbetErb - USAGE = <<~END + USAGE = <<~USAGE Usage: sorbet_erb input_dir output_dir input_dir - where to scan for ERB files output_dir - where to write files with Ruby extracted from ERB - END + USAGE - ERB_TEMPLATE = <<~END + ERB_TEMPLATE = <<~ERB_TEMPLATE # typed: true class SorbetErb<%= class_suffix %> < ApplicationController include ApplicationController::HelperMethods @@ -25,7 +25,7 @@ def body<%= locals %> <% end %> end end - END + ERB_TEMPLATE def self.extract_rb_from_erb(path, output_dir) puts 'Clearing output directory' diff --git a/test/code_extractor_test.rb b/test/code_extractor_test.rb index a1d16a1..db5f7a4 100644 --- a/test/code_extractor_test.rb +++ b/test/code_extractor_test.rb @@ -7,11 +7,11 @@ class CodeExtractorTest < Minitest::Spec test_cases = [ { name: 'normal code', - input: <<~END, + input: <<~INPUT,
<% value -%>
- END + INPUT output: [ ' value ' ], @@ -19,9 +19,9 @@ class CodeExtractorTest < Minitest::Spec }, { name: 'expression', - input: <<~END, + input: <<~INPUT, <%= @something %> - END + INPUT output: [ ' @something ' ], @@ -29,19 +29,19 @@ class CodeExtractorTest < Minitest::Spec }, { name: 'comment', - input: <<~END, + input: <<~INPUT, <%# comment %> - END + INPUT output: [], locals: nil }, { name: 'for loop', - input: <<~END, + input: <<~INPUT, <% collection.each do |item| %> <%= item.name %> <% end %> - END + INPUT output: [ ' collection.each do |item| ', ' item.name ', @@ -51,10 +51,10 @@ class CodeExtractorTest < Minitest::Spec }, { name: 'strict locals - no defaults', - input: <<~END, + input: <<~INPUT, <%# locals: (a:, b:) %> <%= a %> - END + INPUT output: [ ' a ' ],