Skip to content

Fix/adfa 4514 [KDoc-to-JSON plugin]#18

Open
alexmmiller wants to merge 10 commits into
mainfrom
fix/ADFA-4514
Open

Fix/adfa 4514 [KDoc-to-JSON plugin]#18
alexmmiller wants to merge 10 commits into
mainfrom
fix/ADFA-4514

Conversation

@alexmmiller

Copy link
Copy Markdown
Collaborator

Plugin for Dokka that intercepts the HTML rendering process to output raw JSON data in its place.

alexmmiller and others added 8 commits July 1, 2026 15:42
configJson was a dedicated Json instance used only for the manual
config-decode fallback path. Inlining it removes the standalone
property while keeping the same ignoreUnknownKeys tolerance for
extra keys in user-authored plugin config.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- scripts/verify_package_index.py: confirms every object listed in a
  package's index.json actually has documented content on the page its
  url points to (matching by dri), not just that the file exists.
- scripts/kotlin/test_kotlin_stdlib.sh: pure-bash check that the
  default HTML build and the kdoc-to-json JSON build have a one-to-one
  set of pages (extension-swap aware, in both directions).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidschachterADFA

Copy link
Copy Markdown
Collaborator

From Claude AI:

Issues found

  1. omitNulls config option almost certainly doesn't work as documented.
    In JsonPluginConfig.kt:

kotlin
@SerialName("omit-nulls")
val omitNulls: Boolean = false,

Every other field in this data class relies on its default (property-name-matching) serial name — this is the only one with a custom @SerialName, and it maps to kebab-case "omit-nulls" instead of "omitNulls". But the README's own config example (section 3) and its config table both show:

json
{ ..., "omitNulls": true }

Since parsing goes through kotlinx.serialization either via Dokka's native config decoder or the manual Json { ignoreUnknownKeys = true } fallback in JsonRenderer.kt, a user who copies the README's example verbatim will have "omitNulls" silently treated as an unknown key, and omitNulls will stay at its default false — with no error, since ignoreUnknownKeys swallows it. This seems like a stale/accidental annotation (every other field name should probably work here) rather than an intentional key rename. Worth fixing the annotation (or the docs, if kebab-case really is intended) and probably adding a quick round-trip test on JsonPluginConfig to catch this class of bug in future.

  1. README section 7 ("Resolving Cross-Module Links") describes behavior the code doesn't actually implement.
    The README says an unresolved DRI "means the LinkPostProcessor failed to find that DRI" and implies you'd inspect the output for unresolved:... strings to debug it. But in LinkPostProcessor.kt:

kotlin
val replaced = unresolvedRegex.replace(text) { matchResult ->
val dri = matchResult.groupValues[1]
val resolved = driIndex[dri]
if (resolved != null) { ...; "$rootPrefix$resolved" } else { "#" }
}

Every unresolved: gets rewritten in this same pass — resolved ones become a relative path, unresolved ones become a bare "#". So the final on-disk JSON never actually contains an unresolved: string to grep for; the documented troubleshooting technique (search rendered JSON for unresolved:) won't find anything even when links failed to resolve. If diagnosing failed resolutions is meant to be possible, the plugin needs to log which DRIs fell through to "#" (it currently doesn't — only a final aggregate "Successfully resolved $replacedCount..." count is logged, with no count/list of failures), or the docs should stop implying you can find them by inspecting output.

  1. Minor: inconsistent error handling between LinkPostProcessor's two passes.
    Pass 1 (building the DRI index) wraps each file in try/catch and logs+continues on failure. Pass 2 (the actual rewrite) has no such guard — a single unreadable/unwritable file (permissions, disk full, concurrent modification) throws and aborts the whole post-process step, leaving every other file's links unpatched even though the index was already built successfully. Worth matching pass 1's resilience here, especially since this runs as the last step of a potentially long Dokka build.

  2. Minor: driIndex[dri] = fullUrl in extractDris silently last-writer-wins if the same DRI resolves to a URL in more than one file (plausible with expect/actual declarations across source sets). Not necessarily wrong, but undocumented — a one-line comment on why last-wins is fine (or a warning when it happens) would help a future reader trust this is intentional rather than an oversight.

On the "sourceSet whitelisting" commits

The last two commits (sourceSet whitelisting, Whitelist sourceSets per ADFA-4737) look purposeful and match a real ticket, and the whitelist logic itself (in JsonRenderer/ModelMapper) looks correct from what I read. I'd suggest double-checking verify_sourceset_whitelist.py gets run against a real kotlin-stdlib build with a whitelist configured, as part of this PR's test plan — I didn't see that confirmation anywhere in the PR description (there's no "Test plan" checklist here at all, unlike #21).

Suggestion: given the size (10 commits, an entire new Gradle module) and no test plan in the description, it'd help reviewers if the PR description at least linked a sample run's output (e.g. from scripts/build-example.sh or test_kotlin_stdlib.sh) so they don't have to build the whole thing locally to sanity-check items 1–2 above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants