From 20df2994ed4afc3a2c9b5a3dc319de08fe9781dd Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Astor?= Date: Mon, 9 Aug 2021 14:25:25 +0200 Subject: [PATCH] :art: Add did you mean for traits --- include/env/nspc.h | 1 + include/env/trait.h | 1 + src/parse/check_traits.c | 4 ++-- src/parse/did_you_mean.c | 31 +++++++++++++++++++++++++++---- src/parse/scan0.c | 9 +++++++-- 5 files changed, 38 insertions(+), 8 deletions(-) diff --git a/include/env/nspc.h b/include/env/nspc.h index dc590f69..920c3cb8 100644 --- a/include/env/nspc.h +++ b/include/env/nspc.h @@ -70,6 +70,7 @@ describe_nspc_func(Value, value) describe_nspc_func(Type, type) /* howere there is no need for lookup_func0, push_func, pop_func */ ANN void did_you_mean_nspc(const Nspc, const char *); ANN void did_you_mean_type(const Type, const char *); +ANN void did_you_mean_trait(Nspc nspc, const char *name); #define DID_YOU_MEAN_LIMIT 128 #define did_you_mean_nspc(a, b) \ diff --git a/include/env/trait.h b/include/env/trait.h index a479a020..7a1fea48 100644 --- a/include/env/trait.h +++ b/include/env/trait.h @@ -4,6 +4,7 @@ typedef struct Trait_ { struct Vector_ requested_values; struct Vector_ requested_funcs; + m_str name; m_str filename; loc_t loc; } * Trait; diff --git a/src/parse/check_traits.c b/src/parse/check_traits.c index 3b7b6c81..5f7b653b 100644 --- a/src/parse/check_traits.c +++ b/src/parse/check_traits.c @@ -124,8 +124,8 @@ ANN bool check_trait_requests(const Env env, const Type t, const ID_List list) { gwerr_secondary("duplicated trait", trait->filename, trait->loc); return false; } - const bool value_error = check_trait_variables(env, t, trait); - const bool funcs_error = check_trait_functions(env, t, trait); + const bool value_error = trait->requested_values.ptr ? check_trait_variables(env, t, trait) : false; + const bool funcs_error = trait->requested_funcs.ptr ? check_trait_functions(env, t, trait) : false; if (!value_error && !funcs_error) return true; const Value request = (Value)vector_front(&trait->requested_values); gwerr_secondary("from trait", request->from->filename, trait->loc); diff --git a/src/parse/did_you_mean.c b/src/parse/did_you_mean.c index dbce28b2..4f8fd219 100644 --- a/src/parse/did_you_mean.c +++ b/src/parse/did_you_mean.c @@ -29,9 +29,9 @@ static m_bool wagner_fisher(const char *s, const char *t) { return (i && j && d[m - 1][n - 1] < MAX_DISTANCE); } -ANN static void ressembles(const Nspc nspc, const char *name, +ANN static void ressembles(const Scope scope, const char *name, bool *const done) { - struct scope_iter iter = {nspc->info->value, 0, 0}; + struct scope_iter iter = { scope, 0, 0 }; Value value; while (scope_iter(&iter, &value) > 0) { if (wagner_fisher(name, value->name)) { @@ -44,6 +44,22 @@ ANN static void ressembles(const Nspc nspc, const char *name, } } +ANN static void trait_ressembles(const Scope scope, const char *name, + bool *const done) { + struct scope_iter iter = { scope, 0, 0 }; + Trait trait; + while (scope_iter(&iter, &trait) > 0) { + if (wagner_fisher(name, trait->name)) { + if (!*done) { + *done = true; + gw_err("{-/}did you mean{0}:\n"); + } + if (trait->filename) // TODO: check why is that from check + gwerr_secondary(_("defined here"), trait->filename, trait->loc); + } + } +} + #define MAX_NAME_LEN 16 #define CHECK_LEN(name) \ if (strlen(name) > MAX_NAME_LEN) return; @@ -52,7 +68,7 @@ ANN static void ressembles(const Nspc nspc, const char *name, ANN void did_you_mean_nspc(Nspc nspc, const char *name) { CHECK_LEN(name) bool done = false; - do ressembles(nspc, name, &done); + do ressembles(nspc->info->value, name, &done); while ((nspc = nspc->parent)); } @@ -60,6 +76,13 @@ ANN void did_you_mean_nspc(Nspc nspc, const char *name) { ANN void did_you_mean_type(Type type, const char *name) { CHECK_LEN(name) bool done = false; - do ressembles(type->nspc, name, &done); + do ressembles(type->nspc->info->value, name, &done); while ((type = type->info->parent) && type->nspc); } + +ANN void did_you_mean_trait(Nspc nspc, const char *name) { + CHECK_LEN(name) + bool done = false; + do trait_ressembles(nspc->info->trait, name, &done); + while ((nspc = nspc->parent)); +} diff --git a/src/parse/scan0.c b/src/parse/scan0.c index 7c3adeda..7cdfa37d 100644 --- a/src/parse/scan0.c +++ b/src/parse/scan0.c @@ -318,8 +318,12 @@ ANN static Type cdef_parent(const Env env, const Class_Def cdef) { ANN static m_bool find_traits(const Env env, ID_List traits, const loc_t pos) { do { - if (!nspc_lookup_trait1(env->curr, traits->xid)) - ERR_B(pos, _("can't find trait")); + if (!nspc_lookup_trait1(env->curr, traits->xid)) { + gwerr_basic(_("can't find trait"), NULL, NULL, env->name, pos, 0); + did_you_mean_trait(env->curr, s_name(traits->xid)); + env->context->error = true; + return GW_ERROR; + } } while ((traits = traits->next)); return GW_OK; } @@ -435,6 +439,7 @@ ANN static m_bool scan0_extend_def(const Env env, const Extend_Def xdef) { ANN static m_bool _scan0_trait_def(const Env env, const Trait_Def pdef) { const Trait trait = new_trait(env->gwion->mp, pdef->pos); trait->loc = pdef->pos; + trait->name = s_name(pdef->xid); trait->filename = env->name; nspc_add_trait(env->curr, pdef->xid, trait); Ast ast = pdef->body; -- 2.43.0