🐛 fix(vscode): 代码阅读工作区索引跳过嵌套的 checkout 和忽略文件忽略的,任务名不再查到两处
This commit is contained in:
1 parent
de355661f0
commit
113b02657c
7 files changed
+202
-12
No files matched your search
@@ -1,8 +1,10 @@
|
||||
import type { WorkspaceFolder } from 'vscode'
|
||||
import type { IndexHost, WorkspaceFile } from './workspaceIndex'
|
||||
import type { FolderReader } from './workspaceScope'
|
||||
import * as path from 'node:path'
|
||||
import { minimatch } from 'minimatch'
|
||||
import { RelativePattern, Uri, workspace } from 'vscode'
|
||||
import { folderScope } from './workspaceScope'
|
||||
|
||||
/** 建索引时总不看的目录:虚拟环境、依赖、Python 字节码缓存。 */
|
||||
const ALWAYS_EXCLUDED = ['**/.venv', '**/node_modules', '**/__pycache__']
|
||||
@@ -36,17 +38,34 @@ function workspaceFile(uri: Uri): { file: WorkspaceFile, folder: WorkspaceFolder
|
||||
return { folder, file: { uri: uri.toString(), folder: folder.uri.toString(), path: path.posix.relative(folder.uri.path, uri.path) } }
|
||||
}
|
||||
|
||||
/** 库规则的工作区索引在 VS Code 里怎么找文件、读文件、盯改动;解析交给调用方(语言插件 + 解析运行时)。 */
|
||||
/** 这个工作区文件夹里还要跳过的(嵌套的 checkout、忽略文件忽略的),见 folderScope;忽略文件按 search.useIgnoreFiles。 */
|
||||
function scopeOf(folder: WorkspaceFolder): ReturnType<typeof folderScope> {
|
||||
const at = (path: string): Uri => Uri.joinPath(folder.uri, path)
|
||||
const reader: FolderReader = {
|
||||
exists: path => Promise.resolve(workspace.fs.stat(at(path))).then(() => true, () => false),
|
||||
read: path => Promise.resolve(workspace.fs.readFile(at(path))).then(bytes => new TextDecoder('utf-8').decode(bytes), () => undefined),
|
||||
}
|
||||
return folderScope(reader, workspace.getConfiguration('search', folder.uri).get<boolean>('useIgnoreFiles', true))
|
||||
}
|
||||
|
||||
/**
|
||||
* 库规则的工作区索引在 VS Code 里怎么找文件、读文件、盯改动;解析交给调用方(语言插件 + 解析运行时)。
|
||||
* 不看的:files.exclude、search.exclude 排除的、总不看的目录,加上嵌套的 checkout 和忽略文件忽略的(见 folderScope)。
|
||||
* 插件声明的引擎版本(^1.97)的正式 API 里 findFiles 不能按忽略文件筛,所以忽略文件自己读。
|
||||
*/
|
||||
export function workspaceIndexHost(parse: IndexHost['parse'], report: IndexHost['report']): IndexHost {
|
||||
return {
|
||||
async list(include) {
|
||||
const found = await Promise.all((workspace.workspaceFolders ?? []).map(async (folder) => {
|
||||
const patterns = excludedPatterns(folder)
|
||||
const scope = scopeOf(folder)
|
||||
const uris = await workspace.findFiles(new RelativePattern(folder, include), excludeGlob(patterns))
|
||||
return uris.flatMap((uri) => {
|
||||
const files = uris.flatMap((uri) => {
|
||||
const file = workspaceFile(uri)?.file
|
||||
return file && !isExcluded(file.path, patterns) ? [file] : []
|
||||
})
|
||||
const skipped = await Promise.all(files.map(file => scope.skips(file.path)))
|
||||
return files.filter((_, i) => !skipped[i])
|
||||
}))
|
||||
return found.flat()
|
||||
},
|
||||
@@ -54,9 +73,11 @@ export function workspaceIndexHost(parse: IndexHost['parse'], report: IndexHost[
|
||||
return new TextDecoder('utf-8').decode(await workspace.fs.readFile(Uri.parse(file.uri)))
|
||||
},
|
||||
watch(include, listener) {
|
||||
const forward = (kind: 'change' | 'create') => (uri: Uri): void => {
|
||||
const forward = (kind: 'change' | 'create') => async (uri: Uri): Promise<void> => {
|
||||
const found = workspaceFile(uri)
|
||||
if (found && minimatch(found.file.path, include, { dot: true }) && !isExcluded(found.file.path, excludedPatterns(found.folder)))
|
||||
if (!found || !minimatch(found.file.path, include, { dot: true }) || isExcluded(found.file.path, excludedPatterns(found.folder)))
|
||||
return
|
||||
if (!await scopeOf(found.folder).skips(found.file.path))
|
||||
listener({ kind, file: found.file })
|
||||
}
|
||||
// 删目录时 VS Code 只报目录本身,匹配不上 include,所以删除另用一个什么都盯的
|
||||
|
||||
Reference in new issue
Block a user