Skip to content

Add selectors API to Linter() for fast-path filtering#3052

Open
MichaelChirico wants to merge 8 commits into
mainfrom
linter-selector
Open

Add selectors API to Linter() for fast-path filtering#3052
MichaelChirico wants to merge 8 commits into
mainfrom
linter-selector

Conversation

@MichaelChirico

@MichaelChirico MichaelChirico commented May 27, 2026

Copy link
Copy Markdown
Collaborator

Another optimization hit on by Gemini -- basically declaring a set of tokens without which we can skip running a linter. These tokens are necessary but not sufficient to find lints.

There is some decent overlap with #2449 -- for file-level linters, this approach is not quite so effective since the % of files skipped is less than the % of expressions skipped.

As of now, the rough improvement on just the linters currently included is about 35%:

linters <- list(
  any_duplicated_linter(),
  keyword_quote_linter(),
  list_comparison_linter(),
  seq_linter(),
  sort_linter(),
  string_boundary_linter(),
  unreachable_code_linter()
)
system.time(for (ii in 1:2) {
  lint_package("bit64", linters)
  lint_package("lintr", linters)
  lint_package("ggplot2", linters)
  lint_package("data.table", linters)
  lint_package("~/svn/r-devel/src/library/utils", linters)
})

# PR
#    user  system elapsed 
# 177.669   1.078 178.796 
# main
#    user  system elapsed 
# 271.533   1.008 272.598 

I can extend it to more linters if we think this is a worthwhile addition.

Introduce a generic `selectors` API for token-based linter filtering.
Linters can now declare a character vector of required tokens or symbols
via the `selectors` argument in the `Linter()` constructor.

The core dispatch loop in `lint_impl_` checks these selectors against
the expression'\''s parse data (using fast vector matching) before running
the linter, skipping it instantly if no match is found.

Special `"BACKTICK"` selector is supported to handle R'\''s lack of a
dedicated backtick token.

Migrated 7 slow expression-level linters to this new API:
- unreachable_code_linter
- seq_linter
- any_duplicated_linter
- list_comparison_linter
- string_boundary_linter
- sort_linter
- keyword_quote_linter

TAG=agy
CONV=3167de05-de65-467a-876c-a7dcf1003aab
@MichaelChirico MichaelChirico requested a review from AshesITR May 27, 2026 14:36
@codecov

codecov Bot commented May 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.25%. Comparing base (e6126ca) to head (2ff952a).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3052   +/-   ##
=======================================
  Coverage   99.25%   99.25%           
=======================================
  Files         128      128           
  Lines        7369     7382   +13     
=======================================
+ Hits         7314     7327   +13     
  Misses         55       55           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant