nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: ruby/prism
Pull request #2398 (2024-02-12 18:33:15)

Fix `full_name` for constant path targets
We noticed that `full_name` was not working for constant targets. We probably forgot to add handling for them in the original PR.


Patch:
diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb
index f87714e5..8b92fe1f 100644
--- a/lib/prism/node_ext.rb
+++ b/lib/prism/node_ext.rb
@@ -94,7 +94,7 @@ module Prism
 
     # Returns the full name of this constant. For example: "Foo"
     def full_name
-      name.name
+      name.to_s
     end
   end
 
@@ -135,7 +135,17 @@ module Prism
     # Returns the list of parts for the full name of this constant path.
     # For example: [:Foo, :Bar]
     def full_name_parts
-      (parent&.full_name_parts || [:""]).push(child.name)
+      parts = case parent
+      when ConstantPathNode, ConstantReadNode
+        parent.full_name_parts
+      when nil
+        [:""]
+      else
+        raise ConstantPathNode::DynamicPartsInConstantPathError,
+          "Constant path target contains dynamic parts. Cannot compute full name"
+      end
+
+      parts.push(child.name)
     end
 
     # Returns the full name of this constant path. For example: "Foo::Bar"
@@ -144,6 +154,19 @@ module Prism
     end
   end
 
+  class ConstantTargetNode < Node
+    # Returns the list of parts for the full name of this constant.
+    # For example: [:Foo]
+    def full_name_parts
+      [name]
+    end
+
+    # Returns the full name of this constant. For example: "Foo"
+    def full_name
+      name.to_s
+    end
+  end
+
   class ParametersNode < Node
     # Mirrors the Method#parameters method.
     def signature


Test patch:
diff --git a/test/prism/constant_path_node_test.rb b/test/prism/constant_path_node_test.rb
index aeab6e01..dffb55c0 100644
--- a/test/prism/constant_path_node_test.rb
+++ b/test/prism/constant_path_node_test.rb
@@ -63,5 +63,29 @@ module Prism
       node = Prism.parse(source).value.statements.body.first
       assert_equal("::Foo::Bar::Baz::Qux", node.lefts.first.full_name)
     end
+
+    def test_full_name_for_constant_path_target_with_non_constant_parent
+      source = <<~RUBY
+        self::Foo, Bar = [1, 2]
+      RUBY
+
+      constant_target = Prism.parse(source).value.statements.body.first
+      dynamic, static = constant_target.lefts
+
+      assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do
+        dynamic.full_name
+      end
+
+      assert_equal("Bar", static.full_name)
+    end
+
+    def test_full_name_for_constant_read_node
+      source = <<~RUBY
+        Bar
+      RUBY
+
+      constant = Prism.parse(source).value.statements.body.first
+      assert_equal("Bar", constant.full_name)
+    end
   end
 end
Repository: ruby/prism
Pull request #2435 (2024-02-16 13:46:52)

Fix lexing of `foo!` when it's a first thing to parse
Running `Prism::Translation::Parser` on a file which starts with a method call with bang ends up with an error:

```
Error: test_single_method_call_with_bang.txt(Prism::ParserTest): NoMethodError: undefined method `[]' for nil:NilClass
lib/prism/translation/parser/lexer.rb:292:in `to_a'
lib/prism/translation/parser.rb:159:in `build_tokens'
lib/prism/translation/parser.rb:89:in `tokenize'
prism/parser_test.rb:111:in `assert_equal_parses'
test/prism/parser_test.rb:89:in `block (2 levels) in <class:ParserTest>'
```

because `tokens` is an empty array in that case


I've added a separate fixture for it to indicate that the error is happening only if it's a first thing to parse, but I also can move `a!` in the `fixtures/method_calls.txt` to the top instead.


Patch:
diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb
index 6d3321b9..5c993cfa 100644
--- a/lib/prism/translation/parser/lexer.rb
+++ b/lib/prism/translation/parser/lexer.rb
@@ -289,7 +289,7 @@ module Prism
                 index += 1
               end
             when :tFID
-              if tokens[-1][0] == :kDEF
+              if !tokens.empty? && tokens[-1][0] == :kDEF
                 type = :tIDENTIFIER
               end
             end


Test patch:
diff --git a/test/prism/fixtures/single_method_call_with_bang.txt b/test/prism/fixtures/single_method_call_with_bang.txt
new file mode 100644
index 00000000..929efb30
--- /dev/null
+++ b/test/prism/fixtures/single_method_call_with_bang.txt
@@ -0,0 +1,1 @@
+foo!
diff --git a/test/prism/snapshots/single_method_call_with_bang.txt b/test/prism/snapshots/single_method_call_with_bang.txt
new file mode 100644
index 00000000..4c68e0ad
--- /dev/null
+++ b/test/prism/snapshots/single_method_call_with_bang.txt
@@ -0,0 +1,15 @@
+@ ProgramNode (location: (1,0)-(1,4))
+├── locals: []
+└── statements:
+    @ StatementsNode (location: (1,0)-(1,4))
+    └── body: (length: 1)
+        └── @ CallNode (location: (1,0)-(1,4))
+            ├── flags: ignore_visibility
+            ├── receiver: ∅
+            ├── call_operator_loc: ∅
+            ├── name: :foo!
+            ├── message_loc: (1,0)-(1,4) = "foo!"
+            ├── opening_loc: ∅
+            ├── arguments: ∅
+            ├── closing_loc: ∅
+            └── block: ∅