diff options
-rw-r--r-- | bootstrap.conf | 3 | ||||
-rw-r--r-- | data/bison-default.css | 3 | ||||
-rw-r--r-- | lib/.gitignore | 5 | ||||
-rw-r--r-- | lib/glthread/.gitignore | 2 | ||||
-rw-r--r-- | m4/.gitignore | 5 | ||||
-rw-r--r-- | src/location.c | 2 | ||||
-rw-r--r-- | src/symtab.c | 56 | ||||
-rw-r--r-- | tests/diagnostics.at | 36 |
8 files changed, 95 insertions, 17 deletions
diff --git a/bootstrap.conf b/bootstrap.conf index 4f6ef94f..22816271 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -22,7 +22,8 @@ gnulib_modules=' calloc-posix close closeout config-h c-strcase configmake dirname - error extensions fdl fopen-safer + error extensions + fdl fopen-safer fstrcmp getopt-gnu gettext-h git-version-gen gitlog-to-changelog gpl-3.0 intprops inttypes isnan javacomp-script diff --git a/data/bison-default.css b/data/bison-default.css index 41304a2b..68df166a 100644 --- a/data/bison-default.css +++ b/data/bison-default.css @@ -21,7 +21,8 @@ .warning { color: purple; } .error { color: red; } .note { color: cyan; } -.insertion { color: green; } + +.fixit-insert { color: green; } /* Semantic values in Bison's own parser traces. */ .value { color: green; } diff --git a/lib/.gitignore b/lib/.gitignore index 0f007442..dc8934d5 100644 --- a/lib/.gitignore +++ b/lib/.gitignore @@ -53,6 +53,7 @@ /config.h /config.in.h /configmake.h +/diffseq.h /dirname-lgpl.c /dirname.c /dirname.h @@ -91,6 +92,8 @@ /fseterr.c /fseterr.h /fstat.c +/fstrcmp.c +/fstrcmp.h /fsync.c /getdtablesize.c /gethrxtime.c @@ -324,6 +327,8 @@ /windows-recmutex.h /windows-rwlock.c /windows-rwlock.h +/windows-tls.c +/windows-tls.h /xalloc-die.c /xalloc-oversized.h /xalloc.h diff --git a/lib/glthread/.gitignore b/lib/glthread/.gitignore index e0605e15..b854214e 100644 --- a/lib/glthread/.gitignore +++ b/lib/glthread/.gitignore @@ -1,3 +1,5 @@ /lock.c /lock.h /threadlib.c +/tls.c +/tls.h diff --git a/m4/.gitignore b/m4/.gitignore index 45f05270..f661f375 100644 --- a/m4/.gitignore +++ b/m4/.gitignore @@ -71,6 +71,8 @@ /iswblank.m4 /javacomp.m4 /javaexec.m4 +/jm-winsz1.m4 +/jm-winsz2.m4 /largefile.m4 /lcmessage.m4 /ldexp.m4 @@ -179,6 +181,7 @@ /threadlib.m4 /time_h.m4 /timespec.m4 +/tls.m4 /uintmax_t.m4 /unistd-safer.m4 /unistd_h.m4 @@ -202,5 +205,3 @@ /xalloc.m4 /xsize.m4 /xstrndup.m4 -/jm-winsz1.m4 -/jm-winsz2.m4 diff --git a/src/location.c b/src/location.c index b36f49d3..e6406bd6 100644 --- a/src/location.c +++ b/src/location.c @@ -473,7 +473,7 @@ location_caret (location loc, const char *style, FILE *out) void location_caret_suggestion (location loc, const char *s, FILE *out) { - const char *style = "insertion"; + const char *style = "fixit-insert"; fprintf (out, " | %*s", loc.start.column - 1 - caret_info.skip + (caret_info.skip ? 3 : 0), ""); diff --git a/src/symtab.c b/src/symtab.c index c7d308ac..b3642e67 100644 --- a/src/symtab.c +++ b/src/symtab.c @@ -24,6 +24,7 @@ #include "system.h" #include <assure.h> +#include <fstrcmp.h> #include <hash.h> #include "complain.h" @@ -32,6 +33,8 @@ #include "quote.h" +static struct hash_table *symbol_table = NULL; +static struct hash_table *semantic_type_table = NULL; /*----------------------------------------------------------------. | Symbols sorted by tag. Allocated by table_sort, after which no | @@ -41,6 +44,7 @@ static symbol **symbols_sorted = NULL; static semantic_type **semantic_types_sorted = NULL; + /*------------------------. | Distinguished symbols. | `------------------------*/ @@ -321,15 +325,54 @@ complain_class_redeclared (symbol *sym, symbol_class class, location second) } } +static const symbol * +symbol_from_uniqstr_fuzzy (const uniqstr key) +{ + aver (symbols_sorted); +#define FSTRCMP_THRESHOLD 0.6 + double best_similarity = FSTRCMP_THRESHOLD; + const symbol *res = NULL; + size_t count = hash_get_n_entries (symbol_table); + for (int i = 0; i < count; ++i) + { + symbol *sym = symbols_sorted[i]; + if (STRNEQ (key, sym->tag) + && (sym->content->status == declared + || sym->content->status == undeclared)) + { + double similarity = fstrcmp_bounded (key, sym->tag, best_similarity); + if (best_similarity < similarity) + { + res = sym; + best_similarity = similarity; + } + } + } + return res; +} + static void complain_symbol_undeclared (symbol *sym) { assert (sym->content->status != declared); - complain (&sym->location, - sym->content->status == needed ? complaint : Wother, - _("symbol %s is used, but is not defined as a token" - " and has no rules"), - quote (sym->tag)); + const symbol *best = symbol_from_uniqstr_fuzzy (sym->tag); + if (best) + { + complain (&sym->location, + sym->content->status == needed ? complaint : Wother, + _("symbol %s is used, but is not defined as a token" + " and has no rules; did you mean %s?"), + quote_n (0, sym->tag), + quote_n (1, best->tag)); + if (feature_flag & feature_caret) + location_caret_suggestion (sym->location, best->tag, stderr); + } + else + complain (&sym->location, + sym->content->status == needed ? complaint : Wother, + _("symbol %s is used, but is not defined as a token" + " and has no rules"), + quote (sym->tag)); } void @@ -694,9 +737,6 @@ symbol_translation (symbol *this) /* Initial capacity of symbol and semantic type hash table. */ #define HT_INITIAL_CAPACITY 257 -static struct hash_table *symbol_table = NULL; -static struct hash_table *semantic_type_table = NULL; - static inline bool hash_compare_symbol (const symbol *m1, const symbol *m2) { diff --git a/tests/diagnostics.at b/tests/diagnostics.at index 4042a815..bd01c15d 100644 --- a/tests/diagnostics.at +++ b/tests/diagnostics.at @@ -46,7 +46,7 @@ AT_DATA([experr], [$4]) AT_CHECK([LC_ALL=en_US.UTF-8 $5 bison -fcaret --color=debug -Wall input.y], [$3], [], [experr]) # When no style, same messages, but without style. -AT_CHECK([perl -pi -e 's{(</?\w+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr]) +AT_CHECK([perl -pi -e 's{(</?(-|\w)+>)}{ $[]1 eq "<tag>" ? $[]1 : "" }ge' experr]) # Cannot use AT_BISON_CHECK easily as we need to change the # environment. @@ -344,7 +344,7 @@ input.y:9.8-33: previous declaration input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>] 10 | <warning>%error-verbose</warning> | <warning>^~~~~~~~~~~~~~</warning> - | <insertion>%define parse.error verbose</insertion> + | <fixit-insert>%define parse.error verbose</fixit-insert> input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] ]], [[COLUMNS=200]]) @@ -377,7 +377,7 @@ input.y:9.8-33: previous declaration input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>] 10 | <warning>%error-verbose</warning> | <warning>^~~~~~~~~~~~~~</warning> - | <insertion>%define parse.error verbose</insertion> + | <fixit-insert>%define parse.error verbose</fixit-insert> input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] ]], [[COLUMNS=80]]) @@ -410,11 +410,39 @@ input.y:9.8-33: previous declaration input.y:10.56-69: <warning>warning:</warning> deprecated directive: '%error-verbose', use '%define parse.error verbose' [<warning>-Wdeprecated</warning>] 10 | ... <warning>%error-verbose</warning> | <warning>^~~~~~~~~~~~~~</warning> - | <insertion>%define parse.error verbose</insertion> + | <fixit-insert>%define parse.error verbose</fixit-insert> input.y: <warning>warning:</warning> fix-its can be applied. Rerun with option '--update'. [<warning>-Wother</warning>] ]], [[COLUMNS=60]]) + +## ------------- ## +## Suggestions. ## +## ------------- ## + +# Don't suggest to fix QUX with QUUX and QUUX with QUX... +AT_TEST([[Suggestions]], +[[%% +res: QUX baz +bar: QUUX +]], +[1], +[[input.y:11.6-9: <error>error:</error> symbol 'QUUX' is used, but is not defined as a token and has no rules + 11 | bar: <error>QUUX</error> + | <error>^~~~</error> +input.y:10.6-8: <error>error:</error> symbol 'QUX' is used, but is not defined as a token and has no rules + 10 | res: <error>QUX</error> baz + | <error>^~~</error> +input.y:10.10-12: <error>error:</error> symbol 'baz' is used, but is not defined as a token and has no rules; did you mean 'bar'? + 10 | res: QUX <error>baz</error> + | <error>^~~</error> + | <fixit-insert>bar</fixit-insert> +]]) + + + + + m4_popdef([AT_TEST]) |