Guidedog Manual 0.2.0
Idioma
En esta página
Guidedog / Documentación 0.2.0

Documentar Odin

El dominio Odin da destinos con nombre a paquetes, procedimientos, tipos y miembros. Guidedog también genera páginas API analizando Odin, sin ejecutar el compilador ni el paquete. Las firmas generadas aún necesitan un contrato útil.

Describir objetos

Un paquete establece el contexto de lo que sigue, como un módulo Python:

.. odin:package:: core:strings
   :synopsis: Procedures to manipulate UTF-8 encoded strings.
   :imports: rt=base:runtime

.. odin:procedure:: @(require_results) clone :: proc(s: string, allocator := context.allocator) -> (res: string, err: rt.Allocator_Error) #optional_allocator_error

   Clones a string.

   :param s: The string to be cloned.
   :result res: The cloned string.
   :result err: An allocator error, or ``nil``.

.. odin:struct:: Builder :: struct

   A dynamic byte buffer.

   .. odin:field:: buf: [dynamic]byte

Las firmas se escriben en una línea como las declaraciones Odin y se muestran igual. Los ejemplos siguientes se ven así:

shapes.Kind :: enum u8
Circle = 1
@(require_results) shapes.area :: proc(side: f32, scale: f32 = 1) -> (a: f32, ok: bool) #optional_ok

Mide un cuadrado.

Parámetros:

side – Su lado.

Devuelve:
  • a – Su área.

  • ok – Si se conoce su tipo.

Directivas y firmas que aceptan:

odin:package y odin:currentpackage

Acepta core:fmt o una ruta bajo las raíces, como readers/sphinx. Los objetos usan la ruta importada: core:fmt.println. odin:currentpackage cambia el contexto sin destino; None lo limpia. Opciones: :synopsis:, :platform:, :deprecated:, :no-index: y :imports:, que declara alias como pares alias=package (gd=core rst=readers/rst), enlazando gd.Node_Id con core.Node_Id. :private: enumera tipos y miembros privados de grupos (State Rules catalog_text), mostrados como texto al no tener descripción enlazable. Las páginas generadas los enumeran automáticamente.

odin:procedure (o odin:proc)

name :: proc(params) -> results admite atributos previos (@(require_results)), #force_inline antes de proc, convención (proc "c" (...)), valores por defecto (x := 1, x: int = 1), parámetros polimórficos $T, variádicos .., using, #c_vararg, resultados con nombre, etiquetas (#optional_ok) y where. name(params) -> results es la abreviatura.

odin:procgroup

name :: proc{a, b}: cada miembro enlaza a su procedimiento.

odin:struct, odin:union, odin:enum, odin:bitset, odin:bitfield, odin:type

Name :: struct($T: typeid) #packed, Name :: union #no_nil {A, B}, Name :: enum u8, Name :: bit_set[Flag; u8], Name :: bit_field u32; odin:type admite tipos distintos y alias (Handle :: distinct uintptr, Callback :: proc(x: int) -> bool). El contenido del tipo incluye sus miembros.

odin:field y odin:enumerator

Dentro de un tipo: name: Type con etiqueta (name: string `json:"n"`) o tamaño en bits (low: u8 | 3), y Name o Name = 3. Sus nombres son Type.member.

odin:const, odin:var, odin:foreign

NAME :: 64 o NAME : int : 64; name: Type, name := value o name: Type = value; libc "system:c" para una importación externa.

Todos aceptan :no-index:, :no-index-entry:, :no-contents-entry: y :no-typesetting: de Sphinx. Añaden :package: (otro paquete), :private: y :deprecated: message (muestran @(private) y @(deprecated="message") si faltan en la firma), :availability: Windows, Linux (primera línea con plataformas) y :foreign: libc (procedimiento externo). Varias firmas describen el mismo objeto para distintos destinos; solo la primera recibe identificador y entrada de índice.

Los nombres de tipos se buscan primero en el paquete y tipo de la firma y luego tal como están escritos. Tipos integrados (int, string, rawptr, typeid, any…), palabras clave, nombres polimórficos ($T y posteriores T, incluidos los del tipo contenedor), longitudes, valores predeterminados, constantes, etiquetas y where se muestran sin enlaces.

Roles e identificadores

Enlazan :odin:pkg:, :odin:proc:, :odin:type: (estructuras, uniones, enumeraciones, conjuntos y campos de bits, etc.), :odin:const:, :odin:var:, :odin:field:, :odin:enumerator: y :odin:obj: (cualquiera). Como en Python, ~ muestra el final (:odin:proc:`~core:fmt.println` muestra println) y . inicial busca sufijos. Se consulta tipo y paquete del contexto, el nombre literal y el tramo tras : o /: fmt.println encuentra core:fmt.println y sphinx.Config encuentra readers/sphinx.Config, como Odin. Los alias de :imports: tienen prioridad. Con default-domain:: odin o primary_domain = "odin" se omite odin:.

El ID aplica make_id de Sphinx a odin- y el nombre completo: odin-core-fmt.println, odin-readers-sphinx.Config.docname. Conserva mayúsculas y puntos; : y / pasan a guiones. Son legibles, estables y distinguen paquetes con igual nombre final. Un paquete usa odin-package- y su ruta. El índice muestra «println (procedure in core:fmt)». objects.inv enumera todo con dominio odin y tipo (odin:procedure, odin:struct, odin:field…), paquetes primero, como los módulos de Sphinx.

Los campos se agrupan como en otros dominios: :param name: (con :type name:), :result name: para resultados con nombre, :returns: y :rtype:.

Generar desde el código fuente

Indica dónde están los paquetes, respecto a las fuentes:

odin_autoapi_dirs = ["../src"]
odin_collections = {core = "/usr/local/lib/odin/core"}  # optional

Bajo odin_autoapi_dirs, el nombre es la ruta relativa (src/shapes/round es shapes/round); en una colección es el importado por Odin (core:strings). Las directivas funcionan como autodoc:

.. odin:autopackage:: shapes
   :members:
   :undoc-members:
   :member-order: groupwise

.. odin:autoproc:: shapes.area
.. odin:autotype:: Shape

odin:autopackage escribe el paquete, su comentario y, con :members:, todas las declaraciones o las indicadas. odin:autoproc, odin:autoprocgroup, odin:autotype, odin:autoconst y odin:autovar escriben una declaración del contexto o package.name. Opciones: :members:, :undoc-members:, :private-members: (@(private), omitidas normalmente), :exclude-members:, :member-order: (source por archivo y posición, predeterminado; alphabetical; groupwise con «Types», «Procedures», «Procedure groups», «Constants», «Variables», «Foreign imports») y :no-index:.

Los comentarios son líneas // o un bloque /* */ justo encima de una declaración, o al final de un campo o enumerador. Su texto plano se convierte a reStructuredText así:

  • Los párrafos siguen siendo párrafos; las líneas - item siguen siendo listas.
  • Un bloque indentado tras una línea vacía o acabada en dos puntos (Example:) se convierte en code-block:: odin, o text tras Output:. Una línea más indentada que el texto inmediatamente posterior a una línea de párrafo lo continúa.
  • Inputs: con elementos - name: text produce campos :param name:; Returns: produce :result name: o :returns: sin nombre, según el estilo de la biblioteca principal de Odin.
  • Una línea que empieza por NOTE: o WARNING: se convierte en nota o advertencia.
  • `code` es texto literal. Los demás caracteres de marcado (*, |, _ al final de palabra, etc.) se escapan para mostrar el comentario tal como se escribió y sin advertencias.

Páginas de la API

Con odin_autoapi_dirs, cada paquete obtiene una página al leerse, como sphinx-autoapi. api/shapes contiene odin:autopackage:: shapes con odin_autoapi_options; api/index lista paquetes y sinopsis. Son documentos del proyecto en toctree, búsqueda, índice, singlehtml y PDF, pero nunca se escriben en las fuentes. Opciones:

odin_autoapi_dirs

Carpetas de paquetes que obtendrán páginas, relativas a las fuentes. Solo se leen archivos bajo ellas y odin_collections; se rechazan enlaces hacia fuera.

odin_collections

Tabla de nombres de colecciones y carpetas, para argumentos como core:strings. Estos paquetes no obtienen páginas.

odin_autoapi_root

Carpeta de las páginas, "api" por defecto. Un documento fuente con el mismo nombre lo conserva y se emite una advertencia.

odin_autoapi_options

Por defecto ["members", "undoc-members"]; puede añadirse private-members.

odin_autoapi_member_order

"source" (predeterminado), "alphabetical" o "groupwise".

odin_autoapi_add_toctree_entry

true (predeterminado): api/index se añade al primer toctree del documento raíz.

odin_autoapi_generate_api_docs

true (predeterminado); false lee las carpetas solo para las directivas.

No se enlazan tipos de paquetes no documentados (core:io.Writer). Con -n, siléncialos mediante nitpick_ignore_regex = [["odin:type", "(core|base):.*"]]. Así se construye docs/api de Guidedog.

Plataformas

Se documentan los destinos según las reglas de Odin: *_windows.odin, *_linux_arm64.odin y *_amd64.odin solo corresponden a esos destinos; #+build linux, darwin y #+build !windows (también //+build antiguo) restringen más. Un when ODIN_OS == .Windows de archivo se divide por destino, incluido else, si solo compara ODIN_OS y ODIN_ARCH. Se omiten *_test.odin y #+ignore. Las declaraciones comunes aparecen una vez; las parciales indican «Availability: Windows». Cada firma distinta aparece con sus destinos, solo la primera con ID. Un paquete limitado indica :platform:.

Reconstrucción

Cada archivo Odin leído es una dependencia de su página. Tras editarlo, solo se releen las páginas de ese paquete. El índice se relee al añadir o quitar un paquete o cambiar su sinopsis. guidedog serve comprueba las fechas de odin_autoapi_dirs y odin_collections antes de servir HTML. Actualiza el navegador tras editar.

Limitaciones

  • Solo se analiza, sin compilar ni comprobar tipos: tipos y constantes se muestran tal como están, omitiendo valores de más de 100 caracteres, sin inferencia. A :: B se clasifica por nombres: uno que empiece en mayúscula sin ser todo mayúsculas, o un tipo integrado, se considera tipo.
  • Las condiciones when distintas de comparaciones de ODIN_OS y ODIN_ARCH no se evalúan: se documentan ambas ramas.
  • Los tipos privados se muestran como texto, pues no tienen entrada sin :private-members:. El paquete generado los enumera en :private:, así que -n no los denuncia.
  • core:odin/parser rechaza un procedimiento que combine #optional_ok y where. Se informa del archivo y se documenta lo que pudo leerse.
  • El parser Odin consume mucha pila al anidar: cientos de paréntesis pueden desbordar un hilo. Se omiten archivos muy por encima del código real (unos 50 niveles de paréntesis o tipos, o mil else encadenados), con odin.autodoc.nesting; se documenta el resto. when evalúa hasta 64 niveles de &&, || y !; más se considera no evaluado.