Skip to content

Commit dc26613

Browse files
authored
Merge pull request #419 from koic/fix_syntax_error_on_ruby_2_7_0
Fix a `SyntaxError` on Ruby 2.7.0 caused by arguments forwarding syntax
2 parents db460e5 + c4c73e0 commit dc26613

4 files changed

Lines changed: 32 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
strategy:
1010
matrix:
1111
entry:
12-
- { ruby: '2.7', allowed-failure: false }
12+
- { ruby: '2.7.0', allowed-failure: false } # Minimum supported Ruby version.
1313
- { ruby: '3.0', allowed-failure: false }
1414
- { ruby: '3.1', allowed-failure: false }
1515
- { ruby: '3.2', allowed-failure: false }

lib/mcp/server_context.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,14 @@ def notify_elicitation_complete(**kwargs)
130130
end
131131
end
132132

133-
def method_missing(name, ...)
133+
# Forward arguments explicitly with `*args, **kwargs, &block` rather than the `...` forwarding syntax.
134+
# The gem supports Ruby 2.7.0 (see `required_ruby_version`), but RuboCop's Parser backend only runs on Ruby 2.7.8,
135+
# so leading-argument forwarding like `def method_missing(name, ...)` is allowed by the linter even though it
136+
# raises a `SyntaxError` on Ruby 2.7.0 through 2.7.2 (it was added in Ruby 2.7.3). Explicit forwarding keeps
137+
# this method loadable on Ruby 2.7.0.
138+
def method_missing(name, *args, **kwargs, &block)
134139
if @context.respond_to?(name)
135-
@context.public_send(name, ...)
140+
@context.public_send(name, *args, **kwargs, &block)
136141
else
137142
super
138143
end

test/mcp/server_context_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,20 @@ def context.custom_method
201201
assert_equal "custom_value", server_context.custom_method
202202
end
203203

204+
test "ServerContext forwards positional, keyword, and block arguments to the context" do
205+
context = Object.new
206+
def context.combine(prefix, suffix:, &block)
207+
block.call("#{prefix}-#{suffix}")
208+
end
209+
progress = Progress.new(notification_target: mock, progress_token: nil)
210+
211+
server_context = ServerContext.new(context, progress: progress, notification_target: mock)
212+
213+
result = server_context.combine("a", suffix: "b", &:upcase)
214+
215+
assert_equal "A-B", result
216+
end
217+
204218
test "ServerContext#report_progress works with nil context" do
205219
progress = mock
206220
progress.expects(:report).with(50, total: 100, message: nil).once

test/test_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
require "minitest/mock"
77
require "mocha/minitest"
88

9+
# mocha relies on `Hash.ruby2_keywords_hash?`, which is absent on Ruby 2.7.0 and the earlier 2.7.x releases
10+
# before it was backported. Those versions also lack the flag-setting APIs, so no hash is ever flagged as
11+
# ruby2_keywords and returning `false` is correct. Without this shim, mocha raises `NoMethodError` and
12+
# the suite cannot run on Ruby 2.7.0.
13+
unless Hash.respond_to?(:ruby2_keywords_hash?)
14+
def Hash.ruby2_keywords_hash?(_hash)
15+
false
16+
end
17+
end
18+
919
require "active_support"
1020
require "active_support/test_case"
1121

0 commit comments

Comments
 (0)