Skip to content
Merged
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
10 changes: 9 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ on:
- pull_request_target
jobs:
ci:
strategy:
fail-fast: false
matrix:
ruby:
- '2.7'
- '3.0'
- '3.1'
- head
name: CI
runs-on: ubuntu-latest
env:
Expand All @@ -13,7 +21,7 @@ jobs:
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
ruby-version: '3.1'
ruby-version: ${{ matrix.ruby }}
- name: Test
run: bundle exec rake test
automerge:
Expand Down
1 change: 1 addition & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ GEM

PLATFORMS
arm64-darwin-21
ruby
x86_64-darwin-19
x86_64-darwin-21
x86_64-linux
Expand Down
50 changes: 37 additions & 13 deletions lib/syntax_tree/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,9 @@ class BodyStmt < Node
# [nil | Rescue] the optional rescue chain attached to the begin clause
attr_reader :rescue_clause

# [nil | Kw] the optional else keyword
attr_reader :else_keyword

# [nil | Statements] the optional set of statements inside the else clause
attr_reader :else_clause

Expand All @@ -2245,13 +2248,15 @@ class BodyStmt < Node
def initialize(
statements:,
rescue_clause:,
else_keyword:,
else_clause:,
ensure_clause:,
location:,
comments: []
)
@statements = statements
@rescue_clause = rescue_clause
@else_keyword = else_keyword
@else_clause = else_clause
@ensure_clause = ensure_clause
@location = location
Expand Down Expand Up @@ -2294,7 +2299,7 @@ def accept(visitor)
end

def child_nodes
[statements, rescue_clause, else_clause, ensure_clause]
[statements, rescue_clause, else_keyword, else_clause, ensure_clause]
end

alias deconstruct child_nodes
Expand Down Expand Up @@ -2324,10 +2329,13 @@ def format(q)
if else_clause
q.nest(-2) do
q.breakable(force: true)
q.text("else")
q.format(else_keyword)
end

unless else_clause.empty?
q.breakable(force: true)
q.format(else_clause)
end
q.breakable(force: true)
q.format(else_clause)
end

if ensure_clause
Expand Down Expand Up @@ -3295,9 +3303,10 @@ def to_json(*opts)
private

def align?(node)
if node.arguments in Args[parts: [Def | Defs | DefEndless]]
case node.arguments
in Args[parts: [Def | Defs | DefEndless]]
false
elsif node.arguments in Args[parts: [Command => command]]
in Args[parts: [Command => command]]
align?(command)
else
true
Expand Down Expand Up @@ -4710,13 +4719,17 @@ def quotes(q)
# end
#
class Else < Node
# [Kw] the else keyword
attr_reader :keyword

# [Statements] the expressions to be executed
attr_reader :statements

# [Array[ Comment | EmbDoc ]] the comments attached to this node
attr_reader :comments

def initialize(statements:, location:, comments: [])
def initialize(keyword:, statements:, location:, comments: [])
@keyword = keyword
@statements = statements
@location = location
@comments = comments
Expand All @@ -4727,18 +4740,23 @@ def accept(visitor)
end

def child_nodes
[statements]
[keyword, statements]
end

alias deconstruct child_nodes

def deconstruct_keys(keys)
{ statements: statements, location: location, comments: comments }
{
keyword: keyword,
statements: statements,
location: location,
comments: comments
}
end

def format(q)
q.group do
q.text("else")
q.format(keyword)

unless statements.empty?
q.indent do
Expand Down Expand Up @@ -8992,6 +9010,9 @@ def to_json(*opts)
# end
#
class Rescue < Node
# [Kw] the rescue keyword
attr_reader :keyword

# [RescueEx] the exceptions being rescued
attr_reader :exception

Expand All @@ -9005,12 +9026,14 @@ class Rescue < Node
attr_reader :comments

def initialize(
keyword:,
exception:,
statements:,
consequent:,
location:,
comments: []
)
@keyword = keyword
@exception = exception
@statements = statements
@consequent = consequent
Expand Down Expand Up @@ -9040,13 +9063,14 @@ def accept(visitor)
end

def child_nodes
[exception, statements, consequent]
[keyword, exception, statements, consequent]
end

alias deconstruct child_nodes

def deconstruct_keys(keys)
{
keyword: keyword,
exception: exception,
statements: statements,
consequent: consequent,
Expand All @@ -9057,10 +9081,10 @@ def deconstruct_keys(keys)

def format(q)
q.group do
q.text("rescue")
q.format(keyword)

if exception
q.nest("rescue ".length) { q.format(exception) }
q.nest(keyword.value.length + 1) { q.format(exception) }
else
q.text(" StandardError")
end
Expand Down
13 changes: 9 additions & 4 deletions lib/syntax_tree/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,7 @@ def on_bodystmt(statements, rescue_clause, else_clause, ensure_clause)
BodyStmt.new(
statements: statements,
rescue_clause: rescue_clause,
else_keyword: else_clause && find_token(Kw, "else"),
else_clause: else_clause,
ensure_clause: ensure_clause,
location: Location.fixed(line: lineno, char: char_pos)
Expand Down Expand Up @@ -1115,7 +1116,7 @@ def on_dyna_symbol(string_content)
# :call-seq:
# on_else: (Statements statements) -> Else
def on_else(statements)
beginning = find_token(Kw, "else")
keyword = find_token(Kw, "else")

# else can either end with an end keyword (in which case we'll want to
# consume that event) or it can end with an ensure keyword (in which case
Expand All @@ -1127,13 +1128,16 @@ def on_else(statements)

node = tokens[index]
ending = node.value == "end" ? tokens.delete_at(index) : node
# ending = node

statements.bind(beginning.location.end_char, ending.location.start_char)
statements.bind(
find_next_statement_start(keyword.location.end_char),
ending.location.start_char
)

Else.new(
keyword: keyword,
statements: statements,
location: beginning.location.to(ending.location)
location: keyword.location.to(ending.location)
)
end

Expand Down Expand Up @@ -2316,6 +2320,7 @@ def on_rescue(exceptions, variable, statements, consequent)
end

Rescue.new(
keyword: keyword,
exception: rescue_ex,
statements: statements,
consequent: consequent,
Expand Down
4 changes: 0 additions & 4 deletions test/fixtures/begin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,3 @@
begin
expression
end
%
case value
in ^(expression)
end
20 changes: 20 additions & 0 deletions test/fixtures/bodystmt.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,23 @@
ensure
foo
end
%
begin
else # else
end
%
begin
ensure # ensure
end
%
begin
rescue # rescue
else # else
ensure # ensure
end
-
begin
rescue StandardError # rescue
else # else
ensure # ensure
end
6 changes: 0 additions & 6 deletions test/fixtures/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,3 @@
%
meta3 meta2 meta1 def self.foo
end
%
meta1 def foo = 1
%
meta2 meta1 def foo = 1
%
meta3 meta2 meta1 def foo = 1
6 changes: 6 additions & 0 deletions test/fixtures/command_def_endless.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
%
meta1 def foo = 1
%
meta2 meta1 def foo = 1
%
meta3 meta2 meta1 def foo = 1
4 changes: 4 additions & 0 deletions test/fixtures/else.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@
else
bar
end
%
if foo
else # bar
end
4 changes: 4 additions & 0 deletions test/fixtures/pinned_begin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
%
case value
in ^(expression)
end
10 changes: 0 additions & 10 deletions test/fixtures/var_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,3 @@
foo = bar
%
@foo = bar
%
foo in bar
%
foo in ^bar
%
foo in ^@bar
%
foo in ^@@bar
%
foo in ^$gvar
10 changes: 10 additions & 0 deletions test/fixtures/var_field_rassign.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
%
foo in bar
%
foo in ^bar
%
foo in ^@bar
%
foo in ^@@bar
%
foo in ^$gvar
27 changes: 21 additions & 6 deletions test/formatting_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,28 @@

module SyntaxTree
class FormattingTest < Minitest::Test
delimiter = /%(?: # (.+?))?\n/
FIXTURES_3_0_0 = %w[
command_def_endless
def_endless
fndptn
rassign
rassign_rocket
]

FIXTURES_3_1_0 = %w[
pinned_begin
var_field_rassign
]

Dir[File.join(__dir__, "fixtures", "*.rb")].each do |filepath|
basename = File.basename(filepath, ".rb")
sources = File.readlines(filepath).slice_before(delimiter)
fixtures = Dir[File.join(__dir__, "fixtures", "*.rb")].map { |filepath| File.basename(filepath, ".rb") }
fixtures -= FIXTURES_3_1_0 if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.1.0")
fixtures -= FIXTURES_3_0_0 if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.0.0")

delimiter = /%(?: # (.+?))?\n/
fixtures.each do |fixture|
filepath = File.join(__dir__, "fixtures", "#{fixture}.rb")

sources.each_with_index do |source, index|
File.readlines(filepath).slice_before(delimiter).each_with_index do |source, index|
comment = source.shift.match(delimiter)[1]
original, expected = source.join.split("-\n")

Expand All @@ -22,7 +37,7 @@ class FormattingTest < Minitest::Test
next if Gem::Version.new(RUBY_VERSION) < version
end

define_method(:"test_formatting_#{basename}_#{index}") do
define_method(:"test_formatting_#{fixture}_#{index}") do
assert_equal(expected || original, SyntaxTree.format(original))
end
end
Expand Down
Loading