Skip to content

Commit

Permalink
Fix body locations for def nodes that have default args (#10619)
Browse files Browse the repository at this point in the history
  • Loading branch information
oprypin committed Apr 16, 2021
1 parent 9105f58 commit b6b52fe
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 6 deletions.
20 changes: 20 additions & 0 deletions spec/compiler/normalize/def_spec.cr
Expand Up @@ -231,5 +231,25 @@ module Crystal
other_def = a_def.expand_default_arguments(Program.new, 0, ["abstract"])
other_def.to_s.should eq("def foo:abstract(abstract __arg0)\n options = {}\n @abstract = __arg0\nend")
end

describe "gives correct body location with" do
{"default arg" => "def testing(foo = 5)",
"default arg with restriction" => "def testing(foo : Int = 5)",
"splat arg" => "def testing(*foo : Array)",
"block instance var arg" => "def testing(&@foo : ->)",
}.each do |(suffix1, definition)|
{"with body" => "zzz = 7\n",
"without body" => "",
}.each do |(suffix2, body)|
it "#{suffix1}, #{suffix2}" do
a_def = parse("#{definition}\n#{body}end").as(Def)
actual = a_def.expand_default_arguments(Program.new, 1)

actual.location.should eq Location.new("", line_number: 1, column_number: 1)
actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)
end
end
end
end
end
end
4 changes: 2 additions & 2 deletions src/compiler/crystal/semantic/default_arguments.cr
Expand Up @@ -166,7 +166,7 @@ class Crystal::Def
end

new_body.push body
expansion.body = Expressions.new(new_body)
expansion.body = Expressions.new(new_body).at(body)
else
new_args = [] of ASTNode
body = [] of ASTNode
Expand Down Expand Up @@ -203,7 +203,7 @@ class Crystal::Def
call.expansion = true
body << call

expansion.body = Expressions.new(body)
expansion.body = Expressions.new(body).at(self.body)
end

expansion
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/crystal/semantic/new.cr
Expand Up @@ -224,7 +224,7 @@ module Crystal
init.block_arg = Var.new(block_arg.name).at(self)
end

self.body = Expressions.from(exps).at(self)
self.body = Expressions.from(exps).at(self.body)
end

def self.argless_new(instance_type)
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/crystal/syntax/parser.cr
Expand Up @@ -3573,7 +3573,7 @@ module Crystal
end_location = token_end_location

if @token.keyword?(:end)
body = Expressions.from(extra_assigns)
body = Expressions.from(extra_assigns).at(@token.location)
next_token_skip_space
else
body = parse_expressions
Expand All @@ -3585,7 +3585,7 @@ module Crystal
else
exps.push body
end
body = Expressions.from(exps)
body = Expressions.from(exps).at(body)
end
body, end_location = parse_exception_handler body, implicit: true
end
Expand Down Expand Up @@ -3852,6 +3852,7 @@ module Crystal
uses_arg = false
do_next_token = true
when :INSTANCE_VAR
# Transform `def foo(@x); end` to `def foo(x); @x = x; end`
arg_name = @token.value.to_s[1..-1]
if arg_name == external_name
raise "when specified, external name must be different than internal name", @token
Expand Down Expand Up @@ -4367,7 +4368,7 @@ module Crystal
else
exps.push block_body
end
block_body = Expressions.from exps
block_body = Expressions.from(exps).at(block_body)
end

block_body, end_location = yield block_body
Expand Down

0 comments on commit b6b52fe

Please sign in to comment.