fix(ivy): template type-check errors from TS should not use NG error codes (#35146)
A bug previously caused the template type-checking diagnostics produced by TypeScript for template expressions to use -99-prefixed error codes. These codes are converted to "NG" errors instead of "TS" errors during diagnostic printing. This commit fixes the issue. PR Close #35146
This commit is contained in:
parent
1f6da8c7d5
commit
c35671c0a4
|
@ -8,7 +8,6 @@
|
||||||
import {AbsoluteSourceSpan, ParseSourceSpan} from '@angular/compiler';
|
import {AbsoluteSourceSpan, ParseSourceSpan} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
|
||||||
import {getTokenAtPosition} from '../../util/src/typescript';
|
import {getTokenAtPosition} from '../../util/src/typescript';
|
||||||
|
|
||||||
import {ExternalTemplateSourceMapping, TemplateId, TemplateSourceMapping} from './api';
|
import {ExternalTemplateSourceMapping, TemplateId, TemplateSourceMapping} from './api';
|
||||||
|
@ -146,7 +145,7 @@ export function translateDiagnostic(
|
||||||
*/
|
*/
|
||||||
export function makeTemplateDiagnostic(
|
export function makeTemplateDiagnostic(
|
||||||
mapping: TemplateSourceMapping, span: ParseSourceSpan, category: ts.DiagnosticCategory,
|
mapping: TemplateSourceMapping, span: ParseSourceSpan, category: ts.DiagnosticCategory,
|
||||||
code: ErrorCode, messageText: string | ts.DiagnosticMessageChain, relatedMessage?: {
|
code: number, messageText: string | ts.DiagnosticMessageChain, relatedMessage?: {
|
||||||
text: string,
|
text: string,
|
||||||
span: ParseSourceSpan,
|
span: ParseSourceSpan,
|
||||||
}): TemplateDiagnostic {
|
}): TemplateDiagnostic {
|
||||||
|
@ -167,7 +166,9 @@ export function makeTemplateDiagnostic(
|
||||||
// directly into the bytes of the source file.
|
// directly into the bytes of the source file.
|
||||||
return {
|
return {
|
||||||
source: 'ngtsc',
|
source: 'ngtsc',
|
||||||
code: ngErrorCode(code), category, messageText,
|
code,
|
||||||
|
category,
|
||||||
|
messageText,
|
||||||
file: mapping.node.getSourceFile(),
|
file: mapping.node.getSourceFile(),
|
||||||
componentFile: mapping.node.getSourceFile(),
|
componentFile: mapping.node.getSourceFile(),
|
||||||
start: span.start.offset,
|
start: span.start.offset,
|
||||||
|
@ -216,7 +217,8 @@ export function makeTemplateDiagnostic(
|
||||||
return {
|
return {
|
||||||
source: 'ngtsc',
|
source: 'ngtsc',
|
||||||
category,
|
category,
|
||||||
code: ngErrorCode(code), messageText,
|
code,
|
||||||
|
messageText,
|
||||||
file: sf,
|
file: sf,
|
||||||
componentFile: componentSf,
|
componentFile: componentSf,
|
||||||
start: span.start.offset,
|
start: span.start.offset,
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import {DomElementSchemaRegistry, ParseSourceSpan, SchemaMetadata, TmplAstElement} from '@angular/compiler';
|
import {DomElementSchemaRegistry, ParseSourceSpan, SchemaMetadata, TmplAstElement} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode} from '../../diagnostics';
|
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
||||||
|
|
||||||
import {TemplateId} from './api';
|
import {TemplateId} from './api';
|
||||||
import {TemplateSourceResolver, makeTemplateDiagnostic} from './diagnostics';
|
import {TemplateSourceResolver, makeTemplateDiagnostic} from './diagnostics';
|
||||||
|
@ -92,7 +92,7 @@ export class RegistryDomSchemaChecker implements DomSchemaChecker {
|
||||||
|
|
||||||
const diag = makeTemplateDiagnostic(
|
const diag = makeTemplateDiagnostic(
|
||||||
mapping, element.sourceSpan, ts.DiagnosticCategory.Error,
|
mapping, element.sourceSpan, ts.DiagnosticCategory.Error,
|
||||||
ErrorCode.SCHEMA_INVALID_ELEMENT, errorMsg);
|
ngErrorCode(ErrorCode.SCHEMA_INVALID_ELEMENT), errorMsg);
|
||||||
this._diagnostics.push(diag);
|
this._diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,8 @@ export class RegistryDomSchemaChecker implements DomSchemaChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
const diag = makeTemplateDiagnostic(
|
const diag = makeTemplateDiagnostic(
|
||||||
mapping, span, ts.DiagnosticCategory.Error, ErrorCode.SCHEMA_INVALID_ATTRIBUTE, errorMsg);
|
mapping, span, ts.DiagnosticCategory.Error,
|
||||||
|
ngErrorCode(ErrorCode.SCHEMA_INVALID_ATTRIBUTE), errorMsg);
|
||||||
this._diagnostics.push(diag);
|
this._diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
|
||||||
const errorMsg = `No directive found with exportAs '${value}'.`;
|
const errorMsg = `No directive found with exportAs '${value}'.`;
|
||||||
this._diagnostics.push(makeTemplateDiagnostic(
|
this._diagnostics.push(makeTemplateDiagnostic(
|
||||||
mapping, ref.valueSpan || ref.sourceSpan, ts.DiagnosticCategory.Error,
|
mapping, ref.valueSpan || ref.sourceSpan, ts.DiagnosticCategory.Error,
|
||||||
ErrorCode.MISSING_REFERENCE_TARGET, errorMsg));
|
ngErrorCode(ErrorCode.MISSING_REFERENCE_TARGET), errorMsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
missingPipe(templateId: TemplateId, ast: BindingPipe): void {
|
missingPipe(templateId: TemplateId, ast: BindingPipe): void {
|
||||||
|
@ -79,7 +79,8 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
|
||||||
`Assertion failure: no SourceLocation found for usage of pipe '${ast.name}'.`);
|
`Assertion failure: no SourceLocation found for usage of pipe '${ast.name}'.`);
|
||||||
}
|
}
|
||||||
this._diagnostics.push(makeTemplateDiagnostic(
|
this._diagnostics.push(makeTemplateDiagnostic(
|
||||||
mapping, sourceSpan, ts.DiagnosticCategory.Error, ErrorCode.MISSING_PIPE, errorMsg));
|
mapping, sourceSpan, ts.DiagnosticCategory.Error, ngErrorCode(ErrorCode.MISSING_PIPE),
|
||||||
|
errorMsg));
|
||||||
}
|
}
|
||||||
|
|
||||||
illegalAssignmentToTemplateVar(
|
illegalAssignmentToTemplateVar(
|
||||||
|
@ -93,8 +94,8 @@ export class OutOfBandDiagnosticRecorderImpl implements OutOfBandDiagnosticRecor
|
||||||
throw new Error(`Assertion failure: no SourceLocation found for property binding.`);
|
throw new Error(`Assertion failure: no SourceLocation found for property binding.`);
|
||||||
}
|
}
|
||||||
this._diagnostics.push(makeTemplateDiagnostic(
|
this._diagnostics.push(makeTemplateDiagnostic(
|
||||||
mapping, sourceSpan, ts.DiagnosticCategory.Error, ErrorCode.WRITE_TO_READ_ONLY_VARIABLE,
|
mapping, sourceSpan, ts.DiagnosticCategory.Error,
|
||||||
errorMsg, {
|
ngErrorCode(ErrorCode.WRITE_TO_READ_ONLY_VARIABLE), errorMsg, {
|
||||||
text: `The variable ${assignment.name} is declared here.`,
|
text: `The variable ${assignment.name} is declared here.`,
|
||||||
span: target.valueSpan || target.sourceSpan,
|
span: target.valueSpan || target.sourceSpan,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -135,6 +135,8 @@ export declare class AnimationEvent {
|
||||||
const diags = env.driveDiagnostics();
|
const diags = env.driveDiagnostics();
|
||||||
expect(diags.length).toBe(1);
|
expect(diags.length).toBe(1);
|
||||||
expect(diags[0].messageText).toEqual(`Type 'string' is not assignable to type 'number'.`);
|
expect(diags[0].messageText).toEqual(`Type 'string' is not assignable to type 'number'.`);
|
||||||
|
// The reported error code should be in the TS error space, not a -99 "NG" code.
|
||||||
|
expect(diags[0].code).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support inputs and outputs with names that are not JavaScript identifiers', () => {
|
it('should support inputs and outputs with names that are not JavaScript identifiers', () => {
|
||||||
|
|
Loading…
Reference in New Issue