refactor(compiler-cli): create diagnostics using `ts.DiagnosticRelatedInformation` (#37587)
Previously, an anonymous type was used for creating a diagnostic with related information. The anonymous type would then be translated into the necessary `ts.DiagnosticRelatedInformation` shape within `makeDiagnostic`. This commit switches the `makeDiagnostic` signature over to taking `ts.DiagnosticRelatedInformation` directly and introduces `makeRelatedInformation` to easily create such objects. This is done to aid in making upcoming work more readable. PR Close #37587
This commit is contained in:
parent
5103d908c8
commit
d2fb552116
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
|
||||||
import {Reference} from '../../imports';
|
import {Reference} from '../../imports';
|
||||||
import {InjectableClassRegistry, MetadataReader} from '../../metadata';
|
import {InjectableClassRegistry, MetadataReader} from '../../metadata';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
|
@ -44,7 +44,7 @@ Either add the @Injectable() decorator to '${
|
||||||
provider.node.name
|
provider.node.name
|
||||||
.text}', or configure a different provider (such as a provider with 'useFactory').
|
.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;
|
return diagnostics;
|
||||||
|
|
|
@ -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 {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 * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
|
||||||
import {DefaultImportRecorder, Reference, ReferenceEmitter} from '../../imports';
|
import {DefaultImportRecorder, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata';
|
import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata';
|
||||||
import {PartialEvaluator, ResolvedValue, ResolvedValueArray} from '../../partial_evaluator';
|
import {PartialEvaluator, ResolvedValue, ResolvedValueArray} from '../../partial_evaluator';
|
||||||
|
@ -133,10 +133,8 @@ export class NgModuleDecoratorHandler implements
|
||||||
`Cannot declare '${
|
`Cannot declare '${
|
||||||
ref.node.name
|
ref.node.name
|
||||||
.text}' in an NgModule as it's not a part of the current compilation.`,
|
.text}' in an NgModule as it's not a part of the current compilation.`,
|
||||||
[{
|
[makeRelatedInformation(
|
||||||
node: ref.node.name,
|
ref.node.name, `'${ref.node.name.text}' is declared here.`)]));
|
||||||
messageText: `'${ref.node.name.text}' is declared here.`,
|
|
||||||
}]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import {Expression, ExternalExpr, LiteralExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, ReadPropExpr, WrappedNodeExpr} from '@angular/compiler';
|
import {Expression, ExternalExpr, LiteralExpr, ParseLocation, ParseSourceFile, ParseSourceSpan, R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, ReadPropExpr, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
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 {DefaultImportRecorder, ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, CtorParameter, Decorator, Import, isNamedClassDeclaration, ReflectionHost, TypeValueReference} from '../../reflection';
|
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(
|
export function makeDuplicateDeclarationError(
|
||||||
node: ClassDeclaration, data: DeclarationData[], kind: string): ts.Diagnostic {
|
node: ClassDeclaration, data: DeclarationData[], kind: string): ts.Diagnostic {
|
||||||
const context: {node: ts.Node; messageText: string;}[] = [];
|
const context: ts.DiagnosticRelatedInformation[] = [];
|
||||||
for (const decl of data) {
|
for (const decl of data) {
|
||||||
if (decl.rawDeclarations === null) {
|
if (decl.rawDeclarations === null) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -416,11 +416,10 @@ export function makeDuplicateDeclarationError(
|
||||||
// Try to find the reference to the declaration within the declarations array, to hang the
|
// 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.
|
// 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);
|
const contextNode = decl.ref.getOriginForDiagnostics(decl.rawDeclarations, decl.ngModule.name);
|
||||||
context.push({
|
context.push(makeRelatedInformation(
|
||||||
node: contextNode,
|
contextNode,
|
||||||
messageText: `'${node.name.text}' is listed in the declarations of the NgModule '${
|
`'${node.name.text}' is listed in the declarations of the NgModule '${
|
||||||
decl.ngModule.name.text}'.`,
|
decl.ngModule.name.text}'.`));
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, produce the diagnostic.
|
// Finally, produce the diagnostic.
|
||||||
|
|
|
@ -6,6 +6,6 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* 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 {ErrorCode, ngErrorCode} from './src/error_code';
|
||||||
export {replaceTsWithNgInErrors} from './src/util';
|
export {replaceTsWithNgInErrors} from './src/util';
|
||||||
|
|
|
@ -23,33 +23,32 @@ export class FatalDiagnosticError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function makeDiagnostic(code: ErrorCode, node: ts.Node, messageText: string, relatedInfo?: {
|
export function makeDiagnostic(
|
||||||
node: ts.Node,
|
code: ErrorCode, node: ts.Node, messageText: string,
|
||||||
messageText: string,
|
relatedInformation?: ts.DiagnosticRelatedInformation[]): ts.DiagnosticWithLocation {
|
||||||
}[]): ts.DiagnosticWithLocation {
|
|
||||||
node = ts.getOriginalNode(node);
|
node = ts.getOriginalNode(node);
|
||||||
const diag: ts.DiagnosticWithLocation = {
|
return {
|
||||||
category: ts.DiagnosticCategory.Error,
|
category: ts.DiagnosticCategory.Error,
|
||||||
code: Number('-99' + code.valueOf()),
|
code: Number('-99' + code.valueOf()),
|
||||||
file: ts.getOriginalNode(node).getSourceFile(),
|
file: ts.getOriginalNode(node).getSourceFile(),
|
||||||
start: node.getStart(undefined, false),
|
start: node.getStart(undefined, false),
|
||||||
length: node.getWidth(),
|
length: node.getWidth(),
|
||||||
messageText,
|
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 {
|
export function isFatalDiagnosticError(err: any): err is FatalDiagnosticError {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import {ExternalExpr, SchemaMetadata} from '@angular/compiler';
|
import {ExternalExpr, SchemaMetadata} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics';
|
||||||
import {AliasingHost, Reexport, Reference, ReferenceEmitter} from '../../imports';
|
import {AliasingHost, Reexport, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta} from '../../metadata';
|
import {DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta} from '../../metadata';
|
||||||
import {ClassDeclaration} from '../../reflection';
|
import {ClassDeclaration} from '../../reflection';
|
||||||
|
@ -358,7 +358,8 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop
|
||||||
ngModule.ref.node.name
|
ngModule.ref.node.name
|
||||||
.text}', but is not a directive, a component, or a pipe. ` +
|
.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.`,
|
`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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,8 +644,8 @@ function reexportCollision(
|
||||||
To fix this problem please re-export one or both classes directly from this file.
|
To fix this problem please re-export one or both classes directly from this file.
|
||||||
`.trim(),
|
`.trim(),
|
||||||
[
|
[
|
||||||
{node: refA.node.name, messageText: childMessageText},
|
makeRelatedInformation(refA.node.name, childMessageText),
|
||||||
{node: refB.node.name, messageText: childMessageText},
|
makeRelatedInformation(refB.node.name, childMessageText),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue