Skip to content

Commit 45c0d95

Browse files
committed
feat(file-mentions): increase default max items and add noisy directory ignores
1 parent c6f2abf commit 45c0d95

2 files changed

Lines changed: 89 additions & 5 deletions

File tree

src/tests/file-mentions.test.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,62 @@ test("scanFileMentionItems returns relative slash-separated files and directorie
8686
try {
8787
fs.mkdirSync(path.join(root, "src"));
8888
fs.writeFileSync(path.join(root, "src", "index.ts"), "");
89-
fs.mkdirSync(path.join(root, "node_modules"));
90-
fs.writeFileSync(path.join(root, "node_modules", "ignored.js"), "");
89+
fs.mkdirSync(path.join(root, "vendor"));
90+
fs.writeFileSync(path.join(root, "vendor", "dep.js"), "");
9191

9292
assert.deepEqual(
9393
scanFileMentionItems(root).map((item) => item.path),
94-
["node_modules/", "node_modules/ignored.js", "src/", "src/index.ts"]
94+
["src/", "src/index.ts", "vendor/", "vendor/dep.js"]
9595
);
9696
} finally {
9797
fs.rmSync(root, { recursive: true, force: true });
9898
}
9999
});
100100

101+
test("scanFileMentionItems applies default noisy-directory ignores when no gitignore is applicable", () => {
102+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-file-mentions-"));
103+
try {
104+
for (const directory of [
105+
".next",
106+
".pytest_cache",
107+
".ruff_cache",
108+
"__pycache__",
109+
"build",
110+
"dist",
111+
"node_modules",
112+
"out",
113+
"target",
114+
]) {
115+
fs.mkdirSync(path.join(root, directory));
116+
fs.writeFileSync(path.join(root, directory, "ignored.txt"), "");
117+
}
118+
fs.mkdirSync(path.join(root, ".config"));
119+
fs.writeFileSync(path.join(root, ".config", "settings.json"), "");
120+
fs.mkdirSync(path.join(root, "src"));
121+
fs.writeFileSync(path.join(root, "src", "index.ts"), "");
122+
123+
assert.deepEqual(
124+
scanFileMentionItems(root).map((item) => item.path),
125+
[".config/", ".config/settings.json", "src/", "src/index.ts"]
126+
);
127+
} finally {
128+
fs.rmSync(root, { recursive: true, force: true });
129+
}
130+
});
131+
132+
test("scanFileMentionItems default max item cap is above 2000", () => {
133+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-file-mentions-"));
134+
try {
135+
for (let index = 0; index < 2001; index++) {
136+
fs.writeFileSync(path.join(root, `file-${index.toString().padStart(4, "0")}.txt`), "");
137+
}
138+
139+
assert.equal(scanFileMentionItems(root).length, 2001);
140+
} finally {
141+
fs.rmSync(root, { recursive: true, force: true });
142+
}
143+
});
144+
101145
test("scanFileMentionItems respects project gitignore patterns inside git repositories", () => {
102146
const root = fs.mkdtempSync(path.join(os.tmpdir(), "deepcode-file-mentions-"));
103147
try {

src/ui/core/file-mentions.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,20 @@ export type FileMentionToken = {
1515
quoted: boolean;
1616
};
1717

18-
const DEFAULT_MAX_ITEMS = 2000;
18+
const DEFAULT_MAX_ITEMS = 20000;
1919
const DEFAULT_MAX_DEPTH = 8;
20+
const DEFAULT_NOISY_DIR_NAMES = [
21+
".git",
22+
".next",
23+
".pytest_cache",
24+
".ruff_cache",
25+
"__pycache__",
26+
"build",
27+
"dist",
28+
"node_modules",
29+
"out",
30+
"target",
31+
];
2032

2133
type IgnoreMatcher = {
2234
base: string;
@@ -104,7 +116,8 @@ export function scanFileMentionItems(root: string, maxItems = DEFAULT_MAX_ITEMS)
104116
if (rootRealPath) {
105117
visitedDirectories.add(rootRealPath);
106118
}
107-
visit(root, 0, loadAncestorIgnoreMatchers(root, gitRoot));
119+
const initialMatchers = [...loadDefaultIgnoreMatchers(root, gitRoot), ...loadAncestorIgnoreMatchers(root, gitRoot)];
120+
visit(root, 0, initialMatchers);
108121
return items;
109122
}
110123

@@ -162,6 +175,33 @@ function loadDirectoryIgnoreMatchers(directory: string, gitRoot: string | null):
162175
return matchers;
163176
}
164177

178+
function loadDefaultIgnoreMatchers(root: string, gitRoot: string | null): IgnoreMatcher[] {
179+
if (hasApplicableGitignore(root, gitRoot)) {
180+
return [];
181+
}
182+
const patterns = DEFAULT_NOISY_DIR_NAMES.map((name) => `${name}/`);
183+
return [{ base: root, matcher: ignore().add(patterns) }];
184+
}
185+
186+
function hasApplicableGitignore(root: string, gitRoot: string | null): boolean {
187+
if (!gitRoot) {
188+
return false;
189+
}
190+
191+
const resolvedGitRoot = path.resolve(gitRoot);
192+
let current = path.resolve(root);
193+
while (isPathInsideOrEqual(current, resolvedGitRoot)) {
194+
if (fs.existsSync(path.join(current, ".gitignore"))) {
195+
return true;
196+
}
197+
if (current === resolvedGitRoot) {
198+
break;
199+
}
200+
current = path.dirname(current);
201+
}
202+
return false;
203+
}
204+
165205
function loadAncestorIgnoreMatchers(root: string, gitRoot: string | null): IgnoreMatcher[] {
166206
const resolvedRoot = path.resolve(root);
167207
const ancestors: string[] = [];

0 commit comments

Comments
 (0)