Example #1
0
// Document the given package
static void doc_package(docgen_t* docgen, ast_t* ast)
{
  assert(ast != NULL);
  assert(ast_id(ast) == TK_PACKAGE);
  assert(docgen->package_file == NULL);

  ast_list_t types = { NULL, NULL, NULL };
  ast_t* package_doc = NULL;

  // Find and sort package contents
  for(ast_t* m = ast_child(ast); m != NULL; m = ast_sibling(m))
  {
    if(ast_id(m) == TK_STRING)
    {
      // Package docstring
      assert(package_doc == NULL);
      package_doc = m;
    }
    else
    {
      assert(ast_id(m) == TK_MODULE);

      for(ast_t* t = ast_child(m); t != NULL; t = ast_sibling(t))
      {
        if(ast_id(t) != TK_USE)
        {
          assert(ast_id(t) == TK_TYPE || ast_id(t) == TK_INTERFACE ||
            ast_id(t) == TK_TRAIT || ast_id(t) == TK_PRIMITIVE ||
            ast_id(t) == TK_STRUCT || ast_id(t) == TK_CLASS ||
            ast_id(t) == TK_ACTOR);
          // We have a type
          doc_list_add_named(&types, t, 0, true, true);
        }
      }
    }
  }

  doc_package_home(docgen, ast, package_doc);

  // Process types
  for(ast_list_t* p = types.next; p != NULL; p = p->next)
    doc_entity(docgen, p->ast, ast);

  fclose(docgen->package_file);
  docgen->package_file = NULL;
}
Example #2
0
// Write a description of the given entity to its own type file.
// The containing package is handed in to save looking it up again.
static void doc_entity(docgen_t* docgen, ast_t* ast, ast_t* package)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->type_file == NULL);
  assert(ast != NULL);
  assert(package != NULL);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(ast, NULL, &tqfn_len);

  docgen->type_file = doc_open_file(docgen, true, tqfn, ".md");

  if(docgen->type_file == NULL)
    return;

  // Add reference to new file to index file
  AST_GET_CHILDREN(ast, id, tparams, cap, provides, members, c_api, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  fprintf(docgen->index_file, "  - %s %s: \"%s.md\"\n",
    ast_get_print(ast), name, tqfn);

  pool_free_size(tqfn_len, tqfn);

  // Now we can write the actual documentation for the entity
  fprintf(docgen->type_file, "%s %s", ast_get_print(ast), name);
  doc_type_params(docgen, tparams);
  doc_type_list(docgen, provides, " is ", ", ", "");
  fprintf(docgen->type_file, "\n\nIn package \"%s\".\n\n",
    package_qualified_name(package));

  fprintf(docgen->type_file, "%s", (name[0] == '_') ? "Private" : "Public");

  const char* cap_text = doc_get_cap(cap);
  if(cap_text != NULL)
    fprintf(docgen->type_file, ", default capability %s", cap_text);

  fprintf(docgen->type_file, ".\n\n");

  if(ast_id(c_api) == TK_AT)
    fprintf(docgen->type_file, "May be called from C.\n");

  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));
  else
    fprintf(docgen->type_file, "No doc string provided.\n\n");

  // Sort members into varieties
  ast_list_t pub_fields = { NULL, NULL, NULL };
  ast_list_t news = { NULL, NULL, NULL };
  ast_list_t bes = { NULL, NULL, NULL };
  ast_list_t funs = { NULL, NULL, NULL };

  for(ast_t* p = ast_child(members); p != NULL; p = ast_sibling(p))
  {
    switch(ast_id(p))
    {
      case TK_FVAR:
      case TK_FLET:
        doc_list_add_named(&pub_fields, p, 0, true, false);
        break;

      case TK_NEW:
        doc_list_add_named(&news, p, 1, true, true);
        break;

      case TK_BE:
        doc_list_add_named(&bes, p, 1, true, true);
        break;

      case TK_FUN:
        doc_list_add_named(&funs, p, 1, true, true);
        break;

      default:
        assert(0);
        break;
    }
  }

  // Handle member variety lists
  doc_fields(docgen, &pub_fields, "Public fields");
  doc_methods(docgen, &news, "Constructors");
  doc_methods(docgen, &bes, "Behaviours");
  doc_methods(docgen, &funs, "Functions");

  doc_list_free(&pub_fields);
  doc_list_free(&news);
  doc_list_free(&bes);
  doc_list_free(&funs);

  fclose(docgen->type_file);
  docgen->type_file = NULL;
}
Example #3
0
// Document the given package
static void doc_package(docgen_t* docgen, ast_t* ast)
{
  assert(ast != NULL);
  assert(ast_id(ast) == TK_PACKAGE);
  assert(docgen->package_file == NULL);
  assert(docgen->test_types == NULL);
  assert(docgen->public_types == NULL);
  assert(docgen->private_types == NULL);

  ast_list_t types = { NULL, NULL, NULL };
  ast_t* package_doc = NULL;

  // Find and sort package contents
  for(ast_t* m = ast_child(ast); m != NULL; m = ast_sibling(m))
  {
    if(ast_id(m) == TK_STRING)
    {
      // Package docstring
      assert(package_doc == NULL);
      package_doc = m;
    }
    else
    {
      assert(ast_id(m) == TK_MODULE);

      for(ast_t* t = ast_child(m); t != NULL; t = ast_sibling(t))
      {
        if(ast_id(t) != TK_USE)
        {
          assert(ast_id(t) == TK_TYPE || ast_id(t) == TK_INTERFACE ||
            ast_id(t) == TK_TRAIT || ast_id(t) == TK_PRIMITIVE ||
            ast_id(t) == TK_STRUCT || ast_id(t) == TK_CLASS ||
            ast_id(t) == TK_ACTOR);
          // We have a type
          doc_list_add_named(&types, t, 0, true, true);
        }
      }
    }
  }

  doc_package_home(docgen, ast, package_doc);

  // Process types
  for(ast_list_t* p = types.next; p != NULL; p = p->next)
    doc_entity(docgen, p->ast);

  // Add listing of subpackages and links
  if(docgen->public_types->offset > 0)
  {
    fprintf(docgen->package_file, "\n\n## Public Types\n\n");
    fprintf(docgen->package_file, "%s", docgen->public_types->m);
  }

  if(docgen->private_types->offset > 0)
  {
    fprintf(docgen->package_file, "\n\n## Private Types\n\n");
    fprintf(docgen->package_file, "%s", docgen->private_types->m);
  }

  if(docgen->test_types->offset > 0)
  {
    fprintf(docgen->package_file, "\n\n## Test Types\n\n");
    fprintf(docgen->package_file, "%s", docgen->test_types->m);
  }

  fclose(docgen->package_file);
  docgen->package_file = NULL;
  printbuf_free(docgen->test_types);
  printbuf_free(docgen->public_types);
  printbuf_free(docgen->private_types);
  docgen->test_types = NULL;
  docgen->public_types = NULL;
  docgen->private_types = NULL;
}
Example #4
0
// Write a description of the given entity to its own type file.
static void doc_entity(docgen_t* docgen, ast_t* ast)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->package_file != NULL);
  assert(docgen->test_types != NULL);
  assert(docgen->public_types != NULL);
  assert(docgen->private_types != NULL);
  assert(docgen->type_file == NULL);
  assert(ast != NULL);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(ast, NULL, &tqfn_len);

  docgen->type_file = doc_open_file(docgen, true, tqfn, ".md");

  if(docgen->type_file == NULL)
    return;

  // Add reference to new file to index file
  AST_GET_CHILDREN(ast, id, tparams, cap, provides, members, c_api, doc);

  const char* name = ast_name(id);
  assert(name != NULL);

  fprintf(docgen->index_file, "  - %s %s: \"%s.md\"\n",
    ast_get_print(ast), name, tqfn);

  // Add to appropriate package types buffer
  printbuf_t* buffer = docgen->public_types;
  if(is_for_testing(name, provides)) buffer = docgen->test_types;
  else if(name[0] == '_') buffer = docgen->private_types;
  printbuf(buffer,
           "* [%s %s](%s.md)\n",
           ast_get_print(ast), name, tqfn);

  ponyint_pool_free_size(tqfn_len, tqfn);

  // Now we can write the actual documentation for the entity
  fprintf(docgen->type_file, "# %s", name);
  doc_type_params(docgen, tparams, true);
  fprintf(docgen->type_file, "\n\n");

  if(ast_id(doc) != TK_NONE)
    fprintf(docgen->type_file, "%s\n\n", ast_name(doc));

  // code block
  fprintf(docgen->type_file, "```pony\n");
  fprintf(docgen->type_file, "%s ",ast_get_print(ast));

  const char* cap_text = doc_get_cap(cap);
  if(cap_text != NULL) fprintf(docgen->type_file, "%s ", cap_text);

  fprintf(docgen->type_file, "%s", name);

  doc_type_params(docgen, tparams, false);
  doc_type_list(docgen, provides, " is\n  ", ",\n  ", "", false);
  fprintf(docgen->type_file, "\n```\n\n");

  if (ast_id(ast) !=  TK_TYPE)
    doc_type_list(docgen, provides,
      "#### Implements\n\n* ", "\n* ", "\n\n---\n\n", true);
  else
    doc_type_list(docgen, provides,
      "#### Type Alias For\n\n* ", "\n* ", "\n\n---\n\n", true);

  // Sort members into varieties
  ast_list_t pub_fields = { NULL, NULL, NULL };
  ast_list_t news = { NULL, NULL, NULL };
  ast_list_t pub_bes = { NULL, NULL, NULL };
  ast_list_t priv_bes = { NULL, NULL, NULL };
  ast_list_t pub_funs = { NULL, NULL, NULL };
  ast_list_t priv_funs = { NULL, NULL, NULL };

  for(ast_t* p = ast_child(members); p != NULL; p = ast_sibling(p))
  {
    switch(ast_id(p))
    {
      case TK_FVAR:
      case TK_FLET:
      case TK_EMBED:
        doc_list_add_named(&pub_fields, p, 0, true, false);
        break;

      case TK_NEW:
        doc_list_add_named(&news, p, 1, true, true);
        break;

      case TK_BE:
        doc_list_add_named(&pub_bes, p, 1, true, false);
        doc_list_add_named(&priv_bes, p, 1, false, true);
        break;

      case TK_FUN:
        doc_list_add_named(&pub_funs, p, 1, true, false);
        doc_list_add_named(&priv_funs, p, 1, false, true);
        break;

      default:
        assert(0);
        break;
    }
  }

  // Handle member variety lists
  doc_methods(docgen, &news, "Constructors");
  doc_fields(docgen, &pub_fields, "Public fields");
  doc_methods(docgen, &pub_bes, "Public Behaviours");
  doc_methods(docgen, &pub_funs, "Public Functions");
  doc_methods(docgen, &priv_bes, "Private Behaviours");
  doc_methods(docgen, &priv_funs, "Private Functions");

  doc_list_free(&pub_fields);
  doc_list_free(&news);
  doc_list_free(&pub_bes);
  doc_list_free(&priv_bes);
  doc_list_free(&pub_funs);
  doc_list_free(&priv_funs);

  fclose(docgen->type_file);
  docgen->type_file = NULL;
}