2016-11-22 09:10:23 -08:00
/ * *
* @license
* Copyright Google Inc . All Rights Reserved .
*
* 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
* /
2017-05-09 16:16:50 -07:00
import { NgAnalyzedModules , StaticSymbol } from '@angular/compiler' ;
2017-08-15 17:04:45 -07:00
import { DiagnosticTemplateInfo , getTemplateExpressionDiagnostics } from '@angular/compiler-cli/src/language_services' ;
2016-11-22 09:10:23 -08:00
2017-05-09 16:16:50 -07:00
import { AstResult } from './common' ;
2017-11-14 17:49:47 -08:00
import { Declarations , Diagnostic , DiagnosticKind , DiagnosticMessageChain , Diagnostics , Span , TemplateSource } from './types' ;
2017-05-09 16:16:50 -07:00
import { offsetSpan , spanOf } from './utils' ;
2016-11-22 09:10:23 -08:00
export interface AstProvider {
getTemplateAst ( template : TemplateSource , fileName : string ) : AstResult ;
}
export function getTemplateDiagnostics (
fileName : string , astProvider : AstProvider , templates : TemplateSource [ ] ) : Diagnostics {
const results : Diagnostics = [ ] ;
for ( const template of templates ) {
const ast = astProvider . getTemplateAst ( template , fileName ) ;
if ( ast ) {
if ( ast . parseErrors && ast . parseErrors . length ) {
results . push ( . . . ast . parseErrors . map < Diagnostic > (
e = > ( {
kind : DiagnosticKind.Error ,
2017-04-28 15:10:30 -07:00
span : offsetSpan ( spanOf ( e . span ) , template . span . start ) ,
2016-11-22 09:10:23 -08:00
message : e.msg
} ) ) ) ;
2017-05-09 16:16:50 -07:00
} else if ( ast . templateAst && ast . htmlAst ) {
const info : DiagnosticTemplateInfo = {
templateAst : ast.templateAst ,
htmlAst : ast.htmlAst ,
offset : template.span.start ,
query : template.query ,
members : template.members
} ;
const expressionDiagnostics = getTemplateExpressionDiagnostics ( info ) ;
2016-11-22 09:10:23 -08:00
results . push ( . . . expressionDiagnostics ) ;
}
if ( ast . errors ) {
results . push ( . . . ast . errors . map < Diagnostic > (
e = > ( { kind : e.kind , span : e.span || template . span , message : e.message } ) ) ) ;
}
}
}
return results ;
}
export function getDeclarationDiagnostics (
declarations : Declarations , modules : NgAnalyzedModules ) : Diagnostics {
const results : Diagnostics = [ ] ;
let directives : Set < StaticSymbol > | undefined = undefined ;
for ( const declaration of declarations ) {
2017-11-14 17:49:47 -08:00
const report = ( message : string | DiagnosticMessageChain , span? : Span ) = > {
2016-12-02 14:34:16 -08:00
results . push ( < Diagnostic > {
kind : DiagnosticKind.Error ,
span : span || declaration . declarationSpan , message
} ) ;
2016-11-22 09:10:23 -08:00
} ;
2016-12-02 14:34:16 -08:00
for ( const error of declaration . errors ) {
report ( error . message , error . span ) ;
2016-11-22 09:10:23 -08:00
}
if ( declaration . metadata ) {
if ( declaration . metadata . isComponent ) {
if ( ! modules . ngModuleByPipeOrDirective . has ( declaration . type ) ) {
report (
` Component ' ${ declaration . type . name } ' is not included in a module and will not be available inside a template. Consider adding it to a NgModule declaration ` ) ;
}
2017-11-22 12:09:49 -08:00
const { template , templateUrl } = declaration . metadata . template ! ;
if ( template === null && ! templateUrl ) {
report ( ` Component ' ${ declaration . type . name } ' must have a template or templateUrl ` ) ;
} else if ( template && templateUrl ) {
report (
` Component ' ${ declaration . type . name } ' must not have both template and templateUrl ` ) ;
2016-11-22 09:10:23 -08:00
}
} else {
if ( ! directives ) {
directives = new Set ( ) ;
modules . ngModules . forEach ( module = > {
module . declaredDirectives . forEach (
2017-03-24 09:57:32 -07:00
directive = > { directives ! . add ( directive . reference ) ; } ) ;
2016-11-22 09:10:23 -08:00
} ) ;
}
if ( ! directives . has ( declaration . type ) ) {
report (
` Directive ' ${ declaration . type . name } ' is not included in a module and will not be available inside a template. Consider adding it to a NgModule declaration ` ) ;
}
}
}
}
return results ;
}