{"id":49248935,"url":"https://github.com/jassielof/docent","last_synced_at":"2026-04-24T23:08:11.719Z","repository":{"id":344058522,"uuid":"1180273780","full_name":"jassielof/docent","owner":"jassielof","description":"A documentation linter for Zig that enforces doc comments, doctests, and container documentation with configurable severity levels.","archived":false,"fork":false,"pushed_at":"2026-04-14T19:42:55.000Z","size":122,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-14T21:27:28.798Z","etag":null,"topics":["build-options","build-tool","cli","doc","lib","library","linter","zig"],"latest_commit_sha":null,"homepage":"https://jassielof.github.io/docent/","language":"Zig","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jassielof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-12T22:00:27.000Z","updated_at":"2026-04-14T19:42:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jassielof/docent","commit_stats":null,"previous_names":["jassielof/zig-doc-lint","jassielof/docent"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jassielof/docent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jassielof%2Fdocent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jassielof%2Fdocent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jassielof%2Fdocent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jassielof%2Fdocent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jassielof","download_url":"https://codeload.github.com/jassielof/docent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jassielof%2Fdocent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32243804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-24T13:21:15.438Z","status":"ssl_error","status_checked_at":"2026-04-24T13:21:15.005Z","response_time":64,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build-options","build-tool","cli","doc","lib","library","linter","zig"],"created_at":"2026-04-24T23:08:11.186Z","updated_at":"2026-04-24T23:08:11.710Z","avatar_url":"https://github.com/jassielof.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Docent: Zig Documentation Linter\n\nDocent is a documentation linter for Zig.\n\nAvailable as a CLI, library, and build integration step (#1).\n\n## Behavior \u0026 Rules\n\n### Scanning\n\nIt expects a manifest file to be present in your current working directory, then scans the configured `.paths` entries.\n\nDirectory behavior:\n\n- If a directory contains `root.zig`, Docent treats it as an entrypoint and lints files that are publicly reachable from that root via `pub const ... = @import(\"...\")` chains.\n- If a directory has no `root.zig`, Docent treats each top-level `.zig` file as a module entrypoint and lints the union of their publicly reachable files.\n- If no top-level `.zig` files exist, Docent falls back to linting all `.zig` files in that directory tree.\n\nReachability notes:\n\n- Traversal is recursive across imported files, so multi-hop public chains are included.\n- Imports reachable only through non-public declarations are excluded.\n- Package imports (for example `@import(\"std\")`) are not treated as local lint targets.\n\nBuild script defaults:\n\n- `build.zig` and files under `build/` are ignored by default.\n  - Instead of files within the build directory, it's mostly all of those files that are used/imported by the main build script (`build.zig`).\n- This avoids false-positive API checks from build tooling paths that are commonly present in `build.zig.zon` `.paths`.\n- CLI users can opt in with `--include-build-scripts`.\n- Library users can opt in via `docent.targeting.Options{ .include_build_scripts = true }`.\n- Build integration users can opt in via `docent.addLintStep(..., .{ .include_build_scripts = true, ... })`.\n\n### Severities\n\nAll rules accept one of these levels:\n\n- `allow`: disable the rule.\n- `warn`: emit a diagnostic but do not fail the run.\n- `deny`: emit a diagnostic and count it as an error.\n- `forbid`: same behavior as `deny` for now. Either deny or forbid will have to be gone, I fell forbid is better to stay.\n\n### Rule: missing_doc_comment\n\nChecks public declarations for missing `///` documentation comments.\n\nWhat it checks:\n\n- Public functions.\n- Public constants and variables.\n- Fields inside container declarations.\n- Nested members inside container literals (for example `pub const Foo = struct { ... }`).\n\nRe-export behavior:\n\n- For `pub const Foo = @import(\"other.zig\").Bar`, the rule follows the import and checks docs on `Bar` in `other.zig`.\n- If `Bar` is documented, no diagnostic is emitted.\n- If `Bar` is undocumented, one diagnostic is emitted and points to `other.zig`.\n- If resolution fails (missing file, package import, parse failure), the re-export is skipped to avoid false positives.\n\nCurrent limit:\n\n- Re-export resolution is currently one-hop and root-declaration based. It does not perform full project/API reachability traversal.\n\n### Rule: empty_doc_comment\n\nChecks for doc comments that are present but blank.\n\nWhat it checks:\n\n- `///` comments with only whitespace after the prefix.\n- `//!` comments with only whitespace after the prefix.\n\n### Rule: missing_doctest\n\nChecks public function doctest coverage.\n\nWhat it checks:\n\n- Collects top-level `pub fn name(...)` declarations.\n- Collects identifier-style tests `test name { ... }`.\n- Emits a diagnostic when a public function has no matching identifier-style doctest.\n\nNotes:\n\n- String-literal test names (for example `test \"name\"`) are not counted as doctests for this rule.\n\n### Rule: private_doctest\n\nChecks that identifier-style doctests reference public symbols.\n\nWhat it checks:\n\n- Collects top-level public function names and public variable/constant names.\n- For each `test name { ... }`, emits a diagnostic if `name` is not public.\n\n### Rule: doctest_naming_mismatch\n\nChecks for style mismatch when a doctest name matches a public function but is written as a string literal.\n\nWhat it checks:\n\n- If `pub fn foo(...)` exists and the file uses `test \"foo\"`, it suggests using `test foo`.\n\n### Rule: missing_container_doc_comment\n\nChecks `//!` container doc comments.\n\nWhat it checks:\n\n- File-level module container doc comment (`//!`) near the beginning of the file.\n- Public container declarations assigned to `pub const` (for example `pub const Config = struct { ... }`) and recursively nested public containers.\n\nNote:\n\n- This rule exists for compatibility with current parser behavior around top-level/container doc comments and may evolve with Zig 0.16 changes.\n\n### Re-export resolution\n\nWhen a public declaration re-exports a symbol from another file using the\n`pub const Foo = @import(\"other.zig\").Bar` pattern, the linter follows the\nimport and evaluates the doc comment on the _original_ declaration rather than\non the re-export line:\n\n- If `Bar` in `other.zig` has a `///` doc comment → no diagnostic.\n- If `Bar` has no doc comment → one diagnostic pointing to `other.zig`, not to\n  the re-export site.\n- If the import path cannot be resolved (package imports such as `\"std\"`,\n  missing files, parse errors) → the re-export is silently skipped; no false positive is emitted.\n\nCurrent implementation detail:\n\n- Re-export checks are performed while linting the current file and resolving directly imported files. The linter does not currently compute full transitive API reachability for the entire package graph.\n\n## References\n\n### Rust\n\nThe user already has the two core Rust links. A third Clippy-specific lint is worth adding for private item coverage, since `rustc`'s `missing_docs` only covers public items: [github](https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/missing_doc.rs)\n\n- \u003chttps://doc.rust-lang.org/rustdoc/lints.html\u003e — full list of `rustdoc` lints (`missing_docs`, `missing_doc_code_examples`, `broken_intra_doc_links`, etc.) [doc.rust-lang](https://doc.rust-lang.org/rustdoc/lints.html)\n  - Zig docs seem to support intra links\n- \u003chttps://doc.rust-lang.org/beta/rustc/lints/listing/allowed-by-default.html#missing-docs\u003e — `rustc`-level `missing_docs` lint details (allowed by default, enable with `#![warn/deny(missing_docs)]`) [bsdwatch](https://bsdwatch.net/docs/sharedocs/rust/html/rustdoc/lints.html)\n- \u003chttps://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items\u003e — Clippy's `MISSING_DOCS_IN_PRIVATE_ITEMS` (restriction lint), which extends coverage to private items that `rustc` ignores [github](https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/missing_doc.rs)\n\n### Go\n\nGo has no compiler-level equivalent to `#![deny(missing_docs)]`. The canonical approach is through external linters, backed by the official doc comment spec: [go](https://go.dev/doc/comment)\n\n- \u003chttps://go.dev/doc/comment\u003e — official Go doc comment syntax specification (paragraphs, headings, links, lists, code blocks, and formatting rules enforced by `gofmt`) [go](https://go.dev/doc/comment)\n- \u003chttps://pkg.go.dev/go/doc/comment\u003e — `go/doc/comment` standard library package for parsing and reformatting doc comments programmatically [pkg.go](https://pkg.go.dev/go/doc/comment)\n- \u003chttps://github.com/godoc-lint/godoc-lint\u003e — dedicated godoc lint checker with rules like `require-doc`, `start-with-name`, `deprecated`, `max-len`, `no-unused-link`, and `require-stdlib-doclink` [github](https://github.com/godoc-lint/godoc-lint)\n- \u003chttps://golangci-lint.run/docs/linters/\u003e — `golangci-lint` integrates `godoclint` as a configurable linter runner with YAML-based rule configuration [golangci-lint](https://golangci-lint.run/docs/linters/)\n\n## Credits\n\nMainly Rust/Cargo's documentation (and probably Clippy too) linter checks, while also taking inspiration from Go's linting.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjassielof%2Fdocent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjassielof%2Fdocent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjassielof%2Fdocent/lists"}