diff options
author | Bernhard Reutner-Fischer <aldot@gcc.gnu.org> | 2017-10-19 09:24:33 +0200 |
---|---|---|
committer | Bernhard Reutner-Fischer <aldot@gcc.gnu.org> | 2017-10-19 09:24:33 +0200 |
commit | bcc478b9647e2af4b715fda6676d98f1e129d16b (patch) | |
tree | 78eb982a4151306d46381aacdf1b5298544bdac2 /gcc/fortran/symbol.c | |
parent | fba832054d9467a296d126754cc3a5efca707bdf (diff) | |
download | gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.zip gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.tar.gz gcc-bcc478b9647e2af4b715fda6676d98f1e129d16b.tar.bz2 |
Use Levenshtein spelling suggestions in Fortran FE
gcc/fortran/ChangeLog
2017-10-19 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
* gfortran.h (gfc_lookup_function_fuzzy): New declaration.
(gfc_closest_fuzzy_match): New declaration.
(vec_push): New definition.
* misc.c (gfc_closest_fuzzy_match): New definition.
* resolve.c: Include spellcheck.h.
(lookup_function_fuzzy_find_candidates): New static function.
(lookup_uop_fuzzy_find_candidates): Likewise.
(lookup_uop_fuzzy): Likewise.
(resolve_operator) <INTRINSIC_USER>: Call lookup_uop_fuzzy.
(gfc_lookup_function_fuzzy): New definition.
(resolve_unknown_f): Call gfc_lookup_function_fuzzy.
* interface.c (check_interface0): Likewise.
(lookup_arg_fuzzy_find_candidates): New static function.
(lookup_arg_fuzzy ): Likewise.
(compare_actual_formal): Call lookup_arg_fuzzy.
* symbol.c: Include spellcheck.h.
(lookup_symbol_fuzzy_find_candidates): New static function.
(lookup_symbol_fuzzy): Likewise.
(gfc_set_default_type): Call lookup_symbol_fuzzy.
(lookup_component_fuzzy_find_candidates): New static function.
(lookup_component_fuzzy): Likewise.
(gfc_find_component): Call lookup_component_fuzzy.
gcc/testsuite/ChangeLog
2017-10-19 Bernhard Reutner-Fischer <aldot@gcc.gnu.org>
* gfortran.dg/spellcheck-operator.f90: New testcase.
* gfortran.dg/spellcheck-procedure_1.f90: New testcase.
* gfortran.dg/spellcheck-procedure_2.f90: New testcase.
* gfortran.dg/spellcheck-structure.f90: New testcase.
* gfortran.dg/spellcheck-parameter.f90: New testcase.
From-SVN: r253877
Diffstat (limited to 'gcc/fortran/symbol.c')
-rw-r--r-- | gcc/fortran/symbol.c | 86 |
1 files changed, 82 insertions, 4 deletions
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 4c109fd..36abba5 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -245,6 +245,44 @@ gfc_get_default_type (const char *name, gfc_namespace *ns) } +/* Recursively append candidate SYM to CANDIDATES. Store the number of + candidates in CANDIDATES_LEN. */ + +static void +lookup_symbol_fuzzy_find_candidates (gfc_symtree *sym, + char **&candidates, + size_t &candidates_len) +{ + gfc_symtree *p; + + if (sym == NULL) + return; + + if (sym->n.sym->ts.type != BT_UNKNOWN && sym->n.sym->ts.type != BT_PROCEDURE) + vec_push (candidates, candidates_len, sym->name); + p = sym->left; + if (p) + lookup_symbol_fuzzy_find_candidates (p, candidates, candidates_len); + + p = sym->right; + if (p) + lookup_symbol_fuzzy_find_candidates (p, candidates, candidates_len); +} + + +/* Lookup symbol SYM_NAME fuzzily, taking names in SYMBOL into account. */ + +static const char* +lookup_symbol_fuzzy (const char *sym_name, gfc_symbol *symbol) +{ + char **candidates = NULL; + size_t candidates_len = 0; + lookup_symbol_fuzzy_find_candidates (symbol->ns->sym_root, candidates, + candidates_len); + return gfc_closest_fuzzy_match (sym_name, candidates); +} + + /* Given a pointer to a symbol, set its type according to the first letter of its name. Fails if the letter in question has no default type. */ @@ -263,8 +301,14 @@ gfc_set_default_type (gfc_symbol *sym, int error_flag, gfc_namespace *ns) { if (error_flag && !sym->attr.untyped) { - gfc_error ("Symbol %qs at %L has no IMPLICIT type", - sym->name, &sym->declared_at); + const char *guessed = lookup_symbol_fuzzy (sym->name, sym); + if (guessed) + gfc_error ("Symbol %qs at %L has no IMPLICIT type" + "; did you mean %qs?", + sym->name, &sym->declared_at, guessed); + else + gfc_error ("Symbol %qs at %L has no IMPLICIT type", + sym->name, &sym->declared_at); sym->attr.untyped = 1; /* Ensure we only give an error once. */ } @@ -2336,6 +2380,32 @@ find_union_component (gfc_symbol *un, const char *name, } +/* Recursively append candidate COMPONENT structures to CANDIDATES. Store + the number of total candidates in CANDIDATES_LEN. */ + +static void +lookup_component_fuzzy_find_candidates (gfc_component *component, + char **&candidates, + size_t &candidates_len) +{ + for (gfc_component *p = component; p; p = p->next) + vec_push (candidates, candidates_len, p->name); +} + + +/* Lookup component MEMBER fuzzily, taking names in COMPONENT into account. */ + +static const char* +lookup_component_fuzzy (const char *member, gfc_component *component) +{ + char **candidates = NULL; + size_t candidates_len = 0; + lookup_component_fuzzy_find_candidates (component, candidates, + candidates_len); + return gfc_closest_fuzzy_match (member, candidates); +} + + /* Given a derived type node and a component name, try to locate the component structure. Returns the NULL pointer if the component is not found or the components are private. If noaccess is set, no access @@ -2433,8 +2503,16 @@ gfc_find_component (gfc_symbol *sym, const char *name, } if (p == NULL && !silent) - gfc_error ("%qs at %C is not a member of the %qs structure", - name, sym->name); + { + const char *guessed = lookup_component_fuzzy (name, sym->components); + if (guessed) + gfc_error ("%qs at %C is not a member of the %qs structure" + "; did you mean %qs?", + name, sym->name, guessed); + else + gfc_error ("%qs at %C is not a member of the %qs structure", + name, sym->name); + } /* Component was found; build the ultimate component reference. */ if (p != NULL && ref) |