Skip to content
Open
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
14 changes: 14 additions & 0 deletions extensions/typescript-language-features/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2839,6 +2839,20 @@
"description": "%typescript.tsserver.pluginPaths%",
"markdownDeprecationMessage": "%typescript.tsserver.pluginPaths.unifiedDeprecationMessage%",
"scope": "machine"
},
"js/ts.projectConfig.additionalFilePatterns": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"default": [],
"markdownDescription": "%js/ts.projectConfig.additionalFilePatterns%",
"scope": "window",
"keywords": [
"TypeScript",
"JavaScript"
]
Comment thread
unrevised6419 marked this conversation as resolved.
}
}
}
Expand Down
1 change: 1 addition & 0 deletions extensions/typescript-language-features/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"typescript.tsserver.pluginPaths": "Additional paths to discover TypeScript Language Service plugins.",
"typescript.tsserver.pluginPaths.item": "Either an absolute or relative path. Relative path will be resolved against workspace folder(s).",
"typescript.tsserver.pluginPaths.unifiedDeprecationMessage": "This setting is deprecated. Use `#js/ts.tsserver.pluginPaths#` instead.",
"js/ts.projectConfig.additionalFilePatterns": "Additional glob patterns identifying files that should receive `tsconfig.json`/`jsconfig.json`-style document links (for `extends`, `references`, and `files`). Useful for monorepos that name configs without `tsconfig`/`jsconfig` in the filename (for example `base.json`, `build.json`). The standard `tsconfig.json`/`jsconfig.json` patterns are always included; entries here are added to them. Does not affect TypeScript/JavaScript project loading.",
"typescript.tsserver.trace": "Enables tracing of messages sent to the TS server. This trace can be used to diagnose TS Server issues. The trace may contain file paths, source code, and other potentially sensitive information from your project.",
"typescript.validate.enable": "Enable/disable TypeScript validation.",
"javascript.validate.enable": "Enable/disable JavaScript validation.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,79 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider {
}
}

class TsconfigLinkProviderRegistration implements vscode.Disposable {

private static readonly configSection = 'js/ts';
private static readonly configKey = 'projectConfig.additionalFilePatterns';
private static readonly languages: readonly string[] = ['json', 'jsonc'];
private static readonly defaultPatterns: readonly string[] = [
'**/[jt]sconfig.json',
'**/[jt]sconfig.*.json',
];

private readonly _configListener: vscode.Disposable;
private _providerRegistration: vscode.Disposable | undefined;
private _lastPatternsKey: string | undefined;

constructor(private readonly _provider: vscode.DocumentLinkProvider) {
this.update();
this._configListener = vscode.workspace.onDidChangeConfiguration(e => {
const fullKey = `${TsconfigLinkProviderRegistration.configSection}.${TsconfigLinkProviderRegistration.configKey}`;
if (e.affectsConfiguration(fullKey)) {
this.update();
}
});
}

dispose(): void {
this._configListener.dispose();
this._providerRegistration?.dispose();
this._providerRegistration = undefined;
}

private update(): void {
const patterns = this.readPatterns();
const key = patterns.join('\n');

if (key === this._lastPatternsKey) {
return;
}

this._lastPatternsKey = key;
this._providerRegistration?.dispose();
this._providerRegistration = vscode.languages.registerDocumentLinkProvider(
this.buildSelector(patterns), this._provider);
}
Comment thread
unrevised6419 marked this conversation as resolved.

private buildSelector(patterns: readonly string[]): vscode.DocumentSelector {
return TsconfigLinkProviderRegistration.languages.flatMap(
language => patterns.map((pattern): vscode.DocumentFilter => ({ language, pattern })));
}

private readPatterns(): string[] {
const patterns = new Set<string>(TsconfigLinkProviderRegistration.defaultPatterns);
const configured = vscode.workspace
.getConfiguration(TsconfigLinkProviderRegistration.configSection)
.get(TsconfigLinkProviderRegistration.configKey);

if (Array.isArray(configured)) {
for (const value of configured) {
if (typeof value !== 'string') {
continue;
}

const trimmed = value.trim();

if (trimmed.length > 0) {
patterns.add(trimmed);
}
}
}

return Array.from(patterns);
}
}

async function resolveNodeModulesPath(baseDirUri: vscode.Uri, pathCandidates: string[]): Promise<vscode.Uri | undefined> {
let currentUri = baseDirUri;
const baseCandidate = pathCandidates[0];
Expand Down Expand Up @@ -191,17 +264,6 @@ async function getTsconfigPath(baseDirUri: vscode.Uri, pathValue: string, linkTy
}

export function register() {
const patterns: vscode.GlobPattern[] = [
'**/[jt]sconfig.json',
'**/[jt]sconfig.*.json',
];

const languages = ['json', 'jsonc'];

const selector: vscode.DocumentSelector =
languages.map(language => patterns.map((pattern): vscode.DocumentFilter => ({ language, pattern })))
.flat();

return vscode.Disposable.from(
vscode.commands.registerCommand(openExtendsLinkCommandId, async ({ resourceUri, extendsValue, linkType }: OpenExtendsLinkCommandArgs) => {
const tsconfigPath = await getTsconfigPath(Utils.dirname(vscode.Uri.from(resourceUri)), extendsValue, linkType);
Expand All @@ -212,6 +274,7 @@ export function register() {
// Will suggest to create a .json variant if it doesn't exist yet (but only for relative paths)
await vscode.commands.executeCommand('vscode.open', tsconfigPath);
}),
vscode.languages.registerDocumentLinkProvider(selector, new TsconfigLinkProvider()),
new TsconfigLinkProviderRegistration(new TsconfigLinkProvider()),
);
}