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,34 +34,34 @@ export class Extractor { | ||||
|     const programSymbols: StaticSymbol[] = | ||||
|         extractProgramSymbols(this.program, this.staticReflector, this.reflectorHost, this.options); | ||||
| 
 | ||||
|     return compiler | ||||
|         .analyzeNgModules(programSymbols, {transitiveModules: true}, this.metadataResolver) | ||||
|         .then(({files}) => { | ||||
|           const errors: compiler.ParseError[] = []; | ||||
|     const {ngModules, files} = compiler.analyzeAndValidateNgModules( | ||||
|         programSymbols, {transitiveModules: true}, this.metadataResolver); | ||||
|     return compiler.loadNgModuleDirectives(ngModules).then(() => { | ||||
|       const errors: compiler.ParseError[] = []; | ||||
| 
 | ||||
|           files.forEach(file => { | ||||
|             const compMetas: compiler.CompileDirectiveMetadata[] = []; | ||||
|             file.directives.forEach(directiveType => { | ||||
|               const dirMeta = this.metadataResolver.getDirectiveMetadata(directiveType); | ||||
|               if (dirMeta && dirMeta.isComponent) { | ||||
|                 compMetas.push(dirMeta); | ||||
|               } | ||||
|             }); | ||||
|             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)); | ||||
|             }); | ||||
|           }); | ||||
| 
 | ||||
|           if (errors.length) { | ||||
|             throw new Error(errors.map(e => e.toString()).join('\n')); | ||||
|       files.forEach(file => { | ||||
|         const compMetas: compiler.CompileDirectiveMetadata[] = []; | ||||
|         file.directives.forEach(directiveType => { | ||||
|           const dirMeta = this.metadataResolver.getDirectiveMetadata(directiveType); | ||||
|           if (dirMeta && dirMeta.isComponent) { | ||||
|             compMetas.push(dirMeta); | ||||
|           } | ||||
| 
 | ||||
|           return this.messageBundle; | ||||
|         }); | ||||
|         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)); | ||||
|         }); | ||||
|       }); | ||||
| 
 | ||||
|       if (errors.length) { | ||||
|         throw new Error(errors.map(e => e.toString()).join('\n')); | ||||
|       } | ||||
| 
 | ||||
|       return this.messageBundle; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   static create( | ||||
|  | ||||
| @ -589,7 +589,7 @@ export interface CompileNgModuleDirectiveSummary extends CompileSummary { | ||||
|   exportedDirectives: CompileIdentifierMetadata[]; | ||||
|   exportedPipes: CompileIdentifierMetadata[]; | ||||
|   exportedModules: CompileNgModuleDirectiveSummary[]; | ||||
|   loadingPromises: Promise<any>[]; | ||||
|   directiveLoaders: (() => Promise<void>)[]; | ||||
| } | ||||
| 
 | ||||
| export type CompileNgModuleSummary = | ||||
| @ -661,7 +661,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { | ||||
|       exportedModules: this.exportedModules, | ||||
|       exportedDirectives: this.exportedDirectives, | ||||
|       exportedPipes: this.exportedPipes, | ||||
|       loadingPromises: this.transitiveModule.loadingPromises | ||||
|       directiveLoaders: this.transitiveModule.directiveLoaders | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
| @ -682,7 +682,7 @@ export class CompileNgModuleMetadata implements CompileMetadataWithIdentifier { | ||||
|       exportedDirectives: this.exportedDirectives, | ||||
|       exportedPipes: this.exportedPipes, | ||||
|       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 entryComponents: CompileIdentifierMetadata[], | ||||
|       public directives: CompileIdentifierMetadata[], public pipes: CompileIdentifierMetadata[], | ||||
|       public loadingPromises: Promise<any>[]) { | ||||
|       public directiveLoaders: (() => Promise<void>)[]) { | ||||
|     directives.forEach(dir => this.directivesSet.add(dir.reference)); | ||||
|     pipes.forEach(pipe => this.pipesSet.add(pipe.reference)); | ||||
|   } | ||||
|  | ||||
| @ -146,97 +146,43 @@ export class CompileMetadataResolver { | ||||
|       return; | ||||
|     } | ||||
|     directiveType = resolveForwardRef(directiveType); | ||||
|     const dirMeta = this._directiveResolver.resolve(directiveType); | ||||
|     if (!dirMeta) { | ||||
|       return null; | ||||
|     } | ||||
|     let moduleUrl = staticTypeModuleUrl(directiveType); | ||||
|     const nonNormalizedMetadata = this.getNonNormalizedDirectiveMetadata(directiveType); | ||||
| 
 | ||||
|     const createDirectiveMetadata = (templateMeta: cpl.CompileTemplateMetadata) => { | ||||
|       let changeDetectionStrategy: ChangeDetectionStrategy = null; | ||||
|       let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||
|       let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = []; | ||||
|       let selector = dirMeta.selector; | ||||
| 
 | ||||
|       if (dirMeta instanceof Component) { | ||||
|         // Component
 | ||||
|         changeDetectionStrategy = dirMeta.changeDetection; | ||||
|         if (dirMeta.viewProviders) { | ||||
|           viewProviders = this._getProvidersMetadata( | ||||
|               dirMeta.viewProviders, entryComponentMetadata, | ||||
|               `viewProviders for "${stringify(directiveType)}"`); | ||||
|         } | ||||
|         if (dirMeta.entryComponents) { | ||||
|           entryComponentMetadata = | ||||
|               flattenAndDedupeArray(dirMeta.entryComponents) | ||||
|                   .map((type) => this._getIdentifierMetadata(type, staticTypeModuleUrl(type))) | ||||
|                   .concat(entryComponentMetadata); | ||||
|         } | ||||
|         if (!selector) { | ||||
|           selector = this._schemaRegistry.getDefaultComponentElementName(); | ||||
|         } | ||||
|       } else { | ||||
|         // Directive
 | ||||
|         if (!selector) { | ||||
|           throw new Error(`Directive ${stringify(directiveType)} has no selector, please add it!`); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||
|       if (isPresent(dirMeta.providers)) { | ||||
|         providers = this._getProvidersMetadata( | ||||
|             dirMeta.providers, entryComponentMetadata, | ||||
|             `providers for "${stringify(directiveType)}"`); | ||||
|       } | ||||
|       let queries: cpl.CompileQueryMetadata[] = []; | ||||
|       let viewQueries: cpl.CompileQueryMetadata[] = []; | ||||
|       if (isPresent(dirMeta.queries)) { | ||||
|         queries = this._getQueriesMetadata(dirMeta.queries, false, directiveType); | ||||
|         viewQueries = this._getQueriesMetadata(dirMeta.queries, true, directiveType); | ||||
|       } | ||||
| 
 | ||||
|       const meta = cpl.CompileDirectiveMetadata.create({ | ||||
|         selector: selector, | ||||
|         exportAs: dirMeta.exportAs, | ||||
|         isComponent: !!templateMeta, | ||||
|         type: this._getTypeMetadata(directiveType, moduleUrl), | ||||
|         template: templateMeta, | ||||
|         changeDetection: changeDetectionStrategy, | ||||
|         inputs: dirMeta.inputs, | ||||
|         outputs: dirMeta.outputs, | ||||
|         host: dirMeta.host, | ||||
|         providers: providers, | ||||
|         viewProviders: viewProviders, | ||||
|         queries: queries, | ||||
|         viewQueries: viewQueries, | ||||
|         entryComponents: entryComponentMetadata | ||||
|     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, meta); | ||||
|       this._directiveSummaryCache.set(directiveType, meta.toSummary()); | ||||
|       return meta; | ||||
|       this._directiveCache.set(directiveType, normalizedDirMeta); | ||||
|       this._directiveSummaryCache.set(directiveType, normalizedDirMeta.toSummary()); | ||||
|       return normalizedDirMeta; | ||||
|     }; | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
|     if (nonNormalizedMetadata.isComponent) { | ||||
|       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 | ||||
|         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); | ||||
| @ -254,6 +200,96 @@ export class CompileMetadataResolver { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   getNonNormalizedDirectiveMetadata(directiveType: any): cpl.CompileDirectiveMetadata { | ||||
|     directiveType = resolveForwardRef(directiveType); | ||||
|     const dirMeta = this._directiveResolver.resolve(directiveType); | ||||
|     if (!dirMeta) { | ||||
|       return null; | ||||
|     } | ||||
|     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 | ||||
|       }); | ||||
|     } | ||||
| 
 | ||||
|     let changeDetectionStrategy: ChangeDetectionStrategy = null; | ||||
|     let viewProviders: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||
|     let entryComponentMetadata: cpl.CompileIdentifierMetadata[] = []; | ||||
|     let selector = dirMeta.selector; | ||||
| 
 | ||||
|     if (dirMeta instanceof Component) { | ||||
|       // Component
 | ||||
|       changeDetectionStrategy = dirMeta.changeDetection; | ||||
|       if (dirMeta.viewProviders) { | ||||
|         viewProviders = this._getProvidersMetadata( | ||||
|             dirMeta.viewProviders, entryComponentMetadata, | ||||
|             `viewProviders for "${stringify(directiveType)}"`); | ||||
|       } | ||||
|       if (dirMeta.entryComponents) { | ||||
|         entryComponentMetadata = | ||||
|             flattenAndDedupeArray(dirMeta.entryComponents) | ||||
|                 .map((type) => this._getIdentifierMetadata(type, staticTypeModuleUrl(type))) | ||||
|                 .concat(entryComponentMetadata); | ||||
|       } | ||||
|       if (!selector) { | ||||
|         selector = this._schemaRegistry.getDefaultComponentElementName(); | ||||
|       } | ||||
|     } else { | ||||
|       // Directive
 | ||||
|       if (!selector) { | ||||
|         throw new Error(`Directive ${stringify(directiveType)} has no selector, please add it!`); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     let providers: Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> = []; | ||||
|     if (isPresent(dirMeta.providers)) { | ||||
|       providers = this._getProvidersMetadata( | ||||
|           dirMeta.providers, entryComponentMetadata, `providers for "${stringify(directiveType)}"`); | ||||
|     } | ||||
|     let queries: cpl.CompileQueryMetadata[] = []; | ||||
|     let viewQueries: cpl.CompileQueryMetadata[] = []; | ||||
|     if (isPresent(dirMeta.queries)) { | ||||
|       queries = this._getQueriesMetadata(dirMeta.queries, false, directiveType); | ||||
|       viewQueries = this._getQueriesMetadata(dirMeta.queries, true, directiveType); | ||||
|     } | ||||
| 
 | ||||
|     return cpl.CompileDirectiveMetadata.create({ | ||||
|       selector: selector, | ||||
|       exportAs: dirMeta.exportAs, | ||||
|       isComponent: !!nonNormalizedTemplateMetadata, | ||||
|       type: this._getTypeMetadata(directiveType, moduleUrl), | ||||
|       template: nonNormalizedTemplateMetadata, | ||||
|       changeDetection: changeDetectionStrategy, | ||||
|       inputs: dirMeta.inputs, | ||||
|       outputs: dirMeta.outputs, | ||||
|       host: dirMeta.host, | ||||
|       providers: providers, | ||||
|       viewProviders: viewProviders, | ||||
|       queries: queries, | ||||
|       viewQueries: viewQueries, | ||||
|       entryComponents: entryComponentMetadata | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * Gets the metadata for the given directive. | ||||
|    * This assumes `loadNgModuleMetadata` has been called first. | ||||
| @ -309,11 +345,20 @@ export class CompileMetadataResolver { | ||||
|   loadNgModuleMetadata(moduleType: any, isSync: boolean, throwIfNotFound = true): | ||||
|       {ngModule: cpl.CompileNgModuleMetadata, loading: Promise<any>} { | ||||
|     const ngModule = this._loadNgModuleMetadata(moduleType, isSync, throwIfNotFound); | ||||
|     const loading = | ||||
|         ngModule ? Promise.all(ngModule.transitiveModule.loadingPromises) : Promise.resolve(null); | ||||
|     const loading = ngModule ? | ||||
|         Promise.all(ngModule.transitiveModule.directiveLoaders.map(loader => loader())) : | ||||
|         Promise.resolve(null); | ||||
|     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): | ||||
|       cpl.CompileNgModuleMetadata { | ||||
|     moduleType = resolveForwardRef(moduleType); | ||||
| @ -396,10 +441,8 @@ export class CompileMetadataResolver { | ||||
|           transitiveModule.directives.push(declaredIdentifier); | ||||
|           declaredDirectives.push(declaredIdentifier); | ||||
|           this._addTypeToModule(declaredType, moduleType); | ||||
|           const loadingPromise = this._loadDirectiveMetadata(declaredType, isSync); | ||||
|           if (loadingPromise) { | ||||
|             transitiveModule.loadingPromises.push(loadingPromise); | ||||
|           } | ||||
|           transitiveModule.directiveLoaders.push( | ||||
|               () => this._loadDirectiveMetadata(declaredType, isSync)); | ||||
|         } else if (this._pipeResolver.isPipe(declaredType)) { | ||||
|           transitiveModule.pipesSet.add(declaredType); | ||||
|           transitiveModule.pipes.push(declaredIdentifier); | ||||
| @ -525,10 +568,10 @@ export class CompileMetadataResolver { | ||||
|     const directives = | ||||
|         flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedDirectives)); | ||||
|     const pipes = flattenArray(transitiveExportedModules.map((ngModule) => ngModule.exportedPipes)); | ||||
|     const loadingPromises = | ||||
|         ListWrapper.flatten(transitiveExportedModules.map(ngModule => ngModule.loadingPromises)); | ||||
|     const directiveLoaders = | ||||
|         ListWrapper.flatten(transitiveExportedModules.map(ngModule => ngModule.directiveLoaders)); | ||||
|     return new cpl.TransitiveCompileNgModuleMetadata( | ||||
|         transitiveModules, providers, entryComponents, directives, pipes, loadingPromises); | ||||
|         transitiveModules, providers, entryComponents, directives, pipes, directiveLoaders); | ||||
|   } | ||||
| 
 | ||||
|   private _getIdentifierMetadata(type: Type<any>, moduleUrl: string): | ||||
| @ -584,20 +627,26 @@ export class CompileMetadataResolver { | ||||
|     return pipeSummary; | ||||
|   } | ||||
| 
 | ||||
|   private _loadPipeMetadata(pipeType: Type<any>): void { | ||||
|     pipeType = resolveForwardRef(pipeType); | ||||
|     const pipeMeta = this._pipeResolver.resolve(pipeType); | ||||
|   getOrLoadPipeMetadata(pipeType: any): cpl.CompilePipeMetadata { | ||||
|     let pipeMeta = this._pipeCache.get(pipeType); | ||||
|     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)), | ||||
|       name: pipeMeta.name, | ||||
|       pure: pipeMeta.pure | ||||
|       name: pipeAnnotation.name, | ||||
|       pure: pipeAnnotation.pure | ||||
|     }); | ||||
|     this._pipeCache.set(pipeType, meta); | ||||
|     this._pipeSummaryCache.set(pipeType, meta.toSummary()); | ||||
|     this._pipeCache.set(pipeType, pipeMeta); | ||||
|     this._pipeSummaryCache.set(pipeType, pipeMeta.toSummary()); | ||||
|     return pipeMeta; | ||||
|   } | ||||
| 
 | ||||
|   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) {} | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
| export function analyzeNgModules( | ||||
|     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, | ||||
|     metadataResolver: CompileMetadataResolver): Promise<{ | ||||
|   ngModuleByPipeOrDirective: Map<StaticSymbol, CompileNgModuleMetadata>, | ||||
|   files: Array<{srcUrl: string, directives: StaticSymbol[], ngModules: StaticSymbol[]}> | ||||
| }> { | ||||
|   return _loadNgModules(programStaticSymbols, options, metadataResolver).then(_analyzeNgModules); | ||||
|     metadataResolver: CompileMetadataResolver): NgAnalyzedModules { | ||||
|   const {ngModules, symbolsMissingModule} = | ||||
|       _createNgModules(programStaticSymbols, options, metadataResolver); | ||||
|   return _analyzeNgModules(ngModules, symbolsMissingModule); | ||||
| } | ||||
| 
 | ||||
| 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>(); | ||||
|   ngModuleMetas.forEach((ngModule) => moduleMetasByRef.set(ngModule.type.reference, ngModule)); | ||||
|   const ngModuleByPipeOrDirective = new Map<StaticSymbol, CompileNgModuleMetadata>(); | ||||
| @ -78,10 +107,11 @@ function _analyzeNgModules(ngModuleMetas: CompileNgModuleMetadata[]) { | ||||
|   }); | ||||
| 
 | ||||
|   return { | ||||
|       // map directive/pipe to module
 | ||||
|       ngModuleByPipeOrDirective, | ||||
|       // list modules and directives for every source file
 | ||||
|       files, | ||||
|     // map directive/pipe to module
 | ||||
|     ngModuleByPipeOrDirective, | ||||
|     // list modules and directives for every source file
 | ||||
|     files, | ||||
|     ngModules: ngModuleMetas, symbolsMissingModule | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| @ -100,13 +130,14 @@ export class OfflineCompiler { | ||||
| 
 | ||||
|   compileModules(staticSymbols: StaticSymbol[], options: {transitiveModules: boolean}): | ||||
|       Promise<SourceModule[]> { | ||||
|     return analyzeNgModules(staticSymbols, options, this._metadataResolver) | ||||
|         .then(({ngModuleByPipeOrDirective, files}) => { | ||||
|           const sourceModules = files.map( | ||||
|               file => this._compileSrcFile( | ||||
|                   file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules)); | ||||
|           return ListWrapper.flatten(sourceModules); | ||||
|         }); | ||||
|     const {ngModuleByPipeOrDirective, files, ngModules} = | ||||
|         analyzeAndValidateNgModules(staticSymbols, options, this._metadataResolver); | ||||
|     return loadNgModuleDirectives(ngModules).then(() => { | ||||
|       const sourceModules = files.map( | ||||
|           file => this._compileSrcFile( | ||||
|               file.srcUrl, ngModuleByPipeOrDirective, file.directives, file.ngModules)); | ||||
|       return ListWrapper.flatten(sourceModules); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   private _compileSrcFile( | ||||
| @ -328,22 +359,21 @@ function _splitTypescriptSuffix(path: string): string[] { | ||||
| // Load the NgModules and check
 | ||||
| // that all directives / pipes that are present in the program
 | ||||
| // are also declared by a module.
 | ||||
| function _loadNgModules( | ||||
| function _createNgModules( | ||||
|     programStaticSymbols: StaticSymbol[], options: {transitiveModules: boolean}, | ||||
|     metadataResolver: CompileMetadataResolver): Promise<CompileNgModuleMetadata[]> { | ||||
|     metadataResolver: CompileMetadataResolver): | ||||
|     {ngModules: CompileNgModuleMetadata[], symbolsMissingModule: StaticSymbol[]} { | ||||
|   const ngModules = new Map<any, CompileNgModuleMetadata>(); | ||||
|   const programPipesAndDirectives: StaticSymbol[] = []; | ||||
|   const ngModulePipesAndDirective = new Set<StaticSymbol>(); | ||||
|   const loadingPromises: Promise<any>[] = []; | ||||
| 
 | ||||
|   const addNgModule = (staticSymbol: any) => { | ||||
|     if (ngModules.has(staticSymbol)) { | ||||
|       return false; | ||||
|     } | ||||
|     const {ngModule, loading} = metadataResolver.loadNgModuleMetadata(staticSymbol, false, false); | ||||
|     const ngModule = metadataResolver.getUnloadedNgModuleMetadata(staticSymbol, false, false); | ||||
|     if (ngModule) { | ||||
|       ngModules.set(ngModule.type.reference, ngModule); | ||||
|       loadingPromises.push(loading); | ||||
|       ngModule.declaredDirectives.forEach((dir) => ngModulePipesAndDirective.add(dir.reference)); | ||||
|       ngModule.declaredPipes.forEach((pipe) => ngModulePipesAndDirective.add(pipe.reference)); | ||||
|       if (options.transitiveModules) { | ||||
| @ -364,11 +394,5 @@ function _loadNgModules( | ||||
|   const symbolsMissingModule = | ||||
|       programPipesAndDirectives.filter(s => !ngModulePipesAndDirective.has(s)); | ||||
| 
 | ||||
|   if (symbolsMissingModule.length) { | ||||
|     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())); | ||||
|   return {ngModules: Array.from(ngModules.values()), symbolsMissingModule}; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user