Support clickable folder projects refences

A project reference may point either to a tsconfig or to a folder containing a `tsconfig.json` file
This commit is contained in:
Matt Bierner
2018-07-27 11:52:37 -07:00
parent 5c646ecb1b
commit 0edee5d228

View File

@@ -4,11 +4,11 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import * as jsonc from 'jsonc-parser'; import * as jsonc from 'jsonc-parser';
import { dirname, join } from 'path'; import { dirname, join, basename } from 'path';
import * as vscode from 'vscode'; import * as vscode from 'vscode';
import { flatten } from '../utils/arrays'; import { flatten } from '../utils/arrays';
function mapNode<R>(node: jsonc.Node | undefined, f: (x: jsonc.Node) => R): R[] { function mapChildren<R>(node: jsonc.Node | undefined, f: (x: jsonc.Node) => R): R[] {
return node && node.type === 'array' && node.children return node && node.type === 'array' && node.children
? node.children.map(f) ? node.children.map(f)
: []; : [];
@@ -37,15 +37,25 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider {
} }
private getFilesLinks(document: vscode.TextDocument, root: jsonc.Node) { private getFilesLinks(document: vscode.TextDocument, root: jsonc.Node) {
return mapNode( return mapChildren(
jsonc.findNodeAtLocation(root, ['files']), jsonc.findNodeAtLocation(root, ['files']),
node => this.pathNodeToLink(document, node)); child => this.pathNodeToLink(document, child));
} }
private getReferencesLinks(document: vscode.TextDocument, root: jsonc.Node) { private getReferencesLinks(document: vscode.TextDocument, root: jsonc.Node) {
return mapNode( return mapChildren(
jsonc.findNodeAtLocation(root, ['references']), jsonc.findNodeAtLocation(root, ['references']),
child => this.pathNodeToLink(document, jsonc.findNodeAtLocation(child, ['path']))); child => {
const pathNode = jsonc.findNodeAtLocation(child, ['path']);
if (!this.isPathValue(pathNode)) {
return undefined;
}
return new vscode.DocumentLink(this.getRange(document, pathNode),
basename(pathNode.value).match('.json$')
? this.getFileTarget(document, pathNode)
: this.getFolderTarget(document, pathNode));
});
} }
private pathNodeToLink( private pathNodeToLink(
@@ -53,7 +63,7 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider {
node: jsonc.Node | undefined node: jsonc.Node | undefined
): vscode.DocumentLink | undefined { ): vscode.DocumentLink | undefined {
return this.isPathValue(node) return this.isPathValue(node)
? new vscode.DocumentLink(this.getRange(document, node), this.getTarget(document, node)) ? new vscode.DocumentLink(this.getRange(document, node), this.getFileTarget(document, node))
: undefined; : undefined;
} }
@@ -61,13 +71,17 @@ class TsconfigLinkProvider implements vscode.DocumentLinkProvider {
return extendsNode return extendsNode
&& extendsNode.type === 'string' && extendsNode.type === 'string'
&& extendsNode.value && extendsNode.value
&& !(extendsNode.value as string).includes('*'); && !(extendsNode.value as string).includes('*'); // don't treat globs as links.
} }
private getTarget(document: vscode.TextDocument, node: jsonc.Node): vscode.Uri { private getFileTarget(document: vscode.TextDocument, node: jsonc.Node): vscode.Uri {
return vscode.Uri.file(join(dirname(document.uri.fsPath), node!.value)); return vscode.Uri.file(join(dirname(document.uri.fsPath), node!.value));
} }
private getFolderTarget(document: vscode.TextDocument, node: jsonc.Node): vscode.Uri {
return vscode.Uri.file(join(dirname(document.uri.fsPath), node!.value, 'tsconfig.json'));
}
private getRange(document: vscode.TextDocument, node: jsonc.Node) { private getRange(document: vscode.TextDocument, node: jsonc.Node) {
const offset = node!.offset; const offset = node!.offset;
const start = document.positionAt(offset + 1); const start = document.positionAt(offset + 1);