Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 840ebab

Browse files
committed
Even more performance tweaks
1 parent ed0c475 commit 840ebab

File tree

4 files changed

+187
-144
lines changed

4 files changed

+187
-144
lines changed

lib/syntax_tree.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@
2020

2121
require_relative "syntax_tree/parser"
2222

23+
# We rely on Symbol#name being available, which is only available in Ruby 3.0+.
24+
# In case we're running on an older Ruby version, we polyfill it here.
25+
unless :+.respond_to?(:name)
26+
class Symbol
27+
def name
28+
to_s.freeze
29+
end
30+
end
31+
end
32+
2333
# Syntax Tree is a suite of tools built on top of the internal CRuby parser. It
2434
# provides the ability to generate a syntax tree from source, as well as the
2535
# tools necessary to inspect and manipulate that syntax tree. It can be used to

lib/syntax_tree/node.rb

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -606,12 +606,14 @@ def format(q)
606606
private
607607

608608
def trailing_comma?
609-
case arguments
610-
in Args[parts: [*, ArgBlock]]
609+
return false unless arguments.is_a?(Args)
610+
parts = arguments.parts
611+
612+
if parts.last&.is_a?(ArgBlock)
611613
# If the last argument is a block, then we can't put a trailing comma
612614
# after it without resulting in a syntax error.
613615
false
614-
in Args[parts: [Command | CommandCall]]
616+
elsif parts.length == 1 && (part = parts.first) && (part.is_a?(Command) || part.is_a?(CommandCall))
615617
# If the only argument is a command or command call, then a trailing
616618
# comma would be parsed as part of that expression instead of on this
617619
# one, so we don't want to add a trailing comma.
@@ -1668,13 +1670,11 @@ def format(q)
16681670
q.text(" ") unless power
16691671

16701672
if operator == :<<
1671-
q.text(operator.to_s)
1672-
q.text(" ")
1673+
q.text("<< ")
16731674
q.format(right)
16741675
else
16751676
q.group do
1676-
q.text(operator.to_s)
1677-
1677+
q.text(operator.name)
16781678
q.indent do
16791679
power ? q.breakable_empty : q.breakable_space
16801680
q.format(right)
@@ -1974,12 +1974,11 @@ def format(q)
19741974
# If the receiver of this block a Command or CommandCall node, then there
19751975
# are no parentheses around the arguments to that command, so we need to
19761976
# break the block.
1977-
case q.parent
1978-
in { call: Command | CommandCall }
1977+
case q.parent.call
1978+
when Command, CommandCall
19791979
q.break_parent
19801980
format_break(q, break_opening, break_closing)
19811981
return
1982-
else
19831982
end
19841983

19851984
q.group do
@@ -1999,9 +1998,9 @@ def unchangeable_bounds?(q)
19991998
# know for certain we're going to get split over multiple lines
20001999
# anyway.
20012000
case parent
2002-
in Statements | ArgParen
2001+
when Statements, ArgParen
20032002
break false
2004-
in Command | CommandCall
2003+
when Command, CommandCall
20052004
true
20062005
else
20072006
false
@@ -2012,8 +2011,8 @@ def unchangeable_bounds?(q)
20122011
# If we're a sibling of a control-flow keyword, then we're going to have to
20132012
# use the do..end bounds.
20142013
def forced_do_end_bounds?(q)
2015-
case q.parent
2016-
in { call: Break | Next | Return | Super }
2014+
case q.parent.call
2015+
when Break, Next, Return, Super
20172016
true
20182017
else
20192018
false
@@ -2997,15 +2996,31 @@ def format(q)
29972996
private
29982997

29992998
def align(q, node, &block)
3000-
case node.arguments
3001-
in Args[parts: [Def | Defs | DefEndless]]
3002-
q.text(" ")
3003-
yield
3004-
in Args[parts: [IfOp]]
3005-
q.if_flat { q.text(" ") }
3006-
yield
3007-
in Args[parts: [Command => command]]
3008-
align(q, command, &block)
2999+
arguments = node.arguments
3000+
3001+
if arguments.is_a?(Args)
3002+
parts = arguments.parts
3003+
3004+
if parts.size == 1
3005+
part = parts.first
3006+
3007+
case part
3008+
when Def, Defs, DefEndless
3009+
q.text(" ")
3010+
yield
3011+
when IfOp
3012+
q.if_flat { q.text(" ") }
3013+
yield
3014+
when Command
3015+
align(q, part, &block)
3016+
else
3017+
q.text(" ")
3018+
q.nest(message.value.length + 1) { yield }
3019+
end
3020+
else
3021+
q.text(" ")
3022+
q.nest(message.value.length + 1) { yield }
3023+
end
30093024
else
30103025
q.text(" ")
30113026
q.nest(message.value.length + 1) { yield }
@@ -3092,13 +3107,16 @@ def format(q)
30923107
end
30933108
end
30943109

3095-
case arguments
3096-
in Args[parts: [IfOp]]
3097-
q.if_flat { q.text(" ") }
3098-
q.format(arguments)
3099-
in Args
3100-
q.text(" ")
3101-
q.nest(argument_alignment(q, doc)) { q.format(arguments) }
3110+
if arguments
3111+
parts = arguments.parts
3112+
3113+
if parts.length == 1 && parts.first.is_a?(IfOp)
3114+
q.if_flat { q.text(" ") }
3115+
q.format(arguments)
3116+
else
3117+
q.text(" ")
3118+
q.nest(argument_alignment(q, doc)) { q.format(arguments) }
3119+
end
31023120
else
31033121
# If there are no arguments, print nothing.
31043122
end
@@ -5861,11 +5879,15 @@ class Kw < Node
58615879
# [String] the value of the keyword
58625880
attr_reader :value
58635881

5882+
# [Symbol] the symbol version of the value
5883+
attr_reader :name
5884+
58645885
# [Array[ Comment | EmbDoc ]] the comments attached to this node
58655886
attr_reader :comments
58665887

58675888
def initialize(value:, location:, comments: [])
58685889
@value = value
5890+
@name = value.to_sym
58695891
@location = location
58705892
@comments = comments
58715893
end
@@ -6645,11 +6667,15 @@ class Op < Node
66456667
# [String] the operator
66466668
attr_reader :value
66476669

6670+
# [Symbol] the symbol version of the value
6671+
attr_reader :name
6672+
66486673
# [Array[ Comment | EmbDoc ]] the comments attached to this node
66496674
attr_reader :comments
66506675

66516676
def initialize(value:, location:, comments: [])
66526677
@value = value
6678+
@name = value.to_sym
66536679
@location = location
66546680
@comments = comments
66556681
end

0 commit comments

Comments
 (0)