Skip to content

Commit d1ae1ff

Browse files
authored
Make JS/TS go to configuration commands work on non-file: file systems (microsoft#183688)
Make `go to project` commands work on non-`file:` file systems Fixes microsoft#183685
1 parent 9f3c499 commit d1ae1ff

File tree

6 files changed

+37
-35
lines changed

6 files changed

+37
-35
lines changed

extensions/typescript-language-features/src/languageFeatures/updatePathsOnRename.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ class UpdateImportsOnFileRenameHandler extends Disposable {
239239

240240
for (const rename of renames) {
241241
// Group renames by type (js/ts) and by workspace.
242-
const key = `${this.client.getWorkspaceRootForResource(rename.jsTsFileThatIsBeingMoved)}@@@${doesResourceLookLikeATypeScriptFile(rename.jsTsFileThatIsBeingMoved)}`;
242+
const key = `${this.client.getWorkspaceRootForResource(rename.jsTsFileThatIsBeingMoved)?.fsPath}@@@${doesResourceLookLikeATypeScriptFile(rename.jsTsFileThatIsBeingMoved)}`;
243243
if (!groups.has(key)) {
244244
groups.set(key, new Set());
245245
}

extensions/typescript-language-features/src/tsServer/bufferSyncSupport.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import * as vscode from 'vscode';
7-
import { vscodeNotebookCell } from '../configuration/fileSchemes';
7+
import { officeScript, vscodeNotebookCell } from '../configuration/fileSchemes';
88
import * as languageModeIds from '../configuration/languageIds';
99
import * as typeConverters from '../typeConverters';
1010
import { ClientCapability, ITypeScriptServiceClient } from '../typescriptService';
11+
import { inMemoryResourcePrefix } from '../typescriptServiceClient';
1112
import { coalesce } from '../utils/arrays';
1213
import { Delayer, setImmediate } from '../utils/async';
1314
import { nulToken } from '../utils/cancellation';
@@ -200,7 +201,7 @@ class SyncedBuffer {
200201
const args: Proto.OpenRequestArgs = {
201202
file: this.filepath,
202203
fileContent: this.document.getText(),
203-
projectRootPath: this.client.getWorkspaceRootForResource(this.document.uri),
204+
projectRootPath: this.getProjectRootPath(this.document.uri),
204205
};
205206

206207
const scriptKind = mode2ScriptKind(this.document.languageId);
@@ -219,6 +220,16 @@ class SyncedBuffer {
219220
this.state = BufferState.Open;
220221
}
221222

223+
private getProjectRootPath(resource: vscode.Uri): string | undefined {
224+
const workspaceRoot = this.client.getWorkspaceRootForResource(resource);
225+
if (workspaceRoot) {
226+
const tsRoot = this.client.toTsFilePath(workspaceRoot);
227+
return tsRoot?.startsWith(inMemoryResourcePrefix) ? undefined : tsRoot;
228+
}
229+
230+
return resource.scheme === officeScript ? '/' : undefined;
231+
}
232+
222233
public get resource(): vscode.Uri {
223234
return this.document.uri;
224235
}

extensions/typescript-language-features/src/tsconfig.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import * as path from 'path';
76
import * as vscode from 'vscode';
87
import type * as Proto from './tsServer/protocol/protocol';
98
import { ITypeScriptServiceClient, ServerResponse } from './typescriptService';
@@ -87,10 +86,10 @@ function inferredProjectConfigSnippet(
8786

8887
export async function openOrCreateConfig(
8988
projectType: ProjectType,
90-
rootPath: string,
89+
rootPath: vscode.Uri,
9190
configuration: TypeScriptServiceConfiguration,
9291
): Promise<vscode.TextEditor | null> {
93-
const configFile = vscode.Uri.file(path.join(rootPath, projectType === ProjectType.TypeScript ? 'tsconfig.json' : 'jsconfig.json'));
92+
const configFile = vscode.Uri.joinPath(rootPath, projectType === ProjectType.TypeScript ? 'tsconfig.json' : 'jsconfig.json');
9493
const col = vscode.window.activeTextEditor?.viewColumn;
9594
try {
9695
const doc = await vscode.workspace.openTextDocument(configFile);
@@ -108,11 +107,11 @@ export async function openOrCreateConfig(
108107
export async function openProjectConfigOrPromptToCreate(
109108
projectType: ProjectType,
110109
client: ITypeScriptServiceClient,
111-
rootPath: string,
112-
configFileName: string,
110+
rootPath: vscode.Uri,
111+
configFilePath: string,
113112
): Promise<void> {
114-
if (!isImplicitProjectConfigFile(configFileName)) {
115-
const doc = await vscode.workspace.openTextDocument(configFileName);
113+
if (!isImplicitProjectConfigFile(configFilePath)) {
114+
const doc = await vscode.workspace.openTextDocument(client.toResource(configFilePath));
116115
vscode.window.showTextDocument(doc, vscode.window.activeTextEditor?.viewColumn);
117116
return;
118117
}

extensions/typescript-language-features/src/typescriptService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export interface ITypeScriptServiceClient {
156156
*/
157157
hasCapabilityForResource(resource: vscode.Uri, capability: ClientCapability): boolean;
158158

159-
getWorkspaceRootForResource(resource: vscode.Uri): string | undefined;
159+
getWorkspaceRootForResource(resource: vscode.Uri): vscode.Uri | undefined;
160160

161161
readonly onTsServerStarted: vscode.Event<{ version: TypeScriptVersion; usedApiVersion: API }>;
162162
readonly onProjectLanguageServiceStateChanged: vscode.Event<Proto.ProjectLanguageServiceStateEventBody>;

extensions/typescript-language-features/src/typescriptServiceClient.ts

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,12 @@ namespace ServerState {
9191
export type State = typeof None | Running | Errored;
9292
}
9393

94+
export const emptyAuthority = 'ts-nul-authority';
95+
96+
export const inMemoryResourcePrefix = '^';
97+
9498
export default class TypeScriptServiceClient extends Disposable implements ITypeScriptServiceClient {
9599

96-
private readonly emptyAuthority = 'ts-nul-authority';
97-
private readonly inMemoryResourcePrefix = '^';
98100

99101
private readonly _onReady?: { promise: Promise<void>; resolve: () => void; reject: () => void };
100102
private _configuration: TypeScriptServiceConfiguration;
@@ -695,9 +697,9 @@ export default class TypeScriptServiceClient extends Disposable implements IType
695697
return resource.fsPath;
696698
}
697699

698-
return (this.isProjectWideIntellisenseOnWebEnabled() ? '' : this.inMemoryResourcePrefix)
700+
return (this.isProjectWideIntellisenseOnWebEnabled() ? '' : inMemoryResourcePrefix)
699701
+ '/' + resource.scheme
700-
+ '/' + (resource.authority || this.emptyAuthority)
702+
+ '/' + (resource.authority || emptyAuthority)
701703
+ (resource.path.startsWith('/') ? resource.path : '/' + resource.path)
702704
+ (resource.fragment ? '#' + resource.fragment : '');
703705
}
@@ -739,46 +741,36 @@ export default class TypeScriptServiceClient extends Disposable implements IType
739741
}
740742
const parts = filepath.match(/^\/([^\/]+)\/([^\/]*)\/(.+)$/);
741743
if (parts) {
742-
const resource = vscode.Uri.parse(parts[1] + '://' + (parts[2] === this.emptyAuthority ? '' : parts[2]) + '/' + parts[3]);
744+
const resource = vscode.Uri.parse(parts[1] + '://' + (parts[2] === emptyAuthority ? '' : parts[2]) + '/' + parts[3]);
743745
return this.bufferSyncSupport.toVsCodeResource(resource);
744746
}
745747
}
746748

747-
if (filepath.startsWith(this.inMemoryResourcePrefix)) {
749+
if (filepath.startsWith(inMemoryResourcePrefix)) {
748750
const parts = filepath.match(/^\^\/([^\/]+)\/([^\/]*)\/(.+)$/);
749751
if (parts) {
750-
const resource = vscode.Uri.parse(parts[1] + '://' + (parts[2] === this.emptyAuthority ? '' : parts[2]) + '/' + parts[3]);
752+
const resource = vscode.Uri.parse(parts[1] + '://' + (parts[2] === emptyAuthority ? '' : parts[2]) + '/' + parts[3]);
751753
return this.bufferSyncSupport.toVsCodeResource(resource);
752754
}
753755
}
754756
return this.bufferSyncSupport.toResource(filepath);
755757
}
756758

757-
public getWorkspaceRootForResource(resource: vscode.Uri): string | undefined {
759+
public getWorkspaceRootForResource(resource: vscode.Uri): vscode.Uri | undefined {
758760
const roots = vscode.workspace.workspaceFolders ? Array.from(vscode.workspace.workspaceFolders) : undefined;
759761
if (!roots?.length) {
760-
if (resource.scheme === fileSchemes.officeScript) {
761-
return '/';
762-
}
763762
return undefined;
764763
}
765764

766-
let tsRootPath: string | undefined;
767765
for (const root of roots.sort((a, b) => a.uri.fsPath.length - b.uri.fsPath.length)) {
768766
if (root.uri.scheme === resource.scheme && root.uri.authority === resource.authority) {
769767
if (resource.fsPath.startsWith(root.uri.fsPath + path.sep)) {
770-
tsRootPath = this.toTsFilePath(root.uri);
771-
break;
768+
return root.uri;
772769
}
773770
}
774771
}
775772

776-
tsRootPath ??= this.toTsFilePath(roots[0].uri);
777-
if (!tsRootPath || tsRootPath.startsWith(this.inMemoryResourcePrefix)) {
778-
return undefined;
779-
}
780-
781-
return tsRootPath;
773+
return undefined;
782774
}
783775

784776
public execute(command: keyof TypeScriptRequests, args: any, token: vscode.CancellationToken, config?: ExecConfig): Promise<ServerResponse.Response<Proto.Response>> {

extensions/typescript-language-features/src/ui/intellisenseStatus.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,18 @@ export class IntellisenseStatus extends Disposable {
6262

6363
commandManager.register({
6464
id: this.openOpenConfigCommandId,
65-
execute: async (rootPath: string, projectType: ProjectType) => {
65+
execute: async (root: vscode.Uri, projectType: ProjectType) => {
6666
if (this._state.type === IntellisenseState.Type.Resolved) {
67-
await openProjectConfigOrPromptToCreate(projectType, this._client, rootPath, this._state.configFile);
67+
await openProjectConfigOrPromptToCreate(projectType, this._client, root, this._state.configFile);
6868
} else if (this._state.type === IntellisenseState.Type.Pending) {
6969
await openProjectConfigForFile(projectType, this._client, this._state.resource);
7070
}
7171
},
7272
});
7373
commandManager.register({
7474
id: this.createOrOpenConfigCommandId,
75-
execute: async (rootPath: string, projectType: ProjectType) => {
76-
await openOrCreateConfig(projectType, rootPath, this._client.configuration);
75+
execute: async (root: vscode.Uri, projectType: ProjectType) => {
76+
await openOrCreateConfig(projectType, root, this._client.configuration);
7777
},
7878
});
7979

0 commit comments

Comments
 (0)