-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Improve error suggestion when using logical operators. Fixes #2715 #2738
Improve error suggestion when using logical operators. Fixes #2715 #2738
Conversation
@@ -282,6 +285,19 @@ class Crystal::Call | |||
raise message, owner_trace | |||
end | |||
|
|||
def logical_operator?(def_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
created these methods to avoid getting the raise_matches_not_found
method getting bigger and bigger.
If makes sense to keep them, my idea is to keep extracting more methods (is is a good idea?)
totally missed the |
def convert_def_name_to_logical_operator(def_name) | ||
case def_name | ||
when "and"; "&&" | ||
when "or" ; "||" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the formatting here, might just do a Hash(String, String)
to a constant and look up?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's fine with me, I'm not sure adding a Hash is worth it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah... my first solution was a hash, then I thought was polluting unnecessary, and changed to method hahahah what you think is the best approach, I'm ok with :)
Looking at this I wonder whether we should future proof this a bit, we could generically define a list of static overrides for the suggestion, mentioning logic operators in the identifiers chosen here doesn't even seem necessary. |
@jhass in terms of code would be changing from |
@@ -90,6 +90,9 @@ class Crystal::Call | |||
error_msg = String.build do |msg| | |||
if obj && owner != mod | |||
msg << "undefined method '#{def_name}' for #{owner}" | |||
elsif logical_operator?(def_name) | |||
msg << "undefined method '#{def_name}'" | |||
similar_name = convert_def_name_to_logical_operator(def_name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just
similar_name = STATIC_SUGGESTIONS[def_name]? || owner.lookup_similar_def_name(def_name, self.args.size, block)
in line 88 above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that this shouldn't always be suggested, only when there's no receiver. Doing that in line 88 will always suggest it, which is not very good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, that's what I missed.
We can add this if many feel this is OK. I tried doing (but I'm OK with adding these suggestions to make it easier for people coming from Ruby, the problem is when to stop) |
I don't think we should add for every bit of Ruby, just for most common use cases (I know, what is a "common" case? again, when to stop) - that's the reason I added only for |
But "not" is a keyword in Ruby. Maybe we should add it too. |
@asterite what would be the suggestion?
|
@fernandes Yes |
@asterite done! 😄 |
@fernandes Just a final refactor before merging this. There's no need for two methods, if obj && owner != mod
msg << "undefined method '#{def_name}' for #{owner}"
elsif op = logical_operator?(def_name)
msg << "undefined method '#{def_name}'"
similar_name = op That way there's less code and the method is only called once (a bit faster, but won't be noticeable). |
@asterite thanks for the tips... what do you think about usually methods like |
The convention of methods ending with |
But you can use |
When using `if foo and bar` the compiler was suggestion the use of `rand` method, and that is because `rand` is defined at top level and Crystal::MatchesLookup was finding it as the nearest option. Now it checks the missing method is `and` or `or` and suggest the right `&&` and `||` operators.
@asterite ready! 👍 |
Thanks!! |
🙇 |
When using
if foo and bar
the compiler was suggestion the use ofrand
method, and that is becauserand
is defined at top level andCrystal::MatchesLookup was finding it as the nearest option.
Now it checks the missing method is
and
oror
and suggest the right&&
and||
operators.