diff --git a/include/lang/types.h b/include/lang/types.h index 53914e185..574b5e0df 100644 --- a/include/lang/types.h +++ b/include/lang/types.h @@ -28,6 +28,7 @@ struct args_kw { uint32_t node; bool set; bool required; + bool extension; }; enum language_mode { diff --git a/src/functions/environment.c b/src/functions/environment.c index 00767562a..1a99a766c 100644 --- a/src/functions/environment.c +++ b/src/functions/environment.c @@ -180,7 +180,10 @@ func_environment_prepend(struct workspace *wk, obj self, obj *res) static bool func_environment_unset(struct workspace *wk, obj self, obj *res) { - struct args_norm an[] = { { obj_string }, ARG_TYPE_NULL }; + struct args_norm an[] = { + { obj_string, .desc = "The name to unset" }, + ARG_TYPE_NULL, + }; if (!pop_args(wk, an, 0)) { return false; } diff --git a/src/functions/kernel.c b/src/functions/kernel.c index 03e16bc4f..9268df3a8 100644 --- a/src/functions/kernel.c +++ b/src/functions/kernel.c @@ -171,7 +171,10 @@ func_project(struct workspace *wk, obj _, obj *res) [kw_license_files] = { "license_files", TYPE_TAG_LISTIFY | obj_string }, [kw_meson_version] = { "meson_version", obj_string }, [kw_subproject_dir] = { "subproject_dir", obj_string }, - [kw_module_dir] = { "module_dir", obj_string }, + [kw_module_dir] = { "module_dir", + obj_string, + .desc = "Specify a directory to search for .meson files in when import()-ing modules", + .extension = true }, [kw_version] = { "version", tc_string | tc_file }, 0, }; @@ -495,7 +498,10 @@ func_add_languages(struct workspace *wk, obj _, obj *res) struct args_kw akw[] = { [kw_required] = { "required", tc_required_kw }, [kw_native] = { "native", obj_bool }, - [kw_toolchain] = { "toolchain", tc_compiler }, + [kw_toolchain] = { "toolchain", + tc_compiler, + .desc = "Instead of detecting a toolchain, use the compiler `toolchain` for this language.", + .extension = true }, 0, }; @@ -517,7 +523,13 @@ func_add_languages(struct workspace *wk, obj _, obj *res) if (!akw[kw_native].set) { bool _missing = false; - if (!add_languages(wk, an[0].node, an[0].val, akw[kw_toolchain].val, machine_kind_build, requirement_auto, &_missing)) { + if (!add_languages(wk, + an[0].node, + an[0].val, + akw[kw_toolchain].val, + machine_kind_build, + requirement_auto, + &_missing)) { return false; } } diff --git a/src/functions/kernel/dependency.c b/src/functions/kernel/dependency.c index bcd954952..93eb7d796 100644 --- a/src/functions/kernel/dependency.c +++ b/src/functions/kernel/dependency.c @@ -692,9 +692,13 @@ func_dependency(struct workspace *wk, obj self, obj *res) [kw_native] = { "native", obj_bool }, [kw_version] = { "version", TYPE_TAG_LISTIFY | obj_string }, [kw_static] = { "static", obj_bool }, - [kw_modules] = { "modules", TYPE_TAG_LISTIFY | obj_string }, - [kw_optional_modules] = { "optional_modules", TYPE_TAG_LISTIFY | obj_string }, - [kw_components] = { "components", TYPE_TAG_LISTIFY | obj_string }, + [kw_modules] = { + "modules", + TYPE_TAG_LISTIFY | obj_string, + .desc = "A list of sub-dependencies for this dependency. Only supported by certain dependencies.", + }, + [kw_optional_modules] = { "optional_modules", TYPE_TAG_LISTIFY | obj_string, .desc = "Ignored" }, + [kw_components] = { "components", TYPE_TAG_LISTIFY | obj_string, .desc = "Ignored" }, [kw_fallback] = { "fallback", TYPE_TAG_LISTIFY | obj_string }, [kw_allow_fallback] = { "allow_fallback", obj_bool }, [kw_default_options] = { "default_options", wk->complex_types.options_dict_or_list }, diff --git a/src/functions/modules/fs.c b/src/functions/modules/fs.c index f57dae7a7..46bacfc4a 100644 --- a/src/functions/modules/fs.c +++ b/src/functions/modules/fs.c @@ -541,23 +541,23 @@ func_module_fs_relative_to(struct workspace *wk, obj self, obj *res) } const struct func_impl impl_tbl_module_fs[] = { - { "as_posix", func_module_fs_as_posix, tc_string, true }, - { "copyfile", func_module_fs_copyfile, tc_custom_target }, - { "exists", func_module_fs_exists, tc_bool }, - { "expanduser", func_module_fs_expanduser, tc_string }, - { "hash", func_module_fs_hash, tc_string }, - { "is_absolute", func_module_fs_is_absolute, tc_bool, true }, - { "is_dir", func_module_fs_is_dir, tc_bool }, - { "is_file", func_module_fs_is_file, tc_bool }, - { "is_samepath", func_module_fs_is_samepath, tc_bool }, - { "is_symlink", func_module_fs_is_symlink, tc_bool }, - { "name", func_module_fs_name, tc_string, true }, - { "parent", func_module_fs_parent, tc_string, true }, - { "read", func_module_fs_read, tc_string }, - { "relative_to", func_module_fs_relative_to, tc_string, true }, - { "replace_suffix", func_module_fs_replace_suffix, tc_string, true }, - { "size", func_module_fs_size, tc_number }, - { "stem", func_module_fs_stem, tc_string, true }, + { "as_posix", func_module_fs_as_posix, tc_string, true, .desc = "Convert backslashes to `/`" }, + { "copyfile", func_module_fs_copyfile, tc_custom_target, .desc = "Creates a custom target that copies a file at build time" }, + { "exists", func_module_fs_exists, tc_bool, .desc = "Check if a file or directory exists" }, + { "expanduser", func_module_fs_expanduser, tc_string, .desc = "Expand a path that starts with a ~ into an absolute path" }, + { "hash", func_module_fs_hash, tc_string, .desc = "Calculate the content hash of a file" }, + { "is_absolute", func_module_fs_is_absolute, tc_bool, true, .desc = "Check if a path is absolute" }, + { "is_dir", func_module_fs_is_dir, tc_bool, .desc = "Check if a directory exists" }, + { "is_file", func_module_fs_is_file, tc_bool, .desc = "Check if a file exists" }, + { "is_samepath", func_module_fs_is_samepath, tc_bool, .desc = "Check if two paths point to the same object" }, + { "is_symlink", func_module_fs_is_symlink, tc_bool, .desc = "Check if a symlink exists" }, + { "name", func_module_fs_name, tc_string, true, .desc = "Get the basename of a path" }, + { "parent", func_module_fs_parent, tc_string, true, .desc = "Get the dirname of a path" }, + { "read", func_module_fs_read, tc_string, .desc = "Read a file from disk" }, + { "relative_to", func_module_fs_relative_to, tc_string, true, .desc = "Get a path relative to another path" }, + { "replace_suffix", func_module_fs_replace_suffix, tc_string, true, .desc = "Replace a path's suffix" }, + { "size", func_module_fs_size, tc_number, .desc = "Get a file's size in bytes" }, + { "stem", func_module_fs_stem, tc_string, true, .desc = "Get the basename of a path with its extension removed" }, { NULL, NULL }, }; @@ -998,24 +998,24 @@ const struct func_impl impl_tbl_module_fs_internal[] = { { "name", func_module_fs_name, tc_string, true }, { "parent", func_module_fs_parent, tc_string, true }, { "read", func_module_fs_read, tc_string }, + { "relative_to", func_module_fs_relative_to, tc_string, true }, { "replace_suffix", func_module_fs_replace_suffix, tc_string, true }, { "size", func_module_fs_size, tc_number }, { "stem", func_module_fs_stem, tc_string, true }, // non-standard muon extensions - { "add_suffix", func_module_fs_add_suffix, tc_string, true }, - { "copy", func_module_fs_copy, .fuzz_unsafe = true }, - { "cwd", func_module_fs_cwd, tc_string }, - { "executable", func_module_fs_executable, tc_string, true }, - { "glob", func_module_fs_glob, tc_array }, - { "is_basename", func_module_fs_is_basename, tc_bool, true }, - { "is_subpath", func_module_fs_is_subpath, tc_bool, true }, - { "make_absolute", func_module_fs_make_absolute, tc_string }, - { "mkdir", func_module_fs_mkdir, .fuzz_unsafe = true }, - { "relative_to", func_module_fs_relative_to, tc_string, true }, - { "rmdir", func_module_fs_rmdir, .fuzz_unsafe = true }, - { "without_ext", func_module_fs_without_ext, tc_string, true }, - { "write", func_module_fs_write, .fuzz_unsafe = true }, - { "delete_with_suffix", func_module_fs_delete_with_suffix }, - { "canonicalize", func_module_fs_canonicalize, tc_string, true }, + { "add_suffix", func_module_fs_add_suffix, tc_string, true, .desc = "Append a suffix to a path" }, + { "copy", func_module_fs_copy, .fuzz_unsafe = true, .desc = "Copy a file to a destination at configure time" }, + { "cwd", func_module_fs_cwd, tc_string, .desc = "Return the muon's current working directory" }, + { "executable", func_module_fs_executable, tc_string, true, .desc = "Prepend ./ to a path if it is a basename" }, + { "glob", func_module_fs_glob, tc_array, .desc = "Gather a list of files matching a glob expression" }, + { "is_basename", func_module_fs_is_basename, tc_bool, true, .desc = "Check if a path is a basename" }, + { "is_subpath", func_module_fs_is_subpath, tc_bool, true, .desc = "Check if a path is a subpath of another path" }, + { "make_absolute", func_module_fs_make_absolute, tc_string, .desc = "Make a path absolute by prepending the current working directory" }, + { "mkdir", func_module_fs_mkdir, .fuzz_unsafe = true, .desc = "Create a directory" }, + { "rmdir", func_module_fs_rmdir, .fuzz_unsafe = true, .desc = "Remove a directory" }, + { "without_ext", func_module_fs_without_ext, tc_string, true, .desc = "Get a path with its extension removed" }, + { "write", func_module_fs_write, .fuzz_unsafe = true, .desc = "Write a file" }, + { "delete_with_suffix", func_module_fs_delete_with_suffix, .desc = "Recursively delete all files with a matching suffix" }, + { "canonicalize", func_module_fs_canonicalize, tc_string, true, .desc = "Make a path absolute and replace .." }, { NULL, NULL }, }; diff --git a/src/functions/modules/subprojects.c b/src/functions/modules/subprojects.c index 4ebed21c7..c8516d76e 100644 --- a/src/functions/modules/subprojects.c +++ b/src/functions/modules/subprojects.c @@ -112,7 +112,10 @@ func_subprojects_update_iter(struct workspace *wk, struct subprojects_common_ctx static bool func_subprojects_update(struct workspace *wk, obj self, obj *res) { - struct args_norm an[] = { { TYPE_TAG_LISTIFY | tc_string, .optional = true }, ARG_TYPE_NULL }; + struct args_norm an[] = { + { TYPE_TAG_LISTIFY | tc_string, .optional = true, .desc = "A list of subprojects to operate on." }, + ARG_TYPE_NULL, + }; if (!pop_args(wk, an, 0)) { return false; @@ -185,12 +188,15 @@ subprojects_list_iter(struct workspace *wk, struct subprojects_common_ctx *ctx, static bool func_subprojects_list(struct workspace *wk, obj self, obj *res) { - struct args_norm an[] = { { TYPE_TAG_LISTIFY | tc_string, .optional = true }, ARG_TYPE_NULL }; + struct args_norm an[] = { + { TYPE_TAG_LISTIFY | tc_string, .optional = true, .desc = "A list of subprojects to operate on." }, + ARG_TYPE_NULL, + }; enum kwargs { kw_print, }; struct args_kw akw[] = { - [kw_print] = { "print", tc_bool }, + [kw_print] = { "print", tc_bool, .desc = "Print out a formatted list of subprojects as well as returning it." }, 0, }; @@ -241,12 +247,15 @@ subprojects_clean_iter(struct workspace *wk, struct subprojects_common_ctx *ctx, static bool func_subprojects_clean(struct workspace *wk, obj self, obj *res) { - struct args_norm an[] = { { TYPE_TAG_LISTIFY | tc_string, .optional = true }, ARG_TYPE_NULL }; + struct args_norm an[] = { + { TYPE_TAG_LISTIFY | tc_string, .optional = true, .desc = "A list of subprojects to operate on." }, + ARG_TYPE_NULL, + }; enum kwargs { kw_force, }; struct args_kw akw[] = { - [kw_force] = { "force", tc_bool }, + [kw_force] = { "force", tc_bool, .desc = "Force the operation." }, 0, }; @@ -265,8 +274,12 @@ func_subprojects_clean(struct workspace *wk, obj self, obj *res) } const struct func_impl impl_tbl_module_subprojects[] = { - { "update", func_subprojects_update, .fuzz_unsafe = true }, - { "list", func_subprojects_list, .fuzz_unsafe = true }, - { "clean", func_subprojects_clean, .fuzz_unsafe = true }, + { "update", func_subprojects_update, .fuzz_unsafe = true, .desc = "Update subprojects with .wrap files" }, + { "list", + func_subprojects_list, + tc_array, + .fuzz_unsafe = true, + .desc = "List subprojects with .wrap files and their status." }, + { "clean", func_subprojects_clean, .fuzz_unsafe = true, .desc = "Clean wrap-git subprojects" }, { NULL, NULL }, }; diff --git a/src/functions/modules/toolchain.c b/src/functions/modules/toolchain.c index fb3a2ecee..cae828571 100644 --- a/src/functions/modules/toolchain.c +++ b/src/functions/modules/toolchain.c @@ -19,10 +19,19 @@ func_module_toolchain_create(struct workspace *wk, obj self, obj *res) kw_inherit_static_linker, }; struct args_kw akw[] = { - [kw_inherit] = { "inherit", tc_string | tc_compiler }, - [kw_inherit_compiler] = { "inherit_compiler", tc_string | tc_compiler }, - [kw_inherit_linker] = { "inherit_linker", tc_string | tc_compiler }, - [kw_inherit_static_linker] = { "inherit_static_linker", tc_string | tc_compiler }, + [kw_inherit] = { "inherit", tc_compiler, .desc = "A toolchain to inherit from" }, + [kw_inherit_compiler] = { "inherit_compiler", + tc_string | tc_compiler, + .desc + = "The compiler component to inherit from. Can be either a compiler object or compiler type name." }, + [kw_inherit_linker] = { "inherit_linker", + tc_string | tc_compiler, + .desc + = "The linker component to inherit from. Can be either a compiler object or linker type name." }, + [kw_inherit_static_linker] = { "inherit_static_linker", + tc_string | tc_compiler, + .desc + = "The static linker component to inherit from. Can be either a compiler object or static linker type name." }, 0, }; @@ -91,6 +100,10 @@ func_module_toolchain_create(struct workspace *wk, obj self, obj *res) } const struct func_impl impl_tbl_module_toolchain[] = { - { "create", func_module_toolchain_create, tc_compiler }, + { "create", + func_module_toolchain_create, + tc_compiler, + .desc + = "Creates a new compiler object that can be passed in to the `toolchain` keyword on `add_languages` or inherited from when coreating a new toolchain. The toolchain object is reffered to as a `compiler` for historical reasons, although it also contains other information required to compile programs such as linker metadata." }, { NULL, NULL }, }; diff --git a/src/lang/func_lookup.c b/src/lang/func_lookup.c index fbc24c556..08dd77de5 100644 --- a/src/lang/func_lookup.c +++ b/src/lang/func_lookup.c @@ -463,6 +463,33 @@ struct meson_doc_entry_arg meson_doc_posargs[] = { 0 }; struct meson_doc_entry_arg meson_doc_kwargs[] = { 0 }; #endif +struct meson_doc_entry_arg * +meson_doc_lookup_function_kwarg(const struct meson_doc_entry_func *meson_doc_entry, const char *key) +{ + struct meson_doc_entry_arg *args = &meson_doc_kwargs[meson_doc_entry->kwargs_start]; + uint32_t i; + for (i = 0; i < meson_doc_entry->kwargs_len; ++i) { + if (strcmp(args[i].common.name, key) == 0) { + return &args[i]; + } + } + + return 0; +} + +struct meson_doc_entry_func * +meson_doc_lookup_function(enum obj_type t, const char *name) +{ + uint32_t j; + for (j = 0; meson_doc_root[t][j].common.name; ++j) { + if (strcmp(meson_doc_root[t][j].common.name, name) == 0) { + return &meson_doc_root[t][j]; + } + } + + return 0; +} + static obj dump_function_arg(struct workspace *wk, struct args_norm *an, uint32_t an_idx, struct args_kw *kw) { @@ -471,6 +498,7 @@ dump_function_arg(struct workspace *wk, struct args_norm *an, uint32_t an_idx, s obj name = 0; const char *desc = 0; + bool extension = false; if (an) { if (an->desc) { desc = an->desc; @@ -491,19 +519,15 @@ dump_function_arg(struct workspace *wk, struct args_norm *an, uint32_t an_idx, s if (kw->desc) { desc = kw->desc; } else if (function_sig_dump.meson_doc_entry) { - bool found = false; - struct meson_doc_entry_arg *args - = &meson_doc_kwargs[function_sig_dump.meson_doc_entry->kwargs_start]; - uint32_t i; - for (i = 0; i < function_sig_dump.meson_doc_entry->kwargs_len; ++i) { - if (strcmp(args[i].common.name, kw->key) == 0) { - found = true; - break; - } + struct meson_doc_entry_arg *arg; + + arg = meson_doc_lookup_function_kwarg(function_sig_dump.meson_doc_entry, kw->key); + + if (!arg && function_sig_dump.special_func == function_sig_dump_special_func_build_tgt) { + arg = meson_doc_lookup_function_kwarg(meson_doc_lookup_function(obj_null, "build_target"), kw->key); } - if (found) { - struct meson_doc_entry_arg *arg = &args[i]; + if (arg) { desc = arg->common.description; } else { LOG_W("missing documentation for %s kwarg %s", @@ -513,6 +537,7 @@ dump_function_arg(struct workspace *wk, struct args_norm *an, uint32_t an_idx, s } name = make_str(wk, kw->key); + extension = kw->extension; } obj_dict_set(wk, dict, make_str(wk, "name"), name); @@ -521,6 +546,10 @@ dump_function_arg(struct workspace *wk, struct args_norm *an, uint32_t an_idx, s obj_dict_set(wk, dict, make_str(wk, "desc"), make_str(wk, desc)); } + if (extension) { + obj_dict_set(wk, dict, make_str(wk, "extension"), obj_bool_true); + } + return dict; } @@ -643,8 +672,17 @@ dump_function(struct workspace *wk, struct dump_function_opts *opts) } else if (function_sig_dump.meson_doc_entry) { desc = function_sig_dump.meson_doc_entry->common.description; } + if (desc) { obj_dict_set(wk, res, make_str(wk, "desc"), make_str(wk, desc)); + } else { + LOG_W("missing documentation for %s.%s", + opts->module_func ? opts->module : obj_type_to_s(opts->rcvr_t), + opts->impl->name); + } + + if (opts->impl->extension) { + obj_dict_set(wk, res, make_str(wk, "extension"), obj_bool_true); } stack_push(&wk->stack, wk->vm.behavior.pop_args, dump_function_args); @@ -656,8 +694,6 @@ dump_function(struct workspace *wk, struct dump_function_opts *opts) } stack_pop(&wk->stack, wk->vm.behavior.pop_args); - LO("%o\n", res); - return res; } @@ -680,13 +716,7 @@ dump_function_docs_json(struct workspace *wk, struct sbuf *sb) for (i = 0; g->impls[i].name; ++i) { if (meson_doc_root[t] && wk->vm.lang_mode == language_external) { - uint32_t j; - for (j = 0; meson_doc_root[t][j].common.name; ++j) { - if (strcmp(meson_doc_root[t][j].common.name, g->impls[i].name) == 0) { - function_sig_dump.meson_doc_entry = &meson_doc_root[t][j]; - break; - } - } + function_sig_dump.meson_doc_entry = meson_doc_lookup_function(t, g->impls[i].name); } if (strcmp(g->impls[i].name, "executable") || strcmp(g->impls[i].name, "build_target")