Esempio n. 1
0
// Write the given package home page to its own file
static void doc_package_home(docgen_t* docgen,
  ast_t* package,
  ast_t* doc_string)
{
  assert(docgen != NULL);
  assert(docgen->index_file != NULL);
  assert(docgen->home_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(package != NULL);
  assert(ast_id(package) == TK_PACKAGE);

  // First open a file
  size_t tqfn_len;
  char* tqfn = write_tqfn(package, "-index", &tqfn_len);

  // Package group
  fprintf(docgen->index_file, "- package %s:\n",
    package_qualified_name(package));

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

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

  // Add reference to new file to index file
  fprintf(docgen->index_file, "  - Package: \"%s.md\"\n", tqfn);

  // Add reference to package to home file
  fprintf(docgen->home_file, "* [%s](%s)\n", package_qualified_name(package),
    tqfn);

  // Now we can write the actual documentation for the package
  if(doc_string != NULL)
  {
    assert(ast_id(doc_string) == TK_STRING);
    fprintf(docgen->type_file, "%s", ast_name(doc_string));
  }
  else
  {
    fprintf(docgen->type_file, "No package doc string provided for %s.",
      package_qualified_name(package));
  }


  ponyint_pool_free_size(tqfn_len, tqfn);

  docgen->test_types = printbuf_new();
  docgen->public_types = printbuf_new();
  docgen->private_types = printbuf_new();
  docgen->package_file = docgen->type_file;
  docgen->type_file = NULL;
}
Esempio n. 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;
}
Esempio n. 3
0
// Write the given type to the current type file
static void doc_type(docgen_t* docgen, ast_t* type)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(type != NULL);

  switch(ast_id(type))
  {
    case TK_NOMINAL:
    {
      AST_GET_CHILDREN(type, package, id, tparams, cap, ephemeral);

      // Find type we reference so we can link to it
      ast_t* target = (ast_t*)ast_data(type);
      assert(target != NULL);

      size_t link_len;
      char* tqfn = write_tqfn(target, NULL, &link_len);

      // Links are of the form: [text](target)
      fprintf(docgen->type_file, "[%s](%s)", ast_name(id), tqfn);
      pool_free_size(link_len, tqfn);

      doc_type_list(docgen, tparams, "\\[", ", ", "\\]");

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

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_UNIONTYPE:
      doc_type_list(docgen, type, "(", " | ", ")");
      break;

    case TK_ISECTTYPE:
      doc_type_list(docgen, type, "(", " & ", ")");
      break;

    case TK_TUPLETYPE:
      doc_type_list(docgen, type, "(", " , ", ")");
      break;

    case TK_TYPEPARAMREF:
    {
      AST_GET_CHILDREN(type, id, cap, ephemeral);
      fprintf(docgen->type_file, "%s", ast_name(id));

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

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);
      doc_type(docgen, left);
      fprintf(docgen->type_file, "->");
      doc_type(docgen, right);
      break;
    }

    case TK_THISTYPE:
      fprintf(docgen->type_file, "this");
      break;

    case TK_BOXTYPE:
      fprintf(docgen->type_file, "box");
      break;

    default:
      assert(0);
  }
}
Esempio n. 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;
}
Esempio n. 5
0
// Write the given type to the current type file
static void doc_type(docgen_t* docgen, ast_t* type, bool generate_links)
{
  assert(docgen != NULL);
  assert(docgen->type_file != NULL);
  assert(type != NULL);

  switch(ast_id(type))
  {
    case TK_NOMINAL:
    {
      AST_GET_CHILDREN(type, package, id, tparams, cap, ephemeral);

      // Generate links only if directed to and if the type is not anonymous (as
      // indicated by a name created by package_hygienic_id).
      if(generate_links && *ast_name(id) != '$')
      {
        // Find type we reference so we can link to it
        ast_t* target = (ast_t*)ast_data(type);
        assert(target != NULL);

        size_t link_len;
        char* tqfn = write_tqfn(target, NULL, &link_len);

        // Links are of the form: [text](target)
        fprintf(docgen->type_file, "[%s](%s)", ast_nice_name(id), tqfn);
        ponyint_pool_free_size(link_len, tqfn);

        doc_type_list(docgen, tparams, "\\[", ", ", "\\]", true, false);
      }
      else
      {
        fprintf(docgen->type_file, "%s", ast_nice_name(id));
        doc_type_list(docgen, tparams, "[", ", ", "]", false, false);
      }

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

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_UNIONTYPE:
      doc_type_list(docgen, type, "(", " | ", ")", generate_links, true);
      break;

    case TK_ISECTTYPE:
      doc_type_list(docgen, type, "(", " & ", ")", generate_links, false);
      break;

    case TK_TUPLETYPE:
      doc_type_list(docgen, type, "(", " , ", ")", generate_links, false);
      break;

    case TK_TYPEPARAMREF:
    {
      AST_GET_CHILDREN(type, id, cap, ephemeral);
      fprintf(docgen->type_file, "%s", ast_nice_name(id));

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

      if(ast_id(ephemeral) != TK_NONE)
        fprintf(docgen->type_file, "%s", ast_get_print(ephemeral));

      break;
    }

    case TK_ARROW:
    {
      AST_GET_CHILDREN(type, left, right);
      doc_type(docgen, left, generate_links);
      fprintf(docgen->type_file, "->");
      doc_type(docgen, right, generate_links);
      break;
    }

    case TK_THISTYPE:
      fprintf(docgen->type_file, "this");
      break;

    case TK_ISO:
    case TK_TRN:
    case TK_REF:
    case TK_VAL:
    case TK_BOX:
    case TK_TAG:
      fprintf(docgen->type_file, "%s", ast_get_print(type));
      break;

    default:
      assert(0);
  }
}