diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/diagnostics.ts b/packages/compiler-cli/src/ngtsc/annotations/src/diagnostics.ts index 6a7a221345..5a41d31391 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/diagnostics.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/diagnostics.ts @@ -8,7 +8,7 @@ import * as ts from 'typescript'; -import {ErrorCode, makeDiagnostic} from '../../diagnostics'; +import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {Reference} from '../../imports'; import {InjectableClassRegistry, MetadataReader} from '../../metadata'; import {PartialEvaluator} from '../../partial_evaluator'; @@ -44,7 +44,7 @@ Either add the @Injectable() decorator to '${ provider.node.name .text}', or configure a different provider (such as a provider with 'useFactory'). `, - [{node: provider.node, messageText: `'${provider.node.name.text}' is declared here.`}])); + [makeRelatedInformation(provider.node, `'${provider.node.name.text}' is declared here.`)])); } return diagnostics; diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts b/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts index c12cb44722..e78aad3f73 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/ng_module.ts @@ -9,7 +9,7 @@ import {compileInjector, compileNgModule, CUSTOM_ELEMENTS_SCHEMA, Expression, ExternalExpr, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NO_ERRORS_SCHEMA, R3Identifiers, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, SchemaMetadata, Statement, STRING_TYPE, WrappedNodeExpr} from '@angular/compiler'; import * as ts from 'typescript'; -import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics'; +import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {DefaultImportRecorder, Reference, ReferenceEmitter} from '../../imports'; import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata'; import {PartialEvaluator, ResolvedValue, ResolvedValueArray} from '../../partial_evaluator'; @@ -133,10 +133,8 @@ export class NgModuleDecoratorHandler implements `Cannot declare '${ ref.node.name .text}' in an NgModule as it's not a part of the current compilation.`, - [{ - node: ref.node.name, - messageText: `'${ref.node.name.text}' is declared here.`, - }])); + [makeRelatedInformation( + ref.node.name, `'${ref.node.name.text}' is declared here.`)])); } } } diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/util.ts b/packages/compiler-cli/src/ngtsc/annotations/src/util.ts index 2c9e9cdae6..53c93fc868 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/util.ts @@ -9,7 +9,7 @@ import {Expression, ExternalExpr, LiteralExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, ReadPropExpr, WrappedNodeExpr} from '@angular/compiler'; import * as ts from 'typescript'; -import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics'; +import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {DefaultImportRecorder, ImportFlags, Reference, ReferenceEmitter} from '../../imports'; import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator'; import {ClassDeclaration, CtorParameter, Decorator, Import, isNamedClassDeclaration, ReflectionHost, TypeValueReference} from '../../reflection'; @@ -408,7 +408,7 @@ export function wrapFunctionExpressionsInParens(expression: ts.Expression): ts.E */ export function makeDuplicateDeclarationError( node: ClassDeclaration, data: DeclarationData[], kind: string): ts.Diagnostic { - const context: {node: ts.Node; messageText: string;}[] = []; + const context: ts.DiagnosticRelatedInformation[] = []; for (const decl of data) { if (decl.rawDeclarations === null) { continue; @@ -416,11 +416,10 @@ export function makeDuplicateDeclarationError( // Try to find the reference to the declaration within the declarations array, to hang the // error there. If it can't be found, fall back on using the NgModule's name. const contextNode = decl.ref.getOriginForDiagnostics(decl.rawDeclarations, decl.ngModule.name); - context.push({ - node: contextNode, - messageText: `'${node.name.text}' is listed in the declarations of the NgModule '${ - decl.ngModule.name.text}'.`, - }); + context.push(makeRelatedInformation( + contextNode, + `'${node.name.text}' is listed in the declarations of the NgModule '${ + decl.ngModule.name.text}'.`)); } // Finally, produce the diagnostic. diff --git a/packages/compiler-cli/src/ngtsc/diagnostics/index.ts b/packages/compiler-cli/src/ngtsc/diagnostics/index.ts index e9c30007a2..991719e867 100644 --- a/packages/compiler-cli/src/ngtsc/diagnostics/index.ts +++ b/packages/compiler-cli/src/ngtsc/diagnostics/index.ts @@ -6,6 +6,6 @@ * found in the LICENSE file at https://angular.io/license */ -export {FatalDiagnosticError, isFatalDiagnosticError, makeDiagnostic} from './src/error'; +export {FatalDiagnosticError, isFatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from './src/error'; export {ErrorCode, ngErrorCode} from './src/error_code'; export {replaceTsWithNgInErrors} from './src/util'; diff --git a/packages/compiler-cli/src/ngtsc/diagnostics/src/error.ts b/packages/compiler-cli/src/ngtsc/diagnostics/src/error.ts index 734466e230..6dab84bd03 100644 --- a/packages/compiler-cli/src/ngtsc/diagnostics/src/error.ts +++ b/packages/compiler-cli/src/ngtsc/diagnostics/src/error.ts @@ -23,33 +23,32 @@ export class FatalDiagnosticError { } } -export function makeDiagnostic(code: ErrorCode, node: ts.Node, messageText: string, relatedInfo?: { - node: ts.Node, - messageText: string, -}[]): ts.DiagnosticWithLocation { +export function makeDiagnostic( + code: ErrorCode, node: ts.Node, messageText: string, + relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.DiagnosticWithLocation { node = ts.getOriginalNode(node); - const diag: ts.DiagnosticWithLocation = { + return { category: ts.DiagnosticCategory.Error, code: Number('-99' + code.valueOf()), file: ts.getOriginalNode(node).getSourceFile(), start: node.getStart(undefined, false), length: node.getWidth(), messageText, + relatedInformation, + }; +} + +export function makeRelatedInformation( + node: ts.Node, messageText: string): ts.DiagnosticRelatedInformation { + node = ts.getOriginalNode(node); + return { + category: ts.DiagnosticCategory.Message, + code: 0, + file: node.getSourceFile(), + start: node.getStart(), + length: node.getWidth(), + messageText, }; - if (relatedInfo !== undefined) { - diag.relatedInformation = relatedInfo.map(info => { - const infoNode = ts.getOriginalNode(info.node); - return { - category: ts.DiagnosticCategory.Message, - code: 0, - file: infoNode.getSourceFile(), - start: infoNode.getStart(), - length: infoNode.getWidth(), - messageText: info.messageText, - }; - }); - } - return diag; } export function isFatalDiagnosticError(err: any): err is FatalDiagnosticError { diff --git a/packages/compiler-cli/src/ngtsc/scope/src/local.ts b/packages/compiler-cli/src/ngtsc/scope/src/local.ts index 9287efb1ea..985058a157 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/local.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/local.ts @@ -9,7 +9,7 @@ import {ExternalExpr, SchemaMetadata} from '@angular/compiler'; import * as ts from 'typescript'; -import {ErrorCode, makeDiagnostic} from '../../diagnostics'; +import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {AliasingHost, Reexport, Reference, ReferenceEmitter} from '../../imports'; import {DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta} from '../../metadata'; import {ClassDeclaration} from '../../reflection'; @@ -358,7 +358,8 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop ngModule.ref.node.name .text}', but is not a directive, a component, or a pipe. ` + `Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.`, - [{node: decl.node.name, messageText: `'${decl.node.name.text}' is declared here.`}])); + [makeRelatedInformation( + decl.node.name, `'${decl.node.name.text}' is declared here.`)])); continue; } @@ -643,8 +644,8 @@ function reexportCollision( To fix this problem please re-export one or both classes directly from this file. `.trim(), [ - {node: refA.node.name, messageText: childMessageText}, - {node: refB.node.name, messageText: childMessageText}, + makeRelatedInformation(refA.node.name, childMessageText), + makeRelatedInformation(refB.node.name, childMessageText), ]); }