char* CFCPerlPod_gen_subroutine_pod(CFCCallable *func, const char *alias, CFCClass *klass, const char *code_sample, const char *class_name, int is_constructor) { const char *func_name = CFCCallable_get_name(func); // Only allow "public" subs to be exposed as part of the public API. if (!CFCCallable_public(func)) { CFCUtil_die("%s#%s is not public", class_name, func_name); } char *pod = CFCUtil_sprintf("=head2 %s\n\n", alias); // Add code sample. if (!code_sample) { char *auto_sample = S_gen_code_sample(func, alias, klass, is_constructor); pod = CFCUtil_cat(pod, auto_sample, "\n", NULL); FREEMEM(auto_sample); } else { pod = CFCUtil_cat(pod, code_sample, "\n", NULL); } // Get documentation, which may be inherited. CFCDocuComment *docucomment = CFCCallable_get_docucomment(func); if (!docucomment) { CFCClass *parent = klass; while (NULL != (parent = CFCClass_get_parent(parent))) { CFCCallable *parent_func = (CFCCallable*)CFCClass_method(parent, func_name); if (!parent_func) { break; } docucomment = CFCCallable_get_docucomment(parent_func); if (docucomment) { break; } } } if (!docucomment) { return pod; } // Incorporate "description" text from DocuComment. const char *long_doc = CFCDocuComment_get_description(docucomment); if (long_doc && strlen(long_doc)) { char *perlified = CFCPerlPod_md_to_pod(long_doc, klass, 3); pod = CFCUtil_cat(pod, perlified, NULL); FREEMEM(perlified); } // Add params in a list. const char**param_names = CFCDocuComment_get_param_names(docucomment); const char**param_docs = CFCDocuComment_get_param_docs(docucomment); if (param_names[0]) { pod = CFCUtil_cat(pod, "=over\n\n", NULL); for (size_t i = 0; param_names[i] != NULL; i++) { char *perlified = CFCPerlPod_md_to_pod(param_docs[i], klass, 3); pod = CFCUtil_cat(pod, "=item *\n\nB<", param_names[i], "> - ", perlified, NULL); FREEMEM(perlified); } pod = CFCUtil_cat(pod, "=back\n\n", NULL); } // Add return value description, if any. const char *retval_doc = CFCDocuComment_get_retval(docucomment); if (retval_doc && strlen(retval_doc)) { char *perlified = CFCPerlPod_md_to_pod(retval_doc, klass, 3); pod = CFCUtil_cat(pod, "Returns: ", perlified, NULL); FREEMEM(perlified); } return pod; }
char* CFCPerlClass_create_pod(CFCPerlClass *self) { CFCPerlPod *pod_spec = self->pod_spec; const char *class_name = self->class_name; CFCClass *client = self->client; if (!pod_spec) { return NULL; } if (!client) { CFCUtil_die("No client for %s", class_name); } CFCDocuComment *docucom = CFCClass_get_docucomment(client); if (!docucom) { CFCUtil_die("No DocuComment for %s", class_name); } // Get the class's brief description. const char *raw_brief = CFCDocuComment_get_brief(docucom); char *brief = CFCPerlPod_md_to_pod(pod_spec, client, raw_brief); // Get the class's long description. char *description; const char *pod_description = CFCPerlPod_get_description(pod_spec); if (pod_description && strlen(pod_description)) { description = CFCUtil_sprintf("%s\n", pod_description); } else { const char *raw_description = CFCDocuComment_get_long(docucom); description = CFCPerlPod_md_to_pod(pod_spec, client, raw_description); } // Create SYNOPSIS. const char *raw_synopsis = CFCPerlPod_get_synopsis(pod_spec); char *synopsis = CFCUtil_strdup(""); if (raw_synopsis && strlen(raw_synopsis)) { synopsis = CFCUtil_cat(synopsis, "=head1 SYNOPSIS\n\n", raw_synopsis, "\n", NULL); } // Create CONSTRUCTORS. char *constructor_pod = CFCPerlPod_constructors_pod(pod_spec, client); // Create METHODS, possibly including an ABSTRACT METHODS section. char *methods_pod = CFCPerlPod_methods_pod(pod_spec, client); // Build an INHERITANCE section describing class ancestry. char *inheritance = CFCUtil_strdup(""); if (CFCClass_get_parent(client)) { inheritance = CFCUtil_cat(inheritance, "=head1 INHERITANCE\n\n", class_name, NULL); CFCClass *ancestor = client; while (NULL != (ancestor = CFCClass_get_parent(ancestor))) { const char *ancestor_klass = CFCClass_get_class_name(ancestor); if (CFCPerlClass_singleton(ancestor_klass)) { inheritance = CFCUtil_cat(inheritance, " isa L<", ancestor_klass, ">", NULL); } else { inheritance = CFCUtil_cat(inheritance, " isa ", ancestor_klass, NULL); } } inheritance = CFCUtil_cat(inheritance, ".\n\n", NULL); } // Put it all together. const char pattern[] = "=head1 NAME\n" "\n" "%s - %s" "%s" "=head1 DESCRIPTION\n" "\n" "%s" "%s" "%s" "%s" "=cut\n" "\n"; char *pod = CFCUtil_sprintf(pattern, class_name, brief, synopsis, description, constructor_pod, methods_pod, inheritance); FREEMEM(brief); FREEMEM(synopsis); FREEMEM(description); FREEMEM(constructor_pod); FREEMEM(methods_pod); FREEMEM(inheritance); return pod; }
char* CFCPerlPod_gen_subroutine_pod(CFCPerlPod *self, CFCFunction *func, const char *alias, CFCClass *klass, const char *code_sample, const char *class_name, int is_constructor) { // Only allow "public" subs to be exposed as part of the public API. if (!CFCFunction_public(func)) { CFCUtil_die("%s#%s is not public", class_name, alias); } CFCParamList *param_list = CFCFunction_get_param_list(func); int num_vars = (int)CFCParamList_num_vars(param_list); char *pod = CFCUtil_sprintf("=head2 %s", alias); // Get documentation, which may be inherited. CFCDocuComment *docucomment = CFCFunction_get_docucomment(func); if (!docucomment) { const char *micro_sym = CFCFunction_micro_sym(func); CFCClass *parent = klass; while (NULL != (parent = CFCClass_get_parent(parent))) { CFCFunction *parent_func = (CFCFunction*)CFCClass_method(parent, micro_sym); if (!parent_func) { break; } docucomment = CFCFunction_get_docucomment(parent_func); if (docucomment) { break; } } } if (!docucomment) { CFCUtil_die("No DocuComment for '%s' in '%s'", alias, class_name); } // Build string summarizing arguments to use in header. if (num_vars > 2 || (is_constructor && num_vars > 1)) { pod = CFCUtil_cat(pod, "( I<[labeled params]> )\n\n", NULL); } else if (num_vars == 2) { // Kill self param. const char *name_list = CFCParamList_name_list(param_list); const char *after_comma = strchr(name_list, ',') + 1; while (isspace(*after_comma)) { after_comma++; } pod = CFCUtil_cat(pod, "(", after_comma, ")\n\n", NULL); } else { // num_args == 1, leave off 'self'. pod = CFCUtil_cat(pod, "()\n\n", NULL); } // Add code sample. if (code_sample && strlen(code_sample)) { pod = CFCUtil_cat(pod, code_sample, "\n", NULL); } // Incorporate "description" text from DocuComment. const char *long_doc = CFCDocuComment_get_description(docucomment); if (long_doc && strlen(long_doc)) { char *perlified = CFCPerlPod_md_to_pod(self, klass, long_doc); pod = CFCUtil_cat(pod, perlified, NULL); FREEMEM(perlified); } // Add params in a list. const char**param_names = CFCDocuComment_get_param_names(docucomment); const char**param_docs = CFCDocuComment_get_param_docs(docucomment); if (param_names[0]) { pod = CFCUtil_cat(pod, "=over\n\n", NULL); for (size_t i = 0; param_names[i] != NULL; i++) { char *perlified = CFCPerlPod_md_to_pod(self, klass, param_docs[i]); pod = CFCUtil_cat(pod, "=item *\n\nB<", param_names[i], "> - ", perlified, NULL); FREEMEM(perlified); } pod = CFCUtil_cat(pod, "=back\n\n", NULL); } // Add return value description, if any. const char *retval_doc = CFCDocuComment_get_retval(docucomment); if (retval_doc && strlen(retval_doc)) { char *perlified = CFCPerlPod_md_to_pod(self, klass, retval_doc); pod = CFCUtil_cat(pod, "Returns: ", perlified, NULL); FREEMEM(perlified); } return pod; }