8017611: Auto corrector for mistyped vm options

The auto corrector for mistyped vm options fuzzy-matches existing flags based on string similarity (Dice's coefficient).

Reviewed-by: kvn, dsamersoff, hseigel, johnc
This commit is contained in:
Tao Mao 2013-06-28 20:18:04 -07:00
parent f93ee2a9dd
commit 7109e85e43
4 changed files with 128 additions and 4 deletions

View file

@ -276,14 +276,14 @@ static Flag flagTable[] = {
Flag* Flag::flags = flagTable;
size_t Flag::numFlags = (sizeof(flagTable) / sizeof(Flag));
inline bool str_equal(const char* s, char* q, size_t len) {
inline bool str_equal(const char* s, const char* q, size_t len) {
// s is null terminated, q is not!
if (strlen(s) != (unsigned int) len) return false;
return strncmp(s, q, len) == 0;
}
// Search the flag table for a named flag
Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) {
Flag* Flag::find_flag(const char* name, size_t length, bool allow_locked) {
for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
if (str_equal(current->name, name, length)) {
// Found a matching entry. Report locked flags only if allowed.
@ -301,6 +301,52 @@ Flag* Flag::find_flag(char* name, size_t length, bool allow_locked) {
return NULL;
}
// Compute string similarity based on Dice's coefficient
static float str_similar(const char* str1, const char* str2, size_t len2) {
int len1 = (int) strlen(str1);
int total = len1 + (int) len2;
int hit = 0;
for (int i = 0; i < len1 -1; ++i) {
for (int j = 0; j < (int) len2 -1; ++j) {
if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) {
++hit;
break;
}
}
}
return 2.0f * (float) hit / (float) total;
}
Flag* Flag::fuzzy_match(const char* name, size_t length, bool allow_locked) {
float VMOptionsFuzzyMatchSimilarity = 0.7f;
Flag* match = NULL;
float score;
float max_score = -1;
for (Flag* current = &flagTable[0]; current->name != NULL; current++) {
score = str_similar(current->name, name, length);
if (score > max_score) {
max_score = score;
match = current;
}
}
if (!(match->is_unlocked() || match->is_unlocker())) {
if (!allow_locked) {
return NULL;
}
}
if (max_score < VMOptionsFuzzyMatchSimilarity) {
return NULL;
}
return match;
}
// Returns the address of the index'th element
static Flag* address_of_flag(CommandLineFlagWithType flag) {
assert((size_t)flag < Flag::numFlags, "bad command line flag index");