Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle context file searching using forward slashes on Windows #2215

Merged
merged 9 commits into from
Dec 10, 2023
Merged
1 change: 1 addition & 0 deletions vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ This is a log of all notable changes to Cody for VS Code. [Unreleased] changes a
- Chat: Do not parse Windows file paths as URIs. [pull/2197](https://github.com/sourcegraph/cody/pull/2197)
- Search: Fix symf index dir on Windows. [pull/2207](https://github.com/sourcegraph/cody/pull/2207)
- Chat: You can @-mention files on Windows without generating an error. [pull/2197](https://github.com/sourcegraph/cody/pull/2197)
- Chat: You can @-mention files on Windows using backslashes and displayed filenames will use backslashes [pull/2215](https://github.com/sourcegraph/cody/pull/2215)
- Sidebar: Fix "Release Notes" label & link for pre-releases in sidebar. [pull/2210](https://github.com/sourcegraph/cody/pull/2210)
- Search: Send sigkill to symf when extension exits. [pull/2225](https://github.com/sourcegraph/cody/pull/2225)
- Search: Support cancelling index. [pull/2202](https://github.com/sourcegraph/cody/pull/2202)
Expand Down
20 changes: 18 additions & 2 deletions vscode/src/editor/utils/editor-context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { basename, dirname } from 'path'
import path, { basename, dirname } from 'path'

import fuzzysort from 'fuzzysort'
import { throttle } from 'lodash'
Expand Down Expand Up @@ -46,6 +46,10 @@ export async function getFileContextFiles(
return []
}

// On Windows, if the user has typed forward slashes, map them to backslashes before
// running the search so they match the real paths.
query = query.replaceAll(path.posix.sep, path.sep)

const results = fuzzysort.go(query, uris, {
key: 'fsPath',
limit: maxResults,
Expand Down Expand Up @@ -175,6 +179,18 @@ function createContextFilePath(uri: vscode.Uri): ContextFile['path'] {
return {
basename: basename(uri.fsPath),
dirname: dirname(uri.fsPath),
relative: vscode.workspace.asRelativePath(uri.fsPath),
relative: asRelativePath(uri),
}
}

/**
* Returns a relative path using the correct slash direction for the current platform.
*/
function asRelativePath(uri: vscode.Uri): string {
let relativePath = vscode.workspace.asRelativePath(uri.fsPath)
// asRelativePath returns forward slashes on Windows but we want to
// render a native path like VS Code does in the file quick-pick.
relativePath = relativePath.replaceAll(path.posix.sep, path.sep)

return relativePath
}
28 changes: 25 additions & 3 deletions vscode/test/e2e/at-file-context-selecting.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import path from 'path'

import { expect } from '@playwright/test'

import { sidebarSignin } from './common'
Expand Down Expand Up @@ -30,6 +32,20 @@ test('@-file empty state', async ({ page, sidebar }) => {
await chatInput.fill('@#')
await expect(chatPanelFrame.getByRole('heading', { name: 'Search for a symbol to include..' })).toBeVisible()

// Forward slashes
await chatInput.fill('@lib/batches/env')
await expect(
chatPanelFrame.getByRole('button', { name: withPlatformSlashes('lib/batches/env/var.go') })
).toBeVisible()

// Backslashes
if (path.sep === path.win32.sep) {
await chatInput.fill('@lib\\batches\\env')
await expect(
chatPanelFrame.getByRole('button', { name: withPlatformSlashes('lib/batches/env/var.go') })
).toBeVisible()
}

// Searching and clicking
await chatInput.fill('Explain @mj')
await chatPanelFrame.getByRole('button', { name: 'Main.java' }).click()
Expand All @@ -41,21 +57,23 @@ test('@-file empty state', async ({ page, sidebar }) => {
// Keyboard nav
await chatInput.type('Explain @vgo', { delay: 50 }) // without this delay the following Enter submits the form instead of selecting
await chatInput.press('Enter')
await expect(chatInput).toHaveValue('Explain @lib/batches/env/var.go ')
await expect(chatInput).toHaveValue(withPlatformSlashes('Explain @lib/batches/env/var.go '))
await chatInput.type('and @vgo', { delay: 50 }) // without this delay the following Enter submits the form instead of selecting
await chatInput.press('ArrowDown') // second item
await chatInput.press('ArrowDown') // wraps back to first item
await chatInput.press('ArrowDown') // second item again
await chatInput.press('Enter')
await expect(chatInput).toHaveValue(
'Explain @lib/batches/env/var.go and @lib/codeintel/tools/lsif-visualize/visualize.go '
withPlatformSlashes('Explain @lib/batches/env/var.go and @lib/codeintel/tools/lsif-visualize/visualize.go ')
)

// Send the message and check it was included
await chatInput.press('Enter')
await expect(chatInput).toBeEmpty()
await expect(
chatPanelFrame.getByText('Explain @lib/batches/env/var.go and @lib/codeintel/tools/lsif-visualize/visualize.go')
chatPanelFrame.getByText(
withPlatformSlashes('Explain @lib/batches/env/var.go and @lib/codeintel/tools/lsif-visualize/visualize.go')
)
).toBeVisible()

// Check pressing tab after typing a complete filename.
Expand All @@ -66,3 +84,7 @@ test('@-file empty state', async ({ page, sidebar }) => {
await chatInput.press('Tab')
await expect(chatInput).toHaveValue('@Main.java ')
})

function withPlatformSlashes(input: string) {
return input.replaceAll(path.posix.sep, path.sep)
}
Loading