@@ -13,6 +13,8 @@ import {
1313 PropertyWrite ,
1414 TmplAstBoundAttribute ,
1515 TmplAstBoundEvent ,
16+ TmplAstComponent ,
17+ TmplAstDirective ,
1618 TmplAstElement ,
1719 TmplAstForLoopBlock ,
1820 TmplAstForLoopBlockEmpty ,
@@ -23,6 +25,7 @@ import {
2325 TmplAstReference ,
2426 TmplAstSwitchBlockCase ,
2527 TmplAstTemplate ,
28+ TmplAstTextAttribute ,
2629 TmplAstVariable ,
2730 TmplAstViewportDeferredTrigger ,
2831} from '@angular/compiler' ;
@@ -125,7 +128,7 @@ export interface OutOfBandDiagnosticRecorder {
125128 /** Reports required inputs that haven't been bound. */
126129 missingRequiredInputs (
127130 id : TypeCheckId ,
128- element : TmplAstElement | TmplAstTemplate ,
131+ element : TmplAstElement | TmplAstTemplate | TmplAstComponent | TmplAstDirective ,
129132 directiveName : string ,
130133 isComponent : boolean ,
131134 inputAliases : string [ ] ,
@@ -185,6 +188,34 @@ export interface OutOfBandDiagnosticRecorder {
185188 * @param current the `TmplAstLetDeclaration` which is invalid.
186189 */
187190 conflictingDeclaration ( id : TypeCheckId , current : TmplAstLetDeclaration ) : void ;
191+
192+ /**
193+ * Reports that a named template dependency (e.g. `<Missing/>`) is not available.
194+ * @param id Type checking ID of the template in which the dependency is declared.
195+ * @param node Node that declares the dependency.
196+ */
197+ missingNamedTemplateDependency ( id : TypeCheckId , node : TmplAstComponent | TmplAstDirective ) : void ;
198+
199+ /**
200+ * Reports that a templace dependency of the wrong kind has been referenced at a specific position
201+ * (e.g. `<SomeDirective/>`).
202+ * @param id Type checking ID of the template in which the dependency is declared.
203+ * @param node Node that declares the dependency.
204+ */
205+ incorrectTemplateDependencyType ( id : TypeCheckId , node : TmplAstComponent | TmplAstDirective ) : void ;
206+
207+ /**
208+ * Reports a binding inside directive syntax that does not match any of the inputs/outputs of
209+ * the directive.
210+ * @param id Type checking ID of the template in which the directive was defined.
211+ * @param directive Directive that contains the binding.
212+ * @param node Node declaring the binding.
213+ */
214+ unclaimedDirectiveBinding (
215+ id : TypeCheckId ,
216+ directive : TmplAstDirective ,
217+ node : TmplAstBoundAttribute | TmplAstTextAttribute | TmplAstBoundEvent ,
218+ ) : void ;
188219}
189220
190221export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecorder {
@@ -467,7 +498,7 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
467498
468499 missingRequiredInputs (
469500 id : TypeCheckId ,
470- element : TmplAstElement | TmplAstTemplate ,
501+ element : TmplAstElement | TmplAstTemplate | TmplAstComponent | TmplAstDirective ,
471502 directiveName : string ,
472503 isComponent : boolean ,
473504 inputAliases : string [ ] ,
@@ -656,6 +687,58 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
656687 ) ,
657688 ) ;
658689 }
690+
691+ missingNamedTemplateDependency ( id : TypeCheckId , node : TmplAstComponent | TmplAstDirective ) : void {
692+ this . _diagnostics . push (
693+ makeTemplateDiagnostic (
694+ id ,
695+ this . resolver . getTemplateSourceMapping ( id ) ,
696+ node . startSourceSpan ,
697+ ts . DiagnosticCategory . Error ,
698+ ngErrorCode ( ErrorCode . MISSING_NAMED_TEMPLATE_DEPENDENCY ) ,
699+ // Wording is meant to mimic the wording TS uses in their diagnostic for missing symbols.
700+ `Cannot find name "${ node instanceof TmplAstDirective ? node . name : node . componentName } ".` ,
701+ ) ,
702+ ) ;
703+ }
704+
705+ incorrectTemplateDependencyType (
706+ id : TypeCheckId ,
707+ node : TmplAstComponent | TmplAstDirective ,
708+ ) : void {
709+ this . _diagnostics . push (
710+ makeTemplateDiagnostic (
711+ id ,
712+ this . resolver . getTemplateSourceMapping ( id ) ,
713+ node . startSourceSpan ,
714+ ts . DiagnosticCategory . Error ,
715+ ngErrorCode ( ErrorCode . INCORRECT_NAMED_TEMPLATE_DEPENDENCY_TYPE ) ,
716+ `Incorrect reference type. Type must be an ${ node instanceof TmplAstComponent ? '@Component' : '@Directive' } .` ,
717+ ) ,
718+ ) ;
719+ }
720+
721+ unclaimedDirectiveBinding (
722+ id : TypeCheckId ,
723+ directive : TmplAstDirective ,
724+ node : TmplAstBoundAttribute | TmplAstTextAttribute | TmplAstBoundEvent ,
725+ ) : void {
726+ const errorMsg =
727+ `Directive ${ directive . name } does not have an ` +
728+ `${ node instanceof TmplAstBoundEvent ? 'output' : 'input' } named "${ node . name } ". ` +
729+ `Bindings to directives must target existing inputs or outputs.` ;
730+
731+ this . _diagnostics . push (
732+ makeTemplateDiagnostic (
733+ id ,
734+ this . resolver . getTemplateSourceMapping ( id ) ,
735+ node . keySpan || node . sourceSpan ,
736+ ts . DiagnosticCategory . Error ,
737+ ngErrorCode ( ErrorCode . UNCLAIMED_DIRECTIVE_BINDING ) ,
738+ errorMsg ,
739+ ) ,
740+ ) ;
741+ }
659742}
660743
661744function makeInlineDiagnostic (
0 commit comments