-
-
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
Check that def, macro, and block parameters don't end with ?
or !
#12197
base: master
Are you sure you want to change the base?
Conversation
Note: this is a breaking change. I decided to raise an exception because I didn't find how to log a warning + test warning message. In What do you think of this approach? In case you suggest to keep this change backward compatible can you point me to an example of warning + test for the parser please? |
?
or !
This should not be a breaking change. So we'll need a warning. You can use crystal/src/compiler/crystal/semantic/warnings.cr Lines 19 to 39 in e10841c
There are currently no warnings in the parser and no specs for that. |
As I mentioned somewhere else (in the |
Ah, okay. Then we'll probably need a bigger change in order to move forward with this. |
@straight-shoota would it make sense if I add I guess it would be better to split the work in two PRs, one for updating the definition of Any objections? |
I think it should be the opposite: the parser itself should be able to report warnings even without a |
Yeah, I suppose it would be preferable to collect warnings for an individual parser run vs. amending everything in |
@HertzDevil yes and sorry for the late reply. |
a1793e4
to
b08fbd3
Compare
if param_name.ends_with?(/\?|!/) | ||
raise "invalid param name" | ||
end |
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.
Small optimization (no regex) + rephrased error message to make it more clear about the name in question:
if param_name.ends_with?(/\?|!/) | |
raise "invalid param name" | |
end | |
if param_name[-1]?.in?('?', '!') | |
raise "invalid parameter name: #{param_name}" | |
end |
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.
When I use this version I get a bunch of Index out of bounds (IndexError)
errors.
I guess I should first check if the param_name
string is not empty, what do you think?
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.
You can go with this:
if param_name.ends_with?(/\?|!/) | |
raise "invalid param name" | |
end | |
if param_name.ends_with?("?") || param_name.ends_with?("!") | |
raise "invalid param name" | |
end |
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.
I've edited the suggestion
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.
Ok, so the choice is between:
param_name[-1]?.in?('?', '!')
!param_name.empty? && param_name[-1].in?('?', '!')
param_name.ends_with?("?") || param_name.ends_with?("!")
I think the last one is the most clear.
Is there an advantage in using version 1 or 2?
Which one is the most idiomatic?
I've turned failures to parse params with invalid names into syntax warnings similar to crystal-lang#12427, as suggested by @HertzDevil.
if external_name_token.nil? | ||
raise "missing external name token" | ||
end |
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.
When external_name
is present external_name_token
should also be present, so it may be better to turn this into an invariant.
I've brought this change up to date. Actually it looks good, it emits warnings, as was discussed. Not sure why this one got left behind. |
There's one file in the stdlib that will give a warning for this, don't remember which file though. May want to fix that at the same time |
@nobodywasishere That is true. But that instance cannot be fixed without fixing REPLy first - it defines a base class with a parameter that contains a questionmark. So sent I3oris/reply#9 |
I wish the decision to forbid such suffixes was revisited... Given that they're allowed in the method names I see no logical reason to do so. |
@Sija the current syntax allows this, which I personally think is problematic: var = 5
var! : Int32 = 2
# parsed as `(var) != (1)`
puts var!=1 # => true
# parsed as `(var!) = (1)`
puts var! = 1 # => 1 |
I think that's exactly the reason to make this change -- so there is no ambiguity about whether |
@keidax a simple |
Fixes #10917
Tested with: