mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
When working out the dependencies between entry-points ngcc must parse the import statements and then resolve the import path to the actual file. This is complicated because module resolution is not trivial. Previously ngcc used the node.js `require.resolve`, with some hacking to resolve modules. This change refactors the `DependencyHost` to use a new custom `ModuleResolver`, which is optimized for this use case. Moreover, because we are in full control of the resolution, we can support TS `paths` aliases, where not all imports come from `node_modules`. This is the case in some CLI projects where there are compiled libraries that are stored locally in a `dist` folder. See //FW-1210. PR Close #29643
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
import * as ts from 'typescript';
|
|
|
|
export function getOriginalSymbol(checker: ts.TypeChecker): (symbol: ts.Symbol) => ts.Symbol {
|
|
return function(symbol: ts.Symbol) {
|
|
return ts.SymbolFlags.Alias & symbol.flags ? checker.getAliasedSymbol(symbol) : symbol;
|
|
};
|
|
}
|
|
|
|
export function isDefined<T>(value: T | undefined | null): value is T {
|
|
return (value !== undefined) && (value !== null);
|
|
}
|
|
|
|
export function getNameText(name: ts.PropertyName | ts.BindingName): string {
|
|
return ts.isIdentifier(name) || ts.isLiteralExpression(name) ? name.text : name.getText();
|
|
}
|
|
|
|
/**
|
|
* Parse down the AST and capture all the nodes that satisfy the test.
|
|
* @param node The start node.
|
|
* @param test The function that tests whether a node should be included.
|
|
* @returns a collection of nodes that satisfy the test.
|
|
*/
|
|
export function findAll<T>(node: ts.Node, test: (node: ts.Node) => node is ts.Node & T): T[] {
|
|
const nodes: T[] = [];
|
|
findAllVisitor(node);
|
|
return nodes;
|
|
|
|
function findAllVisitor(n: ts.Node) {
|
|
if (test(n)) {
|
|
nodes.push(n);
|
|
} else {
|
|
n.forEachChild(child => findAllVisitor(child));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Does the given declaration have a name which is an identifier?
|
|
* @param declaration The declaration to test.
|
|
* @returns true if the declaration has an identifier for a name.
|
|
*/
|
|
export function hasNameIdentifier(declaration: ts.Declaration): declaration is ts.Declaration&
|
|
{name: ts.Identifier} {
|
|
const namedDeclaration: ts.Declaration&{name?: ts.Node} = declaration;
|
|
return namedDeclaration.name !== undefined && ts.isIdentifier(namedDeclaration.name);
|
|
}
|
|
|
|
export type PathMappings = {
|
|
baseUrl: string,
|
|
paths: {[key: string]: string[]}
|
|
};
|
|
|
|
/**
|
|
* Test whether a path is "relative".
|
|
*
|
|
* Relative paths start with `/`, `./` or `../`; or are simply `.` or `..`.
|
|
*/
|
|
export function isRelativePath(path: string): boolean {
|
|
return /^\/|^\.\.?($|\/)/.test(path);
|
|
}
|