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:
@ -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();
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -85,5 +85,4 @@ describe('compiler compliance: listen()', () => {
|
||||
expectEmit(result.source, componentDef, 'Incorrect component definition');
|
||||
expectEmit(result.source, directiveDef, 'Incorrect directive definition');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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) {
|
||||
|
@ -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>', () => {
|
||||
|
@ -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]));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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', `{
|
||||
|
@ -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 '..';
|
||||
|
@ -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/')}))
|
||||
|
@ -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,
|
||||
|
@ -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)!;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -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}}
|
||||
]);
|
||||
});
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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.
|
||||
|
@ -15,7 +15,7 @@ const testFiles = loadStandardTestFiles();
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('ngtsc incremental compilation', () => {
|
||||
let env !: NgtscTestEnvironment;
|
||||
let env!: NgtscTestEnvironment;
|
||||
|
||||
beforeEach(() => {
|
||||
env = NgtscTestEnvironment.setup(testFiles);
|
||||
|
@ -17,7 +17,7 @@ const testFiles = loadStandardTestFiles();
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('ModuleWithProviders generic type transform', () => {
|
||||
let env !: NgtscTestEnvironment;
|
||||
let env!: NgtscTestEnvironment;
|
||||
|
||||
beforeEach(() => {
|
||||
env = NgtscTestEnvironment.setup(testFiles);
|
||||
|
@ -16,7 +16,7 @@ const testFiles = loadStandardTestFiles();
|
||||
|
||||
runInEachFileSystem(() => {
|
||||
describe('monorepos', () => {
|
||||
let env !: NgtscTestEnvironment;
|
||||
let env!: NgtscTestEnvironment;
|
||||
|
||||
beforeEach(() => {
|
||||
env = NgtscTestEnvironment.setup(testFiles, absoluteFrom('/app'));
|
||||
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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});
|
||||
|
@ -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!);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 = {};
|
||||
|
@ -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 {
|
||||
|
@ -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`
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
}
|
@ -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;',
|
||||
|
@ -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
|
||||
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -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';
|
||||
|
@ -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(
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user