mgechev / ngast

Parser for Angular projects.

Home Page:https://mgechev.github.io/ngast/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`ModuleWithProviders` not reflected in Angular AST

dherges opened this issue · comments

(I may use a lot of wrong terms, please correct me. I try to be precise)

If understanding right, ngast reflects the structure (composition and dependencies) of an Angular application from a run-time view. For example, let's say an AppModule imported the BrowserModule:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now, in the ngast, the ModuleSymbol representing AppModule returns an empty .getProviders() (sounds obvious because providers: [] is an empty array in the above).

The ProjectSymbols.getProvider() includes "imported"(?) providers from BrowserModule like (partial extract): "ɵDomRendererFactory2"


Now, let's import more module in AppModule

@Injectable()
class MyFeatureService {
  constructor (private http: HttpClient) {}
}

@NgModule({})
class MyFeatureModule {
  public static forRoot(): ModuleWithProviders {
    return { ngModule: MyFeatureModule, providers: [ MyFeatureService ]};
  }
}


@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,
    MyFeatureModule.forRoot()
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Still, ModuleSymbol.getProviders() is an empty array (the one repsenting AppModule - ok).

ModuleSymbol.getProviders() is an empty array (also for the one representing MyFeatureModule - ok).

ProjectSymbols.getProviders() now includes also providers from HttpClientModule (like the JsonPClientBackend, HTTP_INTERCEPTORS, and so on) and also the useClass provider for MyFeatureService.


So far, so good. Now let's exclude the AppModule from the ts.Program and only analyze the MyFeatureModule:

Now, in the ProjectSymbols.getProviders() there are still providers for JsonPClientBackend, HTTP_INTERCEPTORS, and so on. But the provider for MyFeatureService is missing. I think probably because MyFeatureModule.forRoot() was nowhere imported but still the dependency metadata for the MyFeatureService was generated because of the @Injectable() annotation.

And also still, ModuleSymbol.getProviders() returns an empty array because of the "empty" module annotation @NgModule({}) class MyFeatureModule.


First question: why are .forRoot() providers on ProjectSymbols.getProviders()?

Seeing this, it looks like ngast reflects an Angular application from a run-time perspective. It looks like ProjectSymbols.getProviders() reflects the "root injector scope". Is that right?

Second question: why is ModuleWithProviders not reflected in ngast?

Even with the ProjectSymbols.getProviders() it's no longer possible to find out which module declared the provider, because ModuleSymbol.getProviders() (the one representing MyFeatureModule) returns an empty provider array. However, the ModuleSymbol.getProviders() representing CoreModule returns a set of providers declared by CoreModule (like "ɵe", "IterableDiffers", "KeyValueDiffers", "LOCALE_ID", and so on).

Also the StaticSymbol.members (of the MyFeatureModule) is an empty array so it's not possible to inflect something about static methods returning a ModuleWithProviders.

Why is the ModuleWithProviders not reflected in ngast?

No longer relevant.