Skip to content

Bug: @ file completion shows submodule folder but no files inside it #4568

@undici77

Description

@undici77

What happened?

When typing @ in the prompt to insert a file reference, the autocomplete suggestion list shows submodule directories but lists no files inside them. Only files from the root (parent) repository are reachable via @ completion.

Steps to reproduce:

  1. Open a project that contains one or more Git submodules.
  2. Start typing @ in the prompt to trigger file completion.
  3. Navigate into the submodule folder: it appears in the list, but expanding it shows nothing.

What did you expect to happen?

Files tracked inside the submodule should be listed under their submodule directory, exactly as they appear on disk and in git ls-files --recurse-submodules. For example, if the project has a submodule at third-party/lib with a file src/helpers.ts, then @third-party/lib/src/helpers.ts should be selectable.

Client information

Client Information
  • Version: 0.16.1
  • Affected file: packages/core/src/utils/filesearch/crawler.ts
  • Platform: Linux / macOS / Windows (any OS where Git submodules are used)

Login information

Introduced in commit 664208c ("feat(core): replace fdir crawler with git ls-files + ripgrep fallback").

The file crawler in packages/core/src/utils/filesearch/crawler.ts uses git ls-files --cached to enumerate tracked files. Without the --recurse-submodules flag, Git returns each submodule as a single opaque entry (the submodule commit SHA recorded in the parent index) rather than recursing into it and listing its individual files.

- const trackedArgs = ['--literal-pathspecs', 'ls-files', '--cached'];
+ const trackedArgs = ['--literal-pathspecs', 'ls-files', '--cached', '--recurse-submodules'];

The previous crawling strategy (fdir / ripgrep) was purely filesystem-based and naturally descended into submodule directories, so this is a regression.

The inconsistency is also visible in the fallback paths: if git ls-files fails for any reason, the ripgrep/fdir fallback kicks in and does return submodule files: meaning the same project can see different results depending on which code path runs.

Fix

Add --recurse-submodules to the git ls-files --cached invocation. Git explicitly supports the -t output-format flag alongside --recurse-submodules (--others/--deleted modes are the unsupported ones). If the flag is unavailable on a very old Git version, the command will fail and the ripgrep/fdir fallback will handle it transparently.

A regression test that creates a real parent repo with a real submodule and verifies crawler output has been added in packages/core/src/utils/filesearch/crawler.test.ts.

Anything else we need to know?

The status === 'S' guard in processTrackedFile (line 1071) was not related to submodules: S in git ls-files -t output is the skip-worktree flag used by sparse checkouts, not a submodule marker. Submodule commit entries appear with status H without --recurse-submodules and are replaced by the actual contained files when --recurse-submodules is active.

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.16.0category/coreCore engine and logicpriority/P2Medium - Moderately impactful, noticeable problemscope/file-operationsFile system operationsscope/gitGit integration featuresscope/ideIDE integration generalstatus/needs-triageIssue needs to be triaged and labeledtype/bugSomething isn't working as expected

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions