Fix workspace tracker path resolution

This commit is contained in:
Saoud Rizwan
2024-09-18 10:34:50 -04:00
parent 57b95acd11
commit b94f6fd4e1
3 changed files with 87 additions and 48 deletions

View File

@@ -11,27 +11,28 @@ class WorkspaceTracker {
private filePaths: Set<string> = new Set() private filePaths: Set<string> = new Set()
constructor(provider: ClaudeDevProvider) { constructor(provider: ClaudeDevProvider) {
console.log("WorkspaceTracker: Initializing")
this.providerRef = new WeakRef(provider) this.providerRef = new WeakRef(provider)
this.registerListeners() this.registerListeners()
} }
async initializeFilePaths() { async initializeFilePaths() {
console.log("WorkspaceTracker: Initializing file paths")
// should not auto get filepaths for desktop since it would immediately show permission popup before claude every creates a file // should not auto get filepaths for desktop since it would immediately show permission popup before claude every creates a file
if (!cwd) { if (!cwd) {
console.log("WorkspaceTracker: No workspace folder found")
return return
} }
const [files, _] = await listFiles(cwd, true, 500) const [files, _] = await listFiles(cwd, true, 500)
files console.log(`WorkspaceTracker: Found ${files.length} files`)
.map((file) => { files.forEach((file) => this.filePaths.add(this.normalizeFilePath(file)))
const relativePath = path.relative(cwd, file) console.log(this.filePaths)
return file.endsWith("/") ? relativePath + "/" : relativePath
})
.forEach((file) => this.filePaths.add(file))
this.workspaceDidUpdate() this.workspaceDidUpdate()
} }
private registerListeners() { private registerListeners() {
console.log("WorkspaceTracker: Registering listeners")
// Listen for file creation // Listen for file creation
this.disposables.push(vscode.workspace.onDidCreateFiles(this.onFilesCreated.bind(this))) this.disposables.push(vscode.workspace.onDidCreateFiles(this.onFilesCreated.bind(this)))
@@ -48,53 +49,65 @@ class WorkspaceTracker {
this.disposables.push(vscode.workspace.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged.bind(this))) this.disposables.push(vscode.workspace.onDidChangeWorkspaceFolders(this.onWorkspaceFoldersChanged.bind(this)))
} }
private onFilesCreated(event: vscode.FileCreateEvent) { private async onFilesCreated(event: vscode.FileCreateEvent) {
event.files.forEach(async (file) => { console.log(`WorkspaceTracker: Files created - ${event.files.length} file(s)`)
this.filePaths.add(file.fsPath) await Promise.all(
this.workspaceDidUpdate() event.files.map(async (file) => {
}) await this.addFilePath(file.fsPath)
})
)
this.workspaceDidUpdate()
} }
private onFilesDeleted(event: vscode.FileDeleteEvent) { private async onFilesDeleted(event: vscode.FileDeleteEvent) {
event.files.forEach((file) => { console.log(`WorkspaceTracker: Files deleted - ${event.files.length} file(s)`)
if (this.filePaths.delete(file.fsPath)) { let updated = false
this.workspaceDidUpdate() await Promise.all(
} event.files.map(async (file) => {
}) if (await this.removeFilePath(file.fsPath)) {
updated = true
}
})
)
if (updated) {
this.workspaceDidUpdate()
}
} }
private onFilesRenamed(event: vscode.FileRenameEvent) { private async onFilesRenamed(event: vscode.FileRenameEvent) {
event.files.forEach(async (file) => { console.log(`WorkspaceTracker: Files renamed - ${event.files.length} file(s)`)
this.filePaths.delete(file.oldUri.fsPath) await Promise.all(
this.filePaths.add(file.newUri.fsPath) event.files.map(async (file) => {
this.workspaceDidUpdate() await this.removeFilePath(file.oldUri.fsPath)
}) await this.addFilePath(file.newUri.fsPath)
})
)
this.workspaceDidUpdate()
} }
private async onFileChanged(event: vscode.TextDocumentChangeEvent) { private async onFileChanged(event: vscode.TextDocumentChangeEvent) {
const filePath = event.document.uri.fsPath const filePath = await this.addFilePath(event.document.uri.fsPath)
if (!this.filePaths.has(filePath)) { if (!this.filePaths.has(filePath)) {
console.log(`WorkspaceTracker: New file changed - ${filePath}`)
this.filePaths.add(filePath) this.filePaths.add(filePath)
this.workspaceDidUpdate() this.workspaceDidUpdate()
} }
} }
private async onWorkspaceFoldersChanged(event: vscode.WorkspaceFoldersChangeEvent) { private async onWorkspaceFoldersChanged(event: vscode.WorkspaceFoldersChangeEvent) {
console.log(
`WorkspaceTracker: Workspace folders changed - Added: ${event.added.length}, Removed: ${event.removed.length}`
)
for (const folder of event.added) { for (const folder of event.added) {
const [files, _] = await listFiles(folder.uri.fsPath, true, 50) // at most 50 files const [files, _] = await listFiles(folder.uri.fsPath, true, 50) // at most 50 files
if (!cwd) { console.log(`WorkspaceTracker: Adding ${files.length} files from new folder`)
continue await Promise.all(files.map((file) => this.addFilePath(file)))
}
files
.map((file) => {
const relativePath = path.relative(cwd, file)
return file.endsWith("/") ? relativePath + "/" : relativePath
})
.forEach((file) => this.filePaths.add(file))
} }
for (const folder of event.removed) { for (const folder of event.removed) {
const folderPath = await this.addFilePath(folder.uri.fsPath)
console.log(`WorkspaceTracker: Removing files from deleted folder - ${folderPath}`)
this.filePaths.forEach((filePath) => { this.filePaths.forEach((filePath) => {
if (filePath.startsWith(folder.uri.fsPath)) { if (filePath.startsWith(folderPath)) {
this.filePaths.delete(filePath) this.filePaths.delete(filePath)
} }
}) })
@@ -103,19 +116,46 @@ class WorkspaceTracker {
} }
private workspaceDidUpdate() { private workspaceDidUpdate() {
console.log("Workspace updated. Current file paths:", Array.from(this.filePaths)) console.log(`WorkspaceTracker: Workspace updated. Current file count: ${this.filePaths.size}`)
// Add your logic here for when the workspace is updated if (!cwd) {
return
}
this.providerRef.deref()?.postMessageToWebview({ this.providerRef.deref()?.postMessageToWebview({
type: "workspaceUpdated", type: "workspaceUpdated",
filePaths: Array.from(this.filePaths), filePaths: Array.from(this.filePaths).map((file) => {
const relativePath = path.relative(cwd, file)
return file.endsWith("/") ? relativePath + "/" : relativePath
}),
}) })
} }
public getFilePaths(): string[] { private normalizeFilePath(filePath: string): string {
return Array.from(this.filePaths) const resolvedPath = path.resolve(filePath)
return filePath.endsWith("/") ? resolvedPath + "/" : resolvedPath
}
private async addFilePath(filePath: string): Promise<string> {
const normalizedPath = this.normalizeFilePath(filePath)
try {
const stat = await vscode.workspace.fs.stat(vscode.Uri.file(normalizedPath))
const isDirectory = (stat.type & vscode.FileType.Directory) !== 0
const pathWithSlash = isDirectory && !normalizedPath.endsWith("/") ? normalizedPath + "/" : normalizedPath
this.filePaths.add(pathWithSlash)
return pathWithSlash
} catch {
// If stat fails, assume it's a file (this can happen for newly created files)
this.filePaths.add(normalizedPath)
return normalizedPath
}
}
private async removeFilePath(filePath: string): Promise<boolean> {
const normalizedPath = this.normalizeFilePath(filePath)
return this.filePaths.delete(normalizedPath) || this.filePaths.delete(normalizedPath + "/")
} }
public dispose() { public dispose() {
console.log("WorkspaceTracker: Disposing")
this.disposables.forEach((d) => d.dispose()) this.disposables.forEach((d) => d.dispose())
} }
} }

View File

@@ -90,7 +90,7 @@ export async function listFiles(dirPath: string, recursive: boolean, limit: numb
cwd: dirPath, cwd: dirPath,
dot: true, // do not ignore hidden files/directories dot: true, // do not ignore hidden files/directories
absolute: true, absolute: true,
markDirectories: true, // Append a / on any directories matched markDirectories: true, // Append a / on any directories matched (/ is used on windows as well, so dont use path.sep)
gitignore: recursive, // globby ignores any files that are gitignored gitignore: recursive, // globby ignores any files that are gitignored
ignore: recursive ? dirsToIgnore : undefined, // just in case there is no gitignore, we ignore sensible defaults ignore: recursive ? dirsToIgnore : undefined, // just in case there is no gitignore, we ignore sensible defaults
onlyFiles: false, // true by default, false means it will list directories on their own too onlyFiles: false, // true by default, false means it will list directories on their own too

View File

@@ -144,24 +144,23 @@ vscode-dropdown::part(listbox) {
} }
.mention-context-highlight { .mention-context-highlight {
background-color: var(--vscode-textLink-activeForeground, #3794ff); background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
opacity: 0.3;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 0 0 0.5px var(--vscode-textLink-activeForeground, #3794ff); box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
color: transparent; color: transparent;
padding: 0.5px; /* padding: 0.5px;
margin: -0.5px; margin: -0.5px;
position: relative; position: relative;
bottom: -0.5px; bottom: -0.5px; */
} }
.mention-context-highlight-visible-with-shadow { .mention-context-highlight-visible-with-shadow {
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 35%, transparent); background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
border-radius: 3px; border-radius: 3px;
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 35%, transparent); box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
} }
.mention-context-highlight-visible-without-shadow { .mention-context-highlight-visible-without-shadow {
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 35%, transparent); background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
border-radius: 3px; border-radius: 3px;
} }