Skip to content

Adopt yard-lint for structured YARD documentation linting#1190

Draft
myronmarston wants to merge 14 commits into
mainfrom
myron/yard-lint
Draft

Adopt yard-lint for structured YARD documentation linting#1190
myronmarston wants to merge 14 commits into
mainfrom
myron/yard-lint

Conversation

@myronmarston
Copy link
Copy Markdown
Collaborator

Summary

Adopts yard-lint to lint YARD documentation quality, addressing #913. The old docs_coverage task only checked whether public objects had a doc comment at all (100% coverage); yard-lint validates the quality of that documentation — missing @param tags, invalid type syntax, tag ordering, etc.

Infrastructure changes:

  • Add yard-lint ~> 1.5 gem
  • Add .yard-lint.yml config and .yard-lint-todo.yml baseline
  • New site:yard_lint rake task (calls yard-lint Ruby API to register custom @dynamic/@implements tags before parsing)
  • Rename docs_coverageyard_warnings (now only checks YARD parser warnings; coverage is handled by yard-lint)
  • Filter @private-tagged objects from yard-lint offenses (yard-lint bug: doesn't respect YARD's @private tag)

Documentation fixes (all 12 categories from the initial baseline):

  • EmptyCommentLine: remove trailing empty comment line
  • MarkdownSyntax: close unclosed backtick
  • TagTypePosition: type after param name
  • RedundantParamDescription: more specific param description
  • UndocumentedObjects: add docs for nullable? and highlightable?
  • InvalidTypes: [bool][Boolean], fix Array<String, :all>
  • BlankLineBeforeDefinition: remove blank lines between doc and def
  • OptionTags: add @option tags for mapping, json_schema, etc.
  • Tags/Order: reorder tags to match param, option, yield, return, raise, see, example, note
  • UndocumentedOptions: add @option/improve @param for **kwargs methods
  • CollectionType: Hash<K, V>Hash{K => V} across 32 files
  • UndocumentedMethodArguments: add @param tags across 52 files

Remaining in todo (11 entries, all legitimate exceptions):

  • BlankLineBeforeDefinition (3 files): section-header comments and copyright headers misidentified as orphaned docs
  • Tags/OptionTags (1 file): (see ...) cross-reference inherits tags that conflict with local @param
  • UndocumentedOptions (7 files): open-ended **kwargs forwarded to other systems where enumerating @option tags is impractical

Test plan

  • bundle exec rake site:yard_lint passes (0 offenses)
  • bundle exec rake site:yard_warnings passes (0 unexpected YARD parser warnings)
  • script/lint passes (0 offenses)
  • Verified yard-lint catches intentional breakage (removed doc from GraphQLEndpoint#call, confirmed offense detected)

🤖 Generated with Claude Code

myronmarston and others added 14 commits May 14, 2026 17:43
Replaces the janky regex-based doc coverage check with yard-lint, a
structured linter with per-check controls and gradual adoption support.
#913

The old `docs_coverage` task parsed YARD's text output to extract
coverage % and warning/error counts. Now yard-lint handles doc quality
(undocumented objects, tag validation, type checking, etc.) while the
renamed `yard_warnings` task retains only YARD parser warning/error
detection (e.g. "Undocumentable superclass" from Data.define) which
yard-lint doesn't cover.

Key details:
- yard-lint is invoked via Ruby API (not CLI) so we can register custom
  YARD tags (@dynamic, @implements) before parsing -- YardOptions in
  .yard-lint.yml only affects visibility filtering, not tag registration
- MinCoverage disabled because yard-lint counts all objects including
  private ones, which doesn't match YARD's --no-private behavior
- .yard-lint-todo.yml baselines 892 existing violations for gradual
  fix-up across 12 validators

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
yard-lint doesn't respect YARD's @Private tag — it only checks Ruby
visibility (public/private/protected). YARD's --no-private verifier
checks both `obj.visibility` AND `obj.tag(:private)` (walking up
ancestors), but yard-lint's QueryExecutor only does the former. This
caused 614 false-positive offenses on @Private classes.

Fix: filter offenses in our rake task by checking the YARD registry
after yard-lint runs. Regenerate .yard-lint-todo.yml with only the
278 real offenses (down from 892).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove empty trailing comment line in doc block for
FromDisk#graphql_schema_string.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Close unclosed backtick in TypeReference#as_static_derived_type doc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move type annotation after param name per YARD convention:
`@param updates [Hash{Symbol => Object}]` instead of
`@param [Hash<Symbol, Object>] updates`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace generic "element to check" param description with a
more specific one describing what kinds of schema elements
are expected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add docs for Field#highlightable? and Indexing::Field#nullable?.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- `[bool]` → `[Boolean]` (YARD type, not Ruby keyword)
- `Array<String, :all>` → `Array<String>, :all` (Array takes one
  type param; `:all` is an alternate value, not a second type param)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove blank lines between doc comments and their definitions in 5
files. The elasticsearch/opensearch client files remain excluded
because their offenses are section header comments (`# Cluster APIs`,
etc.) that yard-lint misidentifies as orphaned documentation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @option tags for methods that accept keyword options:
- HasTypeInfo#mapping: document all CUSTOMIZABLE_DATASTORE_PARAMS
- HasTypeInfo#json_schema: document common JSON schema keywords
- Field#json_schema: document :nullable option
- Field#mapping, ScalarType#mapping: note forwarding to HasTypeInfo
- HasIndices#initialize: note forwarding to super

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reorder YARD tags to match enforced order: param, option, yield,
yieldparam, yieldreturn, return, raise, see, example, note, todo.

The most common fix was moving @note after @example — most methods
had @note before @example. Also removed redundant @param/@option
tags on methods using `(see ...)` cross-references, since those
inherit all tags from the referenced method.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @option tags and improve @param descriptions for methods with
**kwargs. Methods with enumerable options (enum_value, type_namer,
namespace_type, graphql_formatter) got specific @option tags. Methods
with open-ended pass-through kwargs (api, has_indices, field, config)
got improved @param descriptions explaining where the options are
forwarded.

7 files remain in the todo for open-ended kwargs where @option tags
would be impractical/misleading.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace `Hash<K, V>` with `Hash{K => V}` in all YARD type annotations
per YARD's standard collection type syntax.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @param tags to 52 files where methods had doc comments but were
missing parameter documentation. This was the largest category (106
non-@Private offenses).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant