Skip to content

Document the Span → TextRange boundary contract and defer exact identifier spans in ddlint-design.md #252

@coderabbitai

Description

@coderabbitai

Background

Raised during review of PR #248 (implement-unused-variable-diagnostics).

The design document docs/ddlint-design.md currently states that rule-local Symbol::span() values are coarse provenance (pointing to the enclosing rule or literal site). This is correct for the current implementation. However, nothing in the document makes explicit:

  • that Span → TextRange conversion is the linter's responsibility, not the semantic model's;
  • that the coarse semantics of Symbol::span() must not be silently changed when exact identifier locations become desirable;
  • that exact identifier-token spans are a deferred milestone, not an oversight.

Without this written contract, the author of the next correctness rule may either duplicate the local conversion glue or quietly change Symbol::span() to point at the identifier token, breaking the coarse-provenance contract relied on by maps and debugging tooling.

Concern (Doggylump & Telefono)

Write the contract down before the next rule is started. One short addition to the design document is cheaper than a post-hoc migration.

Recommended change

Add a subsection to the relevant section of docs/ddlint-design.md (the semantic-model or diagnostic-rendering section) covering:

  1. Conversion ownership: the linter crate owns Span → rowan::TextRange conversion. The semantic model stores Span as coarse provenance; it does not vend TextRange.
  2. Stability of Symbol::span(): the existing span() accessor returns the coarse declaration or literal site. Its meaning must not change. If exact identifier-token location is required, a separate field (e.g. name_span or identifier_span) must be added additively.
  3. Deferred milestone: exact identifier-token spans are a planned but deferred semantic-model enhancement. Rules written before that milestone use coarse spans; rules written after may opt in to the precise field without breaking earlier rules.

Example wording (illustrative, not prescriptive)

Diagnostic range conversion. The semantic model stores all span information as Span (byte-offset pairs). Converting a Span to a rowan::TextRange for use in a LintDiagnostic is the linter's responsibility and is performed by the shared helper in src/linter/support/span.rs.
Symbol::span() returns coarse provenance — the enclosing rule or literal site — and its semantics are stable. When precise identifier-token location is required, add an additive name_span field to the relevant semantic record rather than redefining span().
Exact identifier-token spans are a deferred milestone; see roadmap item TBD.

Acceptance criteria

  • docs/ddlint-design.md contains an explicit statement that Span → TextRange conversion belongs to the linter.
  • The document states that Symbol::span() semantics are stable and must not be silently changed.
  • The document acknowledges exact identifier spans as a deferred milestone.
  • The roadmap references the new milestone (or an existing entry is updated).

Related

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions