refactor(ngcc): minor code clean-up following #32052 (#32427)

This commit addresses the review feedback from #32052, which was merged
before addressing the feedback there.

PR Close #32427
This commit is contained in:
George Kalpakas 2019-08-09 15:01:57 +03:00 committed by Matias Niemelä
parent bf15d3eea8
commit bd1de32b33
7 changed files with 83 additions and 81 deletions

View File

@ -9,23 +9,23 @@
import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point'; import {EntryPoint, EntryPointJsonProperty} from '../packages/entry_point';
/** The type of the function that analyzes entry-points and creates the list of tasks. */ /** The type of the function that analyzes entry-points and creates the list of tasks. */
export type AnalyzeFn = () => { export type AnalyzeEntryPointsFn = () => {
processingMetadataPerEntryPoint: Map<string, EntryPointProcessingMetadata>; processingMetadataPerEntryPoint: Map<string, EntryPointProcessingMetadata>;
tasks: Task[]; tasks: Task[];
}; };
/** /** The type of the function that can process/compile a task. */
* The type of the function that creates the `compile()` function, which in turn can be used to export type CompileFn = (task: Task) => void;
* process tasks.
*/ /** The type of the function that creates the `CompileFn` function used to process tasks. */
export type CreateCompileFn = export type CreateCompileFn = (onTaskCompleted: TaskCompletedCallback) => CompileFn;
(onTaskCompleted: (task: Task, outcome: TaskProcessingOutcome) => void) => (task: Task) => void;
/** /**
* The type of the function that orchestrates and executes the required work (i.e. analyzes the * The type of the function that orchestrates and executes the required work (i.e. analyzes the
* entry-points, processes the resulting tasks, does book-keeping and validates the final outcome). * entry-points, processes the resulting tasks, does book-keeping and validates the final outcome).
*/ */
export type ExecuteFn = (analyzeFn: AnalyzeFn, createCompileFn: CreateCompileFn) => void; export type ExecuteFn =
(analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn) => void;
/** Represents metadata related to the processing of an entry-point. */ /** Represents metadata related to the processing of an entry-point. */
export interface EntryPointProcessingMetadata { export interface EntryPointProcessingMetadata {
@ -64,6 +64,9 @@ export interface Task {
processDts: boolean; processDts: boolean;
} }
/** A function to be called once a task has been processed. */
export type TaskCompletedCallback = (task: Task, outcome: TaskProcessingOutcome) => void;
/** Represents the outcome of processing a `Task`. */ /** Represents the outcome of processing a `Task`. */
export const enum TaskProcessingOutcome { export const enum TaskProcessingOutcome {
/** The target format property was already processed - didn't have to do anything. */ /** The target format property was already processed - didn't have to do anything. */

View File

@ -16,12 +16,12 @@ import {ModuleResolver} from './dependencies/module_resolver';
import {UmdDependencyHost} from './dependencies/umd_dependency_host'; import {UmdDependencyHost} from './dependencies/umd_dependency_host';
import {DirectoryWalkerEntryPointFinder} from './entry_point_finder/directory_walker_entry_point_finder'; import {DirectoryWalkerEntryPointFinder} from './entry_point_finder/directory_walker_entry_point_finder';
import {TargetedEntryPointFinder} from './entry_point_finder/targeted_entry_point_finder'; import {TargetedEntryPointFinder} from './entry_point_finder/targeted_entry_point_finder';
import {AnalyzeFn, CreateCompileFn, EntryPointProcessingMetadata, ExecuteFn, Task, TaskProcessingOutcome} from './execution/api'; import {AnalyzeEntryPointsFn, CreateCompileFn, EntryPointProcessingMetadata, ExecuteFn, Task, TaskProcessingOutcome} from './execution/api';
import {ConsoleLogger, LogLevel} from './logging/console_logger'; import {ConsoleLogger, LogLevel} from './logging/console_logger';
import {Logger} from './logging/logger'; import {Logger} from './logging/logger';
import {hasBeenProcessed, markAsProcessed} from './packages/build_marker'; import {hasBeenProcessed, markAsProcessed} 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, PackageJsonFormatProperties, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
import {makeEntryPointBundle} from './packages/entry_point_bundle'; import {makeEntryPointBundle} from './packages/entry_point_bundle';
import {Transformer} from './packages/transformer'; import {Transformer} from './packages/transformer';
import {PathMappings} from './utils'; import {PathMappings} from './utils';
@ -87,7 +87,7 @@ export function mainNgcc(
const fileSystem = getFileSystem(); const fileSystem = getFileSystem();
// The function for performing the analysis. // The function for performing the analysis.
const analyzeFn: AnalyzeFn = () => { const analyzeEntryPoints: AnalyzeEntryPointsFn = () => {
const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider); const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider);
const moduleResolver = new ModuleResolver(fileSystem, pathMappings); const moduleResolver = new ModuleResolver(fileSystem, pathMappings);
@ -113,13 +113,12 @@ export function mainNgcc(
for (const entryPoint of entryPoints) { for (const entryPoint of entryPoints) {
const packageJson = entryPoint.packageJson; const packageJson = entryPoint.packageJson;
const hasProcessedTypings = hasBeenProcessed(packageJson, 'typings', entryPoint.path); const hasProcessedTypings = hasBeenProcessed(packageJson, 'typings', entryPoint.path);
const {propertiesToProcess, propertyToPropertiesToMarkAsProcessed} = const {propertiesToProcess, equivalentPropertiesMap} =
getPropertiesToProcessAndMarkAsProcessed(packageJson, supportedPropertiesToConsider); getPropertiesToProcess(packageJson, supportedPropertiesToConsider);
let processDts = !hasProcessedTypings; let processDts = !hasProcessedTypings;
for (const formatProperty of propertiesToProcess) { for (const formatProperty of propertiesToProcess) {
const formatPropertiesToMarkAsProcessed = const formatPropertiesToMarkAsProcessed = equivalentPropertiesMap.get(formatProperty) !;
propertyToPropertiesToMarkAsProcessed.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).
@ -189,54 +188,55 @@ export function mainNgcc(
}; };
// The function for actually planning and getting the work done. // The function for actually planning and getting the work done.
const executeFn: ExecuteFn = (analyzeFn: AnalyzeFn, createCompileFn: CreateCompileFn) => { const execute: ExecuteFn =
const {processingMetadataPerEntryPoint, tasks} = analyzeFn(); (analyzeEntryPoints: AnalyzeEntryPointsFn, createCompileFn: CreateCompileFn) => {
const compile = createCompileFn((task, outcome) => { const {processingMetadataPerEntryPoint, tasks} = analyzeEntryPoints();
const {entryPoint, formatPropertiesToMarkAsProcessed, processDts} = task; const compile = createCompileFn((task, outcome) => {
const processingMeta = processingMetadataPerEntryPoint.get(entryPoint.path) !; const {entryPoint, formatPropertiesToMarkAsProcessed, processDts} = task;
processingMeta.hasAnyProcessedFormat = true; const processingMeta = processingMetadataPerEntryPoint.get(entryPoint.path) !;
processingMeta.hasAnyProcessedFormat = true;
if (outcome === TaskProcessingOutcome.Processed) { if (outcome === TaskProcessingOutcome.Processed) {
const packageJsonPath = fileSystem.resolve(entryPoint.path, 'package.json'); const packageJsonPath = fileSystem.resolve(entryPoint.path, 'package.json');
const propsToMarkAsProcessed: (EntryPointJsonProperty | 'typings')[] = const propsToMarkAsProcessed: PackageJsonFormatProperties[] =
[...formatPropertiesToMarkAsProcessed]; [...formatPropertiesToMarkAsProcessed];
if (processDts) { if (processDts) {
processingMeta.hasProcessedTypings = true; processingMeta.hasProcessedTypings = true;
propsToMarkAsProcessed.push('typings'); propsToMarkAsProcessed.push('typings');
}
markAsProcessed(
fileSystem, entryPoint.packageJson, packageJsonPath, propsToMarkAsProcessed);
}
});
// Process all tasks.
for (const task of tasks) {
const processingMeta = processingMetadataPerEntryPoint.get(task.entryPoint.path) !;
// If we only need one format processed and we already have one for the corresponding
// entry-point, skip the task.
if (!compileAllFormats && processingMeta.hasAnyProcessedFormat) continue;
compile(task);
} }
markAsProcessed( // Check for entry-points for which we could not process any format at all.
fileSystem, entryPoint.packageJson, packageJsonPath, propsToMarkAsProcessed); const unprocessedEntryPointPaths =
} Array.from(processingMetadataPerEntryPoint.entries())
}); .filter(([, processingMeta]) => !processingMeta.hasAnyProcessedFormat)
.map(([entryPointPath]) => `\n - ${entryPointPath}`)
.join('');
// Process all tasks. if (unprocessedEntryPointPaths) {
for (const task of tasks) { throw new Error(
const processingMeta = processingMetadataPerEntryPoint.get(task.entryPoint.path) !; 'Failed to compile any formats for the following entry-points (tried ' +
`${propertiesToConsider.join(', ')}): ${unprocessedEntryPointPaths}`);
}
};
// If we only need one format processed and we already have one for the corresponding return execute(analyzeEntryPoints, createCompileFn);
// entry-point, skip the task.
if (!compileAllFormats && processingMeta.hasAnyProcessedFormat) continue;
compile(task);
}
// Check for entry-points for which we could not process any format at all.
const unprocessedEntryPointPaths =
Array.from(processingMetadataPerEntryPoint.entries())
.filter(([, processingMeta]) => !processingMeta.hasAnyProcessedFormat)
.map(([entryPointPath]) => `\n - ${entryPointPath}`)
.join('');
if (unprocessedEntryPointPaths) {
throw new Error(
'Failed to compile any formats for the following entry-points (tried ' +
`${propertiesToConsider.join(', ')}): ${unprocessedEntryPointPaths}`);
}
};
return executeFn(analyzeFn, createCompileFn);
} }
function ensureSupportedProperties(properties: string[]): EntryPointJsonProperty[] { function ensureSupportedProperties(properties: string[]): EntryPointJsonProperty[] {
@ -370,16 +370,16 @@ function logInvalidEntryPoints(logger: Logger, invalidEntryPoints: InvalidEntryP
/** /**
* This function computes and returns the following: * This function computes and returns the following:
* - `propertiesToProcess`: An (ordered) list of properties that exist and need to be processed, * - `propertiesToProcess`: An (ordered) list of properties that exist and need to be processed,
* based on the specified `propertiesToConsider`, the properties in `package.json` and their * based on the provided `propertiesToConsider`, the properties in `package.json` and their
* corresponding format-paths. NOTE: Only one property per format-path needs to be processed. * corresponding format-paths. NOTE: Only one property per format-path needs to be processed.
* - `propertyToPropertiesToMarkAsProcessed`: A mapping from each property in `propertiesToProcess` * - `equivalentPropertiesMap`: A mapping from each property in `propertiesToProcess` to the list of
* to the list of other properties in `package.json` that need to be marked as processed as soon * other format properties in `package.json` that need to be marked as processed as soon as the
* as of the former being processed. * former has been processed.
*/ */
function getPropertiesToProcessAndMarkAsProcessed( function getPropertiesToProcess(
packageJson: EntryPointPackageJson, propertiesToConsider: EntryPointJsonProperty[]): { packageJson: EntryPointPackageJson, propertiesToConsider: EntryPointJsonProperty[]): {
propertiesToProcess: EntryPointJsonProperty[]; propertiesToProcess: EntryPointJsonProperty[];
propertyToPropertiesToMarkAsProcessed: Map<EntryPointJsonProperty, EntryPointJsonProperty[]>; equivalentPropertiesMap: Map<EntryPointJsonProperty, EntryPointJsonProperty[]>;
} { } {
const formatPathsToConsider = new Set<string>(); const formatPathsToConsider = new Set<string>();
@ -413,13 +413,12 @@ function getPropertiesToProcessAndMarkAsProcessed(
list.push(prop); list.push(prop);
} }
const propertyToPropertiesToMarkAsProcessed = const equivalentPropertiesMap = new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>();
new Map<EntryPointJsonProperty, EntryPointJsonProperty[]>();
for (const prop of propertiesToConsider) { for (const prop of propertiesToConsider) {
const formatPath = packageJson[prop] !; const formatPath = packageJson[prop] !;
const propertiesToMarkAsProcessed = formatPathToProperties[formatPath]; const equivalentProperties = formatPathToProperties[formatPath];
propertyToPropertiesToMarkAsProcessed.set(prop, propertiesToMarkAsProcessed); equivalentPropertiesMap.set(prop, equivalentProperties);
} }
return {propertiesToProcess, propertyToPropertiesToMarkAsProcessed}; return {propertiesToProcess, equivalentPropertiesMap};
} }

View File

@ -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 {AbsoluteFsPath, FileSystem, dirname} from '../../../src/ngtsc/file_system'; import {AbsoluteFsPath, FileSystem, dirname} from '../../../src/ngtsc/file_system';
import {EntryPointJsonProperty, EntryPointPackageJson} from './entry_point'; import {EntryPointPackageJson, PackageJsonFormatProperties} from './entry_point';
export const NGCC_VERSION = '0.0.0-PLACEHOLDER'; export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
@ -23,7 +23,7 @@ export const NGCC_VERSION = '0.0.0-PLACEHOLDER';
* @throws Error if the entry-point has already been processed with a different ngcc version. * @throws Error if the entry-point has already been processed with a different ngcc version.
*/ */
export function hasBeenProcessed( export function hasBeenProcessed(
packageJson: EntryPointPackageJson, format: EntryPointJsonProperty | 'typings', packageJson: EntryPointPackageJson, format: PackageJsonFormatProperties,
entryPointPath: AbsoluteFsPath): boolean { entryPointPath: AbsoluteFsPath): boolean {
if (!packageJson.__processed_by_ivy_ngcc__) { if (!packageJson.__processed_by_ivy_ngcc__) {
return false; return false;
@ -50,7 +50,7 @@ export function hasBeenProcessed(
*/ */
export function markAsProcessed( export function markAsProcessed(
fs: FileSystem, packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath, fs: FileSystem, packageJson: EntryPointPackageJson, packageJsonPath: AbsoluteFsPath,
properties: (EntryPointJsonProperty | 'typings')[]) { properties: PackageJsonFormatProperties[]) {
const processed = const processed =
packageJson.__processed_by_ivy_ngcc__ || (packageJson.__processed_by_ivy_ngcc__ = {}); packageJson.__processed_by_ivy_ngcc__ || (packageJson.__processed_by_ivy_ngcc__ = {});

View File

@ -7,7 +7,7 @@
*/ */
import * as vm from 'vm'; import * as vm from 'vm';
import {AbsoluteFsPath, FileSystem, dirname, join, resolve} from '../../../src/ngtsc/file_system'; import {AbsoluteFsPath, FileSystem, dirname, join, resolve} from '../../../src/ngtsc/file_system';
import {PackageJsonFormatProperties} from './entry_point'; import {PackageJsonFormatPropertiesMap} from './entry_point';
/** /**
* The format of a project level configuration file. * The format of a project level configuration file.
@ -41,7 +41,7 @@ export interface NgccEntryPointConfig {
* This property, if provided, holds values that will override equivalent properties in an * This property, if provided, holds values that will override equivalent properties in an
* entry-point's package.json file. * entry-point's package.json file.
*/ */
override?: PackageJsonFormatProperties; override?: PackageJsonFormatPropertiesMap;
} }
const NGCC_CONFIG_FILENAME = 'ngcc.config.js'; const NGCC_CONFIG_FILENAME = 'ngcc.config.js';
@ -121,4 +121,4 @@ export class NgccConfiguration {
} }
return processedEntryPoints; return processedEntryPoints;
} }
} }

View File

@ -38,7 +38,7 @@ export interface EntryPoint {
compiledByAngular: boolean; compiledByAngular: boolean;
} }
export interface PackageJsonFormatProperties { export interface PackageJsonFormatPropertiesMap {
fesm2015?: string; fesm2015?: string;
fesm5?: string; fesm5?: string;
es2015?: string; // if exists then it is actually FESM2015 es2015?: string; // if exists then it is actually FESM2015
@ -50,16 +50,18 @@ export interface PackageJsonFormatProperties {
typings?: string; // TypeScript .d.ts files typings?: string; // TypeScript .d.ts files
} }
export type PackageJsonFormatProperties = keyof PackageJsonFormatPropertiesMap;
/** /**
* The properties that may be loaded from the `package.json` file. * The properties that may be loaded from the `package.json` file.
*/ */
export interface EntryPointPackageJson extends PackageJsonFormatProperties { export interface EntryPointPackageJson extends PackageJsonFormatPropertiesMap {
name: string; name: string;
scripts?: Record<string, string>; scripts?: Record<string, string>;
__processed_by_ivy_ngcc__?: Record<string, string>; __processed_by_ivy_ngcc__?: Record<string, string>;
} }
export type EntryPointJsonProperty = Exclude<keyof PackageJsonFormatProperties, 'types'|'typings'>; export type EntryPointJsonProperty = Exclude<PackageJsonFormatProperties, 'types'|'typings'>;
// We need to keep the elements of this const and the `EntryPointJsonProperty` type in sync. // We need to keep the elements of this const and the `EntryPointJsonProperty` type in sync.
export const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[] = export const SUPPORTED_FORMAT_PROPERTIES: EntryPointJsonProperty[] =
['fesm2015', 'fesm5', 'es2015', 'esm2015', 'esm5', 'main', 'module']; ['fesm2015', 'fesm5', 'es2015', 'esm2015', 'esm5', 'main', 'module'];

View File

@ -6,8 +6,7 @@
* 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 {AbsoluteFsPath, FileSystem, NgtscCompilerHost, absoluteFrom} from '../../../src/ngtsc/file_system';
import {NgtscCompilerHost} from '../../../src/ngtsc/file_system/src/compiler_host';
import {PathMappings} from '../utils'; import {PathMappings} from '../utils';
import {BundleProgram, makeBundleProgram} from './bundle_program'; import {BundleProgram, makeBundleProgram} from './bundle_program';
import {EntryPoint, EntryPointFormat} from './entry_point'; import {EntryPoint, EntryPointFormat} from './entry_point';

View File

@ -7,8 +7,7 @@
*/ */
import * as ts from 'typescript'; import * as ts from 'typescript';
import {FileSystem} from '../../../src/ngtsc/file_system'; import {FileSystem, NgtscCompilerHost} from '../../../src/ngtsc/file_system';
import {NgtscCompilerHost} from '../../../src/ngtsc/file_system/src/compiler_host';
import {isRelativePath} from '../utils'; import {isRelativePath} from '../utils';
/** /**