( requestedPath: string, )
| 226 | * @returns The corrected path if found under cwd, undefined otherwise |
| 227 | */ |
| 228 | export async function suggestPathUnderCwd( |
| 229 | requestedPath: string, |
| 230 | ): Promise<string | undefined> { |
| 231 | const cwd = getCwd() |
| 232 | const cwdParent = dirname(cwd) |
| 233 | |
| 234 | // Resolve symlinks in the requested path's parent directory (e.g., /tmp -> /private/tmp on macOS) |
| 235 | // so the prefix comparison works correctly against the cwd (which is already realpath-resolved). |
| 236 | let resolvedPath = requestedPath |
| 237 | try { |
| 238 | const resolvedDir = await realpath(dirname(requestedPath)) |
| 239 | resolvedPath = join(resolvedDir, basename(requestedPath)) |
| 240 | } catch { |
| 241 | // Parent directory doesn't exist, use the original path |
| 242 | } |
| 243 | |
| 244 | // Only check if the requested path is under cwd's parent but not under cwd itself. |
| 245 | // When cwdParent is the root directory (e.g., '/'), use it directly as the prefix |
| 246 | // to avoid a double-separator '//' that would never match. |
| 247 | const cwdParentPrefix = cwdParent === sep ? sep : cwdParent + sep |
| 248 | if ( |
| 249 | !resolvedPath.startsWith(cwdParentPrefix) || |
| 250 | resolvedPath.startsWith(cwd + sep) || |
| 251 | resolvedPath === cwd |
| 252 | ) { |
| 253 | return undefined |
| 254 | } |
| 255 | |
| 256 | // Get the relative path from the parent directory |
| 257 | const relFromParent = relative(cwdParent, resolvedPath) |
| 258 | |
| 259 | // Check if the same relative path exists under cwd |
| 260 | const correctedPath = join(cwd, relFromParent) |
| 261 | try { |
| 262 | await stat(correctedPath) |
| 263 | return correctedPath |
| 264 | } catch { |
| 265 | return undefined |
| 266 | } |
| 267 | } |
| 268 | |
| 269 | /** |
| 270 | * Whether to use the compact line-number prefix format (`N\t` instead of |
no test coverage detected