Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix body locations for def nodes that have default args #10619

Merged
merged 3 commits into from Apr 16, 2021

Conversation

oprypin
Copy link
Member

@oprypin oprypin commented Apr 11, 2021

Currently it is reported that the actual body of the method begins at the first "assignment" to a default arg, if there is one:

          \/here
def foo(x, y=5)
  test
 /\not here
end

I think that's a bit arbitrary and won't be helpful for whatever tooling may rely on this, so I change it to be shown at the point of the "not here" example on the diagram.

This also fixes the body location for def self.new generated from def initialize.

Currently it is reported that the actual body of the method begins at the first "assignment" to a default arg, if there is one:

              \/here
    def foo(x, y=5)
      test
     /\not here
    end

I think that's a bit arbitrary and won't be helpful for whatever tooling may rely on this, so I change it to be as shown "not here" on the diagram.

This also fixes the body location for `def self.new` generated from `def initialize`.
@oprypin
Copy link
Member Author

oprypin commented Apr 11, 2021

Specs that I'm adding were previously failing:

Failures:

  1) Normalize: def gives correct body location with default arg, without body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: nil

     # spec/compiler/normalize/def_spec.cr:248

  2) Normalize: def gives correct body location with default arg with restriction, without body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: nil

     # spec/compiler/normalize/def_spec.cr:248

  3) Normalize: def gives correct body location with splat arg, with body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: :1:14

     # spec/compiler/normalize/def_spec.cr:248

  4) Normalize: def gives correct body location with splat arg, without body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: :1:14

     # spec/compiler/normalize/def_spec.cr:248

  5) Normalize: def gives correct body location with block instance var arg, with body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: :1:14

     # spec/compiler/normalize/def_spec.cr:248

  6) Normalize: def gives correct body location with block instance var arg, without body
     Failure/Error: actual.body.location.should eq Location.new("", line_number: 2, column_number: 1)

       Expected: :2:1
            got: :1:14

     # spec/compiler/normalize/def_spec.cr:248

Copy link
Member

@asterite asterite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

Comment on lines 235 to 253
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 |(suf, definition)|
describe suf + "," do
{"with body" => "zzz = 7\n", "without body" => ""}.each do |(suf, body)|
it suf 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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a general consideration, I don't like specs in iterations because they seem unnecessarily hard to understand. Especially with nested iterations.
My preferred style would be a spec helper called with explicit source code of each combination. That also offers much flexibility and it would be easy to add specs for multi-line parameter lists for example.
I'm happy to accept this as is though.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind, but in this particular case I don't see a good way to write this with a helper, particularly due to the nested iterations.
I think I will not do this change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be my proposal: straight-shoota@5da5886

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm some things there that make me like that one less:

  • The with body context comes in the wrong order (precedence).
  • No possibility of auto-indenting the different cases.
  • It is indeed a lot more code, and it's not like the helper will be reused for different tests.

For now I tweaked my version, maybe it looks a little better

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@straight-shoota straight-shoota added this to the 1.1.0 milestone Apr 13, 2021
@straight-shoota straight-shoota merged commit b6b52fe into crystal-lang:master Apr 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants