Skip to content

Commit 363ccf5

Browse files
authored
Merge pull request #246 from Earlopain/raise-required-ruby-version
Raise required ruby version to Ruby 3.3
2 parents 3173de6 + c6bd4b5 commit 363ccf5

15 files changed

Lines changed: 62 additions & 248 deletions

.github/workflows/ci.yml

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
2525
with:
2626
engine: cruby
27+
min_version: 3.3
2728

2829
test:
2930
needs: ruby-versions
@@ -33,7 +34,9 @@ jobs:
3334
matrix:
3435
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
3536
prism_version:
36-
- 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/
37+
# See https://stdgems.org/prism for which ruby version shipped with which prism version
38+
- 0.19.0
39+
- 1.2.0
3740
- 1.8.0
3841
- head
3942
env:
@@ -52,22 +55,3 @@ jobs:
5255
- name: test
5356
run: bin/rake test
5457
continue-on-error: ${{ matrix.ruby == 'head' }}
55-
56-
test-disable-prism:
57-
needs: ruby-versions
58-
runs-on: ubuntu-latest
59-
strategy:
60-
fail-fast: false
61-
matrix:
62-
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
63-
steps:
64-
- name: Checkout code
65-
uses: actions/checkout@v6
66-
- name: Set up Ruby
67-
uses: ruby/setup-ruby@v1
68-
with:
69-
ruby-version: ${{ matrix.ruby }}
70-
bundler-cache: true
71-
- name: test
72-
run: SYNTAX_SUGGEST_DISABLE_PRISM=1 bin/rake test
73-
continue-on-error: ${{ matrix.ruby == 'head' }}

.standard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
ruby_version: 3.0.0
1+
ruby_version: 3.3.0

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## HEAD (unreleased)
22

3+
- Changed: Changed: Minimum supported Ruby version is now 3.3. (https://github.com/ruby/syntax_suggest/pull/246)
4+
35
## 2.0.3
46

57
- Fix: Correctly identify trailing slashes when using Prism > 1.8.0. (https://github.com/ruby/syntax_suggest/pull/243)

lib/syntax_suggest/api.rb

Lines changed: 6 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,12 @@
77
require "pathname"
88
require "timeout"
99

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

14-
# Prism is the new parser, replacing Ripper
15-
#
16-
# We need to "dual boot" both for now because syntax_suggest
17-
# supports older rubies that do not ship with syntax suggest.
18-
#
19-
# We also need the ability to control loading of this library
20-
# so we can test that both modes work correctly in CI.
21-
if (value = ENV["SYNTAX_SUGGEST_DISABLE_PRISM"])
22-
warn "Skipping loading prism due to SYNTAX_SUGGEST_DISABLE_PRISM=#{value}"
23-
else
24-
begin
25-
require "prism"
26-
rescue LoadError
27-
end
28-
end
29-
3016
module SyntaxSuggest
3117
# Used to indicate a default value that cannot
3218
# be confused with another input.
@@ -35,14 +21,6 @@ module SyntaxSuggest
3521
class Error < StandardError; end
3622
TIMEOUT_DEFAULT = ENV.fetch("SYNTAX_SUGGEST_TIMEOUT", 1).to_i
3723

38-
# SyntaxSuggest.use_prism_parser? [Private]
39-
#
40-
# Tells us if the prism parser is available for use
41-
# or if we should fallback to `Ripper`
42-
def self.use_prism_parser?
43-
defined?(Prism)
44-
end
45-
4624
# SyntaxSuggest.handle_error [Public]
4725
#
4826
# Takes a `SyntaxError` exception, uses the
@@ -152,20 +130,11 @@ def self.valid_without?(without_lines:, code_lines:)
152130
# SyntaxSuggest.invalid? [Private]
153131
#
154132
# Opposite of `SyntaxSuggest.valid?`
155-
if defined?(Prism)
156-
def self.invalid?(source)
157-
source = source.join if source.is_a?(Array)
158-
source = source.to_s
133+
def self.invalid?(source)
134+
source = source.join if source.is_a?(Array)
135+
source = source.to_s
159136

160-
Prism.parse(source).failure?
161-
end
162-
else
163-
def self.invalid?(source)
164-
source = source.join if source.is_a?(Array)
165-
source = source.to_s
166-
167-
Ripper.new(source).tap(&:parse).error?
168-
end
137+
Prism.parse(source).failure?
169138
end
170139

171140
# SyntaxSuggest.valid? [Private]

lib/syntax_suggest/clean_document.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ module SyntaxSuggest
8686
class CleanDocument
8787
def initialize(source:)
8888
lines = clean_sweep(source: source)
89-
@document = CodeLine.from_source(lines.join, lines: lines)
89+
@document = CodeLine.from_source(lines.join)
9090
end
9191

9292
# Call all of the document "cleaners"

lib/syntax_suggest/code_line.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ class CodeLine
2626

2727
# Returns an array of CodeLine objects
2828
# from the source string
29-
def self.from_source(source, lines: nil)
30-
lines ||= source.lines
31-
lex_array_for_line = LexAll.new(source: source, source_lines: lines).each_with_object(Hash.new { |h, k| h[k] = [] }) { |lex, hash| hash[lex.line] << lex }
32-
lines.map.with_index do |line, index|
29+
def self.from_source(source)
30+
lex_array_for_line = LexAll.new(source: source).each_with_object(Hash.new { |h, k| h[k] = [] }) { |lex, hash| hash[lex.line] << lex }
31+
source.lines.map.with_index do |line, index|
3332
CodeLine.new(
3433
line: line,
3534
index: index,

lib/syntax_suggest/core_ext.rb

Lines changed: 39 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,47 @@
11
# frozen_string_literal: true
22

3-
# Ruby 3.2+ has a cleaner way to hook into Ruby that doesn't use `require`
4-
if SyntaxError.method_defined?(:detailed_message)
5-
module SyntaxSuggest
6-
# SyntaxSuggest.module_for_detailed_message [Private]
7-
#
8-
# Used to monkeypatch SyntaxError via Module.prepend
9-
def self.module_for_detailed_message
10-
Module.new {
11-
def detailed_message(highlight: true, syntax_suggest: true, **kwargs)
12-
return super unless syntax_suggest
13-
14-
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
15-
16-
message = super
17-
18-
if path
19-
file = Pathname.new(path)
20-
io = SyntaxSuggest::MiniStringIO.new
21-
22-
SyntaxSuggest.call(
23-
io: io,
24-
source: file.read,
25-
filename: file,
26-
terminal: highlight
27-
)
28-
annotation = io.string
29-
30-
annotation += "\n" unless annotation.end_with?("\n")
31-
32-
annotation + message
33-
else
34-
message
35-
end
36-
rescue => e
37-
if ENV["SYNTAX_SUGGEST_DEBUG"]
38-
$stderr.warn(e.message)
39-
$stderr.warn(e.backtrace)
40-
end
41-
42-
# Ignore internal errors
3+
module SyntaxSuggest
4+
# SyntaxSuggest.module_for_detailed_message [Private]
5+
#
6+
# Used to monkeypatch SyntaxError via Module.prepend
7+
def self.module_for_detailed_message
8+
Module.new {
9+
def detailed_message(highlight: true, syntax_suggest: true, **kwargs)
10+
return super unless syntax_suggest
11+
12+
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
13+
14+
message = super
15+
16+
if path
17+
file = Pathname.new(path)
18+
io = SyntaxSuggest::MiniStringIO.new
19+
20+
SyntaxSuggest.call(
21+
io: io,
22+
source: file.read,
23+
filename: file,
24+
terminal: highlight
25+
)
26+
annotation = io.string
27+
28+
annotation += "\n" unless annotation.end_with?("\n")
29+
30+
annotation + message
31+
else
4332
message
4433
end
45-
}
46-
end
47-
end
48-
49-
SyntaxError.prepend(SyntaxSuggest.module_for_detailed_message)
50-
else
51-
autoload :Pathname, "pathname"
52-
53-
#--
54-
# Monkey patch kernel to ensure that all `require` calls call the same
55-
# method
56-
#++
57-
module Kernel
58-
# :stopdoc:
59-
60-
module_function
61-
62-
alias_method :syntax_suggest_original_require, :require
63-
alias_method :syntax_suggest_original_require_relative, :require_relative
64-
alias_method :syntax_suggest_original_load, :load
65-
66-
def load(file, wrap = false)
67-
syntax_suggest_original_load(file)
68-
rescue SyntaxError => e
69-
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
70-
71-
SyntaxSuggest.handle_error(e)
72-
end
73-
74-
def require(file)
75-
syntax_suggest_original_require(file)
76-
rescue SyntaxError => e
77-
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
78-
79-
SyntaxSuggest.handle_error(e)
80-
end
34+
rescue => e
35+
if ENV["SYNTAX_SUGGEST_DEBUG"]
36+
$stderr.warn(e.message)
37+
$stderr.warn(e.backtrace)
38+
end
8139

82-
def require_relative(file)
83-
if Pathname.new(file).absolute?
84-
syntax_suggest_original_require file
85-
else
86-
relative_from = caller_locations(1..1).first
87-
relative_from_path = relative_from.absolute_path || relative_from.path
88-
syntax_suggest_original_require File.expand_path("../#{file}", relative_from_path)
40+
# Ignore internal errors
41+
message
8942
end
90-
rescue SyntaxError => e
91-
require "syntax_suggest/api" unless defined?(SyntaxSuggest::DEFAULT_VALUE)
92-
93-
SyntaxSuggest.handle_error(e)
94-
end
43+
}
9544
end
9645
end
46+
47+
SyntaxError.prepend(SyntaxSuggest.module_for_detailed_message)

lib/syntax_suggest/explain_syntax.rb

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,10 @@
22

33
require_relative "left_right_lex_count"
44

5-
if !SyntaxSuggest.use_prism_parser?
6-
require_relative "ripper_errors"
7-
end
8-
95
module SyntaxSuggest
106
class GetParseErrors
117
def self.errors(source)
12-
if SyntaxSuggest.use_prism_parser?
13-
Prism.parse(source).errors.map(&:message)
14-
else
15-
RipperErrors.new(source).call.errors
16-
end
8+
Prism.parse(source).errors.map(&:message)
179
end
1810
end
1911

lib/syntax_suggest/lex_all.rb

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,7 @@
11
# frozen_string_literal: true
22

33
module SyntaxSuggest
4-
# Ripper.lex is not guaranteed to lex the entire source document
5-
#
6-
# This class guarantees the whole document is lex-ed by iteratively
7-
# lexing the document where ripper stopped.
8-
#
9-
# Prism likely doesn't have the same problem. Once ripper support is removed
10-
# we can likely reduce the complexity here if not remove the whole concept.
4+
# Lexes the whole source and wraps the tokens in `LexValue`.
115
#
126
# Example usage:
137
#
@@ -18,36 +12,16 @@ module SyntaxSuggest
1812
class LexAll
1913
include Enumerable
2014

21-
def initialize(source:, source_lines: nil)
15+
def initialize(source:)
2216
@lex = self.class.lex(source, 1)
23-
lineno = @lex.last[0][0] + 1
24-
source_lines ||= source.lines
25-
last_lineno = source_lines.length
26-
27-
until lineno >= last_lineno
28-
lines = source_lines[lineno..]
29-
30-
@lex.concat(
31-
self.class.lex(lines.join, lineno + 1)
32-
)
33-
34-
lineno = @lex.last[0].first + 1
35-
end
36-
3717
last_lex = nil
3818
@lex.map! { |elem|
3919
last_lex = LexValue.new(elem[0].first, elem[1], elem[2], elem[3], last_lex)
4020
}
4121
end
4222

43-
if SyntaxSuggest.use_prism_parser?
44-
def self.lex(source, line_number)
45-
Prism.lex_compat(source, line: line_number).value.sort_by { |values| values[0] }
46-
end
47-
else
48-
def self.lex(source, line_number)
49-
Ripper::Lexer.new(source, "-", line_number).parse.sort_by(&:pos)
50-
end
23+
def self.lex(source, line_number)
24+
Prism.lex_compat(source, line: line_number).value.sort_by { |values| values[0] }
5125
end
5226

5327
def to_a

lib/syntax_suggest/ripper_errors.rb

Lines changed: 0 additions & 39 deletions
This file was deleted.

0 commit comments

Comments
 (0)