patch 9.0.2076: Vim9: No support for type aliases
Problem: Vim9: No support for type aliases
Solution: Implement :type command
A type definition is giving a name to a type specification. This also known
type alias.
:type ListOfStrings = list<string>
The type alias can be used wherever a built-in type can be used. The type
alias name must start with an upper case character.
closes: #13407
Signed-off-by: Christian Brabandt <cb@256bit.org>
Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
diff --git a/src/vim9class.c b/src/vim9class.c
index a05dcce..0e8dc2d 100644
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -2095,12 +2095,119 @@
}
/*
- * Handle ":type".
+ * Type aliases (:type)
+ */
+
+ void
+typealias_free(typealias_T *ta)
+{
+ // ta->ta_type is freed in clear_type_list()
+ vim_free(ta->ta_name);
+ vim_free(ta);
+}
+
+ void
+typealias_unref(typealias_T *ta)
+{
+ if (ta != NULL && --ta->ta_refcount <= 0)
+ typealias_free(ta);
+}
+
+/*
+ * Handle ":type". Create an alias for a type specification.
*/
void
ex_type(exarg_T *eap UNUSED)
{
- // TODO
+ char_u *arg = eap->arg;
+
+ if (!current_script_is_vim9()
+ || (cmdmod.cmod_flags & CMOD_LEGACY)
+ || !getline_equal(eap->getline, eap->cookie, getsourceline))
+ {
+ emsg(_(e_type_can_only_be_defined_in_vim9_script));
+ return;
+ }
+
+ if (*arg == NUL)
+ {
+ emsg(_(e_missing_typealias_name));
+ return;
+ }
+
+ if (!ASCII_ISUPPER(*arg))
+ {
+ semsg(_(e_type_name_must_start_with_uppercase_letter_str), arg);
+ return;
+ }
+
+ char_u *name_end = find_name_end(arg, NULL, NULL, FNE_CHECK_START);
+ if (!IS_WHITE_OR_NUL(*name_end))
+ {
+ semsg(_(e_white_space_required_after_name_str), arg);
+ return;
+ }
+ char_u *name_start = arg;
+
+ arg = skipwhite(name_end);
+ if (*arg != '=')
+ {
+ semsg(_(e_missing_equal_str), arg);
+ return;
+ }
+ if (!IS_WHITE_OR_NUL(*(arg + 1)))
+ {
+ semsg(_(e_white_space_required_after_str_str), "=", arg);
+ return;
+ }
+ arg++;
+ arg = skipwhite(arg);
+
+ if (*arg == NUL)
+ {
+ emsg(_(e_missing_typealias_type));
+ return;
+ }
+
+ scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid);
+ type_T *type = parse_type(&arg, &si->sn_type_list, TRUE);
+ if (type == NULL)
+ return;
+
+ if (*arg != NUL)
+ {
+ // some text after the type
+ semsg(_(e_trailing_characters_str), arg);
+ return;
+ }
+
+ int cc = *name_end;
+ *name_end = NUL;
+
+ typval_T tv;
+ tv.v_type = VAR_UNKNOWN;
+ if (eval_variable_import(name_start, &tv) == OK)
+ {
+ if (tv.v_type == VAR_TYPEALIAS)
+ semsg(_(e_typealias_already_exists_for_str), name_start);
+ else
+ semsg(_(e_redefining_script_item_str), name_start);
+ clear_tv(&tv);
+ goto done;
+ }
+
+ // Add the user-defined type to the script-local variables.
+ tv.v_type = VAR_TYPEALIAS;
+ tv.v_lock = 0;
+ tv.vval.v_typealias = ALLOC_CLEAR_ONE(typealias_T);
+ ++tv.vval.v_typealias->ta_refcount;
+ tv.vval.v_typealias->ta_name = vim_strsave(name_start);
+ tv.vval.v_typealias->ta_type = type;
+ set_var_const(name_start, current_sctx.sc_sid, NULL, &tv, FALSE,
+ ASSIGN_CONST | ASSIGN_FINAL, 0);
+
+done:
+ *name_end = cc;
}
/*