diff --git a/goldens/public-api/core/errors.md b/goldens/public-api/core/errors.md index db01fc33b2d..a5b3934aef5 100644 --- a/goldens/public-api/core/errors.md +++ b/goldens/public-api/core/errors.md @@ -89,6 +89,8 @@ export const enum RuntimeErrorCode { // (undocumented) MULTIPLE_COMPONENTS_MATCH = -300, // (undocumented) + MULTIPLE_MATCHING_PIPES = 313, + // (undocumented) MULTIPLE_PLATFORMS = 400, // (undocumented) NO_SUPPORTING_DIFFER_FACTORY = 901, diff --git a/packages/core/src/errors.ts b/packages/core/src/errors.ts index c8ebac80a4d..eefc9d84a97 100644 --- a/packages/core/src/errors.ts +++ b/packages/core/src/errors.ts @@ -57,6 +57,7 @@ export const enum RuntimeErrorCode { HOST_DIRECTIVE_COMPONENT = 310, HOST_DIRECTIVE_UNDEFINED_BINDING = 311, HOST_DIRECTIVE_CONFLICTING_ALIAS = 312, + MULTIPLE_MATCHING_PIPES = 313, // Bootstrap Errors MULTIPLE_PLATFORMS = 400, diff --git a/packages/core/src/render3/pipe.ts b/packages/core/src/render3/pipe.ts index a419dbe4430..86679a7d771 100644 --- a/packages/core/src/render3/pipe.ts +++ b/packages/core/src/render3/pipe.ts @@ -8,7 +8,7 @@ import {PipeTransform} from '../change_detection/pipe_transform'; import {setInjectImplementation} from '../di/inject_switch'; -import {RuntimeError, RuntimeErrorCode} from '../errors'; +import {formatRuntimeError, RuntimeError, RuntimeErrorCode} from '../errors'; import {Type} from '../interface/type'; import {getFactoryDef} from './definition_factory'; @@ -76,6 +76,14 @@ export function ɵɵpipe(index: number, pipeName: string): any { */ function getPipeDef(name: string, registry: PipeDefList|null): PipeDef|undefined { if (registry) { + if (ngDevMode) { + const pipes = registry.filter(pipe => pipe.name === name); + // TODO: Throw an error in the next major + if (pipes.length > 1) { + console.warn(formatRuntimeError( + RuntimeErrorCode.MULTIPLE_MATCHING_PIPES, getMultipleMatchingPipesMessage(name))); + } + } for (let i = registry.length - 1; i >= 0; i--) { const pipeDef = registry[i]; if (name === pipeDef.name) { @@ -88,6 +96,26 @@ function getPipeDef(name: string, registry: PipeDefList|null): PipeDef|unde } } +/** + * Generates a helpful error message for the user when multiple pipes match the name. + * + * @param name Name of the pipe + * @returns The error message + */ +function getMultipleMatchingPipesMessage(name: string) { + const lView = getLView(); + const declarationLView = lView[DECLARATION_COMPONENT_VIEW] as LView>; + const context = declarationLView[CONTEXT]; + const hostIsStandalone = isHostComponentStandalone(lView); + const componentInfoMessage = context ? ` in the '${context.constructor.name}' component` : ''; + const verifyMessage = `check ${ + hostIsStandalone ? '\'@Component.imports\' of this component' : + 'the imports of this module'}`; + const errorMessage = + `Multiple pipes match the name \`${name}\`${componentInfoMessage}. ${verifyMessage}`; + return errorMessage; +} + /** * Generates a helpful error message for the user when a pipe is not found. *