fix(compiler): walk third party modules (#12453)
fixes #11889 fixes #12428
This commit is contained in:
parent
bfc97ff2cd
commit
a838aba756
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'use-third-party',
|
||||
template: '<third-party-comp [thirdParty]="title"></third-party-comp>' +
|
||||
'<another-third-party-comp></another-third-party-comp>',
|
||||
})
|
||||
export class ComponentUsingThirdParty {
|
||||
title: string = 'from 3rd party';
|
||||
}
|
|
@ -12,6 +12,10 @@
|
|||
<source>Welcome</source>
|
||||
<target>tervetuloa</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
|
||||
<source>other-3rdP-component</source>
|
||||
<target>other-3rdP-component</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
|
@ -9,4 +9,5 @@
|
|||
<translationbundle>
|
||||
<translation id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4">käännä teksti</translation>
|
||||
<translation id="65cc4ab3b4c438e07c89be2b677d08369fb62da2">tervetuloa</translation>
|
||||
<translation id="63a85808f03b8181e36a952e0fa38202c2304862">other-3rdP-component</translation>
|
||||
</translationbundle>
|
||||
|
|
|
@ -11,9 +11,12 @@ import {FormsModule} from '@angular/forms';
|
|||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {MdButtonModule} from '@angular2-material/button';
|
||||
|
||||
import {ThirdpartyModule} from '../third_party_src/module';
|
||||
|
||||
import {MultipleComponentsMyComp, NextComp} from './a/multiple_components';
|
||||
import {AnimateCmp} from './animate';
|
||||
import {BasicComp} from './basic';
|
||||
import {ComponentUsingThirdParty} from './comp_using_3rdp';
|
||||
import {CompWithAnalyzeEntryComponentsProvider, CompWithEntryComponents} from './entry_components';
|
||||
import {CompConsumingEvents, CompUsingPipes, CompWithProviders, CompWithReferences, DirPublishingEvents, ModuleUsingCustomElements} from './features';
|
||||
import {CompUsingRootModuleDirectiveAndPipe, SomeDirectiveInRootModule, SomePipeInRootModule, SomeService, someLibModuleWithProviders} from './module_fixtures';
|
||||
|
@ -22,35 +25,47 @@ import {CompForChildQuery, CompWithChildQuery, CompWithDirectiveChild, Directive
|
|||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
SomeDirectiveInRootModule,
|
||||
SomePipeInRootModule,
|
||||
AnimateCmp,
|
||||
BasicComp,
|
||||
CompConsumingEvents,
|
||||
CompForChildQuery,
|
||||
CompWithEntryComponents,
|
||||
CompUsingPipes,
|
||||
CompUsingRootModuleDirectiveAndPipe,
|
||||
CompWithAnalyzeEntryComponentsProvider,
|
||||
ProjectingComp,
|
||||
CompWithChildQuery,
|
||||
CompWithDirectiveChild,
|
||||
CompWithEntryComponents,
|
||||
CompWithNgContent,
|
||||
CompUsingRootModuleDirectiveAndPipe,
|
||||
CompWithProviders,
|
||||
CompWithReferences,
|
||||
CompUsingPipes,
|
||||
CompConsumingEvents,
|
||||
DirectiveForQuery,
|
||||
DirPublishingEvents,
|
||||
MultipleComponentsMyComp,
|
||||
DirectiveForQuery,
|
||||
NextComp,
|
||||
ProjectingComp,
|
||||
SomeDirectiveInRootModule,
|
||||
SomePipeInRootModule,
|
||||
ComponentUsingThirdParty,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule, FormsModule, someLibModuleWithProviders(), ModuleUsingCustomElements,
|
||||
MdButtonModule
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
MdButtonModule,
|
||||
ModuleUsingCustomElements,
|
||||
someLibModuleWithProviders(),
|
||||
ThirdpartyModule,
|
||||
],
|
||||
providers: [SomeService],
|
||||
entryComponents: [
|
||||
AnimateCmp, BasicComp, CompWithEntryComponents, CompWithAnalyzeEntryComponentsProvider,
|
||||
ProjectingComp, CompWithChildQuery, CompUsingRootModuleDirectiveAndPipe, CompWithReferences
|
||||
AnimateCmp,
|
||||
BasicComp,
|
||||
CompUsingRootModuleDirectiveAndPipe,
|
||||
CompWithAnalyzeEntryComponentsProvider,
|
||||
CompWithChildQuery,
|
||||
CompWithEntryComponents,
|
||||
CompWithReferences,
|
||||
ProjectingComp,
|
||||
ComponentUsingThirdParty,
|
||||
]
|
||||
})
|
||||
export class MainModule {
|
||||
|
|
|
@ -43,13 +43,13 @@ describe('template codegen output', () => {
|
|||
});
|
||||
|
||||
it('should be able to create the basic component', () => {
|
||||
var compFixture = createComponent(BasicComp);
|
||||
const compFixture = createComponent(BasicComp);
|
||||
expect(compFixture.componentInstance).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support ngIf', () => {
|
||||
var compFixture = createComponent(BasicComp);
|
||||
var debugElement = compFixture.debugElement;
|
||||
const compFixture = createComponent(BasicComp);
|
||||
const debugElement = compFixture.debugElement;
|
||||
expect(debugElement.children.length).toBe(3);
|
||||
|
||||
compFixture.componentInstance.ctxBool = true;
|
||||
|
@ -59,8 +59,8 @@ describe('template codegen output', () => {
|
|||
});
|
||||
|
||||
it('should support ngFor', () => {
|
||||
var compFixture = createComponent(BasicComp);
|
||||
var debugElement = compFixture.debugElement;
|
||||
const compFixture = createComponent(BasicComp);
|
||||
const debugElement = compFixture.debugElement;
|
||||
expect(debugElement.children.length).toBe(3);
|
||||
|
||||
// test NgFor
|
||||
|
@ -83,11 +83,9 @@ describe('template codegen output', () => {
|
|||
});
|
||||
|
||||
it('should support i18n for content tags', () => {
|
||||
const compFixture = createComponent(BasicComp);
|
||||
const debugElement = compFixture.debugElement;
|
||||
const containerElement = <any>debugElement.nativeElement;
|
||||
const pElement = <any>containerElement.children.find((c: any) => c.name == 'p');
|
||||
const pText = <string>pElement.children.map((c: any) => c.data).join('').trim();
|
||||
const containerElement = createComponent(BasicComp).nativeElement;
|
||||
const pElement = containerElement.children.find((c: any) => c.name == 'p');
|
||||
const pText = pElement.children.map((c: any) => c.data).join('').trim();
|
||||
expect(pText).toBe('tervetuloa');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -34,6 +34,7 @@ const EXPECTED_XMB = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<!ELEMENT ex (#PCDATA)>
|
||||
]>
|
||||
<messagebundle>
|
||||
<msg id="63a85808f03b8181e36a952e0fa38202c2304862">other-3rdP-component</msg>
|
||||
<msg id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" desc="desc" meaning="meaning">translate me</msg>
|
||||
<msg id="65cc4ab3b4c438e07c89be2b677d08369fb62da2">Welcome</msg>
|
||||
</messagebundle>
|
||||
|
@ -43,6 +44,10 @@ const EXPECTED_XLIFF = `<?xml version="1.0" encoding="UTF-8" ?>
|
|||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file source-language="en" datatype="plaintext" original="ng2.template">
|
||||
<body>
|
||||
<trans-unit id="63a85808f03b8181e36a952e0fa38202c2304862" datatype="html">
|
||||
<source>other-3rdP-component</source>
|
||||
<target/>
|
||||
</trans-unit>
|
||||
<trans-unit id="76e1eccb1b772fa9f294ef9c146ea6d0efa8a2d4" datatype="html">
|
||||
<source>translate me</source>
|
||||
<target/>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
import './init';
|
||||
|
||||
import {ComponentUsingThirdParty} from '../src/comp_using_3rdp';
|
||||
import {MainModule} from '../src/module';
|
||||
import {CompUsingLibModuleDirectiveAndPipe, CompUsingRootModuleDirectiveAndPipe, SOME_TOKEN, ServiceUsingLibModule, SomeLibModule, SomeService} from '../src/module_fixtures';
|
||||
|
||||
|
@ -15,9 +16,9 @@ import {createComponent, createModule} from './util';
|
|||
describe('NgModule', () => {
|
||||
it('should support providers', () => {
|
||||
const moduleRef = createModule();
|
||||
expect(moduleRef.instance instanceof MainModule).toBe(true);
|
||||
expect(moduleRef.injector.get(MainModule) instanceof MainModule).toBe(true);
|
||||
expect(moduleRef.injector.get(SomeService) instanceof SomeService).toBe(true);
|
||||
expect(moduleRef.instance instanceof MainModule).toEqual(true);
|
||||
expect(moduleRef.injector.get(MainModule) instanceof MainModule).toEqual(true);
|
||||
expect(moduleRef.injector.get(SomeService) instanceof SomeService).toEqual(true);
|
||||
});
|
||||
|
||||
it('should support entryComponents components', () => {
|
||||
|
@ -26,7 +27,7 @@ describe('NgModule', () => {
|
|||
CompUsingRootModuleDirectiveAndPipe);
|
||||
expect(cf.componentType).toBe(CompUsingRootModuleDirectiveAndPipe);
|
||||
const compRef = cf.create(moduleRef.injector);
|
||||
expect(compRef.instance instanceof CompUsingRootModuleDirectiveAndPipe).toBe(true);
|
||||
expect(compRef.instance instanceof CompUsingRootModuleDirectiveAndPipe).toEqual(true);
|
||||
});
|
||||
|
||||
it('should support entryComponents via the ANALYZE_FOR_ENTRY_COMPONENTS provider and function providers in components',
|
||||
|
@ -42,12 +43,30 @@ describe('NgModule', () => {
|
|||
]);
|
||||
});
|
||||
|
||||
describe('third-party modules', () => {
|
||||
// https://github.com/angular/angular/issues/11889
|
||||
it('should support third party entryComponents components', () => {
|
||||
const fixture = createComponent(ComponentUsingThirdParty);
|
||||
const thirdPComps = fixture.nativeElement.children;
|
||||
expect(thirdPComps[0].children[0].children[0].data).toEqual('3rdP-component');
|
||||
expect(thirdPComps[1].children[0].children[0].data).toEqual('other-3rdP-component');
|
||||
});
|
||||
|
||||
// https://github.com/angular/angular/issues/12428
|
||||
it('should support third party directives', () => {
|
||||
const fixture = createComponent(ComponentUsingThirdParty);
|
||||
const debugElement = fixture.debugElement;
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.children[0].properties['title']).toEqual('from 3rd party');
|
||||
});
|
||||
});
|
||||
|
||||
it('should support module directives and pipes', () => {
|
||||
const compFixture = createComponent(CompUsingRootModuleDirectiveAndPipe);
|
||||
compFixture.detectChanges();
|
||||
|
||||
const debugElement = compFixture.debugElement;
|
||||
expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
|
||||
expect(debugElement.children[0].properties['title']).toEqual('transformed someValue');
|
||||
});
|
||||
|
||||
it('should support module directives and pipes on lib modules', () => {
|
||||
|
@ -55,10 +74,10 @@ describe('NgModule', () => {
|
|||
compFixture.detectChanges();
|
||||
|
||||
const debugElement = compFixture.debugElement;
|
||||
expect(debugElement.children[0].properties['title']).toBe('transformed someValue');
|
||||
expect(debugElement.children[0].properties['title']).toEqual('transformed someValue');
|
||||
|
||||
expect(debugElement.injector.get(SomeLibModule) instanceof SomeLibModule).toBe(true);
|
||||
expect(debugElement.injector.get(SomeLibModule) instanceof SomeLibModule).toEqual(true);
|
||||
expect(debugElement.injector.get(ServiceUsingLibModule) instanceof ServiceUsingLibModule)
|
||||
.toBe(true);
|
||||
.toEqual(true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
This folder emulates consuming precompiled modules and components.
|
||||
It is compiled separately from the other sources under `src`
|
||||
to only generate `*.js` / `*.d.ts` / `*.metadata.json` files,
|
||||
but no `*.ngfactory.ts` files.
|
||||
|
||||
** WARNING **
|
||||
Do not import components/directives from here directly as we want to test that ngc still compiles
|
||||
them when they are not imported.
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'third-party-comp',
|
||||
template: '<div>3rdP-component</div>',
|
||||
})
|
||||
export class ThirdPartyComponent {
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Directive, Input} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[thirdParty]',
|
||||
host: {'[title]': 'thirdParty'},
|
||||
})
|
||||
export class ThirdPartyDirective {
|
||||
@Input() thirdParty: string;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgModule} from '@angular/core';
|
||||
|
||||
import {ThirdPartyComponent} from './comp';
|
||||
import {ThirdPartyDirective} from './directive';
|
||||
import {AnotherThirdPartyModule} from './other_module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ThirdPartyComponent,
|
||||
ThirdPartyDirective,
|
||||
],
|
||||
exports: [
|
||||
AnotherThirdPartyModule,
|
||||
ThirdPartyComponent,
|
||||
ThirdPartyDirective,
|
||||
],
|
||||
imports: [AnotherThirdPartyModule]
|
||||
})
|
||||
export class ThirdpartyModule {
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'another-third-party-comp',
|
||||
template: '<div i18n>other-3rdP-component</div>',
|
||||
})
|
||||
export class AnotherThirdpartyComponent {
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {NgModule} from '@angular/core';
|
||||
import {AnotherThirdpartyComponent} from './other_comp';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AnotherThirdpartyComponent],
|
||||
exports: [AnotherThirdpartyComponent],
|
||||
})
|
||||
export class AnotherThirdPartyModule {
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": ".",
|
||||
"outDir": "../node_modules/third_party"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": "."
|
||||
},
|
||||
|
||||
"files": [
|
||||
"src/module",
|
||||
"src/bootstrap",
|
||||
"test/all_spec",
|
||||
"benchmarks/src/tree/ng2/index_aot.ts",
|
||||
"benchmarks/src/tree/ng2_switch/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
|
||||
]
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"angularCompilerOptions": {
|
||||
// For TypeScript 1.8, we have to lay out generated files
|
||||
// in the same source directory with your code.
|
||||
"genDir": ".",
|
||||
"debug": true
|
||||
},
|
||||
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "",
|
||||
"declaration": true,
|
||||
"lib": ["es6", "dom"],
|
||||
"baseUrl": "."
|
||||
},
|
||||
|
||||
"files": [
|
||||
"src/module",
|
||||
"src/bootstrap",
|
||||
"test/all_spec",
|
||||
"benchmarks/src/tree/ng2/index_aot.ts",
|
||||
"benchmarks/src/tree/ng2_switch/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2/index_aot.ts",
|
||||
"benchmarks/src/largetable/ng2_switch/index_aot.ts"
|
||||
]
|
||||
}
|
|
@ -40,50 +40,47 @@ export class CodeGeneratorModuleCollector {
|
|||
private staticReflector: StaticReflector, private reflectorHost: StaticReflectorHost,
|
||||
private program: ts.Program, private options: AngularCompilerOptions) {}
|
||||
|
||||
getModuleSymbols(program: ts.Program): {fileMetas: FileMetadata[], ngModules: StaticSymbol[]} {
|
||||
getModuleSymbols(): StaticSymbol[] {
|
||||
// Compare with false since the default should be true
|
||||
const skipFileNames = (this.options.generateCodeForLibraries === false) ?
|
||||
GENERATED_OR_DTS_FILES :
|
||||
GENERATED_FILES;
|
||||
let filePaths = this.program.getSourceFiles()
|
||||
.filter(sf => !skipFileNames.test(sf.fileName))
|
||||
.map(sf => this.reflectorHost.getCanonicalFileName(sf.fileName));
|
||||
const fileMetas = filePaths.map((filePath) => this.readFileMetadata(filePath));
|
||||
const ngModules = fileMetas.reduce((ngModules, fileMeta) => {
|
||||
ngModules.push(...fileMeta.ngModules);
|
||||
return ngModules;
|
||||
}, <StaticSymbol[]>[]);
|
||||
return {fileMetas, ngModules};
|
||||
}
|
||||
const skipFileNames =
|
||||
this.options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
|
||||
|
||||
private readFileMetadata(absSourcePath: string): FileMetadata {
|
||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
|
||||
const result: FileMetadata = {directives: [], ngModules: [], fileUrl: absSourcePath};
|
||||
if (!moduleMetadata) {
|
||||
console.log(`WARNING: no metadata found for ${absSourcePath}`);
|
||||
return result;
|
||||
}
|
||||
const metadata = moduleMetadata['metadata'];
|
||||
const symbols = metadata && Object.keys(metadata);
|
||||
if (!symbols || !symbols.length) {
|
||||
return result;
|
||||
}
|
||||
for (const symbol of symbols) {
|
||||
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
||||
// Ignore symbols that are only included to record error information.
|
||||
continue;
|
||||
}
|
||||
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
|
||||
const annotations = this.staticReflector.annotations(staticType);
|
||||
annotations.forEach((annotation) => {
|
||||
if (annotation instanceof NgModule) {
|
||||
result.ngModules.push(staticType);
|
||||
} else if (annotation instanceof Directive) {
|
||||
result.directives.push(staticType);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
const ngModules: StaticSymbol[] = [];
|
||||
|
||||
this.program.getSourceFiles()
|
||||
.filter(sourceFile => !skipFileNames.test(sourceFile.fileName))
|
||||
.forEach(sourceFile => {
|
||||
const absSrcPath = this.reflectorHost.getCanonicalFileName(sourceFile.fileName);
|
||||
|
||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSrcPath);
|
||||
if (!moduleMetadata) {
|
||||
console.log(`WARNING: no metadata found for ${absSrcPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const metadata = moduleMetadata['metadata'];
|
||||
|
||||
if (!metadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const symbol of Object.keys(metadata)) {
|
||||
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
||||
// Ignore symbols that are only included to record error information.
|
||||
continue;
|
||||
}
|
||||
const staticType = this.reflectorHost.findDeclaration(absSrcPath, symbol, absSrcPath);
|
||||
const annotations = this.staticReflector.annotations(staticType);
|
||||
annotations.some((annotation) => {
|
||||
if (annotation instanceof NgModule) {
|
||||
ngModules.push(staticType);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return ngModules;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +98,7 @@ export class CodeGenerator {
|
|||
// Write codegen in a directory structure matching the sources.
|
||||
private calculateEmitPath(filePath: string): string {
|
||||
let root = this.options.basePath;
|
||||
for (let eachRootDir of this.options.rootDirs || []) {
|
||||
for (const eachRootDir of this.options.rootDirs || []) {
|
||||
if (this.options.trace) {
|
||||
console.log(`Check if ${filePath} is under rootDirs element ${eachRootDir}`);
|
||||
}
|
||||
|
@ -111,31 +108,27 @@ export class CodeGenerator {
|
|||
}
|
||||
|
||||
// transplant the codegen path to be inside the `genDir`
|
||||
var relativePath: string = path.relative(root, filePath);
|
||||
let relativePath: string = path.relative(root, filePath);
|
||||
while (relativePath.startsWith('..' + path.sep)) {
|
||||
// Strip out any `..` path such as: `../node_modules/@foo` as we want to put everything
|
||||
// into `genDir`.
|
||||
relativePath = relativePath.substr(3);
|
||||
}
|
||||
|
||||
return path.join(this.options.genDir, relativePath);
|
||||
}
|
||||
|
||||
codegen(): Promise<any> {
|
||||
const {fileMetas, ngModules} = this.moduleCollector.getModuleSymbols(this.program);
|
||||
const analyzedNgModules = this.compiler.analyzeModules(ngModules);
|
||||
return Promise.all(fileMetas.map(
|
||||
(fileMeta) =>
|
||||
this.compiler
|
||||
.compile(
|
||||
fileMeta.fileUrl, analyzedNgModules, fileMeta.directives, fileMeta.ngModules)
|
||||
.then((generatedModules) => {
|
||||
generatedModules.forEach((generatedModule) => {
|
||||
const sourceFile = this.program.getSourceFile(fileMeta.fileUrl);
|
||||
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
|
||||
this.host.writeFile(
|
||||
emitPath, PREAMBLE + generatedModule.source, false, () => {}, [sourceFile]);
|
||||
});
|
||||
})));
|
||||
const ngModules = this.moduleCollector.getModuleSymbols();
|
||||
|
||||
return this.compiler.compileModules(ngModules).then(generatedModules => {
|
||||
generatedModules.forEach(generatedModule => {
|
||||
const sourceFile = this.program.getSourceFile(generatedModule.fileUrl);
|
||||
const emitPath = this.calculateEmitPath(generatedModule.moduleUrl);
|
||||
this.host.writeFile(
|
||||
emitPath, PREAMBLE + generatedModule.source, false, () => {}, [sourceFile]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static create(
|
||||
|
@ -201,9 +194,3 @@ export class CodeGenerator {
|
|||
options, program, compilerHost, staticReflector, offlineCompiler, reflectorHost);
|
||||
}
|
||||
}
|
||||
|
||||
export interface FileMetadata {
|
||||
fileUrl: string;
|
||||
directives: StaticSymbol[];
|
||||
ngModules: StaticSymbol[];
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
|
||||
/**
|
||||
* Extract i18n messages from source code
|
||||
*
|
||||
* TODO(vicb): factorize code with the CodeGenerator
|
||||
*/
|
||||
// Must be imported first, because angular2 decorators throws on load.
|
||||
import 'reflect-metadata';
|
||||
|
|
|
@ -18,16 +18,13 @@ import 'reflect-metadata';
|
|||
import * as compiler from '@angular/compiler';
|
||||
import {Component, NgModule, ViewEncapsulation} from '@angular/core';
|
||||
import * as tsc from '@angular/tsc-wrapped';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Console} from './private_import_core';
|
||||
import {ReflectorHost, ReflectorHostContext} from './reflector_host';
|
||||
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
|
||||
import {StaticReflector, StaticSymbol} from './static_reflector';
|
||||
|
||||
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
|
||||
const GENERATED_OR_DTS_FILES = /\.d\.ts$|\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
|
||||
|
||||
export class Extractor {
|
||||
constructor(
|
||||
|
@ -37,82 +34,82 @@ export class Extractor {
|
|||
private metadataResolver: compiler.CompileMetadataResolver,
|
||||
private directiveNormalizer: compiler.DirectiveNormalizer) {}
|
||||
|
||||
private readFileMetadata(absSourcePath: string): FileMetadata {
|
||||
private readModuleSymbols(absSourcePath: string): StaticSymbol[] {
|
||||
const moduleMetadata = this.staticReflector.getModuleMetadata(absSourcePath);
|
||||
const result: FileMetadata = {components: [], ngModules: [], fileUrl: absSourcePath};
|
||||
const modSymbols: StaticSymbol[] = [];
|
||||
if (!moduleMetadata) {
|
||||
console.log(`WARNING: no metadata found for ${absSourcePath}`);
|
||||
return result;
|
||||
return modSymbols;
|
||||
}
|
||||
|
||||
const metadata = moduleMetadata['metadata'];
|
||||
const symbols = metadata && Object.keys(metadata);
|
||||
if (!symbols || !symbols.length) {
|
||||
return result;
|
||||
return modSymbols;
|
||||
}
|
||||
|
||||
for (const symbol of symbols) {
|
||||
if (metadata[symbol] && metadata[symbol].__symbolic == 'error') {
|
||||
// Ignore symbols that are only included to record error information.
|
||||
continue;
|
||||
}
|
||||
|
||||
const staticType = this.reflectorHost.findDeclaration(absSourcePath, symbol, absSourcePath);
|
||||
const annotations = this.staticReflector.annotations(staticType);
|
||||
annotations.forEach((annotation) => {
|
||||
if (annotation instanceof NgModule) {
|
||||
result.ngModules.push(staticType);
|
||||
} else if (annotation instanceof Component) {
|
||||
result.components.push(staticType);
|
||||
|
||||
annotations.some(a => {
|
||||
if (a instanceof NgModule) {
|
||||
modSymbols.push(staticType);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
return modSymbols;
|
||||
}
|
||||
|
||||
extract(): Promise<compiler.MessageBundle> {
|
||||
const skipFileNames = (this.options.generateCodeForLibraries === false) ?
|
||||
GENERATED_OR_DTS_FILES :
|
||||
GENERATED_FILES;
|
||||
const filePaths =
|
||||
this.program.getSourceFiles().map(sf => sf.fileName).filter(f => !skipFileNames.test(f));
|
||||
const fileMetas = filePaths.map((filePath) => this.readFileMetadata(filePath));
|
||||
const ngModules = fileMetas.reduce((ngModules, fileMeta) => {
|
||||
ngModules.push(...fileMeta.ngModules);
|
||||
return ngModules;
|
||||
}, <StaticSymbol[]>[]);
|
||||
const analyzedNgModules = compiler.analyzeModules(ngModules, this.metadataResolver);
|
||||
const errors: compiler.ParseError[] = [];
|
||||
this.program.getSourceFiles().map(sf => sf.fileName).filter(f => !GENERATED_FILES.test(f));
|
||||
const ngModules: StaticSymbol[] = [];
|
||||
|
||||
filePaths.forEach((filePath) => ngModules.push(...this.readModuleSymbols(filePath)));
|
||||
|
||||
const files = compiler.analyzeNgModules(ngModules, this.metadataResolver).files;
|
||||
const errors: compiler.ParseError[] = [];
|
||||
const filePromises: Promise<any>[] = [];
|
||||
|
||||
files.forEach(file => {
|
||||
const cmpPromises: Promise<compiler.CompileDirectiveMetadata>[] = [];
|
||||
file.directives.forEach(directiveType => {
|
||||
const dirMeta = this.metadataResolver.getDirectiveMetadata(directiveType);
|
||||
if (dirMeta.isComponent) {
|
||||
cmpPromises.push(this.directiveNormalizer.normalizeDirective(dirMeta).asyncResult);
|
||||
}
|
||||
});
|
||||
|
||||
if (cmpPromises.length) {
|
||||
const done =
|
||||
Promise.all(cmpPromises).then((compMetas: compiler.CompileDirectiveMetadata[]) => {
|
||||
compMetas.forEach(compMeta => {
|
||||
const html = compMeta.template.template;
|
||||
const interpolationConfig =
|
||||
compiler.InterpolationConfig.fromArray(compMeta.template.interpolation);
|
||||
errors.push(...this.messageBundle.updateFromTemplate(
|
||||
html, file.srcUrl, interpolationConfig));
|
||||
});
|
||||
});
|
||||
|
||||
filePromises.push(done);
|
||||
}
|
||||
});
|
||||
|
||||
let bundlePromise =
|
||||
Promise
|
||||
.all(fileMetas.map((fileMeta) => {
|
||||
const url = fileMeta.fileUrl;
|
||||
return Promise.all(fileMeta.components.map(compType => {
|
||||
const compMeta = this.metadataResolver.getDirectiveMetadata(<any>compType);
|
||||
const ngModule = analyzedNgModules.ngModuleByDirective.get(compType);
|
||||
if (!ngModule) {
|
||||
throw new Error(
|
||||
`Cannot determine the module for component ${compMeta.type.name}!`);
|
||||
}
|
||||
return Promise
|
||||
.all([compMeta, ...ngModule.transitiveModule.directives].map(
|
||||
dirMeta =>
|
||||
this.directiveNormalizer.normalizeDirective(dirMeta).asyncResult))
|
||||
.then((normalizedCompWithDirectives) => {
|
||||
const compMeta = normalizedCompWithDirectives[0];
|
||||
const html = compMeta.template.template;
|
||||
const interpolationConfig =
|
||||
compiler.InterpolationConfig.fromArray(compMeta.template.interpolation);
|
||||
errors.push(
|
||||
...this.messageBundle.updateFromTemplate(html, url, interpolationConfig));
|
||||
});
|
||||
}));
|
||||
}))
|
||||
.then(_ => this.messageBundle);
|
||||
|
||||
if (errors.length) {
|
||||
throw new Error(errors.map(e => e.toString()).join('\n'));
|
||||
}
|
||||
|
||||
return bundlePromise;
|
||||
return Promise.all(filePromises).then(_ => this.messageBundle);
|
||||
}
|
||||
|
||||
static create(
|
||||
|
@ -149,9 +146,3 @@ export class Extractor {
|
|||
normalizer);
|
||||
}
|
||||
}
|
||||
|
||||
interface FileMetadata {
|
||||
fileUrl: string;
|
||||
components: StaticSymbol[];
|
||||
ngModules: StaticSymbol[];
|
||||
}
|
||||
|
|
|
@ -250,6 +250,12 @@ export class ReflectorHost implements StaticReflectorHost, ImportGenerator {
|
|||
} else {
|
||||
const sf = this.program.getSourceFile(filePath);
|
||||
if (!sf) {
|
||||
if (this.context.fileExists(filePath)) {
|
||||
const sourceText = this.context.readFile(filePath);
|
||||
return this.metadataCollector.getMetadata(
|
||||
ts.createSourceFile(filePath, sourceText, ts.ScriptTarget.Latest, true));
|
||||
}
|
||||
|
||||
throw new Error(`Source file ${filePath} not present in program.`);
|
||||
}
|
||||
return this.metadataCollector.getMetadata(sf);
|
||||
|
|
|
@ -508,7 +508,7 @@ export class CompilePipeMetadata implements CompileMetadataWithIdentifier {
|
|||
}
|
||||
|
||||
/**
|
||||
* Metadata regarding compilation of a directive.
|
||||
* Metadata regarding compilation of a module.
|
||||
*/
|
||||
export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
|
||||
type: CompileTypeMetadata;
|
||||
|
@ -568,6 +568,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier {
|
|||
export class TransitiveCompileNgModuleMetadata {
|
||||
directivesSet = new Set<Type<any>>();
|
||||
pipesSet = new Set<Type<any>>();
|
||||
|
||||
constructor(
|
||||
public modules: CompileNgModuleMetadata[], public providers: CompileProviderMetadata[],
|
||||
public entryComponents: CompileTypeMetadata[], public directives: CompileDirectiveMetadata[],
|
||||
|
@ -580,11 +581,13 @@ export class TransitiveCompileNgModuleMetadata {
|
|||
export function removeIdentifierDuplicates<T extends CompileMetadataWithIdentifier>(items: T[]):
|
||||
T[] {
|
||||
const map = new Map<any, T>();
|
||||
|
||||
items.forEach((item) => {
|
||||
if (!map.get(item.identifier.reference)) {
|
||||
map.set(item.identifier.reference, item);
|
||||
}
|
||||
});
|
||||
|
||||
return MapWrapper.values(map);
|
||||
}
|
||||
|
||||
|
|
|
@ -378,15 +378,15 @@ export class CompileMetadataResolver {
|
|||
}
|
||||
|
||||
private _getTypeDescriptor(type: Type<any>): string {
|
||||
if (this._directiveResolver.resolve(type, false) !== null) {
|
||||
if (this._directiveResolver.resolve(type, false)) {
|
||||
return 'directive';
|
||||
}
|
||||
|
||||
if (this._pipeResolver.resolve(type, false) !== null) {
|
||||
if (this._pipeResolver.resolve(type, false)) {
|
||||
return 'pipe';
|
||||
}
|
||||
|
||||
if (this._ngModuleResolver.resolve(type, false) !== null) {
|
||||
if (this._ngModuleResolver.resolve(type, false)) {
|
||||
return 'module';
|
||||
}
|
||||
|
||||
|
@ -508,7 +508,7 @@ export class CompileMetadataResolver {
|
|||
let isOptional = false;
|
||||
let query: Query = null;
|
||||
let viewQuery: Query = null;
|
||||
var token: any = null;
|
||||
let token: any = null;
|
||||
if (Array.isArray(param)) {
|
||||
param.forEach((paramEntry) => {
|
||||
if (paramEntry instanceof Host) {
|
||||
|
@ -605,19 +605,20 @@ export class CompileMetadataResolver {
|
|||
} else if (isValidType(provider)) {
|
||||
compileProvider = this.getTypeMetadata(provider, staticTypeModuleUrl(provider));
|
||||
} else {
|
||||
let providersInfo = (<string[]>providers.reduce(
|
||||
(soFar: string[], seenProvider: any, seenProviderIdx: number) => {
|
||||
if (seenProviderIdx < providerIdx) {
|
||||
soFar.push(`${stringify(seenProvider)}`);
|
||||
} else if (seenProviderIdx == providerIdx) {
|
||||
soFar.push(`?${stringify(seenProvider)}?`);
|
||||
} else if (seenProviderIdx == providerIdx + 1) {
|
||||
soFar.push('...');
|
||||
}
|
||||
return soFar;
|
||||
},
|
||||
[]))
|
||||
.join(', ');
|
||||
const providersInfo =
|
||||
(<string[]>providers.reduce(
|
||||
(soFar: string[], seenProvider: any, seenProviderIdx: number) => {
|
||||
if (seenProviderIdx < providerIdx) {
|
||||
soFar.push(`${stringify(seenProvider)}`);
|
||||
} else if (seenProviderIdx == providerIdx) {
|
||||
soFar.push(`?${stringify(seenProvider)}?`);
|
||||
} else if (seenProviderIdx == providerIdx + 1) {
|
||||
soFar.push('...');
|
||||
}
|
||||
return soFar;
|
||||
},
|
||||
[]))
|
||||
.join(', ');
|
||||
|
||||
throw new Error(
|
||||
`Invalid ${debugInfo ? debugInfo : 'provider'} - only instances of Provider and Type are allowed, got: [${providersInfo}]`);
|
||||
|
|
|
@ -13,6 +13,7 @@ import {AnimationParser} from './animation/animation_parser';
|
|||
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompileNgModuleMetadata, CompilePipeMetadata, CompileProviderMetadata, StaticSymbol, createHostComponentMeta} from './compile_metadata';
|
||||
import {DirectiveNormalizer} from './directive_normalizer';
|
||||
import {DirectiveWrapperCompileResult, DirectiveWrapperCompiler} from './directive_wrapper_compiler';
|
||||
import {ListWrapper, MapWrapper} from './facade/collection';
|
||||
import {Identifiers, resolveIdentifier, resolveIdentifierToken} from './identifiers';
|
||||
import {CompileMetadataResolver} from './metadata_resolver';
|
||||
import {NgModuleCompiler} from './ng_module_compiler';
|
||||
|
@ -23,28 +24,63 @@ import {TemplateParser} from './template_parser/template_parser';
|
|||
import {ComponentFactoryDependency, DirectiveWrapperDependency, ViewCompileResult, ViewCompiler, ViewFactoryDependency} from './view_compiler/view_compiler';
|
||||
|
||||
export class SourceModule {
|
||||
constructor(public moduleUrl: string, public source: string) {}
|
||||
constructor(public fileUrl: string, public moduleUrl: string, public source: string) {}
|
||||
}
|
||||
|
||||
export class NgModulesSummary {
|
||||
constructor(
|
||||
public ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||
public ngModules: CompileNgModuleMetadata[]) {}
|
||||
}
|
||||
// Returns all the source files and a mapping from modules to directives
|
||||
export function analyzeNgModules(
|
||||
ngModules: StaticSymbol[], metadataResolver: CompileMetadataResolver): {
|
||||
ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||
files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}>
|
||||
} {
|
||||
const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>();
|
||||
|
||||
export function analyzeModules(
|
||||
ngModules: StaticSymbol[], metadataResolver: CompileMetadataResolver) {
|
||||
// For every input modules add the list of transitively included modules
|
||||
ngModules.forEach(ngModule => {
|
||||
const modMeta = metadataResolver.getNgModuleMetadata(ngModule);
|
||||
modMeta.transitiveModule.modules.forEach(
|
||||
modMeta => { moduleMetasByRef.set(modMeta.type.reference, modMeta); });
|
||||
});
|
||||
|
||||
const ngModuleMetas = MapWrapper.values(moduleMetasByRef);
|
||||
const ngModuleByDirective = new Map<StaticSymbol, CompileNgModuleMetadata>();
|
||||
const modules: CompileNgModuleMetadata[] = [];
|
||||
const ngModulesByFile = new Map<string, StaticSymbol[]>();
|
||||
const ngDirectivesByFile = new Map<string, StaticSymbol[]>();
|
||||
const srcFileUrls = new Set<string>();
|
||||
|
||||
// Looping over all modules to construct:
|
||||
// - a map from files to modules `ngModulesByFile`,
|
||||
// - a map from files to directives `ngDirectivesByFile`,
|
||||
// - a map from modules to directives `ngModuleByDirective`.
|
||||
ngModuleMetas.forEach((ngModuleMeta) => {
|
||||
const srcFileUrl = ngModuleMeta.type.reference.filePath;
|
||||
srcFileUrls.add(srcFileUrl);
|
||||
ngModulesByFile.set(
|
||||
srcFileUrl, (ngModulesByFile.get(srcFileUrl) || []).concat(ngModuleMeta.type.reference));
|
||||
|
||||
ngModules.forEach((ngModule) => {
|
||||
const ngModuleMeta = metadataResolver.getNgModuleMetadata(<any>ngModule);
|
||||
modules.push(ngModuleMeta);
|
||||
ngModuleMeta.declaredDirectives.forEach((dirMeta: CompileDirectiveMetadata) => {
|
||||
const fileUrl = dirMeta.type.reference.filePath;
|
||||
srcFileUrls.add(fileUrl);
|
||||
ngDirectivesByFile.set(
|
||||
fileUrl, (ngDirectivesByFile.get(fileUrl) || []).concat(dirMeta.type.reference));
|
||||
ngModuleByDirective.set(dirMeta.type.reference, ngModuleMeta);
|
||||
});
|
||||
});
|
||||
return new NgModulesSummary(ngModuleByDirective, modules);
|
||||
|
||||
const files: {srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}[] = [];
|
||||
|
||||
srcFileUrls.forEach((srcUrl) => {
|
||||
const directives = ngDirectivesByFile.get(srcUrl) || [];
|
||||
const ngModules = ngModulesByFile.get(srcUrl) || [];
|
||||
files.push({srcUrl, directives, ngModules});
|
||||
});
|
||||
|
||||
return {
|
||||
// map from modules to declared directives
|
||||
ngModuleByDirective,
|
||||
// list of modules and directives for every source file
|
||||
files,
|
||||
};
|
||||
}
|
||||
|
||||
export class OfflineCompiler {
|
||||
|
@ -59,19 +95,26 @@ export class OfflineCompiler {
|
|||
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
|
||||
private _localeId: string, private _translationFormat: string) {}
|
||||
|
||||
analyzeModules(ngModules: StaticSymbol[]): NgModulesSummary {
|
||||
return analyzeModules(ngModules, this._metadataResolver);
|
||||
}
|
||||
|
||||
clearCache() {
|
||||
this._directiveNormalizer.clearCache();
|
||||
this._metadataResolver.clearCache();
|
||||
}
|
||||
|
||||
compile(
|
||||
moduleUrl: string, ngModulesSummary: NgModulesSummary, directives: StaticSymbol[],
|
||||
ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
const fileSuffix = _splitTypescriptSuffix(moduleUrl)[1];
|
||||
compileModules(ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
const {ngModuleByDirective, files} = analyzeNgModules(ngModules, this._metadataResolver);
|
||||
|
||||
const sourceModules = files.map(
|
||||
file => this._compileSrcFile(
|
||||
file.srcUrl, ngModuleByDirective, file.directives, file.ngModules));
|
||||
|
||||
return Promise.all(sourceModules)
|
||||
.then((modules: SourceModule[][]) => ListWrapper.flatten(modules));
|
||||
}
|
||||
|
||||
private _compileSrcFile(
|
||||
srcFileUrl: string, ngModuleByDirective: Map<StaticSymbol, CompileNgModuleMetadata>,
|
||||
directives: StaticSymbol[], ngModules: StaticSymbol[]): Promise<SourceModule[]> {
|
||||
const fileSuffix = _splitTypescriptSuffix(srcFileUrl)[1];
|
||||
const statements: o.Statement[] = [];
|
||||
const exportedVars: string[] = [];
|
||||
const outputSourceModules: SourceModule[] = [];
|
||||
|
@ -91,7 +134,7 @@ export class OfflineCompiler {
|
|||
if (!compMeta.isComponent) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
const ngModule = ngModulesSummary.ngModuleByDirective.get(dirType);
|
||||
const ngModule = ngModuleByDirective.get(dirType);
|
||||
if (!ngModule) {
|
||||
throw new Error(`Cannot determine the module for component ${compMeta.type.name}!`);
|
||||
}
|
||||
|
@ -106,7 +149,8 @@ export class OfflineCompiler {
|
|||
// compile styles
|
||||
const stylesCompileResults = this._styleCompiler.compileComponent(compMeta);
|
||||
stylesCompileResults.externalStylesheets.forEach((compiledStyleSheet) => {
|
||||
outputSourceModules.push(this._codgenStyles(compiledStyleSheet, fileSuffix));
|
||||
outputSourceModules.push(
|
||||
this._codgenStyles(srcFileUrl, compiledStyleSheet, fileSuffix));
|
||||
});
|
||||
|
||||
// compile components
|
||||
|
@ -119,8 +163,9 @@ export class OfflineCompiler {
|
|||
}))
|
||||
.then(() => {
|
||||
if (statements.length > 0) {
|
||||
outputSourceModules.unshift(this._codegenSourceModule(
|
||||
_ngfactoryModuleUrl(moduleUrl), statements, exportedVars));
|
||||
const srcModule = this._codegenSourceModule(
|
||||
srcFileUrl, _ngfactoryModuleUrl(srcFileUrl), statements, exportedVars);
|
||||
outputSourceModules.unshift(srcModule);
|
||||
}
|
||||
return outputSourceModules;
|
||||
});
|
||||
|
@ -209,18 +254,21 @@ export class OfflineCompiler {
|
|||
return viewResult.viewFactoryVar;
|
||||
}
|
||||
|
||||
private _codgenStyles(stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
|
||||
private _codgenStyles(
|
||||
fileUrl: string, stylesCompileResult: CompiledStylesheet, fileSuffix: string): SourceModule {
|
||||
_resolveStyleStatements(stylesCompileResult, fileSuffix);
|
||||
return this._codegenSourceModule(
|
||||
_stylesModuleUrl(
|
||||
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
|
||||
fileUrl, _stylesModuleUrl(
|
||||
stylesCompileResult.meta.moduleUrl, stylesCompileResult.isShimmed, fileSuffix),
|
||||
stylesCompileResult.statements, [stylesCompileResult.stylesVar]);
|
||||
}
|
||||
|
||||
private _codegenSourceModule(
|
||||
moduleUrl: string, statements: o.Statement[], exportedVars: string[]): SourceModule {
|
||||
fileUrl: string, moduleUrl: string, statements: o.Statement[],
|
||||
exportedVars: string[]): SourceModule {
|
||||
return new SourceModule(
|
||||
moduleUrl, this._outputEmitter.emitStatements(moduleUrl, statements, exportedVars));
|
||||
fileUrl, moduleUrl,
|
||||
this._outputEmitter.emitStatements(moduleUrl, statements, exportedVars));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ LINKABLE_PKGS=(
|
|||
PKGS=(
|
||||
reflect-metadata@0.1.8
|
||||
typescript@2.0.2
|
||||
zone.js@0.6.21
|
||||
rxjs@5.0.0-beta.11
|
||||
zone.js@0.6.25
|
||||
rxjs@5.0.0-beta.12
|
||||
@types/{node@6.0.38,jasmine@2.2.33}
|
||||
jasmine@2.4.1
|
||||
webpack@2.1.0-beta.21
|
||||
|
@ -35,12 +35,20 @@ cp -v package.json $TMP
|
|||
npm install ${LINKABLE_PKGS[*]}
|
||||
|
||||
./node_modules/.bin/tsc --version
|
||||
# Compile the compiler-cli third_party simulation.
|
||||
# Use ngc-wrapped directly so we don't produce *.ngfactory.ts files!
|
||||
|
||||
# Compile the compiler-cli integration tests
|
||||
# TODO(vicb): restore the test for .xtb
|
||||
#./node_modules/.bin/ngc --i18nFile=src/messages.fi.xtb --locale=fi --i18nFormat=xtb
|
||||
./node_modules/.bin/ngc --i18nFile=src/messages.fi.xlf --locale=fi --i18nFormat=xlf
|
||||
./node_modules/.bin/ng-xi18n --i18nFormat=xlf
|
||||
./node_modules/.bin/ng-xi18n --i18nFormat=xmb
|
||||
#./node_modules/.bin/ngc -p tsconfig-build.json --i18nFile=src/messages.fi.xtb --locale=fi --i18nFormat=xtb
|
||||
|
||||
# Generate the metadata for the third-party modules
|
||||
node ./node_modules/@angular/tsc-wrapped/src/main -p third_party_src/tsconfig-build.json
|
||||
|
||||
./node_modules/.bin/ngc -p tsconfig-build.json --i18nFile=src/messages.fi.xlf --locale=fi --i18nFormat=xlf
|
||||
|
||||
./node_modules/.bin/ng-xi18n -p tsconfig-build.json --i18nFormat=xlf
|
||||
./node_modules/.bin/ng-xi18n -p tsconfig-build.json --i18nFormat=xmb
|
||||
|
||||
./node_modules/.bin/jasmine init
|
||||
# Run compiler-cli integration tests in node
|
||||
|
@ -48,6 +56,6 @@ cp -v package.json $TMP
|
|||
./node_modules/.bin/jasmine ./all_spec.js
|
||||
|
||||
# Compile again with a differently named tsconfig file
|
||||
mv tsconfig.json othername.json
|
||||
mv tsconfig-build.json othername.json
|
||||
./node_modules/.bin/ngc -p othername.json
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue