refactor(ivy): implement a virtual file-system layer in ngtsc + ngcc (#30921)
To improve cross platform support, all file access (and path manipulation) is now done through a well known interface (`FileSystem`). For testing a number of `MockFileSystem` implementations are provided. These provide an in-memory file-system which emulates operating systems like OS/X, Unix and Windows. The current file system is always available via the static method, `FileSystem.getFileSystem()`. This is also used by a number of static methods on `AbsoluteFsPath` and `PathSegment`, to avoid having to pass `FileSystem` objects around all the time. The result of this is that one must be careful to ensure that the file-system has been initialized before using any of these static methods. To prevent this happening accidentally the current file system always starts out as an instance of `InvalidFileSystem`, which will throw an error if any of its methods are called. You can set the current file-system by calling `FileSystem.setFileSystem()`. During testing you can call the helper function `initMockFileSystem(os)` which takes a string name of the OS to emulate, and will also monkey-patch aspects of the TypeScript library to ensure that TS is also using the current file-system. Finally there is the `NgtscCompilerHost` to be used for any TypeScript compilation, which uses a given file-system. All tests that interact with the file-system should be tested against each of the mock file-systems. A series of helpers have been provided to support such tests: * `runInEachFileSystem()` - wrap your tests in this helper to run all the wrapped tests in each of the mock file-systems. * `addTestFilesToFileSystem()` - use this to add files and their contents to the mock file system for testing. * `loadTestFilesFromDisk()` - use this to load a mirror image of files on disk into the in-memory mock file-system. * `loadFakeCore()` - use this to load a fake version of `@angular/core` into the mock file-system. All ngcc and ngtsc source and tests now use this virtual file-system setup. PR Close #30921
This commit is contained in:
committed by
Kara Erickson
parent
1e7e065423
commit
7186f9c016
@@ -27,12 +27,12 @@ ts_library(
|
||||
"//packages/compiler-cli/src/ngtsc/cycles",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/entry_point",
|
||||
"//packages/compiler-cli/src/ngtsc/file_system",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/incremental",
|
||||
"//packages/compiler-cli/src/ngtsc/indexer",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/path",
|
||||
"//packages/compiler-cli/src/ngtsc/perf",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/routing",
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* 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 {NodeJSFileSystem, setFileSystem} from './src/ngtsc/file_system';
|
||||
|
||||
export {AotCompilerHost, AotCompilerHost as StaticReflectorHost, StaticReflector, StaticSymbol} from '@angular/compiler';
|
||||
export {DiagnosticTemplateInfo, getExpressionScope, getTemplateExpressionDiagnostics} from './src/diagnostics/expression_diagnostics';
|
||||
export {AstType, ExpressionDiagnosticsContext} from './src/diagnostics/expression_type';
|
||||
@@ -26,3 +28,5 @@ export {NgTools_InternalApi_NG_2 as __NGTOOLS_PRIVATE_API_2} from './src/ngtools
|
||||
|
||||
export {ngToTsDiagnostic} from './src/transformers/util';
|
||||
export {NgTscPlugin} from './src/ngtsc/tsc_plugin';
|
||||
|
||||
setFileSystem(new NodeJSFileSystem());
|
||||
|
||||
@@ -8,15 +8,16 @@ ts_library(
|
||||
"*.ts",
|
||||
"**/*.ts",
|
||||
]),
|
||||
tsconfig = "//packages/compiler-cli:tsconfig",
|
||||
deps = [
|
||||
"//packages:types",
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/annotations",
|
||||
"//packages/compiler-cli/src/ngtsc/cycles",
|
||||
"//packages/compiler-cli/src/ngtsc/file_system",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/path",
|
||||
"//packages/compiler-cli/src/ngtsc/perf",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/scope",
|
||||
@@ -25,7 +26,6 @@ ts_library(
|
||||
"//packages/compiler-cli/src/ngtsc/util",
|
||||
"@npm//@types/convert-source-map",
|
||||
"@npm//@types/node",
|
||||
"@npm//@types/shelljs",
|
||||
"@npm//@types/source-map",
|
||||
"@npm//@types/yargs",
|
||||
"@npm//canonical-path",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system';
|
||||
import {hasBeenProcessed as _hasBeenProcessed} from './src/packages/build_marker';
|
||||
import {EntryPointJsonProperty, EntryPointPackageJson} from './src/packages/entry_point';
|
||||
|
||||
@@ -18,3 +19,6 @@ export function hasBeenProcessed(packageJson: object, format: string) {
|
||||
// We are wrapping this function to hide the internal types.
|
||||
return _hasBeenProcessed(packageJson as EntryPointPackageJson, format as EntryPointJsonProperty);
|
||||
}
|
||||
|
||||
// Configure the file-system for external users.
|
||||
setFileSystem(new NodeJSFileSystem());
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
import * as yargs from 'yargs';
|
||||
|
||||
import {AbsoluteFsPath} from '../src/ngtsc/path';
|
||||
import {resolve, setFileSystem, NodeJSFileSystem} from '../src/ngtsc/file_system';
|
||||
import {mainNgcc} from './src/main';
|
||||
import {ConsoleLogger, LogLevel} from './src/logging/console_logger';
|
||||
|
||||
@@ -56,7 +56,10 @@ if (require.main === module) {
|
||||
'The formats option (-f/--formats) has been removed. Consider the properties option (-p/--properties) instead.');
|
||||
process.exit(1);
|
||||
}
|
||||
const baseSourcePath = AbsoluteFsPath.resolve(options['s'] || './node_modules');
|
||||
|
||||
setFileSystem(new NodeJSFileSystem());
|
||||
|
||||
const baseSourcePath = resolve(options['s'] || './node_modules');
|
||||
const propertiesToConsider: string[] = options['p'];
|
||||
const targetEntryPointPath = options['t'] ? options['t'] : undefined;
|
||||
const compileAllFormats = !options['first-only'];
|
||||
|
||||
@@ -10,14 +10,13 @@ import * as ts from 'typescript';
|
||||
|
||||
import {BaseDefDecoratorHandler, ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
|
||||
import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles';
|
||||
import {AbsoluteFsPath, FileSystem, LogicalFileSystem, absoluteFrom, dirname, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../../src/ngtsc/imports';
|
||||
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, LocalMetadataRegistry} from '../../../src/ngtsc/metadata';
|
||||
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
||||
import {AbsoluteFsPath, LogicalFileSystem} from '../../../src/ngtsc/path';
|
||||
import {ClassDeclaration, ClassSymbol, Decorator} from '../../../src/ngtsc/reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../../src/ngtsc/scope';
|
||||
import {CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||
import {isDefined} from '../utils';
|
||||
|
||||
@@ -57,9 +56,9 @@ class NgccResourceLoader implements ResourceLoader {
|
||||
constructor(private fs: FileSystem) {}
|
||||
canPreload = false;
|
||||
preload(): undefined|Promise<void> { throw new Error('Not implemented.'); }
|
||||
load(url: string): string { return this.fs.readFile(AbsoluteFsPath.resolve(url)); }
|
||||
load(url: string): string { return this.fs.readFile(resolve(url)); }
|
||||
resolve(url: string, containingFile: string): string {
|
||||
return AbsoluteFsPath.resolve(AbsoluteFsPath.dirname(AbsoluteFsPath.from(containingFile)), url);
|
||||
return resolve(dirname(absoluteFrom(containingFile)), url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system';
|
||||
import {Declaration} from '../../../src/ngtsc/reflection';
|
||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||
import {hasNameIdentifier, isDefined} from '../utils';
|
||||
@@ -94,12 +94,11 @@ export class PrivateDeclarationsAnalyzer {
|
||||
});
|
||||
|
||||
return Array.from(privateDeclarations.keys()).map(id => {
|
||||
const from = AbsoluteFsPath.fromSourceFile(id.getSourceFile());
|
||||
const from = absoluteFromSourceFile(id.getSourceFile());
|
||||
const declaration = privateDeclarations.get(id) !;
|
||||
const alias = exportAliasDeclarations.has(id) ? exportAliasDeclarations.get(id) ! : null;
|
||||
const dtsDeclaration = this.host.getDtsDeclaration(declaration.node);
|
||||
const dtsFrom =
|
||||
dtsDeclaration && AbsoluteFsPath.fromSourceFile(dtsDeclaration.getSourceFile());
|
||||
const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile());
|
||||
|
||||
return {identifier: id.text, from, dtsFrom, alias};
|
||||
});
|
||||
|
||||
@@ -6,11 +6,8 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, PathSegment} from '../../../src/ngtsc/file_system';
|
||||
import {isRequireCall} from '../host/commonjs_host';
|
||||
|
||||
import {DependencyHost, DependencyInfo} from './dependency_host';
|
||||
import {ModuleResolver, ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/file_system';
|
||||
|
||||
export interface DependencyHost {
|
||||
findDependencies(entryPointPath: AbsoluteFsPath): DependencyInfo;
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
*/
|
||||
|
||||
import {DepGraph} from 'dependency-graph';
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {EntryPoint, EntryPointFormat, EntryPointJsonProperty, getEntryPointFormat} from '../packages/entry_point';
|
||||
import {DependencyHost} from './dependency_host';
|
||||
@@ -176,7 +175,7 @@ export class DependencyResolver {
|
||||
|
||||
if (format === 'esm2015' || format === 'esm5' || format === 'umd' || format === 'commonjs') {
|
||||
const formatPath = entryPoint.packageJson[property] !;
|
||||
return {format, path: AbsoluteFsPath.resolve(entryPoint.path, formatPath)};
|
||||
return {format, path: resolve(entryPoint.path, formatPath)};
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
|
||||
@@ -6,13 +6,10 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, PathSegment} from '../../../src/ngtsc/file_system';
|
||||
import {DependencyHost, DependencyInfo} from './dependency_host';
|
||||
import {ModuleResolver, ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver';
|
||||
|
||||
|
||||
/**
|
||||
* Helper functions for computing dependencies.
|
||||
*/
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, dirname, isRoot, join, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {PathMappings, isRelativePath} from '../utils';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is a very cut-down implementation of the TypeScript module resolution strategy.
|
||||
*
|
||||
@@ -55,7 +56,7 @@ export class ModuleResolver {
|
||||
* Convert the `pathMappings` into a collection of `PathMapper` functions.
|
||||
*/
|
||||
private processPathMappings(pathMappings: PathMappings): ProcessedPathMapping[] {
|
||||
const baseUrl = AbsoluteFsPath.from(pathMappings.baseUrl);
|
||||
const baseUrl = absoluteFrom(pathMappings.baseUrl);
|
||||
return Object.keys(pathMappings.paths).map(pathPattern => {
|
||||
const matcher = splitOnStar(pathPattern);
|
||||
const templates = pathMappings.paths[pathPattern].map(splitOnStar);
|
||||
@@ -71,9 +72,8 @@ export class ModuleResolver {
|
||||
* If neither of these files exist then the method returns `null`.
|
||||
*/
|
||||
private resolveAsRelativePath(moduleName: string, fromPath: AbsoluteFsPath): ResolvedModule|null {
|
||||
const resolvedPath = this.resolvePath(
|
||||
AbsoluteFsPath.resolve(AbsoluteFsPath.dirname(fromPath), moduleName),
|
||||
this.relativeExtensions);
|
||||
const resolvedPath =
|
||||
this.resolvePath(resolve(dirname(fromPath), moduleName), this.relativeExtensions);
|
||||
return resolvedPath && new ResolvedRelativeModule(resolvedPath);
|
||||
}
|
||||
|
||||
@@ -118,13 +118,13 @@ export class ModuleResolver {
|
||||
*/
|
||||
private resolveAsEntryPoint(moduleName: string, fromPath: AbsoluteFsPath): ResolvedModule|null {
|
||||
let folder = fromPath;
|
||||
while (!AbsoluteFsPath.isRoot(folder)) {
|
||||
folder = AbsoluteFsPath.dirname(folder);
|
||||
while (!isRoot(folder)) {
|
||||
folder = dirname(folder);
|
||||
if (folder.endsWith('node_modules')) {
|
||||
// Skip up if the folder already ends in node_modules
|
||||
folder = AbsoluteFsPath.dirname(folder);
|
||||
folder = dirname(folder);
|
||||
}
|
||||
const modulePath = AbsoluteFsPath.resolve(folder, 'node_modules', moduleName);
|
||||
const modulePath = resolve(folder, 'node_modules', moduleName);
|
||||
if (this.isEntryPoint(modulePath)) {
|
||||
return new ResolvedExternalModule(modulePath);
|
||||
} else if (this.resolveAsRelativePath(modulePath, fromPath)) {
|
||||
@@ -141,7 +141,7 @@ export class ModuleResolver {
|
||||
*/
|
||||
private resolvePath(path: AbsoluteFsPath, postFixes: string[]): AbsoluteFsPath|null {
|
||||
for (const postFix of postFixes) {
|
||||
const testPath = AbsoluteFsPath.fromUnchecked(path + postFix);
|
||||
const testPath = absoluteFrom(path + postFix);
|
||||
if (this.fs.exists(testPath)) {
|
||||
return testPath;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ export class ModuleResolver {
|
||||
* This is achieved by checking for the existence of `${modulePath}/package.json`.
|
||||
*/
|
||||
private isEntryPoint(modulePath: AbsoluteFsPath): boolean {
|
||||
return this.fs.exists(AbsoluteFsPath.join(modulePath, 'package.json'));
|
||||
return this.fs.exists(join(modulePath, 'package.json'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,8 +215,7 @@ export class ModuleResolver {
|
||||
*/
|
||||
private computeMappedTemplates(mapping: ProcessedPathMapping, match: string) {
|
||||
return mapping.templates.map(
|
||||
template =>
|
||||
AbsoluteFsPath.resolve(mapping.baseUrl, template.prefix + match + template.postfix));
|
||||
template => resolve(mapping.baseUrl, template.prefix + match + template.postfix));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,9 +224,9 @@ export class ModuleResolver {
|
||||
*/
|
||||
private findPackagePath(path: AbsoluteFsPath): AbsoluteFsPath|null {
|
||||
let folder = path;
|
||||
while (!AbsoluteFsPath.isRoot(folder)) {
|
||||
folder = AbsoluteFsPath.dirname(folder);
|
||||
if (this.fs.exists(AbsoluteFsPath.join(folder, 'package.json'))) {
|
||||
while (!isRoot(folder)) {
|
||||
folder = dirname(folder);
|
||||
if (this.fs.exists(join(folder, 'package.json'))) {
|
||||
return folder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,16 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, PathSegment} from '../../../src/ngtsc/file_system';
|
||||
import {getImportsOfUmdModule, parseStatementForUmdModule} from '../host/umd_host';
|
||||
|
||||
import {DependencyHost, DependencyInfo} from './dependency_host';
|
||||
import {ModuleResolver, ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Helper functions for computing dependencies.
|
||||
*/
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* @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 {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
|
||||
/**
|
||||
* A basic interface to abstract the underlying file-system.
|
||||
*
|
||||
* This makes it easier to provide mock file-systems in unit tests,
|
||||
* but also to create clever file-systems that have features such as caching.
|
||||
*/
|
||||
export interface FileSystem {
|
||||
exists(path: AbsoluteFsPath): boolean;
|
||||
readFile(path: AbsoluteFsPath): string;
|
||||
writeFile(path: AbsoluteFsPath, data: string): void;
|
||||
readdir(path: AbsoluteFsPath): PathSegment[];
|
||||
lstat(path: AbsoluteFsPath): FileStats;
|
||||
stat(path: AbsoluteFsPath): FileStats;
|
||||
pwd(): AbsoluteFsPath;
|
||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void;
|
||||
ensureDir(path: AbsoluteFsPath): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about an object in the FileSystem.
|
||||
* This is analogous to the `fs.Stats` class in Node.js.
|
||||
*/
|
||||
export interface FileStats {
|
||||
isFile(): boolean;
|
||||
isDirectory(): boolean;
|
||||
isSymbolicLink(): boolean;
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* @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 fs from 'fs';
|
||||
import {cp, mkdir, mv} from 'shelljs';
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from './file_system';
|
||||
|
||||
/**
|
||||
* A wrapper around the Node.js file-system (i.e the `fs` package).
|
||||
*/
|
||||
export class NodeJSFileSystem implements FileSystem {
|
||||
exists(path: AbsoluteFsPath): boolean { return fs.existsSync(path); }
|
||||
readFile(path: AbsoluteFsPath): string { return fs.readFileSync(path, 'utf8'); }
|
||||
writeFile(path: AbsoluteFsPath, data: string): void {
|
||||
return fs.writeFileSync(path, data, 'utf8');
|
||||
}
|
||||
readdir(path: AbsoluteFsPath): PathSegment[] { return fs.readdirSync(path) as PathSegment[]; }
|
||||
lstat(path: AbsoluteFsPath): fs.Stats { return fs.lstatSync(path); }
|
||||
stat(path: AbsoluteFsPath): fs.Stats { return fs.statSync(path); }
|
||||
pwd() { return AbsoluteFsPath.from(process.cwd()); }
|
||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { cp(from, to); }
|
||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { mv(from, to); }
|
||||
ensureDir(path: AbsoluteFsPath): void { mkdir('-p', path); }
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||
import {Declaration, Import} from '../../../src/ngtsc/reflection';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {BundleProgram} from '../packages/bundle_program';
|
||||
@@ -122,13 +122,13 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost {
|
||||
if (this.compilerHost.resolveModuleNames) {
|
||||
const moduleInfo =
|
||||
this.compilerHost.resolveModuleNames([moduleName], containingFile.fileName)[0];
|
||||
return moduleInfo && this.program.getSourceFile(moduleInfo.resolvedFileName);
|
||||
return moduleInfo && this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedFileName));
|
||||
} else {
|
||||
const moduleInfo = ts.resolveModuleName(
|
||||
moduleName, containingFile.fileName, this.program.getCompilerOptions(),
|
||||
this.compilerHost);
|
||||
return moduleInfo.resolvedModule &&
|
||||
this.program.getSourceFile(moduleInfo.resolvedModule.resolvedFileName);
|
||||
this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedModule.resolvedFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ClassSymbol, CtorParameter, Declaration, Decorator, Import, TypeScriptReflectionHost, reflectObjectLiteral} from '../../../src/ngtsc/reflection';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {BundleProgram} from '../packages/bundle_program';
|
||||
@@ -1281,7 +1282,7 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
||||
* @param dtsProgram The program containing all the typings files.
|
||||
* @returns a map of class names to class declarations.
|
||||
*/
|
||||
protected computeDtsDeclarationMap(dtsRootFileName: string, dtsProgram: ts.Program):
|
||||
protected computeDtsDeclarationMap(dtsRootFileName: AbsoluteFsPath, dtsProgram: ts.Program):
|
||||
Map<string, ts.Declaration> {
|
||||
const dtsDeclarationMap = new Map<string, ts.Declaration>();
|
||||
const checker = dtsProgram.getTypeChecker();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||
import {Declaration, Import} from '../../../src/ngtsc/reflection';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {BundleProgram} from '../packages/bundle_program';
|
||||
@@ -154,13 +155,13 @@ export class UmdReflectionHost extends Esm5ReflectionHost {
|
||||
if (this.compilerHost.resolveModuleNames) {
|
||||
const moduleInfo =
|
||||
this.compilerHost.resolveModuleNames([moduleName], containingFile.fileName)[0];
|
||||
return moduleInfo && this.program.getSourceFile(moduleInfo.resolvedFileName);
|
||||
return moduleInfo && this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedFileName));
|
||||
} else {
|
||||
const moduleInfo = ts.resolveModuleName(
|
||||
moduleName, containingFile.fileName, this.program.getCompilerOptions(),
|
||||
this.compilerHost);
|
||||
return moduleInfo.resolvedModule &&
|
||||
this.program.getSourceFile(moduleInfo.resolvedModule.resolvedFileName);
|
||||
this.program.getSourceFile(absoluteFrom(moduleInfo.resolvedModule.resolvedFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,15 +5,12 @@
|
||||
* 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 {AbsoluteFsPath} from '../../src/ngtsc/path';
|
||||
|
||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, resolve} from '../../src/ngtsc/file_system';
|
||||
import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host';
|
||||
import {DependencyResolver} from './dependencies/dependency_resolver';
|
||||
import {EsmDependencyHost} from './dependencies/esm_dependency_host';
|
||||
import {ModuleResolver} from './dependencies/module_resolver';
|
||||
import {UmdDependencyHost} from './dependencies/umd_dependency_host';
|
||||
import {FileSystem} from './file_system/file_system';
|
||||
import {NodeJSFileSystem} from './file_system/node_js_file_system';
|
||||
import {ConsoleLogger, LogLevel} from './logging/console_logger';
|
||||
import {Logger} from './logging/logger';
|
||||
import {hasBeenProcessed, markAsProcessed} from './packages/build_marker';
|
||||
@@ -79,7 +76,7 @@ export function mainNgcc(
|
||||
{basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
||||
compileAllFormats = true, createNewEntryPointFormats = false,
|
||||
logger = new ConsoleLogger(LogLevel.info), pathMappings}: NgccOptions): void {
|
||||
const fs = new NodeJSFileSystem();
|
||||
const fs = getFileSystem();
|
||||
const transformer = new Transformer(fs, logger);
|
||||
const moduleResolver = new ModuleResolver(fs, pathMappings);
|
||||
const esmDependencyHost = new EsmDependencyHost(fs, moduleResolver);
|
||||
@@ -95,7 +92,7 @@ export function mainNgcc(
|
||||
const fileWriter = getFileWriter(fs, createNewEntryPointFormats);
|
||||
|
||||
const absoluteTargetEntryPointPath =
|
||||
targetEntryPointPath ? AbsoluteFsPath.resolve(basePath, targetEntryPointPath) : undefined;
|
||||
targetEntryPointPath ? resolve(basePath, targetEntryPointPath) : undefined;
|
||||
|
||||
if (absoluteTargetEntryPointPath &&
|
||||
hasProcessedTargetEntryPoint(
|
||||
@@ -104,8 +101,8 @@ export function mainNgcc(
|
||||
return;
|
||||
}
|
||||
|
||||
const {entryPoints, invalidEntryPoints} = finder.findEntryPoints(
|
||||
AbsoluteFsPath.from(basePath), absoluteTargetEntryPointPath, pathMappings);
|
||||
const {entryPoints, invalidEntryPoints} =
|
||||
finder.findEntryPoints(absoluteFrom(basePath), absoluteTargetEntryPointPath, pathMappings);
|
||||
|
||||
invalidEntryPoints.forEach(invalidEntryPoint => {
|
||||
logger.debug(
|
||||
@@ -119,14 +116,13 @@ export function mainNgcc(
|
||||
return;
|
||||
}
|
||||
|
||||
entryPoints.forEach(entryPoint => {
|
||||
for (const entryPoint of entryPoints) {
|
||||
// Are we compiling the Angular core?
|
||||
const isCore = entryPoint.name === '@angular/core';
|
||||
|
||||
const compiledFormats = new Set<string>();
|
||||
const entryPointPackageJson = entryPoint.packageJson;
|
||||
const entryPointPackageJsonPath =
|
||||
AbsoluteFsPath.fromUnchecked(`${entryPoint.path}/package.json`);
|
||||
const entryPointPackageJsonPath = fs.resolve(entryPoint.path, 'package.json');
|
||||
|
||||
const hasProcessedDts = hasBeenProcessed(entryPointPackageJson, 'typings');
|
||||
|
||||
@@ -180,7 +176,7 @@ export function mainNgcc(
|
||||
throw new Error(
|
||||
`Failed to compile any formats for entry-point at (${entryPoint.path}). Tried ${propertiesToConsider}.`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getFileWriter(fs: FileSystem, createNewEntryPointFormats: boolean): FileWriter {
|
||||
@@ -190,7 +186,7 @@ function getFileWriter(fs: FileSystem, createNewEntryPointFormats: boolean): Fil
|
||||
function hasProcessedTargetEntryPoint(
|
||||
fs: FileSystem, targetPath: AbsoluteFsPath, propertiesToConsider: string[],
|
||||
compileAllFormats: boolean) {
|
||||
const packageJsonPath = AbsoluteFsPath.resolve(targetPath, 'package.json');
|
||||
const packageJsonPath = resolve(targetPath, 'package.json');
|
||||
const packageJson = JSON.parse(fs.readFile(packageJsonPath));
|
||||
|
||||
for (const property of propertiesToConsider) {
|
||||
@@ -221,7 +217,7 @@ function hasProcessedTargetEntryPoint(
|
||||
*/
|
||||
function markNonAngularPackageAsProcessed(
|
||||
fs: FileSystem, path: AbsoluteFsPath, propertiesToConsider: string[]) {
|
||||
const packageJsonPath = AbsoluteFsPath.resolve(path, 'package.json');
|
||||
const packageJsonPath = resolve(path, 'package.json');
|
||||
const packageJson = JSON.parse(fs.readFile(packageJsonPath));
|
||||
propertiesToConsider.forEach(formatProperty => {
|
||||
if (packageJson[formatProperty])
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
* 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 {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {EntryPointJsonProperty, EntryPointPackageJson} from './entry_point';
|
||||
|
||||
export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, dirname, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {patchTsGetExpandoInitializer, restoreGetExpandoInitializer} from './patch_ts_expando_initializer';
|
||||
|
||||
/**
|
||||
@@ -35,12 +33,14 @@ export interface BundleProgram {
|
||||
export function makeBundleProgram(
|
||||
fs: FileSystem, isCore: boolean, path: AbsoluteFsPath, r3FileName: string,
|
||||
options: ts.CompilerOptions, host: ts.CompilerHost): BundleProgram {
|
||||
const r3SymbolsPath =
|
||||
isCore ? findR3SymbolsPath(fs, AbsoluteFsPath.dirname(path), r3FileName) : null;
|
||||
const r3SymbolsPath = isCore ? findR3SymbolsPath(fs, dirname(path), r3FileName) : null;
|
||||
const rootPaths = r3SymbolsPath ? [path, r3SymbolsPath] : [path];
|
||||
|
||||
const originalGetExpandoInitializer = patchTsGetExpandoInitializer();
|
||||
const program = ts.createProgram(rootPaths, options, host);
|
||||
// Ask for the typeChecker to trigger the binding phase of the compilation.
|
||||
// This will then exercise the patched function.
|
||||
program.getTypeChecker();
|
||||
restoreGetExpandoInitializer(originalGetExpandoInitializer);
|
||||
|
||||
const file = program.getSourceFile(path) !;
|
||||
@@ -54,7 +54,7 @@ export function makeBundleProgram(
|
||||
*/
|
||||
export function findR3SymbolsPath(
|
||||
fs: FileSystem, directory: AbsoluteFsPath, filename: string): AbsoluteFsPath|null {
|
||||
const r3SymbolsFilePath = AbsoluteFsPath.resolve(directory, filename);
|
||||
const r3SymbolsFilePath = resolve(directory, filename);
|
||||
if (fs.exists(r3SymbolsFilePath)) {
|
||||
return r3SymbolsFilePath;
|
||||
}
|
||||
@@ -67,13 +67,12 @@ export function findR3SymbolsPath(
|
||||
.filter(p => p !== 'node_modules')
|
||||
// Only interested in directories (and only those that are not symlinks)
|
||||
.filter(p => {
|
||||
const stat = fs.lstat(AbsoluteFsPath.resolve(directory, p));
|
||||
const stat = fs.lstat(resolve(directory, p));
|
||||
return stat.isDirectory() && !stat.isSymbolicLink();
|
||||
});
|
||||
|
||||
for (const subDirectory of subDirectories) {
|
||||
const r3SymbolsFilePath =
|
||||
findR3SymbolsPath(fs, AbsoluteFsPath.resolve(directory, subDirectory), filename);
|
||||
const r3SymbolsFilePath = findR3SymbolsPath(fs, resolve(directory, subDirectory), filename);
|
||||
if (r3SymbolsFilePath) {
|
||||
return r3SymbolsFilePath;
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, join, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {parseStatementForUmdModule} from '../host/umd_host';
|
||||
import {Logger} from '../logging/logger';
|
||||
|
||||
@@ -70,7 +69,7 @@ export const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[] =
|
||||
export function getEntryPointInfo(
|
||||
fs: FileSystem, logger: Logger, packagePath: AbsoluteFsPath,
|
||||
entryPointPath: AbsoluteFsPath): EntryPoint|null {
|
||||
const packageJsonPath = AbsoluteFsPath.resolve(entryPointPath, 'package.json');
|
||||
const packageJsonPath = resolve(entryPointPath, 'package.json');
|
||||
if (!fs.exists(packageJsonPath)) {
|
||||
return null;
|
||||
}
|
||||
@@ -88,15 +87,14 @@ export function getEntryPointInfo(
|
||||
}
|
||||
|
||||
// Also there must exist a `metadata.json` file next to the typings entry-point.
|
||||
const metadataPath =
|
||||
AbsoluteFsPath.resolve(entryPointPath, typings.replace(/\.d\.ts$/, '') + '.metadata.json');
|
||||
const metadataPath = resolve(entryPointPath, typings.replace(/\.d\.ts$/, '') + '.metadata.json');
|
||||
|
||||
const entryPointInfo: EntryPoint = {
|
||||
name: entryPointPackageJson.name,
|
||||
packageJson: entryPointPackageJson,
|
||||
package: packagePath,
|
||||
path: entryPointPath,
|
||||
typings: AbsoluteFsPath.resolve(entryPointPath, typings),
|
||||
typings: resolve(entryPointPath, typings),
|
||||
compiledByAngular: fs.exists(metadataPath),
|
||||
};
|
||||
|
||||
@@ -127,7 +125,7 @@ export function getEntryPointFormat(
|
||||
if (mainFile === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const pathToMain = AbsoluteFsPath.join(entryPoint.path, mainFile);
|
||||
const pathToMain = join(entryPoint.path, mainFile);
|
||||
return isUmdModule(fs, pathToMain) ? 'umd' : 'commonjs';
|
||||
case 'module':
|
||||
return 'esm5';
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {NgtscCompilerHost} from '../../../src/ngtsc/file_system/src/compiler_host';
|
||||
import {PathMappings} from '../utils';
|
||||
import {BundleProgram, makeBundleProgram} from './bundle_program';
|
||||
import {EntryPointFormat, EntryPointJsonProperty} from './entry_point';
|
||||
import {NgccCompilerHost, NgccSourcesCompilerHost} from './ngcc_compiler_host';
|
||||
import {NgccSourcesCompilerHost} from './ngcc_compiler_host';
|
||||
|
||||
|
||||
/**
|
||||
* A bundle of files and paths (and TS programs) that correspond to a particular
|
||||
@@ -49,17 +49,16 @@ export function makeEntryPointBundle(
|
||||
rootDir: entryPointPath, ...pathMappings
|
||||
};
|
||||
const srcHost = new NgccSourcesCompilerHost(fs, options, entryPointPath);
|
||||
const dtsHost = new NgccCompilerHost(fs, options);
|
||||
const rootDirs = [AbsoluteFsPath.from(entryPointPath)];
|
||||
const dtsHost = new NgtscCompilerHost(fs, options);
|
||||
const rootDirs = [absoluteFrom(entryPointPath)];
|
||||
|
||||
// Create the bundle programs, as necessary.
|
||||
const src = makeBundleProgram(
|
||||
fs, isCore, AbsoluteFsPath.resolve(entryPointPath, formatPath), 'r3_symbols.js', options,
|
||||
srcHost);
|
||||
const dts = transformDts ? makeBundleProgram(
|
||||
fs, isCore, AbsoluteFsPath.resolve(entryPointPath, typingsPath),
|
||||
'r3_symbols.d.ts', options, dtsHost) :
|
||||
null;
|
||||
fs, isCore, resolve(entryPointPath, formatPath), 'r3_symbols.js', options, srcHost);
|
||||
const dts = transformDts ?
|
||||
makeBundleProgram(
|
||||
fs, isCore, resolve(entryPointPath, typingsPath), 'r3_symbols.d.ts', options, dtsHost) :
|
||||
null;
|
||||
const isFlatCore = isCore && src.r3SymbolsFile === null;
|
||||
|
||||
return {format, formatProperty, rootDirs, isCore, isFlatCore, src, dts};
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
* 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 {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {AbsoluteFsPath, FileSystem, join, resolve} from '../../../src/ngtsc/file_system';
|
||||
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {PathMappings} from '../utils';
|
||||
|
||||
import {EntryPoint, getEntryPointInfo} from './entry_point';
|
||||
|
||||
export class EntryPointFinder {
|
||||
@@ -55,9 +55,9 @@ export class EntryPointFinder {
|
||||
AbsoluteFsPath[] {
|
||||
const basePaths = [sourceDirectory];
|
||||
if (pathMappings) {
|
||||
const baseUrl = AbsoluteFsPath.resolve(pathMappings.baseUrl);
|
||||
const baseUrl = resolve(pathMappings.baseUrl);
|
||||
values(pathMappings.paths).forEach(paths => paths.forEach(path => {
|
||||
basePaths.push(AbsoluteFsPath.join(baseUrl, extractPathPrefix(path)));
|
||||
basePaths.push(join(baseUrl, extractPathPrefix(path)));
|
||||
}));
|
||||
}
|
||||
basePaths.sort(); // Get the paths in order with the shorter ones first.
|
||||
@@ -84,17 +84,17 @@ export class EntryPointFinder {
|
||||
.filter(p => p !== 'node_modules')
|
||||
// Only interested in directories (and only those that are not symlinks)
|
||||
.filter(p => {
|
||||
const stat = this.fs.lstat(AbsoluteFsPath.resolve(sourceDirectory, p));
|
||||
const stat = this.fs.lstat(resolve(sourceDirectory, p));
|
||||
return stat.isDirectory() && !stat.isSymbolicLink();
|
||||
})
|
||||
.forEach(p => {
|
||||
// Either the directory is a potential package or a namespace containing packages (e.g
|
||||
// `@angular`).
|
||||
const packagePath = AbsoluteFsPath.join(sourceDirectory, p);
|
||||
const packagePath = join(sourceDirectory, p);
|
||||
entryPoints.push(...this.walkDirectoryForEntryPoints(packagePath));
|
||||
|
||||
// Also check for any nested node_modules in this package
|
||||
const nestedNodeModulesPath = AbsoluteFsPath.join(packagePath, 'node_modules');
|
||||
const nestedNodeModulesPath = join(packagePath, 'node_modules');
|
||||
if (this.fs.exists(nestedNodeModulesPath)) {
|
||||
entryPoints.push(...this.walkDirectoryForEntryPoints(nestedNodeModulesPath));
|
||||
}
|
||||
@@ -145,11 +145,11 @@ export class EntryPointFinder {
|
||||
.filter(p => p !== 'node_modules')
|
||||
// Only interested in directories (and only those that are not symlinks)
|
||||
.filter(p => {
|
||||
const stat = this.fs.lstat(AbsoluteFsPath.resolve(dir, p));
|
||||
const stat = this.fs.lstat(resolve(dir, p));
|
||||
return stat.isDirectory() && !stat.isSymbolicLink();
|
||||
})
|
||||
.forEach(subDir => {
|
||||
const resolvedSubDir = AbsoluteFsPath.resolve(dir, subDir);
|
||||
const resolvedSubDir = resolve(dir, subDir);
|
||||
fn(resolvedSubDir);
|
||||
this.walkDirectory(resolvedSubDir, fn);
|
||||
});
|
||||
|
||||
@@ -5,74 +5,19 @@
|
||||
* 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 os from 'os';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {NgtscCompilerHost} from '../../../src/ngtsc/file_system/src/compiler_host';
|
||||
import {isRelativePath} from '../utils';
|
||||
|
||||
export class NgccCompilerHost implements ts.CompilerHost {
|
||||
private _caseSensitive = this.fs.exists(AbsoluteFsPath.fromUnchecked(__filename.toUpperCase()));
|
||||
|
||||
constructor(protected fs: FileSystem, protected options: ts.CompilerOptions) {}
|
||||
|
||||
getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile|undefined {
|
||||
const text = this.readFile(fileName);
|
||||
return text !== undefined ? ts.createSourceFile(fileName, text, languageVersion) : undefined;
|
||||
}
|
||||
|
||||
getDefaultLibFileName(options: ts.CompilerOptions): string {
|
||||
return this.getDefaultLibLocation() + '/' + ts.getDefaultLibFileName(options);
|
||||
}
|
||||
|
||||
getDefaultLibLocation(): string {
|
||||
const nodeLibPath = AbsoluteFsPath.from(require.resolve('typescript'));
|
||||
return AbsoluteFsPath.join(nodeLibPath, '..');
|
||||
}
|
||||
|
||||
writeFile(fileName: string, data: string): void {
|
||||
this.fs.writeFile(AbsoluteFsPath.fromUnchecked(fileName), data);
|
||||
}
|
||||
|
||||
getCurrentDirectory(): string { return this.fs.pwd(); }
|
||||
|
||||
getCanonicalFileName(fileName: string): string {
|
||||
return this.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||
}
|
||||
|
||||
useCaseSensitiveFileNames(): boolean { return this._caseSensitive; }
|
||||
|
||||
getNewLine(): string {
|
||||
switch (this.options.newLine) {
|
||||
case ts.NewLineKind.CarriageReturnLineFeed:
|
||||
return '\r\n';
|
||||
case ts.NewLineKind.LineFeed:
|
||||
return '\n';
|
||||
default:
|
||||
return os.EOL;
|
||||
}
|
||||
}
|
||||
|
||||
fileExists(fileName: string): boolean {
|
||||
return this.fs.exists(AbsoluteFsPath.fromUnchecked(fileName));
|
||||
}
|
||||
|
||||
readFile(fileName: string): string|undefined {
|
||||
if (!this.fileExists(fileName)) {
|
||||
return undefined;
|
||||
}
|
||||
return this.fs.readFile(AbsoluteFsPath.fromUnchecked(fileName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a compiler host that resolves a module import as a JavaScript source file if
|
||||
* available, instead of the .d.ts typings file that would have been resolved by TypeScript. This
|
||||
* is necessary for packages that have their typings in the same directory as the sources, which
|
||||
* would otherwise let TypeScript prefer the .d.ts file instead of the JavaScript source file.
|
||||
*/
|
||||
export class NgccSourcesCompilerHost extends NgccCompilerHost {
|
||||
export class NgccSourcesCompilerHost extends NgtscCompilerHost {
|
||||
private cache = ts.createModuleResolutionCache(
|
||||
this.getCurrentDirectory(), file => this.getCanonicalFileName(file));
|
||||
|
||||
|
||||
@@ -6,13 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {CompiledFile, DecorationAnalyzer} from '../analysis/decoration_analyzer';
|
||||
import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../analysis/module_with_providers_analyzer';
|
||||
import {NgccReferencesRegistry} from '../analysis/ngcc_references_registry';
|
||||
import {ExportInfo, PrivateDeclarationsAnalyzer} from '../analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyses, SwitchMarkerAnalyzer} from '../analysis/switch_marker_analyzer';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {CommonJsReflectionHost} from '../host/commonjs_host';
|
||||
import {Esm2015ReflectionHost} from '../host/esm2015_host';
|
||||
import {Esm5ReflectionHost} from '../host/esm5_host';
|
||||
@@ -27,11 +26,8 @@ import {Renderer} from '../rendering/renderer';
|
||||
import {RenderingFormatter} from '../rendering/rendering_formatter';
|
||||
import {UmdRenderingFormatter} from '../rendering/umd_rendering_formatter';
|
||||
import {FileToWrite} from '../rendering/utils';
|
||||
|
||||
import {EntryPointBundle} from './entry_point_bundle';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A Package is stored in a directory on disk and that directory can contain one or more package
|
||||
* formats - e.g. fesm2015, UMD, etc. Additionally, each package provides typings (`.d.ts` files).
|
||||
|
||||
@@ -7,20 +7,19 @@
|
||||
*/
|
||||
import MagicString from 'magic-string';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {CompileResult} from '../../../src/ngtsc/transform';
|
||||
import {translateType, ImportManager} from '../../../src/ngtsc/translator';
|
||||
import {DecorationAnalyses} from '../analysis/decoration_analyzer';
|
||||
import {ModuleWithProvidersInfo, ModuleWithProvidersAnalyses} from '../analysis/module_with_providers_analyzer';
|
||||
import {PrivateDeclarationsAnalyses, ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||
import {IMPORT_PREFIX} from '../constants';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {FileToWrite, getImportRewriter} from './utils';
|
||||
import {RenderingFormatter} from './rendering_formatter';
|
||||
import {extractSourceMap, renderSourceAndMap} from './source_maps';
|
||||
import {CompileResult} from '@angular/compiler-cli/src/ngtsc/transform';
|
||||
|
||||
/**
|
||||
* A structure that captures information about what needs to be rendered
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
import MagicString from 'magic-string';
|
||||
import * as ts from 'typescript';
|
||||
import {PathSegment, AbsoluteFsPath} from '../../../src/ngtsc/path';
|
||||
import {relative, dirname, AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system';
|
||||
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
||||
import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
||||
import {CompiledClass} from '../analysis/decoration_analyzer';
|
||||
@@ -46,8 +46,7 @@ export class EsmRenderingFormatter implements RenderingFormatter {
|
||||
|
||||
if (from) {
|
||||
const basePath = stripExtension(from);
|
||||
const relativePath =
|
||||
'./' + PathSegment.relative(AbsoluteFsPath.dirname(entryPointBasePath), basePath);
|
||||
const relativePath = './' + relative(dirname(entryPointBasePath), basePath);
|
||||
exportFrom = entryPointBasePath !== basePath ? ` from '${relativePath}'` : '';
|
||||
}
|
||||
|
||||
@@ -136,12 +135,11 @@ export class EsmRenderingFormatter implements RenderingFormatter {
|
||||
importManager: ImportManager): void {
|
||||
moduleWithProviders.forEach(info => {
|
||||
const ngModuleName = info.ngModule.node.name.text;
|
||||
const declarationFile = AbsoluteFsPath.fromSourceFile(info.declaration.getSourceFile());
|
||||
const ngModuleFile = AbsoluteFsPath.fromSourceFile(info.ngModule.node.getSourceFile());
|
||||
const declarationFile = absoluteFromSourceFile(info.declaration.getSourceFile());
|
||||
const ngModuleFile = absoluteFromSourceFile(info.ngModule.node.getSourceFile());
|
||||
const importPath = info.ngModule.viaModule ||
|
||||
(declarationFile !== ngModuleFile ?
|
||||
stripExtension(
|
||||
`./${PathSegment.relative(AbsoluteFsPath.dirname(declarationFile), ngModuleFile)}`) :
|
||||
stripExtension(`./${relative(dirname(declarationFile), ngModuleFile)}`) :
|
||||
null);
|
||||
const ngModule = generateImportString(importManager, importPath, ngModuleName);
|
||||
|
||||
|
||||
@@ -8,14 +8,13 @@
|
||||
import {ConstantPool, Expression, Statement, WrappedNodeExpr, WritePropExpr} from '@angular/compiler';
|
||||
import MagicString from 'magic-string';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {NOOP_DEFAULT_IMPORT_RECORDER} from '@angular/compiler-cli/src/ngtsc/imports';
|
||||
import {NOOP_DEFAULT_IMPORT_RECORDER} from '../../../src/ngtsc/imports';
|
||||
import {translateStatement, ImportManager} from '../../../src/ngtsc/translator';
|
||||
import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/decoration_analyzer';
|
||||
import {PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer';
|
||||
import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
|
||||
import {IMPORT_PREFIX} from '../constants';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||
import {Logger} from '../logging/logger';
|
||||
|
||||
@@ -9,8 +9,7 @@ import {SourceMapConverter, commentRegex, fromJSON, fromObject, fromSource, gene
|
||||
import MagicString from 'magic-string';
|
||||
import {RawSourceMap, SourceMapConsumer, SourceMapGenerator} from 'source-map';
|
||||
import * as ts from 'typescript';
|
||||
import {AbsoluteFsPath, PathSegment} from '../../../src/ngtsc/path';
|
||||
import {FileSystem} from '../file_system/file_system';
|
||||
import {resolve, FileSystem, absoluteFromSourceFile, dirname, basename, absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||
import {Logger} from '../logging/logger';
|
||||
import {FileToWrite} from './utils';
|
||||
|
||||
@@ -39,19 +38,18 @@ export function extractSourceMap(
|
||||
let externalSourceMap: SourceMapConverter|null = null;
|
||||
try {
|
||||
const fileName = external[1] || external[2];
|
||||
const filePath = AbsoluteFsPath.resolve(
|
||||
AbsoluteFsPath.dirname(AbsoluteFsPath.fromSourceFile(file)), fileName);
|
||||
const filePath = resolve(dirname(absoluteFromSourceFile(file)), fileName);
|
||||
const mappingFile = fs.readFile(filePath);
|
||||
externalSourceMap = fromJSON(mappingFile);
|
||||
} catch (e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
logger.warn(
|
||||
`The external map file specified in the source code comment "${e.path}" was not found on the file system.`);
|
||||
const mapPath = AbsoluteFsPath.fromUnchecked(file.fileName + '.map');
|
||||
if (PathSegment.basename(e.path) !== PathSegment.basename(mapPath) && fs.exists(mapPath) &&
|
||||
const mapPath = absoluteFrom(file.fileName + '.map');
|
||||
if (basename(e.path) !== basename(mapPath) && fs.exists(mapPath) &&
|
||||
fs.stat(mapPath).isFile()) {
|
||||
logger.warn(
|
||||
`Guessing the map file name from the source file name: "${PathSegment.basename(mapPath)}"`);
|
||||
`Guessing the map file name from the source file name: "${basename(mapPath)}"`);
|
||||
try {
|
||||
externalSourceMap = fromObject(JSON.parse(fs.readFile(mapPath)));
|
||||
} catch (e) {
|
||||
@@ -76,9 +74,9 @@ export function extractSourceMap(
|
||||
*/
|
||||
export function renderSourceAndMap(
|
||||
sourceFile: ts.SourceFile, input: SourceMapInfo, output: MagicString): FileToWrite[] {
|
||||
const outputPath = AbsoluteFsPath.fromSourceFile(sourceFile);
|
||||
const outputMapPath = AbsoluteFsPath.fromUnchecked(`${outputPath}.map`);
|
||||
const relativeSourcePath = PathSegment.basename(outputPath);
|
||||
const outputPath = absoluteFromSourceFile(sourceFile);
|
||||
const outputMapPath = absoluteFrom(`${outputPath}.map`);
|
||||
const relativeSourcePath = basename(outputPath);
|
||||
const relativeMapPath = `${relativeSourcePath}.map`;
|
||||
|
||||
const outputMap = output.generateMap({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user