fix(ngcc): allow deep-import warnings to be ignored (#35683)

This commit adds a new ngcc configuration, `ignorableDeepImportMatchers`
for packages. This is a list of regular expressions matching deep imports
that can be safely ignored from that package. Deep imports that are not
ignored cause a warning to be logged.

// FW-1892

Fixes #35615

PR Close #35683
This commit is contained in:
Pete Bacon Darwin
2020-02-25 15:51:54 +00:00
committed by atscott
parent 0b97d07ad6
commit 20b0c80b0b
6 changed files with 119 additions and 24 deletions

View File

@ -9,6 +9,7 @@
import {DepGraph} from 'dependency-graph';
import {AbsoluteFsPath, FileSystem, resolve} from '../../../src/ngtsc/file_system';
import {Logger} from '../logging/logger';
import {NgccConfiguration} from '../packages/configuration';
import {EntryPoint, EntryPointFormat, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from '../packages/entry_point';
import {PartiallyOrderedList} from '../utils';
import {DependencyHost, DependencyInfo, createDependencyInfo} from './dependency_host';
@ -81,7 +82,7 @@ export interface SortedEntryPointsInfo extends DependencyDiagnostics {
*/
export class DependencyResolver {
constructor(
private fs: FileSystem, private logger: Logger,
private fs: FileSystem, private logger: Logger, private config: NgccConfiguration,
private hosts: Partial<Record<EntryPointFormat, DependencyHost>>,
private typingsHost: DependencyHost) {}
/**
@ -176,11 +177,14 @@ export class DependencyResolver {
});
}
if (deepImports.size) {
const imports = Array.from(deepImports).map(i => `'${i}'`).join(', ');
this.logger.warn(
`Entry point '${entryPoint.name}' contains deep imports into ${imports}. ` +
`This is probably not a problem, but may cause the compilation of entry points to be out of order.`);
if (deepImports.size > 0) {
const notableDeepImports = this.filterIgnorableDeepImports(entryPoint, deepImports);
if (notableDeepImports.length > 0) {
const imports = notableDeepImports.map(i => `'${i}'`).join(', ');
this.logger.warn(
`Entry point '${entryPoint.name}' contains deep imports into ${imports}. ` +
`This is probably not a problem, but may cause the compilation of entry points to be out of order.`);
}
}
});
@ -210,6 +214,18 @@ export class DependencyResolver {
throw new Error(
`There is no appropriate source code format in '${entryPoint.path}' entry-point.`);
}
/**
* Filter out the deepImports that can be ignored, according to this entryPoint's config.
*/
private filterIgnorableDeepImports(entryPoint: EntryPoint, deepImports: Set<AbsoluteFsPath>):
AbsoluteFsPath[] {
const version = (entryPoint.packageJson.version || null) as string | null;
const packageConfig = this.config.getConfig(entryPoint.package, version);
const matchers = packageConfig.ignorableDeepImportMatchers || [];
return Array.from(deepImports)
.filter(deepImport => !matchers.some(matcher => matcher.test(deepImport)));
}
}
interface DependencyGraph extends DependencyDiagnostics {

View File

@ -150,7 +150,7 @@ export function mainNgcc(
const fileSystem = getFileSystem();
const absBasePath = absoluteFrom(basePath);
const config = new NgccConfiguration(fileSystem, dirname(absBasePath));
const dependencyResolver = getDependencyResolver(fileSystem, logger, pathMappings);
const dependencyResolver = getDependencyResolver(fileSystem, logger, config, pathMappings);
// Bail out early if the work is already done.
const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider);
@ -355,7 +355,7 @@ function getExecutor(
}
function getDependencyResolver(
fileSystem: FileSystem, logger: Logger,
fileSystem: FileSystem, logger: Logger, config: NgccConfiguration,
pathMappings: PathMappings | undefined): DependencyResolver {
const moduleResolver = new ModuleResolver(fileSystem, pathMappings);
const esmDependencyHost = new EsmDependencyHost(fileSystem, moduleResolver);
@ -363,7 +363,7 @@ function getDependencyResolver(
const commonJsDependencyHost = new CommonJsDependencyHost(fileSystem, moduleResolver);
const dtsDependencyHost = new DtsDependencyHost(fileSystem, pathMappings);
return new DependencyResolver(
fileSystem, logger, {
fileSystem, logger, config, {
esm5: esmDependencyHost,
esm2015: esmDependencyHost,
umd: umdDependencyHost,

View File

@ -13,7 +13,12 @@ import {PackageJsonFormatPropertiesMap} from './entry_point';
/**
* The format of a project level configuration file.
*/
export interface NgccProjectConfig<T = NgccPackageConfig> { packages: {[packagePath: string]: T}; }
export interface NgccProjectConfig<T = NgccPackageConfig> {
/**
* The packages that are configured by this project config.
*/
packages: {[packagePath: string]: T};
}
/**
* The format of a package level configuration file.
@ -27,6 +32,11 @@ export interface NgccPackageConfig {
* will be absolute.
*/
entryPoints: {[entryPointPath: string]: NgccEntryPointConfig;};
/**
* A collection of regexes that match deep imports to ignore, for this package, rather than
* displaying a warning.
*/
ignorableDeepImportMatchers?: RegExp[];
}
/**
@ -201,7 +211,8 @@ export class NgccConfiguration {
const absPackagePath = resolve(baseDir, 'node_modules', packagePath);
const entryPoints = this.processEntryPoints(absPackagePath, packageConfig);
processedConfig.packages[absPackagePath] = processedConfig.packages[absPackagePath] || [];
processedConfig.packages[absPackagePath].push({versionRange, entryPoints});
processedConfig.packages[absPackagePath].push(
{...packageConfig, versionRange, entryPoints});
}
}
return processedConfig;