objectionary / objectionary/lints
`sprintf-constant-args` selects the removed `Φ.txt.sprintf`, so the rule never fires on current EO
@yegor256 is already working on this.
Since Sep 8, 2026.
- Dominant language
- Java
- Stars
- 14
- Forks
- 39
- Avg merge
- 22h 54m
- Merged PRs (30d)
- 90
Description
sprintf-constant-args selects an object current EO does not have, so the rule can never fire on real code.
src/main/resources/org/eolang/lints/misc/sprintf-constant-args.xsl:20:
<xsl:for-each select="//o[@base='Φ.txt.sprintf'][count(o)=2][o[2][@base='Φ.tuple']]">
There is no txt package in objectionary/eo any more, and no sprintf object anywhere in the runtime. Formatting is eo-runtime/src/main/eo/string/printf.eo, reached as a method on the format string, so a parsed XMIR carries a dispatch:
$ grep -rl "txt.sprintf" eo-runtime/target/eo/1-parse/
(nothing)
$ grep -o 'base="[^"]*printf[^"]*"' eo-runtime/target/eo/1-parse/bytes/as-i16.xmir
base=".printf"
Every one of the eight packs feeds the rule txt.sprintf, so the suite stays green while nothing in a real program is ever examined.
The check itself is worth keeping: a format template that is a literal, with arguments that are all literal strings, has a result known at parse time and should be written as one string.
Root cause
The shape of the call changed with the object. "fmt".printf (* args) puts the template on the receiver, which a real XMIR emits as the child without an as attribute, and leaves exactly one argument:
<o base=".printf">
<o base="Φ.string">…the format…</o>
<o as="α0" base="Φ.tuple">…the arguments…</o>
</o>
(checked against eo-runtime/target/eo/1-parse/bytes/as-i16.xmir)
so count(o)=2 still holds, but o[1] is the template rather than o[2] being the tuple, and @base is .printf.
Suggested fix
<xsl:for-each select="//o[@base='.printf'][o[@as][1][@base='Φ.tuple']]">
<xsl:variable name="text" select="o[not(@as)][1][@base='Φ.string']/o[1][@base='Φ.bytes']/o/text()"/>
...
<xsl:apply-templates select="o[@as][1]" mode="constant-args"/>
with the message naming .printf, and the packs rewritten to the current call form so they exercise something the parser can actually produce.
Counting the formatters needs the same treatment as in #1355: the byte pairs 2573, 2564, 2566, 2578, 2562 miss every specifier that carries a flag, a width or a precision, so "%08.2f" counts as zero formatters and the rule stays silent on a call it should examine.
Two sibling rules have the same dead selector and are reported separately, since each needs its own adaptation: #1355 is about arity and tuple shape, #1357 about the template's content, and this one about arguments that are all literals.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.