From 2846505dbd586942d1f8107197ac821d264c5ec2 Mon Sep 17 00:00:00 2001 From: ayazhafiz Date: Mon, 16 Sep 2019 22:33:48 -0500 Subject: [PATCH] feat(language-service): expose determining the NgModule of a Directive (#32710) This sets up the Language Service to support #32565. This PR exposes a `getDirectiveModule` method on `TypeScriptServiceHost` that returns the NgModule owning a Directive given the Directive's TypeScript node or its Angular `StaticSymbol`. Both types are supported to reduce extraneous helper methods. PR Close #32710 --- .../language-service/src/typescript_host.ts | 8 ++++++++ .../test/typescript_host_spec.ts | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/packages/language-service/src/typescript_host.ts b/packages/language-service/src/typescript_host.ts index 5d0032650c..81c325fc41 100644 --- a/packages/language-service/src/typescript_host.ts +++ b/packages/language-service/src/typescript_host.ts @@ -441,6 +441,14 @@ export class TypeScriptServiceHost implements LanguageServiceHost { return astResult; } + /** + * Gets a StaticSymbol from a file and symbol name. + * @return Angular StaticSymbol matching the file and name, if any + */ + getStaticSymbol(file: string, name: string): StaticSymbol|undefined { + return this.reflector.getStaticSymbol(file, name); + } + /** * Find the NgModule which the directive associated with the `classSymbol` * belongs to, then return its schema and transitive directives and pipes. diff --git a/packages/language-service/test/typescript_host_spec.ts b/packages/language-service/test/typescript_host_spec.ts index d57f3d89b3..2827fae668 100644 --- a/packages/language-service/test/typescript_host_spec.ts +++ b/packages/language-service/test/typescript_host_spec.ts @@ -170,4 +170,24 @@ describe('TypeScriptServiceHost', () => { const newModules = ngLSHost.getAnalyzedModules(); expect(newModules).toBe(oldModules); }); + + it('should get the correct StaticSymbol for a Directive', () => { + const tsLSHost = new MockTypescriptHost(['/app/app.component.ts', '/app/main.ts'], toh); + const tsLS = ts.createLanguageService(tsLSHost); + const ngLSHost = new TypeScriptServiceHost(tsLSHost, tsLS); + ngLSHost.getAnalyzedModules(); // modules are analyzed lazily + const sf = ngLSHost.getSourceFile('/app/app.component.ts'); + expect(sf).toBeDefined(); + const directiveDecl = sf !.forEachChild(n => { + if (ts.isClassDeclaration(n) && n.name && n.name.text === 'AppComponent') return n; + }); + + expect(directiveDecl).toBeDefined(); + expect(directiveDecl !.name).toBeDefined(); + const fileName = directiveDecl !.getSourceFile().fileName; + const symbolName = directiveDecl !.name !.getText(); + const directiveSymbol = ngLSHost.getStaticSymbol(fileName, symbolName); + expect(directiveSymbol).toBeDefined(); + expect(directiveSymbol !.name).toBe('AppComponent'); + }); });