From 687477279b3513f56294c54fe16152d966501044 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 26 Aug 2020 17:10:04 +0100 Subject: [PATCH] refactor(compiler): move `ParsedTemplate` interface to compiler (#38594) Previously this interface was mostly stored in compiler-cli, but it contains some properties that would be useful for compiling the "declare component" prelink code. This commit moves some of the interface over to the compiler package so that it can be referenced there without creating a circular dependency between the compiler and compiler-cli. PR Close #38594 --- .../src/ngtsc/annotations/src/component.ts | 93 ++++--------- .../src/ngtsc/typecheck/src/checker.ts | 2 +- .../src/ngtsc/typecheck/test/test_utils.ts | 2 +- packages/compiler/src/compiler.ts | 2 +- packages/compiler/src/jit_compiler_facade.ts | 2 +- .../compiler/src/render3/view/template.ts | 84 ++++++++++-- .../ivy/test/hybrid_visitor_spec.ts | 126 +++++++++--------- 7 files changed, 165 insertions(+), 146 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts index 3a616ea5fe..9de9616075 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/component.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/component.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {compileComponentFromMetadata, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParseError, ParseSourceFile, parseTemplate, ParseTemplateOptions, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, SchemaMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler'; +import {compileComponentFromMetadata, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParsedTemplate, ParseSourceFile, parseTemplate, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, SchemaMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler'; import * as ts from 'typescript'; import {CycleAnalyzer} from '../../cycles'; @@ -31,7 +31,7 @@ import {createValueHasWrongTypeError, getDirectiveDiagnostics, getProviderDiagno import {extractDirectiveMetadata, parseFieldArrayValue} from './directive'; import {compileNgFactoryDefField} from './factory'; import {generateSetClassMetadataCall} from './metadata'; -import {findAngularDecorator, isAngularCoreReference, isExpressionForwardReference, makeDuplicateDeclarationError, readBaseClass, resolveProvidersRequiringFactory, unwrapExpression, wrapFunctionExpressionsInParens} from './util'; +import {findAngularDecorator, isAngularCoreReference, isExpressionForwardReference, readBaseClass, resolveProvidersRequiringFactory, unwrapExpression, wrapFunctionExpressionsInParens} from './util'; const EMPTY_MAP = new Map(); const EMPTY_ARRAY: any[] = []; @@ -260,7 +260,7 @@ export class ComponentDecoratorHandler implements let diagnostics: ts.Diagnostic[]|undefined = undefined; - if (template.errors !== undefined) { + if (template.errors !== null) { // If there are any template parsing errors, convert them to `ts.Diagnostic`s for display. const id = getTemplateId(node); diagnostics = template.errors.map(error => { @@ -336,11 +336,11 @@ export class ComponentDecoratorHandler implements meta: { ...metadata, template: { - nodes: template.emitNodes, + nodes: template.nodes, ngContentSelectors: template.ngContentSelectors, }, encapsulation, - interpolation: template.interpolation, + interpolation: template.interpolationConfig ?? DEFAULT_INTERPOLATION_CONFIG, styles: styles || [], // These will be replaced during the compilation step, after all `NgModule`s have been @@ -772,7 +772,7 @@ export class ComponentDecoratorHandler implements private _parseTemplate( component: Map, templateStr: string, templateUrl: string, - templateRange: LexerRange|undefined, escapedString: boolean): ParsedTemplate { + templateRange: LexerRange|undefined, escapedString: boolean): ParsedComponentTemplate { let preserveWhitespaces: boolean = this.defaultPreserveWhitespaces; if (component.has('preserveWhitespaces')) { const expr = component.get('preserveWhitespaces')!; @@ -783,7 +783,7 @@ export class ComponentDecoratorHandler implements preserveWhitespaces = value; } - let interpolation: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG; + let interpolationConfig = DEFAULT_INTERPOLATION_CONFIG; if (component.has('interpolation')) { const expr = component.get('interpolation')!; const value = this.evaluator.evaluate(expr); @@ -792,21 +792,20 @@ export class ComponentDecoratorHandler implements throw createValueHasWrongTypeError( expr, value, 'interpolation must be an array with 2 elements of string type'); } - interpolation = InterpolationConfig.fromArray(value as [string, string]); + interpolationConfig = InterpolationConfig.fromArray(value as [string, string]); } // We always normalize line endings if the template has been escaped (i.e. is inline). const i18nNormalizeLineEndingsInICUs = escapedString || this.i18nNormalizeLineEndingsInICUs; - const {errors, nodes: emitNodes, styleUrls, styles, ngContentSelectors} = - parseTemplate(templateStr, templateUrl, { - preserveWhitespaces, - interpolationConfig: interpolation, - range: templateRange, - escapedString, - enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, - i18nNormalizeLineEndingsInICUs, - }); + const parsedTemplate = parseTemplate(templateStr, templateUrl, { + preserveWhitespaces, + interpolationConfig, + range: templateRange, + escapedString, + enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, + i18nNormalizeLineEndingsInICUs, + }); // Unfortunately, the primary parse of the template above may not contain accurate source map // information. If used directly, it would result in incorrect code locations in template @@ -823,7 +822,7 @@ export class ComponentDecoratorHandler implements const {nodes: diagNodes} = parseTemplate(templateStr, templateUrl, { preserveWhitespaces: true, - interpolationConfig: interpolation, + interpolationConfig, range: templateRange, escapedString, enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat, @@ -832,13 +831,8 @@ export class ComponentDecoratorHandler implements }); return { - interpolation, - emitNodes, + ...parsedTemplate, diagNodes, - styleUrls, - styles, - ngContentSelectors, - errors, template: templateStr, templateUrl, isInline: component.has('template'), @@ -905,12 +899,7 @@ function sourceMapUrl(resourceUrl: string): string { * This contains the actual parsed template as well as any metadata collected during its parsing, * some of which might be useful for re-parsing the template with different options. */ -export interface ParsedTemplate { - /** - * The `InterpolationConfig` specified by the user. - */ - interpolation: InterpolationConfig; - +export interface ParsedComponentTemplate extends ParsedTemplate { /** * A full path to the file which contains the template. * @@ -920,22 +909,10 @@ export interface ParsedTemplate { templateUrl: string; /** - * The string contents of the template. - * - * This is the "logical" template string, after expansion of any escaped characters (for inline - * templates). This may differ from the actual template bytes as they appear in the .ts file. + * True if the original template was stored inline; + * False if the template was in an external file. */ - template: string; - - /** - * Any errors from parsing the template the first time. - */ - errors?: ParseError[]|undefined; - - /** - * The template AST, parsed according to the user's specifications. - */ - emitNodes: TmplAstNode[]; + isInline: boolean; /** * The template AST, parsed in a manner which preserves source map information for diagnostics. @@ -944,36 +921,12 @@ export interface ParsedTemplate { */ diagNodes: TmplAstNode[]; - /** - * - */ - - /** - * Any styleUrls extracted from the metadata. - */ - styleUrls: string[]; - - /** - * Any inline styles extracted from the metadata. - */ - styles: string[]; - - /** - * Any ng-content selectors extracted from the template. - */ - ngContentSelectors: string[]; - - /** - * Whether the template was inline. - */ - isInline: boolean; - /** * The `ParseSourceFile` for the template. */ file: ParseSourceFile; } -export interface ParsedTemplateWithSource extends ParsedTemplate { +export interface ParsedTemplateWithSource extends ParsedComponentTemplate { sourceMapping: TemplateSourceMapping; } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts index ac29846329..db8ef3487a 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts @@ -79,7 +79,7 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker { leadingTriviaChars: [], }); - if (errors !== undefined) { + if (errors !== null) { return {nodes, errors}; } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/test/test_utils.ts b/packages/compiler-cli/src/ngtsc/typecheck/test/test_utils.ts index 248f5ea352..d87a8141e3 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/test/test_utils.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/test/test_utils.ts @@ -354,7 +354,7 @@ export function setup(targets: TypeCheckingTarget[], overrides: { const templateUrl = `${className}.html`; const templateFile = new ParseSourceFile(template, templateUrl); const {nodes, errors} = parseTemplate(template, templateUrl); - if (errors !== undefined) { + if (errors !== null) { throw new Error('Template parse errors: \n' + errors.join('\n')); } diff --git a/packages/compiler/src/compiler.ts b/packages/compiler/src/compiler.ts index ca5cd12c06..06405307ad 100644 --- a/packages/compiler/src/compiler.ts +++ b/packages/compiler/src/compiler.ts @@ -99,7 +99,7 @@ export {Identifiers as R3Identifiers} from './render3/r3_identifiers'; export {R3DependencyMetadata, R3ResolvedDependencyType, compileFactoryFunction, R3FactoryMetadata, R3FactoryTarget} from './render3/r3_factory'; export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler'; export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler'; -export {makeBindingParser, parseTemplate, ParseTemplateOptions} from './render3/view/template'; +export {makeBindingParser, ParsedTemplate, parseTemplate, ParseTemplateOptions} from './render3/view/template'; export {R3Reference} from './render3/util'; export {compileComponentFromMetadata, compileDirectiveFromMetadata, parseHostBindings, ParsedHostBindings, verifyHostBindings} from './render3/view/compiler'; export {publishFacade} from './jit_compiler_facade'; diff --git a/packages/compiler/src/jit_compiler_facade.ts b/packages/compiler/src/jit_compiler_facade.ts index b3c92ac387..540c0a3e22 100644 --- a/packages/compiler/src/jit_compiler_facade.ts +++ b/packages/compiler/src/jit_compiler_facade.ts @@ -129,7 +129,7 @@ export class CompilerFacadeImpl implements CompilerFacade { const template = parseTemplate( facade.template, sourceMapUrl, {preserveWhitespaces: facade.preserveWhitespaces, interpolationConfig}); - if (template.errors !== undefined) { + if (template.errors !== null) { const errors = template.errors.map(err => err.toString()).join(', '); throw new Error(`Errors during JIT compilation of template for ${facade.name}: ${errors}`); } diff --git a/packages/compiler/src/render3/view/template.ts b/packages/compiler/src/render3/view/template.ts index b0599fc717..3dea5078b0 100644 --- a/packages/compiler/src/render3/view/template.ts +++ b/packages/compiler/src/render3/view/template.ts @@ -2025,13 +2025,7 @@ export interface ParseTemplateOptions { * @param options options to modify how the template is parsed */ export function parseTemplate( - template: string, templateUrl: string, options: ParseTemplateOptions = {}): { - errors?: ParseError[], - nodes: t.Node[], - styleUrls: string[], - styles: string[], - ngContentSelectors: string[] -} { + template: string, templateUrl: string, options: ParseTemplateOptions = {}): ParsedTemplate { const {interpolationConfig, preserveWhitespaces, enableI18nLegacyMessageIdFormat} = options; const bindingParser = makeBindingParser(interpolationConfig); const htmlParser = new HtmlParser(); @@ -2041,6 +2035,9 @@ export function parseTemplate( if (parseResult.errors && parseResult.errors.length > 0) { return { + interpolationConfig, + preserveWhitespaces, + template, errors: parseResult.errors, nodes: [], styleUrls: [], @@ -2076,10 +2073,28 @@ export function parseTemplate( const {nodes, errors, styleUrls, styles, ngContentSelectors} = htmlAstToRender3Ast(rootNodes, bindingParser); if (errors && errors.length > 0) { - return {errors, nodes: [], styleUrls: [], styles: [], ngContentSelectors: []}; + return { + interpolationConfig, + preserveWhitespaces, + template, + errors, + nodes: [], + styleUrls: [], + styles: [], + ngContentSelectors: [] + }; } - return {nodes, styleUrls, styles, ngContentSelectors}; + return { + interpolationConfig, + preserveWhitespaces, + errors: null, + template, + nodes, + styleUrls, + styles, + ngContentSelectors + }; } const elementRegistry = new DomElementSchemaRegistry(); @@ -2196,3 +2211,54 @@ function createClosureModeGuard(): o.BinaryOperatorExpr { .notIdentical(o.literal('undefined', o.STRING_TYPE)) .and(o.variable(NG_I18N_CLOSURE_MODE)); } + +/** + * Information about the template which was extracted during parsing. + * + * This contains the actual parsed template as well as any metadata collected during its parsing, + * some of which might be useful for re-parsing the template with different options. + */ +export interface ParsedTemplate { + /** + * Include whitespace nodes in the parsed output. + */ + preserveWhitespaces?: boolean; + + /** + * How to parse interpolation markers. + */ + interpolationConfig?: InterpolationConfig; + + /** + * The string contents of the template. + * + * This is the "logical" template string, after expansion of any escaped characters (for inline + * templates). This may differ from the actual template bytes as they appear in the .ts file. + */ + template: string; + + /** + * Any errors from parsing the template the first time. + */ + errors: ParseError[]|null; + + /** + * The template AST, parsed from the template. + */ + nodes: t.Node[]; + + /** + * Any styleUrls extracted from the metadata. + */ + styleUrls: string[]; + + /** + * Any inline styles extracted from the metadata. + */ + styles: string[]; + + /** + * Any ng-content selectors extracted from the template. + */ + ngContentSelectors: string[]; +} diff --git a/packages/language-service/ivy/test/hybrid_visitor_spec.ts b/packages/language-service/ivy/test/hybrid_visitor_spec.ts index 30eb4daf73..43820c7e45 100644 --- a/packages/language-service/ivy/test/hybrid_visitor_spec.ts +++ b/packages/language-service/ivy/test/hybrid_visitor_spec.ts @@ -14,7 +14,7 @@ import {findNodeAtPosition, isExpressionNode, isTemplateNode} from '../hybrid_vi interface ParseResult { nodes: t.Node[]; - errors?: ParseError[]; + errors: ParseError[]|null; position: number; } @@ -34,7 +34,7 @@ function parse(template: string): ParseResult { describe('findNodeAtPosition for template AST', () => { it('should locate element in opening tag', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -42,7 +42,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate element in closing tag', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -50,7 +50,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate element when cursor is at the beginning', () => { const {errors, nodes, position} = parse(`<¦div>
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -58,7 +58,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate element when cursor is at the end', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -66,7 +66,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate attribute key', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.TextAttribute); @@ -74,7 +74,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate attribute value', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); // TODO: Note that we do not have the ability to detect the RHS (yet) @@ -83,7 +83,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound attribute key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -91,7 +91,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound attribute value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -99,7 +99,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound event key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundEvent); @@ -107,7 +107,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound event value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.MethodCall); @@ -115,7 +115,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate element children', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -124,7 +124,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate element reference', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Reference); @@ -132,7 +132,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template text attribute', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.TextAttribute); @@ -140,7 +140,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound attribute key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -148,7 +148,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound attribute value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -156,7 +156,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound attribute key in two-way binding', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -165,7 +165,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound attribute value in two-way binding', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -174,7 +174,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound event key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundEvent); @@ -182,14 +182,14 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template bound event value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(node).toBeInstanceOf(e.MethodCall); }); it('should locate template attribute key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.TextAttribute); @@ -197,7 +197,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template attribute value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); // TODO: Note that we do not have the ability to detect the RHS (yet) @@ -206,7 +206,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template reference key via the # notation', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Reference); @@ -215,7 +215,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template reference key via the ref- notation', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Reference); @@ -224,7 +224,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template reference value via the # notation', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Reference); @@ -234,7 +234,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template reference value via the ref- notation', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Reference); @@ -244,7 +244,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template variable key', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Variable); @@ -252,7 +252,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template variable value', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Variable); @@ -260,7 +260,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate template children', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -268,7 +268,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate ng-content', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Content); @@ -276,7 +276,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate ng-content attribute key', () => { const {errors, nodes, position} = parse(''); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.TextAttribute); @@ -284,7 +284,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate ng-content attribute value', () => { const {errors, nodes, position} = parse(''); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); // TODO: Note that we do not have the ability to detect the RHS (yet) expect(isTemplateNode(node!)).toBe(true); @@ -293,7 +293,7 @@ describe('findNodeAtPosition for template AST', () => { it('should not locate implicit receiver', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -301,7 +301,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound attribute key in two-way binding', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -310,7 +310,7 @@ describe('findNodeAtPosition for template AST', () => { it('should locate bound attribute value in two-way binding', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -321,7 +321,7 @@ describe('findNodeAtPosition for template AST', () => { describe('findNodeAtPosition for expression AST', () => { it('should not locate implicit receiver', () => { const {errors, nodes, position} = parse(`{{ ¦title }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -330,7 +330,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate property read', () => { const {errors, nodes, position} = parse(`{{ ti¦tle }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -339,7 +339,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate safe property read', () => { const {errors, nodes, position} = parse(`{{ foo?¦.bar }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.SafePropertyRead); @@ -348,7 +348,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate keyed read', () => { const {errors, nodes, position} = parse(`{{ foo['bar']¦ }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.KeyedRead); @@ -356,7 +356,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate property write', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyWrite); @@ -364,7 +364,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate keyed write', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.KeyedWrite); @@ -372,7 +372,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate binary', () => { const {errors, nodes, position} = parse(`{{ 1 +¦ 2 }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.Binary); @@ -380,7 +380,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate binding pipe with an identifier', () => { const {errors, nodes, position} = parse(`{{ title | p¦ }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.BindingPipe); @@ -391,7 +391,7 @@ describe('findNodeAtPosition for expression AST', () => { // TODO: We are not able to locate pipe if identifier is missing because the // parser throws an error. This case is important for autocomplete. // const {errors, nodes, position} = parse(`{{ title | ¦ }}`); - // expect(errors).toBeUndefined(); + // expect(errors).toBe(null); // const node = findNodeAtPosition(nodes, position); // expect(isExpressionNode(node!)).toBe(true); // expect(node).toBeInstanceOf(e.BindingPipe); @@ -399,7 +399,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate method call', () => { const {errors, nodes, position} = parse(`{{ title.toString(¦) }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.MethodCall); @@ -407,7 +407,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate safe method call', () => { const {errors, nodes, position} = parse(`{{ title?.toString(¦) }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.SafeMethodCall); @@ -415,7 +415,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate literal primitive in interpolation', () => { const {errors, nodes, position} = parse(`{{ title.indexOf('t¦') }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.LiteralPrimitive); @@ -424,7 +424,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate literal primitive in binding', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.LiteralPrimitive); @@ -433,7 +433,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate empty expression', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.EmptyExpr); @@ -441,7 +441,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate literal array', () => { const {errors, nodes, position} = parse(`{{ [1, 2,¦ 3] }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.LiteralArray); @@ -449,7 +449,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate literal map', () => { const {errors, nodes, position} = parse(`{{ { hello:¦ "world" } }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.LiteralMap); @@ -457,7 +457,7 @@ describe('findNodeAtPosition for expression AST', () => { it('should locate conditional', () => { const {errors, nodes, position} = parse(`{{ cond ?¦ true : false }}`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.Conditional); @@ -467,7 +467,7 @@ describe('findNodeAtPosition for expression AST', () => { describe('findNodeAtPosition for microsyntax expression', () => { it('should locate template key', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -475,7 +475,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate template value', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -485,7 +485,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { const {errors, nodes, position} = parse(`
`); // ngFor is a text attribute because the desugared form is // - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); // TODO: this is currently wrong because it should point to ngFor text // attribute instead of ngForOf bound attribute @@ -493,7 +493,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate not let keyword', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); // TODO: this is currently wrong because node is currently pointing to // "item". In this case, it should return undefined. @@ -501,7 +501,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate let variable', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Variable); @@ -510,7 +510,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate bound attribute key', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.BoundAttribute); @@ -519,7 +519,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate bound attribute value', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -528,7 +528,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate template children', () => { const {errors, nodes, position} = parse(``); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Element); @@ -540,7 +540,7 @@ describe('findNodeAtPosition for microsyntax expression', () => {
{{ i¦ }}
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isExpressionNode(node!)).toBe(true); expect(node).toBeInstanceOf(e.PropertyRead); @@ -548,7 +548,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate LHS of variable declaration', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Variable); @@ -558,7 +558,7 @@ describe('findNodeAtPosition for microsyntax expression', () => { it('should locate RHS of variable declaration', () => { const {errors, nodes, position} = parse(`
`); - expect(errors).toBeUndefined(); + expect(errors).toBe(null); const node = findNodeAtPosition(nodes, position); expect(isTemplateNode(node!)).toBe(true); expect(node).toBeInstanceOf(t.Variable);