Skip to content

build: add format-args ESLint rule - #14518

Merged
kgryte merged 4 commits into
developfrom
philipp/format-args-lint-rule
Aug 22, 2026
Merged

kgryte merged 4 commits into
developfrom
philipp/format-args-lint-rule

Conversation

@Planeshifter

@Planeshifter Planeshifter commented Aug 22, 2026 •

Copy link
Copy Markdown
Member

Resolves stdlib-js/metr-issue-tracker#660.

Description

What is the purpose of this pull request?

This pull request:

  • adds a custom ESLint rule (stdlib/format-args) which verifies that calls to the format function exported by @stdlib/string/format are provided a number of arguments matching the number of placeholders in the format string.
  • registers the rule in the rules namespace and enables the rule in the ESLint configuration.

Implementation notes:

  • The rule uses @stdlib/string/base/format-tokenize to tokenize the format string and count placeholders. Escaped percent signs (%%) do not consume arguments, and dynamic widths and precisions (e.g., %*d and %.*f) each consume an additional argument.
  • Rather than blanket matching any identifier named format, the rule resolves each call expression's callee symbol via scope analysis (walking parent scopes and inspecting the nearest binding), thus guarding against shadowed symbols and unrelated symbols sharing the same name. Only symbols bound via require( '@stdlib/string/format' ) are checked.
  • The rule skips calls via #.call and #.apply, calls in which the format string is not a string literal, calls containing spread elements, and format strings containing positional placeholders (e.g., %1$s), as the latter may consume arguments out-of-order and/or reuse arguments.

Running the rule over all 13,722 files in the repository containing a string/format require statement surfaced two genuine bugs and zero false positives. Fixes for those bugs were submitted separately in #14517.

Related Issues

Does this pull request have any related issues?

This pull request has the following related issues:

Questions

Any questions for reviewers of this pull request?

No.

Other

Any other information relevant to this pull request? This may include screenshots, references, and/or implementation notes.

A shared scope-resolution utility (as floated in the issue) was not created, as the nearest-binding scope walk is ~25 lines and currently has only two potential call sites (this rule and no-builtin-big-int); extracting a common _tools/eslint/utils package can be revisited if a third rule needs it.

Checklist

Please ensure the following tasks are completed before submitting this pull request.

AI Assistance

When authoring the changes proposed in this PR, did you use any kind of AI assistance?

  • Yes
  • No

If you answered "yes" above, how did you use AI assistance?

  • Code generation (e.g., when writing an implementation or fixing a bug)
  • Test/benchmark generation
  • Documentation (including examples)
  • Research and understanding

Disclosure

If you answered "yes" to using AI assistance, please provide a short disclosure indicating how you used AI assistance. This helps reviewers determine how much scrutiny to apply when reviewing your contribution. Example disclosures: "This PR was written primarily by Claude Code." or "I consulted ChatGPT to understand the codebase, but the proposed changes were fully authored manually by myself.".

This PR was written by Claude Code under my direction and instructions, following existing rule packages as templates.


@stdlib-js/reviewers

Adds a custom ESLint rule which verifies that calls to the format
function exported by `@stdlib/string/format` are provided a number
of arguments matching the number of placeholders in the format
string. The rule resolves the callee symbol via scope analysis in
order to guard against shadowing and unrelated symbols sharing the
same name, and skips calls via `#.call` and `#.apply`, calls in
which the format string is not a string literal, calls containing
spread elements, and format strings containing positional
placeholders.

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

---
type: pre_commit_static_analysis_report
description: Results of running static analysis checks when committing changes.
report:
  - task: lint_filenames
    status: passed
  - task: lint_editorconfig
    status: passed
  - task: lint_markdown_pkg_readmes
    status: passed
  - task: lint_markdown_docs
    status: na
  - task: lint_markdown
    status: na
  - task: lint_package_json
    status: passed
  - task: lint_repl_help
    status: na
  - task: lint_javascript_src
    status: passed
  - task: lint_javascript_cli
    status: na
  - task: lint_javascript_examples
    status: passed
  - task: lint_javascript_tests
    status: passed
  - task: lint_javascript_benchmarks
    status: na
  - task: lint_python
    status: na
  - task: lint_r
    status: na
  - task: lint_c_src
    status: na
  - task: lint_c_examples
    status: na
  - task: lint_c_benchmarks
    status: na
  - task: lint_c_tests_fixtures
    status: na
  - task: lint_shell
    status: na
  - task: lint_typescript_declarations
    status: passed
  - task: lint_typescript_tests
    status: na
  - task: lint_license_headers
    status: passed
---
@Planeshifter
Planeshifter force-pushed the philipp/format-args-lint-rule branch from 2a1ba12 to 730cfb5 Compare August 22, 2026 05:43
@Planeshifter Planeshifter changed the title feat: add format-args ESLint rule build: add format-args ESLint rule Aug 22, 2026
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---
type: pre_commit_static_analysis_report
description: Results of running static analysis checks when committing changes.
report:
  - task: lint_filenames
    status: passed
  - task: lint_editorconfig
    status: passed
  - task: lint_markdown_pkg_readmes
    status: passed
  - task: lint_markdown_docs
    status: na
  - task: lint_markdown
    status: na
  - task: lint_package_json
    status: passed
  - task: lint_repl_help
    status: na
  - task: lint_javascript_src
    status: na
  - task: lint_javascript_cli
    status: na
  - task: lint_javascript_examples
    status: na
  - task: lint_javascript_tests
    status: na
  - task: lint_javascript_benchmarks
    status: na
  - task: lint_python
    status: na
  - task: lint_r
    status: na
  - task: lint_c_src
    status: na
  - task: lint_c_examples
    status: na
  - task: lint_c_benchmarks
    status: na
  - task: lint_c_tests_fixtures
    status: na
  - task: lint_shell
    status: na
  - task: lint_typescript_declarations
    status: passed
  - task: lint_typescript_tests
    status: na
  - task: lint_license_headers
    status: passed
---
@Planeshifter
Planeshifter marked this pull request as ready for review August 22, 2026 06:01
@Planeshifter
Planeshifter requested a review from a team August 22, 2026 06:01
@stdlib-bot stdlib-bot added the Needs Review A pull request which needs code review. label Aug 22, 2026
@@ -1 +1 @@
/* eslint-disable stdlib/jsdoc-doctest-marker, stdlib/jsdoc-example-require-spacing, stdlib/jsdoc-no-tabs */

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automatically removed by our ESLint autofix because these are not needed anymore here.

kgryte pushed a commit that referenced this pull request Aug 22, 2026
PR-URL: #14517
Reviewed-by: Athan Reines <kgryte@gmail.com>
Ref: #14518
Signed-off-by: Athan <kgryte@gmail.com>
Comment thread lib/node_modules/@stdlib/_tools/eslint/rules/format-args/test/fixtures/invalid.js Outdated
Comment thread lib/node_modules/@stdlib/_tools/eslint/rules/format-args/test/fixtures/valid.js Outdated
Co-authored-by: Athan <kgryte@gmail.com>
Signed-off-by: Athan <kgryte@gmail.com>

@kgryte kgryte left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@kgryte
kgryte merged commit f6bb7cb into develop Aug 22, 2026
10 checks passed
@kgryte
kgryte deleted the philipp/format-args-lint-rule branch August 22, 2026 08:15
@stdlib-bot stdlib-bot removed the Needs Review A pull request which needs code review. label Aug 22, 2026
@Planeshifter Planeshifter added the METR Pull request associated with the METR project. label Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

METR Pull request associated with the METR project.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[RFC]: add lint rule to ensure string/format is provided an expected number of arguments

3 participants