Skip to content

Use prettier_print #78

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 14, 2022
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
2 changes: 0 additions & 2 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
source "https://rubygems.org"

gemspec

gem "rubocop"
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ PATH
remote: .
specs:
syntax_tree (2.4.1)
prettier_print

GEM
remote: https://rubygems.org/
Expand All @@ -12,6 +13,7 @@ GEM
parallel (1.22.1)
parser (3.1.2.0)
ast (~> 2.4.1)
prettier_print (0.1.0)
rainbow (3.1.1)
rake (13.0.6)
regexp_parser (2.4.0)
Expand Down
26 changes: 1 addition & 25 deletions lib/syntax_tree.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

require "json"
require "pp"
require "prettyprint"
require "prettier_print"
require "ripper"
require "stringio"

Expand All @@ -16,30 +16,6 @@
require_relative "syntax_tree/visitor/match_visitor"
require_relative "syntax_tree/visitor/pretty_print_visitor"

# If PrettyPrint::Align isn't defined, then we haven't gotten the updated
# version of prettyprint. In that case we'll define our own. This is going to
# overwrite a bunch of methods, so silencing them as well.
unless PrettyPrint.const_defined?(:Align)
verbose = $VERBOSE
$VERBOSE = nil

begin
require_relative "syntax_tree/prettyprint"
ensure
$VERBOSE = verbose
end
end

# When PP is running, it expects that everything that interacts with it is going
# to flow through PP.pp, since that's the main entry into the module from the
# perspective of its uses in core Ruby. In doing so, it calls guard_inspect_key
# at the top of the PP.pp method, which establishes some thread-local hashes to
# check for cycles in the pretty printed tree. This means that if you want to
# manually call pp on some object _before_ you have established these hashes,
# you're going to break everything. So this call ensures that those hashes have
# been set up before anything uses pp manually.
PP.new(+"", 0).guard_inspect_key {}

# Syntax Tree is a suite of tools built on top of the internal CRuby parser. It
# provides the ability to generate a syntax tree from source, as well as the
# tools necessary to inspect and manipulate that syntax tree. It can be used to
Expand Down
2 changes: 1 addition & 1 deletion lib/syntax_tree/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module SyntaxTree
# A slightly enhanced PP that knows how to format recursively including
# comments.
class Formatter < PP
class Formatter < PrettierPrint
COMMENT_PRIORITY = 1
HEREDOC_PRIORITY = 2

Expand Down
100 changes: 9 additions & 91 deletions lib/syntax_tree/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def to_json(*opts)
end

def construct_keys
PP.format(+"") { |q| Visitor::MatchVisitor.new(q).visit(self) }
PrettierPrint.format(+"") { |q| Visitor::MatchVisitor.new(q).visit(self) }
end
end

Expand Down Expand Up @@ -1666,52 +1666,6 @@ def format(q)
end
end

# This module will remove any breakables from the list of contents so that no
# newlines are present in the output.
module RemoveBreaks
class << self
def call(doc)
marker = Object.new
stack = [doc]

while stack.any?
doc = stack.pop

if doc == marker
stack.pop
next
end

stack += [doc, marker]

case doc
when PrettyPrint::Align, PrettyPrint::Indent, PrettyPrint::Group
doc.contents.map! { |child| remove_breaks(child) }
stack += doc.contents.reverse
when PrettyPrint::IfBreak
doc.flat_contents.map! { |child| remove_breaks(child) }
stack += doc.flat_contents.reverse
end
end
end

private

def remove_breaks(doc)
case doc
when PrettyPrint::Breakable
text = PrettyPrint::Text.new
text.add(object: doc.force? ? "; " : doc.separator, width: doc.width)
text
when PrettyPrint::IfBreak
PrettyPrint::Align.new(indent: 0, contents: doc.flat_contents)
else
doc
end
end
end
end

# BlockVar represents the parameters being declared for a block. Effectively
# this node is everything contained within the pipes. This includes all of the
# various parameter types, as well as block-local variable declarations.
Expand Down Expand Up @@ -1752,8 +1706,7 @@ def deconstruct_keys(_keys)

def format(q)
q.group(0, "|", "|") do
doc = q.format(params)
RemoveBreaks.call(doc)
q.remove_breaks(q.format(params))

if locals.any?
q.text("; ")
Expand Down Expand Up @@ -3096,31 +3049,6 @@ def format(q)

private

# This is a somewhat naive method that is attempting to sum up the width of
# the doc nodes that make up the given doc node. This is used to align
# content.
def doc_width(parent)
queue = [parent]
width = 0

until queue.empty?
doc = queue.shift

case doc
when PrettyPrint::Text
width += doc.width
when PrettyPrint::Indent, PrettyPrint::Align, PrettyPrint::Group
queue = doc.contents + queue
when PrettyPrint::IfBreak
queue = doc.break_contents + queue
when PrettyPrint::Breakable
width = 0
end
end

width
end

def argument_alignment(q, doc)
# Very special handling case for rspec matchers. In general with rspec
# matchers you expect to see something like:
Expand All @@ -3138,7 +3066,7 @@ def argument_alignment(q, doc)
if %w[to not_to to_not].include?(message.value)
0
else
width = doc_width(doc) + 1
width = q.last_position(doc) + 1
width > (q.maxwidth / 2) ? 0 : width
end
end
Expand Down Expand Up @@ -4891,17 +4819,9 @@ def deconstruct_keys(_keys)
end

def format(q)
# This is a very specific behavior that should probably be included in the
# prettyprint module. It's when you want to force a newline, but don't
# want to force the break parent.
breakable = -> do
q.target << PrettyPrint::Breakable.new(
" ",
1,
indent: false,
force: true
)
end
# This is a very specific behavior where you want to force a newline, but
# don't want to force the break parent.
breakable = -> { q.breakable(indent: false, force: :skip_break_parent) }

q.group do
q.format(beginning)
Expand Down Expand Up @@ -5325,9 +5245,8 @@ def format_ternary(q)
# force it into the output but we _don't_ want to explicitly
# break the parent. If a break-parent shows up in the tree, then
# it's going to force it all the way up to the tree, which is
# going to negate the ternary. Maybe this should be an option in
# prettyprint? As in force: :no_break_parent or something.
q.target << PrettyPrint::Breakable.new(" ", 1, force: true)
# going to negate the ternary.
q.breakable(force: :skip_break_parent)
q.format(node.consequent.statements)
end
end
Expand Down Expand Up @@ -8314,8 +8233,7 @@ def format(q)
# same line in the source, then we're going to leave them in place and
# assume that's the way the developer wanted this expression
# represented.
doc = q.group(0, '#{', "}") { q.format(statements) }
RemoveBreaks.call(doc)
q.remove_breaks(q.group(0, '#{', "}") { q.format(statements) })
else
q.group do
q.text('#{')
Expand Down
Loading