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; }
static void S_resolve(CFCUri *self, const char *parcel, const char *struct_sym, const char *callable) { // Try to find a CFCClass. CFCClass *doc_class = self->doc_class; CFCClass *klass = NULL; if (parcel) { char *full_struct_sym = CFCUtil_sprintf("%s_%s", parcel, struct_sym); klass = CFCClass_fetch_by_struct_sym(full_struct_sym); FREEMEM(full_struct_sym); } else if (struct_sym && doc_class) { const char *prefix = CFCClass_get_prefix(doc_class); char *full_struct_sym = CFCUtil_sprintf("%s%s", prefix, struct_sym); klass = CFCClass_fetch_by_struct_sym(full_struct_sym); FREEMEM(full_struct_sym); } else if (callable) { klass = doc_class; } if (klass) { if (!CFCClass_public(klass)) { CFCUtil_warn("Non-public class '%s' in Clownfish URI: %s", CFCClass_get_struct_sym(klass), self->string); } self->type = CFC_URI_CLASS; self->klass = klass; CFCBase_incref((CFCBase*)klass); if (callable) { if (islower(callable[0])) { CFCFunction *function = CFCClass_function(klass, callable); if (!function) { CFCUtil_warn("Unknown function '%s' in Clownfish URI: %s", callable, self->string); } else if (!CFCFunction_public(function)) { CFCUtil_warn("Non-public function '%s' in Clownfish URI:" " %s", callable, self->string); } self->type = CFC_URI_FUNCTION; self->callable = CFCUtil_strdup(callable); } else { CFCMethod *method = CFCClass_method(klass, callable); if (!method) { CFCUtil_warn("Unknown method '%s' in Clownfish URI: %s", callable, self->string); } else if (!CFCMethod_public(method)) { CFCUtil_warn("Non-public method '%s' in Clownfish URI:" " %s", callable, self->string); } self->type = CFC_URI_METHOD; self->callable = CFCUtil_strdup(callable); } } return; } // Try to find a CFCDocument. if (!parcel && struct_sym && !callable) { CFCDocument *doc = CFCDocument_fetch(struct_sym); if (doc) { self->type = CFC_URI_DOCUMENT; self->document = doc; CFCBase_incref((CFCBase*)doc); return; } } S_set_error(self, "Couldn't resolve Clownfish URI"); }
char* CFCPerlPod_gen_subroutine_pod(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); } 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 = CFCFunction_get_docucomment(func); if (!docucomment) { const char *func_name = CFCFunction_get_name(func); CFCClass *parent = klass; while (NULL != (parent = CFCClass_get_parent(parent))) { CFCFunction *parent_func = (CFCFunction*)CFCClass_method(parent, func_name); if (!parent_func) { break; } docucomment = CFCFunction_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; }