Skip to content
Open
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
24 changes: 4 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ jobs:
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
with:
engine: cruby
min_version: 3.3

test:
needs: ruby-versions
Expand All @@ -33,7 +34,9 @@ jobs:
matrix:
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
prism_version:
- 1.2.0 # Shipped with Ruby 3.4 as default parser https://www.ruby-lang.org/en/news/2024/12/25/ruby-3-4-0-released/
# See https://stdgems.org/prism for which ruby version shipped with which prism version
- 0.19.0
- 1.2.0
- 1.8.0
- head
env:
Expand All @@ -52,22 +55,3 @@ jobs:
- name: test
run: bin/rake test
continue-on-error: ${{ matrix.ruby == 'head' }}

test-disable-prism:
needs: ruby-versions
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: test
run: SYNTAX_SUGGEST_DISABLE_PRISM=1 bin/rake test
continue-on-error: ${{ matrix.ruby == 'head' }}
2 changes: 1 addition & 1 deletion .standard.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ruby_version: 3.0.0
ruby_version: 3.3.0
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## HEAD (unreleased)

- Changed: Changed: Minimum supported Ruby version is now 3.3. (https://github.com/ruby/syntax_suggest/pull/246)

## 2.0.3

- Fix: Correctly identify trailing slashes when using Prism > 1.8.0. (https://github.com/ruby/syntax_suggest/pull/243)
Expand Down
43 changes: 6 additions & 37 deletions lib/syntax_suggest/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,12 @@
require "pathname"
require "timeout"

# Prism is the new parser, replacing Ripper
require "prism"
# We need Ripper loaded for `Prism.lex_compat` even if we're using Prism
# for lexing and parsing
require "ripper"

# Prism is the new parser, replacing Ripper
#
# We need to "dual boot" both for now because syntax_suggest
# supports older rubies that do not ship with syntax suggest.
#
# We also need the ability to control loading of this library
# so we can test that both modes work correctly in CI.
if (value = ENV["SYNTAX_SUGGEST_DISABLE_PRISM"])
warn "Skipping loading prism due to SYNTAX_SUGGEST_DISABLE_PRISM=#{value}"
else
begin
require "prism"
rescue LoadError
end
end

module SyntaxSuggest
# Used to indicate a default value that cannot
# be confused with another input.
Expand All @@ -35,14 +21,6 @@ module SyntaxSuggest
class Error < StandardError; end
TIMEOUT_DEFAULT = ENV.fetch("SYNTAX_SUGGEST_TIMEOUT", 1).to_i

# SyntaxSuggest.use_prism_parser? [Private]
#
# Tells us if the prism parser is available for use
# or if we should fallback to `Ripper`
def self.use_prism_parser?
defined?(Prism)
end

# SyntaxSuggest.handle_error [Public]
#
# Takes a `SyntaxError` exception, uses the
Expand Down Expand Up @@ -152,20 +130,11 @@ def self.valid_without?(without_lines:, code_lines:)
# SyntaxSuggest.invalid? [Private]
#
# Opposite of `SyntaxSuggest.valid?`
if defined?(Prism)
def self.invalid?(source)
source = source.join if source.is_a?(Array)
source = source.to_s
def self.invalid?(source)
source = source.join if source.is_a?(Array)
source = source.to_s

Prism.parse(source).failure?
end
else
def self.invalid?(source)
source = source.join if source.is_a?(Array)
source = source.to_s

Ripper.new(source).tap(&:parse).error?
end
Prism.parse(source).failure?
end

# SyntaxSuggest.valid? [Private]
Expand Down
10 changes: 1 addition & 9 deletions lib/syntax_suggest/explain_syntax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,10 @@

require_relative "left_right_lex_count"

if !SyntaxSuggest.use_prism_parser?
require_relative "ripper_errors"
end

module SyntaxSuggest
class GetParseErrors
def self.errors(source)
if SyntaxSuggest.use_prism_parser?
Prism.parse(source).errors.map(&:message)
else
RipperErrors.new(source).call.errors
end
Prism.parse(source).errors.map(&:message)
end
end

Expand Down
32 changes: 3 additions & 29 deletions lib/syntax_suggest/lex_all.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
# frozen_string_literal: true

module SyntaxSuggest
# Ripper.lex is not guaranteed to lex the entire source document
#
# This class guarantees the whole document is lex-ed by iteratively
# lexing the document where ripper stopped.
#
# Prism likely doesn't have the same problem. Once ripper support is removed
# we can likely reduce the complexity here if not remove the whole concept.
# Lexes the whole source and wraps the tokens in `LexValue`.
#
# Example usage:
#
Expand All @@ -20,34 +14,14 @@ class LexAll

def initialize(source:, source_lines: nil)
@lex = self.class.lex(source, 1)
lineno = @lex.last[0][0] + 1
source_lines ||= source.lines
last_lineno = source_lines.length

until lineno >= last_lineno
lines = source_lines[lineno..]

@lex.concat(
self.class.lex(lines.join, lineno + 1)
)

lineno = @lex.last[0].first + 1
end

last_lex = nil
@lex.map! { |elem|
last_lex = LexValue.new(elem[0].first, elem[1], elem[2], elem[3], last_lex)
}
end

if SyntaxSuggest.use_prism_parser?
def self.lex(source, line_number)
Prism.lex_compat(source, line: line_number).value.sort_by { |values| values[0] }
end
else
def self.lex(source, line_number)
Ripper::Lexer.new(source, "-", line_number).parse.sort_by(&:pos)
end
def self.lex(source, line_number)
Prism.lex_compat(source, line: line_number).value.sort_by { |values| values[0] }
end

def to_a
Expand Down
39 changes: 0 additions & 39 deletions lib/syntax_suggest/ripper_errors.rb

This file was deleted.

4 changes: 0 additions & 4 deletions spec/integration/ruby_command_line_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,13 @@ module SyntaxSuggest
end

it "gem can be tested when executing on Ruby with default gem included" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

out = `#{ruby} -I#{lib_dir} -rsyntax_suggest -e "puts SyntaxError.instance_method(:detailed_message).source_location" 2>&1`

expect($?.success?).to be_truthy
expect(out).to include(lib_dir.join("syntax_suggest").join("core_ext.rb").to_s).once
end

it "annotates a syntax error in Ruby 3.2+ when require is not used" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

Dir.mktmpdir do |dir|
tmpdir = Pathname(dir)
script = tmpdir.join("script.rb")
Expand Down
10 changes: 0 additions & 10 deletions spec/unit/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@

module SyntaxSuggest
RSpec.describe "Top level SyntaxSuggest api" do
it "doesn't load prism if env var is set" do
skip("SYNTAX_SUGGEST_DISABLE_PRISM not set") unless ENV["SYNTAX_SUGGEST_DISABLE_PRISM"]

expect(SyntaxSuggest.use_prism_parser?).to be_falsey
end

it "has a `handle_error` interface" do
fake_error = Object.new
def fake_error.message
Expand Down Expand Up @@ -69,8 +63,6 @@ def fake_error.message
end

it "respects highlight API" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
require_relative core_ext_file

Expand All @@ -91,8 +83,6 @@ def detailed_message(**kwargs)
end

it "can be disabled via falsey kwarg" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

core_ext_file = lib_dir.join("syntax_suggest").join("core_ext.rb")
require_relative core_ext_file

Expand Down
2 changes: 0 additions & 2 deletions spec/unit/code_line_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ def to_json(*opts)
end

it "supports endless method definitions" do
skip("Unsupported ruby version") unless Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3")

line = CodeLine.from_source(<<~EOM).first
def square(x) = x * x
EOM
Expand Down
2 changes: 0 additions & 2 deletions spec/unit/core_ext_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
module SyntaxSuggest
RSpec.describe "Core extension" do
it "SyntaxError monkepatch ensures there is a newline to the end of the file" do
skip if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2")

Dir.mktmpdir do |dir|
tmpdir = Pathname(dir)
file = tmpdir.join("file.rb")
Expand Down
2 changes: 1 addition & 1 deletion syntax_suggest.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
spec.description = 'When you get an "unexpected end" in your syntax this gem helps you find it'
spec.homepage = "https://github.com/ruby/syntax_suggest.git"
spec.license = "MIT"
spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
spec.required_ruby_version = Gem::Requirement.new(">= 3.3.0")

spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://github.com/ruby/syntax_suggest.git"
Expand Down