Skip to content

Commit dc72abf

Browse files
committed
fix:修正选择文件时的错误筛选
1 parent a83c6c1 commit dc72abf

File tree

1 file changed

+70
-46
lines changed

1 file changed

+70
-46
lines changed

src/fileSelector.ts

Lines changed: 70 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,80 +18,104 @@ const EXCLUDED_DIRECTORIES = [
1818
]; // 排除目录
1919

2020
/**
21-
* 解析 ignore 文件内容并返回匹配模式数组
22-
* @param filePath ignore 文件路径
23-
* @returns 过滤模式数组
21+
* 解析 .gitignore 文件,返回正向模式和反向模式
22+
* @param filePath .gitignore 文件路径
23+
* @returns { ignorePatterns: string[], includePatterns: string[] }
2424
*/
25-
function parseIgnoreFile(filePath: string): string[] {
25+
function parseGitignore(filePath: string): { ignorePatterns: string[], includePatterns: string[] } {
2626
try {
2727
const content = fs.readFileSync(filePath, 'utf8');
28-
return content
29-
.split('\n')
30-
.map(line => line.trim())
31-
.filter(line =>
32-
line && // 非空行
33-
!line.startsWith('#') && // 不是注释
34-
!line.startsWith('!') // 不是反向模式
35-
)
36-
.map(pattern => {
37-
// 转换 gitignore 风格的模式为 glob 模式
38-
if (pattern.endsWith('/')) {
39-
return `**/${pattern}**`;
40-
}
41-
return `**/${pattern}`;
42-
});
28+
const lines = content.split('\n').map(line => line.trim()).filter(line => line && !line.startsWith('#'));
29+
const ignorePatterns: string[] = [];
30+
const includePatterns: string[] = [];
31+
lines.forEach(line => {
32+
if (line.startsWith('!')) {
33+
includePatterns.push(line.slice(1)); // 去掉 '!',作为强制包含模式
34+
} else {
35+
ignorePatterns.push(line);
36+
}
37+
});
38+
return { ignorePatterns, includePatterns };
4339
} catch (error) {
44-
return [];
40+
return { ignorePatterns: [], includePatterns: [] };
4541
}
4642
}
4743

44+
/**
45+
* 检查文件是否匹配某个模式(简单的手动匹配)
46+
* @param filePath 文件路径
47+
* @param pattern 模式
48+
* @returns 是否匹配
49+
*/
50+
function matchesPattern(filePath: string, pattern: string): boolean {
51+
const basename = path.basename(filePath);
52+
if (pattern.startsWith('*') && pattern.includes(',')) {
53+
const exactExtension = pattern.slice(1); // 去掉前面的 *,保留 .py,cover
54+
return basename.endsWith(exactExtension);
55+
}
56+
// 其他简单模式(可以扩展支持更多规则)
57+
return basename === pattern || filePath.includes(pattern);
58+
}
59+
4860
/**
4961
* 显示文件选择器,并返回用户选择的文件列表
5062
* @returns 用户选择的文件路径数组
5163
*/
5264
export async function selectFiles(): Promise<string[]> {
53-
// 检查是否打开了工作区
5465
const workspaceFolders = vscode.workspace.workspaceFolders;
5566
if (!workspaceFolders) {
5667
vscode.window.showErrorMessage('No workspace folder found.');
5768
return [];
5869
}
5970

6071
const rootPath = workspaceFolders[0].uri.fsPath;
61-
62-
// 构建默认排除模式数组
63-
const defaultExcludePatterns = EXCLUDED_DIRECTORIES.map(dir => `**/${dir}/**`);
64-
65-
// 获取 ignore 文件的模式
66-
let ignorePatterns: string[] = [];
6772
const gitignorePath = path.join(rootPath, '.gitignore');
68-
69-
if (fs.existsSync(gitignorePath)) {
70-
ignorePatterns = ignorePatterns.concat(parseIgnoreFile(gitignorePath));
71-
}
73+
const { ignorePatterns, includePatterns } = fs.existsSync(gitignorePath) ? parseGitignore(gitignorePath) : { ignorePatterns: [], includePatterns: [] };
7274

73-
// 合并所有排除模式并确保是扁平结构
74-
const allExcludePatterns = [...defaultExcludePatterns, ...ignorePatterns];
75-
const excludePattern = allExcludePatterns.length > 0
76-
? `{${allExcludePatterns.join(',')}}`
77-
: undefined;
78-
79-
// 1. 匹配白名单文件名
75+
// 获取所有符合扩展名和文件名的文件
8076
const filenamePattern = `**/{${ALLOWED_FILENAMES.join(',')}}`;
81-
const filenameFiles = await vscode.workspace.findFiles(filenamePattern, excludePattern);
82-
83-
// 2. 匹配扩展名文件
8477
const extensionPattern = `**/*.{${INCLUDED_EXTENSIONS.join(',')}}`;
85-
const extensionFiles = await vscode.workspace.findFiles(extensionPattern, excludePattern);
78+
const filenameFiles = await vscode.workspace.findFiles(filenamePattern);
79+
const extensionFiles = await vscode.workspace.findFiles(extensionPattern);
8680

87-
// 3. 合并结果并去重
81+
// 合并并去重
8882
const allFiles = [...filenameFiles, ...extensionFiles];
8983
const uniqueFiles = Array.from(new Set(allFiles.map(file => file.fsPath)));
9084

91-
// 4. 显示文件选择面板
92-
const selectedItems = await vscode.window.showQuickPick(uniqueFiles, {
85+
// 手动过滤
86+
const filteredFiles = uniqueFiles.filter(filePath => {
87+
const relativePath = path.relative(rootPath, filePath);
88+
89+
// 检查排除目录
90+
for (const dir of EXCLUDED_DIRECTORIES) {
91+
if (relativePath.startsWith(dir + path.sep)) {
92+
return false;
93+
}
94+
}
95+
96+
// 检查 .gitignore 模式
97+
let shouldIgnore = false;
98+
for (const pattern of ignorePatterns) {
99+
if (matchesPattern(filePath, pattern)) {
100+
shouldIgnore = true;
101+
break;
102+
}
103+
}
104+
// 检查反向模式(强制包含)
105+
for (const pattern of includePatterns) {
106+
if (matchesPattern(filePath, pattern)) {
107+
shouldIgnore = false; // 强制包含
108+
break;
109+
}
110+
}
111+
112+
return !shouldIgnore;
113+
});
114+
115+
// 显示选择面板
116+
const selectedItems = await vscode.window.showQuickPick(filteredFiles, {
93117
placeHolder: 'Select files to include in the refactoring',
94-
canPickMany: true, // 允许多选
118+
canPickMany: true,
95119
});
96120

97121
// 返回用户选择的文件

0 commit comments

Comments
 (0)