Normalize all file paths to posix format when presenting to AI or user

This commit is contained in:
Saoud Rizwan
2024-09-22 19:20:10 -04:00
parent 1602ecfe67
commit 69e681ebce
9 changed files with 112 additions and 35 deletions

View File

@@ -146,7 +146,7 @@ async function getFileOrFolderContent(mentionPath: string, cwd: string): Promise
return undefined
}
const content = await extractTextFromFile(absoluteFilePath)
return `<file_content path="${filePath}">\n${content}\n</file_content>`
return `<file_content path="${filePath.toPosix()}">\n${content}\n</file_content>`
} catch (error) {
return undefined
}

View File

@@ -77,7 +77,7 @@ export function diagnosticsToProblemsString(diagnostics: [vscode.Uri, vscode.Dia
(d) => d.severity === vscode.DiagnosticSeverity.Error || d.severity === vscode.DiagnosticSeverity.Warning
)
if (problems.length > 0) {
result += `\n\n${path.relative(cwd, uri.fsPath)}`
result += `\n\n${path.relative(cwd, uri.fsPath).toPosix()}`
for (const diagnostic of problems) {
let severity = diagnostic.severity === vscode.DiagnosticSeverity.Error ? "Error" : "Warning"
const line = diagnostic.range.start.line + 1 // VSCode lines are 0-indexed

75
src/utils/path-helpers.ts Normal file
View File

@@ -0,0 +1,75 @@
import * as path from "path"
/*
The Node.js 'path' module resolves and normalizes paths differently depending on the platform:
- On Windows, it uses backslashes (\) as the default path separator.
- On POSIX-compliant systems (Linux, macOS), it uses forward slashes (/) as the default path separator.
While modules like 'upath' can be used to normalize paths to use forward slashes consistently,
this can create inconsistencies when interfacing with other modules (like vscode.fs) that use
backslashes on Windows.
Our approach:
1. We present paths with forward slashes to the AI and user for consistency.
2. We use the 'arePathsEqual' function for safe path comparisons.
3. Internally, Node.js gracefully handles both backslashes and forward slashes.
This strategy ensures consistent path presentation while leveraging Node.js's built-in
path handling capabilities across different platforms.
Note: When interacting with the file system or VS Code APIs, we still use the native path module
to ensure correct behavior on all platforms. The toPosixPath and arePathsEqual functions are
primarily used for presentation and comparison purposes, not for actual file system operations.
*/
function toPosixPath(p: string) {
// Extended-Length Paths in Windows start with "\\?\" to allow longer paths and bypass usual parsing. If detected, we return the path unmodified to maintain functionality, as altering these paths could break their special syntax.
const isExtendedLengthPath = p.startsWith("\\\\?\\")
if (isExtendedLengthPath) {
return p
}
return p.replace(/\\/g, "/")
}
// Declaration merging allows us to add a new method to the String type
// You must import this file in your entry point (extension.ts) to have access at runtime
declare global {
interface String {
toPosix(): string
}
}
String.prototype.toPosix = function (this: string): string {
return toPosixPath(this)
}
// Safe path comparison that works across different platforms
// export function arePathsEqual(path1?: string, path2?: string): boolean {
// if (!path1 && !path2) {
// return true
// }
// if (!path1 || !path2) {
// return false
// }
// path1 = normalizePath(path1)
// path2 = normalizePath(path2)
// if (process.platform === "win32") {
// return path1.toLowerCase() === path2.toLowerCase()
// }
// return path1 === path2
// }
// function normalizePath(p: string): string {
// // normalize resolve ./.. segments, removes duplicate slashes, and standardizes path separators
// let normalized = path.normalize(p)
// // however it doesn't remove trailing slashes
// // remove trailing slash, except for root paths
// if (normalized.length > 1 && (normalized.endsWith("/") || normalized.endsWith("\\"))) {
// normalized = normalized.slice(0, -1)
// }
// return normalized
// }

View File

@@ -202,7 +202,7 @@ function formatResults(results: SearchResult[], cwd: string): string {
})
for (const [filePath, fileResults] of Object.entries(groupedResults)) {
output += `${filePath}\n│----\n`
output += `${filePath.toPosix()}\n│----\n`
fileResults.forEach((result, index) => {
const allLines = [...result.beforeContext, result.match, ...result.afterContext]