-
-
Notifications
You must be signed in to change notification settings - Fork 804
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
Use levenshtein distance for better error messages #2806
Use levenshtein distance for better error messages #2806
Conversation
Codecov Report
@@ Coverage Diff @@
## master #2806 +/- ##
===========================================
- Coverage 87.46% 57.09% -30.38%
===========================================
Files 93 94 +1
Lines 9960 9994 +34
Branches 2471 2431 -40
===========================================
- Hits 8712 5706 -3006
- Misses 782 3679 +2897
- Partials 466 609 +143
Continue to review full report at Codecov.
|
vyper/semantics/namespace.py
Outdated
@@ -7,6 +7,7 @@ | |||
StructureException, | |||
UndeclaredDefinition, | |||
) | |||
from vyper.utils import get_levenshtein_string |
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 think we should a) rename this to get_levenshtein_error_suggestions
and b) move all the levenshtein utils to their own module. i think vyper/semantics/validation/levenshtein_utils.py
makes sense.
vyper/utils.py
Outdated
|
||
distances = sorted([(i, levenshtein_norm(key, i)) for i in namespace], key=lambda k: k[1]) | ||
if len(distances) > 0 and distances[0][1] <= threshold: | ||
return f" Did you mean '{distances[0][0]}'?" |
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 don't think the initial space is required -- the caller should be responsible for this.
vyper/semantics/validation/utils.py
Outdated
@@ -151,8 +152,11 @@ def types_from_Attribute(self, node): | |||
f"'{name}' is not a storage variable, it should not be prepended with self", | |||
node, | |||
) from None | |||
|
|||
levenshtein_string = get_levenshtein_string(name, var.members, 0.4) |
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 don't think we need to name the variable levenshtein_string
, which is a bit arcane. how about suggestions_str
?
levenshtein_string = get_levenshtein_string(name, var.members, 0.4) | |
suggestions_str = get_levenshtein_error_string(name, var.members, 0.4) |
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.
functionality looks good, just a few nits
distances = sorted([(i, levenshtein_norm(key, i)) for i in namespace], key=lambda k: k[1]) | ||
min_levenshtein_val = distances[0][1] | ||
if len(distances) > 0 and min_levenshtein_val <= threshold: | ||
if distances[1][1] == min_levenshtein_val: |
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.
this doesn't work if there is only one possible suggestion. e.g.
(vyper) ~/vyper $ cat tmp/foo.vy
interface Foo:
def foo(x: uint256, y: uint256 = 1): nonpayable
@external
def foo():
Foo(msg.sender).fooo(1)
|
||
distances = sorted([(i, levenshtein_norm(key, i)) for i in namespace], key=lambda k: k[1]) | ||
if len(distances) > 0 and distances[0][1] <= threshold: | ||
if len(distances) >= 2 and distances[0][1] == distances[1][1]: |
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 think we do not need to check that the top two distances are equal, instead we only require that distances[1][1]
is also <= threshold
.
|
||
distances = sorted([(i, levenshtein_norm(key, i)) for i in namespace], key=lambda k: k[1]) | ||
if len(distances) > 0 and distances[0][1] <= threshold: | ||
if len(distances) >= 2 and distances[0][1] == distances[1][1]: |
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.
also a nit -- for consistency with the above branch, use >
if len(distances) >= 2 and distances[0][1] == distances[1][1]: | |
if len(distances) > 1 and distances[0][1] == distances[1][1]: |
Co-authored-by: Charles Cooper <cooper.charles.m@gmail.com>
What I did
Fix for #2767
How I did it
Refer to Brownie and docopt-ng. Helper function is extracted from the source at docopt-ng.
How to verify it
Commit message
Use Levenshtein distance for better error messages
Description for the changelog
Use Levenshtein distance for better error messages
Cute Animal Picture