diff --git a/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.js b/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.js index 933c640fe8..c0d25b5bac 100644 --- a/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.js +++ b/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.js @@ -158,6 +158,19 @@ module.exports = function processNgModuleDocs(getDocFromAlias, createDocMessage, processNgModuleProviders(ngModuleDoc) { // Add providers from the NgModule decorator. const providers = ngModuleDoc.ngmoduleOptions.providers || []; + + // Update injectables which are provided by this NgModule + for (const provider of providers) { + const injectable = parseProvider(provider); + const injectableDocs = getDocFromAlias(injectable, ngModuleDoc); + if (injectableDocs.length !== 1) { + continue; + } + const injectableDoc = injectableDocs[0]; + injectableDoc.ngModules = injectableDoc.ngModules || []; + injectableDoc.ngModules.push(ngModuleDoc); + } + // And also add those associated via the `Injectable` `providedIn` property. if (Array.isArray(ngModuleDoc.providers)) { for (const provider of ngModuleDoc.providers) { @@ -168,6 +181,7 @@ module.exports = function processNgModuleDocs(getDocFromAlias, createDocMessage, if (providers.length > 0) { ngModuleDoc.providers = providers; } + } }; @@ -191,6 +205,15 @@ module.exports = function processNgModuleDocs(getDocFromAlias, createDocMessage, } }; +function parseProvider(provider) { + const match = /\{\s*provide:\s*(\w+)\s*,/.exec(provider); + if (match) { + return match[1]; + } else { + return provider; + } +} + /** * Compute the name of the array that will hold items of this type in the NgModule document. */ diff --git a/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.spec.js b/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.spec.js index 4bcefc37d6..7c78c86744 100644 --- a/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.spec.js +++ b/aio/tools/transforms/angular-api-package/processors/processNgModuleDocs.spec.js @@ -150,6 +150,24 @@ describe('processNgModuleDocs processor', () => { expect(nonInjectable.ngModules).toBeUndefined(); }); + it('should link injectables that are parsed out of `@NgModule` decorators', () => { + const ngModule1 = { docType: 'ngmodule', id: 'NgModule1', ngmoduleOptions: { providers: ['Injectable1', '{ provide: Injectable2, useClass: Injectable2 }'] } }; + const ngModule2 = { docType: 'ngmodule', id: 'NgModule2', ngmoduleOptions: { providers: ['{ provide: Injectable3, useValue: {} }'] } }; + const injectable1 = { docType: 'class', name: 'Injectable1', aliases: ['Injectable1'] }; + const injectable2 = { docType: 'class', name: 'Injectable2', aliases: ['Injectable2'] }; + const injectable3 = { docType: 'class', name: 'Injectable3', aliases: ['Injectable3'] }; + + const aliasMap = injector.get('aliasMap'); + aliasMap.addDoc(injectable1); + aliasMap.addDoc(injectable2); + aliasMap.addDoc(injectable3); + processor.$process([ngModule1, ngModule2, injectable1, injectable2, injectable3]); + + expect(injectable1.ngModules).toEqual([ngModule1]); + expect(injectable2.ngModules).toEqual([ngModule1]); + expect(injectable3.ngModules).toEqual([ngModule2]); + }); + it('should error if an injectable that has a `providedIn` property that references an unknown NgModule doc', () => { const log = injector.get('log'); const injectable = { docType: 'class', name: 'Injectable1', decorators: [{ name: 'Injectable', argumentInfo: [{ providedIn: 'NgModuleRef' }] }] };