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
Suggest alternatives when identifier not found. Closes #3058. #3147
Changes from all commits
2859834
b1417b3
d123e77
8a491c7
dc0a25f
12c3eb8
5747985
1dcd7c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
This file is part of solidity. | ||
|
||
solidity is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
|
||
solidity is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with solidity. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
/** @file StringUtils.h | ||
* @author Balajiganapathi S <balajiganapathi.s@gmail.com> | ||
* @date 2017 | ||
* | ||
* String routines | ||
*/ | ||
|
||
#include "StringUtils.h" | ||
#include <algorithm> | ||
#include <string> | ||
#include <vector> | ||
|
||
using namespace std; | ||
using namespace dev; | ||
|
||
bool dev::stringWithinDistance(string const& _str1, string const& _str2, size_t _maxDistance) | ||
{ | ||
if (_str1 == _str2) | ||
return true; | ||
|
||
size_t n1 = _str1.size(); | ||
size_t n2 = _str2.size(); | ||
size_t distance = stringDistance(_str1, _str2); | ||
|
||
// if distance is not greater than _maxDistance, and distance is strictly less than length of both names, they can be considered similar | ||
// this is to avoid irrelevant suggestions | ||
return distance <= _maxDistance && distance < n1 && distance < n2; | ||
} | ||
|
||
size_t dev::stringDistance(string const& _str1, string const& _str2) | ||
{ | ||
size_t n1 = _str1.size(); | ||
size_t n2 = _str2.size(); | ||
// Optimize by storing only last 2 rows and current row. So first index is considered modulo 3 | ||
// This is a two-dimensional array of size 3 x (n2 + 1). | ||
vector<size_t> dp(3 * (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. | ||
// So index accesser to _name1 and _name2 have to be adjusted accordingly | ||
for (size_t i1 = 0; i1 <= n1; ++i1) | ||
for (size_t i2 = 0; i2 <= n2; ++i2) | ||
{ | ||
size_t x = 0; | ||
if (min(i1, i2) == 0) // base case | ||
x = max(i1, i2); | ||
else | ||
{ | ||
size_t left = dp[(i1 - 1) % 3 + i2 * 3]; | ||
size_t up = dp[(i1 % 3) + (i2 - 1) * 3]; | ||
size_t upleft = dp[((i1 - 1) % 3) + (i2 - 1) * 3]; | ||
// deletion and insertion | ||
x = min(left + 1, up + 1); | ||
if (_str1[i1-1] == _str2[i2-1]) | ||
// same chars, can skip | ||
x = min(x, upleft); | ||
else | ||
// different chars so try substitution | ||
x = min(x, upleft + 1); | ||
|
||
// transposing | ||
if (i1 > 1 && i2 > 1 && _str1[i1 - 1] == _str2[i2 - 2] && _str1[i1 - 2] == _str2[i2 - 1]) | ||
x = min(x, dp[((i1 - 2) % 3) + (i2 - 2) * 3] + 1); | ||
} | ||
dp[(i1 % 3) + i2 * 3] = x; | ||
} | ||
|
||
return dp[(n1 % 3) + n2 * 3]; | ||
} | ||
|
||
string dev::quotedAlternativesList(vector<string> const& suggestions) | ||
{ | ||
if (suggestions.empty()) | ||
return ""; | ||
if (suggestions.size() == 1) | ||
return "\"" + suggestions.front() + "\""; | ||
|
||
string choices = "\"" + suggestions.front() + "\""; | ||
for (size_t i = 1; i + 1 < suggestions.size(); ++i) | ||
choices += ", \"" + suggestions[i] + "\""; | ||
|
||
choices += " or \"" + suggestions.back() + "\""; | ||
|
||
return choices; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/* | ||
This file is part of solidity. | ||
|
||
solidity is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
|
||
solidity is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with solidity. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
/** @file StringUtils.h | ||
* @author Balajiganapathi S <balajiganapathi.s@gmail.com> | ||
* @date 2017 | ||
* | ||
* String routines | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
namespace dev | ||
{ | ||
|
||
// Calculates the Damerau–Levenshtein distance between _str1 and _str2 and returns true if that distance is not greater than _maxDistance | ||
bool stringWithinDistance(std::string const& _str1, std::string const& _str2, size_t _maxDistance); | ||
// Calculates the Damerau–Levenshtein distance between _str1 and _str2 | ||
size_t stringDistance(std::string const& _str1, std::string const& _str2); | ||
// Return a string having elements of suggestions as quoted, alternative suggestions. e.g. "a", "b" or "c" | ||
std::string quotedAlternativesList(std::vector<std::string> const& suggestions); | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
This file is part of solidity. | ||
|
||
solidity is free software: you can redistribute it and/or modify | ||
it under the terms of the GNU General Public License as published by | ||
the Free Software Foundation, either version 3 of the License, or | ||
(at your option) any later version. | ||
|
||
solidity is distributed in the hope that it will be useful, | ||
but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
GNU General Public License for more details. | ||
|
||
You should have received a copy of the GNU General Public License | ||
along with solidity. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
/** | ||
* Unit tests for the StringUtils routines. | ||
*/ | ||
|
||
#include <libdevcore/StringUtils.h> | ||
|
||
#include "../TestHelper.h" | ||
|
||
using namespace std; | ||
|
||
namespace dev | ||
{ | ||
namespace test | ||
{ | ||
|
||
BOOST_AUTO_TEST_SUITE(StringUtils) | ||
|
||
BOOST_AUTO_TEST_CASE(test_similarity) | ||
{ | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hello", 0), true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the tests here would also profit greatly from a separate distance function. |
||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hello", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hellw", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "helol", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "helo", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "helllo", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hlllo", 1), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hllllo", 1), false); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hllllo", 2), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("hello", "hlllo", 2), true); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("a", "", 2), false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be distance 1? |
||
BOOST_CHECK_EQUAL(stringWithinDistance("abc", "ba", 2), false); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("abc", "abcdef", 2), false); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("abcd", "wxyz", 2), false); | ||
BOOST_CHECK_EQUAL(stringWithinDistance("", "", 2), true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't this be distance 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method checks if it is |
||
} | ||
|
||
BOOST_AUTO_TEST_CASE(test_dldistance) | ||
{ | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "hellw"), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "helol"), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "helo"), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "helllo"), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "hlllo"), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("hello", "hllllo"), 2); | ||
BOOST_CHECK_EQUAL(stringDistance("a", ""), 1); | ||
BOOST_CHECK_EQUAL(stringDistance("abc", "ba"), 2); | ||
BOOST_CHECK_EQUAL(stringDistance("abc", "abcdef"), 3); | ||
BOOST_CHECK_EQUAL(stringDistance("abcd", "wxyz"), 4); | ||
BOOST_CHECK_EQUAL(stringDistance("", ""), 0); | ||
BOOST_CHECK_EQUAL(stringDistance("abcdefghijklmnopqrstuvwxyz", "abcabcabcabcabcabcabcabca"), 23); | ||
|
||
} | ||
|
||
BOOST_AUTO_TEST_CASE(test_alternatives_list) | ||
{ | ||
vector<string> strings; | ||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), ""); | ||
strings.push_back("a"); | ||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\""); | ||
strings.push_back("b"); | ||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\" or \"b\""); | ||
strings.push_back("c"); | ||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\" or \"c\""); | ||
strings.push_back("d"); | ||
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\", \"c\" or \"d\""); | ||
} | ||
|
||
|
||
BOOST_AUTO_TEST_SUITE_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.
This could be a function in
StringUtils
called something likequotedAlternativesList
.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.
Done.