Suggest alternatives when identifier not found. Closes #3058.#3147
Suggest alternatives when identifier not found. Closes #3058.#3147chriseth merged 8 commits intoargotorg:developfrom
Conversation
|
@Balajiganapathi thanks these are great! Will do an individual review, but two small mentions (applies to all PRs): no need to use namespace specifier |
|
Please include a test for inheritance (suggested name in the inheritance tree). |
| if (m_enclosingContainer) | ||
| { | ||
| std::vector<ASTString> enclosingSimilar = m_enclosingContainer->similarNames(_name); | ||
| similar.insert(similar.end(), enclosingSimilar.begin(), enclosingSimilar.end()); |
There was a problem hiding this comment.
I wonder which is faster. The current way or doing the parent first and the push_front to extend that vector?
There was a problem hiding this comment.
I think this is reasonably fast. push_front on vector is quite slow (though we can use list/deque to get around that). Inserting at end like here is efficient.
It can be made slightly faster by avoiding creation of multiple vectors. We can create a single vector and pass it by reference as a parameter to the function. Or we can use a list and use splice to append at end. But I am not sure it will result in any substantial gain.
PS: Thanks for the tips :) will remove std:: and add change log to all my PRs.
| CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier."); | ||
|
|
||
| sourceCode = R"( | ||
| contract c { |
There was a problem hiding this comment.
Indentation on these looks a bit off (one extra level of indentation).
|
Looks really good! Great work @Balajiganapathi |
|
@Balajiganapathi just a heads up: we'll be busy with devcon this week and it is likely that your changes won't be properly addressed this week. |
798084b to
f97a754
Compare
|
@axic I have made the suggested changes to this (and my 3 other) PRs. Waiting for these PRs to be reviewed and merged before taking up more tasks as I don't want to keep repeating the same mistakes :) |
| return similar; | ||
| } | ||
|
|
||
| bool DeclarationContainer::areSimilarNames(ASTString const& name1, ASTString const& name2) |
There was a problem hiding this comment.
I would move this to libdevcore and name it something like stringWithinDistance(name1, name2, distance). It can be later reused for showing potential names for visibility specifiers, etc.
| function g() public { fun(); } | ||
| } | ||
| )"; | ||
| CHECK_ERROR(sourceCode, DeclarationError, "Undeclared identifier. Did you mean func?"); |
There was a problem hiding this comment.
Can you enclose the suggestions in quotes - that is how other messages are? eg "func", "func1", "func2" or "func3"
|
@Balajiganapathi will you have some time before next week to check these changes out or should I push changes to this branch? |
|
@axic had a busy week so could not work on it. Will make these changes over this weekend. |
|
None of the existing files in libdevcore seems to fit. Shall I make a new StringUtils source file for this? |
2c2c7b0 to
8b020c1
Compare
I think it sounds fine, could be more specific too if you find a good name (something along the lines of string similarity). Please add a specific test for the distance module in |
|
Done @axic |
960e853 to
22c7b6c
Compare
| std::map<ASTString, std::vector<Declaration const*>> m_declarations; | ||
| std::map<ASTString, std::vector<Declaration const*>> m_invisibleDeclarations; | ||
|
|
||
| static size_t const MAXIMUM_DISTANCE = 2; |
There was a problem hiding this comment.
Not fully sold we should have this constant here, but if we do the name should reflect what it does.
There was a problem hiding this comment.
I agree, it should just be a constant inside the similarNames function.
22c7b6c to
a32ad20
Compare
|
Rebased and made some tiny updates to the branch. |
a32ad20 to
bc799b1
Compare
libdevcore/StringUtils.cpp
Outdated
| using namespace std; | ||
| using namespace dev; | ||
|
|
||
| namespace dev |
There was a problem hiding this comment.
Style: Please don't use namespace regions in cpp files.
| size_t n1 = _name1.size(), n2 = _name2.size(); | ||
| vector<vector<size_t>> dp(n1 + 1, vector<size_t>(n2 + 1)); | ||
|
|
||
| // In this dp formulation of Damerau–Levenshtein distance we are assuming that the strings are 1-based to make base case storage easier. |
There was a problem hiding this comment.
This seems rather complicated compared to other implementations: https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
Especially the two-dimensional vector could be rather heap-heavy, especially given that this routine will be called on every identifier that is in scope.
There was a problem hiding this comment.
What is the license on the wikibook examples?
There was a problem hiding this comment.
@chriseth the linked example does not consider transpositions. e.g. for "test", "tset" would be considered as distance 2 (i.e. 2 substitution). I think this is a common typo so we should consider these as 1 distance.
There was a problem hiding this comment.
"Text is available under the Creative Commons Attribution-ShareAlike License.; additional terms may apply. By using this site, you agree to the Terms of Use and Privacy Policy."
but I'm not sure copyright and licensing actually applies to such small snippets.
There was a problem hiding this comment.
About the implementation, the implementation currently uses O(n1.n2) space. I will optimize it to O(n1) (or O(n2)) space. It will be different from the one in the wiki link as we will be accessing previous 2 entries. So will need a vector of size (3 * n).
I can also think of another (but ugly) optimization to avoid creating a vector of 3.n1 everytime. Fix the unidentified identifier as s1, so n1 will be same over all calls to the function. So, we can create a 3 * n1 vector once and pass it to the function.
I think we should do the 1st optimization but avoid the 2nd as it would affect generalization of the string distance function.
PS: I will do this and all the other small changes suggested here in a few hours.
libdevcore/StringUtils.cpp
Outdated
| } | ||
| } | ||
|
|
||
| size_t distance = dp[n1][n2]; |
There was a problem hiding this comment.
Could you factor out the distance calculation into its own function?
There was a problem hiding this comment.
Yes that is a good idea. I will:
- Only keep a distance function in StringUtils and remove this one.
- Compare the distance with MIN_EDIT_DISTANCE constant that will be declared in similarNames function.
|
|
||
| if (m_enclosingContainer) | ||
| { | ||
| vector<ASTString> enclosingSimilar = m_enclosingContainer->similarNames(_name); |
There was a problem hiding this comment.
We have an operator overload that allows similar += m_enclosingContainer->similarNames(_name);
| return result; | ||
| } | ||
|
|
||
| string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const |
There was a problem hiding this comment.
This could be a function in StringUtils called something like quotedAlternativesList.
|
|
||
| string NameAndTypeResolver::similarNameSuggestions(ASTString const& _name) const | ||
| { | ||
| return quotedAlternativesList(m_currentScope->similarNames(_name)); |
There was a problem hiding this comment.
Since this has been split into utils I think similarNameSuggestions should only return a vector and the formatting of the contents should be in ReferencesResolver.
There was a problem hiding this comment.
Please move the quotedAlternativeList part to the error message in ReferencesResolver. This method could be also placed into the header since it is a single line (though it is not necessary).
| if (declarations.empty()) | ||
| { | ||
| string const& suggestions = m_resolver.similarNameSuggestions(_identifier.name()); | ||
| string const& suggestions = quotedAlternativesList(m_resolver.similarNameSuggestions(_identifier.name())); |
There was a problem hiding this comment.
You cannot store this as a const&. I actually wonder why the compiler does not complain here...
|
Please use rebasing instead of merging, since it is impossible to review a merge commit. |
bded3e6 to
619c5e2
Compare
619c5e2 to
e3ac2dd
Compare
|
Rebased for review. |
|
@chriseth oh I think actually this was waiting for you to review. Can you review the updates? It shouldn't be too hard to finish this one. |
libdevcore/StringUtils.cpp
Outdated
|
|
||
| size_t dev::stringDistance(string const& _str1, string const& _str2) | ||
| { | ||
| size_t n1 = _str1.size(), n2 = _str2.size(); |
There was a problem hiding this comment.
only one declaration per line.
|
Fine part from minor things. I will rebase and fix those. |
e3ac2dd to
4ecdc51
Compare
|
@axic if tests are green, you can merge at will |
a2d93ce to
8df768d
Compare
|
Circle somehow fails since it cannot fetch the commit. Since travis is green, I would ignore it. |
8df768d to
31c3dd1
Compare
31c3dd1 to
1dcd7c5
Compare
I guess building from external pull requests doesn't properly work with circleci |
We can use the following method to compute alternatives:
For #3058.