|
| 1 | +# frozen_string_literal: true |
| 2 | +# typed: ignore |
| 3 | + |
| 4 | +require_relative "../test_helper" |
| 5 | + |
| 6 | +# Needs Prism.parse_file(file, version: "current") |
| 7 | +return if RUBY_VERSION < "3.3" |
| 8 | + |
| 9 | +require_relative 'inline_method' |
| 10 | + |
| 11 | +module Prism |
| 12 | + class NodeForTest < TestCase |
| 13 | + INDENT = ' ' * 4 |
| 14 | + |
| 15 | + def m(foo) |
| 16 | + 42 |
| 17 | + end |
| 18 | + M_LOCATION = [__LINE__-3, 4, __LINE__-1, 7] |
| 19 | + |
| 20 | + define_method(:define_method_method) { 42 } |
| 21 | + DEFINE_METHOD_LOCATION = [__LINE__-1, 41, __LINE__-1, 47] |
| 22 | + |
| 23 | + def return_block(&block) |
| 24 | + block |
| 25 | + end |
| 26 | + |
| 27 | + iter = Object.new |
| 28 | + def iter.each(&block) |
| 29 | + block.call(block) |
| 30 | + end |
| 31 | + |
| 32 | + for pr in iter |
| 33 | + 42 |
| 34 | + end |
| 35 | + FOR_BODY_PROC = pr |
| 36 | + FOR_BODY_PROC_LOCATION = [__LINE__-4, 4, __LINE__-2, 7] |
| 37 | + |
| 38 | + def with_location(callable, locs, file = __FILE__) |
| 39 | + source_location = [file, *locs] |
| 40 | + if RUBY_VERSION >= "4.1" |
| 41 | + assert_equal callable.source_location, source_location |
| 42 | + else |
| 43 | + callable.define_singleton_method(:source_location) { source_location } |
| 44 | + end |
| 45 | + callable |
| 46 | + end |
| 47 | + |
| 48 | + def test_def_method |
| 49 | + node = Prism.node_for(with_location(NodeForTest.instance_method(:m), M_LOCATION)) |
| 50 | + assert_instance_of(Prism::DefNode, node) |
| 51 | + assert_equal "def m(foo)\n#{INDENT} 42\n#{INDENT}end", node.slice |
| 52 | + |
| 53 | + node = Prism.node_for(with_location(method(:m), M_LOCATION)) |
| 54 | + assert_instance_of(Prism::DefNode, node) |
| 55 | + assert_equal "def m(foo)\n 42\n end", node.slice |
| 56 | + end |
| 57 | + |
| 58 | + def test_inline_method |
| 59 | + node = Prism.node_for(with_location(method(:inline_method), *INLINE_LOCATION_AND_FILE)) |
| 60 | + assert_instance_of(Prism::DefNode, node) |
| 61 | + assert_equal "def inline_method = 42", node.slice |
| 62 | + end |
| 63 | + |
| 64 | + def test_define_method |
| 65 | + node = Prism.node_for(with_location(method(:define_method_method), DEFINE_METHOD_LOCATION)) |
| 66 | + assert_instance_of(Prism::CallNode, node) |
| 67 | + assert_equal "define_method(:define_method_method) { 42 }", node.slice |
| 68 | + assert_equal "{ 42 }", node.block.slice |
| 69 | + end |
| 70 | + |
| 71 | + def test_lambda |
| 72 | + node = Prism.node_for(with_location(-> { 42 }, [__LINE__, 42, __LINE__, 51])) |
| 73 | + assert_instance_of(Prism::LambdaNode, node) |
| 74 | + assert_equal "-> { 42 }", node.slice |
| 75 | + assert_equal "{ 42 }", node.opening_loc.join(node.closing_loc).slice |
| 76 | + |
| 77 | + node = Prism.node_for(with_location(lambda { 42 }, [__LINE__, 49, __LINE__, 55])) |
| 78 | + assert_instance_of(Prism::CallNode, node) |
| 79 | + assert_equal "lambda { 42 }", node.slice |
| 80 | + assert_equal "{ 42 }", node.block.slice |
| 81 | + end |
| 82 | + |
| 83 | + def test_proc |
| 84 | + node = Prism.node_for(with_location(proc { 42 }, [__LINE__, 47, __LINE__, 53])) |
| 85 | + assert_instance_of(Prism::CallNode, node) |
| 86 | + assert_equal "proc { 42 }", node.slice |
| 87 | + assert_equal "{ 42 }", node.block.slice |
| 88 | + |
| 89 | + node = Prism.node_for(with_location(return_block { 42 }, [__LINE__, 55, __LINE__, 61])) |
| 90 | + assert_instance_of(Prism::CallNode, node) |
| 91 | + assert_equal "return_block { 42 }", node.slice |
| 92 | + assert_equal "{ 42 }", node.block.slice |
| 93 | + |
| 94 | + heredoc_proc = proc { <<~END } |
| 95 | + heredoc |
| 96 | + END |
| 97 | + node = Prism.node_for(with_location(heredoc_proc, [__LINE__-3, 26, __LINE__-3, 36])) |
| 98 | + assert_instance_of(Prism::CallNode, node) |
| 99 | + assert_equal "proc { <<~END }", node.slice |
| 100 | + assert_equal "heredoc\n", node.block.body.body.first.unescaped |
| 101 | + end |
| 102 | + |
| 103 | + def test_method_to_proc |
| 104 | + node = Prism.node_for(with_location(method(:inline_method).to_proc, *INLINE_LOCATION_AND_FILE)) |
| 105 | + assert_instance_of(Prism::DefNode, node) |
| 106 | + assert_equal "def inline_method = 42", node.slice |
| 107 | + end |
| 108 | + |
| 109 | + def test_for |
| 110 | + node = Prism.node_for(with_location(FOR_BODY_PROC, FOR_BODY_PROC_LOCATION)) |
| 111 | + assert_instance_of(Prism::ForNode, node) |
| 112 | + assert_equal "for pr in iter\n#{INDENT} 42\n#{INDENT}end", node.slice |
| 113 | + assert_equal "42", node.statements.slice |
| 114 | + end |
| 115 | + |
| 116 | + def test_eval |
| 117 | + l = with_location(eval("-> { 42 }"), [1, 0, 1, 9], "(eval at #{__FILE__}:#{__LINE__})") |
| 118 | + e = assert_raise(ArgumentError) { Prism.node_for(l) } |
| 119 | + assert_include e.message, 'eval' |
| 120 | + |
| 121 | + l = eval "-> { 42 }", nil, __FILE__, __LINE__ |
| 122 | + l = with_location(l, [__LINE__-1, 0, __LINE__-1, 9]) |
| 123 | + e = assert_raise(ArgumentError) { Prism.node_for(l) } |
| 124 | + assert_include e.message, 'Could not find node' |
| 125 | + end |
| 126 | + end |
| 127 | +end |
0 commit comments