style(compiler-cli): reformat of codebase with new clang-format version (#36520)

This commit reformats the packages/compiler-cli tree using the new version
of clang-format.

PR Close #36520
This commit is contained in:
Alex Rickabaugh
2020-04-07 12:43:43 -07:00
committed by atscott
parent 717df13207
commit 0a69a2832b
205 changed files with 2949 additions and 2122 deletions

View File

@ -7,8 +7,9 @@
*/
import {AotCompilerOptions} from '@angular/compiler';
import {escapeRegExp} from '@angular/compiler/src/util';
import {MockCompilerHost, MockData, MockDirectory, arrayToMockDir, toMockFileArray} from '@angular/compiler/test/aot/test_util';
import {arrayToMockDir, MockCompilerHost, MockData, MockDirectory, toMockFileArray} from '@angular/compiler/test/aot/test_util';
import * as ts from 'typescript';
import {NodeJSFileSystem, setFileSystem} from '../../src/ngtsc/file_system';
import {NgtscProgram} from '../../src/ngtsc/program';
@ -22,10 +23,11 @@ const NUMBER = /\d+/;
const ELLIPSIS = '…';
const TOKEN = new RegExp(
`\\s*((${IDENTIFIER.source})|(${BACKTICK_STRING.source})|(${OPERATOR.source})|(${STRING.source})|${NUMBER.source}|${ELLIPSIS})\\s*`,
`\\s*((${IDENTIFIER.source})|(${BACKTICK_STRING.source})|(${OPERATOR.source})|(${
STRING.source})|${NUMBER.source}|${ELLIPSIS})\\s*`,
'y');
type Piece = string | RegExp;
type Piece = string|RegExp;
const SKIP = /(?:.|\n|\r)*/;
@ -116,15 +118,16 @@ export function expectEmit(
const context = fullContext.length > contextLength ?
`...${fullContext.substr(-contextLength)}` :
fullContext;
fail(
`${description}: Failed to find "${expectedPiece}" after "${context}" in:\n'${source.substr(0,last)}[<---HERE expected "${expectedPiece}"]${source.substr(last)}'`);
fail(`${description}: Failed to find "${expectedPiece}" after "${context}" in:\n'${
source.substr(0, last)}[<---HERE expected "${expectedPiece}"]${source.substr(last)}'`);
return;
} else {
last = (m.index || 0) + m[0].length;
}
}
fail(
`Test helper failure: Expected expression failed but the reporting logic could not find where it failed in: ${source}`);
`Test helper failure: Expected expression failed but the reporting logic could not find where it failed in: ${
source}`);
} else {
if (assertIdentifiers) {
// It might be possible to add the constraints in the original regexp (see `buildMatcher`)
@ -141,8 +144,8 @@ export function expectEmit(
const name = matches[groups.get(id) as number];
const regexp = assertIdentifiers[id];
if (!regexp.test(name)) {
throw Error(
`${description}: The matching identifier "${id}" is "${name}" which doesn't match ${regexp}`);
throw Error(`${description}: The matching identifier "${id}" is "${
name}" which doesn't match ${regexp}`);
}
}
}
@ -160,7 +163,7 @@ const MATCHING_IDENT = /^\$.*\$$/;
* - the `regexp` to be used to match the generated code,
* - the `groups` which maps `$...$` identifier to their position in the regexp matches.
*/
function buildMatcher(pieces: (string | RegExp)[]): {regexp: RegExp, groups: Map<string, number>} {
function buildMatcher(pieces: (string|RegExp)[]): {regexp: RegExp, groups: Map<string, number>} {
const results: string[] = [];
let first = true;
let group = 0;
@ -196,7 +199,9 @@ function buildMatcher(pieces: (string | RegExp)[]): {regexp: RegExp, groups: Map
export function compile(
data: MockDirectory, angularFiles: MockData, options: AotCompilerOptions = {},
errorCollector: (error: any, fileName?: string) => void = error => { throw error;}): {
errorCollector: (error: any, fileName?: string) => void = error => {
throw error;
}): {
source: string,
} {
setFileSystem(new NodeJSFileSystem());
@ -211,7 +216,8 @@ export function compile(
target: ts.ScriptTarget.ES2015,
module: ts.ModuleKind.ES2015,
moduleResolution: ts.ModuleResolutionKind.NodeJs,
enableI18nLegacyMessageIdFormat: false, ...options,
enableI18nLegacyMessageIdFormat: false,
...options,
},
mockCompilerHost);
program.emit();

View File

@ -100,14 +100,14 @@ describe('mock_compiler', () => {
it('should be able to properly handle string literals with escaped quote', () => {
const files = {
app: {
'test.ts': String.raw `const identifier = "\"quoted\"";`,
'test.ts': String.raw`const identifier = "\"quoted\"";`,
}
};
const result = compile(files, angularFiles);
expect(() => {
expectEmit(result.source, String.raw `const $a$ = "\"quoted\"";`, 'Output does not match.');
expectEmit(result.source, String.raw`const $a$ = "\"quoted\"";`, 'Output does not match.');
}).not.toThrow();
});
});

View File

@ -16,7 +16,6 @@ import {compile, expectEmit} from './mock_compile';
* test in compiler_canonical_spec.ts should have a corresponding test here.
*/
describe('compiler compliance', () => {
const angularFiles = setup({
compileAngular: false,
compileAnimations: false,
@ -49,7 +48,8 @@ describe('compiler compliance', () => {
// The template should look like this (where IDENT is a wild card for an identifier):
const template = `
consts: [["title", "Hello", ${AttributeMarker.Classes}, "my-app"], ["cx", "20", "cy", "30", "r", "50"]],
consts: [["title", "Hello", ${
AttributeMarker.Classes}, "my-app"], ["cx", "20", "cy", "30", "r", "50"]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "div", 0);
@ -536,7 +536,6 @@ describe('compiler compliance', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect template');
});
});
describe('components & directives', () => {
@ -867,7 +866,6 @@ describe('compiler compliance', () => {
});
describe('value composition', () => {
it('should support array literals', () => {
const files = {
app: {
@ -1143,7 +1141,6 @@ describe('compiler compliance', () => {
});
describe('content projection', () => {
it('should support content projection in root template', () => {
const files = {
app: {
@ -1319,7 +1316,8 @@ describe('compiler compliance', () => {
}
const $_c4$ = [[["span", "title", "tofirst"]], "*"];
consts: [["id", "second", ${AttributeMarker.Template}, "ngIf"], ["id", "third", ${AttributeMarker.Template}, "ngIf"], ["id", "second"], ["id", "third"]],
consts: [["id", "second", ${AttributeMarker.Template}, "ngIf"], ["id", "third", ${
AttributeMarker.Template}, "ngIf"], ["id", "second"], ["id", "third"]],
template: function Cmp_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵprojectionDef($_c4$);
@ -1534,7 +1532,8 @@ describe('compiler compliance', () => {
decls: 1,
vars: 1,
consts: [
["ngProjectAs", ".someclass", ${AttributeMarker.ProjectAs}, ["", 8, "someclass"], ${AttributeMarker.Template}, "ngIf"],
["ngProjectAs", ".someclass", ${AttributeMarker.ProjectAs}, ["", 8, "someclass"], ${
AttributeMarker.Template}, "ngIf"],
["ngProjectAs", ".someclass", ${AttributeMarker.ProjectAs}, ["", 8, "someclass"]]
],
template: function MyApp_Template(rf, ctx) {
@ -1552,7 +1551,6 @@ describe('compiler compliance', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, SimpleComponentDefinition, 'Incorrect MyApp definition');
});
});
describe('queries', () => {
@ -2044,9 +2042,7 @@ describe('compiler compliance', () => {
});
describe('pipes', () => {
it('should render pipes', () => {
const files = {
app: {
'spec.ts': `
@ -2217,7 +2213,6 @@ describe('compiler compliance', () => {
it('should generate the proper instruction when injecting ChangeDetectorRef into a pipe',
() => {
const files = {
app: {
'spec.ts': `
@ -2282,7 +2277,6 @@ describe('compiler compliance', () => {
expectEmit(source, MyOtherPipeDefinition, 'Invalid alternate pipe definition');
expectEmit(source, MyOtherPipeFactory, 'Invalid alternate pipe factory function');
});
});
it('local reference', () => {
@ -2477,7 +2471,8 @@ describe('compiler compliance', () => {
}
// ...
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], ["foo", ""], [${AttributeMarker.Template}, "ngIf"]],
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], ["foo", ""], [${
AttributeMarker.Template}, "ngIf"]],
template:function MyComponent_Template(rf, ctx){
if (rf & 1) {
$i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 4, 1, "div", 0);
@ -3280,7 +3275,6 @@ describe('compiler compliance', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, MyAppDeclaration, 'Invalid component definition');
});
});
describe('inherited base classes', () => {
@ -3849,7 +3843,7 @@ describe('compiler compliance', () => {
}
};
const result = compile(files, angularFiles);
expect(result.source.match(/ɵdir/g) !.length).toBe(1);
expect(result.source.match(/ɵdir/g)!.length).toBe(1);
});
});
});

View File

@ -405,7 +405,6 @@ describe('compiler compliance: bindings', () => {
expectEmit(result.source, template, 'Incorrect template');
});
});
describe('attribute bindings', () => {
@ -640,13 +639,13 @@ describe('compiler compliance: bindings', () => {
};
const template = `
consts: [["target", "_blank", "aria-label", "link", ${AttributeMarker.Bindings}, "title", "id", "customEvent"]],
consts: [["target", "_blank", "aria-label", "link", ${
AttributeMarker.Bindings}, "title", "id", "customEvent"]],
`;
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect attribute array');
});
});
describe('host bindings', () => {
@ -850,12 +849,15 @@ describe('compiler compliance: bindings', () => {
HostAttributeComp.ɵcmp = $r3$.ɵɵdefineComponent({
type: HostAttributeComp,
selectors: [["my-host-attribute-component"]],
hostAttrs: ["title", "hello there from component", ${AttributeMarker.Styles}, "opacity", "1"],
hostAttrs: ["title", "hello there from component", ${
AttributeMarker.Styles}, "opacity", "1"],
HostAttributeDir.ɵdir = $r3$.ɵɵdefineDirective({
type: HostAttributeDir,
selectors: [["", "hostAttributeDir", ""]],
hostAttrs: ["title", "hello there from directive", ${AttributeMarker.Classes}, "one", "two", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostAttrs: ["title", "hello there from directive", ${
AttributeMarker.Classes}, "one", "two", ${
AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostVars: 4,
hostBindings: function HostAttributeDir_HostBindings(rf, ctx) {
@ -1216,7 +1218,6 @@ describe('compiler compliance: bindings', () => {
`;
expectEmit(result.source, template, 'Incorrect template');
});
});
describe('non bindable behavior', () => {
@ -1420,7 +1421,5 @@ describe('compiler compliance: bindings', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect handling of elements with no children');
});
});
});

View File

@ -386,8 +386,7 @@ describe('compiler compliance: dependency injection', () => {
expectEmit(source, MyPipeDefs, 'Invalid pipe factory function');
expectEmit(source, MyOtherPipeDefs, 'Invalid pipe factory function');
expect(source.match(/MyPipe\.ɵfac =/g) !.length).toBe(1);
expect(source.match(/MyOtherPipe\.ɵfac =/g) !.length).toBe(1);
expect(source.match(/MyPipe\.ɵfac =/g)!.length).toBe(1);
expect(source.match(/MyOtherPipe\.ɵfac =/g)!.length).toBe(1);
});
});

View File

@ -10,7 +10,6 @@ import {setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
describe('compiler compliance: directives', () => {
const angularFiles = setup({
compileAngular: false,
compileAnimations: false,
@ -18,7 +17,6 @@ describe('compiler compliance: directives', () => {
});
describe('matching', () => {
it('should not match directives on i18n attribute', () => {
const files = {
app: {
@ -114,7 +112,6 @@ describe('compiler compliance: directives', () => {
});
it('should match directives on element bindings', () => {
const files = {
app: {
'spec.ts': `
@ -273,7 +270,6 @@ describe('compiler compliance: directives', () => {
});
it('should match directives on ng-template bindings', () => {
const files = {
app: {
'spec.ts': `
@ -321,7 +317,6 @@ describe('compiler compliance: directives', () => {
});
it('should match structural directives', () => {
const files = {
app: {
'spec.ts': `
@ -362,11 +357,9 @@ describe('compiler compliance: directives', () => {
const source = result.source;
expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ɵcmp');
});
it('should match directives on element outputs', () => {
const files = {
app: {
'spec.ts': `
@ -413,6 +406,5 @@ describe('compiler compliance: directives', () => {
expectEmit(source, MyComponentDefinition, 'Incorrect ChildComponent.ɵcmp');
});
});
});

View File

@ -85,5 +85,4 @@ describe('compiler compliance: listen()', () => {
expectEmit(result.source, componentDef, 'Incorrect component definition');
expectEmit(result.source, directiveDef, 'Incorrect directive definition');
});
});

View File

@ -10,8 +10,8 @@ import {setup} from '@angular/compiler/test/aot/test_util';
import {compile, expectEmit} from './mock_compile';
/* These tests are codified version of the tests in compiler_canonical_spec.ts. Every
* test in compiler_canonical_spec.ts should have a corresponding test here.
*/
* test in compiler_canonical_spec.ts should have a corresponding test here.
*/
describe('compiler compliance: listen()', () => {
const angularFiles = setup({
compileAngular: false,
@ -292,7 +292,8 @@ describe('compiler compliance: listen()', () => {
const template = `
consts: [[${AttributeMarker.Bindings}, "click", "change"], [${AttributeMarker.Bindings}, "update", "delete"]],
consts: [[${AttributeMarker.Bindings}, "click", "change"], [${
AttributeMarker.Bindings}, "update", "delete"]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵelementStart(0, "div", 0);
@ -446,5 +447,4 @@ describe('compiler compliance: listen()', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect host bindings');
});
});

View File

@ -622,7 +622,6 @@ describe('compiler compliance: styling', () => {
const result = compile(files, angularFiles);
expect(result.source).not.toContain('styling');
});
});
describe('[class]', () => {
@ -743,7 +742,8 @@ describe('compiler compliance: styling', () => {
selectors:[["my-component"]],
decls: 1,
vars: 2,
consts: [[${AttributeMarker.Classes}, "foo", ${AttributeMarker.Styles}, "width", "100px"]],
consts: [[${AttributeMarker.Classes}, "foo", ${
AttributeMarker.Styles}, "width", "100px"]],
template: function MyComponent_Template(rf, $ctx$) {
if (rf & 1) {
$r3$.ɵɵelement(0, "div", 0);
@ -782,7 +782,6 @@ describe('compiler compliance: styling', () => {
const result = compile(files, angularFiles);
expect(result.source).not.toContain('styling');
});
});
describe('[style] mixed with [class]', () => {
@ -1005,7 +1004,8 @@ describe('compiler compliance: styling', () => {
};
const template = `
hostAttrs: [${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostAttrs: [${AttributeMarker.Classes}, "foo", "baz", ${
AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostVars: 8,
hostBindings: function MyComponent_HostBindings(rf, ctx) {
if (rf & 2) {
@ -1594,7 +1594,6 @@ describe('compiler compliance: styling', () => {
expectEmit(result.source, template, 'Incorrect handling of interpolated style properties');
});
});
describe('instruction chaining', () => {
@ -1981,7 +1980,8 @@ describe('compiler compliance: styling', () => {
};
const template = `
hostAttrs: ["title", "foo title", ${AttributeMarker.Classes}, "foo", "baz", ${AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostAttrs: ["title", "foo title", ${AttributeMarker.Classes}, "foo", "baz", ${
AttributeMarker.Styles}, "width", "200px", "height", "500px"],
hostVars: 6,
hostBindings: function MyComponent_HostBindings(rf, ctx) {
if (rf & 2) {

View File

@ -103,7 +103,10 @@ describe('compiler compliance: template', () => {
}
}
// ...
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Bindings}, "title", "click", ${AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Bindings}, "title", "click"]],
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], [${
AttributeMarker.Bindings}, "title", "click", ${
AttributeMarker.Template}, "ngFor", "ngForOf"], [${
AttributeMarker.Bindings}, "title", "click"]],
template:function MyComponent_Template(rf, ctx){
if (rf & 1) {
$i0$.ɵɵtemplate(0, MyComponent_ul_0_Template, 2, 1, "ul", 0);
@ -157,7 +160,8 @@ describe('compiler compliance: template', () => {
}
}
// ...
consts: [[${AttributeMarker.Bindings}, "click", ${AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Bindings}, "click"]],
consts: [[${AttributeMarker.Bindings}, "click", ${
AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Bindings}, "click"]],
template: function MyComponent_Template(rf, ctx) {
if (rf & 1) {
$r3$.ɵɵtemplate(0, MyComponent_div_0_Template, 1, 0, "div", 0);
@ -329,7 +333,8 @@ describe('compiler compliance: template', () => {
}
// ...
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], [${AttributeMarker.Template}, "ngIf"]],
consts: [[${AttributeMarker.Template}, "ngFor", "ngForOf"], [${
AttributeMarker.Template}, "ngIf"]],
template:function MyComponent_Template(rf, ctx){
if (rf & 1) {
$i0$.ɵɵtemplate(0, MyComponent_div_0_Template, 2, 1, "div", 0);
@ -472,7 +477,6 @@ describe('compiler compliance: template', () => {
});
it('should support local refs on <ng-template>', () => {
const files = {
app: {
'spec.ts': `
@ -511,7 +515,6 @@ describe('compiler compliance: template', () => {
});
it('should support directive outputs on <ng-template>', () => {
const files = {
app: {
'spec.ts': `
@ -545,7 +548,6 @@ describe('compiler compliance: template', () => {
const result = compile(files, angularFiles);
expectEmit(result.source, template, 'Incorrect template');
});
it('should allow directive inputs as an interpolated prop on <ng-template>', () => {

View File

@ -11,7 +11,8 @@ import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as ts from 'typescript';
import {TestSupport, expectNoDiagnostics, setup} from '../test_support';
import {expectNoDiagnostics, setup, TestSupport} from '../test_support';
type MockFiles = {
[fileName: string]: string
@ -47,19 +48,19 @@ describe('ng type checker', () => {
}
function reject(
message: string | RegExp, location: RegExp | null, files: MockFiles,
message: string|RegExp, location: RegExp|null, files: MockFiles,
overrideOptions: ng.CompilerOptions = {}) {
const diagnostics = compileAndCheck([QUICKSTART, files], overrideOptions);
if (!diagnostics || !diagnostics.length) {
throw new Error('Expected a diagnostic error message');
} else {
const matches: (d: ng.Diagnostic | ts.Diagnostic) => boolean = typeof message === 'string' ?
const matches: (d: ng.Diagnostic|ts.Diagnostic) => boolean = typeof message === 'string' ?
d => ng.isNgDiagnostic(d)&& d.messageText == message :
d => ng.isNgDiagnostic(d) && message.test(d.messageText);
const matchingDiagnostics = diagnostics.filter(matches) as ng.Diagnostic[];
if (!matchingDiagnostics || !matchingDiagnostics.length) {
throw new Error(
`Expected a diagnostics matching ${message}, received\n ${diagnostics.map(d => d.messageText).join('\n ')}`);
throw new Error(`Expected a diagnostics matching ${message}, received\n ${
diagnostics.map(d => d.messageText).join('\n ')}`);
}
if (location) {
@ -72,7 +73,9 @@ describe('ng type checker', () => {
}
}
it('should accept unmodified QuickStart', () => { accept(); });
it('should accept unmodified QuickStart', () => {
accept();
});
it('should accept unmodified QuickStart with tests for unused variables', () => {
accept({}, {
@ -523,7 +526,7 @@ describe('ng type checker', () => {
};
const r =
(message: string | RegExp, location: RegExp | null, files: MockFiles,
(message: string|RegExp, location: RegExp|null, files: MockFiles,
options: ng.AngularCompilerOptions = {}) => {
reject(
message, location, {'src/app.component.ts': '', 'src/lib.ts': '', ...files},
@ -712,16 +715,18 @@ describe('ng type checker', () => {
});
function addTests(config: {fullTemplateTypeCheck: boolean}) {
function a(template: string) { accept({'src/app.component.html': template}, config); }
function a(template: string) {
accept({'src/app.component.html': template}, config);
}
function r(template: string, message: string | RegExp, location: string) {
function r(template: string, message: string|RegExp, location: string) {
reject(
message, new RegExp(`app\.component\.html\@${location}$`),
{'src/app.component.html': template}, config);
}
function rejectOnlyWithFullTemplateTypeCheck(
template: string, message: string | RegExp, location: string) {
template: string, message: string|RegExp, location: string) {
if (config.fullTemplateTypeCheck) {
r(template, message, location);
} else {
@ -732,23 +737,33 @@ describe('ng type checker', () => {
it('should report an invalid field access', () => {
r('<div>{{fame}}<div>', `Property 'fame' does not exist on type 'AppComponent'.`, '0:5');
});
it('should reject a reference to a field of a nullable',
() => { r('<div>{{maybePerson.name}}</div>', `Object is possibly 'undefined'.`, '0:5'); });
it('should accept a reference to a field of a nullable using using non-null-assert',
() => { a('{{maybePerson!.name}}'); });
it('should accept a safe property access of a nullable person',
() => { a('{{maybePerson?.name}}'); });
it('should reject a reference to a field of a nullable', () => {
r('<div>{{maybePerson.name}}</div>', `Object is possibly 'undefined'.`, '0:5');
});
it('should accept a reference to a field of a nullable using using non-null-assert', () => {
a('{{maybePerson!.name}}');
});
it('should accept a safe property access of a nullable person', () => {
a('{{maybePerson?.name}}');
});
it('should accept using a library pipe', () => { a('{{1 | libPipe}}'); });
it('should accept using a library directive',
() => { a('<div libDir #libDir="libDir">{{libDir.name}}</div>'); });
it('should accept using a library pipe', () => {
a('{{1 | libPipe}}');
});
it('should accept using a library directive', () => {
a('<div libDir #libDir="libDir">{{libDir.name}}</div>');
});
it('should accept a function call', () => { a('{{getName()}}'); });
it('should accept a function call', () => {
a('{{getName()}}');
});
it('should reject an invalid method', () => {
r('<div>{{getFame()}}</div>',
`Property 'getFame' does not exist on type 'AppComponent'. Did you mean 'getName'?`, '0:5');
});
it('should accept a field access of a method result', () => { a('{{getPerson().name}}'); });
it('should accept a field access of a method result', () => {
a('{{getPerson().name}}');
});
it('should reject an invalid field reference of a method result', () => {
r('<div>{{getPerson().fame}}</div>', `Property 'fame' does not exist on type 'Person'.`,
'0:5');
@ -756,10 +771,13 @@ describe('ng type checker', () => {
it('should reject an access to a nullable field of a method result', () => {
r('<div>{{getMaybePerson().name}}</div>', `Object is possibly 'undefined'.`, '0:5');
});
it('should accept a nullable assert of a nullable field references of a method result',
() => { a('{{getMaybePerson()!.name}}'); });
it('should accept a nullable assert of a nullable field references of a method result', () => {
a('{{getMaybePerson()!.name}}');
});
it('should accept a safe property access of a nullable field reference of a method result',
() => { a('{{getMaybePerson()?.name}}'); });
() => {
a('{{getMaybePerson()?.name}}');
});
it('should report an invalid field access inside of an ng-template', () => {
rejectOnlyWithFullTemplateTypeCheck(
@ -779,8 +797,9 @@ describe('ng type checker', () => {
}
describe('with lowered expressions', () => {
it('should not report lowered expressions as errors',
() => { expectNoDiagnostics({}, compileAndCheck([LOWERING_QUICKSTART])); });
it('should not report lowered expressions as errors', () => {
expectNoDiagnostics({}, compileAndCheck([LOWERING_QUICKSTART]));
});
});
});

View File

@ -18,8 +18,9 @@ describe('toNumbers', () => {
});
describe('compareNumbers', () => {
it('should handle empty arrays', () => { expect(compareNumbers([], [])).toEqual(0); });
it('should handle empty arrays', () => {
expect(compareNumbers([], [])).toEqual(0);
});
it('should handle arrays of same length', () => {
expect(compareNumbers([1], [3])).toEqual(-1);

View File

@ -207,7 +207,9 @@ describe('extract_i18n command line', () => {
beforeEach(() => {
errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error);
const support = setup();
write = (fileName: string, content: string) => { support.write(fileName, content); };
write = (fileName: string, content: string) => {
support.write(fileName, content);
};
basePath = support.basePath;
outDir = path.join(basePath, 'built');
write('tsconfig-base.json', `{

View File

@ -7,7 +7,7 @@
*/
/// <reference types="node" />
import {readFileSync, readdirSync, statSync} from 'fs';
import {readdirSync, readFileSync, statSync} from 'fs';
import {resolve} from 'path';
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '..';

View File

@ -22,7 +22,7 @@ export function getAngularPackagesFromRunfiles() {
const runfilesManifestPath = process.env.RUNFILES_MANIFEST_FILE;
if (!runfilesManifestPath) {
const packageRunfilesDir = path.join(process.env.RUNFILES !, 'angular/packages');
const packageRunfilesDir = path.join(process.env.RUNFILES!, 'angular/packages');
return fs.readdirSync(packageRunfilesDir)
.map(name => ({name, pkgPath: path.join(packageRunfilesDir, name, 'npm_package/')}))

View File

@ -15,7 +15,6 @@ import {ClassMetadata, MetadataEntry, MetadataGlobalReferenceExpression, ModuleM
import {Directory, MockAotContext, MockCompilerHost} from '../mocks';
describe('compiler host adapter', () => {
it('should retrieve metadata for an explicit index relative path reference', () => {
const context = new MockAotContext('.', SIMPLE_LIBRARY);
const host = new MockCompilerHost(context);
@ -28,7 +27,7 @@ describe('compiler host adapter', () => {
const metadata = adapter.getMetadataFor('./lib/src/two/index', '.');
expect(metadata).toBeDefined();
expect(Object.keys(metadata !.metadata).sort()).toEqual([
expect(Object.keys(metadata!.metadata).sort()).toEqual([
'PrivateTwo',
'TWO_CLASSES',
'Two',
@ -48,7 +47,7 @@ describe('compiler host adapter', () => {
const metadata = adapter.getMetadataFor('./lib/src/two', '.');
expect(metadata).toBeDefined();
expect(Object.keys(metadata !.metadata).sort()).toEqual([
expect(Object.keys(metadata!.metadata).sort()).toEqual([
'PrivateTwo',
'TWO_CLASSES',
'Two',
@ -82,7 +81,7 @@ describe('compiler host adapter', () => {
const metadata = adapter.getMetadataFor('./lib/src/index', '.');
expect(metadata).toBeDefined();
expect(metadata !.exports !.map(e => e.export !)
expect(metadata!.exports!.map(e => e.export !)
.reduce((prev, next) => prev.concat(next), [])
.sort())
.toEqual([
@ -127,13 +126,13 @@ describe('compiler host adapter', () => {
const metadata = adapter.getMetadataFor('./lib', '.');
expect(metadata).toBeDefined();
expect(Object.keys(metadata !.metadata).sort()).toEqual([
expect(Object.keys(metadata!.metadata).sort()).toEqual([
'ONE_CLASSES',
'One',
'OneMore',
'PrivateOne',
]);
expect(Array.isArray(metadata !.metadata !['ONE_CLASSES'])).toBeTruthy();
expect(Array.isArray(metadata!.metadata!['ONE_CLASSES'])).toBeTruthy();
});
it('should look for non-declaration file when resolving metadata via a package.json "types" entry',
@ -180,19 +179,17 @@ describe('compiler host adapter', () => {
const metadata = adapter.getMetadataFor('./lib', '.');
expect(metadata).toBeDefined();
expect(Object.keys(metadata !.metadata).sort()).toEqual([
expect(Object.keys(metadata!.metadata).sort()).toEqual([
'ONE_CLASSES',
'One',
'OneMore',
'PrivateOne',
]);
expect(Array.isArray(metadata !.metadata !['ONE_CLASSES'])).toBeTruthy();
expect(Array.isArray(metadata!.metadata!['ONE_CLASSES'])).toBeTruthy();
});
});
describe('metadata bundler', () => {
it('should be able to bundle a simple library', () => {
const host = new MockStringBundlerHost('/', SIMPLE_LIBRARY);
const bundler = new MetadataBundler('/lib/index', undefined, host, 'prfx_');
@ -203,9 +200,9 @@ describe('metadata bundler', () => {
const originalOne = './src/one';
const originalTwo = './src/two/index';
expect(Object.keys(result.metadata.origins !)
expect(Object.keys(result.metadata.origins!)
.sort()
.map(name => ({name, value: result.metadata.origins ![name]})))
.map(name => ({name, value: result.metadata.origins![name]})))
.toEqual([
{name: 'ONE_CLASSES', value: originalOne}, {name: 'One', value: originalOne},
{name: 'OneMore', value: originalOne}, {name: 'TWO_CLASSES', value: originalTwo},
@ -239,7 +236,7 @@ describe('metadata bundler', () => {
});
const bundler = new MetadataBundler('/lib/index', undefined, host);
const bundledMetadata = bundler.getMetadataBundle().metadata;
const deepIndexMetadata = host.getMetadataFor('/lib/deep/index') !;
const deepIndexMetadata = host.getMetadataFor('/lib/deep/index')!;
// The unbundled metadata should reference symbols using the relative module path.
expect(deepIndexMetadata.metadata['MyClass']).toEqual(jasmine.objectContaining<MetadataEntry>({
@ -419,7 +416,7 @@ describe('metadata bundler', () => {
from: 'external_one'
}
]);
expect(result.metadata.origins !['E']).toBeUndefined();
expect(result.metadata.origins!['E']).toBeUndefined();
});
it('should be able to bundle a library with multiple unnamed re-exports', () => {
@ -456,7 +453,7 @@ describe('metadata bundler', () => {
const bundler = new MetadataBundler('/public-api', undefined, host);
const result = bundler.getMetadataBundle();
const {A, A2, A3, B1, B2} = result.metadata.metadata as{
const {A, A2, A3, B1, B2} = result.metadata.metadata as {
A: ClassMetadata,
A2: MetadataGlobalReferenceExpression,
A3: ClassMetadata,

View File

@ -9,9 +9,9 @@
import * as ts from 'typescript';
import {MetadataCollector} from '../../src/metadata/collector';
import {ClassMetadata, ConstructorMetadata, METADATA_VERSION, MetadataEntry, MetadataMap, MetadataSymbolicExpression, ModuleMetadata, isClassMetadata, isMetadataGlobalReferenceExpression} from '../../src/metadata/schema';
import {ClassMetadata, ConstructorMetadata, isClassMetadata, isMetadataGlobalReferenceExpression, METADATA_VERSION, MetadataEntry, MetadataMap, MetadataSymbolicExpression, ModuleMetadata} from '../../src/metadata/schema';
import {Directory, Host, expectValidSources} from './typescript.mocks';
import {Directory, expectValidSources, Host} from './typescript.mocks';
describe('Collector', () => {
const documentRegistry = ts.createDocumentRegistry();
@ -40,20 +40,22 @@ describe('Collector', () => {
'interface-reference.ts', 'static-type-check-members.ts',
]);
service = ts.createLanguageService(host, documentRegistry);
program = service.getProgram() !;
program = service.getProgram()!;
collector = new MetadataCollector({quotedNames: true});
});
it('should not have errors in test data', () => { expectValidSources(service, program); });
it('should not have errors in test data', () => {
expectValidSources(service, program);
});
it('should return undefined for modules that have no metadata', () => {
const sourceFile = program.getSourceFile('app/empty.ts') !;
const sourceFile = program.getSourceFile('app/empty.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toBeUndefined();
});
it('should treat all symbols of .d.ts files as exported', () => {
const sourceFile = program.getSourceFile('declarations.d.ts') !;
const sourceFile = program.getSourceFile('declarations.d.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -66,7 +68,7 @@ describe('Collector', () => {
});
it('should return an interface reference for types', () => {
const sourceFile = program.getSourceFile('/exported-type.ts') !;
const sourceFile = program.getSourceFile('/exported-type.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -76,7 +78,7 @@ describe('Collector', () => {
});
it('should return an interface reference for interfaces', () => {
const sourceFile = program.getSourceFile('app/hero.ts') !;
const sourceFile = program.getSourceFile('app/hero.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -86,13 +88,13 @@ describe('Collector', () => {
});
it('should preserve module names from TypeScript sources', () => {
const sourceFile = program.getSourceFile('named-module.d.ts') !;
const sourceFile = program.getSourceFile('named-module.d.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata !['importAs']).toEqual('some-named-module');
expect(metadata!['importAs']).toEqual('some-named-module');
});
it('should be able to collect a simple component\'s metadata', () => {
const sourceFile = program.getSourceFile('app/hero-detail.component.ts') !;
const sourceFile = program.getSourceFile('app/hero-detail.component.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -144,7 +146,7 @@ describe('Collector', () => {
});
it('should be able to get a more complicated component\'s metadata', () => {
const sourceFile = program.getSourceFile('/app/app.component.ts') !;
const sourceFile = program.getSourceFile('/app/app.component.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -236,7 +238,7 @@ describe('Collector', () => {
});
it('should return the values of exported variables', () => {
const sourceFile = program.getSourceFile('/app/mock-heroes.ts') !;
const sourceFile = program.getSourceFile('/app/mock-heroes.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -262,14 +264,14 @@ describe('Collector', () => {
let casesMetadata: ModuleMetadata;
beforeEach(() => {
casesFile = program.getSourceFile('/app/cases-data.ts') !;
casesMetadata = collector.getMetadata(casesFile) !;
casesFile = program.getSourceFile('/app/cases-data.ts')!;
casesMetadata = collector.getMetadata(casesFile)!;
});
it('should provide any reference for an any ctor parameter type', () => {
const casesAny = <ClassMetadata>casesMetadata.metadata['CaseAny'];
expect(casesAny).toBeTruthy();
const ctorData = casesAny.members !['__ctor__'] as ConstructorMetadata[];
const ctorData = casesAny.members!['__ctor__'] as ConstructorMetadata[];
expect(ctorData).toEqual([{
__symbolic: 'constructor',
parameters: [{__symbolic: 'reference', name: 'any'} as MetadataSymbolicExpression]
@ -300,7 +302,8 @@ describe('Collector', () => {
it('should record references to parameterized types', () => {
const casesForIn = <ClassMetadata>casesMetadata.metadata['NgFor'];
expect(casesForIn).toEqual({
__symbolic: 'class', decorators: [{
__symbolic: 'class',
decorators: [{
__symbolic: 'call',
expression: {
__symbolic: 'reference',
@ -310,21 +313,21 @@ describe('Collector', () => {
character: 7
}
}],
members: {
__ctor__: [{
__symbolic: 'constructor',
parameters: [{
__symbolic: 'reference',
name: 'ClassReference',
arguments: [{__symbolic: 'reference', name: 'NgForRow'}]
}]
}]
}
members: {
__ctor__: [{
__symbolic: 'constructor',
parameters: [{
__symbolic: 'reference',
name: 'ClassReference',
arguments: [{__symbolic: 'reference', name: 'NgForRow'}]
}]
}]
}
} as any as ClassMetadata); // TODO: Review use of `any` here (#19904)
});
it('should report errors for destructured imports', () => {
const unsupported1 = program.getSourceFile('/unsupported-1.ts') !;
const unsupported1 = program.getSourceFile('/unsupported-1.ts')!;
const metadata = collector.getMetadata(unsupported1);
expect(metadata).toEqual({
__symbolic: 'module',
@ -340,11 +343,11 @@ describe('Collector', () => {
});
it('should report an error for references to unexpected types', () => {
const unsupported1 = program.getSourceFile('/unsupported-2.ts') !;
const metadata = collector.getMetadata(unsupported1) !;
const unsupported1 = program.getSourceFile('/unsupported-2.ts')!;
const metadata = collector.getMetadata(unsupported1)!;
const barClass = <ClassMetadata>metadata.metadata['Bar'];
const ctor = <ConstructorMetadata>barClass.members !['__ctor__'][0];
const parameter = ctor.parameters ![0];
const ctor = <ConstructorMetadata>barClass.members!['__ctor__'][0];
const parameter = ctor.parameters![0];
expect(parameter).toEqual({
__symbolic: 'error',
message: 'Reference to non-exported class',
@ -355,18 +358,19 @@ describe('Collector', () => {
});
it('should be able to handle import star type references', () => {
const importStar = program.getSourceFile('/import-star.ts') !;
const metadata = collector.getMetadata(importStar) !;
const importStar = program.getSourceFile('/import-star.ts')!;
const metadata = collector.getMetadata(importStar)!;
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
const ctor = <ConstructorMetadata>someClass.members !['__ctor__'][0];
const ctor = <ConstructorMetadata>someClass.members!['__ctor__'][0];
const parameters = ctor.parameters;
expect(parameters).toEqual([{
__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29
} as MetadataSymbolicExpression]);
expect(parameters).toEqual([
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29} as
MetadataSymbolicExpression
]);
});
it('should record all exported classes', () => {
const sourceFile = program.getSourceFile('/exported-classes.ts') !;
const sourceFile = program.getSourceFile('/exported-classes.ts')!;
const metadata = collector.getMetadata(sourceFile);
expect(metadata).toEqual({
__symbolic: 'module',
@ -380,7 +384,7 @@ describe('Collector', () => {
});
it('should be able to record functions', () => {
const exportedFunctions = program.getSourceFile('/exported-functions.ts') !;
const exportedFunctions = program.getSourceFile('/exported-functions.ts')!;
const metadata = collector.getMetadata(exportedFunctions);
expect(metadata).toEqual({
__symbolic: 'module',
@ -440,26 +444,27 @@ describe('Collector', () => {
});
it('should be able to handle import star type references', () => {
const importStar = program.getSourceFile('/import-star.ts') !;
const metadata = collector.getMetadata(importStar) !;
const importStar = program.getSourceFile('/import-star.ts')!;
const metadata = collector.getMetadata(importStar)!;
const someClass = <ClassMetadata>metadata.metadata['SomeClass'];
const ctor = <ConstructorMetadata>someClass.members !['__ctor__'][0];
const ctor = <ConstructorMetadata>someClass.members!['__ctor__'][0];
const parameters = ctor.parameters;
expect(parameters).toEqual([{
__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29
} as MetadataSymbolicExpression]);
expect(parameters).toEqual([
{__symbolic: 'reference', module: 'angular2/common', name: 'NgFor', line: 6, character: 29} as
MetadataSymbolicExpression
]);
});
it('should be able to collect the value of an enum', () => {
const enumSource = program.getSourceFile('/exported-enum.ts') !;
const metadata = collector.getMetadata(enumSource) !;
const enumSource = program.getSourceFile('/exported-enum.ts')!;
const metadata = collector.getMetadata(enumSource)!;
const someEnum: any = metadata.metadata['SomeEnum'];
expect(someEnum).toEqual({A: 0, B: 1, C: 100, D: 101});
});
it('should ignore a non-export enum', () => {
const enumSource = program.getSourceFile('/private-enum.ts') !;
const metadata = collector.getMetadata(enumSource) !;
const enumSource = program.getSourceFile('/private-enum.ts')!;
const metadata = collector.getMetadata(enumSource)!;
const publicEnum: any = metadata.metadata['PublicEnum'];
const privateEnum: any = metadata.metadata['PrivateEnum'];
expect(publicEnum).toEqual({a: 0, b: 1, c: 2});
@ -467,8 +472,8 @@ describe('Collector', () => {
});
it('should be able to collect enums initialized from consts', () => {
const enumSource = program.getSourceFile('/exported-enum.ts') !;
const metadata = collector.getMetadata(enumSource) !;
const enumSource = program.getSourceFile('/exported-enum.ts')!;
const metadata = collector.getMetadata(enumSource)!;
const complexEnum: any = metadata.metadata['ComplexEnum'];
expect(complexEnum).toEqual({
A: 0,
@ -486,8 +491,8 @@ describe('Collector', () => {
});
it('should be able to collect a simple static method', () => {
const staticSource = program.getSourceFile('/static-method.ts') !;
const metadata = collector.getMetadata(staticSource) !;
const staticSource = program.getSourceFile('/static-method.ts')!;
const metadata = collector.getMetadata(staticSource)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['MyModule'];
expect(classData).toBeDefined();
@ -504,43 +509,45 @@ describe('Collector', () => {
});
it('should be able to collect a call to a static method', () => {
const staticSource = program.getSourceFile('/static-method-call.ts') !;
const metadata = collector.getMetadata(staticSource) !;
const staticSource = program.getSourceFile('/static-method-call.ts')!;
const metadata = collector.getMetadata(staticSource)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['Foo'];
expect(classData).toBeDefined();
expect(classData.decorators).toEqual([{
__symbolic: 'call',
expression: {
__symbolic: 'reference',
module: 'angular2/core',
name: 'Component',
line: 4,
character: 5
},
arguments: [{
providers: {
__symbolic: 'call',
expression: {
__symbolic: 'select',
expect(classData.decorators).toEqual([
{
__symbolic: 'call',
expression: {
__symbolic: 'reference',
module: 'angular2/core',
name: 'Component',
line: 4,
character: 5
},
arguments: [{
providers: {
__symbolic: 'call',
expression: {
__symbolic: 'reference',
module: './static-method',
name: 'MyModule',
line: 5,
character: 17
__symbolic: 'select',
expression: {
__symbolic: 'reference',
module: './static-method',
name: 'MyModule',
line: 5,
character: 17
},
member: 'with'
},
member: 'with'
},
arguments: ['a']
}
}]
}] as any as MetadataSymbolicExpression[]); // TODO: Review use of `any` here (#19904)
arguments: ['a']
}
}]
}
] as any as MetadataSymbolicExpression[]); // TODO: Review use of `any` here (#19904)
});
it('should be able to collect a static field', () => {
const staticSource = program.getSourceFile('/static-field.ts') !;
const metadata = collector.getMetadata(staticSource) !;
const staticSource = program.getSourceFile('/static-field.ts')!;
const metadata = collector.getMetadata(staticSource)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['MyModule'];
expect(classData).toBeDefined();
@ -548,8 +555,8 @@ describe('Collector', () => {
});
it('should ignore static type check members without a value', () => {
const typeCheckMembers = program.getSourceFile('/static-type-check-members.ts') !;
const metadata = collector.getMetadata(typeCheckMembers) !;
const typeCheckMembers = program.getSourceFile('/static-type-check-members.ts')!;
const metadata = collector.getMetadata(typeCheckMembers)!;
const classData = <ClassMetadata>metadata.metadata['MyDirective'];
expect(classData.statics).toEqual({
foo: 'bar',
@ -560,42 +567,44 @@ describe('Collector', () => {
});
it('should be able to collect a reference to a static field', () => {
const staticSource = program.getSourceFile('/static-field-reference.ts') !;
const metadata = collector.getMetadata(staticSource) !;
const staticSource = program.getSourceFile('/static-field-reference.ts')!;
const metadata = collector.getMetadata(staticSource)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['Foo'];
expect(classData).toBeDefined();
expect(classData.decorators).toEqual([{
__symbolic: 'call',
expression: {
__symbolic: 'reference',
module: 'angular2/core',
name: 'Component',
line: 4,
character: 5
},
arguments: [{
providers: [{
provide: 'a',
useValue: {
__symbolic: 'select',
expression: {
__symbolic: 'reference',
module: './static-field',
name: 'MyModule',
line: 5,
character: 45
},
member: 'VALUE'
}
expect(classData.decorators).toEqual([
{
__symbolic: 'call',
expression: {
__symbolic: 'reference',
module: 'angular2/core',
name: 'Component',
line: 4,
character: 5
},
arguments: [{
providers: [{
provide: 'a',
useValue: {
__symbolic: 'select',
expression: {
__symbolic: 'reference',
module: './static-field',
name: 'MyModule',
line: 5,
character: 45
},
member: 'VALUE'
}
}]
}]
}]
}] as any as MetadataSymbolicExpression[]); // TODO: Review use of `any` here (#19904)
}
] as any as MetadataSymbolicExpression[]); // TODO: Review use of `any` here (#19904)
});
it('should be able to collect a method with a conditional expression', () => {
const source = program.getSourceFile('/static-method-with-if.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/static-method-with-if.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['MyModule'];
expect(classData).toBeDefined();
@ -619,8 +628,8 @@ describe('Collector', () => {
});
it('should be able to collect a method with a default parameter', () => {
const source = program.getSourceFile('/static-method-with-default.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/static-method-with-default.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata).toBeDefined();
const classData = <ClassMetadata>metadata.metadata['MyModule'];
expect(classData).toBeDefined();
@ -648,8 +657,8 @@ describe('Collector', () => {
});
it('should be able to collect re-exported symbols', () => {
const source = program.getSourceFile('/re-exports.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/re-exports.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.exports).toEqual([
{from: './static-field', export: ['MyModule']},
{from: './static-field-reference', export: [{name: 'Foo', as: 'OtherModule'}]},
@ -658,14 +667,14 @@ describe('Collector', () => {
});
it('should be able to collect a export as symbol', () => {
const source = program.getSourceFile('export-as.d.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('export-as.d.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({SomeFunction: {__symbolic: 'function'}});
});
it('should be able to collect exports with no module specifier', () => {
const source = program.getSourceFile('/re-exports-2.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/re-exports-2.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({
MyClass: Object({__symbolic: 'class'}),
OtherModule: {
@ -686,8 +695,8 @@ describe('Collector', () => {
});
it('should collect an error symbol if collecting a reference to a non-exported symbol', () => {
const source = program.getSourceFile('/local-symbol-ref.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/local-symbol-ref.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({
REQUIRED_VALIDATOR: {
__symbolic: 'error',
@ -714,8 +723,8 @@ describe('Collector', () => {
});
it('should collect an error symbol if collecting a reference to a non-exported function', () => {
const source = program.getSourceFile('/local-function-ref.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/local-function-ref.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({
REQUIRED_VALIDATOR: {
__symbolic: 'error',
@ -742,8 +751,8 @@ describe('Collector', () => {
});
it('should collect an error for a simple function that references a local variable', () => {
const source = program.getSourceFile('/local-symbol-ref-func.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/local-symbol-ref-func.ts')!;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({
foo: {
__symbolic: 'function',
@ -760,8 +769,8 @@ describe('Collector', () => {
});
it('should collect any for interface parameter reference', () => {
const source = program.getSourceFile('/interface-reference.ts') !;
const metadata = collector.getMetadata(source) !;
const source = program.getSourceFile('/interface-reference.ts')!;
const metadata = collector.getMetadata(source)!;
expect((metadata.metadata['SomeClass'] as ClassMetadata).members).toEqual({
__ctor__: [{
__symbolic: 'constructor',
@ -787,11 +796,13 @@ describe('Collector', () => {
return expect(metadata.metadata['value']);
}
it('should be able to collect a raw interpolated string',
() => { e('`simple value`').toBe('simple value'); });
it('should be able to collect a raw interpolated string', () => {
e('`simple value`').toBe('simple value');
});
it('should be able to interpolate a single value',
() => { e('`${foo}`', 'const foo = "foo value"').toBe('foo value'); });
it('should be able to interpolate a single value', () => {
e('`${foo}`', 'const foo = "foo value"').toBe('foo value');
});
it('should be able to interpolate multiple values', () => {
e('`foo:${foo}, bar:${bar}, end`', 'const foo = "foo"; const bar = "bar";')
@ -894,30 +905,30 @@ describe('Collector', () => {
toString(): string { return \`InjectionToken \${this._desc}\`; }
} as any;`,
ts.ScriptTarget.Latest, true);
const metadata = collector.getMetadata(source) !;
const metadata = collector.getMetadata(source)!;
expect(metadata.metadata).toEqual({InjectionToken: {__symbolic: 'class'}});
});
describe('in strict mode', () => {
it('should throw if an error symbol is collecting a reference to a non-exported symbol', () => {
const source = program.getSourceFile('/local-symbol-ref.ts') !;
const source = program.getSourceFile('/local-symbol-ref.ts')!;
expect(() => collector.getMetadata(source, true)).toThrowError(/Reference to a local symbol/);
});
it('should throw if an error if collecting a reference to a non-exported function', () => {
const source = program.getSourceFile('/local-function-ref.ts') !;
const source = program.getSourceFile('/local-function-ref.ts')!;
expect(() => collector.getMetadata(source, true))
.toThrowError(/Reference to a non-exported function/);
});
it('should throw for references to unexpected types', () => {
const unsupported2 = program.getSourceFile('/unsupported-2.ts') !;
const unsupported2 = program.getSourceFile('/unsupported-2.ts')!;
expect(() => collector.getMetadata(unsupported2, true))
.toThrowError(/Reference to non-exported class/);
});
it('should throw for errors in a static method', () => {
const unsupported3 = program.getSourceFile('/unsupported-3.ts') !;
const unsupported3 = program.getSourceFile('/unsupported-3.ts')!;
expect(() => collector.getMetadata(unsupported3, true))
.toThrowError(/Reference to a non-exported class/);
});
@ -927,34 +938,39 @@ describe('Collector', () => {
it('should not throw with a class with no name', () => {
const fileName = '/invalid-class.ts';
override(fileName, 'export class');
const invalidClass = program.getSourceFile(fileName) !;
const invalidClass = program.getSourceFile(fileName)!;
expect(() => collector.getMetadata(invalidClass)).not.toThrow();
});
it('should not throw with a function with no name', () => {
const fileName = '/invalid-function.ts';
override(fileName, 'export function');
const invalidFunction = program.getSourceFile(fileName) !;
const invalidFunction = program.getSourceFile(fileName)!;
expect(() => collector.getMetadata(invalidFunction)).not.toThrow();
});
});
describe('inheritance', () => {
it('should record `extends` clauses for declared classes', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts') !) !;
expect(metadata.metadata['DeclaredChildClass'])
describe(
'inheritance', () => {
it('should record `extends` clauses for declared classes',
() => {
const metadata =
collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!;
expect(metadata.metadata['DeclaredChildClass'])
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
});
});
it('should record `extends` clauses for classes in the same file', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts') !) !;
expect(metadata.metadata['ChildClassSameFile'])
it('should record `extends` clauses for classes in the same file',
() => {
const metadata =
collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!;
expect(metadata.metadata['ChildClassSameFile'])
.toEqual({__symbolic: 'class', extends: {__symbolic: 'reference', name: 'ParentClass'}});
});
});
it('should record `extends` clauses for classes in a different file', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts') !) !;
expect(metadata.metadata['ChildClassOtherFile']).toEqual({
it('should record `extends` clauses for classes in a different file', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-inheritance.ts')!)!;
expect(metadata.metadata['ChildClassOtherFile']).toEqual({
__symbolic: 'class',
extends: {
__symbolic: 'reference',
@ -964,29 +980,29 @@ describe('Collector', () => {
character: 45,
}
});
});
});
function expectClass(entry: MetadataEntry): entry is ClassMetadata {
const result = isClassMetadata(entry);
expect(result).toBeTruthy();
return result;
}
function expectClass(entry: MetadataEntry): entry is ClassMetadata {
const result = isClassMetadata(entry);
expect(result).toBeTruthy();
return result;
}
it('should collect the correct arity for a class', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-arity.ts') !) !;
it('should collect the correct arity for a class', () => {
const metadata = collector.getMetadata(program.getSourceFile('/class-arity.ts')!)!;
const zero = metadata.metadata['Zero'];
if (expectClass(zero)) expect(zero.arity).toBeUndefined();
const one = metadata.metadata['One'];
if (expectClass(one)) expect(one.arity).toBe(1);
const two = metadata.metadata['Two'];
if (expectClass(two)) expect(two.arity).toBe(2);
const three = metadata.metadata['Three'];
if (expectClass(three)) expect(three.arity).toBe(3);
const nine = metadata.metadata['Nine'];
if (expectClass(nine)) expect(nine.arity).toBe(9);
});
});
const zero = metadata.metadata['Zero'];
if (expectClass(zero)) expect(zero.arity).toBeUndefined();
const one = metadata.metadata['One'];
if (expectClass(one)) expect(one.arity).toBe(1);
const two = metadata.metadata['Two'];
if (expectClass(two)) expect(two.arity).toBe(2);
const three = metadata.metadata['Three'];
if (expectClass(three)) expect(three.arity).toBe(3);
const nine = metadata.metadata['Nine'];
if (expectClass(nine)) expect(nine.arity).toBe(9);
});
});
describe('regression', () => {
it('should be able to collect a short-hand property value', () => {
@ -1053,11 +1069,12 @@ describe('Collector', () => {
expect((metadata.metadata.MyIf as any).statics.typeGuard)
.not.toBeUndefined('typeGuard was not collected');
});
});
describe('references', () => {
beforeEach(() => { collector = new MetadataCollector({quotedNames: true}); });
beforeEach(() => {
collector = new MetadataCollector({quotedNames: true});
});
it('should record a reference to an exported field of a useValue', () => {
const metadata = collectSource(`
@ -1113,13 +1130,13 @@ describe('Collector', () => {
}
return value;
});
expect(metadata !.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp});
expect(metadata!.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp});
});
it('should compose substitution functions', () => {
const collector = new MetadataCollector({
substituteExpression: (value, node) => isMetadataGlobalReferenceExpression(value) &&
value.name == lambdaTemp ?
substituteExpression: (value, node) =>
isMetadataGlobalReferenceExpression(value) && value.name == lambdaTemp ?
{__symbolic: 'reference', name: value.name + '2'} :
value
});
@ -1133,19 +1150,19 @@ describe('Collector', () => {
}
return value;
});
expect(metadata !.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp + '2'});
expect(metadata!.metadata['a']).toEqual({__symbolic: 'reference', name: lambdaTemp + '2'});
});
});
function override(fileName: string, content: string) {
host.overrideFile(fileName, content);
host.addFile(fileName);
program = service.getProgram() !;
program = service.getProgram()!;
}
function collectSource(content: string): ModuleMetadata {
const sourceFile = createSource(content);
return collector.getMetadata(sourceFile) !;
return collector.getMetadata(sourceFile)!;
}
});

View File

@ -10,7 +10,7 @@ import * as ts from 'typescript';
import {Evaluator} from '../../src/metadata/evaluator';
import {Symbols} from '../../src/metadata/symbols';
import {Directory, Host, expectNoDiagnostics, findVar, findVarInitializer} from './typescript.mocks';
import {Directory, expectNoDiagnostics, findVar, findVarInitializer, Host} from './typescript.mocks';
describe('Evaluator', () => {
const documentRegistry = ts.createDocumentRegistry();
@ -27,7 +27,7 @@ describe('Evaluator', () => {
'newExpression.ts', 'errors.ts', 'declared.ts'
]);
service = ts.createLanguageService(host, documentRegistry);
program = service.getProgram() !;
program = service.getProgram()!;
typeChecker = program.getTypeChecker();
symbols = new Symbols(null as any as ts.SourceFile);
evaluator = new Evaluator(symbols, new Map());
@ -45,7 +45,7 @@ describe('Evaluator', () => {
});
it('should be able to fold literal expressions', () => {
const consts = program.getSourceFile('consts.ts') !;
const consts = program.getSourceFile('consts.ts')!;
expect(evaluator.isFoldable(findVarInitializer(consts, 'someName'))).toBeTruthy();
expect(evaluator.isFoldable(findVarInitializer(consts, 'someBool'))).toBeTruthy();
expect(evaluator.isFoldable(findVarInitializer(consts, 'one'))).toBeTruthy();
@ -53,7 +53,7 @@ describe('Evaluator', () => {
});
it('should be able to fold expressions with foldable references', () => {
const expressions = program.getSourceFile('expressions.ts') !;
const expressions = program.getSourceFile('expressions.ts')!;
symbols.define('someName', 'some-name');
symbols.define('someBool', true);
symbols.define('one', 1);
@ -67,7 +67,7 @@ describe('Evaluator', () => {
});
it('should be able to evaluate literal expressions', () => {
const consts = program.getSourceFile('consts.ts') !;
const consts = program.getSourceFile('consts.ts')!;
expect(evaluator.evaluateNode(findVarInitializer(consts, 'someName'))).toBe('some-name');
expect(evaluator.evaluateNode(findVarInitializer(consts, 'someBool'))).toBe(true);
expect(evaluator.evaluateNode(findVarInitializer(consts, 'one'))).toBe(1);
@ -75,7 +75,7 @@ describe('Evaluator', () => {
});
it('should be able to evaluate expressions', () => {
const expressions = program.getSourceFile('expressions.ts') !;
const expressions = program.getSourceFile('expressions.ts')!;
symbols.define('someName', 'some-name');
symbols.define('someBool', true);
symbols.define('one', 1);
@ -118,11 +118,10 @@ describe('Evaluator', () => {
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bShiftRight'))).toEqual(-1 >> 2);
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'bShiftRightU')))
.toEqual(-1 >>> 2);
});
it('should report recursive references as symbolic', () => {
const expressions = program.getSourceFile('expressions.ts') !;
const expressions = program.getSourceFile('expressions.ts')!;
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'recursiveA')))
.toEqual({__symbolic: 'reference', name: 'recursiveB'});
expect(evaluator.evaluateNode(findVarInitializer(expressions, 'recursiveB')))
@ -130,13 +129,13 @@ describe('Evaluator', () => {
});
it('should correctly handle special cases for CONST_EXPR', () => {
const const_expr = program.getSourceFile('const_expr.ts') !;
const const_expr = program.getSourceFile('const_expr.ts')!;
expect(evaluator.evaluateNode(findVarInitializer(const_expr, 'bTrue'))).toEqual(true);
expect(evaluator.evaluateNode(findVarInitializer(const_expr, 'bFalse'))).toEqual(false);
});
it('should resolve a forwardRef', () => {
const forwardRef = program.getSourceFile('forwardRef.ts') !;
const forwardRef = program.getSourceFile('forwardRef.ts')!;
expect(evaluator.evaluateNode(findVarInitializer(forwardRef, 'bTrue'))).toEqual(true);
expect(evaluator.evaluateNode(findVarInitializer(forwardRef, 'bFalse'))).toEqual(false);
});
@ -144,7 +143,7 @@ describe('Evaluator', () => {
it('should return new expressions', () => {
symbols.define('Value', {__symbolic: 'reference', module: './classes', name: 'Value'});
evaluator = new Evaluator(symbols, new Map());
const newExpression = program.getSourceFile('newExpression.ts') !;
const newExpression = program.getSourceFile('newExpression.ts')!;
expect(evaluator.evaluateNode(findVarInitializer(newExpression, 'someValue'))).toEqual({
__symbolic: 'new',
expression:
@ -160,9 +159,9 @@ describe('Evaluator', () => {
});
it('should support reference to a declared module type', () => {
const declared = program.getSourceFile('declared.ts') !;
const aDecl = findVar(declared, 'a') !;
expect(evaluator.evaluateNode(aDecl.type !)).toEqual({
const declared = program.getSourceFile('declared.ts')!;
const aDecl = findVar(declared, 'a')!;
expect(evaluator.evaluateNode(aDecl.type!)).toEqual({
__symbolic: 'select',
expression: {__symbolic: 'reference', name: 'Foo'},
member: 'A'
@ -170,28 +169,28 @@ describe('Evaluator', () => {
});
it('should return errors for unsupported expressions', () => {
const errors = program.getSourceFile('errors.ts') !;
const fDecl = findVar(errors, 'f') !;
expect(evaluator.evaluateNode(fDecl.initializer !))
const errors = program.getSourceFile('errors.ts')!;
const fDecl = findVar(errors, 'f')!;
expect(evaluator.evaluateNode(fDecl.initializer!))
.toEqual({__symbolic: 'error', message: 'Lambda not supported', line: 1, character: 12});
const eDecl = findVar(errors, 'e') !;
expect(evaluator.evaluateNode(eDecl.type !)).toEqual({
const eDecl = findVar(errors, 'e')!;
expect(evaluator.evaluateNode(eDecl.type!)).toEqual({
__symbolic: 'error',
message: 'Could not resolve type',
line: 2,
character: 11,
context: {typeName: 'NotFound'}
});
const sDecl = findVar(errors, 's') !;
expect(evaluator.evaluateNode(sDecl.initializer !)).toEqual({
const sDecl = findVar(errors, 's')!;
expect(evaluator.evaluateNode(sDecl.initializer!)).toEqual({
__symbolic: 'error',
message: 'Name expected',
line: 3,
character: 14,
context: {received: '1'}
});
const tDecl = findVar(errors, 't') !;
expect(evaluator.evaluateNode(tDecl.initializer !)).toEqual({
const tDecl = findVar(errors, 't')!;
expect(evaluator.evaluateNode(tDecl.initializer!)).toEqual({
__symbolic: 'error',
message: 'Expression form not supported',
line: 4,
@ -200,16 +199,16 @@ describe('Evaluator', () => {
});
it('should be able to fold an array spread', () => {
const expressions = program.getSourceFile('expressions.ts') !;
const expressions = program.getSourceFile('expressions.ts')!;
symbols.define('arr', [1, 2, 3, 4]);
const arrSpread = findVar(expressions, 'arrSpread') !;
expect(evaluator.evaluateNode(arrSpread.initializer !)).toEqual([0, 1, 2, 3, 4, 5]);
const arrSpread = findVar(expressions, 'arrSpread')!;
expect(evaluator.evaluateNode(arrSpread.initializer!)).toEqual([0, 1, 2, 3, 4, 5]);
});
it('should be able to produce a spread expression', () => {
const expressions = program.getSourceFile('expressions.ts') !;
const arrSpreadRef = findVar(expressions, 'arrSpreadRef') !;
expect(evaluator.evaluateNode(arrSpreadRef.initializer !)).toEqual([
const expressions = program.getSourceFile('expressions.ts')!;
const arrSpreadRef = findVar(expressions, 'arrSpreadRef')!;
expect(evaluator.evaluateNode(arrSpreadRef.initializer!)).toEqual([
0, {__symbolic: 'spread', expression: {__symbolic: 'reference', name: 'arrImport'}}, 5
]);
});
@ -218,8 +217,8 @@ describe('Evaluator', () => {
const source = sourceFileOf(`
export var a = new f;
`);
const expr = findVar(source, 'a') !;
expect(evaluator.evaluateNode(expr.initializer !))
const expr = findVar(source, 'a')!;
expect(evaluator.evaluateNode(expr.initializer!))
.toEqual({__symbolic: 'new', expression: {__symbolic: 'reference', name: 'f'}});
});
@ -244,7 +243,7 @@ describe('Evaluator', () => {
export var a = () => b;
`);
const expr = findVar(source, 'a');
expect(evaluator.evaluateNode(expr !.initializer !))
expect(evaluator.evaluateNode(expr!.initializer!))
.toEqual({__symbolic: 'reference', name: lambdaTemp});
});
@ -256,7 +255,7 @@ describe('Evaluator', () => {
];
`);
const expr = findVar(source, 'a');
expect(evaluator.evaluateNode(expr !.initializer !)).toEqual([
expect(evaluator.evaluateNode(expr!.initializer!)).toEqual([
{provide: 'someValue', useFactory: {__symbolic: 'reference', name: lambdaTemp}}
]);
});

View File

@ -11,7 +11,7 @@ import * as ts from 'typescript';
import {isMetadataGlobalReferenceExpression} from '../../src/metadata/schema';
import {Symbols} from '../../src/metadata/symbols';
import {Directory, Host, expectNoDiagnostics} from './typescript.mocks';
import {Directory, expectNoDiagnostics, Host} from './typescript.mocks';
describe('Symbols', () => {
let symbols: Symbols;
@ -42,9 +42,9 @@ describe('Symbols', () => {
beforeEach(() => {
host = new Host(FILES, ['consts.ts', 'expressions.ts', 'imports.ts']);
service = ts.createLanguageService(host);
program = service.getProgram() !;
expressions = program.getSourceFile('expressions.ts') !;
imports = program.getSourceFile('imports.ts') !;
program = service.getProgram()!;
expressions = program.getSourceFile('expressions.ts')!;
imports = program.getSourceFile('imports.ts')!;
});
it('should not have syntax errors in the test sources', () => {
@ -111,7 +111,7 @@ describe('Symbols', () => {
}
return false;
};
ts.forEachChild(core !, visit);
ts.forEachChild(core!, visit);
});
});

View File

@ -10,7 +10,9 @@ import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
export interface Directory { [name: string]: (Directory|string); }
export interface Directory {
[name: string]: (Directory|string);
}
export class Host implements ts.LanguageServiceHost {
private overrides = new Map<string, string>();
@ -26,20 +28,30 @@ export class Host implements ts.LanguageServiceHost {
};
}
getScriptFileNames(): string[] { return this.scripts; }
getScriptFileNames(): string[] {
return this.scripts;
}
getScriptVersion(fileName: string): string { return this.version.toString(); }
getScriptVersion(fileName: string): string {
return this.version.toString();
}
getScriptSnapshot(fileName: string): ts.IScriptSnapshot|undefined {
const content = this.getFileContent(fileName);
if (content) return ts.ScriptSnapshot.fromString(content);
}
fileExists(fileName: string): boolean { return this.getFileContent(fileName) != null; }
fileExists(fileName: string): boolean {
return this.getFileContent(fileName) != null;
}
getCurrentDirectory(): string { return '/'; }
getCurrentDirectory(): string {
return '/';
}
getDefaultLibFileName(options: ts.CompilerOptions): string { return 'lib.d.ts'; }
getDefaultLibFileName(options: ts.CompilerOptions): string {
return 'lib.d.ts';
}
overrideFile(fileName: string, content: string) {
this.overrides.set(fileName, content);
@ -81,24 +93,52 @@ export function open(directory: Directory, fileName: string): Directory|string|u
export class MockNode implements ts.Node {
decorators?: ts.NodeArray<ts.Decorator>;
modifiers?: ts.NodeArray<ts.Modifier>;
parent !: ts.Node;
parent!: ts.Node;
constructor(
public kind: ts.SyntaxKind = ts.SyntaxKind.Identifier, public flags: ts.NodeFlags = 0,
public pos: number = 0, public end: number = 0) {}
getSourceFile(): ts.SourceFile { return null as any as ts.SourceFile; }
getChildCount(sourceFile?: ts.SourceFile): number { return 0; }
getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
getChildren(sourceFile?: ts.SourceFile): ts.Node[] { return []; }
getStart(sourceFile?: ts.SourceFile): number { return 0; }
getFullStart(): number { return 0; }
getEnd(): number { return 0; }
getWidth(sourceFile?: ts.SourceFile): number { return 0; }
getFullWidth(): number { return 0; }
getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number { return 0; }
getFullText(sourceFile?: ts.SourceFile): string { return ''; }
getText(sourceFile?: ts.SourceFile): string { return ''; }
getFirstToken(sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
getLastToken(sourceFile?: ts.SourceFile): ts.Node { return null as any as ts.Node; }
getSourceFile(): ts.SourceFile {
return null as any as ts.SourceFile;
}
getChildCount(sourceFile?: ts.SourceFile): number {
return 0;
}
getChildAt(index: number, sourceFile?: ts.SourceFile): ts.Node {
return null as any as ts.Node;
}
getChildren(sourceFile?: ts.SourceFile): ts.Node[] {
return [];
}
getStart(sourceFile?: ts.SourceFile): number {
return 0;
}
getFullStart(): number {
return 0;
}
getEnd(): number {
return 0;
}
getWidth(sourceFile?: ts.SourceFile): number {
return 0;
}
getFullWidth(): number {
return 0;
}
getLeadingTriviaWidth(sourceFile?: ts.SourceFile): number {
return 0;
}
getFullText(sourceFile?: ts.SourceFile): string {
return '';
}
getText(sourceFile?: ts.SourceFile): string {
return '';
}
getFirstToken(sourceFile?: ts.SourceFile): ts.Node {
return null as any as ts.Node;
}
getLastToken(sourceFile?: ts.SourceFile): ts.Node {
return null as any as ts.Node;
}
forEachChild<T>(
cbNode: (node: ts.Node) => T | undefined,
cbNodeArray?: (nodes: ts.NodeArray<ts.Node>) => T | undefined): T|undefined {
@ -111,10 +151,10 @@ export class MockIdentifier extends MockNode implements ts.Identifier {
isInJSDocNamespace?: boolean;
decorators?: ts.NodeArray<ts.Decorator>;
modifiers?: ts.NodeArray<ts.Modifier>;
parent !: ts.Node;
parent!: ts.Node;
public text: string;
// TODO(issue/24571): remove '!'.
public escapedText !: ts.__String;
public escapedText!: ts.__String;
// tslint:disable
public _declarationBrand: any;
public _primaryExpressionBrand: any;
@ -135,7 +175,7 @@ export class MockIdentifier extends MockNode implements ts.Identifier {
}
export class MockVariableDeclaration extends MockNode implements ts.VariableDeclaration {
parent !: ts.VariableDeclarationList | ts.CatchClause;
parent!: ts.VariableDeclarationList|ts.CatchClause;
exclamationToken?: ts.Token<ts.SyntaxKind.ExclamationToken>;
type?: ts.TypeNode;
initializer?: ts.Expression;
@ -151,32 +191,46 @@ export class MockVariableDeclaration extends MockNode implements ts.VariableDecl
super(kind, flags, pos, end);
}
static of (name: string): MockVariableDeclaration {
static of(name: string): MockVariableDeclaration {
return new MockVariableDeclaration(new MockIdentifier(name));
}
}
export class MockSymbol implements ts.Symbol {
declarations !: ts.Declaration[];
valueDeclaration !: ts.Declaration;
declarations!: ts.Declaration[];
valueDeclaration!: ts.Declaration;
members?: ts.UnderscoreEscapedMap<ts.Symbol>;
exports?: ts.UnderscoreEscapedMap<ts.Symbol>;
globalExports?: ts.UnderscoreEscapedMap<ts.Symbol>;
// TODO(issue/24571): remove '!'.
public escapedName !: ts.__String;
public escapedName!: ts.__String;
constructor(
public name: string, private node: ts.Declaration = MockVariableDeclaration.of(name),
public flags: ts.SymbolFlags = 0) {}
getFlags(): ts.SymbolFlags { return this.flags; }
getName(): string { return this.name; }
getEscapedName(): ts.__String { return this.escapedName; }
getDeclarations(): ts.Declaration[] { return [this.node]; }
getDocumentationComment(): ts.SymbolDisplayPart[] { return []; }
getFlags(): ts.SymbolFlags {
return this.flags;
}
getName(): string {
return this.name;
}
getEscapedName(): ts.__String {
return this.escapedName;
}
getDeclarations(): ts.Declaration[] {
return [this.node];
}
getDocumentationComment(): ts.SymbolDisplayPart[] {
return [];
}
// TODO(vicb): removed in TS 2.2
getJsDocTags(): any[] { return []; }
getJsDocTags(): any[] {
return [];
}
static of (name: string): MockSymbol { return new MockSymbol(name); }
static of(name: string): MockSymbol {
return new MockSymbol(name);
}
}
export function expectNoDiagnostics(diagnostics: ts.Diagnostic[]) {
@ -219,14 +273,14 @@ export function findVar(sourceFile: ts.SourceFile, name: string): ts.VariableDec
export function findVarInitializer(sourceFile: ts.SourceFile, name: string): ts.Expression {
const v = findVar(sourceFile, name);
expect(v && v.initializer).toBeDefined();
return v !.initializer !;
return v!.initializer!;
}
export function isClass(node: ts.Node): node is ts.ClassDeclaration {
return node.kind === ts.SyntaxKind.ClassDeclaration;
}
export function isNamed(node: ts.Node | undefined, name: string): node is ts.Identifier {
export function isNamed(node: ts.Node|undefined, name: string): node is ts.Identifier {
return !!node && node.kind === ts.SyntaxKind.Identifier && (<ts.Identifier>node).text === name;
}

View File

@ -8,16 +8,22 @@
import * as ts from 'typescript';
export type Entry = string | Directory;
export type Entry = string|Directory;
export interface Directory { [name: string]: Entry; }
export interface Directory {
[name: string]: Entry;
}
export class MockAotContext {
private files: Entry[];
constructor(public currentDirectory: string, ...files: Entry[]) { this.files = files; }
constructor(public currentDirectory: string, ...files: Entry[]) {
this.files = files;
}
fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; }
fileExists(fileName: string): boolean {
return typeof this.getEntry(fileName) === 'string';
}
directoryExists(path: string): boolean {
return path === this.currentDirectory || typeof this.getEntry(path) === 'object';
@ -28,7 +34,7 @@ export class MockAotContext {
if (typeof data === 'string') {
return data;
}
return undefined !;
return undefined!;
}
readResource(fileName: string): Promise<string> {
@ -41,14 +47,16 @@ export class MockAotContext {
writeFile(fileName: string, data: string): void {
const parts = fileName.split('/');
const name = parts.pop() !;
const name = parts.pop()!;
const entry = this.getEntry(parts);
if (entry && typeof entry !== 'string') {
entry[name] = data;
}
}
assumeFileExists(fileName: string): void { this.writeFile(fileName, ''); }
assumeFileExists(fileName: string): void {
this.writeFile(fileName, '');
}
getEntry(fileName: string|string[]): Entry|undefined {
let parts = typeof fileName === 'string' ? fileName.split('/') : fileName;
@ -69,7 +77,9 @@ export class MockAotContext {
}
}
override(files: Entry) { return new MockAotContext(this.currentDirectory, files, ...this.files); }
override(files: Entry) {
return new MockAotContext(this.currentDirectory, files, ...this.files);
}
}
function first<T>(a: T[], cb: (value: T) => T | undefined): T|undefined {
@ -82,7 +92,7 @@ function first<T>(a: T[], cb: (value: T) => T | undefined): T|undefined {
function getEntryFromFiles(parts: string[], files: Entry) {
let current = files;
while (parts.length) {
const part = parts.shift() !;
const part = parts.shift()!;
if (typeof current === 'string') {
return undefined;
}
@ -98,7 +108,7 @@ function getEntryFromFiles(parts: string[], files: Entry) {
function normalize(parts: string[]): string[] {
const result: string[] = [];
while (parts.length) {
const part = parts.shift() !;
const part = parts.shift()!;
switch (part) {
case '.':
break;
@ -115,9 +125,13 @@ function normalize(parts: string[]): string[] {
export class MockCompilerHost implements ts.CompilerHost {
constructor(private context: MockAotContext) {}
fileExists(fileName: string): boolean { return this.context.fileExists(fileName); }
fileExists(fileName: string): boolean {
return this.context.fileExists(fileName);
}
readFile(fileName: string): string { return this.context.readFile(fileName); }
readFile(fileName: string): string {
return this.context.readFile(fileName);
}
directoryExists(directoryName: string): boolean {
return this.context.directoryExists(directoryName);
@ -130,7 +144,7 @@ export class MockCompilerHost implements ts.CompilerHost {
if (sourceText != null) {
return ts.createSourceFile(fileName, sourceText, languageVersion);
} else {
return undefined !;
return undefined!;
}
}
@ -138,15 +152,28 @@ export class MockCompilerHost implements ts.CompilerHost {
return ts.getDefaultLibFileName(options);
}
writeFile: ts.WriteFileCallback = (fileName, text) => { this.context.writeFile(fileName, text); };
writeFile: ts.WriteFileCallback =
(fileName, text) => {
this.context.writeFile(fileName, text);
}
getCurrentDirectory(): string { return this.context.currentDirectory; }
getCurrentDirectory(): string {
return this.context.currentDirectory;
}
getCanonicalFileName(fileName: string): string { return fileName; }
getCanonicalFileName(fileName: string): string {
return fileName;
}
useCaseSensitiveFileNames(): boolean { return false; }
useCaseSensitiveFileNames(): boolean {
return false;
}
getNewLine(): string { return '\n'; }
getNewLine(): string {
return '\n';
}
getDirectories(path: string): string[] { return this.context.getDirectories(path); }
getDirectories(path: string): string[] {
return this.context.getDirectories(path);
}
}

View File

@ -14,7 +14,7 @@ import {NgtscTestEnvironment} from './env';
runInEachFileSystem(() => {
describe('ngtsc component indexing', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
let testSourceFile: AbsoluteFsPath;
let testTemplateFile: AbsoluteFsPath;
@ -177,10 +177,10 @@ runInEachFileSystem(() => {
expect(testComp).toBeDefined();
expect(testImportComp).toBeDefined();
expect(testComp !.template.usedComponents.size).toBe(0);
expect(testImportComp !.template.usedComponents.size).toBe(1);
expect(testComp!.template.usedComponents.size).toBe(0);
expect(testImportComp!.template.usedComponents.size).toBe(1);
const [usedComp] = Array.from(testImportComp !.template.usedComponents);
const [usedComp] = Array.from(testImportComp!.template.usedComponents);
expect(indexed.get(usedComp)).toEqual(testComp);
});
});

View File

@ -6,13 +6,13 @@
* found in the LICENSE file at https://angular.io/license
*/
import {CustomTransformers, Program, defaultGatherDiagnostics} from '@angular/compiler-cli';
import {CustomTransformers, defaultGatherDiagnostics, Program} from '@angular/compiler-cli';
import * as api from '@angular/compiler-cli/src/transformers/api';
import * as ts from 'typescript';
import {createCompilerHost, createProgram} from '../../index';
import {main, mainDiagnosticsForTest, readNgcCommandLineAndConfiguration} from '../../src/main';
import {AbsoluteFsPath, FileSystem, NgtscCompilerHost, absoluteFrom, getFileSystem} from '../../src/ngtsc/file_system';
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, NgtscCompilerHost} from '../../src/ngtsc/file_system';
import {Folder, MockFileSystem} from '../../src/ngtsc/file_system/testing';
import {IndexedComponent} from '../../src/ngtsc/indexer';
import {NgtscProgram} from '../../src/ngtsc/program';
@ -115,7 +115,7 @@ export class NgtscTestEnvironment {
if (this.multiCompileHostExt === null) {
throw new Error(`Not tracking written files - call enableMultipleCompilations()`);
}
this.changedResources !.clear();
this.changedResources!.clear();
this.multiCompileHostExt.flushWrittenFileTracking();
}
@ -123,7 +123,9 @@ export class NgtscTestEnvironment {
* Older versions of the CLI do not provide the `CompilerHost.getModifiedResourceFiles()` method.
* This results in the `changedResources` set being `null`.
*/
simulateLegacyCLICompilerHost() { this.changedResources = null; }
simulateLegacyCLICompilerHost() {
this.changedResources = null;
}
getFilesWrittenSinceLastFlush(): Set<string> {
if (this.multiCompileHostExt === null) {
@ -142,7 +144,7 @@ export class NgtscTestEnvironment {
const absFilePath = this.fs.resolve(this.basePath, fileName);
if (this.multiCompileHostExt !== null) {
this.multiCompileHostExt.invalidate(absFilePath);
this.changedResources !.add(absFilePath);
this.changedResources!.add(absFilePath);
}
this.fs.ensureDir(this.fs.dirname(absFilePath));
this.fs.writeFile(absFilePath, content);
@ -156,8 +158,7 @@ export class NgtscTestEnvironment {
this.multiCompileHostExt.invalidate(absFilePath);
}
tsconfig(extraOpts: {[key: string]: string | boolean | null} = {}, extraRootDirs?: string[]):
void {
tsconfig(extraOpts: {[key: string]: string|boolean|null} = {}, extraRootDirs?: string[]): void {
const tsconfig: {[key: string]: any} = {
extends: './tsconfig-base.json',
angularCompilerOptions: {...extraOpts, enableIvy: true},
@ -179,7 +180,7 @@ export class NgtscTestEnvironment {
*/
driveMain(customTransformers?: CustomTransformers): void {
const errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error);
let reuseProgram: {program: Program | undefined}|undefined = undefined;
let reuseProgram: {program: Program|undefined}|undefined = undefined;
if (this.multiCompileHostExt !== null) {
reuseProgram = {
program: this.oldProgram || undefined,
@ -191,7 +192,7 @@ export class NgtscTestEnvironment {
expect(errorSpy).not.toHaveBeenCalled();
expect(exitCode).toBe(0);
if (this.multiCompileHostExt !== null) {
this.oldProgram = reuseProgram !.program !;
this.oldProgram = reuseProgram!.program!;
}
}
@ -200,7 +201,7 @@ export class NgtscTestEnvironment {
*/
driveDiagnostics(): ReadonlyArray<ts.Diagnostic> {
// ngtsc only produces ts.Diagnostic messages.
let reuseProgram: {program: Program | undefined}|undefined = undefined;
let reuseProgram: {program: Program|undefined}|undefined = undefined;
if (this.multiCompileHostExt !== null) {
reuseProgram = {
program: this.oldProgram || undefined,
@ -212,7 +213,7 @@ export class NgtscTestEnvironment {
if (this.multiCompileHostExt !== null) {
this.oldProgram = reuseProgram !.program !;
this.oldProgram = reuseProgram!.program!;
}
// In ngtsc, only `ts.Diagnostic`s are produced.
@ -245,7 +246,7 @@ export class NgtscTestEnvironment {
}
class AugmentedCompilerHost extends NgtscCompilerHost {
delegate !: ts.CompilerHost;
delegate!: ts.CompilerHost;
}
const ROOT_PREFIX = 'root/';
@ -283,7 +284,7 @@ class MultiCompileHostExt extends AugmentedCompilerHost implements Partial<ts.Co
fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void,
shouldCreateNewSourceFile?: boolean): ts.SourceFile|undefined {
if (this.cache.has(fileName)) {
return this.cache.get(fileName) !;
return this.cache.get(fileName)!;
}
const sf = super.getSourceFile(fileName, languageVersion);
if (sf !== undefined) {
@ -292,7 +293,9 @@ class MultiCompileHostExt extends AugmentedCompilerHost implements Partial<ts.Co
return sf;
}
flushWrittenFileTracking(): void { this.writtenFiles.clear(); }
flushWrittenFileTracking(): void {
this.writtenFiles.clear();
}
writeFile(
fileName: string, data: string, writeByteOrderMark: boolean,
@ -302,9 +305,13 @@ class MultiCompileHostExt extends AugmentedCompilerHost implements Partial<ts.Co
this.writtenFiles.add(fileName);
}
getFilesWrittenSinceLastFlush(): Set<string> { return this.writtenFiles; }
getFilesWrittenSinceLastFlush(): Set<string> {
return this.writtenFiles;
}
invalidate(fileName: string): void { this.cache.delete(fileName); }
invalidate(fileName: string): void {
this.cache.delete(fileName);
}
}
class ResourceLoadingCompileHost extends AugmentedCompilerHost implements api.CompilerHost {
@ -323,7 +330,7 @@ function makeWrapHost(wrapped: AugmentedCompilerHost): (host: ts.CompilerHost) =
return new Proxy(delegate, {
get: (target: ts.CompilerHost, name: string): any => {
if ((wrapped as any)[name] !== undefined) {
return (wrapped as any)[name] !.bind(wrapped);
return (wrapped as any)[name]!.bind(wrapped);
}
return (target as any)[name];
}

View File

@ -8,19 +8,19 @@
interface FnWithArg<T> {
(...args: any[]): T;
new (...args: any[]): T;
new(...args: any[]): T;
}
function callableClassDecorator(): FnWithArg<(clazz: any) => any> {
return null !;
return null!;
}
function callableParamDecorator(): FnWithArg<(a: any, b: any, c: any) => void> {
return null !;
return null!;
}
function callablePropDecorator(): FnWithArg<(a: any, b: any) => any> {
return null !;
return null!;
}
export const Component = callableClassDecorator();
@ -66,7 +66,9 @@ export function forwardRef<T>(fn: () => T): T {
return fn();
}
export interface SimpleChanges { [propName: string]: any; }
export interface SimpleChanges {
[propName: string]: any;
}
export type ɵɵNgModuleDefWithMeta<ModuleT, DeclarationsT, ImportsT, ExportsT> = any;
export type ɵɵDirectiveDefWithMeta<
@ -89,11 +91,15 @@ export const CUSTOM_ELEMENTS_SCHEMA: any = false;
export const NO_ERRORS_SCHEMA: any = false;
export class EventEmitter<T> {
subscribe(generatorOrNext?: any, error?: any, complete?: any): unknown { return null; }
subscribe(generatorOrNext?: any, error?: any, complete?: any): unknown {
return null;
}
}
export interface QueryList<T>/* implements Iterable<T> */ { [Symbol.iterator]: () => Iterator<T>; }
export interface QueryList<T>/* implements Iterable<T> */ {
[Symbol.iterator]: () => Iterator<T>;
}
export type NgIterable<T> = Array<T>| Iterable<T>;
export type NgIterable<T> = Array<T>|Iterable<T>;
export class NgZone {}

View File

@ -16,7 +16,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('ngtsc incremental compilation with errors', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
@ -66,7 +66,7 @@ runInEachFileSystem(() => {
`);
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/other.ts'));
expect(diags[0].file!.fileName).toBe(_('/other.ts'));
expectToHaveWritten([]);
// Remove the error. /other.js should now be emitted again.
@ -92,7 +92,7 @@ runInEachFileSystem(() => {
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/other.ts'));
expect(diags[0].file!.fileName).toBe(_('/other.ts'));
expectToHaveWritten([]);
// Remove the error. All files should be emitted.
@ -128,7 +128,7 @@ runInEachFileSystem(() => {
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/other.ts'));
expect(diags[0].file!.fileName).toBe(_('/other.ts'));
expectToHaveWritten([]);
// Remove the error. All files should be emitted.
@ -175,7 +175,7 @@ runInEachFileSystem(() => {
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/other.ts'));
expect(diags[0].file!.fileName).toBe(_('/other.ts'));
expectToHaveWritten([]);
// Remove the error. All files should be emitted.

View File

@ -15,7 +15,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('ngtsc incremental compilation', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);

View File

@ -17,7 +17,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('ModuleWithProviders generic type transform', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);

View File

@ -16,7 +16,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('monorepos', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles, absoluteFrom('/app'));

View File

@ -38,12 +38,12 @@ const setClassMetadataRegExp = (expectedType: string): RegExp =>
const testFiles = loadStandardTestFiles();
function getDiagnosticSourceCode(diag: ts.Diagnostic): string {
return diag.file !.text.substr(diag.start !, diag.length !);
return diag.file!.text.substr(diag.start!, diag.length!);
}
runInEachFileSystem(os => {
describe('ngtsc behavioral tests', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
@ -369,7 +369,6 @@ runInEachFileSystem(os => {
// that start with `C:`.
if (os !== 'Windows' || platform() === 'win32') {
describe('when closure annotations are requested', () => {
it('should add @nocollapse to static fields', () => {
env.tsconfig({
'annotateForClosureCompiler': true,
@ -531,7 +530,6 @@ runInEachFileSystem(os => {
verifyOutput(env.getContents('test.js'));
});
});
});
}
@ -1714,7 +1712,8 @@ runInEachFileSystem(os => {
});
['ContentChild', 'ContentChildren'].forEach(decorator => {
it(`should throw if \`descendants\` field of @${decorator}'s options argument has wrong type`,
it(`should throw if \`descendants\` field of @${
decorator}'s options argument has wrong type`,
() => {
env.tsconfig({});
env.write('test.ts', `
@ -2148,7 +2147,6 @@ runInEachFileSystem(os => {
expect(jsContents)
.toContain('Test.ɵfac = function Test_Factory(t) { i0.ɵɵinvalidFactory()');
});
});
});
@ -3466,7 +3464,9 @@ runInEachFileSystem(os => {
});
describe('ngfactory shims', () => {
beforeEach(() => { env.tsconfig({'generateNgFactoryShims': true}); });
beforeEach(() => {
env.tsconfig({'generateNgFactoryShims': true});
});
it('should generate correct type annotation for NgModuleFactory calls in ngfactories', () => {
env.write('test.ts', `
@ -3568,7 +3568,9 @@ runInEachFileSystem(os => {
describe('ngsummary shim generation', () => {
beforeEach(() => { env.tsconfig({'generateNgSummaryShims': true}); });
beforeEach(() => {
env.tsconfig({'generateNgSummaryShims': true});
});
it('should generate a summary stub for decorated classes in the input file only', () => {
env.write('test.ts', `
@ -3792,7 +3794,6 @@ runInEachFileSystem(os => {
});
it('should use imported types in setClassMetadata if they can be represented as values', () => {
env.write(`types.ts`, `
export class MyTypeA {}
export class MyTypeB {}
@ -3824,7 +3825,6 @@ runInEachFileSystem(os => {
it('should use imported types in setClassMetadata if they can be represented as values and imported as `* as foo`',
() => {
env.write(`types.ts`, `
export class MyTypeA {}
export class MyTypeB {}
@ -3855,7 +3855,6 @@ runInEachFileSystem(os => {
});
it('should use default-imported types if they can be represented as values', () => {
env.write(`types.ts`, `
export default class Default {}
export class Other {}
@ -3883,7 +3882,6 @@ runInEachFileSystem(os => {
it('should use `undefined` in setClassMetadata if types can\'t be represented as values',
() => {
env.write(`types.ts`, `
export type MyType = Map<any, any>;
`);
@ -4059,7 +4057,6 @@ runInEachFileSystem(os => {
it('should not generate an error when a local ref is unresolved' +
' (outside of template type-checking)',
() => {
env.write('test.ts', `
import {Component} from '@angular/core';
@ -4347,7 +4344,7 @@ runInEachFileSystem(os => {
}
});
it('should throw if @Component is missing a template', async() => {
it('should throw if @Component is missing a template', async () => {
env.write('test.ts', `
import {Component} from '@angular/core';
@ -4359,10 +4356,10 @@ runInEachFileSystem(os => {
const diags = await driveDiagnostics();
expect(diags[0].messageText).toBe('component is missing a template');
expect(diags[0].file !.fileName).toBe(absoluteFrom('/test.ts'));
expect(diags[0].file!.fileName).toBe(absoluteFrom('/test.ts'));
});
it('should throw if `styleUrls` is defined incorrectly in @Component', async() => {
it('should throw if `styleUrls` is defined incorrectly in @Component', async () => {
env.write('test.ts', `
import {Component} from '@angular/core';
@ -4376,7 +4373,7 @@ runInEachFileSystem(os => {
const diags = await driveDiagnostics();
expect(diags[0].messageText).toBe('styleUrls must be an array of strings');
expect(diags[0].file !.fileName).toBe(absoluteFrom('/test.ts'));
expect(diags[0].file!.fileName).toBe(absoluteFrom('/test.ts'));
});
});
});
@ -4497,7 +4494,7 @@ runInEachFileSystem(os => {
// Verify that the error is for the correct class.
const error = errors[0] as ts.Diagnostic;
const id = expectTokenAtPosition(error.file !, error.start !, ts.isIdentifier);
const id = expectTokenAtPosition(error.file!, error.start!, ts.isIdentifier);
expect(id.text).toBe('Dir');
expect(ts.isClassDeclaration(id.parent)).toBe(true);
});
@ -4804,7 +4801,7 @@ runInEachFileSystem(os => {
const diag = env.driveDiagnostics();
expect(diag.length).toBe(1);
expect(diag[0] !.code).toEqual(ngErrorCode(ErrorCode.NGMODULE_REEXPORT_NAME_COLLISION));
expect(diag[0]!.code).toEqual(ngErrorCode(ErrorCode.NGMODULE_REEXPORT_NAME_COLLISION));
});
it('should not error when two directives with the same declared name are exported from the same NgModule, but one is exported from the file directly',
@ -6701,9 +6698,7 @@ export const Foo = Foo__PRE_R3__;
const diags = env.driveDiagnostics();
expect(diags.length).toBe(0);
});
});
});
function expectTokenAtPosition<T extends ts.Node>(
@ -6714,5 +6709,7 @@ export const Foo = Foo__PRE_R3__;
return node as T;
}
function normalize(input: string): string { return input.replace(/\s+/g, ' ').trim(); }
function normalize(input: string): string {
return input.replace(/\s+/g, ' ').trim();
}
});

View File

@ -20,7 +20,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('ngtsc module scopes', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
@ -92,11 +92,11 @@ runInEachFileSystem(() => {
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
const node = findContainingClass(diagnosticToNode(diags[0], ts.isIdentifier));
expect(node.name !.text).toEqual('TestDir');
expect(node.name!.text).toEqual('TestDir');
const relatedNodes = new Set(diags[0].relatedInformation !.map(
const relatedNodes = new Set(diags[0].relatedInformation!.map(
related =>
findContainingClass(diagnosticToNode(related, ts.isIdentifier)).name !.text));
findContainingClass(diagnosticToNode(related, ts.isIdentifier)).name!.text));
expect(relatedNodes).toContain('ModuleA');
expect(relatedNodes).toContain('ModuleB');
expect(relatedNodes.size).toBe(2);
@ -141,11 +141,11 @@ runInEachFileSystem(() => {
const diags = env.driveDiagnostics();
expect(diags.length).toBe(1);
const node = findContainingClass(diagnosticToNode(diags[0], ts.isIdentifier));
expect(node.name !.text).toEqual('TestDir');
expect(node.name!.text).toEqual('TestDir');
const relatedNodes = new Set(diags[0].relatedInformation !.map(
const relatedNodes = new Set(diags[0].relatedInformation!.map(
related =>
findContainingClass(diagnosticToNode(related, ts.isIdentifier)).name !.text));
findContainingClass(diagnosticToNode(related, ts.isIdentifier)).name!.text));
expect(relatedNodes).toContain('ModuleA');
expect(relatedNodes).toContain('ModuleB');
expect(relatedNodes.size).toBe(2);
@ -386,13 +386,13 @@ runInEachFileSystem(() => {
});
function diagnosticToNode<T extends ts.Node>(
diagnostic: ts.Diagnostic | Diagnostic | ts.DiagnosticRelatedInformation,
diagnostic: ts.Diagnostic|Diagnostic|ts.DiagnosticRelatedInformation,
guard: (node: ts.Node) => node is T): T {
const diag = diagnostic as ts.Diagnostic | ts.DiagnosticRelatedInformation;
if (diag.file === undefined) {
throw new Error(`Expected ts.Diagnostic to have a file source`);
}
const node = getTokenAtPosition(diag.file, diag.start !);
const node = getTokenAtPosition(diag.file, diag.start!);
expect(guard(node)).toBe(true);
return node as T;
}

View File

@ -85,7 +85,7 @@ export function getMappedSegments(
while (currentMapping) {
const nextMapping = mappings.shift();
if (nextMapping) {
const source = sources.get(currentMapping.source) !;
const source = sources.get(currentMapping.source)!;
const segment = {
generated: generated.getSegment('generated', currentMapping, nextMapping),
source: source.getSegment('original', currentMapping, nextMapping),

View File

@ -14,13 +14,13 @@ import {tsSourceMapBug29300Fixed} from '../../src/ngtsc/util/src/ts_source_map_b
import {loadStandardTestFiles} from '../helpers/src/mock_file_loading';
import {NgtscTestEnvironment} from './env';
import {SegmentMapping, getMappedSegments} from './sourcemap_utils';
import {getMappedSegments, SegmentMapping} from './sourcemap_utils';
const testFiles = loadStandardTestFiles();
runInEachFileSystem((os) => {
describe('template source-mapping', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
@ -323,7 +323,6 @@ runInEachFileSystem((os) => {
expect(mappings).toContain(
{source: '</div>', generated: 'i0.ɵɵelementEnd()', sourceUrl: '../test.ts'});
});
it('should map ng-template [ngFor] scenario', () => {
@ -518,7 +517,7 @@ runInEachFileSystem((os) => {
});
}
function compileAndMap(template: string, templateUrl: string | null = null) {
function compileAndMap(template: string, templateUrl: string|null = null) {
const templateConfig = templateUrl ? `templateUrl: '${templateUrl}'` :
('template: `' + template.replace(/`/g, '\\`') + '`');
env.tsconfig({sourceMap: true});

View File

@ -19,7 +19,7 @@ const testFiles = loadStandardTestFiles();
runInEachFileSystem(() => {
describe('ngtsc type checking', () => {
let env !: NgtscTestEnvironment;
let env!: NgtscTestEnvironment;
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
@ -1502,8 +1502,9 @@ export declare class AnimationEvent {
});
describe('legacy schema checking with the DOM schema', () => {
beforeEach(
() => { env.tsconfig({ivyTemplateTypeCheck: true, fullTemplateTypeCheck: false}); });
beforeEach(() => {
env.tsconfig({ivyTemplateTypeCheck: true, fullTemplateTypeCheck: false});
});
it('should check for unknown elements', () => {
env.write('test.ts', `
@ -1734,7 +1735,7 @@ export declare class AnimationEvent {
}
});
it('should be correct for direct templates', async() => {
it('should be correct for direct templates', async () => {
env.write('test.ts', `
import {Component, NgModule} from '@angular/core';
@ -1750,11 +1751,11 @@ export declare class AnimationEvent {
const diags = await driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/test.ts'));
expect(diags[0].file!.fileName).toBe(_('/test.ts'));
expect(getSourceCodeForDiagnostic(diags[0])).toBe('user.does_not_exist');
});
it('should be correct for indirect templates', async() => {
it('should be correct for indirect templates', async () => {
env.write('test.ts', `
import {Component, NgModule} from '@angular/core';
@ -1772,12 +1773,12 @@ export declare class AnimationEvent {
const diags = await driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/test.ts') + ' (TestCmp template)');
expect(diags[0].file!.fileName).toBe(_('/test.ts') + ' (TestCmp template)');
expect(getSourceCodeForDiagnostic(diags[0])).toBe('user.does_not_exist');
expect(getSourceCodeForDiagnostic(diags[0].relatedInformation ![0])).toBe('TEMPLATE');
expect(getSourceCodeForDiagnostic(diags[0].relatedInformation![0])).toBe('TEMPLATE');
});
it('should be correct for external templates', async() => {
it('should be correct for external templates', async () => {
env.write('template.html', `<p>
{{user.does_not_exist}}
</p>`);
@ -1795,9 +1796,9 @@ export declare class AnimationEvent {
const diags = await driveDiagnostics();
expect(diags.length).toBe(1);
expect(diags[0].file !.fileName).toBe(_('/template.html'));
expect(diags[0].file!.fileName).toBe(_('/template.html'));
expect(getSourceCodeForDiagnostic(diags[0])).toBe('user.does_not_exist');
expect(getSourceCodeForDiagnostic(diags[0].relatedInformation ![0]))
expect(getSourceCodeForDiagnostic(diags[0].relatedInformation![0]))
.toBe(`'./template.html'`);
});
});
@ -1841,6 +1842,6 @@ export declare class AnimationEvent {
});
function getSourceCodeForDiagnostic(diag: ts.Diagnostic): string {
const text = diag.file !.text;
return text.substr(diag.start !, diag.length !);
const text = diag.file!.text;
return text.substr(diag.start!, diag.length!);
}

View File

@ -10,7 +10,7 @@ import * as path from 'path';
import {readConfiguration} from '../src/perform_compile';
import {TestSupport, setup} from './test_support';
import {setup, TestSupport} from './test_support';
describe('perform_compile', () => {
let support: TestSupport;

View File

@ -14,7 +14,7 @@ import * as ts from 'typescript';
import * as ng from '../index';
import {FileChangeEvent, performWatchCompilation} from '../src/perform_watch';
import {TestSupport, expectNoDiagnostics, setup} from './test_support';
import {expectNoDiagnostics, setup, TestSupport} from './test_support';
describe('perform watch', () => {
let testSupport: TestSupport;
@ -105,23 +105,23 @@ describe('perform watch', () => {
performWatchCompilation(host);
expect(fs.existsSync(mainNgFactory)).toBe(true);
expect(fileExistsSpy !).toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy !).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy !).toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy !).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
expect(fileExistsSpy!).toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy!).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy!).toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy!).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
fileExistsSpy !.calls.reset();
getSourceFileSpy !.calls.reset();
fileExistsSpy!.calls.reset();
getSourceFileSpy!.calls.reset();
// trigger a single file change
// -> all other files should be cached
host.triggerFileChange(FileChangeEvent.Change, utilTsPath);
expectNoDiagnostics(config.options, host.diagnostics);
expect(fileExistsSpy !).not.toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy !).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy !).not.toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy !).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
expect(fileExistsSpy!).not.toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy!).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy!).not.toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy!).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
// trigger a folder change
// -> nothing should be cached
@ -129,10 +129,10 @@ describe('perform watch', () => {
FileChangeEvent.CreateDeleteDir, path.resolve(testSupport.basePath, 'src'));
expectNoDiagnostics(config.options, host.diagnostics);
expect(fileExistsSpy !).toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy !).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy !).toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy !).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
expect(fileExistsSpy!).toHaveBeenCalledWith(mainTsPath);
expect(fileExistsSpy!).toHaveBeenCalledWith(utilTsPath);
expect(getSourceFileSpy!).toHaveBeenCalledWith(mainTsPath, ts.ScriptTarget.ES5);
expect(getSourceFileSpy!).toHaveBeenCalledWith(utilTsPath, ts.ScriptTarget.ES5);
});
// https://github.com/angular/angular/pull/26036
@ -239,10 +239,18 @@ class MockWatchHost {
diagnostics: ng.Diagnostic[] = [];
constructor(public config: ng.ParsedConfiguration) {}
reportDiagnostics(diags: ng.Diagnostics) { this.diagnostics.push(...(diags as ng.Diagnostic[])); }
readConfiguration() { return this.config; }
createCompilerHost(options: ng.CompilerOptions) { return ng.createCompilerHost({options}); }
createEmitCallback() { return undefined; }
reportDiagnostics(diags: ng.Diagnostics) {
this.diagnostics.push(...(diags as ng.Diagnostic[]));
}
readConfiguration() {
return this.config;
}
createCompilerHost(options: ng.CompilerOptions) {
return ng.createCompilerHost({options});
}
createEmitCallback() {
return undefined;
}
onFileChange(
options: ng.CompilerOptions, listener: (event: FileChangeEvent, fileName: string) => void,
ready: () => void) {
@ -258,7 +266,9 @@ class MockWatchHost {
this.timeoutListeners[id] = callback;
return id;
}
clearTimeout(timeoutId: any): void { delete this.timeoutListeners[timeoutId]; }
clearTimeout(timeoutId: any): void {
delete this.timeoutListeners[timeoutId];
}
flushTimeouts() {
const listeners = this.timeoutListeners;
this.timeoutListeners = {};

View File

@ -15,7 +15,7 @@ import {NodeJSFileSystem, setFileSystem} from '../src/ngtsc/file_system';
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '../test/helpers';
// TEST_TMPDIR is always set by Bazel.
const tmpdir = process.env.TEST_TMPDIR !;
const tmpdir = process.env.TEST_TMPDIR!;
export function makeTempDir(): string {
let dir: string;
@ -97,8 +97,11 @@ function createTestSupportFor(basePath: string) {
}
function writeFiles(...mockDirs: {[fileName: string]: string}[]) {
mockDirs.forEach(
(dir) => { Object.keys(dir).forEach((fileName) => { write(fileName, dir[fileName]); }); });
mockDirs.forEach((dir) => {
Object.keys(dir).forEach((fileName) => {
write(fileName, dir[fileName]);
});
});
}
function createCompilerOptions(overrideOptions: ng.CompilerOptions = {}): ng.CompilerOptions {

View File

@ -11,7 +11,7 @@ import * as ts from 'typescript';
import {MetadataCollector} from '../../src/metadata/collector';
import {CompilerHost, CompilerOptions, LibrarySummary} from '../../src/transformers/api';
import {TsCompilerAotCompilerTypeCheckHostAdapter, createCompilerHost} from '../../src/transformers/compiler_host';
import {createCompilerHost, TsCompilerAotCompilerTypeCheckHostAdapter} from '../../src/transformers/compiler_host';
import {Directory, Entry, MockAotContext, MockCompilerHost} from '../mocks';
const dummyModule = 'export let foo: any[];';
@ -53,12 +53,15 @@ describe('NgCompilerHost', () => {
} = {}) {
return new TsCompilerAotCompilerTypeCheckHostAdapter(
rootNames, options, ngHost, new MetadataCollector(), codeGenerator,
new Map(librarySummaries.map(entry => [entry.fileName, entry] as[string, LibrarySummary])));
new Map(
librarySummaries.map(entry => [entry.fileName, entry] as [string, LibrarySummary])));
}
describe('fileNameToModuleName', () => {
let host: TsCompilerAotCompilerTypeCheckHostAdapter;
beforeEach(() => { host = createHost(); });
beforeEach(() => {
host = createHost();
});
it('should use a package import when accessing a package from a source file', () => {
expect(host.fileNameToModuleName('/tmp/node_modules/@angular/core.d.ts', '/tmp/main.ts'))
@ -239,9 +242,8 @@ describe('NgCompilerHost', () => {
it('should not get tripped on nested node_modules', () => {
const genSf = generate('/tmp/node_modules/lib1/node_modules/lib2/thing', {
'tmp': {
'node_modules': {'lib1': {'node_modules': {'lib2': {'thing.ts': `// some content`}}}}
}
'tmp':
{'node_modules': {'lib1': {'node_modules': {'lib2': {'thing.ts': `// some content`}}}}}
});
expect(genSf.moduleName).toBe('lib2/thing.ngfactory');
});
@ -387,8 +389,9 @@ describe('NgCompilerHost', () => {
() => host.updateGeneratedFile(new compiler.GeneratedFile(
'/tmp/src/index.ts', '/tmp/src/index.ngfactory.ts',
[new compiler.DeclareVarStmt(
'x', new compiler.ExternalExpr(
new compiler.ExternalReference('otherModule', 'aName')))])))
'x',
new compiler.ExternalExpr(
new compiler.ExternalReference('otherModule', 'aName')))])))
.toThrowError([
`Illegal State: external references changed in /tmp/src/index.ngfactory.ts.`,
`Old: aModule.`, `New: otherModule`

View File

@ -8,8 +8,8 @@
import * as ts from 'typescript';
import {MetadataCollector, isClassMetadata} from '../../src/metadata/index';
import {InlineResourcesMetadataTransformer, getInlineResourcesTransformFactory} from '../../src/transformers/inline_resources';
import {isClassMetadata, MetadataCollector} from '../../src/metadata/index';
import {getInlineResourcesTransformFactory, InlineResourcesMetadataTransformer} from '../../src/transformers/inline_resources';
import {MetadataCache} from '../../src/transformers/metadata_cache';
import {MockAotContext, MockCompilerHost} from '../mocks';

View File

@ -9,7 +9,7 @@
import * as ts from 'typescript';
import {MetadataCollector, ModuleMetadata} from '../../src/metadata/index';
import {LowerMetadataTransform, LoweringRequest, RequestLocationMap, getExpressionLoweringTransformFactory} from '../../src/transformers/lower_expressions';
import {getExpressionLoweringTransformFactory, LoweringRequest, LowerMetadataTransform, RequestLocationMap} from '../../src/transformers/lower_expressions';
import {MetadataCache} from '../../src/transformers/metadata_cache';
import {Directory, MockAotContext, MockCompilerHost} from '../mocks';
@ -196,14 +196,16 @@ function convert(annotatedSource: string) {
const program = ts.createProgram(
[fileName], {module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017}, host);
const moduleSourceFile = program.getSourceFile(fileName) !;
const moduleSourceFile = program.getSourceFile(fileName)!;
const transformers: ts.CustomTransformers = {
before: [getExpressionLoweringTransformFactory(
{
getRequests(sourceFile: ts.SourceFile): RequestLocationMap{
getRequests(sourceFile: ts.SourceFile): RequestLocationMap {
if (sourceFile.fileName == moduleSourceFile.fileName) {
return requests;
} else {return new Map();}
} else {
return new Map();
}
}
},
program)]
@ -254,6 +256,7 @@ function collect(annotatedSource: string) {
'someName.ts', unannotatedSource, ts.ScriptTarget.Latest, /* setParentNodes */ true);
return {
metadata: cache.getMetadata(sourceFile),
requests: transformer.getRequests(sourceFile), annotations
requests: transformer.getRequests(sourceFile),
annotations
};
}

View File

@ -23,10 +23,9 @@ describe('metadata reader', () => {
readFile: (fileName) => context.readFile(fileName),
getSourceFileMetadata: (fileName) => {
const sourceText = context.readFile(fileName);
return sourceText != null ?
metadataCollector.getMetadata(
ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest)) :
undefined;
return sourceText != null ? metadataCollector.getMetadata(ts.createSourceFile(
fileName, sourceText, ts.ScriptTarget.Latest)) :
undefined;
},
};
});
@ -42,11 +41,13 @@ describe('metadata reader', () => {
expect(readMetadata('node_modules/@angular/unused.d.ts', host)).toEqual([dummyMetadata]);
});
it('should be able to read empty metadata ',
() => { expect(readMetadata('node_modules/@angular/empty.d.ts', host)).toEqual([]); });
it('should be able to read empty metadata ', () => {
expect(readMetadata('node_modules/@angular/empty.d.ts', host)).toEqual([]);
});
it('should return undefined for missing modules',
() => { expect(readMetadata('node_modules/@angular/missing.d.ts', host)).toBeUndefined(); });
it('should return undefined for missing modules', () => {
expect(readMetadata('node_modules/@angular/missing.d.ts', host)).toBeUndefined();
});
it(`should add missing v${METADATA_VERSION} metadata from v1 metadata and .d.ts files`, () => {
expect(readMetadata('metadata_versions/v1.d.ts', host)).toEqual([
@ -117,8 +118,8 @@ const FILES: Entry = {
'node_modules': {
'@angular': {
'core.d.ts': dummyModule,
'core.metadata.json':
`{"__symbolic":"module", "version": ${METADATA_VERSION}, "metadata": {"foo": {"__symbolic": "class"}}}`,
'core.metadata.json': `{"__symbolic":"module", "version": ${
METADATA_VERSION}, "metadata": {"foo": {"__symbolic": "class"}}}`,
'router': {'index.d.ts': dummyModule, 'src': {'providers.d.ts': dummyModule}},
'unused.d.ts': dummyModule,
'empty.d.ts': 'export declare var a: string;',

View File

@ -38,7 +38,7 @@ describe('TypeScriptNodeEmitter', () => {
});
function emitStmt(
stmt: o.Statement | o.Statement[], format: Format = Format.Flat, preamble?: string): string {
stmt: o.Statement|o.Statement[], format: Format = Format.Flat, preamble?: string): string {
const stmts = Array.isArray(stmt) ? stmt : [stmt];
const program = ts.createProgram(
@ -246,8 +246,8 @@ describe('TypeScriptNodeEmitter', () => {
expect(emitStmt(new o.DeclareFunctionStmt(
'someFn', [], [new o.ReturnStatement(o.literal(1))], o.INT_TYPE)))
.toEqual(`function someFn() { return 1; }`);
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [new o.FnParam('param1', o.INT_TYPE)], [
]))).toEqual(`function someFn(param1) { }`);
expect(emitStmt(new o.DeclareFunctionStmt('someFn', [new o.FnParam('param1', o.INT_TYPE)], [])))
.toEqual(`function someFn(param1) { }`);
});
describe('comments', () => {
@ -256,8 +256,9 @@ describe('TypeScriptNodeEmitter', () => {
.toBe('/* SomePreamble */ a;');
});
it('should support singleline comments',
() => { expect(emitStmt(new o.CommentStmt('Simple comment'))).toBe('// Simple comment'); });
it('should support singleline comments', () => {
expect(emitStmt(new o.CommentStmt('Simple comment'))).toBe('// Simple comment');
});
it('should support multiline comments', () => {
expect(emitStmt(new o.CommentStmt('Multiline comment', true)))
@ -314,86 +315,90 @@ describe('TypeScriptNodeEmitter', () => {
`try { body(); } catch (error) { var stack = error.stack; catchFn(error, stack); }`);
});
it('should support support throwing',
() => { expect(emitStmt(new o.ThrowStmt(someVar))).toEqual('throw someVar;'); });
it('should support support throwing', () => {
expect(emitStmt(new o.ThrowStmt(someVar))).toEqual('throw someVar;');
});
describe('classes', () => {
let callSomeMethod: o.Statement;
beforeEach(() => { callSomeMethod = o.THIS_EXPR.callMethod('someMethod', []).toStmt(); });
beforeEach(() => {
callSomeMethod = o.THIS_EXPR.callMethod('someMethod', []).toStmt();
});
it('should support declaring classes', () => {
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
]))).toEqual('class SomeClass { }');
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [], [
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [])))
.toEqual('class SomeClass { }');
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [], [
o.StmtModifier.Exported
]))).toEqual('class SomeClass { } exports.SomeClass = SomeClass;');
expect(emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null !, [
]))).toEqual('class SomeClass extends SomeSuperClass { }');
expect(
emitStmt(new o.ClassStmt('SomeClass', o.variable('SomeSuperClass'), [], [], null!, [])))
.toEqual('class SomeClass extends SomeSuperClass { }');
});
it('should support declaring constructors', () => {
const superCall = o.SUPER_EXPR.callFn([o.variable('someParam')]).toStmt();
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [], new o.ClassMethod(null !, [], []), [])))
expect(emitStmt(
new o.ClassStmt('SomeClass', null!, [], [], new o.ClassMethod(null!, [], []), [])))
.toEqual(`class SomeClass { constructor() { } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [],
new o.ClassMethod(null !, [new o.FnParam('someParam', o.INT_TYPE)], []), [])))
'SomeClass', null!, [], [],
new o.ClassMethod(null!, [new o.FnParam('someParam', o.INT_TYPE)], []), [])))
.toEqual(`class SomeClass { constructor(someParam) { } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [], new o.ClassMethod(null !, [], [superCall]), [])))
'SomeClass', null!, [], [], new o.ClassMethod(null!, [], [superCall]), [])))
.toEqual(`class SomeClass { constructor() { super(someParam); } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [], new o.ClassMethod(null !, [], [callSomeMethod]), [])))
'SomeClass', null!, [], [], new o.ClassMethod(null!, [], [callSomeMethod]), [])))
.toEqual(`class SomeClass { constructor() { this.someMethod(); } }`);
});
it('should support declaring fields', () => {
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [new o.ClassField('someField')], [], null !, [])))
'SomeClass', null!, [new o.ClassField('someField')], [], null!, [])))
.toEqual(`class SomeClass { constructor() { this.someField = null; } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [new o.ClassField('someField', o.INT_TYPE)], [], null !, [])))
'SomeClass', null!, [new o.ClassField('someField', o.INT_TYPE)], [], null!, [])))
.toEqual(`class SomeClass { constructor() { this.someField = null; } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !,
[new o.ClassField('someField', o.INT_TYPE, [o.StmtModifier.Private])], [], null !,
'SomeClass', null!,
[new o.ClassField('someField', o.INT_TYPE, [o.StmtModifier.Private])], [], null!,
[])))
.toEqual(`class SomeClass { constructor() { this.someField = null; } }`);
});
it('should support declaring getters', () => {
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [new o.ClassGetter('someGetter', [])], null !, [])))
'SomeClass', null!, [], [new o.ClassGetter('someGetter', [])], null!, [])))
.toEqual(`class SomeClass { get someGetter() { } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [new o.ClassGetter('someGetter', [], o.INT_TYPE)], null !,
'SomeClass', null!, [], [new o.ClassGetter('someGetter', [], o.INT_TYPE)], null!,
[])))
.toEqual(`class SomeClass { get someGetter() { } }`);
expect(emitStmt(new o.ClassStmt(
'SomeClass', null !, [], [new o.ClassGetter('someGetter', [callSomeMethod])],
null !, [])))
'SomeClass', null!, [], [new o.ClassGetter('someGetter', [callSomeMethod])], null!,
[])))
.toEqual(`class SomeClass { get someGetter() { this.someMethod(); } }`);
expect(
emitStmt(new o.ClassStmt(
'SomeClass', null !, [],
[new o.ClassGetter('someGetter', [], null !, [o.StmtModifier.Private])], null !, [])))
'SomeClass', null!, [],
[new o.ClassGetter('someGetter', [], null!, [o.StmtModifier.Private])], null!, [])))
.toEqual(`class SomeClass { get someGetter() { } }`);
});
it('should support methods', () => {
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [
new o.ClassMethod('someMethod', [], [])
]))).toEqual(`class SomeClass { someMethod() { } }`);
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [
new o.ClassMethod('someMethod', [], [], o.INT_TYPE)
]))).toEqual(`class SomeClass { someMethod() { } }`);
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [
new o.ClassMethod('someMethod', [new o.FnParam('someParam', o.INT_TYPE)], [])
]))).toEqual(`class SomeClass { someMethod(someParam) { } }`);
expect(emitStmt(new o.ClassStmt('SomeClass', null !, [], [], null !, [
expect(emitStmt(new o.ClassStmt('SomeClass', null!, [], [], null!, [
new o.ClassMethod('someMethod', [], [callSomeMethod])
]))).toEqual(`class SomeClass { someMethod() { this.someMethod(); } }`);
});
@ -431,7 +436,7 @@ describe('TypeScriptNodeEmitter', () => {
it('should support combined types', () => {
const writeVarExpr = o.variable('a').set(o.NULL_EXPR);
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(null !)))).toEqual('var a = null;');
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(null!)))).toEqual('var a = null;');
expect(emitStmt(writeVarExpr.toDeclStmt(new o.ArrayType(o.INT_TYPE)))).toEqual('var a = null;');
expect(emitStmt(writeVarExpr.toDeclStmt(new o.MapType(null)))).toEqual('var a = null;');
@ -439,7 +444,7 @@ describe('TypeScriptNodeEmitter', () => {
});
describe('source maps', () => {
function emitStmt(stmt: o.Statement | o.Statement[], preamble?: string): string {
function emitStmt(stmt: o.Statement|o.Statement[], preamble?: string): string {
const stmts = Array.isArray(stmt) ? stmt : [stmt];
const program = ts.createProgram(
@ -473,13 +478,15 @@ describe('TypeScriptNodeEmitter', () => {
function mappingItemsOf(text: string) {
// find the source map:
const sourceMapMatch = /sourceMappingURL\=data\:application\/json;base64,(.*)$/.exec(text);
const sourceMapBase64 = sourceMapMatch ![1];
const sourceMapBase64 = sourceMapMatch![1];
const sourceMapBuffer = Buffer.from(sourceMapBase64, 'base64');
const sourceMapText = sourceMapBuffer.toString('utf8');
const sourceMapParsed = JSON.parse(sourceMapText);
const consumer = new sourceMap.SourceMapConsumer(sourceMapParsed);
const mappings: any[] = [];
consumer.eachMapping((mapping: any) => { mappings.push(mapping); });
consumer.eachMapping((mapping: any) => {
mappings.push(mapping);
});
return mappings;
}
@ -503,7 +510,7 @@ describe('TypeScriptNodeEmitter', () => {
generatedColumn: 0,
originalLine: 1,
originalColumn: 0,
name: null ! // TODO: Review use of `!` here (#19904)
name: null! // TODO: Review use of `!` here (#19904)
},
{
source: sourceUrl,
@ -511,7 +518,7 @@ describe('TypeScriptNodeEmitter', () => {
generatedColumn: 16,
originalLine: 1,
originalColumn: 26,
name: null ! // TODO: Review use of `!` here (#19904)
name: null! // TODO: Review use of `!` here (#19904)
}
]);
});
@ -558,7 +565,10 @@ const FILES: Directory = {
somePackage: {'someGenFile.ts': `export var a: number;`}
};
const enum Format { Raw, Flat }
const enum Format {
Raw,
Flat
}
function normalizeResult(result: string, format: Format): string {
// Remove TypeScript prefixes

View File

@ -10,11 +10,12 @@ import * as ng from '@angular/compiler-cli';
import * as fs from 'fs';
import * as path from 'path';
import * as ts from 'typescript';
import {formatDiagnostics} from '../../src/perform_compile';
import {CompilerHost, EmitFlags, LazyRoute} from '../../src/transformers/api';
import {createSrcToOutPathMapper} from '../../src/transformers/program';
import {StructureIsReused, tsStructureIsReused} from '../../src/transformers/util';
import {TestSupport, expectNoDiagnosticsInProgram, setup, stripAnsi} from '../test_support';
import {expectNoDiagnosticsInProgram, setup, stripAnsi, TestSupport} from '../test_support';
describe('ng program', () => {
let testSupport: TestSupport;
@ -83,21 +84,21 @@ describe('ng program', () => {
const originalGetSourceFile = host.getSourceFile;
const cache = new Map<string, ts.SourceFile>();
host.getSourceFile = function(
fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile |
undefined {
const sf = originalGetSourceFile.call(host, fileName, languageVersion);
if (sf) {
if (cache.has(sf.fileName)) {
const oldSf = cache.get(sf.fileName) !;
if (oldSf.getFullText() === sf.getFullText()) {
return oldSf;
}
}
cache.set(sf.fileName, sf);
}
return sf;
};
host.getSourceFile = function(fileName: string, languageVersion: ts.ScriptTarget):
ts.SourceFile|
undefined {
const sf = originalGetSourceFile.call(host, fileName, languageVersion);
if (sf) {
if (cache.has(sf.fileName)) {
const oldSf = cache.get(sf.fileName)!;
if (oldSf.getFullText() === sf.getFullText()) {
return oldSf;
}
}
cache.set(sf.fileName, sf);
}
return sf;
};
return host;
}
@ -248,7 +249,8 @@ describe('ng program', () => {
fileCache.delete(path.posix.join(testSupport.basePath, 'src/index.ts'));
const p6 = ng.createProgram({
rootNames: [path.posix.join(testSupport.basePath, 'src/index.ts')],
options: testSupport.createCompilerOptions(options), host,
options: testSupport.createCompilerOptions(options),
host,
oldProgram: p5
});
const p7 = compile(p6, options, undefined, host).program;
@ -295,7 +297,6 @@ describe('ng program', () => {
describe(
'verify that program structure is reused within tsc in order to speed up incremental compilation',
() => {
it('should reuse the old ts program completely if nothing changed', () => {
testSupport.writeFiles({'src/index.ts': createModuleAndCompSource('main')});
const host = createWatchModeHost();
@ -351,7 +352,6 @@ describe('ng program', () => {
expect(tsStructureIsReused(p2.getTsProgram())).toBe(StructureIsReused.SafeModules);
});
});
});
it('should not typecheck templates if skipTemplateCodegen is set but fullTemplateTypeCheck is not',
@ -473,7 +473,7 @@ describe('ng program', () => {
host.writeFile =
(fileName: string, data: string, writeByteOrderMark: boolean,
onError: ((message: string) => void) | undefined,
onError: ((message: string) => void)|undefined,
sourceFiles?: ReadonlyArray<ts.SourceFile>) => {
written.set(fileName, {original: sourceFiles, data});
};
@ -487,19 +487,19 @@ describe('ng program', () => {
const writeData = written.get(path.posix.join(testSupport.basePath, fileName));
expect(writeData).toBeTruthy();
expect(
writeData !.original !.some(
writeData!.original!.some(
sf => sf.fileName === path.posix.join(testSupport.basePath, checks.originalFileName)))
.toBe(true);
switch (checks.shouldBe) {
case ShouldBe.Empty:
expect(writeData !.data).toMatch(/^(\s*\/\*([^*]|\*[^/])*\*\/\s*)?$/);
expect(writeData!.data).toMatch(/^(\s*\/\*([^*]|\*[^/])*\*\/\s*)?$/);
break;
case ShouldBe.EmptyExport:
expect(writeData !.data)
expect(writeData!.data)
.toMatch(/^((\s*\/\*([^*]|\*[^/])*\*\/\s*)|(\s*export\s*{\s*}\s*;\s*)|())$/);
break;
case ShouldBe.NoneEmpty:
expect(writeData !.data).not.toBe('');
expect(writeData!.data).not.toBe('');
break;
}
}
@ -1099,15 +1099,15 @@ describe('ng program', () => {
});
const host = ng.createCompilerHost({options});
const originalGetSourceFile = host.getSourceFile;
host.getSourceFile = (fileName: string, languageVersion: ts.ScriptTarget,
onError?: ((message: string) => void) | undefined): ts.SourceFile |
undefined => {
// We should never try to load .ngfactory.ts files
if (fileName.match(/\.ngfactory\.ts$/)) {
throw new Error(`Non existent ngfactory file: ` + fileName);
}
return originalGetSourceFile.call(host, fileName, languageVersion, onError);
};
host.getSourceFile =
(fileName: string, languageVersion: ts.ScriptTarget,
onError?: ((message: string) => void)|undefined): ts.SourceFile|undefined => {
// We should never try to load .ngfactory.ts files
if (fileName.match(/\.ngfactory\.ts$/)) {
throw new Error(`Non existent ngfactory file: ` + fileName);
}
return originalGetSourceFile.call(host, fileName, languageVersion, onError);
};
const program = ng.createProgram({rootNames: allRootNames, options, host});
const structuralErrors = program.getNgStructuralDiagnostics();
expect(structuralErrors.length).toBe(1);
@ -1115,5 +1115,4 @@ describe('ng program', () => {
.toContain('Function expressions are not supported');
});
});
});

View File

@ -9,12 +9,11 @@
import {ClassField, ClassMethod, ClassStmt, PartialModule, Statement, StmtModifier} from '@angular/compiler';
import * as ts from 'typescript';
import {MetadataCollector, isClassMetadata} from '../../src/metadata/index';
import {isClassMetadata, MetadataCollector} from '../../src/metadata/index';
import {MetadataCache} from '../../src/transformers/metadata_cache';
import {PartialModuleMetadataTransformer} from '../../src/transformers/r3_metadata_transform';
describe('r3_transform_spec', () => {
it('should add a static method to collected metadata', () => {
const fileName = '/some/directory/someFileName.ts';
const className = 'SomeClass';

View File

@ -30,8 +30,9 @@ describe('r3_transform_spec', () => {
.toContain('static someMethod(v) { return v; }');
});
it('should be able to generate a static field declaration',
() => { expect(emitStaticField(o.literal(10))).toContain('SomeClass.someField = 10'); });
it('should be able to generate a static field declaration', () => {
expect(emitStaticField(o.literal(10))).toContain('SomeClass.someField = 10');
});
it('should be able to import a symbol', () => {
expect(emitStaticMethod(new o.ReturnStatement(
@ -90,8 +91,8 @@ describe('r3_transform_spec', () => {
}
function emitStaticMethod(
stmt: o.Statement | o.Statement[], parameters: string[] = [],
methodName: string = 'someMethod', className: string = 'SomeClass'): string {
stmt: o.Statement|o.Statement[], parameters: string[] = [], methodName: string = 'someMethod',
className: string = 'SomeClass'): string {
const module: PartialModule = {
fileName: someGenFileName,
statements: [classMethod(stmt, parameters, methodName, className)]
@ -122,7 +123,7 @@ const FILES: Directory = {
};
function classMethod(
stmt: o.Statement | o.Statement[], parameters: string[] = [], methodName: string = 'someMethod',
stmt: o.Statement|o.Statement[], parameters: string[] = [], methodName: string = 'someMethod',
className: string = 'SomeClass'): o.ClassStmt {
const statements = Array.isArray(stmt) ? stmt : [stmt];
return new o.ClassStmt(

View File

@ -11,8 +11,8 @@ describe('checkVersion', () => {
const MIN_TS_VERSION = '2.7.2';
const MAX_TS_VERSION = '2.8.0';
const versionError = (version: string) =>
`The Angular Compiler requires TypeScript >=${MIN_TS_VERSION} and <${MAX_TS_VERSION} but ${version} was found instead.`;
const versionError = (version: string) => `The Angular Compiler requires TypeScript >=${
MIN_TS_VERSION} and <${MAX_TS_VERSION} but ${version} was found instead.`;
it('should not throw when a supported TypeScript version is used', () => {
expect(() => checkVersion('2.7.2', MIN_TS_VERSION, MAX_TS_VERSION)).not.toThrow();