Ensure folders with spaces don't impact link line/col

Fixes #155532
This commit is contained in:
Daniel Imms
2022-07-21 15:17:22 -07:00
parent 0cf530cd3c
commit 0a3ee299ce
2 changed files with 41 additions and 3 deletions
@@ -23,6 +23,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder';
import { ISearchService } from 'vs/workbench/services/search/common/search';
import { basename } from 'vs/base/common/path';
export class TerminalLocalFileLinkOpener implements ITerminalLinkOpener {
constructor(
@@ -35,7 +36,7 @@ export class TerminalLocalFileLinkOpener implements ITerminalLinkOpener {
if (!link.uri) {
throw new Error('Tried to open file link without a resolved URI');
}
const lineColumnInfo: ILineColumnInfo = this.extractLineColumnInfo(link.text);
const lineColumnInfo: ILineColumnInfo = this.extractLineColumnInfo(link.text, link.uri);
const selection: ITextEditorSelection = {
startLineNumber: lineColumnInfo.lineNumber,
startColumn: lineColumnInfo.columnNumber
@@ -51,12 +52,22 @@ export class TerminalLocalFileLinkOpener implements ITerminalLinkOpener {
*
* @param link Url link which may contain line and column number.
*/
extractLineColumnInfo(link: string): ILineColumnInfo {
extractLineColumnInfo(link: string, uri?: URI): ILineColumnInfo {
const lineColumnInfo: ILineColumnInfo = {
lineNumber: 1,
columnNumber: 1
};
// If a URI was passed in the exact file is known, sanitize the link text such that the
// folders and file name do not contain whitespace. The actual path isn't important in
// extracting the line and column from the regex so this is safe
if (uri) {
const fileName = basename(uri.path);
const index = link.indexOf(fileName);
const endIndex = index + fileName.length;
link = link.slice(0, endIndex).replace(/\s/g, '_') + link.slice(endIndex);
}
// The local link regex only works for non file:// links, check these for a simple
// `:line:col` suffix
if (link.startsWith('file://')) {
@@ -7,7 +7,7 @@ import { deepStrictEqual } from 'assert';
import { Schemas } from 'vs/base/common/network';
import { OperatingSystem } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { ITextResourceEditorInput } from 'vs/platform/editor/common/editor';
import { ITextEditorSelection, ITextResourceEditorInput } from 'vs/platform/editor/common/editor';
import { IFileService, IFileStatWithPartialMetadata } from 'vs/platform/files/common/files';
import { FileService } from 'vs/platform/files/common/fileService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
@@ -27,6 +27,7 @@ import { Terminal } from 'xterm';
export interface ITerminalLinkActivationResult {
source: 'editor' | 'search';
link: string;
selection?: ITextEditorSelection;
}
class TestCommandDetectionCapability extends CommandDetectionCapability {
@@ -79,6 +80,10 @@ suite('Workbench - TerminalLinkOpeners', () => {
source: 'editor',
link: editor.resource?.toString()
};
// Only assert on selection if it's not the default value
if (editor.options?.selection && (editor.options.selection.startColumn !== 1 || editor.options.selection.startLineNumber !== 1)) {
activationResult.selection = editor.options.selection;
}
}
} as Partial<IEditorService>);
// /*editorServiceSpy = */instantiationService.spy(IEditorService, 'openEditor');
@@ -165,6 +170,28 @@ suite('Workbench - TerminalLinkOpeners', () => {
});
});
test('should extract line and column from links in a workspace containing spaces', async () => {
localFileOpener = instantiationService.createInstance(TerminalLocalFileLinkOpener, OperatingSystem.Linux);
const localFolderOpener = instantiationService.createInstance(TerminalLocalFolderInWorkspaceLinkOpener);
opener = instantiationService.createInstance(TerminalSearchLinkOpener, capabilities, Promise.resolve('/space folder'), localFileOpener, localFolderOpener, OperatingSystem.Linux);
fileService.setFiles([
URI.from({ scheme: Schemas.file, path: '/space folder/foo/bar.txt' })
]);
await opener.open({
text: './foo/bar.txt:10:5',
bufferRange: { start: { x: 1, y: 1 }, end: { x: 8, y: 1 } },
type: TerminalBuiltinLinkType.Search
});
deepStrictEqual(activationResult, {
link: 'file:///space%20folder/foo/bar.txt',
source: 'editor',
selection: {
startColumn: 5,
startLineNumber: 10
},
});
});
suite('macOS/Linux', () => {
setup(() => {
localFileOpener = instantiationService.createInstance(TerminalLocalFileLinkOpener, OperatingSystem.Linux);