From 7b090bc23d8913eeaca3217e9ed705e1d58d6f5f Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 30 Aug 2023 22:55:43 +0200 Subject: [PATCH] Ensure node are present only once in the desugared AST --- test/yarp/desugar_visitor_test.rb | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/yarp/desugar_visitor_test.rb b/test/yarp/desugar_visitor_test.rb index 1ef2710c8e8..3966d7bfcb6 100644 --- a/test/yarp/desugar_visitor_test.rb +++ b/test/yarp/desugar_visitor_test.rb @@ -51,14 +51,36 @@ def ast_inspect(node) "(#{parts.join(" ")})" end + # Ensure every node is only present once in the AST. + # If the same node is present twice it would most likely indicate it is executed twice, which is invalid semantically. + # This also acts as a sanity check that Node#child_nodes returns only nodes or nil (which caught a couple bugs). + class EnsureEveryNodeOnceInAST < Visitor + def initialize + @all_nodes = {}.compare_by_identity + end + + def visit(node) + if node + if @all_nodes.include?(node) + raise "#{node.inspect} is present multiple times in the desugared AST and likely executed multiple times" + else + @all_nodes[node] = true + end + end + super(node) + end + end + def assert_desugars(expected, source) ast = YARP.parse(source).value.accept(DesugarVisitor.new) assert_equal expected, ast_inspect(ast.statements.body.last) + + ast.accept(EnsureEveryNodeOnceInAST.new) end def assert_not_desugared(source, reason) ast = YARP.parse(source).value - assert_equal_nodes(ast, ast.accept(YARP::DesugarVisitor.new)) + assert_equal_nodes(ast, ast.accept(DesugarVisitor.new)) end end end