Skip to content

Commit

Permalink
Migrate pretty print to Prism #262
Browse files Browse the repository at this point in the history
  • Loading branch information
killondark committed May 9, 2024
1 parent ce22e5a commit e16a269
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Expand Up @@ -7,7 +7,7 @@ gemspec
gem "debug", platform: :mri unless ENV["CI"] == "true"

gem "method_source"
gem "unparser"
gem "prism"

gem 'sqlite3', "~> 1.4.0", platform: :mri
gem 'activerecord-jdbcsqlite3-adapter', '~> 50.0', platform: :jruby
Expand Down
2 changes: 1 addition & 1 deletion docs/debugging.md
Expand Up @@ -2,7 +2,7 @@

**NOTE:** this functionality requires two additional gems to be available in the app:

- [unparser](https://github.com/mbj/unparser)
- [prism](https://github.com/ruby/prism)
- [method_source](https://github.com/banister/method_source).

We usually describe policy rules using _boolean expressions_ (e.g. `A or (B and C)` where each of `A`, `B` and `C` is a simple boolean expression or predicate method).
Expand Down
2 changes: 1 addition & 1 deletion forspell.dict
Expand Up @@ -12,7 +12,7 @@ matchers
non-inferrable
Railsy
testability
unparser
prism
utils
transpiled
supersets
Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails6.gemfile
Expand Up @@ -3,6 +3,6 @@ source "https://rubygems.org"
gem "sqlite3", "~> 1.4"
gem "rails", "~> 6.0"
gem "method_source"
gem "unparser"
gem "prism"

gemspec path: ".."
2 changes: 1 addition & 1 deletion gemfiles/rails7.gemfile
Expand Up @@ -3,7 +3,7 @@ source "https://rubygems.org"
gem "sqlite3", "~> 1.4"
gem "rails", "~> 7.0.0"
gem "method_source"
gem "unparser"
gem "prism"

if ENV["COVERAGE"] == "true"
gem "simplecov"
Expand Down
2 changes: 1 addition & 1 deletion gemfiles/rails71.gemfile
Expand Up @@ -3,7 +3,7 @@ source "https://rubygems.org"
gem "sqlite3", "~> 1.4"
gem "rails", "~> 7.1.0"
gem "method_source"
gem "unparser"
gem "prism"

if ENV["COVERAGE"] == "true"
gem "simplecov"
Expand Down
2 changes: 1 addition & 1 deletion lib/action_policy/policy/core.rb
Expand Up @@ -147,7 +147,7 @@ def resolve_rule(activity)
end

# Return annotated source code for the rule
# NOTE: require "method_source" and "unparser" gems to be installed.
# NOTE: require "method_source" and "prism" gems to be installed.
# Otherwise returns empty string.
def inspect_rule(rule) = PrettyPrint.print_method(self, rule)

Expand Down
54 changes: 25 additions & 29 deletions lib/action_policy/utils/pretty_print.rb
Expand Up @@ -7,8 +7,7 @@
# Ignore parse warnings when patch
# Ruby version mismatches
$VERBOSE = nil
require "parser/current"
require "unparser"
require "prism"
rescue LoadError
# do nothing
ensure
Expand Down Expand Up @@ -42,7 +41,7 @@ module PrettyPrint
FALSE = "\e[31mfalse\e[0m"

class Visitor
attr_reader :lines, :object
attr_reader :lines, :object, :source
attr_accessor :indent

def initialize(object)
Expand All @@ -52,6 +51,8 @@ def initialize(object)
def collect(ast)
@lines = []
@indent = 0
@source = ast.source.source
ast = ast.value.child_nodes[0].child_nodes[0].body

visit_node(ast)

Expand All @@ -67,7 +68,7 @@ def visit_node(ast)
end

def expression_with_result(sexp)
expression = Unparser.unparse(sexp)
expression = source[sexp.location.start_offset...sexp.location.end_offset]
"#{expression} #=> #{PrettyPrint.colorize(eval_exp(expression))}"
end

Expand All @@ -78,36 +79,33 @@ def eval_exp(exp)
"Failed: #{e.message}"
end

def visit_and(ast)
visit_node(ast.children[0])
def visit_and_node(ast)
visit_node(ast.left)
lines << indented("AND")
visit_node(ast.children[1])
visit_node(ast.right)
end

def visit_or(ast)
visit_node(ast.children[0])
def visit_or_node(ast)
visit_node(ast.left)
lines << indented("OR")
visit_node(ast.children[1])
visit_node(ast.right)
end

def visit_begin(ast)
# Parens
if ast.children.size == 1
lines << indented("(")
self.indent += 2
visit_node(ast.children[0])
def visit_statements_node(ast)
ast.child_nodes.each do |node|
visit_node(node)
# restore indent after each expression
self.indent -= 2
lines << indented(")")
else
# Multiple expressions
ast.children.each do |node|
visit_node(node)
# restore indent after each expression
self.indent -= 2
end
end
end

def visit_parentheses_node(ast)
lines << indented("(")
self.indent += 2
visit_node(ast.child_nodes[0])
lines << indented(")")
end

def visit_missing(ast)
lines << indented(expression_with_result(ast))
end
Expand All @@ -128,15 +126,13 @@ def ignore_exp?(exp)
class << self
attr_accessor :ignore_expressions

if defined?(::Unparser) && defined?(::MethodSource)
if defined?(::Prism) && defined?(::MethodSource)
def available?() = true

def print_method(object, method_name)
ast = object.method(method_name).source.then(&Unparser.:parse)
# outer node is a method definition itself
body = ast.children[2]
ast = Prism.parse(object.method(method_name).source)

Visitor.new(object).collect(body)
Visitor.new(object).collect(ast)
end
else
def available?() = false
Expand Down

0 comments on commit e16a269

Please sign in to comment.