Skip to content

Commit c8011ef

Browse files
pvcresincursoragent
authored andcommitted
Fix keyword-as-hash handling for methods without keyword params
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent ef0935b commit c8011ef

4 files changed

Lines changed: 30 additions & 2 deletions

File tree

lib/typeprof/core/ast/method.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def self.parse_params(tbl, raw_args, lenv)
3737
opt_keywords: [],
3838
opt_keyword_defaults: [],
3939
rest_keywords: nil,
40+
no_keywords: false,
4041
block: nil,
4142
}
4243
end
@@ -64,6 +65,7 @@ def self.parse_params(tbl, raw_args, lenv)
6465
req_keywords = []
6566
opt_keywords = []
6667
opt_keyword_defaults = []
68+
no_keywords = false
6769

6870
raw_args.keywords.each do |kw|
6971
case kw.type
@@ -83,7 +85,7 @@ def self.parse_params(tbl, raw_args, lenv)
8385
rest_positionals = :"..."
8486
rest_keywords = :"..."
8587
when Prism::NoKeywordsParameterNode
86-
# what to do?
88+
no_keywords = true
8789
when nil
8890
# nothing to do
8991
else
@@ -102,6 +104,7 @@ def self.parse_params(tbl, raw_args, lenv)
102104
opt_keywords:,
103105
opt_keyword_defaults:,
104106
rest_keywords:,
107+
no_keywords:,
105108
block:,
106109
args_code_ranges:
107110
}
@@ -144,6 +147,7 @@ def initialize(raw_node, lenv, use_result)
144147
@opt_keywords = h[:opt_keywords]
145148
@opt_keyword_defaults = h[:opt_keyword_defaults]
146149
@rest_keywords = h[:rest_keywords]
150+
@no_keywords = h[:no_keywords]
147151
@block = h[:block]
148152
@args_code_ranges = h[:args_code_ranges] || []
149153

@@ -163,6 +167,7 @@ def initialize(raw_node, lenv, use_result)
163167
attr_reader :opt_keywords
164168
attr_reader :opt_keyword_defaults
165169
attr_reader :rest_keywords
170+
attr_reader :no_keywords
166171
attr_reader :block
167172
attr_reader :body
168173
attr_reader :rbs_method_type
@@ -186,6 +191,7 @@ def attrs = {
186191
req_keywords:,
187192
opt_keywords:,
188193
rest_keywords:,
194+
no_keywords:,
189195
block:,
190196
reusable:,
191197
}

lib/typeprof/core/env/method.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,17 @@ def new_vertexes(genv, node)
4141
ActualArguments.new(positionals, splat_flags, keywords, block)
4242
end
4343

44+
def with_keywords_as_last_positional_hash
45+
return self unless @keywords
46+
47+
ActualArguments.new(
48+
@positionals + [@keywords],
49+
@splat_flags + [false],
50+
nil,
51+
@block
52+
)
53+
end
54+
4455
def get_rest_args(genv, changes, start_rest, end_rest)
4556
vtxs = []
4657

lib/typeprof/core/graph/box.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ def run0(genv, changes)
491491
end
492492

493493
def pass_arguments(changes, genv, a_args)
494+
a_args = normalize_keyword_hash_argument_for_def(a_args)
495+
494496
if a_args.splat_flags.any?
495497
# there is at least one splat actual argument
496498

@@ -607,6 +609,15 @@ def pass_arguments(changes, genv, a_args)
607609
return true
608610
end
609611

612+
def normalize_keyword_hash_argument_for_def(a_args)
613+
return a_args unless a_args.keywords
614+
return a_args if @node.no_keywords
615+
return a_args if @node.rest_keywords
616+
return a_args unless @node.req_keywords.empty? && @node.opt_keywords.empty?
617+
618+
a_args.with_keywords_as_last_positional_hash
619+
end
620+
610621
def call(changes, genv, a_args, ret)
611622
if pass_arguments(changes, genv, a_args)
612623
changes.add_edge(genv, a_args.block, @f_args.block) if @f_args.block && a_args.block
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ def foo(a)
77

88
## assert
99
class Object
10-
def foo: (Hash[:x, Integer]) -> Hash[:x, Integer]
10+
def foo: ({ x: Integer }) -> { x: Integer }
1111
end

0 commit comments

Comments
 (0)