objectionary / objectionary/lints

Linter doesn't flag usage of manual identity object instead of `I` glyph

Open
#1,317 0 comments 0 reactions 1 assignee View on GitHub

@yegor256 is already working on this.

Since Aug 28, 2026.

enhancement good-title
Dominant language
Java
Stars
14
Forks
39
Avg merge
22h 54m
Merged PRs (30d)
90

Description

The language has a glyph for the identity object — I, which is
[x] > (φ ↦ x). Still, we keep writing that object out by hand. In
objectionary/eo both printf.eo and as-decimal.eo carried a hand-made
one-attribute formation that a glyph could spell, and nothing complained
(objectionary/eo#7822). I'd like a lint that catches an identity object
wherever it exists and suggests replacing it with I.

Incorrect:

# Jeff.
[] > jeff
  x > [x] >> id
  foo id > @
# Jeff.
[] > jeff
  [value] > pass
    value > @
  foo pass > @

Correct:

# Jeff.
[] > jeff
  foo I > @

What to catch

A formation is the identity object when it binds exactly one void, decorates
that very void, and holds nothing else. In XMIR that is:

<o name="id">
  <o name="x" base="∅"/>
  <o name="φ" base="ξ.x"/>
</o>

The predicate already exists, in eo:identity of eo's
eo-printer/src/main/resources/org/eolang/printer/print/to-eo-tree.xsl
(objectionary/eo#6834), where the printer uses it to print any such formation
back as the glyph:

eo:abstract($o) and not(eo:has-data($o)) and count($o/o) = 2
  and eo:void($o/o[1]) and empty($o/o[1]/(@local, @type, @args))
  and $o/o[2]/@name = $eo:phi and empty($o/o[2]/o)
  and empty($o/o[2]/@const)
  and $o/o[2]/@base = concat($eo:xi, '.', $o/o[1]/@name)

The tight tests there are load-bearing and worth keeping: exactly two children,
because a third is an argument applied to the formation and the glyph has
nowhere to put it; and the φ base rooted at ξ, because an unrooted name
denotes some other object entirely.

The one catch

I desugars to precisely the same XMIR — eo's Emissions.identity emits a
baseless object, a void named x, and a φ bound to it — so a lint that matches
the shape alone would flag every use of the glyph, I > sanitized included.
Two ways out, and I have no strong preference:

  1. Have eo's parser mark the desugared glyph (an attribute on the <o>), and
    let the lint report the shape only where the mark is absent. Cleanest, but it
    needs a change in eo first.
  2. Tell them apart by position: for the desugared glyph the formation, its void
    and its φ all carry the same @line and @pos, since all three come from
    the one character; a hand-written formation spreads over more than one line
    or more than one column. No change in eo needed, at the price of a heuristic.

Deliverables

  • src/main/resources/org/eolang/lints/misc/identity-object.xslwarning
    severity, and maybe experimental="true" at first, the way
    design/no-attribute-formation.xsl does it
  • src/main/resources/org/eolang/motives/misc/identity-object.md
  • a test pack under
    src/test/resources/org/eolang/lints/packs/single/identity-object/, with a
    catching case and a no-catch case — the no-catch one guarding against the
    false positive above, plus the near misses the predicate must let through: a
    formation with two voids, one whose φ is applied to something, and one whose φ
    reaches a name that isn't its void

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.