Skip to content

Commit 4a1ac2f

Browse files
committed
Support Ruby 2.7.0
1 parent 1099498 commit 4a1ac2f

File tree

14 files changed

+96
-45
lines changed

14 files changed

+96
-45
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
fail-fast: false
99
matrix:
1010
ruby:
11-
- '2.7'
11+
- '2.7.0'
1212
- '3.0'
1313
- '3.1'
1414
- head

Rakefile

+13-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@ end
1212

1313
task default: :test
1414

15-
SOURCE_FILES =
16-
FileList[%w[Gemfile Rakefile syntax_tree.gemspec lib/**/*.rb test/*.rb]]
15+
configure = ->(task) do
16+
task.source_files =
17+
FileList[%w[Gemfile Rakefile syntax_tree.gemspec lib/**/*.rb test/*.rb]]
1718

18-
SyntaxTree::Rake::CheckTask.new { |t| t.source_files = SOURCE_FILES }
19-
SyntaxTree::Rake::WriteTask.new { |t| t.source_files = SOURCE_FILES }
19+
# Since Syntax Tree supports back to Ruby 2.7.0, we need to make sure that we
20+
# format our code such that it's compatible with that version. This actually
21+
# has very little effect on the output, the only change at the moment is that
22+
# Ruby < 2.7.3 didn't allow a newline before the closing brace of a hash
23+
# pattern.
24+
task.target_ruby_version = Gem::Version.new("2.7.0")
25+
end
26+
27+
SyntaxTree::Rake::CheckTask.new(&configure)
28+
SyntaxTree::Rake::WriteTask.new(&configure)

lib/syntax_tree/cli.rb

+22-13
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@ def source
5353
end
5454
end
5555

56-
# An item of work that corresponds to a script content passed via the command line.
56+
# An item of work that corresponds to a script content passed via the
57+
# command line.
5758
class ScriptItem
5859
FILEPATH = :script
5960

61+
attr_reader :source
62+
6063
def initialize(source)
6164
@source = source
6265
end
@@ -68,10 +71,6 @@ def handler
6871
def filepath
6972
FILEPATH
7073
end
71-
72-
def source
73-
@source
74-
end
7574
end
7675

7776
# The parent action class for the CLI that implements the basics.
@@ -197,7 +196,7 @@ def run(item)
197196

198197
source = item.source
199198
formatted = item.handler.format(source, options.print_width)
200-
File.write(filepath, formatted) if FileItem === item
199+
File.write(filepath, formatted) if item.filepath != :script
201200

202201
color = source == formatted ? Color.gray(filepath) : filepath
203202
delta = ((Time.now - start) * 1000).round
@@ -259,13 +258,19 @@ def run(item)
259258
# responsible for parsing the list and then returning the file paths at the
260259
# end.
261260
class Options
262-
attr_reader :print_width, :scripts
261+
attr_reader :plugins, :print_width, :scripts, :target_ruby_version
263262

264263
def initialize(print_width: DEFAULT_PRINT_WIDTH)
264+
@plugins = []
265265
@print_width = print_width
266266
@scripts = []
267+
@target_ruby_version = nil
267268
end
268269

270+
# TODO: This function causes a couple of side-effects that I really don't
271+
# like to have here. It mutates the global state by requiring the plugins,
272+
# and mutates the global options hash by adding the target ruby version.
273+
# That should be done on a config-by-config basis, not here.
269274
def parse(arguments)
270275
parser.parse!(arguments)
271276
end
@@ -285,7 +290,8 @@ def parser
285290
# require "syntax_tree/haml"
286291
#
287292
opts.on("--plugins=PLUGINS") do |plugins|
288-
plugins.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
293+
@plugins = plugins.split(",")
294+
@plugins.each { |plugin| require "syntax_tree/#{plugin}" }
289295
end
290296

291297
# If there is a print width specified on the command line, then
@@ -296,8 +302,13 @@ def parser
296302

297303
# If there is a script specified on the command line, then parse
298304
# it and add it to the list of scripts to run.
299-
opts.on("-e SCRIPT") do |script|
300-
@scripts << script
305+
opts.on("-e SCRIPT") { |script| @scripts << script }
306+
307+
# If there is a target ruby version specified on the command line,
308+
# parse that out and use it when formatting.
309+
opts.on("--target-ruby-version=VERSION") do |version|
310+
@target_ruby_version = Gem::Version.new(version)
311+
Formatter::OPTIONS[:target_ruby_version] = @target_ruby_version
301312
end
302313
end
303314
end
@@ -395,9 +406,7 @@ def run(argv)
395406
queue << FileItem.new(filepath) if File.file?(filepath)
396407
end
397408
end
398-
options.scripts.each do |script|
399-
queue << ScriptItem.new(script)
400-
end
409+
options.scripts.each { |script| queue << ScriptItem.new(script) }
401410
else
402411
queue << ScriptItem.new($stdin.read)
403412
end

lib/syntax_tree/formatter.rb

+9-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ class Formatter < PrettierPrint
1414
# Note that we're keeping this in a global-ish hash instead of just
1515
# overriding methods on classes so that other plugins can reference this if
1616
# necessary. For example, the RBS plugin references the quote style.
17-
OPTIONS = { quote: "\"", trailing_comma: false }
17+
OPTIONS = {
18+
quote: "\"",
19+
trailing_comma: false,
20+
target_ruby_version: Gem::Version.new(RUBY_VERSION)
21+
}
1822

1923
COMMENT_PRIORITY = 1
2024
HEREDOC_PRIORITY = 2
@@ -23,14 +27,15 @@ class Formatter < PrettierPrint
2327

2428
# These options are overridden in plugins to we need to make sure they are
2529
# available here.
26-
attr_reader :quote, :trailing_comma
30+
attr_reader :quote, :trailing_comma, :target_ruby_version
2731
alias trailing_comma? trailing_comma
2832

2933
def initialize(
3034
source,
3135
*args,
3236
quote: OPTIONS[:quote],
33-
trailing_comma: OPTIONS[:trailing_comma]
37+
trailing_comma: OPTIONS[:trailing_comma],
38+
target_ruby_version: OPTIONS[:target_ruby_version]
3439
)
3540
super(*args)
3641

@@ -40,6 +45,7 @@ def initialize(
4045
# Memoizing these values per formatter to make access faster.
4146
@quote = quote
4247
@trailing_comma = trailing_comma
48+
@target_ruby_version = target_ruby_version
4349
end
4450

4551
def self.format(source, node)

lib/syntax_tree/node.rb

+9-6
Original file line numberDiff line numberDiff line change
@@ -2132,8 +2132,7 @@ def format(q)
21322132
in [
21332133
Paren[
21342134
contents: {
2135-
body: [ArrayLiteral[contents: { parts: [_, _, *] }] => array]
2136-
}
2135+
body: [ArrayLiteral[contents: { parts: [_, _, *] }] => array] }
21372136
]
21382137
]
21392138
# Here we have a single argument that is a set of parentheses wrapping
@@ -5116,8 +5115,13 @@ def format(q)
51165115
q.breakable
51175116
contents.call
51185117
end
5119-
q.breakable
5120-
q.text("}")
5118+
5119+
if q.target_ruby_version < Gem::Version.new("2.7.3")
5120+
q.text(" }")
5121+
else
5122+
q.breakable
5123+
q.text("}")
5124+
end
51215125
end
51225126
end
51235127
end
@@ -5204,8 +5208,7 @@ def call(q, node)
52045208
false
52055209
in {
52065210
statements: { body: [truthy] },
5207-
consequent: Else[statements: { body: [falsy] }]
5208-
}
5211+
consequent: Else[statements: { body: [falsy] }] }
52095212
ternaryable?(truthy) && ternaryable?(falsy)
52105213
else
52115214
false

lib/syntax_tree/rake/check_task.rb

+12-1
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,22 @@ class CheckTask < ::Rake::TaskLib
3939
# Defaults to 80.
4040
attr_accessor :print_width
4141

42+
# The target Ruby version to use for formatting.
43+
# Defaults to Gem::Version.new(RUBY_VERSION).
44+
attr_accessor :target_ruby_version
45+
4246
def initialize(
4347
name = :"stree:check",
4448
source_files = ::Rake::FileList["lib/**/*.rb"],
4549
plugins = [],
46-
print_width = DEFAULT_PRINT_WIDTH
50+
print_width = DEFAULT_PRINT_WIDTH,
51+
target_ruby_version = Gem::Version.new(RUBY_VERSION)
4752
)
4853
@name = name
4954
@source_files = source_files
5055
@plugins = plugins
5156
@print_width = print_width
57+
@target_ruby_version = target_ruby_version
5258

5359
yield self if block_given?
5460
define_task
@@ -64,10 +70,15 @@ def define_task
6470
def run_task
6571
arguments = ["check"]
6672
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
73+
6774
if print_width != DEFAULT_PRINT_WIDTH
6875
arguments << "--print-width=#{print_width}"
6976
end
7077

78+
if target_ruby_version != Gem::Version.new(RUBY_VERSION)
79+
arguments << "--target-ruby-version=#{target_ruby_version}"
80+
end
81+
7182
SyntaxTree::CLI.run(arguments + Array(source_files))
7283
end
7384
end

lib/syntax_tree/rake/write_task.rb

+12-1
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,22 @@ class WriteTask < ::Rake::TaskLib
3939
# Defaults to 80.
4040
attr_accessor :print_width
4141

42+
# The target Ruby version to use for formatting.
43+
# Defaults to Gem::Version.new(RUBY_VERSION).
44+
attr_accessor :target_ruby_version
45+
4246
def initialize(
4347
name = :"stree:write",
4448
source_files = ::Rake::FileList["lib/**/*.rb"],
4549
plugins = [],
46-
print_width = DEFAULT_PRINT_WIDTH
50+
print_width = DEFAULT_PRINT_WIDTH,
51+
target_ruby_version = Gem::Version.new(RUBY_VERSION)
4752
)
4853
@name = name
4954
@source_files = source_files
5055
@plugins = plugins
5156
@print_width = print_width
57+
@target_ruby_version = target_ruby_version
5258

5359
yield self if block_given?
5460
define_task
@@ -64,10 +70,15 @@ def define_task
6470
def run_task
6571
arguments = ["write"]
6672
arguments << "--plugins=#{plugins.join(",")}" if plugins.any?
73+
6774
if print_width != DEFAULT_PRINT_WIDTH
6875
arguments << "--print-width=#{print_width}"
6976
end
7077

78+
if target_ruby_version != Gem::Version.new(RUBY_VERSION)
79+
arguments << "--target-ruby-version=#{target_ruby_version}"
80+
end
81+
7182
SyntaxTree::CLI.run(arguments + Array(source_files))
7283
end
7384
end

syntax_tree.gemspec

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
1919
.reject { |f| f.match(%r{^(test|spec|features)/}) }
2020
end
2121

22-
spec.required_ruby_version = ">= 2.7.3"
22+
spec.required_ruby_version = ">= 2.7.0"
2323

2424
spec.bindir = "exe"
2525
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }

test/cli_test.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,12 @@ def test_no_arguments_no_tty
134134
end
135135

136136
def test_inline_script
137-
stdio, = capture_io { SyntaxTree::CLI.run(["format", "-e", "1+1"]) }
137+
stdio, = capture_io { SyntaxTree::CLI.run(%w[format -e 1+1]) }
138138
assert_equal("1 + 1\n", stdio)
139139
end
140140

141141
def test_multiple_inline_scripts
142-
stdio, = capture_io { SyntaxTree::CLI.run(["format", "-e", "1+1", "-e", "2+2"]) }
142+
stdio, = capture_io { SyntaxTree::CLI.run(%w[format -e 1+1 -e 2+2]) }
143143
assert_equal("1 + 1\n2 + 2\n", stdio)
144144
end
145145

test/fixtures/args_forward.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
%
1+
% # >= 2.7.3
22
def foo(...)
33
bar(:baz, ...)
44
end

test/fixtures/hshptn.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
case foo
3131
in **bar
3232
end
33-
%
33+
% # >= 2.7.3
3434
case foo
3535
in {
3636
foo:, # comment1

test/fixtures/params.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def foo(*)
1616
%
1717
def foo(*rest)
1818
end
19-
%
19+
% # >= 2.7.3
2020
def foo(...)
2121
end
2222
%

test/node_test.rb

+11-9
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,18 @@ def test_arg_star
104104
end
105105
end
106106

107-
def test_args_forward
108-
source = <<~SOURCE
109-
def get(...)
110-
request(:GET, ...)
111-
end
112-
SOURCE
107+
guard_version("2.7.3") do
108+
def test_args_forward
109+
source = <<~SOURCE
110+
def get(...)
111+
request(:GET, ...)
112+
end
113+
SOURCE
113114

114-
at = location(lines: 2..2, chars: 29..32)
115-
assert_node(ArgsForward, source, at: at) do |node|
116-
node.bodystmt.statements.body.first.arguments.arguments.parts.last
115+
at = location(lines: 2..2, chars: 29..32)
116+
assert_node(ArgsForward, source, at: at) do |node|
117+
node.bodystmt.statements.body.first.arguments.arguments.parts.last
118+
end
117119
end
118120
end
119121

test/test_helper.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def initialize
2626
@called = nil
2727
end
2828

29-
def method_missing(called, ...)
29+
def method_missing(called, *, **)
3030
@called = called
3131
end
3232
end

0 commit comments

Comments
 (0)