refactor(compiler): allows synchronous retrieving of metadata (#12908)
Allows non-normalized metadata to be retrieved synchronously. Related to #7482
This commit is contained in:
		
							parent
							
								
									8b2dfb2eca
								
							
						
					
					
						commit
						481c9b3258
					
				| @ -34,9 +34,9 @@ export class Extractor { | |||||||
|     const programSymbols: StaticSymbol[] = |     const programSymbols: StaticSymbol[] = | ||||||
|         extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options); |         extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options); | ||||||
| 
 | 
 | ||||||
|     return compiler |     const {ngModules, files} = compiler.analyzeAndValidateNgModules( | ||||||
|         .analyzeNgModules(programSymbols, {transitiveModules: true}, this.metadataResolver) |         programSymbols, {transitiveModules: true}, this.metadataResolver); | ||||||
|         .then(({files}) => { |     return compiler.loadNgModuleDirectives(ngModules).then(() => { | ||||||
|       const errors: compiler.ParseError[] = []; |       const errors: compiler.ParseError[] = []; | ||||||
| 
 | 
 | ||||||
|       files.forEach(file => { |       files.forEach(file => { | ||||||
|  | |||||||
| @ -589,7 +589,7 @@ export interface CompileNgModuleDirectiveSummary extends CompileSummary { | |||||||
|   exportedDirectives: CompileIdentifierMetadata[]; |   exportedDirectives: CompileIdentifierMetadata[]; | ||||||
|   exportedPipes: CompileIdentifierMetadata[]; |   exportedPipes: CompileIdentifierMetadata[]; | ||||||
|   exportedModules: CompileNgModuleDirectiveSummary[]; |   exportedModules: CompileNgModuleDirectiveSummary[]; | ||||||
|   loadingPromises: Promise<any>[]; |   directiveLoaders: (() => Promise<void>)[]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export type CompileNgModuleSummary = | export type CompileNgModuleSummary = | ||||||
| @ -661,7 +661,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { | |||||||
|       exportedModules: this.exportedModules, |       exportedModules: this.exportedModules, | ||||||
|       exportedDirectives: this.exportedDirectives, |       exportedDirectives: this.exportedDirectives, | ||||||
|       exportedPipes: this.exportedPipes, |       exportedPipes: this.exportedPipes, | ||||||
|       loadingPromises: this.transitiveModule.loadingPromises |       directiveLoaders: this.transitiveModule.directiveLoaders | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -682,7 +682,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { | |||||||
|       exportedDirectives: this.exportedDirectives, |       exportedDirectives: this.exportedDirectives, | ||||||
|       exportedPipes: this.exportedPipes, |       exportedPipes: this.exportedPipes, | ||||||
|       exportedModules: this.exportedModules, |       exportedModules: this.exportedModules, | ||||||
|       loadingPromises: this.transitiveModule.loadingPromises |       directiveLoaders: this.transitiveModule.directiveLoaders | ||||||
|     }; |     }; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @ -695,7 +695,7 @@ export class TransitiveCompileNgModuleMetadata { | |||||||
|       public modules: CompileNgModuleInjectorSummary[], public providers: CompileProviderMetadata[], |       public modules: CompileNgModuleInjectorSummary[], public providers: CompileProviderMetadata[], | ||||||
|       public entryComponents: CompileIdentifierMetadata[], |       public entryComponents: CompileIdentifierMetadata[], | ||||||
|       public directives: CompileIdentifierMetadata[], public pipes: CompileIdentifierMetadata[], |       public directives: CompileIdentifierMetadata[], public pipes: CompileIdentifierMetadata[], | ||||||
|       public loadingPromises: Promise<any>[]) { |       public directiveLoaders: (() => Promise<void>)[]) { | ||||||
|     directives.forEach(dir => this.directivesSet.add(dir.reference)); |     directives.forEach(dir => this.directivesSet.add(dir.reference)); | ||||||
|     pipes.forEach(pipe => this.pipesSet.add(pipe.reference)); |     pipes.forEach(pipe => this.pipesSet.add(pipe.reference)); | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -145,14 +145,92 @@ export class CompileMetadataResolver { | |||||||
|     if (this._directiveCache.has(directiveType)) { |     if (this._directiveCache.has(directiveType)) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |     directiveType = resolveForwardRef(directiveType); | ||||||
|  |     const nonNormalizedMetadata = this.getNonNormalizedDirectiveMetadata(directiveType); | ||||||
|  | 
 | ||||||
|  |     const createDirectiveMetadata = (templateMetadata: cpl.CompileTemplateMetadata) => { | ||||||
|  |       const normalizedDirMeta = new cpl.CompileDirectiveMetadata({ | ||||||
|  |         type: nonNormalizedMetadata.type, | ||||||
|  |         isComponent: nonNormalizedMetadata.isComponent, | ||||||
|  |         selector: nonNormalizedMetadata.selector, | ||||||
|  |         exportAs: nonNormalizedMetadata.exportAs, | ||||||
|  |         changeDetection: nonNormalizedMetadata.changeDetection, | ||||||
|  |         inputs: nonNormalizedMetadata.inputs, | ||||||
|  |         outputs: nonNormalizedMetadata.outputs, | ||||||
|  |         hostListeners: nonNormalizedMetadata.hostListeners, | ||||||
|  |         hostProperties: nonNormalizedMetadata.hostProperties, | ||||||
|  |         hostAttributes: nonNormalizedMetadata.hostAttributes, | ||||||
|  |         providers: nonNormalizedMetadata.providers, | ||||||
|  |         viewProviders: nonNormalizedMetadata.viewProviders, | ||||||
|  |         queries: nonNormalizedMetadata.queries, | ||||||
|  |         viewQueries: nonNormalizedMetadata.viewQueries, | ||||||
|  |         entryComponents: nonNormalizedMetadata.entryComponents, | ||||||
|  |         template: templateMetadata | ||||||
|  |       }); | ||||||
|  |       this._directiveCache.set(directiveType, normalizedDirMeta); | ||||||
|  |       this._directiveSummaryCache.set(directiveType, normalizedDirMeta.toSummary()); | ||||||
|  |       return normalizedDirMeta; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     if (nonNormalizedMetadata.isComponent) { | ||||||
|  |       const templateMeta = this._directiveNormalizer.normalizeTemplate({ | ||||||
|  |         componentType: directiveType, | ||||||
|  |         moduleUrl: nonNormalizedMetadata.type.moduleUrl, | ||||||
|  |         encapsulation: nonNormalizedMetadata.template.encapsulation, | ||||||
|  |         template: nonNormalizedMetadata.template.template, | ||||||
|  |         templateUrl: nonNormalizedMetadata.template.templateUrl, | ||||||
|  |         styles: nonNormalizedMetadata.template.styles, | ||||||
|  |         styleUrls: nonNormalizedMetadata.template.styleUrls, | ||||||
|  |         animations: nonNormalizedMetadata.template.animations, | ||||||
|  |         interpolation: nonNormalizedMetadata.template.interpolation | ||||||
|  |       }); | ||||||
|  |       if (templateMeta.syncResult) { | ||||||
|  |         createDirectiveMetadata(templateMeta.syncResult); | ||||||
|  |         return null; | ||||||
|  |       } else { | ||||||
|  |         if (isSync) { | ||||||
|  |           throw new ComponentStillLoadingError(directiveType); | ||||||
|  |         } | ||||||
|  |         return templateMeta.asyncResult.then(createDirectiveMetadata); | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       // directive
 | ||||||
|  |       createDirectiveMetadata(null); | ||||||
|  |       return null; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   getNonNormalizedDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata { | ||||||
|     directiveType = resolveForwardRef(directiveType); |     directiveType = resolveForwardRef(directiveType); | ||||||
|     const dirMeta = this._directiveResolver.resolve(directiveType); |     const dirMeta = this._directiveResolver.resolve(directiveType); | ||||||
|     if (!dirMeta) { |     if (!dirMeta) { | ||||||
|       return null; |       return null; | ||||||
|     } |     } | ||||||
|     let moduleUrl = staticTypeModuleUrl(directiveType); |     let moduleUrl = staticTypeModuleUrl(directiveType); | ||||||
|  |     let nonNormalizedTemplateMetadata: cpl.CompileTemplateMetadata; | ||||||
|  | 
 | ||||||
|  |     if (dirMeta instanceof Component) { | ||||||
|  |       // component
 | ||||||
|  |       moduleUrl = componentModuleUrl(this._reflector, directiveType, dirMeta); | ||||||
|  |       assertArrayOfStrings('styles', dirMeta.styles); | ||||||
|  |       assertArrayOfStrings('styleUrls', dirMeta.styleUrls); | ||||||
|  |       assertInterpolationSymbols('interpolation', dirMeta.interpolation); | ||||||
|  | 
 | ||||||
|  |       const animations = dirMeta.animations ? | ||||||
|  |           dirMeta.animations.map(e => this.getAnimationEntryMetadata(e)) : | ||||||
|  |           null; | ||||||
|  | 
 | ||||||
|  |       nonNormalizedTemplateMetadata = new cpl.CompileTemplateMetadata({ | ||||||
|  |         encapsulation: dirMeta.encapsulation, | ||||||
|  |         template: dirMeta.template, | ||||||
|  |         templateUrl: dirMeta.templateUrl, | ||||||
|  |         styles: dirMeta.styles, | ||||||
|  |         styleUrls: dirMeta.styleUrls, | ||||||
|  |         animations: animations, | ||||||
|  |         interpolation: dirMeta.interpolation | ||||||
|  |       }); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     const createDirectiveMetadata = (templateMeta: cpl.CompileTemplateMetadata) => { |  | ||||||
|     let changeDetectionStrategy: ChangeDetectionStrategy = null; |     let changeDetectionStrategy: ChangeDetectionStrategy = null; | ||||||
|     let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; |     let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||||
|     let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = []; |     let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = []; | ||||||
| @ -185,8 +263,7 @@ export class CompileMetadataResolver { | |||||||
|     let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; |     let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||||
|     if (isPresent(dirMeta.providers)) { |     if (isPresent(dirMeta.providers)) { | ||||||
|       providers = this._getProvidersMetadata( |       providers = this._getProvidersMetadata( | ||||||
|             dirMeta.providers, entryComponentMetadata, |           dirMeta.providers, entryComponentMetadata, `providers for "${stringify(directiveType)}"`); | ||||||
|             `providers for "${stringify(directiveType)}"`); |  | ||||||
|     } |     } | ||||||
|     let queries: cpl.CompileQueryMetadata[] = []; |     let queries: cpl.CompileQueryMetadata[] = []; | ||||||
|     let viewQueries: cpl.CompileQueryMetadata[] = []; |     let viewQueries: cpl.CompileQueryMetadata[] = []; | ||||||
| @ -195,12 +272,12 @@ export class CompileMetadataResolver { | |||||||
|       viewQueries = this._getQueriesMetadata(dirMeta.queries, true, directiveType); |       viewQueries = this._getQueriesMetadata(dirMeta.queries, true, directiveType); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|       const meta = cpl.CompileDirectiveMetadata.create({ |     return cpl.CompileDirectiveMetadata.create({ | ||||||
|       selector: selector, |       selector: selector, | ||||||
|       exportAs: dirMeta.exportAs, |       exportAs: dirMeta.exportAs, | ||||||
|         isComponent: !!templateMeta, |       isComponent: !!nonNormalizedTemplateMetadata, | ||||||
|       type: this._getTypeMetadata(directiveType, moduleUrl), |       type: this._getTypeMetadata(directiveType, moduleUrl), | ||||||
|         template: templateMeta, |       template: nonNormalizedTemplateMetadata, | ||||||
|       changeDetection: changeDetectionStrategy, |       changeDetection: changeDetectionStrategy, | ||||||
|       inputs: dirMeta.inputs, |       inputs: dirMeta.inputs, | ||||||
|       outputs: dirMeta.outputs, |       outputs: dirMeta.outputs, | ||||||
| @ -211,47 +288,6 @@ export class CompileMetadataResolver { | |||||||
|       viewQueries: viewQueries, |       viewQueries: viewQueries, | ||||||
|       entryComponents: entryComponentMetadata |       entryComponents: entryComponentMetadata | ||||||
|     }); |     }); | ||||||
|       this._directiveCache.set(directiveType, meta); |  | ||||||
|       this._directiveSummaryCache.set(directiveType, meta.toSummary()); |  | ||||||
|       return meta; |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     if (dirMeta instanceof Component) { |  | ||||||
|       // component
 |  | ||||||
|       moduleUrl = componentModuleUrl(this._reflector, directiveType, dirMeta); |  | ||||||
|       assertArrayOfStrings('styles', dirMeta.styles); |  | ||||||
|       assertArrayOfStrings('styleUrls', dirMeta.styleUrls); |  | ||||||
|       assertInterpolationSymbols('interpolation', dirMeta.interpolation); |  | ||||||
| 
 |  | ||||||
|       const animations = dirMeta.animations ? |  | ||||||
|           dirMeta.animations.map(e => this.getAnimationEntryMetadata(e)) : |  | ||||||
|           null; |  | ||||||
| 
 |  | ||||||
|       const templateMeta = this._directiveNormalizer.normalizeTemplate({ |  | ||||||
|         componentType: directiveType, |  | ||||||
|         moduleUrl: moduleUrl, |  | ||||||
|         encapsulation: dirMeta.encapsulation, |  | ||||||
|         template: dirMeta.template, |  | ||||||
|         templateUrl: dirMeta.templateUrl, |  | ||||||
|         styles: dirMeta.styles, |  | ||||||
|         styleUrls: dirMeta.styleUrls, |  | ||||||
|         animations: animations, |  | ||||||
|         interpolation: dirMeta.interpolation |  | ||||||
|       }); |  | ||||||
|       if (templateMeta.syncResult) { |  | ||||||
|         createDirectiveMetadata(templateMeta.syncResult); |  | ||||||
|         return null; |  | ||||||
|       } else { |  | ||||||
|         if (isSync) { |  | ||||||
|           throw new ComponentStillLoadingError(directiveType); |  | ||||||
|         } |  | ||||||
|         return templateMeta.asyncResult.then(createDirectiveMetadata); |  | ||||||
|       } |  | ||||||
|     } else { |  | ||||||
|       // directive
 |  | ||||||
|       createDirectiveMetadata(null); |  | ||||||
|       return null; |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   /** |   /** | ||||||
| @ -309,11 +345,20 @@ export class CompileMetadataResolver { | |||||||
|   loadNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): |   loadNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): | ||||||
|       {ngModule: cpl.CompileNgModuleMetadata, loading: Promise<any>} { |       {ngModule: cpl.CompileNgModuleMetadata, loading: Promise<any>} { | ||||||
|     const ngModule = this._loadNgModuleMetadata(moduleType, isSync, throwIfNotFound); |     const ngModule = this._loadNgModuleMetadata(moduleType, isSync, throwIfNotFound); | ||||||
|     const loading = |     const loading = ngModule ? | ||||||
|         ngModule ? Promise.all(ngModule.transitiveModule.loadingPromises) : Promise.resolve(null); |         Promise.all(ngModule.transitiveModule.directiveLoaders.map(loader => loader())) : | ||||||
|  |         Promise.resolve(null); | ||||||
|     return {ngModule, loading}; |     return {ngModule, loading}; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   /** | ||||||
|  |    * Get the NgModule metadata without loading the directives. | ||||||
|  |    */ | ||||||
|  |   getUnloadedNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): | ||||||
|  |       cpl.CompileNgModuleMetadata { | ||||||
|  |     return this._loadNgModuleMetadata(moduleType, isSync, throwIfNotFound); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private _loadNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): |   private _loadNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): | ||||||
|       cpl.CompileNgModuleMetadata { |       cpl.CompileNgModuleMetadata { | ||||||
|     moduleType = resolveForwardRef(moduleType); |     moduleType = resolveForwardRef(moduleType); | ||||||
| @ -396,10 +441,8 @@ export class CompileMetadataResolver { | |||||||
|           transitiveModule.directives.push(declaredIdentifier); |           transitiveModule.directives.push(declaredIdentifier); | ||||||
|           declaredDirectives.push(declaredIdentifier); |           declaredDirectives.push(declaredIdentifier); | ||||||
|           this._addTypeToModule(declaredType, moduleType); |           this._addTypeToModule(declaredType, moduleType); | ||||||
|           const loadingPromise = this._loadDirectiveMetadata(declaredType, isSync); |           transitiveModule.directiveLoaders.push( | ||||||
|           if (loadingPromise) { |               () => this._loadDirectiveMetadata(declaredType, isSync)); | ||||||
|             transitiveModule.loadingPromises.push(loadingPromise); |  | ||||||
|           } |  | ||||||
|         } else if (this._pipeResolver.isPipe(declaredType)) { |         } else if (this._pipeResolver.isPipe(declaredType)) { | ||||||
|           transitiveModule.pipesSet.add(declaredType); |           transitiveModule.pipesSet.add(declaredType); | ||||||
|           transitiveModule.pipes.push(declaredIdentifier); |           transitiveModule.pipes.push(declaredIdentifier); | ||||||
| @ -525,10 +568,10 @@ export class CompileMetadataResolver { | |||||||
|     const directives = |     const directives = | ||||||
|         flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives)); |         flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives)); | ||||||
|     const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes)); |     const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes)); | ||||||
|     const loadingPromises = |     const directiveLoaders = | ||||||
|         ListWrapper.flatten(transitiveExportedModules.map(ngModule => ngModule.loadingPromises)); |         ListWrapper.flatten(transitiveExportedModules.map(ngModule => ngModule.directiveLoaders)); | ||||||
|     return new cpl.TransitiveCompileNgModuleMetadata( |     return new cpl.TransitiveCompileNgModuleMetadata( | ||||||
|         transitiveModules, providers, entryComponents, directives, pipes, loadingPromises); |         transitiveModules, providers, entryComponents, directives, pipes, directiveLoaders); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private _getIdentifierMetadata(type: Type<any>, moduleUrl: string): |   private _getIdentifierMetadata(type: Type<any>, moduleUrl: string): | ||||||
| @ -584,20 +627,26 @@ export class CompileMetadataResolver { | |||||||
|     return pipeSummary; |     return pipeSummary; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private _loadPipeMetadata(pipeType: Type<any>): void { |   getOrLoadPipeMetadata(pipeType: any): cpl.CompilePipeMetadata { | ||||||
|     pipeType = resolveForwardRef(pipeType); |     let pipeMeta = this._pipeCache.get(pipeType); | ||||||
|     const pipeMeta = this._pipeResolver.resolve(pipeType); |  | ||||||
|     if (!pipeMeta) { |     if (!pipeMeta) { | ||||||
|       return null; |       pipeMeta = this._loadPipeMetadata(pipeType); | ||||||
|  |     } | ||||||
|  |     return pipeMeta; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|     const meta = new cpl.CompilePipeMetadata({ |   private _loadPipeMetadata(pipeType: any): cpl.CompilePipeMetadata { | ||||||
|  |     pipeType = resolveForwardRef(pipeType); | ||||||
|  |     const pipeAnnotation = this._pipeResolver.resolve(pipeType); | ||||||
|  | 
 | ||||||
|  |     const pipeMeta = new cpl.CompilePipeMetadata({ | ||||||
|       type: this._getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)), |       type: this._getTypeMetadata(pipeType, staticTypeModuleUrl(pipeType)), | ||||||
|       name: pipeMeta.name, |       name: pipeAnnotation.name, | ||||||
|       pure: pipeMeta.pure |       pure: pipeAnnotation.pure | ||||||
|     }); |     }); | ||||||
|     this._pipeCache.set(pipeType, meta); |     this._pipeCache.set(pipeType, pipeMeta); | ||||||
|     this._pipeSummaryCache.set(pipeType, meta.toSummary()); |     this._pipeSummaryCache.set(pipeType, pipeMeta.toSummary()); | ||||||
|  |     return pipeMeta; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   private _getDependenciesMetadata(typeOrFunc: Type<any>|Function, dependencies: any[]): |   private _getDependenciesMetadata(typeOrFunc: Type<any>|Function, dependencies: any[]): | ||||||
|  | |||||||
| @ -27,17 +27,46 @@ export class SourceModule { | |||||||
|   constructor(public fileUrl: string, public moduleUrl: string, public source: string) {} |   constructor(public fileUrl: string, public moduleUrl: string, public source: string) {} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | export interface NgAnalyzedModules { | ||||||
|  |   ngModules: CompileNgModuleMetadata[]; | ||||||
|  |   ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>; | ||||||
|  |   files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}>; | ||||||
|  |   symbolsMissingModule?: StaticSymbol[]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Returns all the source files and a mapping from modules to directives
 | // Returns all the source files and a mapping from modules to directives
 | ||||||
| export function analyzeNgModules( | export function analyzeNgModules( | ||||||
|     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, |     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, | ||||||
|     metadataResolver: CompileMetadataResolver): Promise<{ |     metadataResolver: CompileMetadataResolver): NgAnalyzedModules { | ||||||
|   ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>, |   const {ngModules, symbolsMissingModule} = | ||||||
|   files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}> |       _createNgModules(programStaticSymbols, options, metadataResolver); | ||||||
| }> { |   return _analyzeNgModules(ngModules, symbolsMissingModule); | ||||||
|   return _loadNgModules(programStaticSymbols, options, metadataResolver).then(_analyzeNgModules); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function _analyzeNgModules(ngModuleMetas: CompileNgModuleMetadata[]) { | 
 | ||||||
|  | export function analyzeAndValidateNgModules( | ||||||
|  |     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, | ||||||
|  |     metadataResolver: CompileMetadataResolver): NgAnalyzedModules { | ||||||
|  |   const result = analyzeNgModules(programStaticSymbols, options, metadataResolver); | ||||||
|  |   if (result.symbolsMissingModule && result.symbolsMissingModule.length) { | ||||||
|  |     const messages = result.symbolsMissingModule.map( | ||||||
|  |         s => `Cannot determine the module for class ${s.name} in ${s.filePath}!`); | ||||||
|  |     throw new Error(messages.join('\n')); | ||||||
|  |   } | ||||||
|  |   return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Wait for the directives in the given modules have been loaded
 | ||||||
|  | export function loadNgModuleDirectives(ngModules: CompileNgModuleMetadata[]) { | ||||||
|  |   return Promise | ||||||
|  |       .all(ListWrapper.flatten(ngModules.map( | ||||||
|  |           (ngModule) => ngModule.transitiveModule.directiveLoaders.map(loader => loader())))) | ||||||
|  |       .then(() => {}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function _analyzeNgModules( | ||||||
|  |     ngModuleMetas: CompileNgModuleMetadata[], | ||||||
|  |     symbolsMissingModule: StaticSymbol[]): NgAnalyzedModules { | ||||||
|   const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>(); |   const moduleMetasByRef = new Map<any, CompileNgModuleMetadata>(); | ||||||
|   ngModuleMetas.forEach((ngModule) => moduleMetasByRef.set(ngModule.type.reference, ngModule)); |   ngModuleMetas.forEach((ngModule) => moduleMetasByRef.set(ngModule.type.reference, ngModule)); | ||||||
|   const ngModuleByPipeOrDirective = new Map<StaticSymbol, CompileNgModuleMetadata>(); |   const ngModuleByPipeOrDirective = new Map<StaticSymbol, CompileNgModuleMetadata>(); | ||||||
| @ -82,6 +111,7 @@ function _analyzeNgModules(ngModuleMetas: CompileNgModuleMetadata[]) { | |||||||
|     ngModuleByPipeOrDirective, |     ngModuleByPipeOrDirective, | ||||||
|     // list modules and directives for every source file
 |     // list modules and directives for every source file
 | ||||||
|     files, |     files, | ||||||
|  |     ngModules: ngModuleMetas, symbolsMissingModule | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -100,8 +130,9 @@ export class OfflineCompiler { | |||||||
| 
 | 
 | ||||||
|   compileModules(staticSymbols: StaticSymbol[], options: {transitiveModules: boolean}): |   compileModules(staticSymbols: StaticSymbol[], options: {transitiveModules: boolean}): | ||||||
|       Promise<SourceModule[]> { |       Promise<SourceModule[]> { | ||||||
|     return analyzeNgModules(staticSymbols, options, this._metadataResolver) |     const {ngModuleByPipeOrDirective, files, ngModules} = | ||||||
|         .then(({ngModuleByPipeOrDirective, files}) => { |         analyzeAndValidateNgModules(staticSymbols, options, this._metadataResolver); | ||||||
|  |     return loadNgModuleDirectives(ngModules).then(() => { | ||||||
|       const sourceModules = files.map( |       const sourceModules = files.map( | ||||||
|           file => this._compileSrcFile( |           file => this._compileSrcFile( | ||||||
|               file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules)); |               file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules)); | ||||||
| @ -328,22 +359,21 @@ function _splitTypescriptSuffix(path: string): string[] { | |||||||
| // Load the NgModules and check
 | // Load the NgModules and check
 | ||||||
| // that all directives / pipes that are present in the program
 | // that all directives / pipes that are present in the program
 | ||||||
| // are also declared by a module.
 | // are also declared by a module.
 | ||||||
| function _loadNgModules( | function _createNgModules( | ||||||
|     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, |     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, | ||||||
|     metadataResolver: CompileMetadataResolver): Promise<CompileNgModuleMetadata[]> { |     metadataResolver: CompileMetadataResolver): | ||||||
|  |     {ngModules: CompileNgModuleMetadata[], symbolsMissingModule: StaticSymbol[]} { | ||||||
|   const ngModules = new Map<any, CompileNgModuleMetadata>(); |   const ngModules = new Map<any, CompileNgModuleMetadata>(); | ||||||
|   const programPipesAndDirectives: StaticSymbol[] = []; |   const programPipesAndDirectives: StaticSymbol[] = []; | ||||||
|   const ngModulePipesAndDirective = new Set<StaticSymbol>(); |   const ngModulePipesAndDirective = new Set<StaticSymbol>(); | ||||||
|   const loadingPromises: Promise<any>[] = []; |  | ||||||
| 
 | 
 | ||||||
|   const addNgModule = (staticSymbol: any) => { |   const addNgModule = (staticSymbol: any) => { | ||||||
|     if (ngModules.has(staticSymbol)) { |     if (ngModules.has(staticSymbol)) { | ||||||
|       return false; |       return false; | ||||||
|     } |     } | ||||||
|     const {ngModule, loading} = metadataResolver.loadNgModuleMetadata(staticSymbol, false, false); |     const ngModule = metadataResolver.getUnloadedNgModuleMetadata(staticSymbol, false, false); | ||||||
|     if (ngModule) { |     if (ngModule) { | ||||||
|       ngModules.set(ngModule.type.reference, ngModule); |       ngModules.set(ngModule.type.reference, ngModule); | ||||||
|       loadingPromises.push(loading); |  | ||||||
|       ngModule.declaredDirectives.forEach((dir) => ngModulePipesAndDirective.add(dir.reference)); |       ngModule.declaredDirectives.forEach((dir) => ngModulePipesAndDirective.add(dir.reference)); | ||||||
|       ngModule.declaredPipes.forEach((pipe) => ngModulePipesAndDirective.add(pipe.reference)); |       ngModule.declaredPipes.forEach((pipe) => ngModulePipesAndDirective.add(pipe.reference)); | ||||||
|       if (options.transitiveModules) { |       if (options.transitiveModules) { | ||||||
| @ -364,11 +394,5 @@ function _loadNgModules( | |||||||
|   const symbolsMissingModule = |   const symbolsMissingModule = | ||||||
|       programPipesAndDirectives.filter(s => !ngModulePipesAndDirective.has(s)); |       programPipesAndDirectives.filter(s => !ngModulePipesAndDirective.has(s)); | ||||||
| 
 | 
 | ||||||
|   if (symbolsMissingModule.length) { |   return {ngModules: Array.from(ngModules.values()), symbolsMissingModule}; | ||||||
|     const messages = symbolsMissingModule.map( |  | ||||||
|         s => `Cannot determine the module for class ${s.name} in ${s.filePath}!`); |  | ||||||
|     throw new Error(messages.join('\n')); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   return Promise.all(loadingPromises).then(() => Array.from(ngModules.values())); |  | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user