diff --git a/Gemfile b/Gemfile index e8784ebae..2fb3f7495 100644 --- a/Gemfile +++ b/Gemfile @@ -18,3 +18,4 @@ end # gem "rbs", path: "../rbs" gem "rbs", git: "https://github.com/ruby/rbs.git", branch: "master" +gem "herb", "~> 0.9" diff --git a/Gemfile.lock b/Gemfile.lock index c7fe1ce9a..1e66a19d0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,6 +16,7 @@ PATH concurrent-ruby (>= 1.1.10) csv (>= 3.0.9) fileutils (>= 1.1.0) + herb (>= 0.9.0) json (>= 2.1.0) language_server-protocol (>= 3.17.0.4, < 4.0) listen (~> 3.0) @@ -58,6 +59,7 @@ GEM erb (6.0.2) ffi (1.17.3) fileutils (1.8.0) + herb (0.9.0) i18n (1.14.8) concurrent-ruby (~> 1.0) io-console (0.8.2) @@ -122,6 +124,7 @@ PLATFORMS DEPENDENCIES debug + herb (~> 0.9) majo memory_profiler minitest (~> 5.25) diff --git a/lib/steep/source.rb b/lib/steep/source.rb index 2a8436a32..6bf6d3584 100644 --- a/lib/steep/source.rb +++ b/lib/steep/source.rb @@ -1,3 +1,5 @@ +require "herb" + module Steep class Source attr_reader :buffer @@ -38,6 +40,8 @@ def self.new_parser end def self.parse(source_code, path:, factory:) + source_code = extract_ruby_from_erb(source_code) if path.to_s.end_with?(".erb") + buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code) node, comments = new_parser().parse_with_comments(buffer) @@ -98,6 +102,10 @@ def self.parse(source_code, path:, factory:) new(buffer: buffer, path: path, node: node, mapping: map, comments: comments, ignores: ignores) end + def self.extract_ruby_from_erb(source_code) + ::Herb.extract_ruby(source_code, semicolons: true, comments: true) + end + def self.construct_mapping(node:, annotations:, mapping:, line_range: nil) case node.type when :if diff --git a/sig/test/cli_test.rbs b/sig/test/cli_test.rbs index aaf5324d1..57908fb91 100644 --- a/sig/test/cli_test.rbs +++ b/sig/test/cli_test.rbs @@ -21,6 +21,10 @@ class CLITest < Minitest::Test def test_check_failure: () -> untyped + def test_erb_check_failure: () -> untyped + + def test_erb_check_success: () -> untyped + def test_check_failure_with_formatter: () -> untyped def test_check_group__target: () -> untyped diff --git a/steep.gemspec b/steep.gemspec index 42d84cc6d..d95bf62d9 100644 --- a/steep.gemspec +++ b/steep.gemspec @@ -52,4 +52,5 @@ Gem::Specification.new do |spec| spec.add_runtime_dependency "strscan", ">= 1.0.0" spec.add_runtime_dependency "csv", ">= 3.0.9" spec.add_runtime_dependency "uri", ">= 0.12.0" + spec.add_runtime_dependency "herb", ">= 0.9" end diff --git a/test/cli_test.rb b/test/cli_test.rb index aa5ceea50..cdf95e659 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -125,6 +125,52 @@ def test_check_failure end end + def test_erb_check_failure + in_tmpdir do + (current_dir + "Steepfile").write(<<-EOF) +target :app do + check "app/views/**/*.erb" +end + EOF + + (current_dir + "app").mkdir + (current_dir + "app/views").mkdir + (current_dir + "app/views/companies").mkdir + + (current_dir + "app/views/companies/_form.html.erb").write(<<-EOF) +