Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,9 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
case 'tilde': {
const home = this._getHomeDir(useWindowsStylePath, capabilities);
if (home) {
lastWordFolderResource = URI.joinPath(URI.file(home), lastWordFolder.slice(1).replaceAll('\\ ', ' '));
// Use the scheme and authority from cwd to handle remote scenarios correctly
const homeUri = cwd.with({ path: home });
lastWordFolderResource = URI.joinPath(homeUri, lastWordFolder.slice(1).replaceAll('\\ ', ' '));
}
if (!lastWordFolderResource) {
// Use less strong wording here as it's not as strong of a concept on Windows
Expand All @@ -332,10 +334,13 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
break;
}
case 'absolute': {
// Use the scheme and authority from cwd to handle remote scenarios correctly
// (e.g., Remote SSH where cwd has vscode-remote:// scheme)
if (shellType === WindowsShellType.GitBash) {
lastWordFolderResource = URI.file(gitBashToWindowsPath(lastWordFolder, this._processEnv.SystemDrive));
const windowsPath = gitBashToWindowsPath(lastWordFolder, this._processEnv.SystemDrive);
lastWordFolderResource = cwd.with({ path: windowsPath });
} else {
lastWordFolderResource = URI.file(lastWordFolder.replaceAll('\\ ', ' '));
lastWordFolderResource = cwd.with({ path: lastWordFolder.replaceAll('\\ ', ' ') });
}
break;
}
Expand Down Expand Up @@ -492,7 +497,9 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
const cdPathEntries = cdPath.split(useWindowsStylePath ? ';' : ':');
for (const cdPathEntry of cdPathEntries) {
try {
const fileStat = await this._fileService.resolve(URI.file(cdPathEntry), { resolveSingleChildDescendants: true });
// Use the scheme and authority from cwd to handle remote scenarios correctly
const cdPathUri = cwd.with({ path: cdPathEntry });
const fileStat = await this._fileService.resolve(cdPathUri, { resolveSingleChildDescendants: true });
if (fileStat?.children) {
for (const child of fileStat.children) {
if (!child.isDirectory) {
Expand Down Expand Up @@ -553,7 +560,8 @@ export class TerminalCompletionService extends Disposable implements ITerminalCo
let homeResource: URI | string | undefined;
const home = this._getHomeDir(useWindowsStylePath, capabilities);
if (home) {
homeResource = URI.joinPath(URI.file(home), lastWordFolder.slice(1).replaceAll('\\ ', ' '));
// Use the scheme and authority from cwd to handle remote scenarios correctly
homeResource = cwd.with({ path: home });
}
if (!homeResource) {
// Use less strong wording here as it's not as strong of a concept on Windows
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,27 @@ suite('TerminalCompletionService', () => {
{ label: '~/vscode/bar.txt', detail: '/home/vscode/bar.txt', kind: TerminalCompletionItemKind.File },
], { replacementRange: [0, 9] });
});

test('~/| with remote SSH URI scheme should respect remote scheme', async () => {
// Test that tilde paths respect the remote URI scheme from cwd
const remoteResourceOptions: TerminalCompletionResourceOptions = {
cwd: URI.parse('vscode-remote://ssh-remote+hostname/home/user'),
showFiles: true,
showDirectories: true,
pathSeparator: '/'
};
validResources = [
URI.parse('vscode-remote://ssh-remote+hostname/home'),
URI.parse('vscode-remote://ssh-remote+hostname/home/vscode'),
];
childResources = [
{ resource: URI.parse('vscode-remote://ssh-remote+hostname/home/vscode'), isDirectory: true },
];
assertCompletions(await terminalCompletionService.resolveResources(remoteResourceOptions, '~/', 2, provider, capabilities), [
{ label: '~/', detail: '/home/' },
{ label: '~/vscode/', detail: '/home/vscode/' },
], { replacementRange: [0, 2] });
});
});

suite('resolveResources edge cases and advanced scenarios', () => {
Expand Down Expand Up @@ -390,6 +411,26 @@ suite('TerminalCompletionService', () => {
{ label: '/foo/Bar/', detail: '/foo/Bar/' },
], { replacementRange: [0, 5] });
});

test('/foo/| absolute paths with remote SSH URI scheme', async () => {
// Test that absolute paths respect the remote URI scheme from cwd
const resourceOptions: TerminalCompletionResourceOptions = {
cwd: URI.parse('vscode-remote://ssh-remote+hostname/home/user'),
showDirectories: true,
pathSeparator: '/'
};
validResources = [URI.parse('vscode-remote://ssh-remote+hostname/foo')];
childResources = [
{ resource: URI.parse('vscode-remote://ssh-remote+hostname/foo/Bar'), isDirectory: true, isFile: false },
{ resource: URI.parse('vscode-remote://ssh-remote+hostname/foo/Baz.txt'), isDirectory: false, isFile: true }
];
const result = await terminalCompletionService.resolveResources(resourceOptions, '/foo/', 5, provider, capabilities);

assertCompletions(result, [
{ label: '/foo/', detail: '/foo/' },
{ label: '/foo/Bar/', detail: '/foo/Bar/' },
], { replacementRange: [0, 5] });
});
}

if (isWindows) {
Expand Down
Loading