style(ngcc): reformat of ngcc after clang update (#36447)
PR Close #36447
This commit is contained in:
parent
c8bef1259c
commit
8be8466a00
|
@ -7,9 +7,10 @@
|
||||||
*/
|
*/
|
||||||
import {CachedFileSystem, NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system';
|
import {CachedFileSystem, NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {AsyncNgccOptions, NgccOptions, SyncNgccOptions, mainNgcc} from './src/main';
|
import {AsyncNgccOptions, mainNgcc, NgccOptions, SyncNgccOptions} from './src/main';
|
||||||
|
|
||||||
export {ConsoleLogger} from './src/logging/console_logger';
|
export {ConsoleLogger} from './src/logging/console_logger';
|
||||||
export {LogLevel, Logger} from './src/logging/logger';
|
export {Logger, LogLevel} from './src/logging/logger';
|
||||||
export {AsyncNgccOptions, NgccOptions, SyncNgccOptions} from './src/main';
|
export {AsyncNgccOptions, NgccOptions, SyncNgccOptions} from './src/main';
|
||||||
export {PathMappings} from './src/utils';
|
export {PathMappings} from './src/utils';
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ if (require.main === module) {
|
||||||
// And we have to convert the option to a string to handle `no-tsconfig`, which will be `false`.
|
// And we have to convert the option to a string to handle `no-tsconfig`, which will be `false`.
|
||||||
const tsConfigPath = `${options['tsconfig']}` === 'false' ? null : options['tsconfig'];
|
const tsConfigPath = `${options['tsconfig']}` === 'false' ? null : options['tsconfig'];
|
||||||
|
|
||||||
(async() => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
const logger = logLevel && new ConsoleLogger(LogLevel[logLevel]);
|
const logger = logLevel && new ConsoleLogger(LogLevel[logLevel]);
|
||||||
|
|
||||||
|
@ -137,7 +137,10 @@ if (require.main === module) {
|
||||||
createNewEntryPointFormats,
|
createNewEntryPointFormats,
|
||||||
logger,
|
logger,
|
||||||
enableI18nLegacyMessageIdFormat,
|
enableI18nLegacyMessageIdFormat,
|
||||||
async: options['async'], invalidateEntryPointManifest, errorOnFailedEntryPoint, tsConfigPath
|
async: options['async'],
|
||||||
|
invalidateEntryPointManifest,
|
||||||
|
errorOnFailedEntryPoint,
|
||||||
|
tsConfigPath
|
||||||
});
|
});
|
||||||
|
|
||||||
if (logger) {
|
if (logger) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {ParsedConfiguration} from '../../..';
|
||||||
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
|
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
|
||||||
import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles';
|
import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles';
|
||||||
import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics';
|
import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics';
|
||||||
import {FileSystem, LogicalFileSystem, absoluteFrom, dirname, resolve} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, dirname, FileSystem, LogicalFileSystem, resolve} from '../../../src/ngtsc/file_system';
|
||||||
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, PrivateExportAliasingHost, Reexport, ReferenceEmitter} from '../../../src/ngtsc/imports';
|
import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, PrivateExportAliasingHost, Reexport, ReferenceEmitter} from '../../../src/ngtsc/imports';
|
||||||
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../../src/ngtsc/metadata';
|
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../../src/ngtsc/metadata';
|
||||||
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
||||||
|
@ -28,7 +28,7 @@ import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||||
import {DefaultMigrationHost} from './migration_host';
|
import {DefaultMigrationHost} from './migration_host';
|
||||||
import {NgccTraitCompiler} from './ngcc_trait_compiler';
|
import {NgccTraitCompiler} from './ngcc_trait_compiler';
|
||||||
import {CompiledClass, CompiledFile, DecorationAnalyses} from './types';
|
import {CompiledClass, CompiledFile, DecorationAnalyses} from './types';
|
||||||
import {NOOP_DEPENDENCY_TRACKER, isWithinPackage} from './util';
|
import {isWithinPackage, NOOP_DEPENDENCY_TRACKER} from './util';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,8 +38,12 @@ import {NOOP_DEPENDENCY_TRACKER, isWithinPackage} from './util';
|
||||||
class NgccResourceLoader implements ResourceLoader {
|
class NgccResourceLoader implements ResourceLoader {
|
||||||
constructor(private fs: FileSystem) {}
|
constructor(private fs: FileSystem) {}
|
||||||
canPreload = false;
|
canPreload = false;
|
||||||
preload(): undefined|Promise<void> { throw new Error('Not implemented.'); }
|
preload(): undefined|Promise<void> {
|
||||||
load(url: string): string { return this.fs.readFile(resolve(url)); }
|
throw new Error('Not implemented.');
|
||||||
|
}
|
||||||
|
load(url: string): string {
|
||||||
|
return this.fs.readFile(resolve(url));
|
||||||
|
}
|
||||||
resolve(url: string, containingFile: string): string {
|
resolve(url: string, containingFile: string): string {
|
||||||
return resolve(dirname(absoluteFrom(containingFile)), url);
|
return resolve(dirname(absoluteFrom(containingFile)), url);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +60,7 @@ export class DecorationAnalyzer {
|
||||||
private rootDirs = this.bundle.rootDirs;
|
private rootDirs = this.bundle.rootDirs;
|
||||||
private packagePath = this.bundle.entryPoint.package;
|
private packagePath = this.bundle.entryPoint.package;
|
||||||
private isCore = this.bundle.isCore;
|
private isCore = this.bundle.isCore;
|
||||||
private compilerOptions = this.tsConfig !== null? this.tsConfig.options: {};
|
private compilerOptions = this.tsConfig !== null ? this.tsConfig.options : {};
|
||||||
|
|
||||||
moduleResolver =
|
moduleResolver =
|
||||||
new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null);
|
new ModuleResolver(this.program, this.options, this.host, /* moduleResolutionCache */ null);
|
||||||
|
@ -73,8 +77,9 @@ export class DecorationAnalyzer {
|
||||||
// based on whether a bestGuessOwningModule is present in the Reference.
|
// based on whether a bestGuessOwningModule is present in the Reference.
|
||||||
new LogicalProjectStrategy(this.reflectionHost, new LogicalFileSystem(this.rootDirs)),
|
new LogicalProjectStrategy(this.reflectionHost, new LogicalFileSystem(this.rootDirs)),
|
||||||
]);
|
]);
|
||||||
aliasingHost = this.bundle.entryPoint.generateDeepReexports?
|
aliasingHost = this.bundle.entryPoint.generateDeepReexports ?
|
||||||
new PrivateExportAliasingHost(this.reflectionHost): null;
|
new PrivateExportAliasingHost(this.reflectionHost) :
|
||||||
|
null;
|
||||||
dtsModuleScopeResolver =
|
dtsModuleScopeResolver =
|
||||||
new MetadataDtsModuleScopeResolver(this.dtsMetaReader, this.aliasingHost);
|
new MetadataDtsModuleScopeResolver(this.dtsMetaReader, this.aliasingHost);
|
||||||
scopeRegistry = new LocalModuleScopeRegistry(
|
scopeRegistry = new LocalModuleScopeRegistry(
|
||||||
|
@ -191,7 +196,9 @@ export class DecorationAnalyzer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected reportDiagnostics() { this.compiler.diagnostics.forEach(this.diagnosticHandler); }
|
protected reportDiagnostics() {
|
||||||
|
this.compiler.diagnostics.forEach(this.diagnosticHandler);
|
||||||
|
}
|
||||||
|
|
||||||
protected compileFile(sourceFile: ts.SourceFile): CompiledFile {
|
protected compileFile(sourceFile: ts.SourceFile): CompiledFile {
|
||||||
const constantPool = new ConstantPool();
|
const constantPool = new ConstantPool();
|
||||||
|
@ -211,7 +218,8 @@ export class DecorationAnalyzer {
|
||||||
compiledClasses.push({
|
compiledClasses.push({
|
||||||
name: record.node.name.text,
|
name: record.node.name.text,
|
||||||
decorators: this.compiler.getAllDecorators(record.node),
|
decorators: this.compiler.getAllDecorators(record.node),
|
||||||
declaration: record.node, compilation
|
declaration: record.node,
|
||||||
|
compilation
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +232,7 @@ export class DecorationAnalyzer {
|
||||||
if (!exportStatements.has(sf.fileName)) {
|
if (!exportStatements.has(sf.fileName)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const exports = exportStatements.get(sf.fileName) !;
|
const exports = exportStatements.get(sf.fileName)!;
|
||||||
|
|
||||||
const reexports: Reexport[] = [];
|
const reexports: Reexport[] = [];
|
||||||
exports.forEach(([fromModule, symbolName], asAlias) => {
|
exports.forEach(([fromModule, symbolName], asAlias) => {
|
||||||
|
|
|
@ -75,8 +75,7 @@ export class ModuleWithProvidersAnalyzer {
|
||||||
const dtsClass = this.host.getDtsDeclaration(containerClass.declaration.valueDeclaration);
|
const dtsClass = this.host.getDtsDeclaration(containerClass.declaration.valueDeclaration);
|
||||||
// Get the declaration of the matching static method
|
// Get the declaration of the matching static method
|
||||||
dtsFn = dtsClass && ts.isClassDeclaration(dtsClass) ?
|
dtsFn = dtsClass && ts.isClassDeclaration(dtsClass) ?
|
||||||
dtsClass.members
|
dtsClass.members.find(
|
||||||
.find(
|
|
||||||
member => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
|
member => ts.isMethodDeclaration(member) && ts.isIdentifier(member.name) &&
|
||||||
member.name.text === fn.name) as ts.Declaration :
|
member.name.text === fn.name) as ts.Declaration :
|
||||||
null;
|
null;
|
||||||
|
@ -87,8 +86,8 @@ export class ModuleWithProvidersAnalyzer {
|
||||||
throw new Error(`Matching type declaration for ${fn.declaration.getText()} is missing`);
|
throw new Error(`Matching type declaration for ${fn.declaration.getText()} is missing`);
|
||||||
}
|
}
|
||||||
if (!isFunctionOrMethod(dtsFn)) {
|
if (!isFunctionOrMethod(dtsFn)) {
|
||||||
throw new Error(
|
throw new Error(`Matching type declaration for ${
|
||||||
`Matching type declaration for ${fn.declaration.getText()} is not a function: ${dtsFn.getText()}`);
|
fn.declaration.getText()} is not a function: ${dtsFn.getText()}`);
|
||||||
}
|
}
|
||||||
return dtsFn;
|
return dtsFn;
|
||||||
}
|
}
|
||||||
|
@ -106,12 +105,14 @@ export class ModuleWithProvidersAnalyzer {
|
||||||
// to its type declaration.
|
// to its type declaration.
|
||||||
const dtsNgModule = this.host.getDtsDeclaration(ngModule.node);
|
const dtsNgModule = this.host.getDtsDeclaration(ngModule.node);
|
||||||
if (!dtsNgModule) {
|
if (!dtsNgModule) {
|
||||||
throw new Error(
|
throw new Error(`No typings declaration can be found for the referenced NgModule class in ${
|
||||||
`No typings declaration can be found for the referenced NgModule class in ${fn.declaration.getText()}.`);
|
fn.declaration.getText()}.`);
|
||||||
}
|
}
|
||||||
if (!ts.isClassDeclaration(dtsNgModule) || !hasNameIdentifier(dtsNgModule)) {
|
if (!ts.isClassDeclaration(dtsNgModule) || !hasNameIdentifier(dtsNgModule)) {
|
||||||
throw new Error(
|
throw new Error(`The referenced NgModule in ${
|
||||||
`The referenced NgModule in ${fn.declaration.getText()} is not a named class declaration in the typings program; instead we get ${dtsNgModule.getText()}`);
|
fn.declaration
|
||||||
|
.getText()} is not a named class declaration in the typings program; instead we get ${
|
||||||
|
dtsNgModule.getText()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {node: dtsNgModule, known: null, viaModule: null};
|
return {node: dtsNgModule, known: null, viaModule: null};
|
||||||
|
|
|
@ -45,5 +45,7 @@ export class NgccReferencesRegistry implements ReferencesRegistry {
|
||||||
* Create and return a mapping for the registered resolved references.
|
* Create and return a mapping for the registered resolved references.
|
||||||
* @returns A map of reference identifiers to reference declarations.
|
* @returns A map of reference identifiers to reference declarations.
|
||||||
*/
|
*/
|
||||||
getDeclarationMap(): Map<ts.Identifier, ConcreteDeclaration> { return this.map; }
|
getDeclarationMap(): Map<ts.Identifier, ConcreteDeclaration> {
|
||||||
|
return this.map;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,9 @@ export class NgccTraitCompiler extends TraitCompiler {
|
||||||
/* compileNonExportedClasses */ true, new DtsTransformRegistry());
|
/* compileNonExportedClasses */ true, new DtsTransformRegistry());
|
||||||
}
|
}
|
||||||
|
|
||||||
get analyzedFiles(): ts.SourceFile[] { return Array.from(this.fileToClasses.keys()); }
|
get analyzedFiles(): ts.SourceFile[] {
|
||||||
|
return Array.from(this.fileToClasses.keys());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyzes the source file in search for classes to process. For any class that is found in the
|
* Analyzes the source file in search for classes to process. For any class that is found in the
|
||||||
|
@ -81,5 +83,7 @@ export class NgccTraitCompiler extends TraitCompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoIncrementalBuild implements IncrementalBuild<any> {
|
class NoIncrementalBuild implements IncrementalBuild<any> {
|
||||||
priorWorkFor(sf: ts.SourceFile): any[]|null { return null; }
|
priorWorkFor(sf: ts.SourceFile): any[]|null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system';
|
import {absoluteFromSourceFile, AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||||
import {ConcreteDeclaration} from '../../../src/ngtsc/reflection';
|
import {ConcreteDeclaration} from '../../../src/ngtsc/reflection';
|
||||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||||
import {hasNameIdentifier, isDefined} from '../utils';
|
import {hasNameIdentifier, isDefined} from '../utils';
|
||||||
|
|
||||||
import {NgccReferencesRegistry} from './ngcc_references_registry';
|
import {NgccReferencesRegistry} from './ngcc_references_registry';
|
||||||
|
|
||||||
export interface ExportInfo {
|
export interface ExportInfo {
|
||||||
|
@ -48,7 +49,7 @@ export class PrivateDeclarationsAnalyzer {
|
||||||
exports.forEach((declaration, exportedName) => {
|
exports.forEach((declaration, exportedName) => {
|
||||||
if (declaration.node !== null && hasNameIdentifier(declaration.node)) {
|
if (declaration.node !== null && hasNameIdentifier(declaration.node)) {
|
||||||
if (privateDeclarations.has(declaration.node.name)) {
|
if (privateDeclarations.has(declaration.node.name)) {
|
||||||
const privateDeclaration = privateDeclarations.get(declaration.node.name) !;
|
const privateDeclaration = privateDeclarations.get(declaration.node.name)!;
|
||||||
if (privateDeclaration.node !== declaration.node) {
|
if (privateDeclaration.node !== declaration.node) {
|
||||||
throw new Error(`${declaration.node.name.text} is declared multiple times.`);
|
throw new Error(`${declaration.node.name.text} is declared multiple times.`);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +63,7 @@ export class PrivateDeclarationsAnalyzer {
|
||||||
|
|
||||||
return Array.from(privateDeclarations.keys()).map(id => {
|
return Array.from(privateDeclarations.keys()).map(id => {
|
||||||
const from = absoluteFromSourceFile(id.getSourceFile());
|
const from = absoluteFromSourceFile(id.getSourceFile());
|
||||||
const declaration = privateDeclarations.get(id) !;
|
const declaration = privateDeclarations.get(id)!;
|
||||||
const dtsDeclaration = this.host.getDtsDeclaration(declaration.node);
|
const dtsDeclaration = this.host.getDtsDeclaration(declaration.node);
|
||||||
const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile());
|
const dtsFrom = dtsDeclaration && absoluteFromSourceFile(dtsDeclaration.getSourceFile());
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFromSourceFile, relative} from '../../../src/ngtsc/file_system';
|
import {absoluteFromSourceFile, AbsoluteFsPath, relative} from '../../../src/ngtsc/file_system';
|
||||||
import {DependencyTracker} from '../../../src/ngtsc/incremental/api';
|
import {DependencyTracker} from '../../../src/ngtsc/incremental/api';
|
||||||
|
|
||||||
export function isWithinPackage(packagePath: AbsoluteFsPath, sourceFile: ts.SourceFile): boolean {
|
export function isWithinPackage(packagePath: AbsoluteFsPath, sourceFile: ts.SourceFile): boolean {
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||||
import {RequireCall, isReexportStatement, isRequireCall} from '../host/commonjs_umd_utils';
|
import {isReexportStatement, isRequireCall, RequireCall} from '../host/commonjs_umd_utils';
|
||||||
|
|
||||||
import {DependencyHostBase} from './dependency_host';
|
import {DependencyHostBase} from './dependency_host';
|
||||||
import {ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver';
|
import {ResolvedDeepImport, ResolvedRelativeModule} from './module_resolver';
|
||||||
|
|
||||||
|
@ -120,5 +122,7 @@ export class CommonJsDependencyHost extends DependencyHostBase {
|
||||||
* @returns false if there are definitely no require calls
|
* @returns false if there are definitely no require calls
|
||||||
* in this file, true otherwise.
|
* in this file, true otherwise.
|
||||||
*/
|
*/
|
||||||
private hasRequireCalls(source: string): boolean { return /require\(['"]/.test(source); }
|
private hasRequireCalls(source: string): boolean {
|
||||||
|
return /require\(['"]/.test(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {DepGraph} from 'dependency-graph';
|
import {DepGraph} from 'dependency-graph';
|
||||||
|
|
||||||
import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {NgccConfiguration} from '../packages/configuration';
|
import {NgccConfiguration} from '../packages/configuration';
|
||||||
import {EntryPoint, EntryPointFormat, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from '../packages/entry_point';
|
import {EntryPoint, EntryPointFormat, getEntryPointFormat, SUPPORTED_FORMAT_PROPERTIES} from '../packages/entry_point';
|
||||||
import {PartiallyOrderedList} from '../utils';
|
import {PartiallyOrderedList} from '../utils';
|
||||||
import {DependencyHost, DependencyInfo, createDependencyInfo} from './dependency_host';
|
|
||||||
|
import {createDependencyInfo, DependencyHost, DependencyInfo} from './dependency_host';
|
||||||
|
|
||||||
const builtinNodeJsModules = new Set<string>(require('module').builtinModules);
|
const builtinNodeJsModules = new Set<string>(require('module').builtinModules);
|
||||||
|
|
||||||
|
@ -123,7 +125,8 @@ export class DependencyResolver {
|
||||||
const host = this.hosts[formatInfo.format];
|
const host = this.hosts[formatInfo.format];
|
||||||
if (!host) {
|
if (!host) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Could not find a suitable format for computing dependencies of entry-point: '${entryPoint.path}'.`);
|
`Could not find a suitable format for computing dependencies of entry-point: '${
|
||||||
|
entryPoint.path}'.`);
|
||||||
}
|
}
|
||||||
const depInfo = createDependencyInfo();
|
const depInfo = createDependencyInfo();
|
||||||
host.collectDependencies(formatInfo.path, depInfo);
|
host.collectDependencies(formatInfo.path, depInfo);
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, dirname, isRoot, join, resolve} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem, isRoot, join, resolve} from '../../../src/ngtsc/file_system';
|
||||||
import {PathMappings, isRelativePath, resolveFileWithPostfixes} from '../utils';
|
import {isRelativePath, PathMappings, resolveFileWithPostfixes} from '../utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a very cut-down implementation of the TypeScript module resolution strategy.
|
* This is a very cut-down implementation of the TypeScript module resolution strategy.
|
||||||
|
@ -222,7 +222,7 @@ export class ModuleResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The result of resolving an import to a module. */
|
/** The result of resolving an import to a module. */
|
||||||
export type ResolvedModule = ResolvedExternalModule | ResolvedRelativeModule | ResolvedDeepImport;
|
export type ResolvedModule = ResolvedExternalModule|ResolvedRelativeModule|ResolvedDeepImport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A module that is external to the package doing the importing.
|
* A module that is external to the package doing the importing.
|
||||||
|
|
|
@ -84,5 +84,7 @@ export class UmdDependencyHost extends DependencyHostBase {
|
||||||
* @returns false if there are definitely no require calls
|
* @returns false if there are definitely no require calls
|
||||||
* in this file, true otherwise.
|
* in this file, true otherwise.
|
||||||
*/
|
*/
|
||||||
private hasRequireCalls(source: string): boolean { return /require\(['"]/.test(source); }
|
private hasRequireCalls(source: string): boolean {
|
||||||
|
return /require\(['"]/.test(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,11 @@ import {AbsoluteFsPath, FileSystem, PathSegment} from '../../../src/ngtsc/file_s
|
||||||
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {NgccConfiguration} from '../packages/configuration';
|
import {NgccConfiguration} from '../packages/configuration';
|
||||||
import {EntryPoint, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from '../packages/entry_point';
|
import {EntryPoint, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point';
|
||||||
import {EntryPointManifest} from '../packages/entry_point_manifest';
|
import {EntryPointManifest} from '../packages/entry_point_manifest';
|
||||||
import {PathMappings} from '../utils';
|
import {PathMappings} from '../utils';
|
||||||
import {NGCC_DIRECTORY} from '../writing/new_entry_point_file_writer';
|
import {NGCC_DIRECTORY} from '../writing/new_entry_point_file_writer';
|
||||||
|
|
||||||
import {EntryPointFinder} from './interface';
|
import {EntryPointFinder} from './interface';
|
||||||
import {getBasePaths, trackDuration} from './utils';
|
import {getBasePaths, trackDuration} from './utils';
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,14 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, PathSegment, join, relative, relativeFrom} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, FileSystem, join, PathSegment, relative, relativeFrom} from '../../../src/ngtsc/file_system';
|
||||||
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
import {DependencyResolver, SortedEntryPointsInfo} from '../dependencies/dependency_resolver';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {hasBeenProcessed} from '../packages/build_marker';
|
import {hasBeenProcessed} from '../packages/build_marker';
|
||||||
import {NgccConfiguration} from '../packages/configuration';
|
import {NgccConfiguration} from '../packages/configuration';
|
||||||
import {EntryPoint, EntryPointJsonProperty, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from '../packages/entry_point';
|
import {EntryPoint, EntryPointJsonProperty, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from '../packages/entry_point';
|
||||||
import {PathMappings} from '../utils';
|
import {PathMappings} from '../utils';
|
||||||
|
|
||||||
import {EntryPointFinder} from './interface';
|
import {EntryPointFinder} from './interface';
|
||||||
import {getBasePaths} from './utils';
|
import {getBasePaths} from './utils';
|
||||||
|
|
||||||
|
@ -76,7 +77,7 @@ export class TargetedEntryPointFinder implements EntryPointFinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private processNextPath(): void {
|
private processNextPath(): void {
|
||||||
const path = this.unprocessedPaths.shift() !;
|
const path = this.unprocessedPaths.shift()!;
|
||||||
const entryPoint = this.getEntryPoint(path);
|
const entryPoint = this.getEntryPoint(path);
|
||||||
if (entryPoint === null || !entryPoint.compiledByAngular) {
|
if (entryPoint === null || !entryPoint.compiledByAngular) {
|
||||||
return;
|
return;
|
||||||
|
@ -130,7 +131,7 @@ export class TargetedEntryPointFinder implements EntryPointFinder {
|
||||||
// Start the search at the deepest nested `node_modules` folder that is below the `basePath`
|
// Start the search at the deepest nested `node_modules` folder that is below the `basePath`
|
||||||
// but above the `entryPointPath`, if there are any.
|
// but above the `entryPointPath`, if there are any.
|
||||||
while (nodeModulesIndex >= 0) {
|
while (nodeModulesIndex >= 0) {
|
||||||
packagePath = join(packagePath, segments.shift() !);
|
packagePath = join(packagePath, segments.shift()!);
|
||||||
nodeModulesIndex--;
|
nodeModulesIndex--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import {PathMappings} from '../utils';
|
||||||
*/
|
*/
|
||||||
export function getBasePaths(
|
export function getBasePaths(
|
||||||
logger: Logger, sourceDirectory: AbsoluteFsPath,
|
logger: Logger, sourceDirectory: AbsoluteFsPath,
|
||||||
pathMappings: PathMappings | undefined): AbsoluteFsPath[] {
|
pathMappings: PathMappings|undefined): AbsoluteFsPath[] {
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const basePaths = [sourceDirectory];
|
const basePaths = [sourceDirectory];
|
||||||
if (pathMappings) {
|
if (pathMappings) {
|
||||||
|
@ -51,7 +51,8 @@ export function getBasePaths(
|
||||||
basePaths.push(basePath);
|
basePaths.push(basePath);
|
||||||
} else {
|
} else {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${path}" does not exist in the file-system.\n` +
|
`The basePath "${basePath}" computed from baseUrl "${baseUrl}" and path mapping "${
|
||||||
|
path}" does not exist in the file-system.\n` +
|
||||||
`It will not be scanned for entry-points.`);
|
`It will not be scanned for entry-points.`);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -109,8 +110,8 @@ function removeContainedPaths(value: AbsoluteFsPath, index: number, array: Absol
|
||||||
* @param log The function to call with the duration of the task
|
* @param log The function to call with the duration of the task
|
||||||
* @returns The result of calling `task`.
|
* @returns The result of calling `task`.
|
||||||
*/
|
*/
|
||||||
export function trackDuration<T = void>(
|
export function trackDuration<T = void>(task: () => T extends Promise<unknown>? never : T,
|
||||||
task: () => T extends Promise<unknown>? never : T, log: (duration: number) => void): T {
|
log: (duration: number) => void): T {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const result = task();
|
const result = task();
|
||||||
const duration = Math.round((Date.now() - startTime) / 100) / 10;
|
const duration = Math.round((Date.now() - startTime) / 100) / 10;
|
||||||
|
|
|
@ -44,7 +44,7 @@ export interface UpdatePackageJsonMessage extends JsonObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The type of messages sent from cluster workers to the cluster master. */
|
/** The type of messages sent from cluster workers to the cluster master. */
|
||||||
export type MessageFromWorker = ErrorMessage | TaskCompletedMessage | UpdatePackageJsonMessage;
|
export type MessageFromWorker = ErrorMessage|TaskCompletedMessage|UpdatePackageJsonMessage;
|
||||||
|
|
||||||
/** The type of messages sent from the cluster master to cluster workers. */
|
/** The type of messages sent from the cluster master to cluster workers. */
|
||||||
export type MessageToWorker = ProcessTaskMessage;
|
export type MessageToWorker = ProcessTaskMessage;
|
||||||
|
|
|
@ -35,8 +35,8 @@ export class ClusterExecutor implements Executor {
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
// This process is the cluster master.
|
// This process is the cluster master.
|
||||||
return this.lockFile.lock(() => {
|
return this.lockFile.lock(() => {
|
||||||
this.logger.debug(
|
this.logger.debug(`Running ngcc on ${this.constructor.name} (using ${
|
||||||
`Running ngcc on ${this.constructor.name} (using ${this.workerCount} worker processes).`);
|
this.workerCount} worker processes).`);
|
||||||
const master = new ClusterMaster(
|
const master = new ClusterMaster(
|
||||||
this.workerCount, this.logger, this.pkgJsonUpdater, analyzeEntryPoints,
|
this.workerCount, this.logger, this.pkgJsonUpdater, analyzeEntryPoints,
|
||||||
this.createTaskCompletedCallback);
|
this.createTaskCompletedCallback);
|
||||||
|
|
|
@ -262,7 +262,7 @@ export class ClusterMaster {
|
||||||
*/
|
*/
|
||||||
private wrapEventHandler<Args extends unknown[]>(fn: (...args: Args) => void|Promise<void>):
|
private wrapEventHandler<Args extends unknown[]>(fn: (...args: Args) => void|Promise<void>):
|
||||||
(...args: Args) => Promise<void> {
|
(...args: Args) => Promise<void> {
|
||||||
return async(...args: Args) => {
|
return async (...args: Args) => {
|
||||||
try {
|
try {
|
||||||
await fn(...args);
|
await fn(...args);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as cluster from 'cluster';
|
||||||
|
|
||||||
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
|
||||||
import {JsonObject} from '../../packages/entry_point';
|
import {JsonObject} from '../../packages/entry_point';
|
||||||
import {PackageJsonChange, PackageJsonUpdate, PackageJsonUpdater, applyChange} from '../../writing/package_json_updater';
|
import {applyChange, PackageJsonChange, PackageJsonUpdate, PackageJsonUpdater} from '../../writing/package_json_updater';
|
||||||
|
|
||||||
import {sendMessageToMaster} from './utils';
|
import {sendMessageToMaster} from './utils';
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,14 @@ export class Deferred<T> {
|
||||||
*
|
*
|
||||||
* @param value The value to resolve the promise with.
|
* @param value The value to resolve the promise with.
|
||||||
*/
|
*/
|
||||||
resolve !: (value: T) => void;
|
resolve!: (value: T) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rejects the associated promise with the specified reason.
|
* Rejects the associated promise with the specified reason.
|
||||||
*
|
*
|
||||||
* @param reason The rejection reason.
|
* @param reason The rejection reason.
|
||||||
*/
|
*/
|
||||||
reject !: (reason: any) => void;
|
reject!: (reason: any) => void;
|
||||||
|
|
||||||
/** The `Promise` instance associated with this deferred. */
|
/** The `Promise` instance associated with this deferred. */
|
||||||
promise = new Promise<T>((resolve, reject) => {
|
promise = new Promise<T>((resolve, reject) => {
|
||||||
|
|
|
@ -30,7 +30,7 @@ export abstract class SingleProcessorExecutorBase {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
while (!taskQueue.allTasksCompleted) {
|
while (!taskQueue.allTasksCompleted) {
|
||||||
const task = taskQueue.getNextTask() !;
|
const task = taskQueue.getNextTask()!;
|
||||||
compile(task);
|
compile(task);
|
||||||
taskQueue.markTaskCompleted(task);
|
taskQueue.markTaskCompleted(task);
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,6 @@ export class SingleProcessExecutorAsync extends SingleProcessorExecutorBase impl
|
||||||
}
|
}
|
||||||
async execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn):
|
async execute(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn):
|
||||||
Promise<void> {
|
Promise<void> {
|
||||||
await this.lockFile.lock(async() => this.doExecute(analyzeEntryPoints, createCompileFn));
|
await this.lockFile.lock(async () => this.doExecute(analyzeEntryPoints, createCompileFn));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ export type CreateTaskCompletedCallback = (taskQueue: TaskQueue) => TaskComplete
|
||||||
* A function to be called once a task has been processed.
|
* A function to be called once a task has been processed.
|
||||||
*/
|
*/
|
||||||
export type TaskCompletedCallback =
|
export type TaskCompletedCallback =
|
||||||
(task: Task, outcome: TaskProcessingOutcome, message: string | null) => void;
|
(task: Task, outcome: TaskProcessingOutcome, message: string|null) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the outcome of processing a `Task`.
|
* Represents the outcome of processing a `Task`.
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
import {FileSystem, resolve} from '../../../../src/ngtsc/file_system';
|
import {FileSystem, resolve} from '../../../../src/ngtsc/file_system';
|
||||||
import {Logger} from '../../logging/logger';
|
import {Logger} from '../../logging/logger';
|
||||||
import {markAsProcessed} from '../../packages/build_marker';
|
import {markAsProcessed} from '../../packages/build_marker';
|
||||||
import {PackageJsonFormatProperties, getEntryPointFormat} from '../../packages/entry_point';
|
import {getEntryPointFormat, PackageJsonFormatProperties} from '../../packages/entry_point';
|
||||||
import {PackageJsonUpdater} from '../../writing/package_json_updater';
|
import {PackageJsonUpdater} from '../../writing/package_json_updater';
|
||||||
|
|
||||||
import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './api';
|
import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './api';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,7 +19,7 @@ import {Task, TaskCompletedCallback, TaskProcessingOutcome, TaskQueue} from './a
|
||||||
* These functions can be composed using the `composeTaskCompletedCallbacks()`
|
* These functions can be composed using the `composeTaskCompletedCallbacks()`
|
||||||
* to create a `TaskCompletedCallback` function that can be passed to an `Executor`.
|
* to create a `TaskCompletedCallback` function that can be passed to an `Executor`.
|
||||||
*/
|
*/
|
||||||
export type TaskCompletedHandler = (task: Task, message: string | null) => void;
|
export type TaskCompletedHandler = (task: Task, message: string|null) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compose a group of TaskCompletedHandlers into a single TaskCompletedCallback.
|
* Compose a group of TaskCompletedHandlers into a single TaskCompletedCallback.
|
||||||
|
@ -30,11 +31,11 @@ export type TaskCompletedHandler = (task: Task, message: string | null) => void;
|
||||||
*/
|
*/
|
||||||
export function composeTaskCompletedCallbacks(
|
export function composeTaskCompletedCallbacks(
|
||||||
callbacks: Record<TaskProcessingOutcome, TaskCompletedHandler>): TaskCompletedCallback {
|
callbacks: Record<TaskProcessingOutcome, TaskCompletedHandler>): TaskCompletedCallback {
|
||||||
return (task: Task, outcome: TaskProcessingOutcome, message: string | null): void => {
|
return (task: Task, outcome: TaskProcessingOutcome, message: string|null): void => {
|
||||||
const callback = callbacks[outcome];
|
const callback = callbacks[outcome];
|
||||||
if (callback === undefined) {
|
if (callback === undefined) {
|
||||||
throw new Error(
|
throw new Error(`Unknown task outcome: "${outcome}" - supported outcomes: ${
|
||||||
`Unknown task outcome: "${outcome}" - supported outcomes: ${JSON.stringify(Object.keys(callbacks))}`);
|
JSON.stringify(Object.keys(callbacks))}`);
|
||||||
}
|
}
|
||||||
callback(task, message);
|
callback(task, message);
|
||||||
};
|
};
|
||||||
|
@ -64,10 +65,11 @@ export function createMarkAsProcessedHandler(pkgJsonUpdater: PackageJsonUpdater)
|
||||||
* Create a handler that will throw an error.
|
* Create a handler that will throw an error.
|
||||||
*/
|
*/
|
||||||
export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler {
|
export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler {
|
||||||
return (task: Task, message: string | null): void => {
|
return (task: Task, message: string|null): void => {
|
||||||
const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty);
|
const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty);
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${format})` +
|
`Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${
|
||||||
|
format})` +
|
||||||
(message !== null ? ` due to ${message}` : ''));
|
(message !== null ? ` due to ${message}` : ''));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -77,11 +79,12 @@ export function createThrowErrorHandler(fs: FileSystem): TaskCompletedHandler {
|
||||||
*/
|
*/
|
||||||
export function createLogErrorHandler(
|
export function createLogErrorHandler(
|
||||||
logger: Logger, fs: FileSystem, taskQueue: TaskQueue): TaskCompletedHandler {
|
logger: Logger, fs: FileSystem, taskQueue: TaskQueue): TaskCompletedHandler {
|
||||||
return (task: Task, message: string | null): void => {
|
return (task: Task, message: string|null): void => {
|
||||||
taskQueue.markAsFailed(task);
|
taskQueue.markAsFailed(task);
|
||||||
const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty);
|
const format = getEntryPointFormat(fs, task.entryPoint, task.formatProperty);
|
||||||
logger.error(
|
logger.error(
|
||||||
`Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${format})` +
|
`Failed to compile entry-point ${task.entryPoint.name} (${task.formatProperty} as ${
|
||||||
|
format})` +
|
||||||
(message !== null ? ` due to ${message}` : ''));
|
(message !== null ? ` due to ${message}` : ''));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,9 +38,9 @@ export abstract class BaseTaskQueue implements TaskQueue {
|
||||||
}
|
}
|
||||||
// We are skipping this task so mark it as complete
|
// We are skipping this task so mark it as complete
|
||||||
this.markTaskCompleted(nextTask);
|
this.markTaskCompleted(nextTask);
|
||||||
const failedTask = this.tasksToSkip.get(nextTask) !;
|
const failedTask = this.tasksToSkip.get(nextTask)!;
|
||||||
this.logger.warn(
|
this.logger.warn(`Skipping processing of ${nextTask.entryPoint.name} because its dependency ${
|
||||||
`Skipping processing of ${nextTask.entryPoint.name} because its dependency ${failedTask.entryPoint.name} failed to compile.`);
|
failedTask.entryPoint.name} failed to compile.`);
|
||||||
nextTask = this.computeNextTask();
|
nextTask = this.computeNextTask();
|
||||||
}
|
}
|
||||||
return nextTask;
|
return nextTask;
|
||||||
|
@ -48,7 +48,7 @@ export abstract class BaseTaskQueue implements TaskQueue {
|
||||||
|
|
||||||
markAsFailed(task: Task) {
|
markAsFailed(task: Task) {
|
||||||
if (this.dependencies.has(task)) {
|
if (this.dependencies.has(task)) {
|
||||||
for (const dependentTask of this.dependencies.get(task) !) {
|
for (const dependentTask of this.dependencies.get(task)!) {
|
||||||
this.skipDependentTasks(dependentTask, task);
|
this.skipDependentTasks(dependentTask, task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ export abstract class BaseTaskQueue implements TaskQueue {
|
||||||
protected skipDependentTasks(task: Task, failedTask: Task) {
|
protected skipDependentTasks(task: Task, failedTask: Task) {
|
||||||
this.tasksToSkip.set(task, failedTask);
|
this.tasksToSkip.set(task, failedTask);
|
||||||
if (this.dependencies.has(task)) {
|
if (this.dependencies.has(task)) {
|
||||||
for (const dependentTask of this.dependencies.get(task) !) {
|
for (const dependentTask of this.dependencies.get(task)!) {
|
||||||
this.skipDependentTasks(dependentTask, failedTask);
|
this.skipDependentTasks(dependentTask, failedTask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ export class ParallelTaskQueue extends BaseTaskQueue {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unblock the tasks that are dependent upon `task`
|
// Unblock the tasks that are dependent upon `task`
|
||||||
for (const dependentTask of this.dependencies.get(task) !) {
|
for (const dependentTask of this.dependencies.get(task)!) {
|
||||||
if (this.blockedTasks.has(dependentTask)) {
|
if (this.blockedTasks.has(dependentTask)) {
|
||||||
const blockingTasks = this.blockedTasks.get(dependentTask) !;
|
const blockingTasks = this.blockedTasks.get(dependentTask)!;
|
||||||
// Remove the completed task from the lists of tasks blocking other tasks.
|
// Remove the completed task from the lists of tasks blocking other tasks.
|
||||||
blockingTasks.delete(task);
|
blockingTasks.delete(task);
|
||||||
if (blockingTasks.size === 0) {
|
if (blockingTasks.size === 0) {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import {EntryPoint} from '../../packages/entry_point';
|
||||||
import {PartiallyOrderedTasks, Task, TaskDependencies} from './api';
|
import {PartiallyOrderedTasks, Task, TaskDependencies} from './api';
|
||||||
|
|
||||||
/** Stringify a task for debugging purposes. */
|
/** Stringify a task for debugging purposes. */
|
||||||
export const stringifyTask = (task: Task): string =>
|
export const stringifyTask = (task: Task): string => `{entryPoint: ${
|
||||||
`{entryPoint: ${task.entryPoint.name}, formatProperty: ${task.formatProperty}, processDts: ${task.processDts}}`;
|
task.entryPoint.name}, formatProperty: ${task.formatProperty}, processDts: ${task.processDts}}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute a mapping of tasks to the tasks that are dependent on them (if any).
|
* Compute a mapping of tasks to the tasks that are dependent on them (if any).
|
||||||
|
@ -45,7 +45,7 @@ export function computeTaskDependencies(
|
||||||
// Find the earlier tasks (`candidateDependencies`) that this task depends upon.
|
// Find the earlier tasks (`candidateDependencies`) that this task depends upon.
|
||||||
const deps = graph.dependenciesOf(entryPointPath);
|
const deps = graph.dependenciesOf(entryPointPath);
|
||||||
const taskDependencies = deps.filter(dep => candidateDependencies.has(dep))
|
const taskDependencies = deps.filter(dep => candidateDependencies.has(dep))
|
||||||
.map(dep => candidateDependencies.get(dep) !);
|
.map(dep => candidateDependencies.get(dep)!);
|
||||||
|
|
||||||
// If this task has dependencies, add it to the dependencies and dependents maps.
|
// If this task has dependencies, add it to the dependencies and dependents maps.
|
||||||
if (taskDependencies.length > 0) {
|
if (taskDependencies.length > 0) {
|
||||||
|
@ -61,7 +61,7 @@ export function computeTaskDependencies(
|
||||||
// dependency of other tasks), so the following should theoretically never happen, but check
|
// dependency of other tasks), so the following should theoretically never happen, but check
|
||||||
// just in case.
|
// just in case.
|
||||||
if (candidateDependencies.has(entryPointPath)) {
|
if (candidateDependencies.has(entryPointPath)) {
|
||||||
const otherTask = candidateDependencies.get(entryPointPath) !;
|
const otherTask = candidateDependencies.get(entryPointPath)!;
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Invariant violated: Multiple tasks are assigned generating typings for ' +
|
'Invariant violated: Multiple tasks are assigned generating typings for ' +
|
||||||
`'${entryPointPath}':\n - ${stringifyTask(otherTask)}\n - ${stringifyTask(task)}`);
|
`'${entryPointPath}':\n - ${stringifyTask(otherTask)}\n - ${stringifyTask(task)}`);
|
||||||
|
@ -73,7 +73,7 @@ export function computeTaskDependencies(
|
||||||
// This task is not generating typings so we need to add it to the dependents of the task that
|
// This task is not generating typings so we need to add it to the dependents of the task that
|
||||||
// does generate typings, if that exists
|
// does generate typings, if that exists
|
||||||
if (candidateDependencies.has(entryPointPath)) {
|
if (candidateDependencies.has(entryPointPath)) {
|
||||||
const typingsTask = candidateDependencies.get(entryPointPath) !;
|
const typingsTask = candidateDependencies.get(entryPointPath)!;
|
||||||
const typingsTaskDependents = getDependentsSet(dependencies, typingsTask);
|
const typingsTaskDependents = getDependentsSet(dependencies, typingsTask);
|
||||||
typingsTaskDependents.add(task);
|
typingsTaskDependents.add(task);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ export function getDependentsSet(map: TaskDependencies, task: Task): Set<Task> {
|
||||||
if (!map.has(task)) {
|
if (!map.has(task)) {
|
||||||
map.set(task, new Set());
|
map.set(task, new Set());
|
||||||
}
|
}
|
||||||
return map.get(task) !;
|
return map.get(task)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,13 +125,13 @@ export function sortTasksByPriority(
|
||||||
tasks: PartiallyOrderedTasks, dependencies: TaskDependencies): PartiallyOrderedTasks {
|
tasks: PartiallyOrderedTasks, dependencies: TaskDependencies): PartiallyOrderedTasks {
|
||||||
const priorityPerTask = new Map<Task, [number, number]>();
|
const priorityPerTask = new Map<Task, [number, number]>();
|
||||||
const computePriority = (task: Task, idx: number):
|
const computePriority = (task: Task, idx: number):
|
||||||
[number, number] => [dependencies.has(task) ? dependencies.get(task) !.size : 0, idx];
|
[number, number] => [dependencies.has(task) ? dependencies.get(task)!.size : 0, idx];
|
||||||
|
|
||||||
tasks.forEach((task, i) => priorityPerTask.set(task, computePriority(task, i)));
|
tasks.forEach((task, i) => priorityPerTask.set(task, computePriority(task, i)));
|
||||||
|
|
||||||
return tasks.slice().sort((task1, task2) => {
|
return tasks.slice().sort((task1, task2) => {
|
||||||
const [p1, idx1] = priorityPerTask.get(task1) !;
|
const [p1, idx1] = priorityPerTask.get(task1)!;
|
||||||
const [p2, idx2] = priorityPerTask.get(task2) !;
|
const [p2, idx2] = priorityPerTask.get(task2)!;
|
||||||
|
|
||||||
return (p2 - p1) || (idx1 - idx2);
|
return (p2 - p1) || (idx1 - idx2);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||||
import {Declaration, Import} from '../../../src/ngtsc/reflection';
|
import {Declaration, Import} from '../../../src/ngtsc/reflection';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {BundleProgram} from '../packages/bundle_program';
|
import {BundleProgram} from '../packages/bundle_program';
|
||||||
import {FactoryMap, getTsHelperFnFromIdentifier, isDefined, stripExtension} from '../utils';
|
import {FactoryMap, getTsHelperFnFromIdentifier, isDefined, stripExtension} from '../utils';
|
||||||
|
|
||||||
import {ExportDeclaration, ExportStatement, ReexportStatement, RequireCall, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall} from './commonjs_umd_utils';
|
import {ExportDeclaration, ExportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall, ReexportStatement, RequireCall} from './commonjs_umd_utils';
|
||||||
import {Esm5ReflectionHost} from './esm5_host';
|
import {Esm5ReflectionHost} from './esm5_host';
|
||||||
import {NgccClassSymbol} from './ngcc_host';
|
import {NgccClassSymbol} from './ngcc_host';
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,12 @@ export interface ExportDeclaration {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExportStatement extends ts.ExpressionStatement {
|
export interface ExportStatement extends ts.ExpressionStatement {
|
||||||
expression: ts.BinaryExpression&{left: ts.PropertyAccessExpression & {expression: ts.Identifier}};
|
expression: ts.BinaryExpression&{
|
||||||
|
left: ts.PropertyAccessExpression &
|
||||||
|
{
|
||||||
|
expression: ts.Identifier
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +39,9 @@ export interface ExportStatement extends ts.ExpressionStatement {
|
||||||
* expression and can be either a `require('...')` call or an identifier (initialized via a
|
* expression and can be either a `require('...')` call or an identifier (initialized via a
|
||||||
* `require('...')` call).
|
* `require('...')` call).
|
||||||
*/
|
*/
|
||||||
export interface ReexportStatement extends ts.ExpressionStatement { expression: ts.CallExpression; }
|
export interface ReexportStatement extends ts.ExpressionStatement {
|
||||||
|
expression: ts.CallExpression;
|
||||||
|
}
|
||||||
|
|
||||||
export interface RequireCall extends ts.CallExpression {
|
export interface RequireCall extends ts.CallExpression {
|
||||||
arguments: ts.CallExpression['arguments']&[ts.StringLiteral];
|
arguments: ts.CallExpression['arguments']&[ts.StringLiteral];
|
||||||
|
|
|
@ -13,7 +13,8 @@ import {Declaration, Import} from '../../../src/ngtsc/reflection';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {BundleProgram} from '../packages/bundle_program';
|
import {BundleProgram} from '../packages/bundle_program';
|
||||||
import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils';
|
import {FactoryMap, getTsHelperFnFromIdentifier, stripExtension} from '../utils';
|
||||||
import {ExportDeclaration, ExportStatement, ReexportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall} from './commonjs_umd_utils';
|
|
||||||
|
import {ExportDeclaration, ExportStatement, findNamespaceOfIdentifier, findRequireCallReference, isExportStatement, isReexportStatement, isRequireCall, ReexportStatement} from './commonjs_umd_utils';
|
||||||
import {Esm5ReflectionHost, stripParentheses} from './esm5_host';
|
import {Esm5ReflectionHost, stripParentheses} from './esm5_host';
|
||||||
|
|
||||||
export class UmdReflectionHost extends Esm5ReflectionHost {
|
export class UmdReflectionHost extends Esm5ReflectionHost {
|
||||||
|
@ -61,7 +62,8 @@ export class UmdReflectionHost extends Esm5ReflectionHost {
|
||||||
return this.umdImportPaths.get(importParameter);
|
return this.umdImportPaths.get(importParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the top level statements for a module.
|
/**
|
||||||
|
* Get the top level statements for a module.
|
||||||
*
|
*
|
||||||
* In UMD modules these are the body of the UMD factory function.
|
* In UMD modules these are the body of the UMD factory function.
|
||||||
*
|
*
|
||||||
|
|
|
@ -52,7 +52,7 @@ export class AsyncLocker {
|
||||||
if (attempts === 0) {
|
if (attempts === 0) {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`Another process, with id ${pid}, is currently running ngcc.\n` +
|
`Another process, with id ${pid}, is currently running ngcc.\n` +
|
||||||
`Waiting up to ${this.retryDelay*this.retryAttempts/1000}s for it to finish.`);
|
`Waiting up to ${this.retryDelay * this.retryAttempts / 1000}s for it to finish.`);
|
||||||
}
|
}
|
||||||
// The file is still locked by another process so wait for a bit and retry
|
// The file is still locked by another process so wait for a bit and retry
|
||||||
await new Promise(resolve => setTimeout(resolve, this.retryDelay));
|
await new Promise(resolve => setTimeout(resolve, this.retryDelay));
|
||||||
|
@ -60,7 +60,10 @@ export class AsyncLocker {
|
||||||
}
|
}
|
||||||
// If we fall out of the loop then we ran out of rety attempts
|
// If we fall out of the loop then we ran out of rety attempts
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Timed out waiting ${this.retryAttempts * this.retryDelay/1000}s for another ngcc process, with id ${pid}, to complete.\n` +
|
`Timed out waiting ${
|
||||||
`(If you are sure no ngcc process is running then you should delete the lock-file at ${this.lockFile.path}.)`);
|
this.retryAttempts * this.retryDelay /
|
||||||
|
1000}s for another ngcc process, with id ${pid}, to complete.\n` +
|
||||||
|
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
|
||||||
|
this.lockFile.path}.)`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
import {ChildProcess, fork} from 'child_process';
|
import {ChildProcess, fork} from 'child_process';
|
||||||
|
|
||||||
import {AbsoluteFsPath, CachedFileSystem, FileSystem} from '../../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, CachedFileSystem, FileSystem} from '../../../../src/ngtsc/file_system';
|
||||||
import {LogLevel, Logger} from '../../logging/logger';
|
import {Logger, LogLevel} from '../../logging/logger';
|
||||||
import {LockFile, getLockFilePath} from '../lock_file';
|
import {getLockFilePath, LockFile} from '../lock_file';
|
||||||
|
|
||||||
import {removeLockFile} from './util';
|
import {removeLockFile} from './util';
|
||||||
|
|
||||||
|
|
|
@ -20,14 +20,14 @@ const fs = new NodeJSFileSystem();
|
||||||
|
|
||||||
// We create a logger that has the same logging level as the parent process, since it should have
|
// We create a logger that has the same logging level as the parent process, since it should have
|
||||||
// been passed through as one of the args
|
// been passed through as one of the args
|
||||||
const logLevel = parseInt(process.argv.pop() !, 10);
|
const logLevel = parseInt(process.argv.pop()!, 10);
|
||||||
const logger = new ConsoleLogger(logLevel);
|
const logger = new ConsoleLogger(logLevel);
|
||||||
|
|
||||||
// We must store the parent PID now as it changes if the parent process is killed early
|
// We must store the parent PID now as it changes if the parent process is killed early
|
||||||
const ppid = process.ppid.toString();
|
const ppid = process.ppid.toString();
|
||||||
|
|
||||||
// The path to the lock-file to remove should have been passed as one of the args
|
// The path to the lock-file to remove should have been passed as one of the args
|
||||||
const lockFilePath = fs.resolve(process.argv.pop() !);
|
const lockFilePath = fs.resolve(process.argv.pop()!);
|
||||||
|
|
||||||
logger.debug(`Starting unlocker at process ${process.pid} on behalf of process ${ppid}`);
|
logger.debug(`Starting unlocker at process ${process.pid} on behalf of process ${ppid}`);
|
||||||
logger.debug(`The lock-file path is ${lockFilePath}`);
|
logger.debug(`The lock-file path is ${lockFilePath}`);
|
||||||
|
@ -36,4 +36,6 @@ logger.debug(`The lock-file path is ${lockFilePath}`);
|
||||||
* When the parent process exits (for whatever reason) remove the loc-file if it exists and as long
|
* When the parent process exits (for whatever reason) remove the loc-file if it exists and as long
|
||||||
* as it was one that was created by the parent process.
|
* as it was one that was created by the parent process.
|
||||||
*/
|
*/
|
||||||
process.on('disconnect', () => { removeLockFile(fs, logger, lockFilePath, ppid); });
|
process.on('disconnect', () => {
|
||||||
|
removeLockFile(fs, logger, lockFilePath, ppid);
|
||||||
|
});
|
||||||
|
|
|
@ -57,6 +57,7 @@ export class SyncLocker {
|
||||||
`ngcc is already running at process with id ${pid}.\n` +
|
`ngcc is already running at process with id ${pid}.\n` +
|
||||||
`If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` +
|
`If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` +
|
||||||
`See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` +
|
`See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` +
|
||||||
`(If you are sure no ngcc process is running then you should delete the lock-file at ${this.lockFile.path}.)`);
|
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
|
||||||
|
this.lockFile.path}.)`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {LogLevel, Logger} from './logger';
|
import {Logger, LogLevel} from './logger';
|
||||||
|
|
||||||
const RESET = '\x1b[0m';
|
const RESET = '\x1b[0m';
|
||||||
const RED = '\x1b[31m';
|
const RED = '\x1b[31m';
|
||||||
|
|
|
@ -14,7 +14,7 @@ import * as ts from 'typescript';
|
||||||
|
|
||||||
import {readConfiguration} from '../..';
|
import {readConfiguration} from '../..';
|
||||||
import {replaceTsWithNgInErrors} from '../../src/ngtsc/diagnostics';
|
import {replaceTsWithNgInErrors} from '../../src/ngtsc/diagnostics';
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, dirname, getFileSystem, resolve} from '../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, dirname, FileSystem, getFileSystem, resolve} from '../../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host';
|
import {CommonJsDependencyHost} from './dependencies/commonjs_dependency_host';
|
||||||
import {DependencyResolver, InvalidEntryPoint} from './dependencies/dependency_resolver';
|
import {DependencyResolver, InvalidEntryPoint} from './dependencies/dependency_resolver';
|
||||||
|
@ -38,10 +38,10 @@ import {AsyncLocker} from './locking/async_locker';
|
||||||
import {LockFileWithChildProcess} from './locking/lock_file_with_child_process';
|
import {LockFileWithChildProcess} from './locking/lock_file_with_child_process';
|
||||||
import {SyncLocker} from './locking/sync_locker';
|
import {SyncLocker} from './locking/sync_locker';
|
||||||
import {ConsoleLogger} from './logging/console_logger';
|
import {ConsoleLogger} from './logging/console_logger';
|
||||||
import {LogLevel, Logger} from './logging/logger';
|
import {Logger, LogLevel} from './logging/logger';
|
||||||
import {hasBeenProcessed} from './packages/build_marker';
|
import {hasBeenProcessed} from './packages/build_marker';
|
||||||
import {NgccConfiguration} from './packages/configuration';
|
import {NgccConfiguration} from './packages/configuration';
|
||||||
import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
|
import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, getEntryPointFormat, SUPPORTED_FORMAT_PROPERTIES} from './packages/entry_point';
|
||||||
import {makeEntryPointBundle} from './packages/entry_point_bundle';
|
import {makeEntryPointBundle} from './packages/entry_point_bundle';
|
||||||
import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest';
|
import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest';
|
||||||
import {Transformer} from './packages/transformer';
|
import {Transformer} from './packages/transformer';
|
||||||
|
@ -164,12 +164,12 @@ export interface SyncNgccOptions {
|
||||||
/**
|
/**
|
||||||
* The options to configure the ngcc compiler for asynchronous execution.
|
* The options to configure the ngcc compiler for asynchronous execution.
|
||||||
*/
|
*/
|
||||||
export type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'>& {async: true};
|
export type AsyncNgccOptions = Omit<SyncNgccOptions, 'async'>&{async: true};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The options to configure the ngcc compiler.
|
* The options to configure the ngcc compiler.
|
||||||
*/
|
*/
|
||||||
export type NgccOptions = AsyncNgccOptions | SyncNgccOptions;
|
export type NgccOptions = AsyncNgccOptions|SyncNgccOptions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main entry-point into ngcc (aNGular Compatibility Compiler).
|
* This is the main entry-point into ngcc (aNGular Compatibility Compiler).
|
||||||
|
@ -181,12 +181,20 @@ export type NgccOptions = AsyncNgccOptions | SyncNgccOptions;
|
||||||
*/
|
*/
|
||||||
export function mainNgcc(options: AsyncNgccOptions): Promise<void>;
|
export function mainNgcc(options: AsyncNgccOptions): Promise<void>;
|
||||||
export function mainNgcc(options: SyncNgccOptions): void;
|
export function mainNgcc(options: SyncNgccOptions): void;
|
||||||
export function mainNgcc(
|
export function mainNgcc({
|
||||||
{basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
basePath,
|
||||||
compileAllFormats = true, createNewEntryPointFormats = false,
|
targetEntryPointPath,
|
||||||
logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false,
|
propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
||||||
errorOnFailedEntryPoint = false, enableI18nLegacyMessageIdFormat = true,
|
compileAllFormats = true,
|
||||||
invalidateEntryPointManifest = false, tsConfigPath}: NgccOptions): void|Promise<void> {
|
createNewEntryPointFormats = false,
|
||||||
|
logger = new ConsoleLogger(LogLevel.info),
|
||||||
|
pathMappings,
|
||||||
|
async = false,
|
||||||
|
errorOnFailedEntryPoint = false,
|
||||||
|
enableI18nLegacyMessageIdFormat = true,
|
||||||
|
invalidateEntryPointManifest = false,
|
||||||
|
tsConfigPath
|
||||||
|
}: NgccOptions): void|Promise<void> {
|
||||||
if (!!targetEntryPointPath) {
|
if (!!targetEntryPointPath) {
|
||||||
// targetEntryPointPath forces us to error if an entry-point fails.
|
// targetEntryPointPath forces us to error if an entry-point fails.
|
||||||
errorOnFailedEntryPoint = true;
|
errorOnFailedEntryPoint = true;
|
||||||
|
@ -279,7 +287,7 @@ export function mainNgcc(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty) !;
|
const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty)!;
|
||||||
tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts});
|
tasks.push({entryPoint, formatProperty, formatPropertiesToMarkAsProcessed, processDts});
|
||||||
|
|
||||||
// Only process typings for the first property (if not already processed).
|
// Only process typings for the first property (if not already processed).
|
||||||
|
@ -442,7 +450,7 @@ function getExecutor(
|
||||||
|
|
||||||
function getDependencyResolver(
|
function getDependencyResolver(
|
||||||
fileSystem: FileSystem, logger: Logger, config: NgccConfiguration,
|
fileSystem: FileSystem, logger: Logger, config: NgccConfiguration,
|
||||||
pathMappings: PathMappings | undefined): DependencyResolver {
|
pathMappings: PathMappings|undefined): DependencyResolver {
|
||||||
const moduleResolver = new ModuleResolver(fileSystem, pathMappings);
|
const moduleResolver = new ModuleResolver(fileSystem, pathMappings);
|
||||||
const esmDependencyHost = new EsmDependencyHost(fileSystem, moduleResolver);
|
const esmDependencyHost = new EsmDependencyHost(fileSystem, moduleResolver);
|
||||||
const umdDependencyHost = new UmdDependencyHost(fileSystem, moduleResolver);
|
const umdDependencyHost = new UmdDependencyHost(fileSystem, moduleResolver);
|
||||||
|
@ -461,8 +469,8 @@ function getDependencyResolver(
|
||||||
function getEntryPointFinder(
|
function getEntryPointFinder(
|
||||||
fs: FileSystem, logger: Logger, resolver: DependencyResolver, config: NgccConfiguration,
|
fs: FileSystem, logger: Logger, resolver: DependencyResolver, config: NgccConfiguration,
|
||||||
entryPointManifest: EntryPointManifest, basePath: AbsoluteFsPath,
|
entryPointManifest: EntryPointManifest, basePath: AbsoluteFsPath,
|
||||||
absoluteTargetEntryPointPath: AbsoluteFsPath | null,
|
absoluteTargetEntryPointPath: AbsoluteFsPath|null,
|
||||||
pathMappings: PathMappings | undefined): EntryPointFinder {
|
pathMappings: PathMappings|undefined): EntryPointFinder {
|
||||||
if (absoluteTargetEntryPointPath !== null) {
|
if (absoluteTargetEntryPointPath !== null) {
|
||||||
return new TargetedEntryPointFinder(
|
return new TargetedEntryPointFinder(
|
||||||
fs, config, logger, resolver, basePath, absoluteTargetEntryPointPath, pathMappings);
|
fs, config, logger, resolver, basePath, absoluteTargetEntryPointPath, pathMappings);
|
||||||
|
@ -533,7 +541,7 @@ function getPropertiesToProcess(
|
||||||
|
|
||||||
const equivalentPropertiesMap = new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>();
|
const equivalentPropertiesMap = new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>();
|
||||||
for (const prop of propertiesToConsider) {
|
for (const prop of propertiesToConsider) {
|
||||||
const formatPath = packageJson[prop] !;
|
const formatPath = packageJson[prop]!;
|
||||||
const equivalentProperties = formatPathToProperties[formatPath];
|
const equivalentProperties = formatPathToProperties[formatPath];
|
||||||
equivalentPropertiesMap.set(prop, equivalentProperties);
|
equivalentPropertiesMap.set(prop, equivalentProperties);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ function migrateProviders(metadata: ResolvedValueMap, field: string, host: Migra
|
||||||
if (!metadata.has(field)) {
|
if (!metadata.has(field)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const providers = metadata.get(field) !;
|
const providers = metadata.get(field)!;
|
||||||
if (!Array.isArray(providers)) {
|
if (!Array.isArray(providers)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -127,10 +127,10 @@ function migrateProvider(provider: ResolvedValue, host: MigrationHost): void {
|
||||||
// as the provider itself configures 'deps'. Only if 'deps' is missing will this require a
|
// as the provider itself configures 'deps'. Only if 'deps' is missing will this require a
|
||||||
// factory to exist on SomeClass.
|
// factory to exist on SomeClass.
|
||||||
if (!provider.has('deps')) {
|
if (!provider.has('deps')) {
|
||||||
migrateProviderClass(provider.get('useClass') !, host);
|
migrateProviderClass(provider.get('useClass')!, host);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
migrateProviderClass(provider.get('provide') !, host);
|
migrateProviderClass(provider.get('provide')!, host);
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(provider)) {
|
} else if (Array.isArray(provider)) {
|
||||||
for (const v of provider) {
|
for (const v of provider) {
|
||||||
|
|
|
@ -43,7 +43,7 @@ export function hasConstructor(host: MigrationHost, clazz: ClassDeclaration): bo
|
||||||
*/
|
*/
|
||||||
export function createDirectiveDecorator(
|
export function createDirectiveDecorator(
|
||||||
clazz: ClassDeclaration,
|
clazz: ClassDeclaration,
|
||||||
metadata?: {selector: string | null, exportAs: string[] | null}): Decorator {
|
metadata?: {selector: string|null, exportAs: string[]|null}): Decorator {
|
||||||
const args: ts.Expression[] = [];
|
const args: ts.Expression[] = [];
|
||||||
if (metadata !== undefined) {
|
if (metadata !== undefined) {
|
||||||
const metaArgs: ts.PropertyAssignment[] = [];
|
const metaArgs: ts.PropertyAssignment[] = [];
|
||||||
|
@ -60,7 +60,8 @@ export function createDirectiveDecorator(
|
||||||
identifier: null,
|
identifier: null,
|
||||||
import: {name: 'Directive', from: '@angular/core'},
|
import: {name: 'Directive', from: '@angular/core'},
|
||||||
node: null,
|
node: null,
|
||||||
synthesizedFor: clazz.name, args,
|
synthesizedFor: clazz.name,
|
||||||
|
args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ export function createDirectiveDecorator(
|
||||||
*/
|
*/
|
||||||
export function createComponentDecorator(
|
export function createComponentDecorator(
|
||||||
clazz: ClassDeclaration,
|
clazz: ClassDeclaration,
|
||||||
metadata: {selector: string | null, exportAs: string[] | null}): Decorator {
|
metadata: {selector: string|null, exportAs: string[]|null}): Decorator {
|
||||||
const metaArgs: ts.PropertyAssignment[] = [
|
const metaArgs: ts.PropertyAssignment[] = [
|
||||||
property('template', ''),
|
property('template', ''),
|
||||||
];
|
];
|
||||||
|
@ -127,5 +128,5 @@ function reifySourceFile(expr: ts.Expression): ts.Expression {
|
||||||
if (!ts.isVariableStatement(stmt)) {
|
if (!ts.isVariableStatement(stmt)) {
|
||||||
throw new Error(`Expected VariableStatement, got ${ts.SyntaxKind[stmt.kind]}`);
|
throw new Error(`Expected VariableStatement, got ${ts.SyntaxKind[stmt.kind]}`);
|
||||||
}
|
}
|
||||||
return stmt.declarationList.declarations[0].initializer !;
|
return stmt.declarationList.declarations[0].initializer!;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,17 +6,19 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {AbsoluteFsPath, FileSystem, dirname, resolve} from '../../../src/ngtsc/file_system';
|
|
||||||
|
import {AbsoluteFsPath, dirname, FileSystem, resolve} from '../../../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {patchTsGetExpandoInitializer, restoreGetExpandoInitializer} from './patch_ts_expando_initializer';
|
import {patchTsGetExpandoInitializer, restoreGetExpandoInitializer} from './patch_ts_expando_initializer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An entry point bundle contains one or two programs, e.g. `src` and `dts`,
|
* An entry point bundle contains one or two programs, e.g. `src` and `dts`,
|
||||||
* that are compiled via TypeScript.
|
* that are compiled via TypeScript.
|
||||||
*
|
*
|
||||||
* To aid with processing the program, this interface exposes the program itself,
|
* To aid with processing the program, this interface exposes the program itself,
|
||||||
* as well as path and TS file of the entry-point to the program and the r3Symbols
|
* as well as path and TS file of the entry-point to the program and the r3Symbols
|
||||||
* file, if appropriate.
|
* file, if appropriate.
|
||||||
*/
|
*/
|
||||||
export interface BundleProgram {
|
export interface BundleProgram {
|
||||||
program: ts.Program;
|
program: ts.Program;
|
||||||
options: ts.CompilerOptions;
|
options: ts.CompilerOptions;
|
||||||
|
@ -46,7 +48,7 @@ export function makeBundleProgram(
|
||||||
program.getTypeChecker();
|
program.getTypeChecker();
|
||||||
restoreGetExpandoInitializer(originalGetExpandoInitializer);
|
restoreGetExpandoInitializer(originalGetExpandoInitializer);
|
||||||
|
|
||||||
const file = program.getSourceFile(path) !;
|
const file = program.getSourceFile(path)!;
|
||||||
const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null;
|
const r3SymbolsFile = r3SymbolsPath && program.getSourceFile(r3SymbolsPath) || null;
|
||||||
|
|
||||||
return {program, options, host, package: pkg, path, file, r3SymbolsPath, r3SymbolsFile};
|
return {program, options, host, package: pkg, path, file, r3SymbolsPath, r3SymbolsFile};
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
import {createHash} from 'crypto';
|
import {createHash} from 'crypto';
|
||||||
import {satisfies} from 'semver';
|
import {satisfies} from 'semver';
|
||||||
import * as vm from 'vm';
|
import * as vm from 'vm';
|
||||||
import {AbsoluteFsPath, FileSystem, dirname, join, resolve} from '../../../src/ngtsc/file_system';
|
|
||||||
|
import {AbsoluteFsPath, dirname, FileSystem, join, resolve} from '../../../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {PackageJsonFormatPropertiesMap} from './entry_point';
|
import {PackageJsonFormatPropertiesMap} from './entry_point';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,7 +180,7 @@ export class NgccConfiguration {
|
||||||
getConfig(packagePath: AbsoluteFsPath, version: string|null): VersionedPackageConfig {
|
getConfig(packagePath: AbsoluteFsPath, version: string|null): VersionedPackageConfig {
|
||||||
const cacheKey = packagePath + (version !== null ? `@${version}` : '');
|
const cacheKey = packagePath + (version !== null ? `@${version}` : '');
|
||||||
if (this.cache.has(cacheKey)) {
|
if (this.cache.has(cacheKey)) {
|
||||||
return this.cache.get(cacheKey) !;
|
return this.cache.get(cacheKey)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
const projectLevelConfig =
|
const projectLevelConfig =
|
||||||
|
@ -256,7 +258,8 @@ export class NgccConfiguration {
|
||||||
const theExports = {};
|
const theExports = {};
|
||||||
const sandbox = {
|
const sandbox = {
|
||||||
module: {exports: theExports},
|
module: {exports: theExports},
|
||||||
exports: theExports, require,
|
exports: theExports,
|
||||||
|
require,
|
||||||
__dirname: dirname(srcPath),
|
__dirname: dirname(srcPath),
|
||||||
__filename: srcPath
|
__filename: srcPath
|
||||||
};
|
};
|
||||||
|
@ -292,9 +295,8 @@ export class NgccConfiguration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function findSatisfactoryVersion(
|
function findSatisfactoryVersion(configs: VersionedPackageConfig[]|undefined, version: string|null):
|
||||||
configs: VersionedPackageConfig[] | undefined, version: string | null): VersionedPackageConfig|
|
VersionedPackageConfig|null {
|
||||||
null {
|
|
||||||
if (configs === undefined) {
|
if (configs === undefined) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {NgccConfiguration, NgccEntryPointConfig} from './configuration';
|
||||||
/**
|
/**
|
||||||
* The possible values for the format of an entry-point.
|
* The possible values for the format of an entry-point.
|
||||||
*/
|
*/
|
||||||
export type EntryPointFormat = 'esm5' | 'esm2015' | 'umd' | 'commonjs';
|
export type EntryPointFormat = 'esm5'|'esm2015'|'umd'|'commonjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object containing information about an entry-point, including paths
|
* An object containing information about an entry-point, including paths
|
||||||
|
@ -42,10 +42,12 @@ export interface EntryPoint extends JsonObject {
|
||||||
generateDeepReexports: boolean;
|
generateDeepReexports: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type JsonPrimitive = string | number | boolean | null;
|
export type JsonPrimitive = string|number|boolean|null;
|
||||||
export type JsonValue = JsonPrimitive | JsonArray | JsonObject | undefined;
|
export type JsonValue = JsonPrimitive|JsonArray|JsonObject|undefined;
|
||||||
export interface JsonArray extends Array<JsonValue> {}
|
export interface JsonArray extends Array<JsonValue> {}
|
||||||
export interface JsonObject { [key: string]: JsonValue; }
|
export interface JsonObject {
|
||||||
|
[key: string]: JsonValue;
|
||||||
|
}
|
||||||
|
|
||||||
export interface PackageJsonFormatPropertiesMap {
|
export interface PackageJsonFormatPropertiesMap {
|
||||||
fesm2015?: string;
|
fesm2015?: string;
|
||||||
|
@ -97,8 +99,7 @@ export const INCOMPATIBLE_ENTRY_POINT = 'incompatible-entry-point';
|
||||||
* * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched
|
* * INCOMPATIBLE_ENTRY_POINT - the path was a non-processable entry-point that should be searched
|
||||||
* for sub-entry-points
|
* for sub-entry-points
|
||||||
*/
|
*/
|
||||||
export type GetEntryPointResult =
|
export type GetEntryPointResult = EntryPoint|typeof INCOMPATIBLE_ENTRY_POINT|typeof NO_ENTRY_POINT;
|
||||||
EntryPoint | typeof INCOMPATIBLE_ENTRY_POINT | typeof NO_ENTRY_POINT;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -161,7 +162,8 @@ export function getEntryPointInfo(
|
||||||
packageJson: entryPointPackageJson,
|
packageJson: entryPointPackageJson,
|
||||||
package: packagePath,
|
package: packagePath,
|
||||||
path: entryPointPath,
|
path: entryPointPath,
|
||||||
typings: resolve(entryPointPath, typings), compiledByAngular,
|
typings: resolve(entryPointPath, typings),
|
||||||
|
compiledByAngular,
|
||||||
ignoreMissingDependencies:
|
ignoreMissingDependencies:
|
||||||
entryPointConfig !== undefined ? !!entryPointConfig.ignoreMissingDependencies : false,
|
entryPointConfig !== undefined ? !!entryPointConfig.ignoreMissingDependencies : false,
|
||||||
generateDeepReexports:
|
generateDeepReexports:
|
||||||
|
@ -236,7 +238,7 @@ function isUmdModule(fs: FileSystem, sourceFilePath: AbsoluteFsPath): boolean {
|
||||||
}
|
}
|
||||||
|
|
||||||
function mergeConfigAndPackageJson(
|
function mergeConfigAndPackageJson(
|
||||||
entryPointPackageJson: EntryPointPackageJson | null, entryPointConfig: NgccEntryPointConfig,
|
entryPointPackageJson: EntryPointPackageJson|null, entryPointConfig: NgccEntryPointConfig,
|
||||||
packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): EntryPointPackageJson {
|
packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath): EntryPointPackageJson {
|
||||||
if (entryPointPackageJson !== null) {
|
if (entryPointPackageJson !== null) {
|
||||||
return {...entryPointPackageJson, ...entryPointConfig.override};
|
return {...entryPointPackageJson, ...entryPointConfig.override};
|
||||||
|
|
|
@ -48,10 +48,8 @@ export function makeEntryPointBundle(
|
||||||
enableI18nLegacyMessageIdFormat: boolean = true): EntryPointBundle {
|
enableI18nLegacyMessageIdFormat: boolean = true): EntryPointBundle {
|
||||||
// Create the TS program and necessary helpers.
|
// Create the TS program and necessary helpers.
|
||||||
const rootDir = entryPoint.package;
|
const rootDir = entryPoint.package;
|
||||||
const options: ts.CompilerOptions = {
|
const options: ts
|
||||||
allowJs: true,
|
.CompilerOptions = {allowJs: true, maxNodeModuleJsDepth: Infinity, rootDir, ...pathMappings};
|
||||||
maxNodeModuleJsDepth: Infinity, rootDir, ...pathMappings
|
|
||||||
};
|
|
||||||
const srcHost = new NgccSourcesCompilerHost(fs, options, entryPoint.path);
|
const srcHost = new NgccSourcesCompilerHost(fs, options, entryPoint.path);
|
||||||
const dtsHost = new NgtscCompilerHost(fs, options);
|
const dtsHost = new NgtscCompilerHost(fs, options);
|
||||||
|
|
||||||
|
@ -72,7 +70,12 @@ export function makeEntryPointBundle(
|
||||||
return {
|
return {
|
||||||
entryPoint,
|
entryPoint,
|
||||||
format,
|
format,
|
||||||
rootDirs: [rootDir], isCore, isFlatCore, src, dts, enableI18nLegacyMessageIdFormat
|
rootDirs: [rootDir],
|
||||||
|
isCore,
|
||||||
|
isFlatCore,
|
||||||
|
src,
|
||||||
|
dts,
|
||||||
|
enableI18nLegacyMessageIdFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {Logger} from '../logging/logger';
|
||||||
|
|
||||||
import {NGCC_VERSION} from './build_marker';
|
import {NGCC_VERSION} from './build_marker';
|
||||||
import {NgccConfiguration} from './configuration';
|
import {NgccConfiguration} from './configuration';
|
||||||
import {EntryPoint, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT, getEntryPointInfo} from './entry_point';
|
import {EntryPoint, getEntryPointInfo, INCOMPATIBLE_ENTRY_POINT, NO_ENTRY_POINT} from './entry_point';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages reading and writing a manifest file that contains a list of all the entry-points that
|
* Manages reading and writing a manifest file that contains a list of all the entry-points that
|
||||||
|
@ -63,8 +63,8 @@ export class EntryPointManifest {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.debug(
|
this.logger.debug(`Entry-point manifest found for ${
|
||||||
`Entry-point manifest found for ${basePath} so loading entry-point information directly.`);
|
basePath} so loading entry-point information directly.`);
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
|
|
||||||
const entryPoints: EntryPoint[] = [];
|
const entryPoints: EntryPoint[] = [];
|
||||||
|
@ -72,8 +72,9 @@ export class EntryPointManifest {
|
||||||
const result =
|
const result =
|
||||||
getEntryPointInfo(this.fs, this.config, this.logger, packagePath, entryPointPath);
|
getEntryPointInfo(this.fs, this.config, this.logger, packagePath, entryPointPath);
|
||||||
if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) {
|
if (result === NO_ENTRY_POINT || result === INCOMPATIBLE_ENTRY_POINT) {
|
||||||
throw new Error(
|
throw new Error(`The entry-point manifest at ${
|
||||||
`The entry-point manifest at ${manifestPath} contained an invalid pair of package paths: [${packagePath}, ${entryPointPath}]`);
|
manifestPath} contained an invalid pair of package paths: [${packagePath}, ${
|
||||||
|
entryPointPath}]`);
|
||||||
} else {
|
} else {
|
||||||
entryPoints.push(result);
|
entryPoints.push(result);
|
||||||
}
|
}
|
||||||
|
@ -142,7 +143,9 @@ export class EntryPointManifest {
|
||||||
* called.
|
* called.
|
||||||
*/
|
*/
|
||||||
export class InvalidatingEntryPointManifest extends EntryPointManifest {
|
export class InvalidatingEntryPointManifest extends EntryPointManifest {
|
||||||
readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPoint[]|null { return null; }
|
readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPoint[]|null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -58,13 +58,12 @@ export function patchTsGetExpandoInitializer(): unknown {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override the function to add support for recognizing the IIFE structure used in ES5 bundles.
|
// Override the function to add support for recognizing the IIFE structure used in ES5 bundles.
|
||||||
(ts as any).getExpandoInitializer =
|
(ts as any).getExpandoInitializer = (initializer: ts.Node,
|
||||||
(initializer: ts.Node, isPrototypeAssignment: boolean): ts.Expression | undefined => {
|
isPrototypeAssignment: boolean): ts.Expression|undefined => {
|
||||||
// If the initializer is a call expression within parenthesis, unwrap the parenthesis
|
// If the initializer is a call expression within parenthesis, unwrap the parenthesis
|
||||||
// upfront such that unsupported IIFE syntax `(function(){}())` becomes `function(){}()`,
|
// upfront such that unsupported IIFE syntax `(function(){}())` becomes `function(){}()`,
|
||||||
// which is supported.
|
// which is supported.
|
||||||
if (ts.isParenthesizedExpression(initializer) &&
|
if (ts.isParenthesizedExpression(initializer) && ts.isCallExpression(initializer.expression)) {
|
||||||
ts.isCallExpression(initializer.expression)) {
|
|
||||||
initializer = initializer.expression;
|
initializer = initializer.expression;
|
||||||
}
|
}
|
||||||
return originalGetExpandoInitializer(initializer, isPrototypeAssignment);
|
return originalGetExpandoInitializer(initializer, isPrototypeAssignment);
|
||||||
|
@ -125,16 +124,36 @@ function checkIfExpandoPropertyIsPresent(): boolean {
|
||||||
const sourceFile =
|
const sourceFile =
|
||||||
ts.createSourceFile('test.js', sourceText, ts.ScriptTarget.ES5, true, ts.ScriptKind.JS);
|
ts.createSourceFile('test.js', sourceText, ts.ScriptTarget.ES5, true, ts.ScriptKind.JS);
|
||||||
const host: ts.CompilerHost = {
|
const host: ts.CompilerHost = {
|
||||||
getSourceFile(): ts.SourceFile | undefined{return sourceFile;},
|
getSourceFile(): ts.SourceFile |
|
||||||
fileExists(): boolean{return true;},
|
undefined {
|
||||||
readFile(): string | undefined{return '';},
|
return sourceFile;
|
||||||
|
},
|
||||||
|
fileExists(): boolean {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
readFile(): string |
|
||||||
|
undefined {
|
||||||
|
return '';
|
||||||
|
},
|
||||||
writeFile() {},
|
writeFile() {},
|
||||||
getDefaultLibFileName(): string{return '';},
|
getDefaultLibFileName(): string {
|
||||||
getCurrentDirectory(): string{return '';},
|
return '';
|
||||||
getDirectories(): string[]{return [];},
|
},
|
||||||
getCanonicalFileName(fileName: string): string{return fileName;},
|
getCurrentDirectory(): string {
|
||||||
useCaseSensitiveFileNames(): boolean{return true;},
|
return '';
|
||||||
getNewLine(): string{return '\n';},
|
},
|
||||||
|
getDirectories(): string[] {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
getCanonicalFileName(fileName: string): string {
|
||||||
|
return fileName;
|
||||||
|
},
|
||||||
|
useCaseSensitiveFileNames(): boolean {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
getNewLine(): string {
|
||||||
|
return '\n';
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const options = {noResolve: true, noLib: true, noEmit: true, allowJs: true};
|
const options = {noResolve: true, noLib: true, noEmit: true, allowJs: true};
|
||||||
const program = ts.createProgram(['test.js'], options, host);
|
const program = ts.createProgram(['test.js'], options, host);
|
||||||
|
|
|
@ -36,8 +36,7 @@ import {EntryPointBundle} from './entry_point_bundle';
|
||||||
|
|
||||||
export type TransformResult = {
|
export type TransformResult = {
|
||||||
success: true; diagnostics: ts.Diagnostic[]; transformedFiles: FileToWrite[];
|
success: true; diagnostics: ts.Diagnostic[]; transformedFiles: FileToWrite[];
|
||||||
} |
|
}|{
|
||||||
{
|
|
||||||
success: false;
|
success: false;
|
||||||
diagnostics: ts.Diagnostic[];
|
diagnostics: ts.Diagnostic[];
|
||||||
};
|
};
|
||||||
|
@ -79,8 +78,13 @@ export class Transformer {
|
||||||
const reflectionHost = new DelegatingReflectionHost(tsReflectionHost, ngccReflectionHost);
|
const reflectionHost = new DelegatingReflectionHost(tsReflectionHost, ngccReflectionHost);
|
||||||
|
|
||||||
// Parse and analyze the files.
|
// Parse and analyze the files.
|
||||||
const {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
const {
|
||||||
moduleWithProvidersAnalyses, diagnostics} = this.analyzeProgram(reflectionHost, bundle);
|
decorationAnalyses,
|
||||||
|
switchMarkerAnalyses,
|
||||||
|
privateDeclarationsAnalyses,
|
||||||
|
moduleWithProvidersAnalyses,
|
||||||
|
diagnostics
|
||||||
|
} = this.analyzeProgram(reflectionHost, bundle);
|
||||||
|
|
||||||
// Bail if the analysis produced any errors.
|
// Bail if the analysis produced any errors.
|
||||||
if (hasErrors(diagnostics)) {
|
if (hasErrors(diagnostics)) {
|
||||||
|
@ -162,8 +166,13 @@ export class Transformer {
|
||||||
const privateDeclarationsAnalyses =
|
const privateDeclarationsAnalyses =
|
||||||
privateDeclarationsAnalyzer.analyzeProgram(bundle.src.program);
|
privateDeclarationsAnalyzer.analyzeProgram(bundle.src.program);
|
||||||
|
|
||||||
return {decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
|
return {
|
||||||
moduleWithProvidersAnalyses, diagnostics};
|
decorationAnalyses,
|
||||||
|
switchMarkerAnalyses,
|
||||||
|
privateDeclarationsAnalyses,
|
||||||
|
moduleWithProvidersAnalyses,
|
||||||
|
diagnostics
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,15 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {dirname, relative} from 'canonical-path';
|
import {dirname, relative} from 'canonical-path';
|
||||||
import * as ts from 'typescript';
|
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {Reexport} from '../../../src/ngtsc/imports';
|
import {Reexport} from '../../../src/ngtsc/imports';
|
||||||
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
||||||
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||||
import {isRequireCall} from '../host/commonjs_umd_utils';
|
import {isRequireCall} from '../host/commonjs_umd_utils';
|
||||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||||
|
|
||||||
import {Esm5RenderingFormatter} from './esm5_rendering_formatter';
|
import {Esm5RenderingFormatter} from './esm5_rendering_formatter';
|
||||||
import {stripExtension} from './utils';
|
import {stripExtension} from './utils';
|
||||||
|
|
||||||
|
|
|
@ -7,20 +7,22 @@
|
||||||
*/
|
*/
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {Reexport} from '../../../src/ngtsc/imports';
|
import {Reexport} from '../../../src/ngtsc/imports';
|
||||||
import {CompileResult} from '../../../src/ngtsc/transform';
|
import {CompileResult} from '../../../src/ngtsc/transform';
|
||||||
import {translateType, ImportManager} from '../../../src/ngtsc/translator';
|
import {ImportManager, translateType} from '../../../src/ngtsc/translator';
|
||||||
|
import {ModuleWithProvidersAnalyses, ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
||||||
|
import {ExportInfo, PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer';
|
||||||
import {DecorationAnalyses} from '../analysis/types';
|
import {DecorationAnalyses} from '../analysis/types';
|
||||||
import {ModuleWithProvidersInfo, ModuleWithProvidersAnalyses} from '../analysis/module_with_providers_analyzer';
|
|
||||||
import {PrivateDeclarationsAnalyses, ExportInfo} from '../analysis/private_declarations_analyzer';
|
|
||||||
import {IMPORT_PREFIX} from '../constants';
|
import {IMPORT_PREFIX} from '../constants';
|
||||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {FileToWrite, getImportRewriter} from './utils';
|
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||||
|
|
||||||
import {RenderingFormatter} from './rendering_formatter';
|
import {RenderingFormatter} from './rendering_formatter';
|
||||||
import {renderSourceAndMap} from './source_maps';
|
import {renderSourceAndMap} from './source_maps';
|
||||||
|
import {FileToWrite, getImportRewriter} from './utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A structure that captures information about what needs to be rendered
|
* A structure that captures information about what needs to be rendered
|
||||||
|
@ -84,7 +86,7 @@ export class DtsRenderer {
|
||||||
const outputText = new MagicString(dtsFile.text);
|
const outputText = new MagicString(dtsFile.text);
|
||||||
const printer = ts.createPrinter();
|
const printer = ts.createPrinter();
|
||||||
const importManager = new ImportManager(
|
const importManager = new ImportManager(
|
||||||
getImportRewriter(this.bundle.dts !.r3SymbolsFile, this.bundle.isCore, false),
|
getImportRewriter(this.bundle.dts!.r3SymbolsFile, this.bundle.isCore, false),
|
||||||
IMPORT_PREFIX);
|
IMPORT_PREFIX);
|
||||||
|
|
||||||
renderInfo.classInfo.forEach(dtsClass => {
|
renderInfo.classInfo.forEach(dtsClass => {
|
||||||
|
@ -129,7 +131,7 @@ export class DtsRenderer {
|
||||||
const dtsDeclaration = this.host.getDtsDeclaration(compiledClass.declaration);
|
const dtsDeclaration = this.host.getDtsDeclaration(compiledClass.declaration);
|
||||||
if (dtsDeclaration) {
|
if (dtsDeclaration) {
|
||||||
const dtsFile = dtsDeclaration.getSourceFile();
|
const dtsFile = dtsDeclaration.getSourceFile();
|
||||||
const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile) ! : new DtsRenderInfo();
|
const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile)! : new DtsRenderInfo();
|
||||||
renderInfo.classInfo.push({dtsDeclaration, compilation: compiledClass.compilation});
|
renderInfo.classInfo.push({dtsDeclaration, compilation: compiledClass.compilation});
|
||||||
// Only add re-exports if the .d.ts tree is overlayed with the .js tree, as re-exports in
|
// Only add re-exports if the .d.ts tree is overlayed with the .js tree, as re-exports in
|
||||||
// ngcc are only used to support deep imports into e.g. commonjs code. For a deep import
|
// ngcc are only used to support deep imports into e.g. commonjs code. For a deep import
|
||||||
|
@ -150,7 +152,7 @@ export class DtsRenderer {
|
||||||
// Capture the ModuleWithProviders functions/methods that need updating
|
// Capture the ModuleWithProviders functions/methods that need updating
|
||||||
if (moduleWithProvidersAnalyses !== null) {
|
if (moduleWithProvidersAnalyses !== null) {
|
||||||
moduleWithProvidersAnalyses.forEach((moduleWithProvidersToFix, dtsFile) => {
|
moduleWithProvidersAnalyses.forEach((moduleWithProvidersToFix, dtsFile) => {
|
||||||
const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile) ! : new DtsRenderInfo();
|
const renderInfo = dtsMap.has(dtsFile) ? dtsMap.get(dtsFile)! : new DtsRenderInfo();
|
||||||
renderInfo.moduleWithProviders = moduleWithProvidersToFix;
|
renderInfo.moduleWithProviders = moduleWithProvidersToFix;
|
||||||
dtsMap.set(dtsFile, renderInfo);
|
dtsMap.set(dtsFile, renderInfo);
|
||||||
});
|
});
|
||||||
|
@ -167,9 +169,9 @@ export class DtsRenderer {
|
||||||
`The simplest fix for this is to ensure that this class is exported from the package's entry-point.`);
|
`The simplest fix for this is to ensure that this class is exported from the package's entry-point.`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const dtsEntryPoint = this.bundle.dts !.file;
|
const dtsEntryPoint = this.bundle.dts!.file;
|
||||||
const renderInfo =
|
const renderInfo =
|
||||||
dtsMap.has(dtsEntryPoint) ? dtsMap.get(dtsEntryPoint) ! : new DtsRenderInfo();
|
dtsMap.has(dtsEntryPoint) ? dtsMap.get(dtsEntryPoint)! : new DtsRenderInfo();
|
||||||
renderInfo.privateExports = privateDeclarationsAnalyses;
|
renderInfo.privateExports = privateDeclarationsAnalyses;
|
||||||
dtsMap.set(dtsEntryPoint, renderInfo);
|
dtsMap.set(dtsEntryPoint, renderInfo);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,14 @@ export class Esm5RenderingFormatter extends EsmRenderingFormatter {
|
||||||
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void {
|
addDefinitions(output: MagicString, compiledClass: CompiledClass, definitions: string): void {
|
||||||
const iifeBody = getIifeBody(compiledClass.declaration);
|
const iifeBody = getIifeBody(compiledClass.declaration);
|
||||||
if (!iifeBody) {
|
if (!iifeBody) {
|
||||||
throw new Error(
|
throw new Error(`Compiled class declaration is not inside an IIFE: ${compiledClass.name} in ${
|
||||||
`Compiled class declaration is not inside an IIFE: ${compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`);
|
compiledClass.declaration.getSourceFile().fileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const returnStatement = iifeBody.statements.find(ts.isReturnStatement);
|
const returnStatement = iifeBody.statements.find(ts.isReturnStatement);
|
||||||
if (!returnStatement) {
|
if (!returnStatement) {
|
||||||
throw new Error(
|
throw new Error(`Compiled class wrapper IIFE does not have a return statement: ${
|
||||||
`Compiled class wrapper IIFE does not have a return statement: ${compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`);
|
compiledClass.name} in ${compiledClass.declaration.getSourceFile().fileName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const insertionPoint = returnStatement.getFullStart();
|
const insertionPoint = returnStatement.getFullStart();
|
||||||
|
|
|
@ -8,17 +8,19 @@
|
||||||
import {Statement} from '@angular/compiler';
|
import {Statement} from '@angular/compiler';
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {relative, dirname, AbsoluteFsPath, absoluteFromSourceFile} from '../../../src/ngtsc/file_system';
|
|
||||||
|
import {absoluteFromSourceFile, AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system';
|
||||||
import {NOOP_DEFAULT_IMPORT_RECORDER, Reexport} from '../../../src/ngtsc/imports';
|
import {NOOP_DEFAULT_IMPORT_RECORDER, Reexport} from '../../../src/ngtsc/imports';
|
||||||
import {Import, ImportManager, translateStatement} from '../../../src/ngtsc/translator';
|
import {Import, ImportManager, translateStatement} from '../../../src/ngtsc/translator';
|
||||||
import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
||||||
import {CompiledClass} from '../analysis/types';
|
|
||||||
import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host';
|
|
||||||
import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
||||||
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||||
import {RenderingFormatter, RedundantDecoratorMap} from './rendering_formatter';
|
import {CompiledClass} from '../analysis/types';
|
||||||
import {stripExtension} from './utils';
|
|
||||||
import {isAssignment} from '../host/esm2015_host';
|
import {isAssignment} from '../host/esm2015_host';
|
||||||
|
import {NgccReflectionHost, POST_R3_MARKER, PRE_R3_MARKER, SwitchableVariableDeclaration} from '../host/ngcc_host';
|
||||||
|
|
||||||
|
import {RedundantDecoratorMap, RenderingFormatter} from './rendering_formatter';
|
||||||
|
import {stripExtension} from './utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RenderingFormatter that works with ECMAScript Module import and export statements.
|
* A RenderingFormatter that works with ECMAScript Module import and export statements.
|
||||||
|
@ -226,7 +228,8 @@ export class EsmRenderingFormatter implements RenderingFormatter {
|
||||||
info.declaration.getEnd();
|
info.declaration.getEnd();
|
||||||
outputText.appendLeft(
|
outputText.appendLeft(
|
||||||
insertPoint,
|
insertPoint,
|
||||||
`: ${generateImportString(importManager, '@angular/core', 'ModuleWithProviders')}<${ngModule}>`);
|
`: ${generateImportString(importManager, '@angular/core', 'ModuleWithProviders')}<${
|
||||||
|
ngModule}>`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -296,7 +299,7 @@ function findStatement(node: ts.Node): ts.Statement|undefined {
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateImportString(
|
function generateImportString(
|
||||||
importManager: ImportManager, importPath: string | null, importName: string) {
|
importManager: ImportManager, importPath: string|null, importName: string) {
|
||||||
const importAs = importPath ? importManager.generateNamedImport(importPath, importName) : null;
|
const importAs = importPath ? importManager.generateNamedImport(importPath, importName) : null;
|
||||||
return importAs ? `${importAs.moduleImport}.${importAs.symbol}` : `${importName}`;
|
return importAs ? `${importAs.moduleImport}.${importAs.symbol}` : `${importName}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,18 @@
|
||||||
import {ConstantPool, Expression, Statement, WrappedNodeExpr, WritePropExpr} from '@angular/compiler';
|
import {ConstantPool, Expression, Statement, WrappedNodeExpr, WritePropExpr} from '@angular/compiler';
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
|
import {FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {ImportManager} from '../../../src/ngtsc/translator';
|
import {ImportManager} from '../../../src/ngtsc/translator';
|
||||||
import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/types';
|
|
||||||
import {PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer';
|
import {PrivateDeclarationsAnalyses} from '../analysis/private_declarations_analyzer';
|
||||||
import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
|
import {SwitchMarkerAnalyses, SwitchMarkerAnalysis} from '../analysis/switch_marker_analyzer';
|
||||||
|
import {CompiledClass, CompiledFile, DecorationAnalyses} from '../analysis/types';
|
||||||
import {IMPORT_PREFIX} from '../constants';
|
import {IMPORT_PREFIX} from '../constants';
|
||||||
import {FileSystem} from '../../../src/ngtsc/file_system';
|
|
||||||
import {NgccReflectionHost} from '../host/ngcc_host';
|
import {NgccReflectionHost} from '../host/ngcc_host';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||||
import {RenderingFormatter, RedundantDecoratorMap} from './rendering_formatter';
|
|
||||||
|
import {RedundantDecoratorMap, RenderingFormatter} from './rendering_formatter';
|
||||||
import {renderSourceAndMap} from './source_maps';
|
import {renderSourceAndMap} from './source_maps';
|
||||||
import {FileToWrite, getImportRewriter, stripExtension} from './utils';
|
import {FileToWrite, getImportRewriter, stripExtension} from './utils';
|
||||||
|
|
||||||
|
@ -138,11 +140,11 @@ export class Renderer {
|
||||||
if (dec.node === null) {
|
if (dec.node === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const decoratorArray = dec.node.parent !;
|
const decoratorArray = dec.node.parent!;
|
||||||
if (!decoratorsToRemove.has(decoratorArray)) {
|
if (!decoratorsToRemove.has(decoratorArray)) {
|
||||||
decoratorsToRemove.set(decoratorArray, [dec.node]);
|
decoratorsToRemove.set(decoratorArray, [dec.node]);
|
||||||
} else {
|
} else {
|
||||||
decoratorsToRemove.get(decoratorArray) !.push(dec.node);
|
decoratorsToRemove.get(decoratorArray)!.push(dec.node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -160,8 +162,9 @@ export class Renderer {
|
||||||
private renderDefinitions(
|
private renderDefinitions(
|
||||||
sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: ImportManager): string {
|
sourceFile: ts.SourceFile, compiledClass: CompiledClass, imports: ImportManager): string {
|
||||||
const name = this.host.getInternalNameOfClass(compiledClass.declaration);
|
const name = this.host.getInternalNameOfClass(compiledClass.declaration);
|
||||||
const statements: Statement[] = compiledClass.compilation.map(
|
const statements: Statement[] = compiledClass.compilation.map(c => {
|
||||||
c => { return createAssignmentStatement(name, c.name, c.initializer); });
|
return createAssignmentStatement(name, c.name, c.initializer);
|
||||||
|
});
|
||||||
return this.renderStatements(sourceFile, statements, imports);
|
return this.renderStatements(sourceFile, statements, imports);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,13 @@
|
||||||
import {Statement} from '@angular/compiler';
|
import {Statement} from '@angular/compiler';
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {Reexport} from '../../../src/ngtsc/imports';
|
import {Reexport} from '../../../src/ngtsc/imports';
|
||||||
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
||||||
|
import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
||||||
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||||
import {CompiledClass} from '../analysis/types';
|
import {CompiledClass} from '../analysis/types';
|
||||||
import {SwitchableVariableDeclaration} from '../host/ngcc_host';
|
import {SwitchableVariableDeclaration} from '../host/ngcc_host';
|
||||||
import {ModuleWithProvidersInfo} from '../analysis/module_with_providers_analyzer';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collected decorators that have become redundant after the compilation
|
* The collected decorators that have become redundant after the compilation
|
||||||
|
|
|
@ -5,14 +5,16 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {SourceMapConverter, fromObject, generateMapFileComment} from 'convert-source-map';
|
import {fromObject, generateMapFileComment, SourceMapConverter} from 'convert-source-map';
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {FileSystem, absoluteFromSourceFile, basename, absoluteFrom} from '../../../src/ngtsc/file_system';
|
|
||||||
import {FileToWrite} from './utils';
|
import {absoluteFrom, absoluteFromSourceFile, basename, FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {SourceFileLoader} from '../sourcemaps/source_file_loader';
|
|
||||||
import {RawSourceMap} from '../sourcemaps/raw_source_map';
|
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
|
import {RawSourceMap} from '../sourcemaps/raw_source_map';
|
||||||
|
import {SourceFileLoader} from '../sourcemaps/source_file_loader';
|
||||||
|
|
||||||
|
import {FileToWrite} from './utils';
|
||||||
|
|
||||||
export interface SourceMapInfo {
|
export interface SourceMapInfo {
|
||||||
source: string;
|
source: string;
|
||||||
|
@ -53,8 +55,8 @@ export function renderSourceAndMap(
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error(
|
logger.error(`Error when flattening the source-map "${generatedMapPath}" for "${
|
||||||
`Error when flattening the source-map "${generatedMapPath}" for "${generatedPath}": ${e.toString()}`);
|
generatedPath}": ${e.toString()}`);
|
||||||
return [
|
return [
|
||||||
{path: generatedPath, contents: generatedContent},
|
{path: generatedPath, contents: generatedContent},
|
||||||
{path: generatedMapPath, contents: fromObject(generatedMap).toJSON()},
|
{path: generatedMapPath, contents: fromObject(generatedMap).toJSON()},
|
||||||
|
|
|
@ -6,17 +6,19 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {dirname, relative} from 'canonical-path';
|
import {dirname, relative} from 'canonical-path';
|
||||||
import * as ts from 'typescript';
|
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
|
import {Reexport} from '../../../src/ngtsc/imports';
|
||||||
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
import {Import, ImportManager} from '../../../src/ngtsc/translator';
|
||||||
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
import {ExportInfo} from '../analysis/private_declarations_analyzer';
|
||||||
import {UmdReflectionHost} from '../host/umd_host';
|
import {UmdReflectionHost} from '../host/umd_host';
|
||||||
|
|
||||||
import {Esm5RenderingFormatter} from './esm5_rendering_formatter';
|
import {Esm5RenderingFormatter} from './esm5_rendering_formatter';
|
||||||
import {stripExtension} from './utils';
|
import {stripExtension} from './utils';
|
||||||
import {Reexport} from '../../../src/ngtsc/imports';
|
|
||||||
|
|
||||||
type CommonJsConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression};
|
type CommonJsConditional = ts.ConditionalExpression&{whenTrue: ts.CallExpression};
|
||||||
type AmdConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression};
|
type AmdConditional = ts.ConditionalExpression&{whenTrue: ts.CallExpression};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A RenderingFormatter that works with UMD files, instead of `import` and `export` statements
|
* A RenderingFormatter that works with UMD files, instead of `import` and `export` statements
|
||||||
|
@ -24,7 +26,9 @@ type AmdConditional = ts.ConditionalExpression & {whenTrue: ts.CallExpression};
|
||||||
* wrapper function for AMD, CommonJS and global module formats.
|
* wrapper function for AMD, CommonJS and global module formats.
|
||||||
*/
|
*/
|
||||||
export class UmdRenderingFormatter extends Esm5RenderingFormatter {
|
export class UmdRenderingFormatter extends Esm5RenderingFormatter {
|
||||||
constructor(protected umdHost: UmdReflectionHost, isCore: boolean) { super(umdHost, isCore); }
|
constructor(protected umdHost: UmdReflectionHost, isCore: boolean) {
|
||||||
|
super(umdHost, isCore);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add the imports to the UMD module IIFE.
|
* Add the imports to the UMD module IIFE.
|
||||||
|
|
|
@ -24,11 +24,11 @@ export interface FileToWrite {
|
||||||
* Create an appropriate ImportRewriter given the parameters.
|
* Create an appropriate ImportRewriter given the parameters.
|
||||||
*/
|
*/
|
||||||
export function getImportRewriter(
|
export function getImportRewriter(
|
||||||
r3SymbolsFile: ts.SourceFile | null, isCore: boolean, isFlat: boolean): ImportRewriter {
|
r3SymbolsFile: ts.SourceFile|null, isCore: boolean, isFlat: boolean): ImportRewriter {
|
||||||
if (isCore && isFlat) {
|
if (isCore && isFlat) {
|
||||||
return new NgccFlatImportRewriter();
|
return new NgccFlatImportRewriter();
|
||||||
} else if (isCore) {
|
} else if (isCore) {
|
||||||
return new R3SymbolsImportRewriter(r3SymbolsFile !.fileName);
|
return new R3SymbolsImportRewriter(r3SymbolsFile!.fileName);
|
||||||
} else {
|
} else {
|
||||||
return new NoopImportRewriter();
|
return new NoopImportRewriter();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker that indicates the start of a segment in a mapping.
|
* A marker that indicates the start of a segment in a mapping.
|
||||||
*
|
*
|
||||||
* The end of a segment is indicated by the the first segment-marker of another mapping whose start
|
* The end of a segment is indicated by the the first segment-marker of another mapping whose start
|
||||||
* is greater or equal to this one.
|
* is greater or equal to this one.
|
||||||
*/
|
*/
|
||||||
export interface SegmentMarker {
|
export interface SegmentMarker {
|
||||||
readonly line: number;
|
readonly line: number;
|
||||||
readonly column: number;
|
readonly column: number;
|
||||||
|
|
|
@ -6,10 +6,12 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {removeComments, removeMapFileComments} from 'convert-source-map';
|
import {removeComments, removeMapFileComments} from 'convert-source-map';
|
||||||
import {SourceMapMappings, SourceMapSegment, decode, encode} from 'sourcemap-codec';
|
import {decode, encode, SourceMapMappings, SourceMapSegment} from 'sourcemap-codec';
|
||||||
|
|
||||||
import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, dirname, relative} from '../../../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {RawSourceMap} from './raw_source_map';
|
import {RawSourceMap} from './raw_source_map';
|
||||||
import {SegmentMarker, compareSegments, offsetSegment} from './segment_marker';
|
import {compareSegments, offsetSegment, SegmentMarker} from './segment_marker';
|
||||||
|
|
||||||
export function removeSourceMapComments(contents: string): string {
|
export function removeSourceMapComments(contents: string): string {
|
||||||
return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n');
|
return removeMapFileComments(removeComments(contents)).replace(/\n\n$/, '\n');
|
||||||
|
@ -77,7 +79,8 @@ export class SourceFile {
|
||||||
const sourceMap: RawSourceMap = {
|
const sourceMap: RawSourceMap = {
|
||||||
version: 3,
|
version: 3,
|
||||||
file: relative(sourcePathDir, this.sourcePath),
|
file: relative(sourcePathDir, this.sourcePath),
|
||||||
sources: sources.map(sf => relative(sourcePathDir, sf.sourcePath)), names,
|
sources: sources.map(sf => relative(sourcePathDir, sf.sourcePath)),
|
||||||
|
names,
|
||||||
mappings: encode(mappings),
|
mappings: encode(mappings),
|
||||||
sourcesContent: sources.map(sf => sf.contents),
|
sourcesContent: sources.map(sf => sf.contents),
|
||||||
};
|
};
|
||||||
|
@ -302,7 +305,7 @@ export function mergeMappings(generatedSource: SourceFile, ab: Mapping, bc: Mapp
|
||||||
* in the `sources` parameter.
|
* in the `sources` parameter.
|
||||||
*/
|
*/
|
||||||
export function parseMappings(
|
export function parseMappings(
|
||||||
rawMap: RawSourceMap | null, sources: (SourceFile | null)[],
|
rawMap: RawSourceMap|null, sources: (SourceFile|null)[],
|
||||||
generatedSourceStartOfLinePositions: number[]): Mapping[] {
|
generatedSourceStartOfLinePositions: number[]): Mapping[] {
|
||||||
if (rawMap === null) {
|
if (rawMap === null) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -318,15 +321,15 @@ export function parseMappings(
|
||||||
const generatedLineMappings = rawMappings[generatedLine];
|
const generatedLineMappings = rawMappings[generatedLine];
|
||||||
for (const rawMapping of generatedLineMappings) {
|
for (const rawMapping of generatedLineMappings) {
|
||||||
if (rawMapping.length >= 4) {
|
if (rawMapping.length >= 4) {
|
||||||
const originalSource = sources[rawMapping[1] !];
|
const originalSource = sources[rawMapping[1]!];
|
||||||
if (originalSource === null || originalSource === undefined) {
|
if (originalSource === null || originalSource === undefined) {
|
||||||
// the original source is missing so ignore this mapping
|
// the original source is missing so ignore this mapping
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const generatedColumn = rawMapping[0];
|
const generatedColumn = rawMapping[0];
|
||||||
const name = rawMapping.length === 5 ? rawMap.names[rawMapping[4]] : undefined;
|
const name = rawMapping.length === 5 ? rawMap.names[rawMapping[4]] : undefined;
|
||||||
const line = rawMapping[2] !;
|
const line = rawMapping[2]!;
|
||||||
const column = rawMapping[3] !;
|
const column = rawMapping[3]!;
|
||||||
const generatedSegment: SegmentMarker = {
|
const generatedSegment: SegmentMarker = {
|
||||||
line: generatedLine,
|
line: generatedLine,
|
||||||
column: generatedColumn,
|
column: generatedColumn,
|
||||||
|
@ -361,7 +364,7 @@ export function extractOriginalSegments(mappings: Mapping[]): Map<SourceFile, Se
|
||||||
if (!originalSegments.has(originalSource)) {
|
if (!originalSegments.has(originalSource)) {
|
||||||
originalSegments.set(originalSource, []);
|
originalSegments.set(originalSource, []);
|
||||||
}
|
}
|
||||||
const segments = originalSegments.get(originalSource) !;
|
const segments = originalSegments.get(originalSource)!;
|
||||||
segments.push(mapping.originalSegment);
|
segments.push(mapping.originalSegment);
|
||||||
}
|
}
|
||||||
originalSegments.forEach(segmentMarkers => segmentMarkers.sort(compareSegments));
|
originalSegments.forEach(segmentMarkers => segmentMarkers.sort(compareSegments));
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {commentRegex, fromComment, mapFileCommentRegex} from 'convert-source-map';
|
import {commentRegex, fromComment, mapFileCommentRegex} from 'convert-source-map';
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom} from '../../../src/ngtsc/file_system';
|
|
||||||
|
import {absoluteFrom, AbsoluteFsPath, FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
|
|
||||||
import {RawSourceMap} from './raw_source_map';
|
import {RawSourceMap} from './raw_source_map';
|
||||||
import {SourceFile} from './source_file';
|
import {SourceFile} from './source_file';
|
||||||
|
|
||||||
|
@ -51,8 +53,8 @@ export class SourceFileLoader {
|
||||||
// Track source file paths if we have loaded them from disk so that we don't get into an
|
// Track source file paths if we have loaded them from disk so that we don't get into an
|
||||||
// infinite recursion
|
// infinite recursion
|
||||||
if (previousPaths.includes(sourcePath)) {
|
if (previousPaths.includes(sourcePath)) {
|
||||||
throw new Error(
|
throw new Error(`Circular source file mapping dependency: ${
|
||||||
`Circular source file mapping dependency: ${previousPaths.join(' -> ')} -> ${sourcePath}`);
|
previousPaths.join(' -> ')} -> ${sourcePath}`);
|
||||||
}
|
}
|
||||||
previousPaths = previousPaths.concat([sourcePath]);
|
previousPaths = previousPaths.concat([sourcePath]);
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ export class SourceFileLoader {
|
||||||
|
|
||||||
let map: RawSourceMap|null = null;
|
let map: RawSourceMap|null = null;
|
||||||
let inline = true;
|
let inline = true;
|
||||||
let sources: (SourceFile | null)[] = [];
|
let sources: (SourceFile|null)[] = [];
|
||||||
if (mapAndPath !== null) {
|
if (mapAndPath !== null) {
|
||||||
const basePath = mapAndPath.mapPath || sourcePath;
|
const basePath = mapAndPath.mapPath || sourcePath;
|
||||||
sources = this.processSources(basePath, mapAndPath.map, previousPaths);
|
sources = this.processSources(basePath, mapAndPath.map, previousPaths);
|
||||||
|
@ -87,7 +89,7 @@ export class SourceFileLoader {
|
||||||
private loadSourceMap(sourcePath: AbsoluteFsPath, contents: string): MapAndPath|null {
|
private loadSourceMap(sourcePath: AbsoluteFsPath, contents: string): MapAndPath|null {
|
||||||
const inline = commentRegex.exec(contents);
|
const inline = commentRegex.exec(contents);
|
||||||
if (inline !== null) {
|
if (inline !== null) {
|
||||||
return {map: fromComment(inline.pop() !).sourcemap, mapPath: null};
|
return {map: fromComment(inline.pop()!).sourcemap, mapPath: null};
|
||||||
}
|
}
|
||||||
|
|
||||||
const external = mapFileCommentRegex.exec(contents);
|
const external = mapFileCommentRegex.exec(contents);
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom} from '../../src/ngtsc/file_system';
|
|
||||||
|
import {absoluteFrom, AbsoluteFsPath, FileSystem} from '../../src/ngtsc/file_system';
|
||||||
import {KnownDeclaration} from '../../src/ngtsc/reflection';
|
import {KnownDeclaration} from '../../src/ngtsc/reflection';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,11 +38,11 @@ export function getOriginalSymbol(checker: ts.TypeChecker): (symbol: ts.Symbol)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isDefined<T>(value: T | undefined | null): value is T {
|
export function isDefined<T>(value: T|undefined|null): value is T {
|
||||||
return (value !== undefined) && (value !== null);
|
return (value !== undefined) && (value !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getNameText(name: ts.PropertyName | ts.BindingName): string {
|
export function getNameText(name: ts.PropertyName|ts.BindingName): string {
|
||||||
return ts.isIdentifier(name) || ts.isLiteralExpression(name) ? name.text : name.getText();
|
return ts.isIdentifier(name) || ts.isLiteralExpression(name) ? name.text : name.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,10 +112,12 @@ export class FactoryMap<K, V> {
|
||||||
this.internalMap.set(key, this.factory(key));
|
this.internalMap.set(key, this.factory(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.internalMap.get(key) !;
|
return this.internalMap.get(key)!;
|
||||||
}
|
}
|
||||||
|
|
||||||
set(key: K, value: V): void { this.internalMap.set(key, value); }
|
set(key: K, value: V): void {
|
||||||
|
this.internalMap.set(key, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,15 +5,16 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, PathSegment, absoluteFrom} from '../../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, PathSegment} from '../../../../src/ngtsc/file_system';
|
||||||
import {cleanPackageJson} from '../../packages/build_marker';
|
import {cleanPackageJson} from '../../packages/build_marker';
|
||||||
import {NGCC_BACKUP_EXTENSION} from '../in_place_file_writer';
|
import {NGCC_BACKUP_EXTENSION} from '../in_place_file_writer';
|
||||||
import {NGCC_DIRECTORY} from '../new_entry_point_file_writer';
|
import {NGCC_DIRECTORY} from '../new_entry_point_file_writer';
|
||||||
|
|
||||||
import {isLocalDirectory} from './utils';
|
import {isLocalDirectory} from './utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement this interface to extend the cleaning strategies of the `PackageCleaner`.
|
* Implement this interface to extend the cleaning strategies of the `PackageCleaner`.
|
||||||
*/
|
*/
|
||||||
export interface CleaningStrategy {
|
export interface CleaningStrategy {
|
||||||
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean;
|
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean;
|
||||||
clean(path: AbsoluteFsPath, basename: PathSegment): void;
|
clean(path: AbsoluteFsPath, basename: PathSegment): void;
|
||||||
|
@ -44,7 +45,9 @@ export class NgccDirectoryCleaner implements CleaningStrategy {
|
||||||
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean {
|
canClean(path: AbsoluteFsPath, basename: PathSegment): boolean {
|
||||||
return basename === NGCC_DIRECTORY && isLocalDirectory(this.fs, path);
|
return basename === NGCC_DIRECTORY && isLocalDirectory(this.fs, path);
|
||||||
}
|
}
|
||||||
clean(path: AbsoluteFsPath, _basename: PathSegment): void { this.fs.removeDeep(path); }
|
clean(path: AbsoluteFsPath, _basename: PathSegment): void {
|
||||||
|
this.fs.removeDeep(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,11 +5,12 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {FileSystem, absoluteFrom, dirname} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, dirname, FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {EntryPointJsonProperty} from '../packages/entry_point';
|
import {EntryPointJsonProperty} from '../packages/entry_point';
|
||||||
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
import {EntryPointBundle} from '../packages/entry_point_bundle';
|
||||||
import {FileToWrite} from '../rendering/utils';
|
import {FileToWrite} from '../rendering/utils';
|
||||||
|
|
||||||
import {FileWriter} from './file_writer';
|
import {FileWriter} from './file_writer';
|
||||||
|
|
||||||
export const NGCC_BACKUP_EXTENSION = '.__ivy_ngcc_bak';
|
export const NGCC_BACKUP_EXTENSION = '.__ivy_ngcc_bak';
|
||||||
|
@ -37,7 +38,9 @@ export class InPlaceFileWriter implements FileWriter {
|
||||||
`Tried to overwrite ${backPath} with an ngcc back up file, which is disallowed.`);
|
`Tried to overwrite ${backPath} with an ngcc back up file, which is disallowed.`);
|
||||||
} else {
|
} else {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
`Tried to write ${backPath} with an ngcc back up file but it already exists so not writing, nor backing up, ${file.path}.\n` +
|
`Tried to write ${
|
||||||
|
backPath} with an ngcc back up file but it already exists so not writing, nor backing up, ${
|
||||||
|
file.path}.\n` +
|
||||||
`This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` +
|
`This error may be because two or more entry-points overlap and ngcc has been asked to process some files more than once.\n` +
|
||||||
`You should check other entry-points in this package and set up a config to ignore any that you are not using.`);
|
`You should check other entry-points in this package and set up a config to ignore any that you are not using.`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFromSourceFile, dirname, join, relative} from '../../../src/ngtsc/file_system';
|
import {absoluteFromSourceFile, AbsoluteFsPath, dirname, FileSystem, join, relative} from '../../../src/ngtsc/file_system';
|
||||||
import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
import {isDtsPath} from '../../../src/ngtsc/util/src/typescript';
|
||||||
import {Logger} from '../logging/logger';
|
import {Logger} from '../logging/logger';
|
||||||
import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point';
|
import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point';
|
||||||
|
@ -83,8 +83,8 @@ export class NewEntryPointFileWriter extends InPlaceFileWriter {
|
||||||
const packageJsonPath = join(entryPoint.path, 'package.json');
|
const packageJsonPath = join(entryPoint.path, 'package.json');
|
||||||
|
|
||||||
// All format properties point to the same format-path.
|
// All format properties point to the same format-path.
|
||||||
const oldFormatProp = formatProperties[0] !;
|
const oldFormatProp = formatProperties[0]!;
|
||||||
const oldFormatPath = packageJson[oldFormatProp] !;
|
const oldFormatPath = packageJson[oldFormatProp]!;
|
||||||
const oldAbsFormatPath = join(entryPoint.path, oldFormatPath);
|
const oldAbsFormatPath = join(entryPoint.path, oldFormatPath);
|
||||||
const newAbsFormatPath = join(ngccFolder, relative(entryPoint.package, oldAbsFormatPath));
|
const newAbsFormatPath = join(ngccFolder, relative(entryPoint.package, oldAbsFormatPath));
|
||||||
const newFormatPath = relative(entryPoint.path, newAbsFormatPath);
|
const newFormatPath = relative(entryPoint.path, newAbsFormatPath);
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {AbsoluteFsPath, FileSystem, dirname} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, dirname, FileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {JsonObject, JsonValue} from '../packages/entry_point';
|
import {JsonObject, JsonValue} from '../packages/entry_point';
|
||||||
|
|
||||||
|
|
||||||
export type PackageJsonChange = [string[], JsonValue, PackageJsonPropertyPositioning];
|
export type PackageJsonChange = [string[], JsonValue, PackageJsonPropertyPositioning];
|
||||||
export type PackageJsonPropertyPositioning = 'unimportant' | 'alphabetic' | {before: string};
|
export type PackageJsonPropertyPositioning = 'unimportant'|'alphabetic'|{before: string};
|
||||||
export type WritePackageJsonChangesFn =
|
export type WritePackageJsonChangesFn =
|
||||||
(changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject) =>
|
(changes: PackageJsonChange[], packageJsonPath: AbsoluteFsPath, parsedJson?: JsonObject) =>
|
||||||
void;
|
void;
|
||||||
|
|
|
@ -9,7 +9,7 @@ import * as ts from 'typescript';
|
||||||
|
|
||||||
import {FatalDiagnosticError, makeDiagnostic} from '../../../src/ngtsc/diagnostics';
|
import {FatalDiagnosticError, makeDiagnostic} from '../../../src/ngtsc/diagnostics';
|
||||||
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection';
|
import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection';
|
||||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform';
|
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../../src/ngtsc/transform';
|
||||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||||
|
@ -21,7 +21,7 @@ import {Migration, MigrationHost} from '../../src/migrations/migration';
|
||||||
import {MockLogger} from '../helpers/mock_logger';
|
import {MockLogger} from '../helpers/mock_logger';
|
||||||
import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils';
|
import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils';
|
||||||
|
|
||||||
type DecoratorHandlerWithResolve = DecoratorHandler<unknown, unknown, unknown>& {
|
type DecoratorHandlerWithResolve = DecoratorHandler<unknown, unknown, unknown>&{
|
||||||
resolve: NonNullable<DecoratorHandler<unknown, unknown, unknown>['resolve']>;
|
resolve: NonNullable<DecoratorHandler<unknown, unknown, unknown>['resolve']>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ runInEachFileSystem(() => {
|
||||||
describe('DecorationAnalyzer', () => {
|
describe('DecorationAnalyzer', () => {
|
||||||
let _: typeof absoluteFrom;
|
let _: typeof absoluteFrom;
|
||||||
|
|
||||||
beforeEach(() => { _ = absoluteFrom; });
|
beforeEach(() => {
|
||||||
|
_ = absoluteFrom;
|
||||||
|
});
|
||||||
|
|
||||||
describe('analyzeProgram()', () => {
|
describe('analyzeProgram()', () => {
|
||||||
let logs: string[];
|
let logs: string[];
|
||||||
|
@ -50,7 +52,7 @@ runInEachFileSystem(() => {
|
||||||
]);
|
]);
|
||||||
// Only detect the Component and Directive decorators
|
// Only detect the Component and Directive decorators
|
||||||
handler.detect.and.callFake(
|
handler.detect.and.callFake(
|
||||||
(node: ts.Declaration, decorators: Decorator[] | null): DetectResult<unknown>|
|
(node: ts.Declaration, decorators: Decorator[]|null): DetectResult<unknown>|
|
||||||
undefined => {
|
undefined => {
|
||||||
const className = (node as any).name.text;
|
const className = (node as any).name.text;
|
||||||
if (decorators === null) {
|
if (decorators === null) {
|
||||||
|
@ -94,17 +96,17 @@ runInEachFileSystem(() => {
|
||||||
// The "test" compilation result is just the name of the decorator being compiled
|
// The "test" compilation result is just the name of the decorator being compiled
|
||||||
// (suffixed with `(compiled)`)
|
// (suffixed with `(compiled)`)
|
||||||
handler.compile.and.callFake((decl: ts.Declaration, analysis: any) => {
|
handler.compile.and.callFake((decl: ts.Declaration, analysis: any) => {
|
||||||
logs.push(
|
logs.push(`compile: ${(decl as any).name.text}@${analysis.decoratorName} (resolved: ${
|
||||||
`compile: ${(decl as any).name.text}@${analysis.decoratorName} (resolved: ${analysis.resolved})`);
|
analysis.resolved})`);
|
||||||
return `@${analysis.decoratorName} (compiled)`;
|
return `@${analysis.decoratorName} (compiled)`;
|
||||||
});
|
});
|
||||||
return handler;
|
return handler;
|
||||||
};
|
};
|
||||||
|
|
||||||
function setUpAnalyzer(
|
function setUpAnalyzer(testFiles: TestFile[], options: {
|
||||||
testFiles: TestFile[],
|
analyzeError: boolean,
|
||||||
options: {analyzeError: boolean,
|
resolveError: boolean
|
||||||
resolveError: boolean} = {analyzeError: false, resolveError: false}) {
|
} = {analyzeError: false, resolveError: false}) {
|
||||||
logs = [];
|
logs = [];
|
||||||
loadTestFiles(testFiles);
|
loadTestFiles(testFiles);
|
||||||
loadFakeCore(getFileSystem());
|
loadFakeCore(getFileSystem());
|
||||||
|
@ -173,9 +175,9 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
it('should return an object containing a reference to the original source file', () => {
|
it('should return an object containing a reference to the original source file', () => {
|
||||||
const testFile = getSourceFileOrError(program, _('/node_modules/test-package/test.js'));
|
const testFile = getSourceFileOrError(program, _('/node_modules/test-package/test.js'));
|
||||||
expect(result.get(testFile) !.sourceFile).toBe(testFile);
|
expect(result.get(testFile)!.sourceFile).toBe(testFile);
|
||||||
const otherFile = getSourceFileOrError(program, _('/node_modules/test-package/other.js'));
|
const otherFile = getSourceFileOrError(program, _('/node_modules/test-package/other.js'));
|
||||||
expect(result.get(otherFile) !.sourceFile).toBe(otherFile);
|
expect(result.get(otherFile)!.sourceFile).toBe(otherFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call detect on the decorator handlers with each class from the parsed file',
|
it('should call detect on the decorator handlers with each class from the parsed file',
|
||||||
|
@ -192,20 +194,23 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
it('should return an object containing the classes that were analyzed', () => {
|
it('should return an object containing the classes that were analyzed', () => {
|
||||||
const file1 = getSourceFileOrError(program, _('/node_modules/test-package/test.js'));
|
const file1 = getSourceFileOrError(program, _('/node_modules/test-package/test.js'));
|
||||||
const compiledFile1 = result.get(file1) !;
|
const compiledFile1 = result.get(file1)!;
|
||||||
expect(compiledFile1.compiledClasses.length).toEqual(2);
|
expect(compiledFile1.compiledClasses.length).toEqual(2);
|
||||||
expect(compiledFile1.compiledClasses[0]).toEqual(jasmine.objectContaining({
|
expect(compiledFile1.compiledClasses[0]).toEqual(jasmine.objectContaining({
|
||||||
name: 'MyComponent', compilation: ['@Component (compiled)'],
|
name: 'MyComponent',
|
||||||
|
compilation: ['@Component (compiled)'],
|
||||||
} as unknown as CompiledClass));
|
} as unknown as CompiledClass));
|
||||||
expect(compiledFile1.compiledClasses[1]).toEqual(jasmine.objectContaining({
|
expect(compiledFile1.compiledClasses[1]).toEqual(jasmine.objectContaining({
|
||||||
name: 'MyDirective', compilation: ['@Directive (compiled)'],
|
name: 'MyDirective',
|
||||||
|
compilation: ['@Directive (compiled)'],
|
||||||
} as unknown as CompiledClass));
|
} as unknown as CompiledClass));
|
||||||
|
|
||||||
const file2 = getSourceFileOrError(program, _('/node_modules/test-package/other.js'));
|
const file2 = getSourceFileOrError(program, _('/node_modules/test-package/other.js'));
|
||||||
const compiledFile2 = result.get(file2) !;
|
const compiledFile2 = result.get(file2)!;
|
||||||
expect(compiledFile2.compiledClasses.length).toEqual(1);
|
expect(compiledFile2.compiledClasses.length).toEqual(1);
|
||||||
expect(compiledFile2.compiledClasses[0]).toEqual(jasmine.objectContaining({
|
expect(compiledFile2.compiledClasses[0]).toEqual(jasmine.objectContaining({
|
||||||
name: 'MyOtherComponent', compilation: ['@Component (compiled)'],
|
name: 'MyOtherComponent',
|
||||||
|
compilation: ['@Component (compiled)'],
|
||||||
} as unknown as CompiledClass));
|
} as unknown as CompiledClass));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -284,18 +289,18 @@ runInEachFileSystem(() => {
|
||||||
() => {
|
() => {
|
||||||
const file =
|
const file =
|
||||||
getSourceFileOrError(program, _('/node_modules/test-package/component.js'));
|
getSourceFileOrError(program, _('/node_modules/test-package/component.js'));
|
||||||
const analysis = result.get(file) !;
|
const analysis = result.get(file)!;
|
||||||
expect(analysis).toBeDefined();
|
expect(analysis).toBeDefined();
|
||||||
const ImportedComponent =
|
const ImportedComponent =
|
||||||
analysis.compiledClasses.find(f => f.name === 'ImportedComponent') !;
|
analysis.compiledClasses.find(f => f.name === 'ImportedComponent')!;
|
||||||
expect(ImportedComponent).toBeDefined();
|
expect(ImportedComponent).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should analyze an internally defined component, which is not exported at all', () => {
|
it('should analyze an internally defined component, which is not exported at all', () => {
|
||||||
const file = getSourceFileOrError(program, _('/node_modules/test-package/entrypoint.js'));
|
const file = getSourceFileOrError(program, _('/node_modules/test-package/entrypoint.js'));
|
||||||
const analysis = result.get(file) !;
|
const analysis = result.get(file)!;
|
||||||
expect(analysis).toBeDefined();
|
expect(analysis).toBeDefined();
|
||||||
const LocalComponent = analysis.compiledClasses.find(f => f.name === 'LocalComponent') !;
|
const LocalComponent = analysis.compiledClasses.find(f => f.name === 'LocalComponent')!;
|
||||||
expect(LocalComponent).toBeDefined();
|
expect(LocalComponent).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -341,7 +346,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore classes from an externally imported file', () => {
|
it('should ignore classes from an externally imported file', () => {
|
||||||
const file = program.getSourceFile(_('/node_modules/other/component.js')) !;
|
const file = program.getSourceFile(_('/node_modules/other/component.js'))!;
|
||||||
expect(result.has(file)).toBe(false);
|
expect(result.has(file)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -427,11 +432,15 @@ runInEachFileSystem(() => {
|
||||||
name = 'FakeDecoratorHandler';
|
name = 'FakeDecoratorHandler';
|
||||||
precedence = HandlerPrecedence.PRIMARY;
|
precedence = HandlerPrecedence.PRIMARY;
|
||||||
|
|
||||||
detect(): undefined { throw new Error('detect should not have been called'); }
|
detect(): undefined {
|
||||||
|
throw new Error('detect should not have been called');
|
||||||
|
}
|
||||||
analyze(): AnalysisOutput<unknown> {
|
analyze(): AnalysisOutput<unknown> {
|
||||||
throw new Error('analyze should not have been called');
|
throw new Error('analyze should not have been called');
|
||||||
}
|
}
|
||||||
compile(): CompileResult { throw new Error('compile should not have been called'); }
|
compile(): CompileResult {
|
||||||
|
throw new Error('compile should not have been called');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const analyzer = setUpAnalyzer([{
|
const analyzer = setUpAnalyzer([{
|
||||||
|
|
|
@ -62,7 +62,7 @@ runInEachFileSystem(() => {
|
||||||
const {host, compiler} = createMigrationHost({entryPoint, handlers: [handler]});
|
const {host, compiler} = createMigrationHost({entryPoint, handlers: [handler]});
|
||||||
host.injectSyntheticDecorator(mockClazz, injectedDecorator);
|
host.injectSyntheticDecorator(mockClazz, injectedDecorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(mockClazz) !;
|
const record = compiler.recordFor(mockClazz)!;
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record.traits.length).toBe(1);
|
expect(record.traits.length).toBe(1);
|
||||||
expect(record.traits[0].detected.decorator).toBe(injectedDecorator);
|
expect(record.traits[0].detected.decorator).toBe(injectedDecorator);
|
||||||
|
@ -77,7 +77,7 @@ runInEachFileSystem(() => {
|
||||||
const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null});
|
const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null});
|
||||||
host.injectSyntheticDecorator(mockClazz, decorator);
|
host.injectSyntheticDecorator(mockClazz, decorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(mockClazz) !;
|
const record = compiler.recordFor(mockClazz)!;
|
||||||
const migratedTrait = record.traits[0];
|
const migratedTrait = record.traits[0];
|
||||||
if (migratedTrait.state !== TraitState.ERRORED) {
|
if (migratedTrait.state !== TraitState.ERRORED) {
|
||||||
return fail('Expected migrated class trait to be in an error state');
|
return fail('Expected migrated class trait to be in an error state');
|
||||||
|
@ -120,7 +120,7 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
host.injectSyntheticDecorator(myClass, injectedDecorator);
|
host.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const decorators = host.getAllDecorators(myClass) !;
|
const decorators = host.getAllDecorators(myClass)!;
|
||||||
expect(decorators.length).toBe(2);
|
expect(decorators.length).toBe(2);
|
||||||
expect(decorators[0].name).toBe('Directive');
|
expect(decorators[0].name).toBe('Directive');
|
||||||
expect(decorators[1].name).toBe('InjectedDecorator');
|
expect(decorators[1].name).toBe('InjectedDecorator');
|
||||||
|
@ -183,9 +183,13 @@ class DetectDecoratorHandler implements DecoratorHandler<unknown, unknown, unkno
|
||||||
return {trigger: node, decorator, metadata: {}};
|
return {trigger: node, decorator, metadata: {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
analyze(node: ClassDeclaration): AnalysisOutput<unknown> { return {}; }
|
analyze(node: ClassDeclaration): AnalysisOutput<unknown> {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
compile(node: ClassDeclaration): CompileResult|CompileResult[] { return []; }
|
compile(node: ClassDeclaration): CompileResult|CompileResult[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, unknown> {
|
class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, unknown> {
|
||||||
|
@ -201,5 +205,7 @@ class DiagnosticProducingHandler implements DecoratorHandler<unknown, unknown, u
|
||||||
return {diagnostics: [makeDiagnostic(9999, node, 'test diagnostic')]};
|
return {diagnostics: [makeDiagnostic(9999, node, 'test diagnostic')]};
|
||||||
}
|
}
|
||||||
|
|
||||||
compile(node: ClassDeclaration): CompileResult|CompileResult[] { return []; }
|
compile(node: ClassDeclaration): CompileResult|CompileResult[] {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer';
|
import {ModuleWithProvidersAnalyses, ModuleWithProvidersAnalyzer} from '../../src/analysis/module_with_providers_analyzer';
|
||||||
|
@ -333,7 +333,7 @@ runInEachFileSystem(() => {
|
||||||
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
||||||
getRootFiles(TEST_DTS_PROGRAM));
|
getRootFiles(TEST_DTS_PROGRAM));
|
||||||
program = bundle.src.program;
|
program = bundle.src.program;
|
||||||
dtsProgram = bundle.dts !;
|
dtsProgram = bundle.dts!;
|
||||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram);
|
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram);
|
||||||
referencesRegistry = new NgccReferencesRegistry(host);
|
referencesRegistry = new NgccReferencesRegistry(host);
|
||||||
|
|
||||||
|
@ -367,8 +367,8 @@ runInEachFileSystem(() => {
|
||||||
const libraryModuleDeclaration = getDeclaration(
|
const libraryModuleDeclaration = getDeclaration(
|
||||||
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
||||||
ts.isClassDeclaration);
|
ts.isClassDeclaration);
|
||||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
expect(declarations.has(externalModuleDeclaration.name!)).toBe(true);
|
||||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find declarations that have implicit return types', () => {
|
it('should find declarations that have implicit return types', () => {
|
||||||
|
@ -414,11 +414,10 @@ runInEachFileSystem(() => {
|
||||||
analyses: ModuleWithProvidersAnalyses, fileName: AbsoluteFsPath) {
|
analyses: ModuleWithProvidersAnalyses, fileName: AbsoluteFsPath) {
|
||||||
const file = getSourceFileOrError(dtsProgram.program, fileName);
|
const file = getSourceFileOrError(dtsProgram.program, fileName);
|
||||||
const analysis = analyses.get(file);
|
const analysis = analyses.get(file);
|
||||||
return analysis ?
|
return analysis ? analysis.map(
|
||||||
analysis.map(
|
|
||||||
info =>
|
info =>
|
||||||
[info.declaration.name !.getText(),
|
[info.declaration.name!.getText(),
|
||||||
(info.ngModule.node as ts.ClassDeclaration).name !.getText(),
|
(info.ngModule.node as ts.ClassDeclaration).name!.getText(),
|
||||||
info.ngModule.viaModule]) :
|
info.ngModule.viaModule]) :
|
||||||
[];
|
[];
|
||||||
}
|
}
|
||||||
|
@ -536,7 +535,7 @@ runInEachFileSystem(() => {
|
||||||
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
'test-package', 'esm2015', false, getRootFiles(TEST_PROGRAM),
|
||||||
getRootFiles(TEST_DTS_PROGRAM));
|
getRootFiles(TEST_DTS_PROGRAM));
|
||||||
const program = bundle.src.program;
|
const program = bundle.src.program;
|
||||||
const dtsProgram = bundle.dts !;
|
const dtsProgram = bundle.dts!;
|
||||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram);
|
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle.src, dtsProgram);
|
||||||
const referencesRegistry = new NgccReferencesRegistry(host);
|
const referencesRegistry = new NgccReferencesRegistry(host);
|
||||||
|
|
||||||
|
@ -558,9 +557,9 @@ runInEachFileSystem(() => {
|
||||||
const libraryModuleDeclaration = getDeclaration(
|
const libraryModuleDeclaration = getDeclaration(
|
||||||
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
||||||
ts.isClassDeclaration);
|
ts.isClassDeclaration);
|
||||||
expect(declarations.has(explicitInternalModuleDeclaration.name !)).toBe(true);
|
expect(declarations.has(explicitInternalModuleDeclaration.name!)).toBe(true);
|
||||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
expect(declarations.has(externalModuleDeclaration.name!)).toBe(true);
|
||||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should track references even when typings have already been processed', () => {
|
it('should track references even when typings have already been processed', () => {
|
||||||
|
@ -586,9 +585,9 @@ runInEachFileSystem(() => {
|
||||||
const libraryModuleDeclaration = getDeclaration(
|
const libraryModuleDeclaration = getDeclaration(
|
||||||
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
program, absoluteFrom('/node_modules/some-library/index.d.ts'), 'LibraryModule',
|
||||||
ts.isClassDeclaration);
|
ts.isClassDeclaration);
|
||||||
expect(declarations.has(explicitInternalModuleDeclaration.name !)).toBe(true);
|
expect(declarations.has(explicitInternalModuleDeclaration.name!)).toBe(true);
|
||||||
expect(declarations.has(externalModuleDeclaration.name !)).toBe(true);
|
expect(declarations.has(externalModuleDeclaration.name!)).toBe(true);
|
||||||
expect(declarations.has(libraryModuleDeclaration.name !)).toBe(false);
|
expect(declarations.has(libraryModuleDeclaration.name!)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -91,7 +91,7 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
const record = compiler.recordFor(mockClazz);
|
const record = compiler.recordFor(mockClazz);
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record !.traits.length).toBe(1);
|
expect(record!.traits.length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add a new trait to an existing class record', () => {
|
it('should add a new trait to an existing class record', () => {
|
||||||
|
@ -118,11 +118,11 @@ runInEachFileSystem(() => {
|
||||||
compiler.analyzeFile(entryPoint.src.file);
|
compiler.analyzeFile(entryPoint.src.file);
|
||||||
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(myClass) !;
|
const record = compiler.recordFor(myClass)!;
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record.traits.length).toBe(2);
|
expect(record.traits.length).toBe(2);
|
||||||
expect(record.traits[0].detected.decorator !.name).toBe('Directive');
|
expect(record.traits[0].detected.decorator!.name).toBe('Directive');
|
||||||
expect(record.traits[1].detected.decorator !.name).toBe('InjectedDecorator');
|
expect(record.traits[1].detected.decorator!.name).toBe('InjectedDecorator');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not add a weak handler when a primary handler already exists', () => {
|
it('should not add a weak handler when a primary handler already exists', () => {
|
||||||
|
@ -150,10 +150,10 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(myClass) !;
|
const record = compiler.recordFor(myClass)!;
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record.traits.length).toBe(1);
|
expect(record.traits.length).toBe(1);
|
||||||
expect(record.traits[0].detected.decorator !.name).toBe('Directive');
|
expect(record.traits[0].detected.decorator!.name).toBe('Directive');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should replace an existing weak handler when injecting a primary handler', () => {
|
it('should replace an existing weak handler when injecting a primary handler', () => {
|
||||||
|
@ -181,10 +181,10 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(myClass) !;
|
const record = compiler.recordFor(myClass)!;
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record.traits.length).toBe(1);
|
expect(record.traits.length).toBe(1);
|
||||||
expect(record.traits[0].detected.decorator !.name).toBe('InjectedDecorator');
|
expect(record.traits[0].detected.decorator!.name).toBe('InjectedDecorator');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should produce an error when a primary handler is added when a primary handler is already present',
|
it('should produce an error when a primary handler is added when a primary handler is already present',
|
||||||
|
@ -214,12 +214,11 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(myClass) !;
|
const record = compiler.recordFor(myClass)!;
|
||||||
expect(record).toBeDefined();
|
expect(record).toBeDefined();
|
||||||
expect(record.metaDiagnostics).toBeDefined();
|
expect(record.metaDiagnostics).toBeDefined();
|
||||||
expect(record.metaDiagnostics !.length).toBe(1);
|
expect(record.metaDiagnostics!.length).toBe(1);
|
||||||
expect(record.metaDiagnostics ![0].code)
|
expect(record.metaDiagnostics![0].code).toBe(ngErrorCode(ErrorCode.DECORATOR_COLLISION));
|
||||||
.toBe(ngErrorCode(ErrorCode.DECORATOR_COLLISION));
|
|
||||||
expect(record.traits.length).toBe(0);
|
expect(record.traits.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -233,7 +232,7 @@ runInEachFileSystem(() => {
|
||||||
const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null});
|
const decorator = createComponentDecorator(mockClazz, {selector: 'comp', exportAs: null});
|
||||||
compiler.injectSyntheticDecorator(mockClazz, decorator);
|
compiler.injectSyntheticDecorator(mockClazz, decorator);
|
||||||
|
|
||||||
const record = compiler.recordFor(mockClazz) !;
|
const record = compiler.recordFor(mockClazz)!;
|
||||||
const migratedTrait = record.traits[0];
|
const migratedTrait = record.traits[0];
|
||||||
if (migratedTrait.state !== TraitState.ERRORED) {
|
if (migratedTrait.state !== TraitState.ERRORED) {
|
||||||
return fail('Expected migrated class trait to be in an error state');
|
return fail('Expected migrated class trait to be in an error state');
|
||||||
|
@ -286,13 +285,12 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
compiler.injectSyntheticDecorator(myClass, injectedDecorator);
|
||||||
|
|
||||||
const decorators = compiler.getAllDecorators(myClass) !;
|
const decorators = compiler.getAllDecorators(myClass)!;
|
||||||
expect(decorators.length).toBe(2);
|
expect(decorators.length).toBe(2);
|
||||||
expect(decorators[0].name).toBe('Directive');
|
expect(decorators[0].name).toBe('Directive');
|
||||||
expect(decorators[1].name).toBe('InjectedDecorator');
|
expect(decorators[1].name).toBe('InjectedDecorator');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -302,7 +300,7 @@ class TestHandler implements DecoratorHandler<unknown, unknown, unknown> {
|
||||||
precedence = HandlerPrecedence.PRIMARY;
|
precedence = HandlerPrecedence.PRIMARY;
|
||||||
|
|
||||||
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined {
|
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<unknown>|undefined {
|
||||||
this.log.push(`${this.name}:detect:${node.name.text}:${decorators !.map(d => d.name)}`);
|
this.log.push(`${this.name}:detect:${node.name.text}:${decorators!.map(d => d.name)}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {Reference} from '../../../src/ngtsc/imports';
|
import {Reference} from '../../../src/ngtsc/imports';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers/src/mock_file_loading';
|
import {loadTestFiles} from '../../../test/helpers/src/mock_file_loading';
|
||||||
|
@ -192,6 +192,6 @@ runInEachFileSystem(() => {
|
||||||
program: ts.Program, registry: NgccReferencesRegistry, fileName: AbsoluteFsPath,
|
program: ts.Program, registry: NgccReferencesRegistry, fileName: AbsoluteFsPath,
|
||||||
componentName: string) {
|
componentName: string) {
|
||||||
const declaration = getDeclaration(program, fileName, componentName, ts.isClassDeclaration);
|
const declaration = getDeclaration(program, fileName, componentName, ts.isClassDeclaration);
|
||||||
registry.add(null !, new Reference(declaration));
|
registry.add(null!, new Reference(declaration));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {Reference} from '../../../src/ngtsc/imports';
|
import {Reference} from '../../../src/ngtsc/imports';
|
||||||
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
||||||
import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection';
|
import {TypeScriptReflectionHost} from '../../../src/ngtsc/reflection';
|
||||||
|
@ -44,19 +44,19 @@ runInEachFileSystem(() => {
|
||||||
getDeclaration(program, indexPath, 'someFunction', ts.isFunctionDeclaration);
|
getDeclaration(program, indexPath, 'someFunction', ts.isFunctionDeclaration);
|
||||||
const someVariableDecl =
|
const someVariableDecl =
|
||||||
getDeclaration(program, indexPath, 'someVariable', ts.isVariableDeclaration);
|
getDeclaration(program, indexPath, 'someVariable', ts.isVariableDeclaration);
|
||||||
const testArrayExpression = testArrayDeclaration.initializer !;
|
const testArrayExpression = testArrayDeclaration.initializer!;
|
||||||
|
|
||||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||||
const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null);
|
const evaluator = new PartialEvaluator(reflectionHost, checker, /* dependencyTracker */ null);
|
||||||
const registry = new NgccReferencesRegistry(reflectionHost);
|
const registry = new NgccReferencesRegistry(reflectionHost);
|
||||||
|
|
||||||
const references = (evaluator.evaluate(testArrayExpression) as any[]).filter(isReference);
|
const references = (evaluator.evaluate(testArrayExpression) as any[]).filter(isReference);
|
||||||
registry.add(null !, ...references);
|
registry.add(null!, ...references);
|
||||||
|
|
||||||
const map = registry.getDeclarationMap();
|
const map = registry.getDeclarationMap();
|
||||||
expect(map.size).toEqual(2);
|
expect(map.size).toEqual(2);
|
||||||
expect(map.get(someClassDecl.name !) !.node).toBe(someClassDecl);
|
expect(map.get(someClassDecl.name!)!.node).toBe(someClassDecl);
|
||||||
expect(map.get(someFunctionDecl.name !) !.node).toBe(someFunctionDecl);
|
expect(map.get(someFunctionDecl.name!)!.node).toBe(someFunctionDecl);
|
||||||
expect(map.has(someVariableDecl.name as ts.Identifier)).toBe(false);
|
expect(map.has(someVariableDecl.name as ts.Identifier)).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
|
import {SwitchMarkerAnalyzer} from '../../src/analysis/switch_marker_analyzer';
|
||||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||||
|
@ -15,7 +15,6 @@ import {makeTestEntryPointBundle} from '../helpers/utils';
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
describe('SwitchMarkerAnalyzer', () => {
|
describe('SwitchMarkerAnalyzer', () => {
|
||||||
|
|
||||||
let _: typeof absoluteFrom;
|
let _: typeof absoluteFrom;
|
||||||
let TEST_PROGRAM: TestFile[];
|
let TEST_PROGRAM: TestFile[];
|
||||||
|
|
||||||
|
@ -87,14 +86,14 @@ runInEachFileSystem(() => {
|
||||||
expect(analysis.has(entrypoint)).toBe(false);
|
expect(analysis.has(entrypoint)).toBe(false);
|
||||||
expect(analysis.has(a)).toBe(false);
|
expect(analysis.has(a)).toBe(false);
|
||||||
expect(analysis.has(b)).toBe(true);
|
expect(analysis.has(b)).toBe(true);
|
||||||
expect(analysis.get(b) !.sourceFile).toBe(b);
|
expect(analysis.get(b)!.sourceFile).toBe(b);
|
||||||
expect(analysis.get(b) !.declarations.map(decl => decl.getText())).toEqual([
|
expect(analysis.get(b)!.declarations.map(decl => decl.getText())).toEqual([
|
||||||
'factoryB = factory__PRE_R3__'
|
'factoryB = factory__PRE_R3__'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
expect(analysis.has(c)).toBe(true);
|
expect(analysis.has(c)).toBe(true);
|
||||||
expect(analysis.get(c) !.sourceFile).toBe(c);
|
expect(analysis.get(c)!.sourceFile).toBe(c);
|
||||||
expect(analysis.get(c) !.declarations.map(decl => decl.getText())).toEqual([
|
expect(analysis.get(c)!.declarations.map(decl => decl.getText())).toEqual([
|
||||||
'factoryC = factory__PRE_R3__',
|
'factoryC = factory__PRE_R3__',
|
||||||
'factoryD = factory__PRE_R3__',
|
'factoryD = factory__PRE_R3__',
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -387,7 +387,7 @@ runInEachFileSystem(() => {
|
||||||
reExportsWithoutRequire?: string[];
|
reExportsWithoutRequire?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function commonJs(importsPerType: ImportsPerType | string[], exportNames: string[] = []): string {
|
function commonJs(importsPerType: ImportsPerType|string[], exportNames: string[] = []): string {
|
||||||
if (Array.isArray(importsPerType)) {
|
if (Array.isArray(importsPerType)) {
|
||||||
importsPerType = {varDeclaration: importsPerType};
|
importsPerType = {varDeclaration: importsPerType};
|
||||||
}
|
}
|
||||||
|
@ -414,8 +414,9 @@ runInEachFileSystem(() => {
|
||||||
} = importsPerType;
|
} = importsPerType;
|
||||||
|
|
||||||
// var foo = require('...');
|
// var foo = require('...');
|
||||||
importsOfTypeVarDeclaration.forEach(
|
importsOfTypeVarDeclaration.forEach(p => {
|
||||||
p => { importStatements.push(`var ${pathToVarName(p)} = require('${p}');`); });
|
importStatements.push(`var ${pathToVarName(p)} = require('${p}');`);
|
||||||
|
});
|
||||||
|
|
||||||
// var foo = require('...'), bar = require('...');
|
// var foo = require('...'), bar = require('...');
|
||||||
importsOfTypeVarDeclarations.forEach(pp => {
|
importsOfTypeVarDeclarations.forEach(pp => {
|
||||||
|
@ -424,8 +425,9 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// exports.foo = require('...');
|
// exports.foo = require('...');
|
||||||
importsOfTypePropAssignment.forEach(
|
importsOfTypePropAssignment.forEach(p => {
|
||||||
p => { importStatements.push(`exports.${pathToVarName(p)} = require('${p}');`); });
|
importStatements.push(`exports.${pathToVarName(p)} = require('${p}');`);
|
||||||
|
});
|
||||||
|
|
||||||
// module.exports = {foo: require('...')};
|
// module.exports = {foo: require('...')};
|
||||||
const propAssignments =
|
const propAssignments =
|
||||||
|
@ -434,15 +436,19 @@ runInEachFileSystem(() => {
|
||||||
importStatements.push(`module.exports = {${propAssignments}\n};`);
|
importStatements.push(`module.exports = {${propAssignments}\n};`);
|
||||||
|
|
||||||
// require('...');
|
// require('...');
|
||||||
importsOfTypeForSideEffects.forEach(p => { importStatements.push(`require('${p}');`); });
|
importsOfTypeForSideEffects.forEach(p => {
|
||||||
|
importStatements.push(`require('${p}');`);
|
||||||
|
});
|
||||||
|
|
||||||
// __export(require('...'));
|
// __export(require('...'));
|
||||||
importsOfTypeReExportsWithEmittedHelper.forEach(
|
importsOfTypeReExportsWithEmittedHelper.forEach(p => {
|
||||||
p => { importStatements.push(`__export(require('${p}'));`); });
|
importStatements.push(`__export(require('${p}'));`);
|
||||||
|
});
|
||||||
|
|
||||||
// tslib_1.__exportStar(require('...'), exports);
|
// tslib_1.__exportStar(require('...'), exports);
|
||||||
importsOfTypeReExportsWithImportedHelper.forEach(
|
importsOfTypeReExportsWithImportedHelper.forEach(p => {
|
||||||
p => { importStatements.push(`tslib_1.__exportStar(require('${p}'), exports);`); });
|
importStatements.push(`tslib_1.__exportStar(require('${p}'), exports);`);
|
||||||
|
});
|
||||||
|
|
||||||
// var foo = require('...');
|
// var foo = require('...');
|
||||||
// __export(foo);
|
// __export(foo);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import {DepGraph} from 'dependency-graph';
|
import {DepGraph} from 'dependency-graph';
|
||||||
|
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relativeFrom} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relativeFrom} from '../../../src/ngtsc/file_system';
|
||||||
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {DependencyInfo} from '../../src/dependencies/dependency_host';
|
import {DependencyInfo} from '../../src/dependencies/dependency_host';
|
||||||
import {DependencyResolver, SortedEntryPointsInfo} from '../../src/dependencies/dependency_resolver';
|
import {DependencyResolver, SortedEntryPointsInfo} from '../../src/dependencies/dependency_resolver';
|
||||||
|
@ -254,7 +254,8 @@ runInEachFileSystem(() => {
|
||||||
const result = resolver.sortEntryPointsByDependency([first]);
|
const result = resolver.sortEntryPointsByDependency([first]);
|
||||||
expect(result.entryPoints).toEqual([first]);
|
expect(result.entryPoints).toEqual([first]);
|
||||||
expect(logger.logs.warn).toEqual([[
|
expect(logger.logs.warn).toEqual([[
|
||||||
`Entry point 'first' contains deep imports into '${_('/deep/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.`
|
`Entry point 'first' contains deep imports into '${
|
||||||
|
_('/deep/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.`
|
||||||
]]);
|
]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -292,14 +293,14 @@ runInEachFileSystem(() => {
|
||||||
const result = resolver.sortEntryPointsByDependency([testEntryPoint]);
|
const result = resolver.sortEntryPointsByDependency([testEntryPoint]);
|
||||||
expect(result.entryPoints).toEqual([testEntryPoint]);
|
expect(result.entryPoints).toEqual([testEntryPoint]);
|
||||||
expect(logger.logs.warn).toEqual([[
|
expect(logger.logs.warn).toEqual([[
|
||||||
`Entry point 'test-package' contains deep imports into '${_('/project/node_modules/deeper/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.`
|
`Entry point 'test-package' contains deep imports into '${
|
||||||
|
_('/project/node_modules/deeper/one')}'. This is probably not a problem, but may cause the compilation of entry points to be out of order.`
|
||||||
]]);
|
]]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should error if the entry point does not have a suitable format', () => {
|
it('should error if the entry point does not have a suitable format', () => {
|
||||||
expect(() => resolver.sortEntryPointsByDependency([
|
expect(() => resolver.sortEntryPointsByDependency([
|
||||||
{ path: '/first', packageJson: {}, compiledByAngular: true } as EntryPoint
|
{path: '/first', packageJson: {}, compiledByAngular: true} as EntryPoint
|
||||||
])).toThrowError(`There is no appropriate source code format in '/first' entry-point.`);
|
])).toThrowError(`There is no appropriate source code format in '/first' entry-point.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -307,7 +308,8 @@ runInEachFileSystem(() => {
|
||||||
resolver = new DependencyResolver(fs, new MockLogger(), config, {esm2015: host}, host);
|
resolver = new DependencyResolver(fs, new MockLogger(), config, {esm2015: host}, host);
|
||||||
expect(() => resolver.sortEntryPointsByDependency([first]))
|
expect(() => resolver.sortEntryPointsByDependency([first]))
|
||||||
.toThrowError(
|
.toThrowError(
|
||||||
`Could not find a suitable format for computing dependencies of entry-point: '${first.path}'.`);
|
`Could not find a suitable format for computing dependencies of entry-point: '${
|
||||||
|
first.path}'.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should capture any dependencies that were ignored', () => {
|
it('should capture any dependencies that were ignored', () => {
|
||||||
|
@ -462,7 +464,7 @@ runInEachFileSystem(() => {
|
||||||
deps[entryPointPath].missing.forEach(
|
deps[entryPointPath].missing.forEach(
|
||||||
dep => missing.add(fs.isRooted(dep) ? absoluteFrom(dep) : relativeFrom(dep)));
|
dep => missing.add(fs.isRooted(dep) ? absoluteFrom(dep) : relativeFrom(dep)));
|
||||||
if (deps[entryPointPath].deepImports) {
|
if (deps[entryPointPath].deepImports) {
|
||||||
deps[entryPointPath].deepImports !.forEach(dep => deepImports.add(dep));
|
deps[entryPointPath].deepImports!.forEach(dep => deepImports.add(dep));
|
||||||
}
|
}
|
||||||
return {dependencies, missing, deepImports};
|
return {dependencies, missing, deepImports};
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,6 @@ import {createDependencyInfo} from '../../src/dependencies/dependency_host';
|
||||||
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
|
|
||||||
describe('DtsDependencyHost', () => {
|
describe('DtsDependencyHost', () => {
|
||||||
let _: typeof absoluteFrom;
|
let _: typeof absoluteFrom;
|
||||||
let host: DtsDependencyHost;
|
let host: DtsDependencyHost;
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {EsmDependencyHost, hasImportOrReexportStatements, isStringImportOrReexpo
|
||||||
import {ModuleResolver} from '../../src/dependencies/module_resolver';
|
import {ModuleResolver} from '../../src/dependencies/module_resolver';
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
|
|
||||||
describe('EsmDependencyHost', () => {
|
describe('EsmDependencyHost', () => {
|
||||||
let _: typeof absoluteFrom;
|
let _: typeof absoluteFrom;
|
||||||
let host: EsmDependencyHost;
|
let host: EsmDependencyHost;
|
||||||
|
|
|
@ -251,8 +251,10 @@ runInEachFileSystem(() => {
|
||||||
exportNames.map(e => ` exports.${e.replace(/.+\./, '')} = ${e};`).join('\n');
|
exportNames.map(e => ` exports.${e.replace(/.+\./, '')} = ${e};`).join('\n');
|
||||||
return `
|
return `
|
||||||
(function (global, factory) {
|
(function (global, factory) {
|
||||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports${commonJsRequires}) :
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports${
|
||||||
typeof define === 'function' && define.amd ? define('${moduleName}', ['exports'${amdDeps}], factory) :
|
commonJsRequires}) :
|
||||||
|
typeof define === 'function' && define.amd ? define('${moduleName}', ['exports'${
|
||||||
|
amdDeps}], factory) :
|
||||||
(factory(global.${moduleName}${globalParams}));
|
(factory(global.${moduleName}${globalParams}));
|
||||||
}(this, (function (exports${params}) { 'use strict';
|
}(this, (function (exports${params}) { 'use strict';
|
||||||
${exportStatements}
|
${exportStatements}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relative} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relative} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
||||||
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, relative} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, relative} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
import {DependencyResolver} from '../../src/dependencies/dependency_resolver';
|
||||||
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
import {DtsDependencyHost} from '../../src/dependencies/dts_dependency_host';
|
||||||
|
@ -365,7 +365,6 @@ runInEachFileSystem(() => {
|
||||||
basePath: AbsoluteFsPath, entryPoints: EntryPoint[]): [string, string][] {
|
basePath: AbsoluteFsPath, entryPoints: EntryPoint[]): [string, string][] {
|
||||||
return entryPoints.map(x => [relative(basePath, x.package), relative(basePath, x.path)]);
|
return entryPoints.map(x => [relative(basePath, x.package), relative(basePath, x.path)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('targetNeedsProcessingOrCleaning()', () => {
|
describe('targetNeedsProcessingOrCleaning()', () => {
|
||||||
|
|
|
@ -132,9 +132,12 @@ runInEachFileSystem(() => {
|
||||||
fs.resolve(projectDirectory, 'dist-1'),
|
fs.resolve(projectDirectory, 'dist-1'),
|
||||||
]);
|
]);
|
||||||
expect(logger.logs.warn).toEqual([
|
expect(logger.logs.warn).toEqual([
|
||||||
[`The basePath "${fs.resolve(projectDirectory, 'sub-folder/dist-2')}" computed from baseUrl "${projectDirectory}" and path mapping "sub-folder/dist-2" does not exist in the file-system.\n` +
|
[`The basePath "${
|
||||||
|
fs.resolve(projectDirectory, 'sub-folder/dist-2')}" computed from baseUrl "${
|
||||||
|
projectDirectory}" and path mapping "sub-folder/dist-2" does not exist in the file-system.\n` +
|
||||||
`It will not be scanned for entry-points.`],
|
`It will not be scanned for entry-points.`],
|
||||||
[`The basePath "${fs.resolve(projectDirectory, 'libs')}" computed from baseUrl "${projectDirectory}" and path mapping "libs/*" does not exist in the file-system.\n` +
|
[`The basePath "${fs.resolve(projectDirectory, 'libs')}" computed from baseUrl "${
|
||||||
|
projectDirectory}" and path mapping "libs/*" does not exist in the file-system.\n` +
|
||||||
`It will not be scanned for entry-points.`],
|
`It will not be scanned for entry-points.`],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -51,7 +51,7 @@ describe('ClusterExecutor', () => {
|
||||||
describe('(on cluster master)', () => {
|
describe('(on cluster master)', () => {
|
||||||
beforeEach(() => runAsClusterMaster(true));
|
beforeEach(() => runAsClusterMaster(true));
|
||||||
|
|
||||||
it('should log debug info about the executor', async() => {
|
it('should log debug info about the executor', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
await executor.execute(anyFn, anyFn);
|
await executor.execute(anyFn, anyFn);
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ describe('ClusterExecutor', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delegate to `ClusterMaster#run()`', async() => {
|
it('should delegate to `ClusterMaster#run()`', async () => {
|
||||||
const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints');
|
const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints');
|
||||||
const createCompilerFnSpy = jasmine.createSpy('createCompilerFn');
|
const createCompilerFnSpy = jasmine.createSpy('createCompilerFn');
|
||||||
|
|
||||||
|
@ -75,13 +75,13 @@ describe('ClusterExecutor', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call LockFile.write() and LockFile.remove() if master runner completes successfully',
|
it('should call LockFile.write() and LockFile.remove() if master runner completes successfully',
|
||||||
async() => {
|
async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
await executor.execute(anyFn, anyFn);
|
await executor.execute(anyFn, anyFn);
|
||||||
expect(lockFileLog).toEqual(['write()', 'remove()']);
|
expect(lockFileLog).toEqual(['write()', 'remove()']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call LockFile.write() and LockFile.remove() if master runner fails', async() => {
|
it('should call LockFile.write() and LockFile.remove() if master runner fails', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
masterRunSpy.and.returnValue(Promise.reject(new Error('master runner error')));
|
masterRunSpy.and.returnValue(Promise.reject(new Error('master runner error')));
|
||||||
let error = '';
|
let error = '';
|
||||||
|
@ -94,7 +94,7 @@ describe('ClusterExecutor', () => {
|
||||||
expect(lockFileLog).toEqual(['write()', 'remove()']);
|
expect(lockFileLog).toEqual(['write()', 'remove()']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not call master runner if LockFile.write() fails', async() => {
|
it('should not call master runner if LockFile.write() fails', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
spyOn(mockLockFile, 'write').and.callFake(() => {
|
spyOn(mockLockFile, 'write').and.callFake(() => {
|
||||||
lockFileLog.push('write()');
|
lockFileLog.push('write()');
|
||||||
|
@ -114,7 +114,7 @@ describe('ClusterExecutor', () => {
|
||||||
expect(masterRunSpy).not.toHaveBeenCalled();
|
expect(masterRunSpy).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should fail if LockFile.remove() fails', async() => {
|
it('should fail if LockFile.remove() fails', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
spyOn(mockLockFile, 'remove').and.callFake(() => {
|
spyOn(mockLockFile, 'remove').and.callFake(() => {
|
||||||
lockFileLog.push('remove()');
|
lockFileLog.push('remove()');
|
||||||
|
@ -139,14 +139,14 @@ describe('ClusterExecutor', () => {
|
||||||
describe('(on cluster worker)', () => {
|
describe('(on cluster worker)', () => {
|
||||||
beforeEach(() => runAsClusterMaster(false));
|
beforeEach(() => runAsClusterMaster(false));
|
||||||
|
|
||||||
it('should not log debug info about the executor', async() => {
|
it('should not log debug info about the executor', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
await executor.execute(anyFn, anyFn);
|
await executor.execute(anyFn, anyFn);
|
||||||
|
|
||||||
expect(mockLogger.logs.debug).toEqual([]);
|
expect(mockLogger.logs.debug).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should delegate to `ClusterWorker#run()`', async() => {
|
it('should delegate to `ClusterWorker#run()`', async () => {
|
||||||
const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints');
|
const analyzeEntryPointsSpy = jasmine.createSpy('analyzeEntryPoints');
|
||||||
const createCompilerFnSpy = jasmine.createSpy('createCompilerFn');
|
const createCompilerFnSpy = jasmine.createSpy('createCompilerFn');
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ describe('ClusterExecutor', () => {
|
||||||
expect(createCompilerFnSpy).toHaveBeenCalledWith(jasmine.any(Function));
|
expect(createCompilerFnSpy).toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not call LockFile.write() or LockFile.remove()', async() => {
|
it('should not call LockFile.write() or LockFile.remove()', async () => {
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
await executor.execute(anyFn, anyFn);
|
await executor.execute(anyFn, anyFn);
|
||||||
expect(lockFileLog).toEqual([]);
|
expect(lockFileLog).toEqual([]);
|
||||||
|
|
|
@ -39,8 +39,9 @@ runInEachFileSystem(() => {
|
||||||
isMaster => describe(`(on cluster ${isMaster ? 'master' : 'worker'})`, () => {
|
isMaster => describe(`(on cluster ${isMaster ? 'master' : 'worker'})`, () => {
|
||||||
beforeEach(() => runAsClusterMaster(isMaster));
|
beforeEach(() => runAsClusterMaster(isMaster));
|
||||||
|
|
||||||
it('should return a `PackageJsonUpdate` instance',
|
it('should return a `PackageJsonUpdate` instance', () => {
|
||||||
() => { expect(updater.createUpdate()).toEqual(jasmine.any(PackageJsonUpdate)); });
|
expect(updater.createUpdate()).toEqual(jasmine.any(PackageJsonUpdate));
|
||||||
|
});
|
||||||
|
|
||||||
it('should wire up the `PackageJsonUpdate` with its `writeChanges()` method', () => {
|
it('should wire up the `PackageJsonUpdate` with its `writeChanges()` method', () => {
|
||||||
const writeChangesSpy = spyOn(updater, 'writeChanges');
|
const writeChangesSpy = spyOn(updater, 'writeChanges');
|
||||||
|
|
|
@ -60,11 +60,9 @@ describe('ClusterWorker', () => {
|
||||||
|
|
||||||
onTaskCompleted(null as any, TaskProcessingOutcome.Processed, null);
|
onTaskCompleted(null as any, TaskProcessingOutcome.Processed, null);
|
||||||
expect(processSendSpy).toHaveBeenCalledTimes(1);
|
expect(processSendSpy).toHaveBeenCalledTimes(1);
|
||||||
expect(processSendSpy).toHaveBeenCalledWith({
|
expect(processSendSpy)
|
||||||
type: 'task-completed',
|
.toHaveBeenCalledWith(
|
||||||
outcome: TaskProcessingOutcome.Processed,
|
{type: 'task-completed', outcome: TaskProcessingOutcome.Processed, message: null});
|
||||||
message: null
|
|
||||||
});
|
|
||||||
|
|
||||||
processSendSpy.calls.reset();
|
processSendSpy.calls.reset();
|
||||||
|
|
||||||
|
@ -137,7 +135,9 @@ describe('ClusterWorker', () => {
|
||||||
} as unknown as Task;
|
} as unknown as Task;
|
||||||
|
|
||||||
let err: string|Error;
|
let err: string|Error;
|
||||||
compileFnSpy.and.callFake(() => { throw err; });
|
compileFnSpy.and.callFake(() => {
|
||||||
|
throw err;
|
||||||
|
});
|
||||||
|
|
||||||
worker.run();
|
worker.run();
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ import {EntryPoint} from '../../src/packages/entry_point';
|
||||||
*
|
*
|
||||||
* NOTE 1: The first task for each entry-point generates typings (which is similar to what happens
|
* NOTE 1: The first task for each entry-point generates typings (which is similar to what happens
|
||||||
* in the actual code).
|
* in the actual code).
|
||||||
* NOTE 2: The `computeTaskDependencies()` implementation relies on the fact that tasks are sorted in such
|
* NOTE 2: The `computeTaskDependencies()` implementation relies on the fact that tasks are sorted
|
||||||
* a way that a task can only depend upon earlier tasks (i.e. dependencies always come
|
* in such a way that a task can only depend upon earlier tasks (i.e. dependencies always come
|
||||||
* before dependents in the list of tasks).
|
* before dependents in the list of tasks).
|
||||||
* To preserve this attribute, you need to ensure that entry-points will only depend on
|
* To preserve this attribute, you need to ensure that entry-points will only depend on
|
||||||
* entry-points with a lower index. Take this into account when defining `entryPointDeps`.
|
* entry-points with a lower index. Take this into account when defining `entryPointDeps`.
|
||||||
|
@ -52,7 +52,7 @@ export function createTasksAndGraph(
|
||||||
graph.addNode(entryPoint.path);
|
graph.addNode(entryPoint.path);
|
||||||
|
|
||||||
for (let tIdx = 0; tIdx < tasksPerEntryPointCount; tIdx++) {
|
for (let tIdx = 0; tIdx < tasksPerEntryPointCount; tIdx++) {
|
||||||
tasks.push({ entryPoint, formatProperty: `prop-${tIdx}`, processDts: tIdx === 0 } as Task);
|
tasks.push({entryPoint, formatProperty: `prop-${tIdx}`, processDts: tIdx === 0} as Task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,13 @@ describe('SingleProcessExecutor', () => {
|
||||||
executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback);
|
executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback);
|
||||||
});
|
});
|
||||||
|
|
||||||
const noTasks = () => ({ allTasksCompleted: true, getNextTask: () => null } as TaskQueue);
|
const noTasks = () => ({allTasksCompleted: true, getNextTask: () => null} as TaskQueue);
|
||||||
const oneTask = () => {
|
const oneTask = () => {
|
||||||
let tasksCount = 1;
|
let tasksCount = 1;
|
||||||
return <TaskQueue>{
|
return <TaskQueue>{
|
||||||
get allTasksCompleted() { return tasksCount === 0; },
|
get allTasksCompleted() {
|
||||||
|
return tasksCount === 0;
|
||||||
|
},
|
||||||
getNextTask() {
|
getNextTask() {
|
||||||
tasksCount--;
|
tasksCount--;
|
||||||
return {};
|
return {};
|
||||||
|
@ -55,7 +57,9 @@ describe('SingleProcessExecutor', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call LockFile.write() and LockFile.remove() if `analyzeEntryPoints` fails', () => {
|
it('should call LockFile.write() and LockFile.remove() if `analyzeEntryPoints` fails', () => {
|
||||||
const errorFn: () => never = () => { throw new Error('analyze error'); };
|
const errorFn: () => never = () => {
|
||||||
|
throw new Error('analyze error');
|
||||||
|
};
|
||||||
const createCompileFn: () => any = () => undefined;
|
const createCompileFn: () => any = () => undefined;
|
||||||
let error: string = '';
|
let error: string = '';
|
||||||
try {
|
try {
|
||||||
|
@ -68,7 +72,9 @@ describe('SingleProcessExecutor', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call LockFile.write() and LockFile.remove() if `createCompileFn` fails', () => {
|
it('should call LockFile.write() and LockFile.remove() if `createCompileFn` fails', () => {
|
||||||
const createErrorCompileFn: () => any = () => { throw new Error('compile error'); };
|
const createErrorCompileFn: () => any = () => {
|
||||||
|
throw new Error('compile error');
|
||||||
|
};
|
||||||
let error: string = '';
|
let error: string = '';
|
||||||
try {
|
try {
|
||||||
executor.execute(oneTask, createErrorCompileFn);
|
executor.execute(oneTask, createErrorCompileFn);
|
||||||
|
@ -85,7 +91,9 @@ describe('SingleProcessExecutor', () => {
|
||||||
throw new Error('LockFile.write() error');
|
throw new Error('LockFile.write() error');
|
||||||
});
|
});
|
||||||
|
|
||||||
const analyzeFn: () => any = () => { lockFileLog.push('analyzeFn'); };
|
const analyzeFn: () => any = () => {
|
||||||
|
lockFileLog.push('analyzeFn');
|
||||||
|
};
|
||||||
const anyFn: () => any = () => undefined;
|
const anyFn: () => any = () => undefined;
|
||||||
executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback);
|
executor = new SingleProcessExecutorSync(mockLogger, locker, createTaskCompletedCallback);
|
||||||
let error = '';
|
let error = '';
|
||||||
|
|
|
@ -77,9 +77,9 @@ describe('ParallelTaskQueue', () => {
|
||||||
it('should be `true`, when there are no unprocess or in-progress tasks', () => {
|
it('should be `true`, when there are no unprocess or in-progress tasks', () => {
|
||||||
const {queue} = createQueue(3);
|
const {queue} = createQueue(3);
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
const task3 = queue.getNextTask() !;
|
const task3 = queue.getNextTask()!;
|
||||||
expect(queue.allTasksCompleted).toBe(false);
|
expect(queue.allTasksCompleted).toBe(false);
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
|
@ -266,8 +266,8 @@ describe('ParallelTaskQueue', () => {
|
||||||
it('should mark a task as completed', () => {
|
it('should mark a task as completed', () => {
|
||||||
const {queue} = createQueue(2);
|
const {queue} = createQueue(2);
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
expect(queue.allTasksCompleted).toBe(false);
|
expect(queue.allTasksCompleted).toBe(false);
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
|
@ -327,7 +327,7 @@ describe('ParallelTaskQueue', () => {
|
||||||
|
|
||||||
processNextTask(queue2);
|
processNextTask(queue2);
|
||||||
processNextTask(queue2);
|
processNextTask(queue2);
|
||||||
const task = queue2.getNextTask() !;
|
const task = queue2.getNextTask()!;
|
||||||
|
|
||||||
expect(queue2.toString()).toContain(' All tasks completed: false\n');
|
expect(queue2.toString()).toContain(' All tasks completed: false\n');
|
||||||
|
|
||||||
|
@ -344,7 +344,7 @@ describe('ParallelTaskQueue', () => {
|
||||||
' - {entryPoint: entry-point-1, formatProperty: prop-0, processDts: true}\n' +
|
' - {entryPoint: entry-point-1, formatProperty: prop-0, processDts: true}\n' +
|
||||||
' - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n');
|
' - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n');
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' Unprocessed tasks (2): \n' +
|
' Unprocessed tasks (2): \n' +
|
||||||
|
@ -352,7 +352,7 @@ describe('ParallelTaskQueue', () => {
|
||||||
' - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n');
|
' - {entryPoint: entry-point-2, formatProperty: prop-0, processDts: true}\n');
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' Unprocessed tasks (1): \n' +
|
' Unprocessed tasks (1): \n' +
|
||||||
|
@ -367,14 +367,14 @@ describe('ParallelTaskQueue', () => {
|
||||||
const {queue} = createQueue(3);
|
const {queue} = createQueue(3);
|
||||||
expect(queue.toString()).toContain(' In-progress tasks (0): \n');
|
expect(queue.toString()).toContain(' In-progress tasks (0): \n');
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' In-progress tasks (1): \n' +
|
' In-progress tasks (1): \n' +
|
||||||
' - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}\n');
|
' - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}\n');
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' In-progress tasks (1): \n' +
|
' In-progress tasks (1): \n' +
|
||||||
|
|
|
@ -30,12 +30,10 @@ describe('SerialTaskQueue', () => {
|
||||||
const tasks: PartiallyOrderedTasks = [] as any;
|
const tasks: PartiallyOrderedTasks = [] as any;
|
||||||
const graph = new DepGraph<EntryPoint>();
|
const graph = new DepGraph<EntryPoint>();
|
||||||
for (let i = 0; i < taskCount; i++) {
|
for (let i = 0; i < taskCount; i++) {
|
||||||
const entryPoint = {
|
const entryPoint = {name: `entry-point-${i}`, path: `/path/to/entry/point/${i}`} as
|
||||||
name: `entry-point-${i}`,
|
EntryPoint;
|
||||||
path: `/path/to/entry/point/${i}`
|
|
||||||
} as EntryPoint;
|
|
||||||
tasks.push(
|
tasks.push(
|
||||||
{ entryPoint: entryPoint, formatProperty: `prop-${i}`, processDts: i % 2 === 0 } as Task);
|
{entryPoint: entryPoint, formatProperty: `prop-${i}`, processDts: i % 2 === 0} as Task);
|
||||||
graph.addNode(entryPoint.path);
|
graph.addNode(entryPoint.path);
|
||||||
}
|
}
|
||||||
const dependencies = computeTaskDependencies(tasks, graph);
|
const dependencies = computeTaskDependencies(tasks, graph);
|
||||||
|
@ -140,7 +138,7 @@ describe('SerialTaskQueue', () => {
|
||||||
describe('markTaskCompleted()', () => {
|
describe('markTaskCompleted()', () => {
|
||||||
it('should mark a task as completed, so that the next task can be picked', () => {
|
it('should mark a task as completed, so that the next task can be picked', () => {
|
||||||
const {queue} = createQueue(3);
|
const {queue} = createQueue(3);
|
||||||
const task = queue.getNextTask() !;
|
const task = queue.getNextTask()!;
|
||||||
|
|
||||||
expect(() => queue.getNextTask()).toThrow();
|
expect(() => queue.getNextTask()).toThrow();
|
||||||
|
|
||||||
|
@ -174,7 +172,7 @@ describe('SerialTaskQueue', () => {
|
||||||
|
|
||||||
processNextTask(queue2);
|
processNextTask(queue2);
|
||||||
processNextTask(queue2);
|
processNextTask(queue2);
|
||||||
const task = queue2.getNextTask() !;
|
const task = queue2.getNextTask()!;
|
||||||
|
|
||||||
expect(queue2.toString()).toContain(' All tasks completed: false\n');
|
expect(queue2.toString()).toContain(' All tasks completed: false\n');
|
||||||
|
|
||||||
|
@ -191,7 +189,7 @@ describe('SerialTaskQueue', () => {
|
||||||
' - {entryPoint: entry-point-1, formatProperty: prop-1, processDts: false}\n' +
|
' - {entryPoint: entry-point-1, formatProperty: prop-1, processDts: false}\n' +
|
||||||
' - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n');
|
' - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n');
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' Unprocessed tasks (2): \n' +
|
' Unprocessed tasks (2): \n' +
|
||||||
|
@ -199,7 +197,7 @@ describe('SerialTaskQueue', () => {
|
||||||
' - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n');
|
' - {entryPoint: entry-point-2, formatProperty: prop-2, processDts: true}\n');
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' Unprocessed tasks (1): \n' +
|
' Unprocessed tasks (1): \n' +
|
||||||
|
@ -214,14 +212,14 @@ describe('SerialTaskQueue', () => {
|
||||||
const {queue} = createQueue(3);
|
const {queue} = createQueue(3);
|
||||||
expect(queue.toString()).toContain(' In-progress tasks (0): ');
|
expect(queue.toString()).toContain(' In-progress tasks (0): ');
|
||||||
|
|
||||||
const task1 = queue.getNextTask() !;
|
const task1 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' In-progress tasks (1): \n' +
|
' In-progress tasks (1): \n' +
|
||||||
' - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}');
|
' - {entryPoint: entry-point-0, formatProperty: prop-0, processDts: true}');
|
||||||
|
|
||||||
queue.markTaskCompleted(task1);
|
queue.markTaskCompleted(task1);
|
||||||
const task2 = queue.getNextTask() !;
|
const task2 = queue.getNextTask()!;
|
||||||
expect(queue.toString())
|
expect(queue.toString())
|
||||||
.toContain(
|
.toContain(
|
||||||
' In-progress tasks (1): \n' +
|
' In-progress tasks (1): \n' +
|
||||||
|
@ -253,7 +251,7 @@ describe('SerialTaskQueue', () => {
|
||||||
' In-progress tasks (0): ');
|
' In-progress tasks (0): ');
|
||||||
|
|
||||||
processNextTask(queue2);
|
processNextTask(queue2);
|
||||||
const task = queue2.getNextTask() !;
|
const task = queue2.getNextTask()!;
|
||||||
expect(queue2.toString())
|
expect(queue2.toString())
|
||||||
.toBe(
|
.toBe(
|
||||||
'SerialTaskQueue\n' +
|
'SerialTaskQueue\n' +
|
||||||
|
|
|
@ -15,10 +15,14 @@ export class MockLockFile implements LockFile {
|
||||||
constructor(
|
constructor(
|
||||||
fs: FileSystem, private log: string[] = [], public path = fs.resolve('/lockfile'),
|
fs: FileSystem, private log: string[] = [], public path = fs.resolve('/lockfile'),
|
||||||
private pid = '1234') {}
|
private pid = '1234') {}
|
||||||
write() { this.log.push('write()'); }
|
write() {
|
||||||
|
this.log.push('write()');
|
||||||
|
}
|
||||||
read(): string {
|
read(): string {
|
||||||
this.log.push('read()');
|
this.log.push('read()');
|
||||||
return this.pid;
|
return this.pid;
|
||||||
}
|
}
|
||||||
remove() { this.log.push('remove()'); }
|
remove() {
|
||||||
|
this.log.push('remove()');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {LogLevel, Logger} from '../../src/logging/logger';
|
import {Logger, LogLevel} from '../../src/logging/logger';
|
||||||
|
|
||||||
export class MockLogger implements Logger {
|
export class MockLogger implements Logger {
|
||||||
constructor(public level = LogLevel.info) {}
|
constructor(public level = LogLevel.info) {}
|
||||||
|
@ -17,8 +17,16 @@ export class MockLogger implements Logger {
|
||||||
warn: [],
|
warn: [],
|
||||||
error: [],
|
error: [],
|
||||||
};
|
};
|
||||||
debug(...args: string[]) { this.logs.debug.push(args); }
|
debug(...args: string[]) {
|
||||||
info(...args: string[]) { this.logs.info.push(args); }
|
this.logs.debug.push(args);
|
||||||
warn(...args: string[]) { this.logs.warn.push(args); }
|
}
|
||||||
error(...args: string[]) { this.logs.error.push(args); }
|
info(...args: string[]) {
|
||||||
|
this.logs.info.push(args);
|
||||||
|
}
|
||||||
|
warn(...args: string[]) {
|
||||||
|
this.logs.warn.push(args);
|
||||||
|
}
|
||||||
|
error(...args: string[]) {
|
||||||
|
this.logs.error.push(args);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, NgtscCompilerHost, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, getFileSystem, NgtscCompilerHost} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile} from '../../../src/ngtsc/file_system/testing';
|
import {TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {BundleProgram, makeBundleProgram} from '../../src/packages/bundle_program';
|
import {BundleProgram, makeBundleProgram} from '../../src/packages/bundle_program';
|
||||||
import {NgccEntryPointConfig} from '../../src/packages/configuration';
|
import {NgccEntryPointConfig} from '../../src/packages/configuration';
|
||||||
|
@ -49,7 +49,12 @@ export function makeTestEntryPointBundle(
|
||||||
return {
|
return {
|
||||||
entryPoint,
|
entryPoint,
|
||||||
format,
|
format,
|
||||||
rootDirs: [absoluteFrom('/')], src, dts, isCore, isFlatCore, enableI18nLegacyMessageIdFormat
|
rootDirs: [absoluteFrom('/')],
|
||||||
|
src,
|
||||||
|
dts,
|
||||||
|
isCore,
|
||||||
|
isFlatCore,
|
||||||
|
enableI18nLegacyMessageIdFormat
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
import {isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||||
|
@ -90,15 +90,15 @@ exports.AliasedDirective$1 = AliasedDirective$1;
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective',
|
bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('core.Directive');
|
expect(decorator.identifier!.getText()).toEqual('core.Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -111,15 +111,15 @@ exports.AliasedDirective$1 = AliasedDirective$1;
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'AliasedDirective$1',
|
bundle.program, TOPLEVEL_DECORATORS_FILE.name, 'AliasedDirective$1',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('core.Directive');
|
expect(decorator.identifier!.getText()).toEqual('core.Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {ClassMemberKind, Import, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
import {ClassMemberKind, Import, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
||||||
|
@ -168,16 +168,16 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -189,16 +189,16 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective',
|
bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -210,16 +210,16 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -234,15 +234,15 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
|
|
||||||
const input2 = members.find(member => member.name === 'input2') !;
|
const input2 = members.find(member => member.name === 'input2')!;
|
||||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input2.isStatic).toEqual(false);
|
expect(input2.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`',
|
it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`',
|
||||||
|
@ -254,10 +254,10 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find non decorated properties on a class', () => {
|
it('should find non decorated properties on a class', () => {
|
||||||
|
@ -268,11 +268,11 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const instanceProperty = members.find(member => member.name === 'instanceProperty') !;
|
const instanceProperty = members.find(member => member.name === 'instanceProperty')!;
|
||||||
expect(instanceProperty.kind).toEqual(ClassMemberKind.Property);
|
expect(instanceProperty.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(instanceProperty.isStatic).toEqual(false);
|
expect(instanceProperty.isStatic).toEqual(false);
|
||||||
expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true);
|
expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true);
|
||||||
expect(instanceProperty.value !.getText()).toEqual(`'instance'`);
|
expect(instanceProperty.value!.getText()).toEqual(`'instance'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find static methods on a class', () => {
|
it('should find static methods on a class', () => {
|
||||||
|
@ -283,10 +283,10 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const staticMethod = members.find(member => member.name === 'staticMethod') !;
|
const staticMethod = members.find(member => member.name === 'staticMethod')!;
|
||||||
expect(staticMethod.kind).toEqual(ClassMemberKind.Method);
|
expect(staticMethod.kind).toEqual(ClassMemberKind.Method);
|
||||||
expect(staticMethod.isStatic).toEqual(true);
|
expect(staticMethod.isStatic).toEqual(true);
|
||||||
expect(ts.isMethodDeclaration(staticMethod.implementation !)).toEqual(true);
|
expect(ts.isMethodDeclaration(staticMethod.implementation!)).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find static properties on a class', () => {
|
it('should find static properties on a class', () => {
|
||||||
|
@ -297,11 +297,11 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
|
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
const staticProperty = members.find(member => member.name === 'staticProperty') !;
|
const staticProperty = members.find(member => member.name === 'staticProperty')!;
|
||||||
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(staticProperty.isStatic).toEqual(true);
|
expect(staticProperty.isStatic).toEqual(true);
|
||||||
expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true);
|
expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true);
|
||||||
expect(staticProperty.value !.getText()).toEqual(`'static'`);
|
expect(staticProperty.value!.getText()).toEqual(`'static'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find static properties on a class that has an intermediate variable assignment',
|
it('should find static properties on a class that has an intermediate variable assignment',
|
||||||
|
@ -313,11 +313,11 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
|
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
const staticProperty = members.find(member => member.name === 'staticProperty') !;
|
const staticProperty = members.find(member => member.name === 'staticProperty')!;
|
||||||
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(staticProperty.isStatic).toEqual(true);
|
expect(staticProperty.isStatic).toEqual(true);
|
||||||
expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true);
|
expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true);
|
||||||
expect(staticProperty.value !.getText()).toEqual(`'static'`);
|
expect(staticProperty.value!.getText()).toEqual(`'static'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support decorators being used inside @angular/core', () => {
|
it('should support decorators being used inside @angular/core', () => {
|
||||||
|
@ -329,10 +329,10 @@ runInEachFileSystem(() => {
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -346,10 +346,10 @@ runInEachFileSystem(() => {
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
|
|
||||||
expect(parameters).toBeDefined();
|
expect(parameters).toBeDefined();
|
||||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
expect(parameters!.map(parameter => parameter.name)).toEqual([
|
||||||
'_viewContainer', '_template', 'injected'
|
'_viewContainer', '_template', 'injected'
|
||||||
]);
|
]);
|
||||||
expectTypeValueReferencesForParameters(parameters !, [
|
expectTypeValueReferencesForParameters(parameters!, [
|
||||||
'ViewContainerRef',
|
'ViewContainerRef',
|
||||||
'TemplateRef',
|
'TemplateRef',
|
||||||
'String',
|
'String',
|
||||||
|
@ -366,20 +366,20 @@ runInEachFileSystem(() => {
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
|
|
||||||
expect(parameters).toBeDefined();
|
expect(parameters).toBeDefined();
|
||||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
expect(parameters!.map(parameter => parameter.name)).toEqual([
|
||||||
'_viewContainer', '_template', 'injected'
|
'_viewContainer', '_template', 'injected'
|
||||||
]);
|
]);
|
||||||
expectTypeValueReferencesForParameters(parameters !, [
|
expectTypeValueReferencesForParameters(parameters!, [
|
||||||
'ViewContainerRef',
|
'ViewContainerRef',
|
||||||
'TemplateRef',
|
'TemplateRef',
|
||||||
null,
|
null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const decorators = parameters ![2].decorators !;
|
const decorators = parameters![2].decorators!;
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
expect(decorators[0].name).toBe('Inject');
|
expect(decorators[0].name).toBe('Inject');
|
||||||
expect(decorators[0].import !.from).toBe('@angular/core');
|
expect(decorators[0].import!.from).toBe('@angular/core');
|
||||||
expect(decorators[0].import !.name).toBe('Inject');
|
expect(decorators[0].import!.name).toBe('Inject');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -390,8 +390,8 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const ctrDecorators = host.getConstructorParameters(classNode) !;
|
const ctrDecorators = host.getConstructorParameters(classNode)!;
|
||||||
const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{
|
const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as {
|
||||||
local: true,
|
local: true,
|
||||||
expression: ts.Identifier,
|
expression: ts.Identifier,
|
||||||
defaultImportStatement: null,
|
defaultImportStatement: null,
|
||||||
|
@ -401,8 +401,8 @@ runInEachFileSystem(() => {
|
||||||
bundle.program, _('/some_directive.js'), 'ViewContainerRef', ts.isClassDeclaration);
|
bundle.program, _('/some_directive.js'), 'ViewContainerRef', ts.isClassDeclaration);
|
||||||
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef);
|
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef);
|
||||||
expect(actualDeclaration).not.toBe(null);
|
expect(actualDeclaration).not.toBe(null);
|
||||||
expect(actualDeclaration !.node).toBe(expectedDeclarationNode);
|
expect(actualDeclaration!.node).toBe(expectedDeclarationNode);
|
||||||
expect(actualDeclaration !.viaModule).toBe(null);
|
expect(actualDeclaration!.viaModule).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the declaration of an externally defined identifier', () => {
|
it('should return the declaration of an externally defined identifier', () => {
|
||||||
|
@ -411,8 +411,8 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const classDecorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
const decoratorNode = classDecorators[0].node !;
|
const decoratorNode = classDecorators[0].node!;
|
||||||
const identifierOfDirective =
|
const identifierOfDirective =
|
||||||
ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ?
|
ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ?
|
||||||
decoratorNode.expression :
|
decoratorNode.expression :
|
||||||
|
@ -421,10 +421,10 @@ runInEachFileSystem(() => {
|
||||||
const expectedDeclarationNode = getDeclaration(
|
const expectedDeclarationNode = getDeclaration(
|
||||||
bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive',
|
bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective !);
|
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective!);
|
||||||
expect(actualDeclaration).not.toBe(null);
|
expect(actualDeclaration).not.toBe(null);
|
||||||
expect(actualDeclaration !.node).toBe(expectedDeclarationNode);
|
expect(actualDeclaration!.node).toBe(expectedDeclarationNode);
|
||||||
expect(actualDeclaration !.viaModule).toBe('@angular/core');
|
expect(actualDeclaration!.viaModule).toBe('@angular/core');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -435,13 +435,13 @@ runInEachFileSystem(() => {
|
||||||
const ngModuleRef = findVariableDeclaration(
|
const ngModuleRef = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1');
|
||||||
|
|
||||||
const value = host.getVariableValue(ngModuleRef !);
|
const value = host.getVariableValue(ngModuleRef!);
|
||||||
expect(value).not.toBe(null);
|
expect(value).not.toBe(null);
|
||||||
if (!value || !ts.isClassExpression(value)) {
|
if (!value || !ts.isClassExpression(value)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Expected value to be a class expression: ${value && value.getText()}.`);
|
`Expected value to be a class expression: ${value && value.getText()}.`);
|
||||||
}
|
}
|
||||||
expect(value.name !.text).toBe('HttpClientXsrfModule');
|
expect(value.name!.text).toBe('HttpClientXsrfModule');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return null if the variable has no assignment', () => {
|
it('should return null if the variable has no assignment', () => {
|
||||||
|
@ -449,7 +449,7 @@ runInEachFileSystem(() => {
|
||||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const missingValue = findVariableDeclaration(
|
const missingValue = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue');
|
||||||
const value = host.getVariableValue(missingValue !);
|
const value = host.getVariableValue(missingValue!);
|
||||||
expect(value).toBe(null);
|
expect(value).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -458,7 +458,7 @@ runInEachFileSystem(() => {
|
||||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const nonDecoratedVar = findVariableDeclaration(
|
const nonDecoratedVar = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar');
|
||||||
const value = host.getVariableValue(nonDecoratedVar !);
|
const value = host.getVariableValue(nonDecoratedVar!);
|
||||||
expect(value).toBe(null);
|
expect(value).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -468,7 +468,7 @@ runInEachFileSystem(() => {
|
||||||
const bundle = makeTestBundleProgram(_('/ngmodule.js'));
|
const bundle = makeTestBundleProgram(_('/ngmodule.js'));
|
||||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const classSymbol =
|
const classSymbol =
|
||||||
host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js')) !)[0];
|
host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js'))!)[0];
|
||||||
const endOfClass = host.getEndOfClass(classSymbol);
|
const endOfClass = host.getEndOfClass(classSymbol);
|
||||||
expect(endOfClass.getText())
|
expect(endOfClass.getText())
|
||||||
.toMatch(
|
.toMatch(
|
||||||
|
@ -479,7 +479,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function findVariableDeclaration(
|
function findVariableDeclaration(
|
||||||
node: ts.Node | undefined, variableName: string): ts.VariableDeclaration|undefined {
|
node: ts.Node|undefined, variableName: string): ts.VariableDeclaration|undefined {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {ClassMemberKind, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
import {ClassMemberKind, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles, loadTsLib} from '../../../test/helpers';
|
||||||
|
@ -227,19 +227,18 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find the decorators on a minified class', () => {
|
it('should find the decorators on a minified class', () => {
|
||||||
|
@ -248,19 +247,18 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_minified_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_minified_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find the decorators on an aliased class', () => {
|
it('should find the decorators on an aliased class', () => {
|
||||||
|
@ -269,16 +267,16 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_aliased_directive.js'), 'AliasedDirective$1',
|
bundle.program, _('/some_aliased_directive.js'), 'AliasedDirective$1',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -290,16 +288,16 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective',
|
bundle.program, _('/some_directive_ctor_parameters.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -311,16 +309,16 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/node_modules/@angular/core/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('Directive');
|
expect(decorator.identifier!.getText()).toEqual('Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
expect(decorator.import).toEqual({name: 'Directive', from: './directives'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -333,13 +331,12 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_minified_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_minified_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const innerNode =
|
const innerNode = getIifeBody(classNode)!.statements.find(isNamedFunctionDeclaration)!;
|
||||||
getIifeBody(classNode) !.statements.find(isNamedFunctionDeclaration) !;
|
|
||||||
const classSymbol = host.getClassSymbol(classNode);
|
const classSymbol = host.getClassSymbol(classNode);
|
||||||
|
|
||||||
expect(classSymbol).toBeDefined();
|
expect(classSymbol).toBeDefined();
|
||||||
expect(classSymbol !.declaration.valueDeclaration).toBe(classNode);
|
expect(classSymbol!.declaration.valueDeclaration).toBe(classNode);
|
||||||
expect(classSymbol !.implementation.valueDeclaration).toBe(innerNode);
|
expect(classSymbol!.implementation.valueDeclaration).toBe(innerNode);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -352,15 +349,15 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
|
|
||||||
const input2 = members.find(member => member.name === 'input2') !;
|
const input2 = members.find(member => member.name === 'input2')!;
|
||||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input2.isStatic).toEqual(false);
|
expect(input2.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`',
|
it('should find decorated members on a class when mixing `ctorParameters` and `__decorate`',
|
||||||
|
@ -372,10 +369,10 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find non decorated properties on a class', () => {
|
it('should find non decorated properties on a class', () => {
|
||||||
|
@ -386,11 +383,11 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const instanceProperty = members.find(member => member.name === 'instanceProperty') !;
|
const instanceProperty = members.find(member => member.name === 'instanceProperty')!;
|
||||||
expect(instanceProperty.kind).toEqual(ClassMemberKind.Property);
|
expect(instanceProperty.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(instanceProperty.isStatic).toEqual(false);
|
expect(instanceProperty.isStatic).toEqual(false);
|
||||||
expect(ts.isBinaryExpression(instanceProperty.implementation !)).toEqual(true);
|
expect(ts.isBinaryExpression(instanceProperty.implementation!)).toEqual(true);
|
||||||
expect(instanceProperty.value !.getText()).toEqual(`'instance'`);
|
expect(instanceProperty.value!.getText()).toEqual(`'instance'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find static methods on a class', () => {
|
it('should find static methods on a class', () => {
|
||||||
|
@ -401,10 +398,10 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const staticMethod = members.find(member => member.name === 'staticMethod') !;
|
const staticMethod = members.find(member => member.name === 'staticMethod')!;
|
||||||
expect(staticMethod.kind).toEqual(ClassMemberKind.Method);
|
expect(staticMethod.kind).toEqual(ClassMemberKind.Method);
|
||||||
expect(staticMethod.isStatic).toEqual(true);
|
expect(staticMethod.isStatic).toEqual(true);
|
||||||
expect(ts.isFunctionExpression(staticMethod.implementation !)).toEqual(true);
|
expect(ts.isFunctionExpression(staticMethod.implementation!)).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find static properties on a class', () => {
|
it('should find static properties on a class', () => {
|
||||||
|
@ -415,11 +412,11 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const staticProperty = members.find(member => member.name === 'staticProperty') !;
|
const staticProperty = members.find(member => member.name === 'staticProperty')!;
|
||||||
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
expect(staticProperty.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(staticProperty.isStatic).toEqual(true);
|
expect(staticProperty.isStatic).toEqual(true);
|
||||||
expect(ts.isPropertyAccessExpression(staticProperty.implementation !)).toEqual(true);
|
expect(ts.isPropertyAccessExpression(staticProperty.implementation!)).toEqual(true);
|
||||||
expect(staticProperty.value !.getText()).toEqual(`'static'`);
|
expect(staticProperty.value!.getText()).toEqual(`'static'`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support decorators being used inside @angular/core', () => {
|
it('should support decorators being used inside @angular/core', () => {
|
||||||
|
@ -431,10 +428,10 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('getConstructorParameters', () => {
|
describe('getConstructorParameters', () => {
|
||||||
|
@ -447,10 +444,10 @@ export { AliasedDirective$1 };
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
|
|
||||||
expect(parameters).toBeDefined();
|
expect(parameters).toBeDefined();
|
||||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
expect(parameters!.map(parameter => parameter.name)).toEqual([
|
||||||
'_viewContainer', '_template', 'injected'
|
'_viewContainer', '_template', 'injected'
|
||||||
]);
|
]);
|
||||||
expectTypeValueReferencesForParameters(parameters !, [
|
expectTypeValueReferencesForParameters(parameters!, [
|
||||||
'ViewContainerRef',
|
'ViewContainerRef',
|
||||||
'TemplateRef',
|
'TemplateRef',
|
||||||
'String',
|
'String',
|
||||||
|
@ -467,10 +464,10 @@ export { AliasedDirective$1 };
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
|
|
||||||
expect(parameters).toBeDefined();
|
expect(parameters).toBeDefined();
|
||||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
expect(parameters!.map(parameter => parameter.name)).toEqual([
|
||||||
'_viewContainer', '_template', 'injected'
|
'_viewContainer', '_template', 'injected'
|
||||||
]);
|
]);
|
||||||
expectTypeValueReferencesForParameters(parameters !, [
|
expectTypeValueReferencesForParameters(parameters!, [
|
||||||
'ViewContainerRef',
|
'ViewContainerRef',
|
||||||
'TemplateRef',
|
'TemplateRef',
|
||||||
null,
|
null,
|
||||||
|
@ -485,7 +482,7 @@ export { AliasedDirective$1 };
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
const decorators = parameters ![2].decorators !;
|
const decorators = parameters![2].decorators!;
|
||||||
|
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
expect(decorators[0].import).toEqual({name: 'Inject', from: '@angular/core'});
|
||||||
|
@ -522,7 +519,7 @@ export { AliasedDirective$1 };
|
||||||
const ngModuleDecorators = ngModuleClasses.map(s => host.getDecoratorsOfSymbol(s));
|
const ngModuleDecorators = ngModuleClasses.map(s => host.getDecoratorsOfSymbol(s));
|
||||||
|
|
||||||
expect(ngModuleClasses.length).toEqual(1);
|
expect(ngModuleClasses.length).toEqual(1);
|
||||||
expect(ngModuleDecorators[0] !.map(d => d.name)).toEqual(['NgModule']);
|
expect(ngModuleDecorators[0]!.map(d => d.name)).toEqual(['NgModule']);
|
||||||
|
|
||||||
const someDirectiveFile = getSourceFileOrError(bundle.program, _('/some_directive.js'));
|
const someDirectiveFile = getSourceFileOrError(bundle.program, _('/some_directive.js'));
|
||||||
const someDirectiveClasses = host.findClassSymbols(someDirectiveFile);
|
const someDirectiveClasses = host.findClassSymbols(someDirectiveFile);
|
||||||
|
@ -532,7 +529,7 @@ export { AliasedDirective$1 };
|
||||||
expect(someDirectiveDecorators.length).toEqual(3);
|
expect(someDirectiveDecorators.length).toEqual(3);
|
||||||
expect(someDirectiveDecorators[0]).toBe(null);
|
expect(someDirectiveDecorators[0]).toBe(null);
|
||||||
expect(someDirectiveDecorators[1]).toBe(null);
|
expect(someDirectiveDecorators[1]).toBe(null);
|
||||||
expect(someDirectiveDecorators[2] !.map(d => d.name)).toEqual(['Directive']);
|
expect(someDirectiveDecorators[2]!.map(d => d.name)).toEqual(['Directive']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -543,8 +540,8 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const ctrDecorators = host.getConstructorParameters(classNode) !;
|
const ctrDecorators = host.getConstructorParameters(classNode)!;
|
||||||
const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference !as{
|
const identifierOfViewContainerRef = (ctrDecorators[0].typeValueReference! as {
|
||||||
local: true,
|
local: true,
|
||||||
expression: ts.Identifier,
|
expression: ts.Identifier,
|
||||||
defaultImportStatement: null,
|
defaultImportStatement: null,
|
||||||
|
@ -555,8 +552,8 @@ export { AliasedDirective$1 };
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef);
|
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfViewContainerRef);
|
||||||
expect(actualDeclaration).not.toBe(null);
|
expect(actualDeclaration).not.toBe(null);
|
||||||
expect(actualDeclaration !.node).toBe(expectedDeclarationNode);
|
expect(actualDeclaration!.node).toBe(expectedDeclarationNode);
|
||||||
expect(actualDeclaration !.viaModule).toBe(null);
|
expect(actualDeclaration!.viaModule).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the declaration of an externally defined identifier', () => {
|
it('should return the declaration of an externally defined identifier', () => {
|
||||||
|
@ -565,8 +562,8 @@ export { AliasedDirective$1 };
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
bundle.program, _('/some_directive.js'), 'SomeDirective',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const classDecorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const classDecorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
const decoratorNode = classDecorators[0].node !;
|
const decoratorNode = classDecorators[0].node!;
|
||||||
|
|
||||||
const identifierOfDirective =
|
const identifierOfDirective =
|
||||||
ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ?
|
ts.isCallExpression(decoratorNode) && ts.isIdentifier(decoratorNode.expression) ?
|
||||||
|
@ -576,10 +573,10 @@ export { AliasedDirective$1 };
|
||||||
const expectedDeclarationNode = getDeclaration(
|
const expectedDeclarationNode = getDeclaration(
|
||||||
bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive',
|
bundle.program, _('/node_modules/@angular/core/index.d.ts'), 'Directive',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective !);
|
const actualDeclaration = host.getDeclarationOfIdentifier(identifierOfDirective!);
|
||||||
expect(actualDeclaration).not.toBe(null);
|
expect(actualDeclaration).not.toBe(null);
|
||||||
expect(actualDeclaration !.node).toBe(expectedDeclarationNode);
|
expect(actualDeclaration!.node).toBe(expectedDeclarationNode);
|
||||||
expect(actualDeclaration !.viaModule).toBe('@angular/core');
|
expect(actualDeclaration!.viaModule).toBe('@angular/core');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should find the "actual" declaration of an aliased variable identifier', () => {
|
it('should find the "actual" declaration of an aliased variable identifier', () => {
|
||||||
|
@ -589,9 +586,9 @@ export { AliasedDirective$1 };
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1',
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1',
|
||||||
isNgModulePropertyAssignment);
|
isNgModulePropertyAssignment);
|
||||||
|
|
||||||
const declaration = host.getDeclarationOfIdentifier(ngModuleRef !);
|
const declaration = host.getDeclarationOfIdentifier(ngModuleRef!);
|
||||||
expect(declaration).not.toBe(null);
|
expect(declaration).not.toBe(null);
|
||||||
expect(declaration !.node !.getText()).toContain('function HttpClientXsrfModule()');
|
expect(declaration!.node!.getText()).toContain('function HttpClientXsrfModule()');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('getVariableValue', () => {
|
describe('getVariableValue', () => {
|
||||||
|
@ -601,7 +598,7 @@ export { AliasedDirective$1 };
|
||||||
const ngModuleRef = findVariableDeclaration(
|
const ngModuleRef = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'HttpClientXsrfModule_1');
|
||||||
|
|
||||||
const value = host.getVariableValue(ngModuleRef !);
|
const value = host.getVariableValue(ngModuleRef!);
|
||||||
expect(value).not.toBe(null);
|
expect(value).not.toBe(null);
|
||||||
if (!value || !ts.isFunctionDeclaration(value.parent)) {
|
if (!value || !ts.isFunctionDeclaration(value.parent)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -615,7 +612,7 @@ export { AliasedDirective$1 };
|
||||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const missingValue = findVariableDeclaration(
|
const missingValue = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'missingValue');
|
||||||
const value = host.getVariableValue(missingValue !);
|
const value = host.getVariableValue(missingValue!);
|
||||||
expect(value).toBe(null);
|
expect(value).toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -624,7 +621,7 @@ export { AliasedDirective$1 };
|
||||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const nonDecoratedVar = findVariableDeclaration(
|
const nonDecoratedVar = findVariableDeclaration(
|
||||||
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar');
|
getSourceFileOrError(bundle.program, _('/ngmodule.js')), 'nonDecoratedVar');
|
||||||
const value = host.getVariableValue(nonDecoratedVar !);
|
const value = host.getVariableValue(nonDecoratedVar!);
|
||||||
expect(value).toBe(null);
|
expect(value).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -634,7 +631,7 @@ export { AliasedDirective$1 };
|
||||||
const bundle = makeTestBundleProgram(_('/ngmodule.js'));
|
const bundle = makeTestBundleProgram(_('/ngmodule.js'));
|
||||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle);
|
||||||
const classSymbol =
|
const classSymbol =
|
||||||
host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js')) !)[0];
|
host.findClassSymbols(bundle.program.getSourceFile(_('/ngmodule.js'))!)[0];
|
||||||
const endOfClass = host.getEndOfClass(classSymbol);
|
const endOfClass = host.getEndOfClass(classSymbol);
|
||||||
expect(endOfClass.getText())
|
expect(endOfClass.getText())
|
||||||
.toMatch(
|
.toMatch(
|
||||||
|
@ -644,7 +641,7 @@ export { AliasedDirective$1 };
|
||||||
});
|
});
|
||||||
|
|
||||||
function findVariableDeclaration(
|
function findVariableDeclaration(
|
||||||
node: ts.Node | undefined, variableName: string): ts.VariableDeclaration|undefined {
|
node: ts.Node|undefined, variableName: string): ts.VariableDeclaration|undefined {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -656,7 +653,7 @@ export { AliasedDirective$1 };
|
||||||
});
|
});
|
||||||
|
|
||||||
function findIdentifier(
|
function findIdentifier(
|
||||||
node: ts.Node | undefined, identifierName: string,
|
node: ts.Node|undefined, identifierName: string,
|
||||||
requireFn: (node: ts.Identifier) => boolean): ts.Identifier|undefined {
|
requireFn: (node: ts.Identifier) => boolean): ts.Identifier|undefined {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {ClassMemberKind, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
import {ClassMemberKind, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
|
@ -81,16 +81,16 @@ runInEachFileSystem(() => {
|
||||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle);
|
const host = new UmdReflectionHost(new MockLogger(), false, bundle);
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('core.Directive');
|
expect(decorator.identifier!.getText()).toEqual('core.Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -102,16 +102,16 @@ runInEachFileSystem(() => {
|
||||||
const classNode = getDeclaration(
|
const classNode = getDeclaration(
|
||||||
bundle.program, SOME_DIRECTIVE_FILE.name, 'AliasedDirective$1',
|
bundle.program, SOME_DIRECTIVE_FILE.name, 'AliasedDirective$1',
|
||||||
isNamedVariableDeclaration);
|
isNamedVariableDeclaration);
|
||||||
const decorators = host.getDecoratorsOfDeclaration(classNode) !;
|
const decorators = host.getDecoratorsOfDeclaration(classNode)!;
|
||||||
|
|
||||||
expect(decorators).toBeDefined();
|
expect(decorators).toBeDefined();
|
||||||
expect(decorators.length).toEqual(1);
|
expect(decorators.length).toEqual(1);
|
||||||
|
|
||||||
const decorator = decorators[0];
|
const decorator = decorators[0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier !.getText()).toEqual('core.Directive');
|
expect(decorator.identifier!.getText()).toEqual('core.Directive');
|
||||||
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
expect(decorator.import).toEqual({name: 'Directive', from: '@angular/core'});
|
||||||
expect(decorator.args !.map(arg => arg.getText())).toEqual([
|
expect(decorator.args!.map(arg => arg.getText())).toEqual([
|
||||||
'{ selector: \'[someDirective]\' }',
|
'{ selector: \'[someDirective]\' }',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
@ -126,15 +126,15 @@ runInEachFileSystem(() => {
|
||||||
bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
bundle.program, SOME_DIRECTIVE_FILE.name, 'SomeDirective', isNamedVariableDeclaration);
|
||||||
const members = host.getMembersOfClass(classNode);
|
const members = host.getMembersOfClass(classNode);
|
||||||
|
|
||||||
const input1 = members.find(member => member.name === 'input1') !;
|
const input1 = members.find(member => member.name === 'input1')!;
|
||||||
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
expect(input1.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input1.isStatic).toEqual(false);
|
expect(input1.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
|
|
||||||
const input2 = members.find(member => member.name === 'input2') !;
|
const input2 = members.find(member => member.name === 'input2')!;
|
||||||
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
expect(input2.kind).toEqual(ClassMemberKind.Property);
|
||||||
expect(input2.isStatic).toEqual(false);
|
expect(input2.isStatic).toEqual(false);
|
||||||
expect(input1.decorators !.map(d => d.name)).toEqual(['Input']);
|
expect(input1.decorators!.map(d => d.name)).toEqual(['Input']);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getConstructorParameters', () => {
|
describe('getConstructorParameters', () => {
|
||||||
|
@ -148,10 +148,10 @@ runInEachFileSystem(() => {
|
||||||
const parameters = host.getConstructorParameters(classNode);
|
const parameters = host.getConstructorParameters(classNode);
|
||||||
|
|
||||||
expect(parameters).toBeDefined();
|
expect(parameters).toBeDefined();
|
||||||
expect(parameters !.map(parameter => parameter.name)).toEqual([
|
expect(parameters!.map(parameter => parameter.name)).toEqual([
|
||||||
'_viewContainer', '_template', 'injected'
|
'_viewContainer', '_template', 'injected'
|
||||||
]);
|
]);
|
||||||
expectTypeValueReferencesForParameters(parameters !, [
|
expectTypeValueReferencesForParameters(parameters!, [
|
||||||
'ViewContainerRef',
|
'ViewContainerRef',
|
||||||
'TemplateRef',
|
'TemplateRef',
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -14,9 +14,8 @@ import {CtorParameter} from '../../../src/ngtsc/reflection';
|
||||||
* names.
|
* names.
|
||||||
*/
|
*/
|
||||||
export function expectTypeValueReferencesForParameters(
|
export function expectTypeValueReferencesForParameters(
|
||||||
parameters: CtorParameter[], expectedParams: (string | null)[],
|
parameters: CtorParameter[], expectedParams: (string|null)[], fromModule: string|null = null) {
|
||||||
fromModule: string | null = null) {
|
parameters!.forEach((param, idx) => {
|
||||||
parameters !.forEach((param, idx) => {
|
|
||||||
const expected = expectedParams[idx];
|
const expected = expectedParams[idx];
|
||||||
if (expected !== null) {
|
if (expected !== null) {
|
||||||
if (param.typeValueReference === null) {
|
if (param.typeValueReference === null) {
|
||||||
|
@ -32,7 +31,7 @@ export function expectTypeValueReferencesForParameters(
|
||||||
expect(param.typeValueReference.expression.text).toEqual(expected);
|
expect(param.typeValueReference.expression.text).toEqual(expected);
|
||||||
}
|
}
|
||||||
} else if (param.typeValueReference !== null) {
|
} else if (param.typeValueReference !== null) {
|
||||||
expect(param.typeValueReference.moduleName).toBe(fromModule !);
|
expect(param.typeValueReference.moduleName).toBe(fromModule!);
|
||||||
expect(param.typeValueReference.name).toBe(expected);
|
expect(param.typeValueReference.name).toBe(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,9 @@
|
||||||
|
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, join} from '../../../src/ngtsc/file_system';
|
|
||||||
import {Folder, MockFileSystem, TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, join} from '../../../src/ngtsc/file_system';
|
||||||
|
import {Folder, MockFileSystem, runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers';
|
import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers';
|
||||||
import {getLockFilePath} from '../../src/locking/lock_file';
|
import {getLockFilePath} from '../../src/locking/lock_file';
|
||||||
import {mainNgcc} from '../../src/main';
|
import {mainNgcc} from '../../src/main';
|
||||||
|
@ -19,6 +20,7 @@ import {EntryPointManifestFile} from '../../src/packages/entry_point_manifest';
|
||||||
import {Transformer} from '../../src/packages/transformer';
|
import {Transformer} from '../../src/packages/transformer';
|
||||||
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
||||||
import {MockLogger} from '../helpers/mock_logger';
|
import {MockLogger} from '../helpers/mock_logger';
|
||||||
|
|
||||||
import {compileIntoApf, compileIntoFlatEs5Package} from './util';
|
import {compileIntoApf, compileIntoFlatEs5Package} from './util';
|
||||||
|
|
||||||
const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true});
|
const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true});
|
||||||
|
@ -145,7 +147,8 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
['esm5', 'esm2015'].forEach(target => {
|
['esm5', 'esm2015'].forEach(target => {
|
||||||
it(`should be able to process spread operator inside objects for ${target} format (imported helpers)`,
|
it(`should be able to process spread operator inside objects for ${
|
||||||
|
target} format (imported helpers)`,
|
||||||
() => {
|
() => {
|
||||||
compileIntoApf(
|
compileIntoApf(
|
||||||
'test-package', {
|
'test-package', {
|
||||||
|
@ -184,7 +187,8 @@ runInEachFileSystem(() => {
|
||||||
expect(jsContents).toContain('ngcc0.ɵɵclassProp("a", true)("b", true)("c", false)');
|
expect(jsContents).toContain('ngcc0.ɵɵclassProp("a", true)("b", true)("c", false)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should be able to process emitted spread operator inside objects for ${target} format (emitted helpers)`,
|
it(`should be able to process emitted spread operator inside objects for ${
|
||||||
|
target} format (emitted helpers)`,
|
||||||
() => {
|
() => {
|
||||||
compileIntoApf(
|
compileIntoApf(
|
||||||
'test-package', {
|
'test-package', {
|
||||||
|
@ -326,7 +330,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const before = fs.readFile(_(`/node_modules/test-package/index.js`));
|
const before = fs.readFile(_(`/node_modules/test-package/index.js`));
|
||||||
const originalProp = /ɵprov[^;]+/.exec(before) ![0];
|
const originalProp = /ɵprov[^;]+/.exec(before)![0];
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
targetEntryPointPath: 'test-package',
|
targetEntryPointPath: 'test-package',
|
||||||
|
@ -496,7 +500,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('in async mode', () => {
|
describe('in async mode', () => {
|
||||||
it('should run ngcc without errors for fesm2015', async() => {
|
it('should run ngcc without errors for fesm2015', async () => {
|
||||||
const promise = mainNgcc({
|
const promise = mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
propertiesToConsider: ['fesm2015'],
|
propertiesToConsider: ['fesm2015'],
|
||||||
|
@ -507,7 +511,7 @@ runInEachFileSystem(() => {
|
||||||
await promise;
|
await promise;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject, if some of the entry-points are unprocessable', async() => {
|
it('should reject, if some of the entry-points are unprocessable', async () => {
|
||||||
const createEntryPoint = (name: string, prop: EntryPointJsonProperty): TestFile[] => {
|
const createEntryPoint = (name: string, prop: EntryPointJsonProperty): TestFile[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -541,7 +545,7 @@ runInEachFileSystem(() => {
|
||||||
` - ${_('/dist/unprocessable-3')}`)));
|
` - ${_('/dist/unprocessable-3')}`)));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should reject, if an error happens during processing', async() => {
|
it('should reject, if an error happens during processing', async () => {
|
||||||
spyOn(Transformer.prototype, 'transform').and.throwError('Test error.');
|
spyOn(Transformer.prototype, 'transform').and.throwError('Test error.');
|
||||||
|
|
||||||
const promise = mainNgcc({
|
const promise = mainNgcc({
|
||||||
|
@ -651,7 +655,8 @@ runInEachFileSystem(() => {
|
||||||
markPropertiesAsProcessed('@angular/common/http/testing', SUPPORTED_FORMAT_PROPERTIES);
|
markPropertiesAsProcessed('@angular/common/http/testing', SUPPORTED_FORMAT_PROPERTIES);
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
targetEntryPointPath: '@angular/common/http/testing', logger,
|
targetEntryPointPath: '@angular/common/http/testing',
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
expect(logger.logs.debug).toContain([
|
expect(logger.logs.debug).toContain([
|
||||||
'The target entry-point has already been processed'
|
'The target entry-point has already been processed'
|
||||||
|
@ -665,7 +670,8 @@ runInEachFileSystem(() => {
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
targetEntryPointPath: '@angular/common/http/testing',
|
targetEntryPointPath: '@angular/common/http/testing',
|
||||||
propertiesToConsider: ['fesm2015', 'esm5', 'esm2015'], logger,
|
propertiesToConsider: ['fesm2015', 'esm5', 'esm2015'],
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
expect(logger.logs.debug).not.toContain([
|
expect(logger.logs.debug).not.toContain([
|
||||||
'The target entry-point has already been processed'
|
'The target entry-point has already been processed'
|
||||||
|
@ -682,7 +688,8 @@ runInEachFileSystem(() => {
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
targetEntryPointPath: '@angular/common/http/testing',
|
targetEntryPointPath: '@angular/common/http/testing',
|
||||||
propertiesToConsider: ['esm5', 'esm2015'],
|
propertiesToConsider: ['esm5', 'esm2015'],
|
||||||
compileAllFormats: false, logger,
|
compileAllFormats: false,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logger.logs.debug).not.toContain([
|
expect(logger.logs.debug).not.toContain([
|
||||||
|
@ -699,7 +706,8 @@ runInEachFileSystem(() => {
|
||||||
targetEntryPointPath: '@angular/common/http/testing',
|
targetEntryPointPath: '@angular/common/http/testing',
|
||||||
// Simulate a property that does not exist on the package.json and will be ignored.
|
// Simulate a property that does not exist on the package.json and will be ignored.
|
||||||
propertiesToConsider: ['missing', 'esm2015', 'esm5'],
|
propertiesToConsider: ['missing', 'esm2015', 'esm5'],
|
||||||
compileAllFormats: false, logger,
|
compileAllFormats: false,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logger.logs.debug).toContain([
|
expect(logger.logs.debug).toContain([
|
||||||
|
@ -717,7 +725,8 @@ runInEachFileSystem(() => {
|
||||||
targetEntryPointPath: '@angular/common/http/testing',
|
targetEntryPointPath: '@angular/common/http/testing',
|
||||||
// Simulate a property that does not exist on the package.json and will be ignored.
|
// Simulate a property that does not exist on the package.json and will be ignored.
|
||||||
propertiesToConsider: ['missing', 'esm2015', 'esm5'],
|
propertiesToConsider: ['missing', 'esm2015', 'esm5'],
|
||||||
compileAllFormats: false, logger,
|
compileAllFormats: false,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logger.logs.debug).toContain([
|
expect(logger.logs.debug).toContain([
|
||||||
|
@ -752,7 +761,7 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
// Now hack the files to look like it was processed by an outdated version of ngcc
|
// Now hack the files to look like it was processed by an outdated version of ngcc
|
||||||
const packageJson = loadPackage('test-package', _('/node_modules'));
|
const packageJson = loadPackage('test-package', _('/node_modules'));
|
||||||
packageJson.__processed_by_ivy_ngcc__ !.typings = '8.0.0';
|
packageJson.__processed_by_ivy_ngcc__!.typings = '8.0.0';
|
||||||
packageJson.main_ivy_ngcc = '__ivy_ngcc__/main.js';
|
packageJson.main_ivy_ngcc = '__ivy_ngcc__/main.js';
|
||||||
fs.writeFile(_('/node_modules/test-package/package.json'), JSON.stringify(packageJson));
|
fs.writeFile(_('/node_modules/test-package/package.json'), JSON.stringify(packageJson));
|
||||||
fs.writeFile(_('/node_modules/test-package/x.js'), 'processed content');
|
fs.writeFile(_('/node_modules/test-package/x.js'), 'processed content');
|
||||||
|
@ -838,7 +847,8 @@ runInEachFileSystem(() => {
|
||||||
// `fesm2015` and `es2015` map to the same file: `./fesm2015/common.js`
|
// `fesm2015` and `es2015` map to the same file: `./fesm2015/common.js`
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules/@angular/common',
|
basePath: '/node_modules/@angular/common',
|
||||||
propertiesToConsider: ['fesm2015'], logger,
|
propertiesToConsider: ['fesm2015'],
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logs).not.toContain(['Skipping @angular/common : es2015 (already compiled).']);
|
expect(logs).not.toContain(['Skipping @angular/common : es2015 (already compiled).']);
|
||||||
|
@ -851,7 +861,8 @@ runInEachFileSystem(() => {
|
||||||
// Now, compiling `es2015` should be a no-op.
|
// Now, compiling `es2015` should be a no-op.
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules/@angular/common',
|
basePath: '/node_modules/@angular/common',
|
||||||
propertiesToConsider: ['es2015'], logger,
|
propertiesToConsider: ['es2015'],
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(logs).toContain(['Skipping @angular/common : es2015 (already compiled).']);
|
expect(logs).toContain(['Skipping @angular/common : es2015 (already compiled).']);
|
||||||
|
@ -997,21 +1008,21 @@ runInEachFileSystem(() => {
|
||||||
expectNotToHaveProp(pkg, 'esm5_ivy_ngcc');
|
expectNotToHaveProp(pkg, 'esm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
||||||
expectNotToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
expectNotToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'fesm2015');
|
expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'fesm2015');
|
||||||
|
|
||||||
// Process `fesm5` and update `package.json`.
|
// Process `fesm5` and update `package.json`.
|
||||||
pkg = processFormatAndUpdatePackageJson('fesm5');
|
pkg = processFormatAndUpdatePackageJson('fesm5');
|
||||||
expectNotToHaveProp(pkg, 'esm5_ivy_ngcc');
|
expectNotToHaveProp(pkg, 'esm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
||||||
expectToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
expectToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'fesm5');
|
expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'fesm5');
|
||||||
|
|
||||||
// Process `esm5` and update `package.json`.
|
// Process `esm5` and update `package.json`.
|
||||||
pkg = processFormatAndUpdatePackageJson('esm5');
|
pkg = processFormatAndUpdatePackageJson('esm5');
|
||||||
expectToHaveProp(pkg, 'esm5_ivy_ngcc');
|
expectToHaveProp(pkg, 'esm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
expectToHaveProp(pkg, 'fesm2015_ivy_ngcc');
|
||||||
expectToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
expectToHaveProp(pkg, 'fesm5_ivy_ngcc');
|
||||||
expectToHaveProp(pkg.__processed_by_ivy_ngcc__ !, 'esm5');
|
expectToHaveProp(pkg.__processed_by_ivy_ngcc__!, 'esm5');
|
||||||
|
|
||||||
// Ensure the properties are in deterministic order (regardless of processing order).
|
// Ensure the properties are in deterministic order (regardless of processing order).
|
||||||
const pkgKeys = stringifyKeys(pkg);
|
const pkgKeys = stringifyKeys(pkg);
|
||||||
|
@ -1026,7 +1037,7 @@ runInEachFileSystem(() => {
|
||||||
// For example:
|
// For example:
|
||||||
// - `fesm2015` <=> `es2015`
|
// - `fesm2015` <=> `es2015`
|
||||||
// - `fesm5` <=> `module`
|
// - `fesm5` <=> `module`
|
||||||
expect(stringifyKeys(pkg.__processed_by_ivy_ngcc__ !))
|
expect(stringifyKeys(pkg.__processed_by_ivy_ngcc__!))
|
||||||
.toBe('|es2015|esm5|fesm2015|fesm5|module|typings|');
|
.toBe('|es2015|esm5|fesm2015|fesm5|module|typings|');
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
@ -1034,7 +1045,8 @@ runInEachFileSystem(() => {
|
||||||
expect(obj.hasOwnProperty(prop))
|
expect(obj.hasOwnProperty(prop))
|
||||||
.toBe(
|
.toBe(
|
||||||
false,
|
false,
|
||||||
`Expected object not to have property '${prop}': ${JSON.stringify(obj, null, 2)}`);
|
`Expected object not to have property '${prop}': ${
|
||||||
|
JSON.stringify(obj, null, 2)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectToHaveProp(obj: object, prop: string) {
|
function expectToHaveProp(obj: object, prop: string) {
|
||||||
|
@ -1053,7 +1065,9 @@ runInEachFileSystem(() => {
|
||||||
return loadPackage('@angular/core');
|
return loadPackage('@angular/core');
|
||||||
}
|
}
|
||||||
|
|
||||||
function stringifyKeys(obj: object) { return `|${Object.keys(obj).join('|')}|`; }
|
function stringifyKeys(obj: object) {
|
||||||
|
return `|${Object.keys(obj).join('|')}|`;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1206,7 +1220,8 @@ runInEachFileSystem(() => {
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
propertiesToConsider: ['es2015'],
|
propertiesToConsider: ['es2015'],
|
||||||
errorOnFailedEntryPoint: false, logger,
|
errorOnFailedEntryPoint: false,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
expect(logger.logs.error.length).toEqual(1);
|
expect(logger.logs.error.length).toEqual(1);
|
||||||
const message = logger.logs.error[0][0];
|
const message = logger.logs.error[0][0];
|
||||||
|
@ -1236,7 +1251,8 @@ runInEachFileSystem(() => {
|
||||||
const logger = new MockLogger();
|
const logger = new MockLogger();
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
propertiesToConsider: ['esm2015'], logger,
|
propertiesToConsider: ['esm2015'],
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
expect(logger.logs.info).toContain(['Compiling @angular/common/http : esm2015 as esm2015']);
|
expect(logger.logs.info).toContain(['Compiling @angular/common/http : esm2015 as esm2015']);
|
||||||
});
|
});
|
||||||
|
@ -1281,7 +1297,8 @@ runInEachFileSystem(() => {
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/dist',
|
basePath: '/dist',
|
||||||
propertiesToConsider: ['es2015'],
|
propertiesToConsider: ['es2015'],
|
||||||
tsConfigPath: _('/tsconfig.app.json'), logger
|
tsConfigPath: _('/tsconfig.app.json'),
|
||||||
|
logger
|
||||||
});
|
});
|
||||||
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
|
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -1316,7 +1333,8 @@ runInEachFileSystem(() => {
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/node_modules',
|
basePath: '/node_modules',
|
||||||
propertiesToConsider: ['es2015'],
|
propertiesToConsider: ['es2015'],
|
||||||
pathMappings: {paths: {'*': ['dist/*']}, baseUrl: '/'}, logger
|
pathMappings: {paths: {'*': ['dist/*']}, baseUrl: '/'},
|
||||||
|
logger
|
||||||
});
|
});
|
||||||
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
|
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -1356,7 +1374,8 @@ runInEachFileSystem(() => {
|
||||||
mainNgcc({
|
mainNgcc({
|
||||||
basePath: '/dist',
|
basePath: '/dist',
|
||||||
propertiesToConsider: ['es2015'],
|
propertiesToConsider: ['es2015'],
|
||||||
tsConfigPath: null, logger,
|
tsConfigPath: null,
|
||||||
|
logger,
|
||||||
});
|
});
|
||||||
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
|
expect(loadPackage('local-package', _('/dist')).__processed_by_ivy_ngcc__).toEqual({
|
||||||
es2015: '0.0.0-PLACEHOLDER',
|
es2015: '0.0.0-PLACEHOLDER',
|
||||||
|
@ -1821,7 +1840,7 @@ runInEachFileSystem(() => {
|
||||||
expect(jsContents).toContain('exports.ɵngExportɵFooModuleɵFoo = ɵngcc1.Foo;');
|
expect(jsContents).toContain('exports.ɵngExportɵFooModuleɵFoo = ɵngcc1.Foo;');
|
||||||
expect(dtsContents)
|
expect(dtsContents)
|
||||||
.toContain(`export {Foo as ɵngExportɵFooModuleɵFoo} from './directive';`);
|
.toContain(`export {Foo as ɵngExportɵFooModuleɵFoo} from './directive';`);
|
||||||
expect(dtsContents.match(/ɵngExportɵFooModuleɵFoo/g) !.length).toBe(1);
|
expect(dtsContents.match(/ɵngExportɵFooModuleɵFoo/g)!.length).toBe(1);
|
||||||
expect(dtsContents).not.toContain(`ɵngExportɵFooModuleɵLocalDir`);
|
expect(dtsContents).not.toContain(`ɵngExportɵFooModuleɵLocalDir`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -234,11 +234,21 @@ class MockCompilerHost implements ts.CompilerHost {
|
||||||
this.fs.writeFile(this.fs.resolve(fileName), data);
|
this.fs.writeFile(this.fs.resolve(fileName), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentDirectory(): string { return this.fs.pwd(); }
|
getCurrentDirectory(): string {
|
||||||
getCanonicalFileName(fileName: string): string { return fileName; }
|
return this.fs.pwd();
|
||||||
useCaseSensitiveFileNames(): boolean { return true; }
|
}
|
||||||
getNewLine(): string { return '\n'; }
|
getCanonicalFileName(fileName: string): string {
|
||||||
fileExists(fileName: string): boolean { return this.fs.exists(this.fs.resolve(fileName)); }
|
return fileName;
|
||||||
|
}
|
||||||
|
useCaseSensitiveFileNames(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
getNewLine(): string {
|
||||||
|
return '\n';
|
||||||
|
}
|
||||||
|
fileExists(fileName: string): boolean {
|
||||||
|
return this.fs.exists(this.fs.resolve(fileName));
|
||||||
|
}
|
||||||
readFile(fileName: string): string|undefined {
|
readFile(fileName: string): string|undefined {
|
||||||
const abs = this.fs.resolve(fileName);
|
const abs = this.fs.resolve(fileName);
|
||||||
return this.fs.exists(abs) ? this.fs.readFile(abs) : undefined;
|
return this.fs.exists(abs) ? this.fs.readFile(abs) : undefined;
|
||||||
|
|
|
@ -14,13 +14,13 @@ import {MockLogger} from '../helpers/mock_logger';
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
describe('AsyncLocker', () => {
|
describe('AsyncLocker', () => {
|
||||||
describe('lock()', () => {
|
describe('lock()', () => {
|
||||||
it('should guard the `fn()` with calls to `write()` and `remove()`', async() => {
|
it('should guard the `fn()` with calls to `write()` and `remove()`', async () => {
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const log: string[] = [];
|
const log: string[] = [];
|
||||||
const lockFile = new MockLockFile(fs, log);
|
const lockFile = new MockLockFile(fs, log);
|
||||||
const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10);
|
const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10);
|
||||||
|
|
||||||
await locker.lock(async() => {
|
await locker.lock(async () => {
|
||||||
log.push('fn() - before');
|
log.push('fn() - before');
|
||||||
// This promise forces node to do a tick in this function, ensuring that we are truly
|
// This promise forces node to do a tick in this function, ensuring that we are truly
|
||||||
// testing an async scenario.
|
// testing an async scenario.
|
||||||
|
@ -31,7 +31,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should guard the `fn()` with calls to `write()` and `remove()`, even if it throws',
|
it('should guard the `fn()` with calls to `write()` and `remove()`, even if it throws',
|
||||||
async() => {
|
async () => {
|
||||||
let error: string = '';
|
let error: string = '';
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const log: string[] = [];
|
const log: string[] = [];
|
||||||
|
@ -39,7 +39,7 @@ runInEachFileSystem(() => {
|
||||||
const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10);
|
const locker = new AsyncLocker(lockFile, new MockLogger(), 100, 10);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await locker.lock(async() => {
|
await locker.lock(async () => {
|
||||||
log.push('fn()');
|
log.push('fn()');
|
||||||
throw new Error('ERROR');
|
throw new Error('ERROR');
|
||||||
});
|
});
|
||||||
|
@ -50,7 +50,7 @@ runInEachFileSystem(() => {
|
||||||
expect(log).toEqual(['write()', 'fn()', 'remove()']);
|
expect(log).toEqual(['write()', 'fn()', 'remove()']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should retry if another process is locking', async() => {
|
it('should retry if another process is locking', async () => {
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const log: string[] = [];
|
const log: string[] = [];
|
||||||
const lockFile = new MockLockFile(fs, log);
|
const lockFile = new MockLockFile(fs, log);
|
||||||
|
@ -69,7 +69,7 @@ runInEachFileSystem(() => {
|
||||||
return lockFileContents;
|
return lockFileContents;
|
||||||
});
|
});
|
||||||
|
|
||||||
const promise = locker.lock(async() => log.push('fn()'));
|
const promise = locker.lock(async () => log.push('fn()'));
|
||||||
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
||||||
expect(log).toEqual(['write()', 'read() => 188']);
|
expect(log).toEqual(['write()', 'read() => 188']);
|
||||||
expect(logger.logs.info).toEqual([[
|
expect(logger.logs.info).toEqual([[
|
||||||
|
@ -83,7 +83,7 @@ runInEachFileSystem(() => {
|
||||||
expect(log).toEqual(['write()', 'read() => 188', 'write()', 'fn()', 'remove()']);
|
expect(log).toEqual(['write()', 'read() => 188', 'write()', 'fn()', 'remove()']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should extend the retry timeout if the other process locking the file changes', async() => {
|
it('should extend the retry timeout if the other process locking the file changes', async () => {
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const log: string[] = [];
|
const log: string[] = [];
|
||||||
const lockFile = new MockLockFile(fs, log);
|
const lockFile = new MockLockFile(fs, log);
|
||||||
|
@ -102,7 +102,7 @@ runInEachFileSystem(() => {
|
||||||
return lockFileContents;
|
return lockFileContents;
|
||||||
});
|
});
|
||||||
|
|
||||||
const promise = locker.lock(async() => log.push('fn()'));
|
const promise = locker.lock(async () => log.push('fn()'));
|
||||||
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
||||||
expect(log).toEqual(['write()', 'read() => 188']);
|
expect(log).toEqual(['write()', 'read() => 188']);
|
||||||
expect(logger.logs.info).toEqual([[
|
expect(logger.logs.info).toEqual([[
|
||||||
|
@ -132,7 +132,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should error if another process does not release the lock-file before this times out',
|
it('should error if another process does not release the lock-file before this times out',
|
||||||
async() => {
|
async () => {
|
||||||
const fs = getFileSystem();
|
const fs = getFileSystem();
|
||||||
const log: string[] = [];
|
const log: string[] = [];
|
||||||
const lockFile = new MockLockFile(fs, log);
|
const lockFile = new MockLockFile(fs, log);
|
||||||
|
@ -151,7 +151,7 @@ runInEachFileSystem(() => {
|
||||||
return lockFileContents;
|
return lockFileContents;
|
||||||
});
|
});
|
||||||
|
|
||||||
const promise = locker.lock(async() => log.push('fn()'));
|
const promise = locker.lock(async () => log.push('fn()'));
|
||||||
|
|
||||||
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
// The lock is now waiting on the lock-file becoming free, so no `fn()` in the log.
|
||||||
expect(log).toEqual(['write()', 'read() => 188']);
|
expect(log).toEqual(['write()', 'read() => 188']);
|
||||||
|
@ -159,10 +159,11 @@ runInEachFileSystem(() => {
|
||||||
let error: Error;
|
let error: Error;
|
||||||
await promise.catch(e => error = e);
|
await promise.catch(e => error = e);
|
||||||
expect(log).toEqual(['write()', 'read() => 188', 'write()', 'read() => 188']);
|
expect(log).toEqual(['write()', 'read() => 188', 'write()', 'read() => 188']);
|
||||||
expect(error !.message)
|
expect(error!.message)
|
||||||
.toEqual(
|
.toEqual(
|
||||||
`Timed out waiting 0.2s for another ngcc process, with id 188, to complete.\n` +
|
`Timed out waiting 0.2s for another ngcc process, with id 188, to complete.\n` +
|
||||||
`(If you are sure no ngcc process is running then you should delete the lock-file at ${lockFile.path}.)`);
|
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
|
||||||
|
lockFile.path}.)`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,7 @@ runInEachFileSystem(() => {
|
||||||
class LockFileUnderTest extends LockFileWithChildProcess {
|
class LockFileUnderTest extends LockFileWithChildProcess {
|
||||||
// Note that log is initialized in the `createUnlocker()` function that is called from
|
// Note that log is initialized in the `createUnlocker()` function that is called from
|
||||||
// super(), so we can't initialize it here.
|
// super(), so we can't initialize it here.
|
||||||
log !: string[];
|
log!: string[];
|
||||||
constructor(fs: FileSystem) {
|
constructor(fs: FileSystem) {
|
||||||
super(fs, new MockLogger());
|
super(fs, new MockLogger());
|
||||||
fs.ensureDir(fs.dirname(this.path));
|
fs.ensureDir(fs.dirname(this.path));
|
||||||
|
@ -47,7 +47,11 @@ runInEachFileSystem(() => {
|
||||||
const log = this.log;
|
const log = this.log;
|
||||||
// Normally this would fork a child process and return it.
|
// Normally this would fork a child process and return it.
|
||||||
// But we don't want to do that in these tests.
|
// But we don't want to do that in these tests.
|
||||||
return <any>{disconnect() { log.push('unlocker.disconnect()'); }};
|
return <any>{
|
||||||
|
disconnect() {
|
||||||
|
log.push('unlocker.disconnect()');
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* 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
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem} from '../../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem} from '../../../../src/ngtsc/file_system';
|
||||||
import {runInEachFileSystem} from '../../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem} from '../../../../src/ngtsc/file_system/testing';
|
||||||
import {removeLockFile} from '../../../src/locking/lock_file_with_child_process/util';
|
import {removeLockFile} from '../../../src/locking/lock_file_with_child_process/util';
|
||||||
import {MockLogger} from '../../helpers/mock_logger';
|
import {MockLogger} from '../../helpers/mock_logger';
|
||||||
|
@ -24,8 +24,9 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('removeLockFile()', () => {
|
describe('removeLockFile()', () => {
|
||||||
it('should do nothing if there is no file to remove',
|
it('should do nothing if there is no file to remove', () => {
|
||||||
() => { removeLockFile(fs, logger, absoluteFrom('/lockfile/path'), '1234'); });
|
removeLockFile(fs, logger, absoluteFrom('/lockfile/path'), '1234');
|
||||||
|
});
|
||||||
|
|
||||||
it('should do nothing if the pid does not match', () => {
|
it('should do nothing if the pid does not match', () => {
|
||||||
fs.writeFile(lockFilePath, '888');
|
fs.writeFile(lockFilePath, '888');
|
||||||
|
|
|
@ -50,7 +50,9 @@ runInEachFileSystem(() => {
|
||||||
const lockFile = new MockLockFile(fs, log);
|
const lockFile = new MockLockFile(fs, log);
|
||||||
const locker = new SyncLocker(lockFile);
|
const locker = new SyncLocker(lockFile);
|
||||||
|
|
||||||
spyOn(lockFile, 'write').and.callFake(() => { throw {code: 'EEXIST'}; });
|
spyOn(lockFile, 'write').and.callFake(() => {
|
||||||
|
throw {code: 'EEXIST'};
|
||||||
|
});
|
||||||
spyOn(lockFile, 'read').and.returnValue('188');
|
spyOn(lockFile, 'read').and.returnValue('188');
|
||||||
|
|
||||||
expect(() => locker.lock(() => {}))
|
expect(() => locker.lock(() => {}))
|
||||||
|
@ -58,7 +60,8 @@ runInEachFileSystem(() => {
|
||||||
`ngcc is already running at process with id 188.\n` +
|
`ngcc is already running at process with id 188.\n` +
|
||||||
`If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` +
|
`If you are running multiple builds in parallel then you should pre-process your node_modules via the command line ngcc tool before starting the builds;\n` +
|
||||||
`See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` +
|
`See https://v9.angular.io/guide/ivy#speeding-up-ngcc-compilation.\n` +
|
||||||
`(If you are sure no ngcc process is running then you should delete the lock-file at ${lockFile.path}.)`);
|
`(If you are sure no ngcc process is running then you should delete the lock-file at ${
|
||||||
|
lockFile.path}.)`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, AbsoluteFsPath, getFileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||||
import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
||||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||||
import {DecorationAnalyses} from '../../src/analysis/types';
|
import {DecorationAnalyses} from '../../src/analysis/types';
|
||||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||||
import {MissingInjectableMigration, getAngularCoreDecoratorName} from '../../src/migrations/missing_injectable_migration';
|
import {getAngularCoreDecoratorName, MissingInjectableMigration} from '../../src/migrations/missing_injectable_migration';
|
||||||
import {MockLogger} from '../helpers/mock_logger';
|
import {MockLogger} from '../helpers/mock_logger';
|
||||||
import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils';
|
import {getRootFiles, makeTestEntryPointBundle} from '../helpers/utils';
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false);
|
||||||
|
@ -66,7 +66,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
function runTests(
|
function runTests(
|
||||||
type: 'NgModule' | 'Directive' | 'Component', propName: 'providers' | 'viewProviders') {
|
type: 'NgModule'|'Directive'|'Component', propName: 'providers'|'viewProviders') {
|
||||||
const args = type === 'Component' ? 'template: "", ' : '';
|
const args = type === 'Component' ? 'template: "", ' : '';
|
||||||
|
|
||||||
it(`should migrate type provider in ${type}`, () => {
|
it(`should migrate type provider in ${type}`, () => {
|
||||||
|
@ -85,7 +85,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
@ -106,12 +106,12 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'OtherService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should migrate object literal provider with forwardRef in ${type}`, async() => {
|
it(`should migrate object literal provider with forwardRef in ${type}`, async () => {
|
||||||
const {program, analysis} = setUpAndAnalyzeProgram([{
|
const {program, analysis} = setUpAndAnalyzeProgram([{
|
||||||
name: INDEX_FILENAME,
|
name: INDEX_FILENAME,
|
||||||
contents: `
|
contents: `
|
||||||
|
@ -121,12 +121,13 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
export class TestClass {}
|
export class TestClass {}
|
||||||
TestClass.decorators = [
|
TestClass.decorators = [
|
||||||
{ type: ${type}, args: [{${args}${propName}: [{provide: forwardRef(() => MyService) }]}] }
|
{ type: ${type}, args: [{${args}${
|
||||||
|
propName}: [{provide: forwardRef(() => MyService) }]}] }
|
||||||
];
|
];
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -140,12 +141,13 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
export class TestClass {}
|
export class TestClass {}
|
||||||
TestClass.decorators = [
|
TestClass.decorators = [
|
||||||
{ type: ${type}, args: [{${args}${propName}: [{provide: MyService, useValue: null }]}] }
|
{ type: ${type}, args: [{${args}${
|
||||||
|
propName}: [{provide: MyService, useValue: null }]}] }
|
||||||
];
|
];
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -159,12 +161,13 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
export class TestClass {}
|
export class TestClass {}
|
||||||
TestClass.decorators = [
|
TestClass.decorators = [
|
||||||
{ type: ${type}, args: [{${args}${propName}: [{provide: MyService, useFactory: () => null }]}] }
|
{ type: ${type}, args: [{${args}${
|
||||||
|
propName}: [{provide: MyService, useFactory: () => null }]}] }
|
||||||
];
|
];
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -189,7 +192,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyTokenAlias')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyTokenAlias')).toBe(false);
|
||||||
|
@ -206,12 +209,13 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
export class TestClass {}
|
export class TestClass {}
|
||||||
TestClass.decorators = [
|
TestClass.decorators = [
|
||||||
{ type: ${type}, args: [{${args}${propName}: [{provide: MyToken, useClass: MyService}]}] }
|
{ type: ${type}, args: [{${args}${
|
||||||
|
propName}: [{provide: MyToken, useClass: MyService}]}] }
|
||||||
];
|
];
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyToken')).toBe(false);
|
||||||
});
|
});
|
||||||
|
@ -234,7 +238,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(getInjectableDecorators(index, analysis, 'MyService').length).toBe(1);
|
expect(getInjectableDecorators(index, analysis, 'MyService').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -256,7 +260,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -278,7 +282,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -300,7 +304,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -320,7 +324,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
||||||
});
|
});
|
||||||
|
@ -348,7 +352,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true);
|
||||||
|
@ -381,7 +385,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(true);
|
||||||
|
@ -407,7 +411,7 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceB')).toBe(true);
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceC')).toBe(false);
|
||||||
|
@ -434,7 +438,7 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(getInjectableDecorators(index, analysis, 'ServiceA').length).toBe(1);
|
expect(getInjectableDecorators(index, analysis, 'ServiceA').length).toBe(1);
|
||||||
expect(getInjectableDecorators(index, analysis, 'ServiceB').length).toBe(1);
|
expect(getInjectableDecorators(index, analysis, 'ServiceB').length).toBe(1);
|
||||||
});
|
});
|
||||||
|
@ -454,7 +458,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'ServiceA')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -481,7 +485,7 @@ runInEachFileSystem(() => {
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const index = program.getSourceFile(SERVICE_FILENAME) !;
|
const index = program.getSourceFile(SERVICE_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -508,7 +512,7 @@ runInEachFileSystem(() => {
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const index = program.getSourceFile(SERVICE_FILENAME) !;
|
const index = program.getSourceFile(SERVICE_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -527,7 +531,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -546,7 +550,7 @@ runInEachFileSystem(() => {
|
||||||
`,
|
`,
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
const index = program.getSourceFile(INDEX_FILENAME) !;
|
const index = program.getSourceFile(INDEX_FILENAME)!;
|
||||||
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
expect(hasInjectableDecorator(index, analysis, 'MyService')).toBe(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {AbsoluteFsPath, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
|
||||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {absoluteFrom, AbsoluteFsPath, getFileSystem} from '../../../src/ngtsc/file_system';
|
||||||
|
import {runInEachFileSystem, TestFile} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||||
import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
import {DecorationAnalyzer} from '../../src/analysis/decoration_analyzer';
|
||||||
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
import {NgccReferencesRegistry} from '../../src/analysis/ngcc_references_registry';
|
||||||
|
@ -34,7 +35,7 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !);
|
const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!);
|
||||||
expect(file).toBeUndefined();
|
expect(file).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !;
|
const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!;
|
||||||
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
||||||
expect(file.compiledClasses.find(c => c.name === 'BaseClass')).toBeUndefined();
|
expect(file.compiledClasses.find(c => c.name === 'BaseClass')).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
@ -81,15 +82,15 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !;
|
const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!;
|
||||||
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
||||||
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !;
|
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!;
|
||||||
expect(baseClass.decorators !.length).toEqual(1);
|
expect(baseClass.decorators!.length).toEqual(1);
|
||||||
const decorator = baseClass.decorators ![0];
|
const decorator = baseClass.decorators![0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier).toBeNull('The decorator must be synthesized');
|
expect(decorator.identifier).toBeNull('The decorator must be synthesized');
|
||||||
expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||||
expect(decorator.args !.length).toEqual(0);
|
expect(decorator.args!.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not add a decorator to a base class that is already decorated', () => {
|
it('should not add a decorator to a base class that is already decorated', () => {
|
||||||
|
@ -114,11 +115,11 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !;
|
const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!;
|
||||||
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
||||||
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !;
|
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!;
|
||||||
expect(baseClass.decorators !.length).toEqual(1);
|
expect(baseClass.decorators!.length).toEqual(1);
|
||||||
const decorator = baseClass.decorators ![0];
|
const decorator = baseClass.decorators![0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier).not.toBeNull('The decorator must not be synthesized');
|
expect(decorator.identifier).not.toBeNull('The decorator must not be synthesized');
|
||||||
});
|
});
|
||||||
|
@ -145,25 +146,25 @@ runInEachFileSystem(() => {
|
||||||
`
|
`
|
||||||
}]);
|
}]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(INDEX_FILENAME) !) !;
|
const file = analysis.get(program.getSourceFile(INDEX_FILENAME)!)!;
|
||||||
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
expect(file.compiledClasses.find(c => c.name === 'DerivedClass')).toBeDefined();
|
||||||
expect(file.compiledClasses.find(c => c.name === 'RealBaseClass')).toBeUndefined();
|
expect(file.compiledClasses.find(c => c.name === 'RealBaseClass')).toBeUndefined();
|
||||||
|
|
||||||
const intermediateClass = file.compiledClasses.find(c => c.name === 'IntermediateClass') !;
|
const intermediateClass = file.compiledClasses.find(c => c.name === 'IntermediateClass')!;
|
||||||
expect(intermediateClass.decorators !.length).toEqual(1);
|
expect(intermediateClass.decorators!.length).toEqual(1);
|
||||||
const intermediateDecorator = intermediateClass.decorators ![0];
|
const intermediateDecorator = intermediateClass.decorators![0];
|
||||||
expect(intermediateDecorator.name).toEqual('Directive');
|
expect(intermediateDecorator.name).toEqual('Directive');
|
||||||
expect(intermediateDecorator.identifier).toBeNull('The decorator must be synthesized');
|
expect(intermediateDecorator.identifier).toBeNull('The decorator must be synthesized');
|
||||||
expect(intermediateDecorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
expect(intermediateDecorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||||
expect(intermediateDecorator.args !.length).toEqual(0);
|
expect(intermediateDecorator.args!.length).toEqual(0);
|
||||||
|
|
||||||
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !;
|
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!;
|
||||||
expect(baseClass.decorators !.length).toEqual(1);
|
expect(baseClass.decorators!.length).toEqual(1);
|
||||||
const baseDecorator = baseClass.decorators ![0];
|
const baseDecorator = baseClass.decorators![0];
|
||||||
expect(baseDecorator.name).toEqual('Directive');
|
expect(baseDecorator.name).toEqual('Directive');
|
||||||
expect(baseDecorator.identifier).toBeNull('The decorator must be synthesized');
|
expect(baseDecorator.identifier).toBeNull('The decorator must be synthesized');
|
||||||
expect(baseDecorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
expect(baseDecorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||||
expect(baseDecorator.args !.length).toEqual(0);
|
expect(baseDecorator.args!.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle the base class being in a different file (same package) as the derived class',
|
it('should handle the base class being in a different file (same package) as the derived class',
|
||||||
|
@ -195,14 +196,14 @@ runInEachFileSystem(() => {
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
expect(errors).toEqual([]);
|
expect(errors).toEqual([]);
|
||||||
const file = analysis.get(program.getSourceFile(BASE_FILENAME) !) !;
|
const file = analysis.get(program.getSourceFile(BASE_FILENAME)!)!;
|
||||||
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass') !;
|
const baseClass = file.compiledClasses.find(c => c.name === 'BaseClass')!;
|
||||||
expect(baseClass.decorators !.length).toEqual(1);
|
expect(baseClass.decorators!.length).toEqual(1);
|
||||||
const decorator = baseClass.decorators ![0];
|
const decorator = baseClass.decorators![0];
|
||||||
expect(decorator.name).toEqual('Directive');
|
expect(decorator.name).toEqual('Directive');
|
||||||
expect(decorator.identifier).toBeNull('The decorator must be synthesized');
|
expect(decorator.identifier).toBeNull('The decorator must be synthesized');
|
||||||
expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
expect(decorator.import).toEqual({from: '@angular/core', name: 'Directive'});
|
||||||
expect(decorator.args !.length).toEqual(0);
|
expect(decorator.args!.length).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should skip the base class if it is in a different package from the derived class', () => {
|
it('should skip the base class if it is in a different package from the derived class', () => {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
import {absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
||||||
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadTestFiles} from '../../../test/helpers';
|
import {loadTestFiles} from '../../../test/helpers';
|
||||||
import {NGCC_VERSION, cleanPackageJson, hasBeenProcessed, markAsProcessed, needsCleaning} from '../../src/packages/build_marker';
|
import {cleanPackageJson, hasBeenProcessed, markAsProcessed, needsCleaning, NGCC_VERSION} from '../../src/packages/build_marker';
|
||||||
import {EntryPointPackageJson} from '../../src/packages/entry_point';
|
import {EntryPointPackageJson} from '../../src/packages/entry_point';
|
||||||
import {DirectPackageJsonUpdater} from '../../src/writing/package_json_updater';
|
import {DirectPackageJsonUpdater} from '../../src/writing/package_json_updater';
|
||||||
|
|
||||||
|
@ -192,8 +192,9 @@ runInEachFileSystem(() => {
|
||||||
.toBe(false);
|
.toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if no markers exist',
|
it('should return false if no markers exist', () => {
|
||||||
() => { expect(hasBeenProcessed({name: 'test'}, 'module')).toBe(false); });
|
expect(hasBeenProcessed({name: 'test'}, 'module')).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('needsCleaning()', () => {
|
describe('needsCleaning()', () => {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue