Skip to content

fix(query-parser): stop treating dotted numbers as file-path filters - #870

Merged
dmtrKovalenko merged 1 commit into
dmtrKovalenko:mainfrom
kevin9327:fix/filename-constraint-version-tokens
Sep 12, 2026
Merged

dmtrKovalenko merged 1 commit into
dmtrKovalenko:mainfrom
kevin9327:fix/filename-constraint-version-tokens

Conversation

@kevin9327

@kevin9327 kevin9327 commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

The defect

Grepping for a version number or an IP address scopes the search to a file path
that does not exist, so the query returns nothing of its own and falls back to
unrelated results:

ffgrep { pattern: "192.168.1.1 timeout" }
  -> constraints: [FilePath("192.168.1.1")]     // expected: none

Constraint::is_filename_constraint_token decides which bare tokens become a
FilePath scope. Its own doc comment states the rule that keeps version-like
tokens out:

// Extension must exist and look like a real file extension:
// starts with an ASCII letter (rejects version numbers like "v2.0"),
// followed by alphanumeric chars, max 10 chars total.

The first clause is never implemented — only the "alphanumeric" part is:

!extension.is_empty()
    && extension.len() <= 10
    && extension.bytes().all(|b| b.is_ascii_alphanumeric())

v2.0 -> extension "0", 192.168.1.1 -> "1", 3.11 -> "11". All
non-empty, all alphanumeric, so all three become FilePath constraints.

test_file_picker_version_number_not_filename was written for exactly this
("v2.0 extension starts with digit -> not a filename constraint"), but it builds
its parser from FileSearchConfig, where enable_filename_constraint is false
by the trait default. The token never reaches the check, so the test passes
without exercising it — and it still passes both before and after this change.

Why it matters

enable_filename_constraint is on unconditionally in AiGrepConfig, the config
fff-mcp's grep tool parses every query with, and opt-in for :FFGrep via
grep.enable_filename_constraint. Both go through prefilter_with_filepath_retry,
so a query scoped to a path no file has matches nothing and is then re-run
repo-wide with the scope dropped — the caller gets "0 exact matches" followed by
hits that have nothing to do with the number it searched for.

The fix

Implement the documented first-character rule. starts_with on a char
predicate is false for an empty string, so it subsumes the is_empty check it
replaces.

Verification (Windows, default features)

RUSTUP_TOOLCHAIN was pinned to 1.98.0-x86_64-pc-windows-msvc because
rust-toolchain.toml's stable channel could not update on this machine.

New test test_dotted_numbers_are_not_filename_constraints runs the same
assertions through AiGrepConfig and through a config with
enable_filename_constraint enabled, mirroring the Neovim opt-in.

Before, cargo test -p fff-query-parser --lib -- test_dotted_numbers:

test parser::tests::test_dotted_numbers_are_not_filename_constraints ... FAILED

---- parser::tests::test_dotted_numbers_are_not_filename_constraints stdout ----

thread 'parser::tests::test_dotted_numbers_are_not_filename_constraints' (21644) panicked at crates\fff-query-parser\src\parser.rs:1500:17:
ai-grep: "192.168.1.1 timeout" must stay search text, got [FilePath("192.168.1.1")]

test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 89 filtered out

After:

test result: ok. 90 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

The same test pins what must not change, in both configs — these two assertions
pass before and after, so the rule only rejects digit-led extensions and does not
narrow real filenames:

  • schema.rs users still yields FilePath("schema.rs").
  • libswscale/input.c avframe still yields FilePath("libswscale/input.c").

test_file_picker_bare_filename_constraint,
test_file_picker_path_prefixed_filename_constraint,
test_file_picker_only_one_filepath_constraint and
test_file_picker_version_number_not_filename are unchanged and still pass.

  • cargo test -p fff-query-parser — 90 lib + 3 doc tests passed, 0 failed
    (baseline on unmodified upstream: 89 lib + 3 doc, 0 failed).
  • cargo test -p fff-search --lib — 162 passed, 0 failed.
  • cargo test -p fff-search --test grep_integration — 68 passed, 0 failed.
  • cargo test -p fff-mcp — 22 + 1 passed, 0 failed.
  • cargo fmt --all -- --check — clean.
  • cargo clippy -p fff-query-parser --all-targets — no warnings, same as
    unmodified upstream (delta 0).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved query parsing to distinguish filenames from dotted numeric values.
    • Numeric-leading extensions and dotted-number tokens such as IP addresses, version numbers, and decimal values now remain searchable text instead of being treated as file paths.
    • Valid filenames, including extensions beginning with letters, continue to be recognized as file path constraints.

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

coderabbitai Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 5cc042c8-a477-4f8e-b021-0729cb48cc08

📥 Commits

Reviewing files that changed from the base of the PR and between c3f2c7f and 2f6129c.

📒 Files selected for processing (2)
  • crates/fff-query-parser/src/constraints.rs
  • crates/fff-query-parser/src/parser.rs

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


📝 Walkthrough

Walkthrough

Filename constraint validation now rejects numeric-leading extensions. Parser tests confirm that dotted numbers remain search text while valid filenames still produce FilePath constraints.

Changes

Filename constraint validation

Layer / File(s) Summary
Extension validation and parser tests
crates/fff-query-parser/src/constraints.rs, crates/fff-query-parser/src/parser.rs
Filename extensions must begin with an ASCII letter. Tests cover dotted numbers and valid filenames for both parser configurations.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Suggested reviewers: dmtrkovalenko

Merge Risk: ⚪ Minimal · up to 2f612

The parser now keeps dotted numeric input as search text while retaining valid filename filters, with no actionable merge risk identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: dotted numbers are no longer treated as file-path filters.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 2 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Sep 12, 2026

Copy link
Copy Markdown

Confidence Score: 4/5

The implementation appears safe to merge, with a non-blocking gap in the regression test’s assertions.

The parser currently preserves dotted-number tokens as search text and the predicate change matches its documented contract; only the test’s ability to detect future token-loss regressions is incomplete.

Files Needing Attention: crates/fff-query-parser/src/parser.rs

Important Files Changed

Filename Overview
crates/fff-query-parser/src/constraints.rs Narrows implicit filename detection to alphabetic-led extensions, consistently implementing the documented rule.
crates/fff-query-parser/src/parser.rs Adds relevant regression cases, but verifies only constraint removal rather than preservation of the complete search text.

Reviews (1): Last reviewed commit: "fix(query-parser): stop treating dotted ..." | Re-trigger Greptile

Comment on lines +1500 to +1504
assert!(
result.constraints.is_empty(),
"{label}: {query:?} must stay search text, got {:?}",
result.constraints
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Search Text Is Unverified

This regression test only checks that dotted numbers produce no constraints. It does not verify that the complete token remains in the searchable text, so an implementation that accidentally discards the token would still pass and leave the reported search failure uncovered. Please also assert the resulting grep_text() or fuzzy-query contents for each case.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@dmtrKovalenko
dmtrKovalenko merged commit e208805 into dmtrKovalenko:main Sep 12, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants