fix(compiler): do not throw away render3 AST on errors (#39413)
Currently render3's `parseTemplate` throws away the parsed AST and returns an empty list of HTML nodes if HTML->R3 translation failed. This is not preferrable in some contexts like that of a language service, where we would like a well-formed AST even if it is has errors. PR Close #39413
This commit is contained in:
parent
0a63eeaff1
commit
19b88cef71
@ -2046,6 +2046,8 @@ export function parseTemplate(
|
|||||||
{leadingTriviaChars: LEADING_TRIVIA_CHARS, ...options, tokenizeExpansionForms: true});
|
{leadingTriviaChars: LEADING_TRIVIA_CHARS, ...options, tokenizeExpansionForms: true});
|
||||||
|
|
||||||
if (parseResult.errors && parseResult.errors.length > 0) {
|
if (parseResult.errors && parseResult.errors.length > 0) {
|
||||||
|
// TODO(ayazhafiz): we may not always want to bail out at this point (e.g. in
|
||||||
|
// the context of a language service).
|
||||||
return {
|
return {
|
||||||
interpolationConfig,
|
interpolationConfig,
|
||||||
preserveWhitespaces,
|
preserveWhitespaces,
|
||||||
@ -2084,23 +2086,11 @@ export function parseTemplate(
|
|||||||
|
|
||||||
const {nodes, errors, styleUrls, styles, ngContentSelectors} =
|
const {nodes, errors, styleUrls, styles, ngContentSelectors} =
|
||||||
htmlAstToRender3Ast(rootNodes, bindingParser);
|
htmlAstToRender3Ast(rootNodes, bindingParser);
|
||||||
if (errors && errors.length > 0) {
|
|
||||||
return {
|
|
||||||
interpolationConfig,
|
|
||||||
preserveWhitespaces,
|
|
||||||
template,
|
|
||||||
errors,
|
|
||||||
nodes: [],
|
|
||||||
styleUrls: [],
|
|
||||||
styles: [],
|
|
||||||
ngContentSelectors: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
interpolationConfig,
|
interpolationConfig,
|
||||||
preserveWhitespaces,
|
preserveWhitespaces,
|
||||||
errors: null,
|
errors: errors.length > 0 ? errors : null,
|
||||||
template,
|
template,
|
||||||
nodes,
|
nodes,
|
||||||
styleUrls,
|
styleUrls,
|
||||||
@ -2265,6 +2255,8 @@ export interface ParsedTemplate {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Any errors from parsing the template the first time.
|
* Any errors from parsing the template the first time.
|
||||||
|
*
|
||||||
|
* `null` if there are no errors. Otherwise, the array of errors is guaranteed to be non-empty.
|
||||||
*/
|
*/
|
||||||
errors: ParseError[]|null;
|
errors: ParseError[]|null;
|
||||||
|
|
||||||
|
@ -433,15 +433,16 @@ describe('findNodeAtPosition for expression AST', () => {
|
|||||||
expect(node).toBeInstanceOf(e.BindingPipe);
|
expect(node).toBeInstanceOf(e.BindingPipe);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should locate binding pipe without identifier',
|
it('should locate binding pipe without identifier', () => {
|
||||||
() => {
|
const {errors, nodes, position} = parse(`{{ title | ¦ }}`);
|
||||||
// TODO: We are not able to locate pipe if identifier is missing because the
|
expect(errors?.length).toBe(1);
|
||||||
// parser throws an error. This case is important for autocomplete.
|
expect(errors![0].toString())
|
||||||
// const {errors, nodes, position} = parse(`{{ title | ¦ }}`);
|
.toContain(
|
||||||
// expect(errors).toBe(null);
|
'Unexpected end of input, expected identifier or keyword at the end of the expression');
|
||||||
// const node = findNodeAtPosition(nodes, position);
|
const node = findNodeAtPosition(nodes, position);
|
||||||
// expect(isExpressionNode(node!)).toBe(true);
|
expect(isExpressionNode(node!)).toBe(true);
|
||||||
// expect(node).toBeInstanceOf(e.BindingPipe);
|
// TODO: We want this to be a BindingPipe.
|
||||||
|
expect(node).toBeInstanceOf(e.Interpolation);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should locate method call', () => {
|
it('should locate method call', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user