Skip to content

Commit 65123b4

Browse files
authored
Allow clickable links to absolute tsconfig extends paths (microsoft#182921)
Fixes microsoft#182898
1 parent 5015de8 commit 65123b4

File tree

3 files changed

+20
-19
lines changed

3 files changed

+20
-19
lines changed

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { basename, posix } from 'path';
88
import * as vscode from 'vscode';
99
import { Utils } from 'vscode-uri';
1010
import { coalesce } from '../utils/arrays';
11-
import { exists } from '../utils/fs';
11+
import { exists, looksLikeAbsoluteWindowsPath } from '../utils/fs';
1212

1313
function mapChildren<R>(node: jsonc.Node | undefined, f: (x: jsonc.Node) => R): R[] {
1414
return node && node.type === 'array' && node.children
@@ -48,10 +48,6 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider {
4848
}
4949

5050
const extendsValue: string = extendsNode.value;
51-
if (extendsValue.startsWith('/')) {
52-
return undefined;
53-
}
54-
5551
const args: OpenExtendsLinkCommandArgs = {
5652
resourceUri: { ...document.uri.toJSON(), $mid: undefined }, // Prevent VS Code from trying to transform the uri
5753
extendsValue: extendsValue
@@ -161,20 +157,24 @@ async function resolveNodeModulesPath(baseDirUri: vscode.Uri, pathCandidates: st
161157
* @returns Returns undefined in case of lack of result while trying to resolve from node_modules
162158
*/
163159
async function getTsconfigPath(baseDirUri: vscode.Uri, extendsValue: string): Promise<vscode.Uri | undefined> {
164-
// Don't take into account a case, where tsconfig might be resolved from the root (see the reference)
165-
// e.g. C:/projects/shared-tsconfig/tsconfig.json (note that C: prefix is optional)
166-
167-
const isRelativePath = ['./', '../'].some(str => extendsValue.startsWith(str));
168-
if (isRelativePath) {
169-
const absolutePath = vscode.Uri.joinPath(baseDirUri, extendsValue);
170-
if (await exists(absolutePath) || absolutePath.path.endsWith('.json')) {
160+
async function resolve(absolutePath: vscode.Uri): Promise<vscode.Uri> {
161+
if (absolutePath.path.endsWith('.json') || await exists(absolutePath)) {
171162
return absolutePath;
172163
}
173164
return absolutePath.with({
174165
path: `${absolutePath.path}.json`
175166
});
176167
}
177168

169+
const isRelativePath = ['./', '../'].some(str => extendsValue.startsWith(str));
170+
if (isRelativePath) {
171+
return resolve(vscode.Uri.joinPath(baseDirUri, extendsValue));
172+
}
173+
174+
if (extendsValue.startsWith('/') || looksLikeAbsoluteWindowsPath(extendsValue)) {
175+
return resolve(vscode.Uri.file(extendsValue));
176+
}
177+
178178
// Otherwise resolve like a module
179179
return resolveNodeModulesPath(baseDirUri, [
180180
extendsValue,

extensions/typescript-language-features/src/utils/fs.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55

66
import * as vscode from 'vscode';
77

8-
export const exists = async (resource: vscode.Uri): Promise<boolean> => {
8+
export async function exists(resource: vscode.Uri): Promise<boolean> {
99
try {
1010
const stat = await vscode.workspace.fs.stat(resource);
1111
// stat.type is an enum flag
1212
return !!(stat.type & vscode.FileType.File);
1313
} catch {
1414
return false;
1515
}
16-
};
16+
}
17+
18+
export function looksLikeAbsoluteWindowsPath(path: string): boolean {
19+
return /^[a-zA-Z]:[\/\\]/.test(path);
20+
}

extensions/typescript-language-features/src/utils/resourceMap.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import * as vscode from 'vscode';
77
import * as fileSchemes from '../configuration/fileSchemes';
8+
import { looksLikeAbsoluteWindowsPath } from './fs';
89

910
/**
1011
* Maps of file resources
@@ -89,13 +90,9 @@ export class ResourceMap<T> {
8990
}
9091

9192
private isCaseInsensitivePath(path: string) {
92-
if (isWindowsPath(path)) {
93+
if (looksLikeAbsoluteWindowsPath(path)) {
9394
return true;
9495
}
9596
return path[0] === '/' && this.config.onCaseInsensitiveFileSystem;
9697
}
9798
}
98-
99-
function isWindowsPath(path: string): boolean {
100-
return /^[a-zA-Z]:[\/\\]/.test(path);
101-
}

0 commit comments

Comments
 (0)