style(compiler-cli): reformat of codebase with new clang-format version (#36520)
This commit reformats the packages/compiler-cli tree using the new version of clang-format. PR Close #36520
This commit is contained in:
parent
717df13207
commit
0a69a2832b
|
@ -20,7 +20,9 @@ export class NormalService {
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
found: boolean;
|
found: boolean;
|
||||||
constructor(service: ShakeableService) { this.found = !!service.normal; }
|
constructor(service: ShakeableService) {
|
||||||
|
this.found = !!service.normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -29,7 +29,9 @@ export class AppComponent {
|
||||||
export class ChildComponent {
|
export class ChildComponent {
|
||||||
found: boolean;
|
found: boolean;
|
||||||
|
|
||||||
constructor(@Optional() @Self() service: Service|null) { this.found = !!service; }
|
constructor(@Optional() @Self() service: Service|null) {
|
||||||
|
this.found = !!service;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -21,7 +21,9 @@ export class NormalService {
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
found: boolean;
|
found: boolean;
|
||||||
constructor(service: NormalService) { this.found = !!service.shakeable; }
|
constructor(service: NormalService) {
|
||||||
|
this.found = !!service.shakeable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -17,7 +17,9 @@ import {ServerModule} from '@angular/platform-server';
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
data: string;
|
data: string;
|
||||||
constructor(service: Service) { this.data = service.data; }
|
constructor(service: Service) {
|
||||||
|
this.data = service.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, Inject, Injectable, InjectionToken, NgModule, forwardRef, inject} from '@angular/core';
|
import {Component, forwardRef, Inject, inject, Injectable, InjectionToken, NgModule} from '@angular/core';
|
||||||
import {BrowserModule} from '@angular/platform-browser';
|
import {BrowserModule} from '@angular/platform-browser';
|
||||||
import {ServerModule} from '@angular/platform-server';
|
import {ServerModule} from '@angular/platform-server';
|
||||||
|
|
||||||
export interface IService { readonly dep: {readonly data: string;}; }
|
export interface IService {
|
||||||
|
readonly dep: {readonly data: string;};
|
||||||
|
}
|
||||||
|
|
||||||
@NgModule({})
|
@NgModule({})
|
||||||
export class TokenModule {
|
export class TokenModule {
|
||||||
|
@ -28,7 +30,9 @@ export const TOKEN = new InjectionToken('test', {
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
data: string;
|
data: string;
|
||||||
constructor(@Inject(TOKEN) service: IService) { this.data = service.dep.data; }
|
constructor(@Inject(TOKEN) service: IService) {
|
||||||
|
this.data = service.dep.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Component, INJECTOR, Injectable, NgModule} from '@angular/core';
|
import {Component, Injectable, INJECTOR, NgModule} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {renderModuleFactory} from '@angular/platform-server';
|
import {renderModuleFactory} from '@angular/platform-server';
|
||||||
import {BasicAppModuleNgFactory} from 'app_built/src/basic.ngfactory';
|
import {BasicAppModuleNgFactory} from 'app_built/src/basic.ngfactory';
|
||||||
|
@ -104,7 +104,6 @@ describe('ngInjectableDef Bazel Integration', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows provider override in JIT for module-scoped @Injectables', () => {
|
it('allows provider override in JIT for module-scoped @Injectables', () => {
|
||||||
|
|
||||||
@NgModule()
|
@NgModule()
|
||||||
class Module {
|
class Module {
|
||||||
}
|
}
|
||||||
|
@ -172,7 +171,9 @@ describe('ngInjectableDef Bazel Integration', () => {
|
||||||
|
|
||||||
// ChildServices exteds ParentService but does not have @Injectable
|
// ChildServices exteds ParentService but does not have @Injectable
|
||||||
class ChildService extends ParentService {
|
class ChildService extends ParentService {
|
||||||
constructor(value: string) { super(value); }
|
constructor(value: string) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
static ngInjectableDef = {
|
static ngInjectableDef = {
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
factory: () => new ChildService('child'),
|
factory: () => new ChildService('child'),
|
||||||
|
|
|
@ -6,17 +6,23 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Injectable, InjectionToken, Injector, NgModule, forwardRef, ɵcreateInjector as createInjector} from '@angular/core';
|
import {forwardRef, Injectable, InjectionToken, Injector, NgModule, ɵcreateInjector as createInjector} from '@angular/core';
|
||||||
import {AOT_TOKEN, AotModule, AotService} from 'app_built/src/module';
|
import {AOT_TOKEN, AotModule, AotService} from 'app_built/src/module';
|
||||||
|
|
||||||
describe('Ivy NgModule', () => {
|
describe('Ivy NgModule', () => {
|
||||||
describe('AOT', () => {
|
describe('AOT', () => {
|
||||||
let injector: Injector;
|
let injector: Injector;
|
||||||
|
|
||||||
beforeEach(() => { injector = createInjector(AotModule); });
|
beforeEach(() => {
|
||||||
it('works', () => { expect(injector.get(AotService) instanceof AotService).toBeTruthy(); });
|
injector = createInjector(AotModule);
|
||||||
|
});
|
||||||
|
it('works', () => {
|
||||||
|
expect(injector.get(AotService) instanceof AotService).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
it('merges imports and exports', () => { expect(injector.get(AOT_TOKEN)).toEqual('exports'); });
|
it('merges imports and exports', () => {
|
||||||
|
expect(injector.get(AOT_TOKEN)).toEqual('exports');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +44,9 @@ describe('Ivy NgModule', () => {
|
||||||
class JitAppModule {
|
class JitAppModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('works', () => { createInjector(JitAppModule); });
|
it('works', () => {
|
||||||
|
createInjector(JitAppModule);
|
||||||
|
});
|
||||||
|
|
||||||
it('throws an error on circular module dependencies', () => {
|
it('throws an error on circular module dependencies', () => {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -16,10 +16,8 @@ export class LazyFeatureComponent {
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [RouterModule.forChild([
|
imports: [RouterModule.forChild([
|
||||||
{path: '', component: LazyFeatureComponent, pathMatch: 'full'},
|
{path: '', component: LazyFeatureComponent, pathMatch: 'full'},
|
||||||
{path: 'feature', loadChildren: './feature.module#FeatureModule'}, {
|
{path: 'feature', loadChildren: './feature.module#FeatureModule'},
|
||||||
path: 'nested-feature',
|
{path: 'nested-feature', loadChildren: './lazy-feature-nested.module#LazyFeatureNestedModule'}
|
||||||
loadChildren: './lazy-feature-nested.module#LazyFeatureNestedModule'
|
|
||||||
}
|
|
||||||
])],
|
])],
|
||||||
declarations: [LazyFeatureComponent]
|
declarations: [LazyFeatureComponent]
|
||||||
})
|
})
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Use of this source code is governed by an MIT-style license that can be
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import {AUTO_STYLE, animate, state, style, transition, trigger} from '@angular/animations';
|
import {animate, AUTO_STYLE, state, style, transition, trigger} from '@angular/animations';
|
||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -30,8 +30,16 @@ import {Component} from '@angular/core';
|
||||||
})
|
})
|
||||||
export class AnimateCmp {
|
export class AnimateCmp {
|
||||||
stateExpression: string;
|
stateExpression: string;
|
||||||
constructor() { this.setAsClosed(); }
|
constructor() {
|
||||||
setAsSomethingElse() { this.stateExpression = 'something'; }
|
this.setAsClosed();
|
||||||
setAsOpen() { this.stateExpression = 'open'; }
|
}
|
||||||
setAsClosed() { this.stateExpression = 'closed'; }
|
setAsSomethingElse() {
|
||||||
|
this.stateExpression = 'something';
|
||||||
|
}
|
||||||
|
setAsOpen() {
|
||||||
|
this.stateExpression = 'open';
|
||||||
|
}
|
||||||
|
setAsClosed() {
|
||||||
|
this.stateExpression = 'closed';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
import {InjectionToken} from '@angular/core';
|
import {InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
export interface Named { name: string; }
|
export interface Named {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
export const CUSTOM = new InjectionToken<Named>('CUSTOM');
|
export const CUSTOM = new InjectionToken<Named>('CUSTOM');
|
||||||
|
|
|
@ -10,5 +10,7 @@ import {Component} from '@angular/core';
|
||||||
|
|
||||||
@Component({selector: 'comp-with-error', templateUrl: 'errors.html'})
|
@Component({selector: 'comp-with-error', templateUrl: 'errors.html'})
|
||||||
export class BindingErrorComp {
|
export class BindingErrorComp {
|
||||||
createError() { throw new Error('Test'); }
|
createError() {
|
||||||
|
throw new Error('Test');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as common from '@angular/common';
|
import * as common from '@angular/common';
|
||||||
import {CUSTOM_ELEMENTS_SCHEMA, Component, Directive, EventEmitter, Inject, InjectionToken, NgModule, Output, forwardRef} from '@angular/core';
|
import {Component, CUSTOM_ELEMENTS_SCHEMA, Directive, EventEmitter, forwardRef, Inject, InjectionToken, NgModule, Output} from '@angular/core';
|
||||||
import {Observable} from 'rxjs';
|
import {Observable} from 'rxjs';
|
||||||
|
|
||||||
import {wrapInArray} from './funcs';
|
import {wrapInArray} from './funcs';
|
||||||
|
@ -62,7 +62,9 @@ export class CompUsingCustomElements {
|
||||||
})
|
})
|
||||||
export class CompConsumingEvents {
|
export class CompConsumingEvents {
|
||||||
handleDomEventVoid(e: any): void {}
|
handleDomEventVoid(e: any): void {}
|
||||||
handleDomEventPreventDefault(e: any): boolean { return false; }
|
handleDomEventPreventDefault(e: any): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
handleDirEvent(e: any): void {}
|
handleDirEvent(e: any): void {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +72,7 @@ export class CompConsumingEvents {
|
||||||
selector: '[dirEvent]',
|
selector: '[dirEvent]',
|
||||||
})
|
})
|
||||||
export class DirPublishingEvents {
|
export class DirPublishingEvents {
|
||||||
@Output('dirEvent')
|
@Output('dirEvent') dirEvent: Observable<string> = new EventEmitter();
|
||||||
dirEvent: Observable<string> = new EventEmitter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: wrapInArray(CompUsingCustomElements)})
|
@NgModule({schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: wrapInArray(CompUsingCustomElements)})
|
||||||
|
|
|
@ -19,7 +19,9 @@ export function expectInstanceCreated(type: any) {
|
||||||
export class SomeDep {}
|
export class SomeDep {}
|
||||||
|
|
||||||
export class Base {
|
export class Base {
|
||||||
constructor(public dep: SomeDep) { instances.set(Object.getPrototypeOf(this).constructor, this); }
|
constructor(public dep: SomeDep) {
|
||||||
|
instances.set(Object.getPrototypeOf(this).constructor, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({templateUrl: './jit_summaries.html'})
|
@Component({templateUrl: './jit_summaries.html'})
|
||||||
|
@ -36,7 +38,9 @@ export class SomeDirective extends Base {
|
||||||
|
|
||||||
@Pipe({name: 'somePipe'})
|
@Pipe({name: 'somePipe'})
|
||||||
export class SomePipe extends Base {
|
export class SomePipe extends Base {
|
||||||
transform(value: any) { return value; }
|
transform(value: any) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ApplicationRef, NgModule, forwardRef} from '@angular/core';
|
import {ApplicationRef, forwardRef, NgModule} from '@angular/core';
|
||||||
import {FormsModule} from '@angular/forms';
|
import {FormsModule} from '@angular/forms';
|
||||||
import {ServerModule} from '@angular/platform-server';
|
import {ServerModule} from '@angular/platform-server';
|
||||||
import {FlatModule} from 'flat_module';
|
import {FlatModule} from 'flat_module';
|
||||||
|
|
|
@ -19,24 +19,26 @@ export class ServiceUsingLibModule {
|
||||||
|
|
||||||
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
|
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
|
||||||
export class SomeDirectiveInRootModule {
|
export class SomeDirectiveInRootModule {
|
||||||
@Input()
|
@Input() someDir: string;
|
||||||
someDir: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
|
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
|
||||||
export class SomeDirectiveInLibModule {
|
export class SomeDirectiveInLibModule {
|
||||||
@Input()
|
@Input() someDir: string;
|
||||||
someDir: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Pipe({name: 'somePipe'})
|
@Pipe({name: 'somePipe'})
|
||||||
export class SomePipeInRootModule {
|
export class SomePipeInRootModule {
|
||||||
transform(value: string): any { return `transformed ${value}`; }
|
transform(value: string): any {
|
||||||
|
return `transformed ${value}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Pipe({name: 'somePipe'})
|
@Pipe({name: 'somePipe'})
|
||||||
export class SomePipeInLibModule {
|
export class SomePipeInLibModule {
|
||||||
transform(value: string): any { return `transformed ${value}`; }
|
transform(value: string): any {
|
||||||
|
return `transformed ${value}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({selector: 'comp', template: `<div [someDir]="'someValue' | somePipe"></div>`})
|
@Component({selector: 'comp', template: `<div [someDir]="'someValue' | somePipe"></div>`})
|
||||||
|
@ -66,8 +68,8 @@ export class SomeLibModule {
|
||||||
return {
|
return {
|
||||||
ngModule: SomeLibModule,
|
ngModule: SomeLibModule,
|
||||||
providers: [
|
providers: [
|
||||||
ServiceUsingLibModule, provideValueWithEntryComponents(
|
ServiceUsingLibModule,
|
||||||
[{a: 'b', component: CompUsingLibModuleDirectiveAndPipe}])
|
provideValueWithEntryComponents([{a: 'b', component: CompUsingLibModuleDirectiveAndPipe}])
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {TestBed} from '@angular/core/testing';
|
import {TestBed} from '@angular/core/testing';
|
||||||
import {ServerTestingModule, platformServerTesting} from '@angular/platform-server/testing';
|
import {platformServerTesting, ServerTestingModule} from '@angular/platform-server/testing';
|
||||||
|
|
||||||
import {SomeDep, SomeDirective, SomeModule, SomePipe, SomePrivateComponent, SomeService, expectInstanceCreated} from '../src/jit_summaries';
|
import {expectInstanceCreated, SomeDep, SomeDirective, SomeModule, SomePipe, SomePrivateComponent, SomeService} from '../src/jit_summaries';
|
||||||
import {SomeModuleNgSummary} from '../src/jit_summaries.ngsummary';
|
import {SomeModuleNgSummary} from '../src/jit_summaries.ngsummary';
|
||||||
|
|
||||||
describe('Jit Summaries', () => {
|
describe('Jit Summaries', () => {
|
||||||
|
@ -18,7 +18,9 @@ describe('Jit Summaries', () => {
|
||||||
TestBed.initTestEnvironment(ServerTestingModule, platformServerTesting(), SomeModuleNgSummary);
|
TestBed.initTestEnvironment(ServerTestingModule, platformServerTesting(), SomeModuleNgSummary);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => { TestBed.resetTestEnvironment(); });
|
afterEach(() => {
|
||||||
|
TestBed.resetTestEnvironment();
|
||||||
|
});
|
||||||
|
|
||||||
it('should use directive metadata from summaries', () => {
|
it('should use directive metadata from summaries', () => {
|
||||||
@Component({template: '<div someDir></div>'})
|
@Component({template: '<div someDir></div>'})
|
||||||
|
|
|
@ -10,7 +10,7 @@ import './init';
|
||||||
import {ComponentUsingThirdParty} from '../src/comp_using_3rdp';
|
import {ComponentUsingThirdParty} from '../src/comp_using_3rdp';
|
||||||
import {ComponentUsingFlatModule} from '../src/comp_using_flat_module';
|
import {ComponentUsingFlatModule} from '../src/comp_using_flat_module';
|
||||||
import {MainModule} from '../src/module';
|
import {MainModule} from '../src/module';
|
||||||
import {CompUsingLibModuleDirectiveAndPipe, CompUsingRootModuleDirectiveAndPipe, SOME_TOKEN, ServiceUsingLibModule, SomeLibModule, SomeService} from '../src/module_fixtures';
|
import {CompUsingLibModuleDirectiveAndPipe, CompUsingRootModuleDirectiveAndPipe, ServiceUsingLibModule, SOME_TOKEN, SomeLibModule, SomeService} from '../src/module_fixtures';
|
||||||
|
|
||||||
import {createComponent, createModule} from './util';
|
import {createComponent, createModule} from './util';
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ describe('child queries', () => {
|
||||||
debugElement.query(By.directive(CompWithChildQuery));
|
debugElement.query(By.directive(CompWithChildQuery));
|
||||||
expect(childQueryCompFixture.componentInstance.child).toBeDefined();
|
expect(childQueryCompFixture.componentInstance.child).toBeDefined();
|
||||||
expect(childQueryCompFixture.componentInstance.child instanceof CompForChildQuery).toBe(true);
|
expect(childQueryCompFixture.componentInstance.child instanceof CompForChildQuery).toBe(true);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support compiling children queries', () => {
|
it('should support compiling children queries', () => {
|
||||||
|
|
|
@ -22,7 +22,12 @@ import {createProgram, readConfiguration} from '@angular/compiler-cli';
|
||||||
* properly read and wrote.
|
* properly read and wrote.
|
||||||
*/
|
*/
|
||||||
function main() {
|
function main() {
|
||||||
Promise.resolve().then(() => lazyRoutesTest()).then(() => { process.exit(0); }).catch((err) => {
|
Promise.resolve()
|
||||||
|
.then(() => lazyRoutesTest())
|
||||||
|
.then(() => {
|
||||||
|
process.exit(0);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
console.error(err.stack);
|
console.error(err.stack);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
@ -36,7 +41,8 @@ function lazyRoutesTest() {
|
||||||
const host = ts.createCompilerHost(config.options, true);
|
const host = ts.createCompilerHost(config.options, true);
|
||||||
const program = createProgram({
|
const program = createProgram({
|
||||||
rootNames: config.rootNames,
|
rootNames: config.rootNames,
|
||||||
options: config.options, host,
|
options: config.options,
|
||||||
|
host,
|
||||||
});
|
});
|
||||||
|
|
||||||
config.options.basePath = basePath;
|
config.options.basePath = basePath;
|
||||||
|
|
|
@ -35,7 +35,8 @@ export function translateDiagnostics(
|
||||||
const fileName = span.start.file.url;
|
const fileName = span.start.file.url;
|
||||||
ng.push({
|
ng.push({
|
||||||
messageText: diagnosticMessageToString(diagnostic.messageText),
|
messageText: diagnosticMessageToString(diagnostic.messageText),
|
||||||
category: diagnostic.category, span,
|
category: diagnostic.category,
|
||||||
|
span,
|
||||||
source: SOURCE,
|
source: SOURCE,
|
||||||
code: DEFAULT_ERROR_CODE
|
code: DEFAULT_ERROR_CODE
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,4 +16,4 @@ to the language service.
|
||||||
*/
|
*/
|
||||||
export {MetadataCollector, ModuleMetadata} from './metadata';
|
export {MetadataCollector, ModuleMetadata} from './metadata';
|
||||||
export {CompilerOptions} from './transformers/api';
|
export {CompilerOptions} from './transformers/api';
|
||||||
export {MetadataReaderCache, MetadataReaderHost, createMetadataReaderCache, readMetadata} from './transformers/metadata_reader';
|
export {createMetadataReaderCache, MetadataReaderCache, MetadataReaderHost, readMetadata} from './transformers/metadata_reader';
|
||||||
|
|
|
@ -47,7 +47,9 @@ export function main(
|
||||||
options,
|
options,
|
||||||
emitFlags,
|
emitFlags,
|
||||||
oldProgram,
|
oldProgram,
|
||||||
emitCallback: createEmitCallback(options), customTransformers, modifiedResourceFiles
|
emitCallback: createEmitCallback(options),
|
||||||
|
customTransformers,
|
||||||
|
modifiedResourceFiles
|
||||||
});
|
});
|
||||||
if (programReuse !== undefined) {
|
if (programReuse !== undefined) {
|
||||||
programReuse.program = program;
|
programReuse.program = program;
|
||||||
|
@ -100,9 +102,10 @@ function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|un
|
||||||
options.emitDecoratorMetadata = true;
|
options.emitDecoratorMetadata = true;
|
||||||
}
|
}
|
||||||
const tsickleHost: Pick<
|
const tsickleHost: Pick<
|
||||||
tsickle.TsickleHost, 'shouldSkipTsickleProcessing'|'pathToModuleName'|
|
tsickle.TsickleHost,
|
||||||
'shouldIgnoreWarningsForPath'|'fileNameToModuleId'|'googmodule'|'untyped'|
|
'shouldSkipTsickleProcessing'|'pathToModuleName'|'shouldIgnoreWarningsForPath'|
|
||||||
'convertIndexImportShorthand'|'transformDecorators'|'transformTypesToClosure'> = {
|
'fileNameToModuleId'|'googmodule'|'untyped'|'convertIndexImportShorthand'|
|
||||||
|
'transformDecorators'|'transformTypesToClosure'> = {
|
||||||
shouldSkipTsickleProcessing: (fileName) => /\.d\.ts$/.test(fileName) ||
|
shouldSkipTsickleProcessing: (fileName) => /\.d\.ts$/.test(fileName) ||
|
||||||
// View Engine's generated files were never intended to be processed with tsickle.
|
// View Engine's generated files were never intended to be processed with tsickle.
|
||||||
(!options.enableIvy && GENERATED_FILES.test(fileName)),
|
(!options.enableIvy && GENERATED_FILES.test(fileName)),
|
||||||
|
@ -111,7 +114,9 @@ function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|un
|
||||||
fileNameToModuleId: (fileName) => fileName,
|
fileNameToModuleId: (fileName) => fileName,
|
||||||
googmodule: false,
|
googmodule: false,
|
||||||
untyped: true,
|
untyped: true,
|
||||||
convertIndexImportShorthand: false, transformDecorators, transformTypesToClosure,
|
convertIndexImportShorthand: false,
|
||||||
|
transformDecorators,
|
||||||
|
transformTypesToClosure,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.annotateForClosureCompiler || options.annotationsAs === 'static fields') {
|
if (options.annotateForClosureCompiler || options.annotationsAs === 'static fields') {
|
||||||
|
@ -147,7 +152,9 @@ function createEmitCallback(options: api.CompilerOptions): api.TsEmitCallback|un
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NgcParsedConfiguration extends ParsedConfiguration { watch?: boolean; }
|
export interface NgcParsedConfiguration extends ParsedConfiguration {
|
||||||
|
watch?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export function readNgcCommandLineAndConfiguration(args: string[]): NgcParsedConfiguration {
|
export function readNgcCommandLineAndConfiguration(args: string[]): NgcParsedConfiguration {
|
||||||
const options: api.CompilerOptions = {};
|
const options: api.CompilerOptions = {};
|
||||||
|
@ -194,7 +201,8 @@ export function readCommandLineAndConfiguration(
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
project,
|
project,
|
||||||
rootNames: config.rootNames, options,
|
rootNames: config.rootNames,
|
||||||
|
options,
|
||||||
errors: config.errors,
|
errors: config.errors,
|
||||||
emitFlags: config.emitFlags
|
emitFlags: config.emitFlags
|
||||||
};
|
};
|
||||||
|
|
|
@ -47,8 +47,7 @@ function createSyntheticIndexHost<H extends ts.CompilerHost>(
|
||||||
|
|
||||||
newHost.writeFile =
|
newHost.writeFile =
|
||||||
(fileName: string, data: string, writeByteOrderMark: boolean,
|
(fileName: string, data: string, writeByteOrderMark: boolean,
|
||||||
onError: ((message: string) => void) | undefined,
|
onError: ((message: string) => void)|undefined, sourceFiles: Readonly<ts.SourceFile>[]) => {
|
||||||
sourceFiles: Readonly<ts.SourceFile>[]) => {
|
|
||||||
delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
delegate.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles);
|
||||||
if (fileName.match(DTS) && sourceFiles && sourceFiles.length == 1 &&
|
if (fileName.match(DTS) && sourceFiles && sourceFiles.length == 1 &&
|
||||||
path.normalize(sourceFiles[0].fileName) === normalSyntheticIndexName) {
|
path.normalize(sourceFiles[0].fileName) === normalSyntheticIndexName) {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import * as ts from 'typescript';
|
||||||
import {MetadataCache} from '../transformers/metadata_cache';
|
import {MetadataCache} from '../transformers/metadata_cache';
|
||||||
|
|
||||||
import {MetadataCollector} from './collector';
|
import {MetadataCollector} from './collector';
|
||||||
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, METADATA_VERSION, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataObject, MetadataSymbolicExpression, MetadataSymbolicReferenceExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isInterfaceMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicCallExpression, isMetadataSymbolicExpression, isMethodMetadata} from './schema';
|
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isInterfaceMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicCallExpression, isMetadataSymbolicExpression, isMethodMetadata, MemberMetadata, METADATA_VERSION, MetadataEntry, MetadataError, MetadataMap, MetadataObject, MetadataSymbolicExpression, MetadataSymbolicReferenceExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata} from './schema';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,9 @@ interface Symbol {
|
||||||
privateName?: string;
|
privateName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BundleEntries { [name: string]: MetadataEntry; }
|
export interface BundleEntries {
|
||||||
|
[name: string]: MetadataEntry;
|
||||||
|
}
|
||||||
|
|
||||||
export interface BundlePrivateEntry {
|
export interface BundlePrivateEntry {
|
||||||
privateName: string;
|
privateName: string;
|
||||||
|
@ -121,7 +123,9 @@ export class MetadataBundler {
|
||||||
metadata: {
|
metadata: {
|
||||||
__symbolic: 'module',
|
__symbolic: 'module',
|
||||||
version: METADATA_VERSION,
|
version: METADATA_VERSION,
|
||||||
exports: exports.length ? exports : undefined, metadata, origins,
|
exports: exports.length ? exports : undefined,
|
||||||
|
metadata,
|
||||||
|
origins,
|
||||||
importAs: this.importAs!
|
importAs: this.importAs!
|
||||||
},
|
},
|
||||||
privates
|
privates
|
||||||
|
@ -466,8 +470,8 @@ export class MetadataBundler {
|
||||||
}
|
}
|
||||||
|
|
||||||
private convertExpression(
|
private convertExpression(
|
||||||
moduleName: string, value: MetadataSymbolicExpression|MetadataError|null|
|
moduleName: string, value: MetadataSymbolicExpression|MetadataError|null|undefined):
|
||||||
undefined): MetadataSymbolicExpression|MetadataError|undefined|null {
|
MetadataSymbolicExpression|MetadataError|undefined|null {
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (value.__symbolic) {
|
switch (value.__symbolic) {
|
||||||
case 'error':
|
case 'error':
|
||||||
|
@ -487,7 +491,8 @@ export class MetadataBundler {
|
||||||
message: value.message,
|
message: value.message,
|
||||||
line: value.line,
|
line: value.line,
|
||||||
character: value.character,
|
character: value.character,
|
||||||
context: value.context, module
|
context: value.context,
|
||||||
|
module
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {Evaluator, errorSymbol, recordMapEntry} from './evaluator';
|
import {errorSymbol, Evaluator, recordMapEntry} from './evaluator';
|
||||||
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, InterfaceMetadata, METADATA_VERSION, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema';
|
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, InterfaceMetadata, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata, MemberMetadata, METADATA_VERSION, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata} from './schema';
|
||||||
import {Symbols} from './symbols';
|
import {Symbols} from './symbols';
|
||||||
|
|
||||||
const isStatic = (node: ts.Declaration) =>
|
const isStatic = (node: ts.Declaration) =>
|
||||||
|
@ -88,9 +88,9 @@ export class MetadataCollector {
|
||||||
return errorSymbol(message, node, context, sourceFile);
|
return errorSymbol(message, node, context, sourceFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
function maybeGetSimpleFunction(
|
function maybeGetSimpleFunction(functionDeclaration: ts.FunctionDeclaration|
|
||||||
functionDeclaration: ts.FunctionDeclaration |
|
ts.MethodDeclaration): {func: FunctionMetadata, name: string}|
|
||||||
ts.MethodDeclaration): {func: FunctionMetadata, name: string}|undefined {
|
undefined {
|
||||||
if (functionDeclaration.name && functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
|
if (functionDeclaration.name && functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
|
||||||
const nameNode = <ts.Identifier>functionDeclaration.name;
|
const nameNode = <ts.Identifier>functionDeclaration.name;
|
||||||
const functionName = nameNode.text;
|
const functionName = nameNode.text;
|
||||||
|
@ -119,8 +119,8 @@ export class MetadataCollector {
|
||||||
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
|
||||||
const result: ClassMetadata = {__symbolic: 'class'};
|
const result: ClassMetadata = {__symbolic: 'class'};
|
||||||
|
|
||||||
function getDecorators(decorators: ReadonlyArray<ts.Decorator>| undefined):
|
function getDecorators(decorators: ReadonlyArray<ts.Decorator>|
|
||||||
MetadataSymbolicExpression[]|undefined {
|
undefined): MetadataSymbolicExpression[]|undefined {
|
||||||
if (decorators && decorators.length)
|
if (decorators && decorators.length)
|
||||||
return decorators.map(decorator => objFromDecorator(decorator));
|
return decorators.map(decorator => objFromDecorator(decorator));
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -189,10 +189,9 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
const methodDecorators = getDecorators(method.decorators);
|
const methodDecorators = getDecorators(method.decorators);
|
||||||
const parameters = method.parameters;
|
const parameters = method.parameters;
|
||||||
const parameterDecoratorData:
|
const parameterDecoratorData: ((MetadataSymbolicExpression | MetadataError)[]|
|
||||||
((MetadataSymbolicExpression | MetadataError)[] | undefined)[] = [];
|
undefined)[] = [];
|
||||||
const parametersData:
|
const parametersData: (MetadataSymbolicReferenceExpression|MetadataError|
|
||||||
(MetadataSymbolicReferenceExpression | MetadataError |
|
|
||||||
MetadataSymbolicSelectExpression|null)[] = [];
|
MetadataSymbolicSelectExpression|null)[] = [];
|
||||||
let hasDecoratorData: boolean = false;
|
let hasDecoratorData: boolean = false;
|
||||||
let hasParameterData: boolean = false;
|
let hasParameterData: boolean = false;
|
||||||
|
@ -282,15 +281,14 @@ export class MetadataCollector {
|
||||||
ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export;
|
ts.getCombinedModifierFlags(node as ts.Declaration) & ts.ModifierFlags.Export;
|
||||||
const isExportedIdentifier = (identifier?: ts.Identifier) =>
|
const isExportedIdentifier = (identifier?: ts.Identifier) =>
|
||||||
identifier && exportMap.has(identifier.text);
|
identifier && exportMap.has(identifier.text);
|
||||||
const isExported =
|
const isExported = (node: ts.FunctionDeclaration|ts.ClassDeclaration|ts.TypeAliasDeclaration|
|
||||||
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.TypeAliasDeclaration |
|
|
||||||
ts.InterfaceDeclaration|ts.EnumDeclaration) =>
|
ts.InterfaceDeclaration|ts.EnumDeclaration) =>
|
||||||
isExport(node) || isExportedIdentifier(node.name);
|
isExport(node) || isExportedIdentifier(node.name);
|
||||||
const exportedIdentifierName = (identifier?: ts.Identifier) =>
|
const exportedIdentifierName = (identifier?: ts.Identifier) =>
|
||||||
identifier && (exportMap.get(identifier.text) || identifier.text);
|
identifier && (exportMap.get(identifier.text) || identifier.text);
|
||||||
const exportedName =
|
const exportedName = (node: ts.FunctionDeclaration|ts.ClassDeclaration|
|
||||||
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
|
ts.InterfaceDeclaration|ts.TypeAliasDeclaration|ts.EnumDeclaration) =>
|
||||||
ts.TypeAliasDeclaration | ts.EnumDeclaration) => exportedIdentifierName(node.name);
|
exportedIdentifierName(node.name);
|
||||||
|
|
||||||
|
|
||||||
// Pre-declare classes and functions
|
// Pre-declare classes and functions
|
||||||
|
@ -419,8 +417,8 @@ export class MetadataCollector {
|
||||||
if (name) {
|
if (name) {
|
||||||
if (!metadata) metadata = {};
|
if (!metadata) metadata = {};
|
||||||
// TODO(alxhub): The literal here is not valid FunctionMetadata.
|
// TODO(alxhub): The literal here is not valid FunctionMetadata.
|
||||||
metadata[name] = maybeFunc ? recordEntry(maybeFunc.func, node) :
|
metadata[name] =
|
||||||
({ __symbolic: 'function' } as any);
|
maybeFunc ? recordEntry(maybeFunc.func, node) : ({__symbolic: 'function'} as any);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -456,7 +454,8 @@ export class MetadataCollector {
|
||||||
operator: '+',
|
operator: '+',
|
||||||
left: {
|
left: {
|
||||||
__symbolic: 'select',
|
__symbolic: 'select',
|
||||||
expression: recordEntry({__symbolic: 'reference', name: enumName}, node), name
|
expression: recordEntry({__symbolic: 'reference', name: enumName}, node),
|
||||||
|
name
|
||||||
},
|
},
|
||||||
} as any;
|
} as any;
|
||||||
} else {
|
} else {
|
||||||
|
@ -555,7 +554,8 @@ export class MetadataCollector {
|
||||||
}
|
}
|
||||||
const result: ModuleMetadata = {
|
const result: ModuleMetadata = {
|
||||||
__symbolic: 'module',
|
__symbolic: 'module',
|
||||||
version: this.options.version || METADATA_VERSION, metadata
|
version: this.options.version || METADATA_VERSION,
|
||||||
|
metadata
|
||||||
};
|
};
|
||||||
if (sourceFile.moduleName) result.importAs = sourceFile.moduleName;
|
if (sourceFile.moduleName) result.importAs = sourceFile.moduleName;
|
||||||
if (exports) result.exports = exports;
|
if (exports) result.exports = exports;
|
||||||
|
@ -570,8 +570,7 @@ function validateMetadata(
|
||||||
metadata: {[name: string]: MetadataEntry}) {
|
metadata: {[name: string]: MetadataEntry}) {
|
||||||
let locals: Set<string> = new Set(['Array', 'Object', 'Set', 'Map', 'string', 'number', 'any']);
|
let locals: Set<string> = new Set(['Array', 'Object', 'Set', 'Map', 'string', 'number', 'any']);
|
||||||
|
|
||||||
function validateExpression(
|
function validateExpression(expression: MetadataValue|MetadataSymbolicExpression|MetadataError) {
|
||||||
expression: MetadataValue | MetadataSymbolicExpression | MetadataError) {
|
|
||||||
if (!expression) {
|
if (!expression) {
|
||||||
return;
|
return;
|
||||||
} else if (Array.isArray(expression)) {
|
} else if (Array.isArray(expression)) {
|
||||||
|
@ -688,12 +687,13 @@ function validateMetadata(
|
||||||
function reportError(error: MetadataError) {
|
function reportError(error: MetadataError) {
|
||||||
const node = nodeMap.get(error);
|
const node = nodeMap.get(error);
|
||||||
if (shouldReportNode(node)) {
|
if (shouldReportNode(node)) {
|
||||||
const lineInfo = error.line != undefined ?
|
const lineInfo = error.line != undefined ? error.character != undefined ?
|
||||||
error.character != undefined ? `:${error.line + 1}:${error.character + 1}` :
|
`:${error.line + 1}:${error.character + 1}` :
|
||||||
`:${error.line + 1}` :
|
`:${error.line + 1}` :
|
||||||
'';
|
'';
|
||||||
throw new Error(
|
throw new Error(`${sourceFile.fileName}${
|
||||||
`${sourceFile.fileName}${lineInfo}: Metadata collected contains an error that will be reported at runtime: ${expandedMessage(error)}.\n ${JSON.stringify(error)}`);
|
lineInfo}: Metadata collected contains an error that will be reported at runtime: ${
|
||||||
|
expandedMessage(error)}.\n ${JSON.stringify(error)}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,8 +708,9 @@ function validateMetadata(
|
||||||
if (shouldReportNode(node)) {
|
if (shouldReportNode(node)) {
|
||||||
if (node) {
|
if (node) {
|
||||||
const {line, character} = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
const {line, character} = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
||||||
throw new Error(
|
throw new Error(`${sourceFile.fileName}:${line + 1}:${
|
||||||
`${sourceFile.fileName}:${line + 1}:${character + 1}: Error encountered in metadata generated for exported symbol '${name}': \n ${e.message}`);
|
character + 1}: Error encountered in metadata generated for exported symbol '${
|
||||||
|
name}': \n ${e.message}`);
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Error encountered in metadata generated for exported symbol ${name}: \n ${e.message}`);
|
`Error encountered in metadata generated for exported symbol ${name}: \n ${e.message}`);
|
||||||
|
@ -752,7 +753,8 @@ function expandedMessage(error: any): string {
|
||||||
switch (error.message) {
|
switch (error.message) {
|
||||||
case 'Reference to non-exported class':
|
case 'Reference to non-exported class':
|
||||||
if (error.context && error.context.className) {
|
if (error.context && error.context.className) {
|
||||||
return `Reference to a non-exported class ${error.context.className}. Consider exporting the class`;
|
return `Reference to a non-exported class ${
|
||||||
|
error.context.className}. Consider exporting the class`;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Variable not initialized':
|
case 'Variable not initialized':
|
||||||
|
@ -771,7 +773,8 @@ function expandedMessage(error: any): string {
|
||||||
'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function';
|
'unction calls are not supported. Consider replacing the function or lambda with a reference to an exported function';
|
||||||
case 'Reference to a local symbol':
|
case 'Reference to a local symbol':
|
||||||
if (error.context && error.context.name) {
|
if (error.context && error.context.name) {
|
||||||
return `Reference to a local (non-exported) symbol '${error.context.name}'. Consider exporting the symbol`;
|
return `Reference to a local (non-exported) symbol '${
|
||||||
|
error.context.name}'. Consider exporting the symbol`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return error.message;
|
return error.message;
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {CollectorOptions} from './collector';
|
import {CollectorOptions} from './collector';
|
||||||
import {ClassMetadata, FunctionMetadata, InterfaceMetadata, MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataSourceLocationInfo, MetadataSymbolicCallExpression, MetadataValue, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression} from './schema';
|
import {ClassMetadata, FunctionMetadata, InterfaceMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataImportDefaultReference, isMetadataImportedSymbolReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression, MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataSourceLocationInfo, MetadataSymbolicCallExpression, MetadataValue} from './schema';
|
||||||
import {Symbols} from './symbols';
|
import {Symbols} from './symbols';
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,7 +46,8 @@ export function recordMapEntry<T extends MetadataEntry>(
|
||||||
sourceFile?: ts.SourceFile) {
|
sourceFile?: ts.SourceFile) {
|
||||||
if (!nodeMap.has(entry)) {
|
if (!nodeMap.has(entry)) {
|
||||||
nodeMap.set(entry, node);
|
nodeMap.set(entry, node);
|
||||||
if (node && (isMetadataImportedSymbolReferenceExpression(entry) ||
|
if (node &&
|
||||||
|
(isMetadataImportedSymbolReferenceExpression(entry) ||
|
||||||
isMetadataImportDefaultReference(entry)) &&
|
isMetadataImportDefaultReference(entry)) &&
|
||||||
entry.line == null) {
|
entry.line == null) {
|
||||||
const info = sourceInfo(node, sourceFile);
|
const info = sourceInfo(node, sourceFile);
|
||||||
|
|
|
@ -49,12 +49,16 @@ export function isClassMetadata(value: any): value is ClassMetadata {
|
||||||
return value && value.__symbolic === 'class';
|
return value && value.__symbolic === 'class';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InterfaceMetadata { __symbolic: 'interface'; }
|
export interface InterfaceMetadata {
|
||||||
|
__symbolic: 'interface';
|
||||||
|
}
|
||||||
export function isInterfaceMetadata(value: any): value is InterfaceMetadata {
|
export function isInterfaceMetadata(value: any): value is InterfaceMetadata {
|
||||||
return value && value.__symbolic === 'interface';
|
return value && value.__symbolic === 'interface';
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MetadataMap { [name: string]: MemberMetadata[]; }
|
export interface MetadataMap {
|
||||||
|
[name: string]: MemberMetadata[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface MemberMetadata {
|
export interface MemberMetadata {
|
||||||
__symbolic: 'constructor'|'method'|'property';
|
__symbolic: 'constructor'|'method'|'property';
|
||||||
|
@ -99,21 +103,23 @@ export function isFunctionMetadata(value: any): value is FunctionMetadata {
|
||||||
return value && value.__symbolic === 'function';
|
return value && value.__symbolic === 'function';
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetadataValue = string | number | boolean | undefined | null | MetadataObject |
|
export type MetadataValue = string|number|boolean|undefined|null|MetadataObject|MetadataArray|
|
||||||
MetadataArray | MetadataSymbolicExpression | MetadataSymbolicReferenceExpression |
|
MetadataSymbolicExpression|MetadataSymbolicReferenceExpression|MetadataSymbolicBinaryExpression|
|
||||||
MetadataSymbolicBinaryExpression | MetadataSymbolicIndexExpression |
|
MetadataSymbolicIndexExpression|MetadataSymbolicCallExpression|MetadataSymbolicPrefixExpression|
|
||||||
MetadataSymbolicCallExpression | MetadataSymbolicPrefixExpression |
|
MetadataSymbolicIfExpression|MetadataSymbolicSpreadExpression|MetadataSymbolicSelectExpression|
|
||||||
MetadataSymbolicIfExpression | MetadataSymbolicSpreadExpression |
|
MetadataError;
|
||||||
MetadataSymbolicSelectExpression | MetadataError;
|
|
||||||
|
|
||||||
export interface MetadataObject { [name: string]: MetadataValue; }
|
export interface MetadataObject {
|
||||||
|
[name: string]: MetadataValue;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MetadataArray { [name: number]: MetadataValue; }
|
export interface MetadataArray {
|
||||||
|
[name: number]: MetadataValue;
|
||||||
|
}
|
||||||
|
|
||||||
export type MetadataSymbolicExpression = MetadataSymbolicBinaryExpression|
|
export type MetadataSymbolicExpression = MetadataSymbolicBinaryExpression|
|
||||||
MetadataSymbolicIndexExpression | MetadataSymbolicIndexExpression |
|
MetadataSymbolicIndexExpression|MetadataSymbolicIndexExpression|MetadataSymbolicCallExpression|
|
||||||
MetadataSymbolicCallExpression | MetadataSymbolicCallExpression |
|
MetadataSymbolicCallExpression|MetadataSymbolicPrefixExpression|MetadataSymbolicIfExpression|
|
||||||
MetadataSymbolicPrefixExpression | MetadataSymbolicIfExpression |
|
|
||||||
MetadataGlobalReferenceExpression|MetadataModuleReferenceExpression|
|
MetadataGlobalReferenceExpression|MetadataModuleReferenceExpression|
|
||||||
MetadataImportedSymbolReferenceExpression|MetadataImportedDefaultReferenceExpression|
|
MetadataImportedSymbolReferenceExpression|MetadataImportedDefaultReferenceExpression|
|
||||||
MetadataSymbolicSelectExpression|MetadataSymbolicSpreadExpression;
|
MetadataSymbolicSelectExpression|MetadataSymbolicSpreadExpression;
|
||||||
|
@ -234,8 +240,7 @@ export function isMetadataImportedSymbolReferenceExpression(value: any):
|
||||||
export interface MetadataImportedDefaultReferenceExpression extends MetadataSourceLocationInfo {
|
export interface MetadataImportedDefaultReferenceExpression extends MetadataSourceLocationInfo {
|
||||||
__symbolic: 'reference';
|
__symbolic: 'reference';
|
||||||
module: string;
|
module: string;
|
||||||
default:
|
default: boolean;
|
||||||
boolean;
|
|
||||||
arguments?: MetadataValue[];
|
arguments?: MetadataValue[];
|
||||||
}
|
}
|
||||||
export function isMetadataImportDefaultReference(value: any):
|
export function isMetadataImportDefaultReference(value: any):
|
||||||
|
@ -243,9 +248,9 @@ export function isMetadataImportDefaultReference(value: any):
|
||||||
return value && value.module && value.default && isMetadataSymbolicReferenceExpression(value);
|
return value && value.module && value.default && isMetadataSymbolicReferenceExpression(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MetadataSymbolicReferenceExpression = MetadataGlobalReferenceExpression |
|
export type MetadataSymbolicReferenceExpression =
|
||||||
MetadataModuleReferenceExpression | MetadataImportedSymbolReferenceExpression |
|
MetadataGlobalReferenceExpression|MetadataModuleReferenceExpression|
|
||||||
MetadataImportedDefaultReferenceExpression;
|
MetadataImportedSymbolReferenceExpression|MetadataImportedDefaultReferenceExpression;
|
||||||
export function isMetadataSymbolicReferenceExpression(value: any):
|
export function isMetadataSymbolicReferenceExpression(value: any):
|
||||||
value is MetadataSymbolicReferenceExpression {
|
value is MetadataSymbolicReferenceExpression {
|
||||||
return value && value.__symbolic === 'reference';
|
return value && value.__symbolic === 'reference';
|
||||||
|
|
|
@ -21,12 +21,16 @@ export class Symbols {
|
||||||
return (preferReference && this.references.get(name)) || this.symbols.get(name);
|
return (preferReference && this.references.get(name)) || this.symbols.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
define(name: string, value: MetadataValue) { this.symbols.set(name, value); }
|
define(name: string, value: MetadataValue) {
|
||||||
|
this.symbols.set(name, value);
|
||||||
|
}
|
||||||
defineReference(name: string, value: MetadataSymbolicReferenceExpression) {
|
defineReference(name: string, value: MetadataSymbolicReferenceExpression) {
|
||||||
this.references.set(name, value);
|
this.references.set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
has(name: string): boolean { return this.symbols.has(name); }
|
has(name: string): boolean {
|
||||||
|
return this.symbols.has(name);
|
||||||
|
}
|
||||||
|
|
||||||
private get symbols(): Map<string, MetadataValue> {
|
private get symbols(): Map<string, MetadataValue> {
|
||||||
let result = this._symbols;
|
let result = this._symbols;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, ParseError, ParseSourceFile, ParseTemplateOptions, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, SchemaMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr, compileComponentFromMetadata, makeBindingParser, parseTemplate} from '@angular/compiler';
|
import {compileComponentFromMetadata, ConstantPool, CssSelector, DEFAULT_INTERPOLATION_CONFIG, DomElementSchemaRegistry, Expression, ExternalExpr, Identifiers, InterpolationConfig, LexerRange, makeBindingParser, ParseError, ParseSourceFile, parseTemplate, ParseTemplateOptions, R3ComponentMetadata, R3FactoryTarget, R3TargetBinder, SchemaMetadata, SelectorMatcher, Statement, TmplAstNode, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {CycleAnalyzer} from '../../cycles';
|
import {CycleAnalyzer} from '../../cycles';
|
||||||
|
@ -15,7 +15,7 @@ import {absoluteFrom, relative} from '../../file_system';
|
||||||
import {DefaultImportRecorder, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
|
import {DefaultImportRecorder, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {DependencyTracker} from '../../incremental/api';
|
import {DependencyTracker} from '../../incremental/api';
|
||||||
import {IndexingContext} from '../../indexer';
|
import {IndexingContext} from '../../indexer';
|
||||||
import {DirectiveMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, extractDirectiveGuards} from '../../metadata';
|
import {DirectiveMeta, extractDirectiveGuards, InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata';
|
||||||
import {flattenInheritedDirectiveMetadata} from '../../metadata/src/inheritance';
|
import {flattenInheritedDirectiveMetadata} from '../../metadata/src/inheritance';
|
||||||
import {EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
import {EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
||||||
|
@ -323,7 +323,8 @@ export class ComponentDecoratorHandler implements
|
||||||
// analyzed and the full compilation scope for the component can be realized.
|
// analyzed and the full compilation scope for the component can be realized.
|
||||||
animations,
|
animations,
|
||||||
viewProviders: wrappedViewProviders,
|
viewProviders: wrappedViewProviders,
|
||||||
i18nUseExternalIds: this.i18nUseExternalIds, relativeContextFilePath,
|
i18nUseExternalIds: this.i18nUseExternalIds,
|
||||||
|
relativeContextFilePath,
|
||||||
},
|
},
|
||||||
guards: extractDirectiveGuards(node, this.reflector),
|
guards: extractDirectiveGuards(node, this.reflector),
|
||||||
metadataStmt: generateSetClassMetadataCall(
|
metadataStmt: generateSetClassMetadataCall(
|
||||||
|
@ -353,7 +354,8 @@ export class ComponentDecoratorHandler implements
|
||||||
outputs: analysis.meta.outputs,
|
outputs: analysis.meta.outputs,
|
||||||
queries: analysis.meta.queries.map(query => query.propertyName),
|
queries: analysis.meta.queries.map(query => query.propertyName),
|
||||||
isComponent: true,
|
isComponent: true,
|
||||||
baseClass: analysis.baseClass, ...analysis.guards,
|
baseClass: analysis.baseClass,
|
||||||
|
...analysis.guards,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.injectableRegistry.registerInjectable(node);
|
this.injectableRegistry.registerInjectable(node);
|
||||||
|
@ -415,8 +417,8 @@ export class ComponentDecoratorHandler implements
|
||||||
}
|
}
|
||||||
for (const {name, ref} of scope.compilation.pipes) {
|
for (const {name, ref} of scope.compilation.pipes) {
|
||||||
if (!ts.isClassDeclaration(ref.node)) {
|
if (!ts.isClassDeclaration(ref.node)) {
|
||||||
throw new Error(
|
throw new Error(`Unexpected non-class declaration ${
|
||||||
`Unexpected non-class declaration ${ts.SyntaxKind[ref.node.kind]} for pipe ${ref.debugName}`);
|
ts.SyntaxKind[ref.node.kind]} for pipe ${ref.debugName}`);
|
||||||
}
|
}
|
||||||
pipes.set(name, ref as Reference<ClassDeclaration<ts.ClassDeclaration>>);
|
pipes.set(name, ref as Reference<ClassDeclaration<ts.ClassDeclaration>>);
|
||||||
}
|
}
|
||||||
|
@ -775,7 +777,8 @@ export class ComponentDecoratorHandler implements
|
||||||
parseTemplate(templateStr, templateUrl, {
|
parseTemplate(templateStr, templateUrl, {
|
||||||
preserveWhitespaces,
|
preserveWhitespaces,
|
||||||
interpolationConfig: interpolation,
|
interpolationConfig: interpolation,
|
||||||
range: templateRange, escapedString,
|
range: templateRange,
|
||||||
|
escapedString,
|
||||||
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -795,7 +798,8 @@ export class ComponentDecoratorHandler implements
|
||||||
const {nodes: diagNodes} = parseTemplate(templateStr, templateUrl, {
|
const {nodes: diagNodes} = parseTemplate(templateStr, templateUrl, {
|
||||||
preserveWhitespaces: true,
|
preserveWhitespaces: true,
|
||||||
interpolationConfig: interpolation,
|
interpolationConfig: interpolation,
|
||||||
range: templateRange, escapedString,
|
range: templateRange,
|
||||||
|
escapedString,
|
||||||
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
enableI18nLegacyMessageIdFormat: this.enableI18nLegacyMessageIdFormat,
|
||||||
leadingTriviaChars: [],
|
leadingTriviaChars: [],
|
||||||
});
|
});
|
||||||
|
@ -808,7 +812,8 @@ export class ComponentDecoratorHandler implements
|
||||||
styles,
|
styles,
|
||||||
ngContentSelectors,
|
ngContentSelectors,
|
||||||
errors,
|
errors,
|
||||||
template: templateStr, templateUrl,
|
template: templateStr,
|
||||||
|
templateUrl,
|
||||||
isInline: component.has('template'),
|
isInline: component.has('template'),
|
||||||
file: new ParseSourceFile(templateStr, templateUrl),
|
file: new ParseSourceFile(templateStr, templateUrl),
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,9 +36,13 @@ export function getProviderDiagnostics(
|
||||||
const contextNode = provider.getOriginForDiagnostics(providersDeclaration);
|
const contextNode = provider.getOriginForDiagnostics(providersDeclaration);
|
||||||
diagnostics.push(makeDiagnostic(
|
diagnostics.push(makeDiagnostic(
|
||||||
ErrorCode.UNDECORATED_PROVIDER, contextNode,
|
ErrorCode.UNDECORATED_PROVIDER, contextNode,
|
||||||
`The class '${provider.node.name.text}' cannot be created via dependency injection, as it does not have an Angular decorator. This will result in an error at runtime.
|
`The class '${
|
||||||
|
provider.node.name
|
||||||
|
.text}' cannot be created via dependency injection, as it does not have an Angular decorator. This will result in an error at runtime.
|
||||||
|
|
||||||
Either add the @Injectable() decorator to '${provider.node.name.text}', or configure a different provider (such as a provider with 'useFactory').
|
Either add the @Injectable() decorator to '${
|
||||||
|
provider.node.name
|
||||||
|
.text}', or configure a different provider (such as a provider with 'useFactory').
|
||||||
`,
|
`,
|
||||||
[{node: provider.node, messageText: `'${provider.node.name.text}' is declared here.`}]));
|
[{node: provider.node, messageText: `'${provider.node.name.text}' is declared here.`}]));
|
||||||
}
|
}
|
||||||
|
@ -127,8 +131,10 @@ function getInheritedUndecoratedCtorDiagnostic(
|
||||||
|
|
||||||
return makeDiagnostic(
|
return makeDiagnostic(
|
||||||
ErrorCode.DIRECTIVE_INHERITS_UNDECORATED_CTOR, node.name,
|
ErrorCode.DIRECTIVE_INHERITS_UNDECORATED_CTOR, node.name,
|
||||||
`The ${dirOrComp.toLowerCase()} ${node.name.text} inherits its constructor from ${baseClassName}, ` +
|
`The ${dirOrComp.toLowerCase()} ${node.name.text} inherits its constructor from ${
|
||||||
|
baseClassName}, ` +
|
||||||
`but the latter does not have an Angular decorator of its own. Dependency injection will not be able to ` +
|
`but the latter does not have an Angular decorator of its own. Dependency injection will not be able to ` +
|
||||||
`resolve the parameters of ${baseClassName}'s constructor. Either add a @Directive decorator ` +
|
`resolve the parameters of ${
|
||||||
|
baseClassName}'s constructor. Either add a @Directive decorator ` +
|
||||||
`to ${baseClassName}, or add an explicit constructor to ${node.name.text}.`);
|
`to ${baseClassName}, or add an explicit constructor to ${node.name.text}.`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {ConstantPool, Expression, Identifiers, ParseError, ParsedHostBindings, R3DependencyMetadata, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, Statement, WrappedNodeExpr, compileDirectiveFromMetadata, makeBindingParser, parseHostBindings, verifyHostBindings} from '@angular/compiler';
|
import {compileDirectiveFromMetadata, ConstantPool, Expression, Identifiers, makeBindingParser, ParsedHostBindings, ParseError, parseHostBindings, R3DependencyMetadata, R3DirectiveMetadata, R3FactoryTarget, R3QueryMetadata, Statement, verifyHostBindings, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||||
|
@ -14,7 +14,7 @@ import {DefaultImportRecorder, Reference} from '../../imports';
|
||||||
import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata';
|
import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../metadata';
|
||||||
import {extractDirectiveGuards} from '../../metadata/src/util';
|
import {extractDirectiveGuards} from '../../metadata/src/util';
|
||||||
import {DynamicValue, EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
import {DynamicValue, EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
|
import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, filterToMembersWithDecorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
||||||
import {LocalModuleScopeRegistry} from '../../scope';
|
import {LocalModuleScopeRegistry} from '../../scope';
|
||||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerFlags, HandlerPrecedence, ResolveResult} from '../../transform';
|
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerFlags, HandlerPrecedence, ResolveResult} from '../../transform';
|
||||||
|
|
||||||
|
@ -102,7 +102,8 @@ export class DirectiveDecoratorHandler implements
|
||||||
node, this.reflector, this.defaultImportRecorder, this.isCore,
|
node, this.reflector, this.defaultImportRecorder, this.isCore,
|
||||||
this.annotateForClosureCompiler),
|
this.annotateForClosureCompiler),
|
||||||
baseClass: readBaseClass(node, this.reflector, this.evaluator),
|
baseClass: readBaseClass(node, this.reflector, this.evaluator),
|
||||||
guards: extractDirectiveGuards(node, this.reflector), providersRequiringFactory
|
guards: extractDirectiveGuards(node, this.reflector),
|
||||||
|
providersRequiringFactory
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,7 +121,8 @@ export class DirectiveDecoratorHandler implements
|
||||||
outputs: analysis.meta.outputs,
|
outputs: analysis.meta.outputs,
|
||||||
queries: analysis.meta.queries.map(query => query.propertyName),
|
queries: analysis.meta.queries.map(query => query.propertyName),
|
||||||
isComponent: false,
|
isComponent: false,
|
||||||
baseClass: analysis.baseClass, ...analysis.guards,
|
baseClass: analysis.baseClass,
|
||||||
|
...analysis.guards,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.injectableRegistry.registerInjectable(node);
|
this.injectableRegistry.registerInjectable(node);
|
||||||
|
@ -176,9 +178,8 @@ export class DirectiveDecoratorHandler implements
|
||||||
export function extractDirectiveMetadata(
|
export function extractDirectiveMetadata(
|
||||||
clazz: ClassDeclaration, decorator: Readonly<Decorator|null>, reflector: ReflectionHost,
|
clazz: ClassDeclaration, decorator: Readonly<Decorator|null>, reflector: ReflectionHost,
|
||||||
evaluator: PartialEvaluator, defaultImportRecorder: DefaultImportRecorder, isCore: boolean,
|
evaluator: PartialEvaluator, defaultImportRecorder: DefaultImportRecorder, isCore: boolean,
|
||||||
flags: HandlerFlags, annotateForClosureCompiler: boolean,
|
flags: HandlerFlags, annotateForClosureCompiler: boolean, defaultSelector: string|null = null):
|
||||||
defaultSelector: string | null =
|
{decorator: Map<string, ts.Expression>, metadata: R3DirectiveMetadata}|undefined {
|
||||||
null): {decorator: Map<string, ts.Expression>, metadata: R3DirectiveMetadata}|undefined {
|
|
||||||
let directive: Map<string, ts.Expression>;
|
let directive: Map<string, ts.Expression>;
|
||||||
if (decorator === null || decorator.args === null || decorator.args.length === 0) {
|
if (decorator === null || decorator.args === null || decorator.args.length === 0) {
|
||||||
directive = new Map<string, ts.Expression>();
|
directive = new Map<string, ts.Expression>();
|
||||||
|
@ -220,7 +221,8 @@ export function extractDirectiveMetadata(
|
||||||
|
|
||||||
// And outputs.
|
// And outputs.
|
||||||
const outputsFromMeta = parseFieldToPropertyMapping(directive, 'outputs', evaluator);
|
const outputsFromMeta = parseFieldToPropertyMapping(directive, 'outputs', evaluator);
|
||||||
const outputsFromFields = parseDecoratedFields(
|
const outputsFromFields =
|
||||||
|
parseDecoratedFields(
|
||||||
filterToMembersWithDecorator(decoratedElements, 'Output', coreModule), evaluator,
|
filterToMembersWithDecorator(decoratedElements, 'Output', coreModule), evaluator,
|
||||||
resolveOutput) as {[field: string]: string};
|
resolveOutput) as {[field: string]: string};
|
||||||
// Construct the list of queries.
|
// Construct the list of queries.
|
||||||
|
@ -312,15 +314,24 @@ export function extractDirectiveMetadata(
|
||||||
|
|
||||||
const metadata: R3DirectiveMetadata = {
|
const metadata: R3DirectiveMetadata = {
|
||||||
name: clazz.name.text,
|
name: clazz.name.text,
|
||||||
deps: ctorDeps, host,
|
deps: ctorDeps,
|
||||||
|
host,
|
||||||
lifecycle: {
|
lifecycle: {
|
||||||
usesOnChanges,
|
usesOnChanges,
|
||||||
},
|
},
|
||||||
inputs: {...inputsFromMeta, ...inputsFromFields},
|
inputs: {...inputsFromMeta, ...inputsFromFields},
|
||||||
outputs: {...outputsFromMeta, ...outputsFromFields}, queries, viewQueries, selector,
|
outputs: {...outputsFromMeta, ...outputsFromFields},
|
||||||
fullInheritance: !!(flags & HandlerFlags.FULL_INHERITANCE), type, internalType,
|
queries,
|
||||||
|
viewQueries,
|
||||||
|
selector,
|
||||||
|
fullInheritance: !!(flags & HandlerFlags.FULL_INHERITANCE),
|
||||||
|
type,
|
||||||
|
internalType,
|
||||||
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
|
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
|
||||||
typeSourceSpan: createSourceSpan(clazz.name), usesInheritance, exportAs, providers
|
typeSourceSpan: createSourceSpan(clazz.name),
|
||||||
|
usesInheritance,
|
||||||
|
exportAs,
|
||||||
|
providers
|
||||||
};
|
};
|
||||||
return {decorator: directive, metadata};
|
return {decorator: directive, metadata};
|
||||||
}
|
}
|
||||||
|
@ -489,15 +500,13 @@ function parseFieldToPropertyMapping(
|
||||||
return EMPTY_OBJECT;
|
return EMPTY_OBJECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
return metaValues.reduce(
|
return metaValues.reduce((results, value) => {
|
||||||
(results, value) => {
|
|
||||||
// Either the value is 'field' or 'field: property'. In the first case, `property` will
|
// Either the value is 'field' or 'field: property'. In the first case, `property` will
|
||||||
// be undefined, in which case the field name should also be used as the property name.
|
// be undefined, in which case the field name should also be used as the property name.
|
||||||
const [field, property] = value.split(':', 2).map(str => str.trim());
|
const [field, property] = value.split(':', 2).map(str => str.trim());
|
||||||
results[field] = property || field;
|
results[field] = property || field;
|
||||||
return results;
|
return results;
|
||||||
},
|
}, {} as {[field: string]: string});
|
||||||
{} as{[field: string]: string});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -508,8 +517,7 @@ function parseDecoratedFields(
|
||||||
fields: {member: ClassMember, decorators: Decorator[]}[], evaluator: PartialEvaluator,
|
fields: {member: ClassMember, decorators: Decorator[]}[], evaluator: PartialEvaluator,
|
||||||
mapValueResolver: (publicName: string, internalName: string) =>
|
mapValueResolver: (publicName: string, internalName: string) =>
|
||||||
string | [string, string]): {[field: string]: string|[string, string]} {
|
string | [string, string]): {[field: string]: string|[string, string]} {
|
||||||
return fields.reduce(
|
return fields.reduce((results, field) => {
|
||||||
(results, field) => {
|
|
||||||
const fieldName = field.member.name;
|
const fieldName = field.member.name;
|
||||||
field.decorators.forEach(decorator => {
|
field.decorators.forEach(decorator => {
|
||||||
// The decorator either doesn't have an argument (@Input()) in which case the property
|
// The decorator either doesn't have an argument (@Input()) in which case the property
|
||||||
|
@ -528,12 +536,12 @@ function parseDecoratedFields(
|
||||||
// Too many arguments.
|
// Too many arguments.
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.DECORATOR_ARITY_WRONG, Decorator.nodeForError(decorator),
|
ErrorCode.DECORATOR_ARITY_WRONG, Decorator.nodeForError(decorator),
|
||||||
`@${decorator.name} can have at most one argument, got ${decorator.args.length} argument(s)`);
|
`@${decorator.name} can have at most one argument, got ${
|
||||||
|
decorator.args.length} argument(s)`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return results;
|
return results;
|
||||||
},
|
}, {} as {[field: string]: string | [string, string]});
|
||||||
{} as{[field: string]: string | [string, string]});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveInput(publicName: string, internalName: string): [string, string] {
|
function resolveInput(publicName: string, internalName: string): [string, string] {
|
||||||
|
@ -635,14 +643,16 @@ export function extractHostBindings(
|
||||||
bindings = parseHostBindings({});
|
bindings = parseHostBindings({});
|
||||||
}
|
}
|
||||||
|
|
||||||
filterToMembersWithDecorator(members, 'HostBinding', coreModule).forEach(({member, decorators}) => {
|
filterToMembersWithDecorator(members, 'HostBinding', coreModule)
|
||||||
|
.forEach(({member, decorators}) => {
|
||||||
decorators.forEach(decorator => {
|
decorators.forEach(decorator => {
|
||||||
let hostPropertyName: string = member.name;
|
let hostPropertyName: string = member.name;
|
||||||
if (decorator.args !== null && decorator.args.length > 0) {
|
if (decorator.args !== null && decorator.args.length > 0) {
|
||||||
if (decorator.args.length !== 1) {
|
if (decorator.args.length !== 1) {
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.DECORATOR_ARITY_WRONG, Decorator.nodeForError(decorator),
|
ErrorCode.DECORATOR_ARITY_WRONG, Decorator.nodeForError(decorator),
|
||||||
`@HostBinding can have at most one argument, got ${decorator.args.length} argument(s)`);
|
`@HostBinding can have at most one argument, got ${
|
||||||
|
decorator.args.length} argument(s)`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolved = evaluator.evaluate(decorator.args[0]);
|
const resolved = evaluator.evaluate(decorator.args[0]);
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {R3FactoryMetadata, compileFactoryFunction} from '@angular/compiler';
|
import {compileFactoryFunction, R3FactoryMetadata} from '@angular/compiler';
|
||||||
|
|
||||||
import {CompileResult} from '../../transform';
|
import {CompileResult} from '../../transform';
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Expression, Identifiers, LiteralExpr, R3DependencyMetadata, R3FactoryTarget, R3InjectableMetadata, R3ResolvedDependencyType, Statement, WrappedNodeExpr, compileInjectable as compileIvyInjectable} from '@angular/compiler';
|
import {compileInjectable as compileIvyInjectable, Expression, Identifiers, LiteralExpr, R3DependencyMetadata, R3FactoryTarget, R3InjectableMetadata, R3ResolvedDependencyType, Statement, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||||
|
@ -83,7 +83,9 @@ export class InjectableDecoratorHandler implements
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
register(node: ClassDeclaration): void { this.injectableRegistry.registerInjectable(node); }
|
register(node: ClassDeclaration): void {
|
||||||
|
this.injectableRegistry.registerInjectable(node);
|
||||||
|
}
|
||||||
|
|
||||||
compile(node: ClassDeclaration, analysis: Readonly<InjectableHandlerData>): CompileResult[] {
|
compile(node: ClassDeclaration, analysis: Readonly<InjectableHandlerData>): CompileResult[] {
|
||||||
const res = compileIvyInjectable(analysis.meta);
|
const res = compileIvyInjectable(analysis.meta);
|
||||||
|
@ -216,7 +218,8 @@ function extractInjectableMetadata(
|
||||||
typeArgumentCount,
|
typeArgumentCount,
|
||||||
internalType,
|
internalType,
|
||||||
providedIn,
|
providedIn,
|
||||||
useFactory: factory, userDeps,
|
useFactory: factory,
|
||||||
|
userDeps,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {name, type, typeArgumentCount, internalType, providedIn};
|
return {name, type, typeArgumentCount, internalType, providedIn};
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Expression, ExternalExpr, FunctionExpr, Identifiers, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NONE_TYPE, ReturnStatement, Statement, WrappedNodeExpr, literalMap} from '@angular/compiler';
|
import {Expression, ExternalExpr, FunctionExpr, Identifiers, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, literalMap, NONE_TYPE, ReturnStatement, Statement, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {DefaultImportRecorder} from '../../imports';
|
import {DefaultImportRecorder} from '../../imports';
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CUSTOM_ELEMENTS_SCHEMA, Expression, ExternalExpr, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NO_ERRORS_SCHEMA, R3Identifiers, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, STRING_TYPE, SchemaMetadata, Statement, WrappedNodeExpr, compileInjector, compileNgModule} from '@angular/compiler';
|
import {compileInjector, compileNgModule, CUSTOM_ELEMENTS_SCHEMA, Expression, ExternalExpr, InvokeFunctionExpr, LiteralArrayExpr, LiteralExpr, NO_ERRORS_SCHEMA, R3Identifiers, R3InjectorMetadata, R3NgModuleMetadata, R3Reference, SchemaMetadata, Statement, STRING_TYPE, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
||||||
|
@ -40,7 +40,9 @@ export interface NgModuleAnalysis {
|
||||||
providers: ts.Expression|null;
|
providers: ts.Expression|null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NgModuleResolution { injectorImports: Expression[]; }
|
export interface NgModuleResolution {
|
||||||
|
injectorImports: Expression[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles @NgModule annotations to ngModuleDef fields.
|
* Compiles @NgModule annotations to ngModuleDef fields.
|
||||||
|
@ -128,7 +130,9 @@ export class NgModuleDecoratorHandler implements
|
||||||
|
|
||||||
diagnostics.push(makeDiagnostic(
|
diagnostics.push(makeDiagnostic(
|
||||||
ErrorCode.NGMODULE_INVALID_DECLARATION, errorNode,
|
ErrorCode.NGMODULE_INVALID_DECLARATION, errorNode,
|
||||||
`Cannot declare '${ref.node.name.text}' in an NgModule as it's not a part of the current compilation.`,
|
`Cannot declare '${
|
||||||
|
ref.node.name
|
||||||
|
.text}' in an NgModule as it's not a part of the current compilation.`,
|
||||||
[{
|
[{
|
||||||
node: ref.node.name,
|
node: ref.node.name,
|
||||||
messageText: `'${ref.node.name.text}' is declared here.`,
|
messageText: `'${ref.node.name.text}' is declared here.`,
|
||||||
|
@ -279,7 +283,8 @@ export class NgModuleDecoratorHandler implements
|
||||||
schemas: schemas,
|
schemas: schemas,
|
||||||
mod: ngModuleDef,
|
mod: ngModuleDef,
|
||||||
inj: ngInjectorDef,
|
inj: ngInjectorDef,
|
||||||
declarations: declarationRefs, rawDeclarations,
|
declarations: declarationRefs,
|
||||||
|
rawDeclarations,
|
||||||
imports: importRefs,
|
imports: importRefs,
|
||||||
exports: exportRefs,
|
exports: exportRefs,
|
||||||
providers: rawProviders,
|
providers: rawProviders,
|
||||||
|
@ -472,7 +477,8 @@ export class NgModuleDecoratorHandler implements
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const typeName = type && (ts.isIdentifier(type.typeName) && type.typeName ||
|
const typeName = type &&
|
||||||
|
(ts.isIdentifier(type.typeName) && type.typeName ||
|
||||||
ts.isQualifiedName(type.typeName) && type.typeName.right) ||
|
ts.isQualifiedName(type.typeName) && type.typeName.right) ||
|
||||||
null;
|
null;
|
||||||
if (typeName === null) {
|
if (typeName === null) {
|
||||||
|
@ -569,14 +575,16 @@ export class NgModuleDecoratorHandler implements
|
||||||
if (!this.isClassDeclarationReference(entry)) {
|
if (!this.isClassDeclarationReference(entry)) {
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.VALUE_HAS_WRONG_TYPE, entry.node,
|
ErrorCode.VALUE_HAS_WRONG_TYPE, entry.node,
|
||||||
`Value at position ${idx} in the NgModule.${arrayName} of ${className} is not a class`);
|
`Value at position ${idx} in the NgModule.${arrayName} of ${
|
||||||
|
className} is not a class`);
|
||||||
}
|
}
|
||||||
refList.push(entry);
|
refList.push(entry);
|
||||||
} else {
|
} else {
|
||||||
// TODO(alxhub): Produce a better diagnostic here - the array index may be an inner array.
|
// TODO(alxhub): Produce a better diagnostic here - the array index may be an inner array.
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr,
|
ErrorCode.VALUE_HAS_WRONG_TYPE, expr,
|
||||||
`Value at position ${idx} in the NgModule.${arrayName} of ${className} is not a reference: ${entry}`);
|
`Value at position ${idx} in the NgModule.${arrayName} of ${
|
||||||
|
className} is not a reference: ${entry}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Identifiers, R3FactoryTarget, R3PipeMetadata, Statement, WrappedNodeExpr, compilePipeFromMetadata} from '@angular/compiler';
|
import {compilePipeFromMetadata, Identifiers, R3FactoryTarget, R3PipeMetadata, Statement, WrappedNodeExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||||
|
@ -103,7 +103,8 @@ export class PipeDecoratorHandler implements DecoratorHandler<Decorator, PipeHan
|
||||||
name,
|
name,
|
||||||
type,
|
type,
|
||||||
internalType,
|
internalType,
|
||||||
typeArgumentCount: this.reflector.getGenericArityOfClass(clazz) || 0, pipeName,
|
typeArgumentCount: this.reflector.getGenericArityOfClass(clazz) || 0,
|
||||||
|
pipeName,
|
||||||
deps: getValidConstructorDependencies(
|
deps: getValidConstructorDependencies(
|
||||||
clazz, this.reflector, this.defaultImportRecorder, this.isCore),
|
clazz, this.reflector, this.defaultImportRecorder, this.isCore),
|
||||||
pure,
|
pure,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import * as ts from 'typescript';
|
||||||
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
import {ErrorCode, FatalDiagnosticError, makeDiagnostic} from '../../diagnostics';
|
||||||
import {DefaultImportRecorder, ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
import {DefaultImportRecorder, ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
import {ForeignFunctionResolver, PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, CtorParameter, Decorator, Import, ReflectionHost, TypeValueReference, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, CtorParameter, Decorator, Import, isNamedClassDeclaration, ReflectionHost, TypeValueReference} from '../../reflection';
|
||||||
import {DeclarationData} from '../../scope';
|
import {DeclarationData} from '../../scope';
|
||||||
|
|
||||||
export enum ConstructorDepErrorKind {
|
export enum ConstructorDepErrorKind {
|
||||||
|
@ -21,8 +21,7 @@ export enum ConstructorDepErrorKind {
|
||||||
|
|
||||||
export type ConstructorDeps = {
|
export type ConstructorDeps = {
|
||||||
deps: R3DependencyMetadata[];
|
deps: R3DependencyMetadata[];
|
||||||
} |
|
}|{
|
||||||
{
|
|
||||||
deps: null;
|
deps: null;
|
||||||
errors: ConstructorDepError[];
|
errors: ConstructorDepError[];
|
||||||
};
|
};
|
||||||
|
@ -97,7 +96,8 @@ export function getConstructorDependencies(
|
||||||
if (token === null) {
|
if (token === null) {
|
||||||
errors.push({
|
errors.push({
|
||||||
index: idx,
|
index: idx,
|
||||||
kind: ConstructorDepErrorKind.NO_SUITABLE_TOKEN, param,
|
kind: ConstructorDepErrorKind.NO_SUITABLE_TOKEN,
|
||||||
|
param,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
deps.push({token, attribute, optional, self, skipSelf, host, resolved});
|
deps.push({token, attribute, optional, self, skipSelf, host, resolved});
|
||||||
|
@ -187,7 +187,8 @@ export function validateConstructorDependencies(
|
||||||
// There is at least one error.
|
// There is at least one error.
|
||||||
throw new FatalDiagnosticError(
|
throw new FatalDiagnosticError(
|
||||||
ErrorCode.PARAM_MISSING_TOKEN, param.nameNode,
|
ErrorCode.PARAM_MISSING_TOKEN, param.nameNode,
|
||||||
`No suitable injection token for parameter '${param.name || index}' of class '${clazz.name.text}'.\n` +
|
`No suitable injection token for parameter '${param.name || index}' of class '${
|
||||||
|
clazz.name.text}'.\n` +
|
||||||
(param.typeNode !== null ? `Found ${param.typeNode.getText()}` :
|
(param.typeNode !== null ? `Found ${param.typeNode.getText()}` :
|
||||||
'no type or decorator'));
|
'no type or decorator'));
|
||||||
}
|
}
|
||||||
|
@ -319,8 +320,7 @@ export function forwardRefResolver(
|
||||||
*/
|
*/
|
||||||
export function combineResolvers(resolvers: ForeignFunctionResolver[]): ForeignFunctionResolver {
|
export function combineResolvers(resolvers: ForeignFunctionResolver[]): ForeignFunctionResolver {
|
||||||
return (ref: Reference<ts.FunctionDeclaration|ts.MethodDeclaration|ts.FunctionExpression>,
|
return (ref: Reference<ts.FunctionDeclaration|ts.MethodDeclaration|ts.FunctionExpression>,
|
||||||
args: ReadonlyArray<ts.Expression>): ts.Expression |
|
args: ReadonlyArray<ts.Expression>): ts.Expression|null => {
|
||||||
null => {
|
|
||||||
for (const resolver of resolvers) {
|
for (const resolver of resolvers) {
|
||||||
const resolved = resolver(ref, args);
|
const resolved = resolver(ref, args);
|
||||||
if (resolved !== null) {
|
if (resolved !== null) {
|
||||||
|
@ -406,8 +406,8 @@ export function makeDuplicateDeclarationError(
|
||||||
const contextNode = decl.ref.getOriginForDiagnostics(decl.rawDeclarations, decl.ngModule.name);
|
const contextNode = decl.ref.getOriginForDiagnostics(decl.rawDeclarations, decl.ngModule.name);
|
||||||
context.push({
|
context.push({
|
||||||
node: contextNode,
|
node: contextNode,
|
||||||
messageText:
|
messageText: `'${node.name.text}' is listed in the declarations of the NgModule '${
|
||||||
`'${node.name.text}' is listed in the declarations of the NgModule '${decl.ngModule.name.text}'.`,
|
decl.ngModule.name.text}'.`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,23 @@ import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
import {ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||||
import {CompoundMetadataReader, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
import {CompoundMetadataReader, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {ResourceLoader} from '../src/api';
|
import {ResourceLoader} from '../src/api';
|
||||||
import {ComponentDecoratorHandler} from '../src/component';
|
import {ComponentDecoratorHandler} from '../src/component';
|
||||||
|
|
||||||
export class NoopResourceLoader implements ResourceLoader {
|
export class NoopResourceLoader implements ResourceLoader {
|
||||||
resolve(): string { throw new Error('Not implemented.'); }
|
resolve(): string {
|
||||||
|
throw new Error('Not implemented.');
|
||||||
|
}
|
||||||
canPreload = false;
|
canPreload = false;
|
||||||
load(): string { throw new Error('Not implemented'); }
|
load(): string {
|
||||||
preload(): Promise<void>|undefined { throw new Error('Not implemented'); }
|
throw new Error('Not implemented');
|
||||||
|
}
|
||||||
|
preload(): Promise<void>|undefined {
|
||||||
|
throw new Error('Not implemented');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
describe('ComponentDecoratorHandler', () => {
|
describe('ComponentDecoratorHandler', () => {
|
||||||
|
@ -88,5 +94,7 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function ivyCode(code: ErrorCode): number { return Number('-99' + code.valueOf()); }
|
function ivyCode(code: ErrorCode): number {
|
||||||
|
return Number('-99' + code.valueOf());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,12 +6,13 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom} from '../../file_system';
|
import {absoluteFrom} from '../../file_system';
|
||||||
import {runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
import {NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||||
import {DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
import {DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {ClassDeclaration, TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {DirectiveDecoratorHandler} from '../src/directive';
|
import {DirectiveDecoratorHandler} from '../src/directive';
|
||||||
|
@ -77,9 +78,13 @@ runInEachFileSystem(() => {
|
||||||
// Helpers
|
// Helpers
|
||||||
function analyzeDirective(program: ts.Program, dirName: string, hasBaseClass: boolean = false) {
|
function analyzeDirective(program: ts.Program, dirName: string, hasBaseClass: boolean = false) {
|
||||||
class TestReflectionHost extends TypeScriptReflectionHost {
|
class TestReflectionHost extends TypeScriptReflectionHost {
|
||||||
constructor(checker: ts.TypeChecker) { super(checker); }
|
constructor(checker: ts.TypeChecker) {
|
||||||
|
super(checker);
|
||||||
|
}
|
||||||
|
|
||||||
hasBaseClass(_class: ClassDeclaration): boolean { return hasBaseClass; }
|
hasBaseClass(_class: ClassDeclaration): boolean {
|
||||||
|
return hasBaseClass;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const checker = program.getTypeChecker();
|
const checker = program.getTypeChecker();
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {absoluteFrom} from '../../file_system';
|
||||||
import {runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {NOOP_DEFAULT_IMPORT_RECORDER} from '../../imports';
|
import {NOOP_DEFAULT_IMPORT_RECORDER} from '../../imports';
|
||||||
import {InjectableClassRegistry} from '../../metadata';
|
import {InjectableClassRegistry} from '../../metadata';
|
||||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {InjectableDecoratorHandler} from '../src/injectable';
|
import {InjectableDecoratorHandler} from '../src/injectable';
|
||||||
|
|
||||||
|
@ -43,7 +43,6 @@ runInEachFileSystem(() => {
|
||||||
expect(res).not.toContain(jasmine.objectContaining({name: 'ɵprov'}));
|
expect(res).not.toContain(jasmine.objectContaining({name: 'ɵprov'}));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {absoluteFrom, getSourceFileOrError} from '../../file_system';
|
import {absoluteFrom, getSourceFileOrError} from '../../file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../file_system/testing';
|
||||||
import {NOOP_DEFAULT_IMPORT_RECORDER, NoopImportRewriter} from '../../imports';
|
import {NOOP_DEFAULT_IMPORT_RECORDER, NoopImportRewriter} from '../../imports';
|
||||||
import {TypeScriptReflectionHost} from '../../reflection';
|
import {TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {LocalIdentifierStrategy, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
import {LocalIdentifierStrategy, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||||
import {CompoundMetadataReader, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
import {CompoundMetadataReader, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry} from '../../metadata';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {NgModuleDecoratorHandler} from '../src/ng_module';
|
import {NgModuleDecoratorHandler} from '../src/ng_module';
|
||||||
|
|
|
@ -13,8 +13,9 @@ import {unwrapExpression} from '../src/util';
|
||||||
describe('ngtsc annotation utilities', () => {
|
describe('ngtsc annotation utilities', () => {
|
||||||
describe('unwrapExpression', () => {
|
describe('unwrapExpression', () => {
|
||||||
const obj = ts.createObjectLiteral();
|
const obj = ts.createObjectLiteral();
|
||||||
it('should pass through an ObjectLiteralExpression',
|
it('should pass through an ObjectLiteralExpression', () => {
|
||||||
() => { expect(unwrapExpression(obj)).toBe(obj); });
|
expect(unwrapExpression(obj)).toBe(obj);
|
||||||
|
});
|
||||||
|
|
||||||
it('should unwrap an ObjectLiteralExpression in parentheses', () => {
|
it('should unwrap an ObjectLiteralExpression in parentheses', () => {
|
||||||
const wrapped = ts.createParen(obj);
|
const wrapped = ts.createParen(obj);
|
||||||
|
|
|
@ -36,7 +36,8 @@ export interface TestOnlyOptions {
|
||||||
*/
|
*/
|
||||||
ivyTemplateTypeCheck?: boolean;
|
ivyTemplateTypeCheck?: boolean;
|
||||||
|
|
||||||
/** An option to enable ngtsc's internal performance tracing.
|
/**
|
||||||
|
* An option to enable ngtsc's internal performance tracing.
|
||||||
*
|
*
|
||||||
* This should be a path to a JSON file where trace information will be written. An optional 'ts:'
|
* This should be a path to a JSON file where trace information will be written. An optional 'ts:'
|
||||||
* prefix will cause the trace to be written via the TS host instead of directly to the filesystem
|
* prefix will cause the trace to be written via the TS host instead of directly to the filesystem
|
||||||
|
@ -54,4 +55,5 @@ export interface TestOnlyOptions {
|
||||||
* Also includes a few miscellaneous options.
|
* Also includes a few miscellaneous options.
|
||||||
*/
|
*/
|
||||||
export interface NgCompilerOptions extends ts.CompilerOptions, LegacyNgcOptions, BazelAndG3Options,
|
export interface NgCompilerOptions extends ts.CompilerOptions, LegacyNgcOptions, BazelAndG3Options,
|
||||||
NgcCompatibilityOptions, StrictTemplateOptions, TestOnlyOptions, I18nOptions, MiscOptions {}
|
NgcCompatibilityOptions, StrictTemplateOptions,
|
||||||
|
TestOnlyOptions, I18nOptions, MiscOptions {}
|
|
@ -12,23 +12,23 @@ import * as ts from 'typescript';
|
||||||
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, NoopReferencesRegistry, PipeDecoratorHandler, ReferencesRegistry} from '../../annotations';
|
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, NoopReferencesRegistry, PipeDecoratorHandler, ReferencesRegistry} from '../../annotations';
|
||||||
import {CycleAnalyzer, ImportGraph} from '../../cycles';
|
import {CycleAnalyzer, ImportGraph} from '../../cycles';
|
||||||
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
||||||
import {ReferenceGraph, checkForPrivateExports} from '../../entry_point';
|
import {checkForPrivateExports, ReferenceGraph} from '../../entry_point';
|
||||||
import {LogicalFileSystem, getSourceFileOrError} from '../../file_system';
|
import {getSourceFileOrError, LogicalFileSystem} from '../../file_system';
|
||||||
import {AbsoluteModuleStrategy, AliasStrategy, AliasingHost, DefaultImportTracker, ImportRewriter, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NoopImportRewriter, PrivateExportAliasingHost, R3SymbolsImportRewriter, Reference, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesAliasingHost, UnifiedModulesStrategy} from '../../imports';
|
import {AbsoluteModuleStrategy, AliasingHost, AliasStrategy, DefaultImportTracker, ImportRewriter, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, NoopImportRewriter, PrivateExportAliasingHost, R3SymbolsImportRewriter, Reference, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesAliasingHost, UnifiedModulesStrategy} from '../../imports';
|
||||||
import {IncrementalDriver} from '../../incremental';
|
import {IncrementalDriver} from '../../incremental';
|
||||||
import {IndexedComponent, IndexingContext, generateAnalysis} from '../../indexer';
|
import {generateAnalysis, IndexedComponent, IndexingContext} from '../../indexer';
|
||||||
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry, MetadataReader} from '../../metadata';
|
import {CompoundMetadataReader, CompoundMetadataRegistry, DtsMetadataReader, InjectableClassRegistry, LocalMetadataRegistry, MetadataReader} from '../../metadata';
|
||||||
import {ModuleWithProvidersScanner} from '../../modulewithproviders';
|
import {ModuleWithProvidersScanner} from '../../modulewithproviders';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
import {NOOP_PERF_RECORDER, PerfRecorder} from '../../perf';
|
import {NOOP_PERF_RECORDER, PerfRecorder} from '../../perf';
|
||||||
import {TypeScriptReflectionHost} from '../../reflection';
|
import {TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {HostResourceLoader} from '../../resource';
|
import {HostResourceLoader} from '../../resource';
|
||||||
import {NgModuleRouteAnalyzer, entryPointKeyFor} from '../../routing';
|
import {entryPointKeyFor, NgModuleRouteAnalyzer} from '../../routing';
|
||||||
import {ComponentScopeReader, LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
import {ComponentScopeReader, LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||||
import {generatedFactoryTransform} from '../../shims';
|
import {generatedFactoryTransform} from '../../shims';
|
||||||
import {ivySwitchTransform} from '../../switch';
|
import {ivySwitchTransform} from '../../switch';
|
||||||
import {DecoratorHandler, DtsTransformRegistry, TraitCompiler, aliasTransformFactory, declarationTransformFactory, ivyTransformFactory} from '../../transform';
|
import {aliasTransformFactory, declarationTransformFactory, DecoratorHandler, DtsTransformRegistry, ivyTransformFactory, TraitCompiler} from '../../transform';
|
||||||
import {TypeCheckContext, TypeCheckingConfig, isTemplateDiagnostic} from '../../typecheck';
|
import {isTemplateDiagnostic, TypeCheckContext, TypeCheckingConfig} from '../../typecheck';
|
||||||
import {getSourceFileOrNull, isDtsPath, resolveModuleName} from '../../util/src/typescript';
|
import {getSourceFileOrNull, isDtsPath, resolveModuleName} from '../../util/src/typescript';
|
||||||
import {LazyRoute, NgCompilerOptions} from '../api';
|
import {LazyRoute, NgCompilerOptions} from '../api';
|
||||||
|
|
||||||
|
@ -191,7 +191,9 @@ export class NgCompiler {
|
||||||
/**
|
/**
|
||||||
* Get all setup-related diagnostics for this compilation.
|
* Get all setup-related diagnostics for this compilation.
|
||||||
*/
|
*/
|
||||||
getOptionDiagnostics(): ts.Diagnostic[] { return this.constructionDiagnostics; }
|
getOptionDiagnostics(): ts.Diagnostic[] {
|
||||||
|
return this.constructionDiagnostics;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the `ts.Program` to use as a starting point when spawning a subsequent incremental
|
* Get the `ts.Program` to use as a starting point when spawning a subsequent incremental
|
||||||
|
@ -202,7 +204,9 @@ export class NgCompiler {
|
||||||
* operation, the consumer's `ts.Program` is no longer usable for starting a new incremental
|
* operation, the consumer's `ts.Program` is no longer usable for starting a new incremental
|
||||||
* compilation. `getNextProgram` retrieves the `ts.Program` which can be used instead.
|
* compilation. `getNextProgram` retrieves the `ts.Program` which can be used instead.
|
||||||
*/
|
*/
|
||||||
getNextProgram(): ts.Program { return this.nextProgram; }
|
getNextProgram(): ts.Program {
|
||||||
|
return this.nextProgram;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform Angular's analysis step (as a precursor to `getDiagnostics` or `prepareEmit`)
|
* Perform Angular's analysis step (as a precursor to `getDiagnostics` or `prepareEmit`)
|
||||||
|
@ -262,8 +266,8 @@ export class NgCompiler {
|
||||||
|
|
||||||
// Relative entry paths are disallowed.
|
// Relative entry paths are disallowed.
|
||||||
if (entryRoute.startsWith('.')) {
|
if (entryRoute.startsWith('.')) {
|
||||||
throw new Error(
|
throw new Error(`Failed to list lazy routes: Resolution of relative paths (${
|
||||||
`Failed to list lazy routes: Resolution of relative paths (${entryRoute}) is not supported.`);
|
entryRoute}) is not supported.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-relative entry paths fall into one of the following categories:
|
// Non-relative entry paths fall into one of the following categories:
|
||||||
|
@ -547,8 +551,7 @@ export class NgCompiler {
|
||||||
addTypeReplacement: (node: ts.Declaration, type: Type): void => {
|
addTypeReplacement: (node: ts.Declaration, type: Type): void => {
|
||||||
// Only obtain the return type transform for the source file once there's a type to replace,
|
// Only obtain the return type transform for the source file once there's a type to replace,
|
||||||
// so that no transform is allocated when there's nothing to do.
|
// so that no transform is allocated when there's nothing to do.
|
||||||
this.compilation !.dtsTransforms !.getReturnTypeTransform(sf).addTypeReplacement(
|
this.compilation!.dtsTransforms!.getReturnTypeTransform(sf).addTypeReplacement(node, type);
|
||||||
node, type);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -686,9 +689,18 @@ export class NgCompiler {
|
||||||
this.options.compileNonExportedClasses !== false, dtsTransforms);
|
this.options.compileNonExportedClasses !== false, dtsTransforms);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isCore, traitCompiler, reflector, scopeRegistry,
|
isCore,
|
||||||
dtsTransforms, exportReferenceGraph, routeAnalyzer, mwpScanner,
|
traitCompiler,
|
||||||
metaReader, defaultImportTracker, aliasingHost, refEmitter,
|
reflector,
|
||||||
|
scopeRegistry,
|
||||||
|
dtsTransforms,
|
||||||
|
exportReferenceGraph,
|
||||||
|
routeAnalyzer,
|
||||||
|
mwpScanner,
|
||||||
|
metaReader,
|
||||||
|
defaultImportTracker,
|
||||||
|
aliasingHost,
|
||||||
|
refEmitter,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
import {ErrorCode, ngErrorCode} from '../../diagnostics';
|
||||||
import {FlatIndexGenerator, findFlatIndexEntryPoint} from '../../entry_point';
|
import {findFlatIndexEntryPoint, FlatIndexGenerator} from '../../entry_point';
|
||||||
import {AbsoluteFsPath, resolve} from '../../file_system';
|
import {AbsoluteFsPath, resolve} from '../../file_system';
|
||||||
import {FactoryGenerator, FactoryTracker, ShimGenerator, SummaryGenerator, TypeCheckShimGenerator} from '../../shims';
|
import {FactoryGenerator, FactoryTracker, ShimGenerator, SummaryGenerator, TypeCheckShimGenerator} from '../../shims';
|
||||||
import {typeCheckFilePath} from '../../typecheck';
|
import {typeCheckFilePath} from '../../typecheck';
|
||||||
|
@ -88,8 +88,7 @@ export class DelegatingCompilerHost implements
|
||||||
* `ExtendedTsCompilerHost` methods whenever present.
|
* `ExtendedTsCompilerHost` methods whenever present.
|
||||||
*/
|
*/
|
||||||
export class NgCompilerHost extends DelegatingCompilerHost implements
|
export class NgCompilerHost extends DelegatingCompilerHost implements
|
||||||
RequiredCompilerHostDelegations,
|
RequiredCompilerHostDelegations, ExtendedTsCompilerHost {
|
||||||
ExtendedTsCompilerHost {
|
|
||||||
readonly factoryTracker: FactoryTracker|null = null;
|
readonly factoryTracker: FactoryTracker|null = null;
|
||||||
readonly entryPoint: AbsoluteFsPath|null = null;
|
readonly entryPoint: AbsoluteFsPath|null = null;
|
||||||
readonly diagnostics: ts.Diagnostic[];
|
readonly diagnostics: ts.Diagnostic[];
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {FileSystem, NgtscCompilerHost, absoluteFrom as _, getFileSystem, getSourceFileOrError, setFileSystem} from '../../file_system';
|
import {absoluteFrom as _, FileSystem, getFileSystem, getSourceFileOrError, NgtscCompilerHost, setFileSystem} from '../../file_system';
|
||||||
import {runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {NgCompilerOptions} from '../api';
|
import {NgCompilerOptions} from '../api';
|
||||||
import {NgCompiler} from '../src/compiler';
|
import {NgCompiler} from '../src/compiler';
|
||||||
|
@ -16,7 +16,6 @@ import {NgCompilerHost} from '../src/host';
|
||||||
|
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
|
|
||||||
describe('NgCompiler', () => {
|
describe('NgCompiler', () => {
|
||||||
let fs: FileSystem;
|
let fs: FileSystem;
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,9 @@ export class ImportGraph {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
results.add(sf);
|
results.add(sf);
|
||||||
this.importsOf(sf).forEach(imported => { this.transitiveImportsOfHelper(imported, results); });
|
this.importsOf(sf).forEach(imported => {
|
||||||
|
this.transitiveImportsOfHelper(imported, results);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,8 @@ export function makeDiagnostic(code: ErrorCode, node: ts.Node, messageText: stri
|
||||||
code: Number('-99' + code.valueOf()),
|
code: Number('-99' + code.valueOf()),
|
||||||
file: ts.getOriginalNode(node).getSourceFile(),
|
file: ts.getOriginalNode(node).getSourceFile(),
|
||||||
start: node.getStart(undefined, false),
|
start: node.getStart(undefined, false),
|
||||||
length: node.getWidth(), messageText,
|
length: node.getWidth(),
|
||||||
|
messageText,
|
||||||
};
|
};
|
||||||
if (relatedInfo !== undefined) {
|
if (relatedInfo !== undefined) {
|
||||||
diag.relatedInformation = relatedInfo.map(info => {
|
diag.relatedInformation = relatedInfo.map(info => {
|
||||||
|
|
|
@ -24,7 +24,9 @@ export class FlatIndexGenerator implements ShimGenerator {
|
||||||
join(dirname(entryPoint), relativeFlatIndexPath).replace(/\.js$/, '') + '.ts';
|
join(dirname(entryPoint), relativeFlatIndexPath).replace(/\.js$/, '') + '.ts';
|
||||||
}
|
}
|
||||||
|
|
||||||
recognize(fileName: string): boolean { return fileName === this.flatIndexPath; }
|
recognize(fileName: string): boolean {
|
||||||
|
return fileName === this.flatIndexPath;
|
||||||
|
}
|
||||||
|
|
||||||
generate(): ts.SourceFile {
|
generate(): ts.SourceFile {
|
||||||
const relativeEntryPoint = relativePathBetween(this.flatIndexPath, this.entryPoint);
|
const relativeEntryPoint = relativePathBetween(this.flatIndexPath, this.entryPoint);
|
||||||
|
|
|
@ -95,9 +95,11 @@ export function checkForPrivateExports(
|
||||||
const diagnostic: ts.Diagnostic = {
|
const diagnostic: ts.Diagnostic = {
|
||||||
category: ts.DiagnosticCategory.Error,
|
category: ts.DiagnosticCategory.Error,
|
||||||
code: ngErrorCode(ErrorCode.SYMBOL_NOT_EXPORTED),
|
code: ngErrorCode(ErrorCode.SYMBOL_NOT_EXPORTED),
|
||||||
file: transitiveReference.getSourceFile(), ...getPosOfDeclaration(transitiveReference),
|
file: transitiveReference.getSourceFile(),
|
||||||
messageText:
|
...getPosOfDeclaration(transitiveReference),
|
||||||
`Unsupported private ${descriptor} ${name}. This ${descriptor} is visible to consumers via ${visibleVia}, but is not exported from the top-level library entrypoint.`,
|
messageText: `Unsupported private ${descriptor} ${name}. This ${
|
||||||
|
descriptor} is visible to consumers via ${
|
||||||
|
visibleVia}, but is not exported from the top-level library entrypoint.`,
|
||||||
};
|
};
|
||||||
|
|
||||||
diagnostics.push(diagnostic);
|
diagnostics.push(diagnostic);
|
||||||
|
|
|
@ -16,9 +16,9 @@ runInEachFileSystem(() => {
|
||||||
beforeEach(() => _ = absoluteFrom);
|
beforeEach(() => _ = absoluteFrom);
|
||||||
|
|
||||||
describe('findFlatIndexEntryPoint', () => {
|
describe('findFlatIndexEntryPoint', () => {
|
||||||
|
it('should use the only source file if only a single one is specified', () => {
|
||||||
it('should use the only source file if only a single one is specified',
|
expect(findFlatIndexEntryPoint([_('/src/index.ts')])).toBe(_('/src/index.ts'));
|
||||||
() => { expect(findFlatIndexEntryPoint([_('/src/index.ts')])).toBe(_('/src/index.ts')); });
|
});
|
||||||
|
|
||||||
it('should use the shortest source file ending with "index.ts" for multiple files', () => {
|
it('should use the shortest source file ending with "index.ts" for multiple files', () => {
|
||||||
expect(findFlatIndexEntryPoint([
|
expect(findFlatIndexEntryPoint([
|
||||||
|
|
|
@ -12,8 +12,9 @@ import {ReferenceGraph} from '../src/reference_graph';
|
||||||
describe('entry_point reference graph', () => {
|
describe('entry_point reference graph', () => {
|
||||||
let graph: ReferenceGraph<string>;
|
let graph: ReferenceGraph<string>;
|
||||||
|
|
||||||
const refs =
|
const refs = (target: string) => {
|
||||||
(target: string) => { return Array.from(graph.transitiveReferencesOf(target)).sort(); };
|
return Array.from(graph.transitiveReferencesOf(target)).sort();
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
graph = new ReferenceGraph();
|
graph = new ReferenceGraph();
|
||||||
|
@ -45,6 +46,7 @@ describe('entry_point reference graph', () => {
|
||||||
expect(graph.pathFrom('beta', 'alpha')).toEqual(['beta', 'delta', 'alpha']);
|
expect(graph.pathFrom('beta', 'alpha')).toEqual(['beta', 'delta', 'alpha']);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not report a path that doesn\'t exist',
|
it('should not report a path that doesn\'t exist', () => {
|
||||||
() => { expect(graph.pathFrom('gamma', 'beta')).toBeNull(); });
|
expect(graph.pathFrom('gamma', 'beta')).toBeNull();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -131,15 +131,33 @@ export class CachedFileSystem implements FileSystem {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The following methods simply call through to the delegate.
|
// The following methods simply call through to the delegate.
|
||||||
readdir(path: AbsoluteFsPath): PathSegment[] { return this.delegate.readdir(path); }
|
readdir(path: AbsoluteFsPath): PathSegment[] {
|
||||||
pwd(): AbsoluteFsPath { return this.delegate.pwd(); }
|
return this.delegate.readdir(path);
|
||||||
chdir(path: AbsoluteFsPath): void { this.delegate.chdir(path); }
|
}
|
||||||
extname(path: AbsoluteFsPath|PathSegment): string { return this.delegate.extname(path); }
|
pwd(): AbsoluteFsPath {
|
||||||
isCaseSensitive(): boolean { return this.delegate.isCaseSensitive(); }
|
return this.delegate.pwd();
|
||||||
isRoot(path: AbsoluteFsPath): boolean { return this.delegate.isRoot(path); }
|
}
|
||||||
isRooted(path: string): boolean { return this.delegate.isRooted(path); }
|
chdir(path: AbsoluteFsPath): void {
|
||||||
resolve(...paths: string[]): AbsoluteFsPath { return this.delegate.resolve(...paths); }
|
this.delegate.chdir(path);
|
||||||
dirname<T extends PathString>(file: T): T { return this.delegate.dirname(file); }
|
}
|
||||||
|
extname(path: AbsoluteFsPath|PathSegment): string {
|
||||||
|
return this.delegate.extname(path);
|
||||||
|
}
|
||||||
|
isCaseSensitive(): boolean {
|
||||||
|
return this.delegate.isCaseSensitive();
|
||||||
|
}
|
||||||
|
isRoot(path: AbsoluteFsPath): boolean {
|
||||||
|
return this.delegate.isRoot(path);
|
||||||
|
}
|
||||||
|
isRooted(path: string): boolean {
|
||||||
|
return this.delegate.isRooted(path);
|
||||||
|
}
|
||||||
|
resolve(...paths: string[]): AbsoluteFsPath {
|
||||||
|
return this.delegate.resolve(...paths);
|
||||||
|
}
|
||||||
|
dirname<T extends PathString>(file: T): T {
|
||||||
|
return this.delegate.dirname(file);
|
||||||
|
}
|
||||||
join<T extends PathString>(basePath: T, ...paths: string[]): T {
|
join<T extends PathString>(basePath: T, ...paths: string[]): T {
|
||||||
return this.delegate.join(basePath, ...paths);
|
return this.delegate.join(basePath, ...paths);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +167,13 @@ export class CachedFileSystem implements FileSystem {
|
||||||
basename(filePath: string, extension?: string|undefined): PathSegment {
|
basename(filePath: string, extension?: string|undefined): PathSegment {
|
||||||
return this.delegate.basename(filePath, extension);
|
return this.delegate.basename(filePath, extension);
|
||||||
}
|
}
|
||||||
realpath(filePath: AbsoluteFsPath): AbsoluteFsPath { return this.delegate.realpath(filePath); }
|
realpath(filePath: AbsoluteFsPath): AbsoluteFsPath {
|
||||||
getDefaultLibLocation(): AbsoluteFsPath { return this.delegate.getDefaultLibLocation(); }
|
return this.delegate.realpath(filePath);
|
||||||
normalize<T extends PathString>(path: T): T { return this.delegate.normalize(path); }
|
}
|
||||||
|
getDefaultLibLocation(): AbsoluteFsPath {
|
||||||
|
return this.delegate.getDefaultLibLocation();
|
||||||
|
}
|
||||||
|
normalize<T extends PathString>(path: T): T {
|
||||||
|
return this.delegate.normalize(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,9 @@ export class NgtscCompilerHost implements ts.CompilerHost {
|
||||||
return this.fs.join(this.getDefaultLibLocation(), ts.getDefaultLibFileName(options));
|
return this.fs.join(this.getDefaultLibLocation(), ts.getDefaultLibFileName(options));
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefaultLibLocation(): string { return this.fs.getDefaultLibLocation(); }
|
getDefaultLibLocation(): string {
|
||||||
|
return this.fs.getDefaultLibLocation();
|
||||||
|
}
|
||||||
|
|
||||||
writeFile(
|
writeFile(
|
||||||
fileName: string, data: string, writeByteOrderMark: boolean,
|
fileName: string, data: string, writeByteOrderMark: boolean,
|
||||||
|
@ -37,13 +39,17 @@ export class NgtscCompilerHost implements ts.CompilerHost {
|
||||||
this.fs.writeFile(path, data);
|
this.fs.writeFile(path, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentDirectory(): string { return this.fs.pwd(); }
|
getCurrentDirectory(): string {
|
||||||
|
return this.fs.pwd();
|
||||||
|
}
|
||||||
|
|
||||||
getCanonicalFileName(fileName: string): string {
|
getCanonicalFileName(fileName: string): string {
|
||||||
return this.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
return this.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
useCaseSensitiveFileNames(): boolean { return this.fs.isCaseSensitive(); }
|
useCaseSensitiveFileNames(): boolean {
|
||||||
|
return this.fs.isCaseSensitive();
|
||||||
|
}
|
||||||
|
|
||||||
getNewLine(): string {
|
getNewLine(): string {
|
||||||
switch (this.options.newLine) {
|
switch (this.options.newLine) {
|
||||||
|
|
|
@ -16,32 +16,84 @@ import {AbsoluteFsPath, FileStats, FileSystem, PathSegment, PathString} from './
|
||||||
* the `FileSystem` under the hood.
|
* the `FileSystem` under the hood.
|
||||||
*/
|
*/
|
||||||
export class InvalidFileSystem implements FileSystem {
|
export class InvalidFileSystem implements FileSystem {
|
||||||
exists(path: AbsoluteFsPath): boolean { throw makeError(); }
|
exists(path: AbsoluteFsPath): boolean {
|
||||||
readFile(path: AbsoluteFsPath): string { throw makeError(); }
|
throw makeError();
|
||||||
writeFile(path: AbsoluteFsPath, data: string, exclusive?: boolean): void { throw makeError(); }
|
}
|
||||||
removeFile(path: AbsoluteFsPath): void { throw makeError(); }
|
readFile(path: AbsoluteFsPath): string {
|
||||||
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void { throw makeError(); }
|
throw makeError();
|
||||||
readdir(path: AbsoluteFsPath): PathSegment[] { throw makeError(); }
|
}
|
||||||
lstat(path: AbsoluteFsPath): FileStats { throw makeError(); }
|
writeFile(path: AbsoluteFsPath, data: string, exclusive?: boolean): void {
|
||||||
stat(path: AbsoluteFsPath): FileStats { throw makeError(); }
|
throw makeError();
|
||||||
pwd(): AbsoluteFsPath { throw makeError(); }
|
}
|
||||||
chdir(path: AbsoluteFsPath): void { throw makeError(); }
|
removeFile(path: AbsoluteFsPath): void {
|
||||||
extname(path: AbsoluteFsPath|PathSegment): string { throw makeError(); }
|
throw makeError();
|
||||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { throw makeError(); }
|
}
|
||||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { throw makeError(); }
|
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void {
|
||||||
ensureDir(path: AbsoluteFsPath): void { throw makeError(); }
|
throw makeError();
|
||||||
removeDeep(path: AbsoluteFsPath): void { throw makeError(); }
|
}
|
||||||
isCaseSensitive(): boolean { throw makeError(); }
|
readdir(path: AbsoluteFsPath): PathSegment[] {
|
||||||
resolve(...paths: string[]): AbsoluteFsPath { throw makeError(); }
|
throw makeError();
|
||||||
dirname<T extends PathString>(file: T): T { throw makeError(); }
|
}
|
||||||
join<T extends PathString>(basePath: T, ...paths: string[]): T { throw makeError(); }
|
lstat(path: AbsoluteFsPath): FileStats {
|
||||||
isRoot(path: AbsoluteFsPath): boolean { throw makeError(); }
|
throw makeError();
|
||||||
isRooted(path: string): boolean { throw makeError(); }
|
}
|
||||||
relative<T extends PathString>(from: T, to: T): PathSegment { throw makeError(); }
|
stat(path: AbsoluteFsPath): FileStats {
|
||||||
basename(filePath: string, extension?: string): PathSegment { throw makeError(); }
|
throw makeError();
|
||||||
realpath(filePath: AbsoluteFsPath): AbsoluteFsPath { throw makeError(); }
|
}
|
||||||
getDefaultLibLocation(): AbsoluteFsPath { throw makeError(); }
|
pwd(): AbsoluteFsPath {
|
||||||
normalize<T extends PathString>(path: T): T { throw makeError(); }
|
throw makeError();
|
||||||
|
}
|
||||||
|
chdir(path: AbsoluteFsPath): void {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
extname(path: AbsoluteFsPath|PathSegment): string {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
ensureDir(path: AbsoluteFsPath): void {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
removeDeep(path: AbsoluteFsPath): void {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
isCaseSensitive(): boolean {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
resolve(...paths: string[]): AbsoluteFsPath {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
dirname<T extends PathString>(file: T): T {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
join<T extends PathString>(basePath: T, ...paths: string[]): T {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
isRoot(path: AbsoluteFsPath): boolean {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
isRooted(path: string): boolean {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
relative<T extends PathString>(from: T, to: T): PathSegment {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
basename(filePath: string, extension?: string): PathSegment {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
realpath(filePath: AbsoluteFsPath): AbsoluteFsPath {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
getDefaultLibLocation(): AbsoluteFsPath {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
|
normalize<T extends PathString>(path: T): T {
|
||||||
|
throw makeError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeError() {
|
function makeError() {
|
||||||
|
|
|
@ -17,20 +17,42 @@ import {AbsoluteFsPath, FileStats, FileSystem, PathSegment, PathString} from './
|
||||||
*/
|
*/
|
||||||
export class NodeJSFileSystem implements FileSystem {
|
export class NodeJSFileSystem implements FileSystem {
|
||||||
private _caseSensitive: boolean|undefined = undefined;
|
private _caseSensitive: boolean|undefined = undefined;
|
||||||
exists(path: AbsoluteFsPath): boolean { return fs.existsSync(path); }
|
exists(path: AbsoluteFsPath): boolean {
|
||||||
readFile(path: AbsoluteFsPath): string { return fs.readFileSync(path, 'utf8'); }
|
return fs.existsSync(path);
|
||||||
|
}
|
||||||
|
readFile(path: AbsoluteFsPath): string {
|
||||||
|
return fs.readFileSync(path, 'utf8');
|
||||||
|
}
|
||||||
writeFile(path: AbsoluteFsPath, data: string, exclusive: boolean = false): void {
|
writeFile(path: AbsoluteFsPath, data: string, exclusive: boolean = false): void {
|
||||||
fs.writeFileSync(path, data, exclusive ? {flag: 'wx'} : undefined);
|
fs.writeFileSync(path, data, exclusive ? {flag: 'wx'} : undefined);
|
||||||
}
|
}
|
||||||
removeFile(path: AbsoluteFsPath): void { fs.unlinkSync(path); }
|
removeFile(path: AbsoluteFsPath): void {
|
||||||
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void { fs.symlinkSync(target, path); }
|
fs.unlinkSync(path);
|
||||||
readdir(path: AbsoluteFsPath): PathSegment[] { return fs.readdirSync(path) as PathSegment[]; }
|
}
|
||||||
lstat(path: AbsoluteFsPath): FileStats { return fs.lstatSync(path); }
|
symlink(target: AbsoluteFsPath, path: AbsoluteFsPath): void {
|
||||||
stat(path: AbsoluteFsPath): FileStats { return fs.statSync(path); }
|
fs.symlinkSync(target, path);
|
||||||
pwd(): AbsoluteFsPath { return this.normalize(process.cwd()) as AbsoluteFsPath; }
|
}
|
||||||
chdir(dir: AbsoluteFsPath): void { process.chdir(dir); }
|
readdir(path: AbsoluteFsPath): PathSegment[] {
|
||||||
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { fs.copyFileSync(from, to); }
|
return fs.readdirSync(path) as PathSegment[];
|
||||||
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void { fs.renameSync(from, to); }
|
}
|
||||||
|
lstat(path: AbsoluteFsPath): FileStats {
|
||||||
|
return fs.lstatSync(path);
|
||||||
|
}
|
||||||
|
stat(path: AbsoluteFsPath): FileStats {
|
||||||
|
return fs.statSync(path);
|
||||||
|
}
|
||||||
|
pwd(): AbsoluteFsPath {
|
||||||
|
return this.normalize(process.cwd()) as AbsoluteFsPath;
|
||||||
|
}
|
||||||
|
chdir(dir: AbsoluteFsPath): void {
|
||||||
|
process.chdir(dir);
|
||||||
|
}
|
||||||
|
copyFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void {
|
||||||
|
fs.copyFileSync(from, to);
|
||||||
|
}
|
||||||
|
moveFile(from: AbsoluteFsPath, to: AbsoluteFsPath): void {
|
||||||
|
fs.renameSync(from, to);
|
||||||
|
}
|
||||||
ensureDir(path: AbsoluteFsPath): void {
|
ensureDir(path: AbsoluteFsPath): void {
|
||||||
const parents: AbsoluteFsPath[] = [];
|
const parents: AbsoluteFsPath[] = [];
|
||||||
while (!this.isRoot(path) && !this.exists(path)) {
|
while (!this.isRoot(path) && !this.exists(path)) {
|
||||||
|
@ -41,7 +63,9 @@ export class NodeJSFileSystem implements FileSystem {
|
||||||
this.safeMkdir(parents.pop()!);
|
this.safeMkdir(parents.pop()!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
removeDeep(path: AbsoluteFsPath): void { fsExtra.removeSync(path); }
|
removeDeep(path: AbsoluteFsPath): void {
|
||||||
|
fsExtra.removeSync(path);
|
||||||
|
}
|
||||||
isCaseSensitive(): boolean {
|
isCaseSensitive(): boolean {
|
||||||
if (this._caseSensitive === undefined) {
|
if (this._caseSensitive === undefined) {
|
||||||
this._caseSensitive = this.exists(togglePathCase(__filename));
|
this._caseSensitive = this.exists(togglePathCase(__filename));
|
||||||
|
@ -52,20 +76,30 @@ export class NodeJSFileSystem implements FileSystem {
|
||||||
return this.normalize(p.resolve(...paths)) as AbsoluteFsPath;
|
return this.normalize(p.resolve(...paths)) as AbsoluteFsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirname<T extends string>(file: T): T { return this.normalize(p.dirname(file)) as T; }
|
dirname<T extends string>(file: T): T {
|
||||||
|
return this.normalize(p.dirname(file)) as T;
|
||||||
|
}
|
||||||
join<T extends string>(basePath: T, ...paths: string[]): T {
|
join<T extends string>(basePath: T, ...paths: string[]): T {
|
||||||
return this.normalize(p.join(basePath, ...paths)) as T;
|
return this.normalize(p.join(basePath, ...paths)) as T;
|
||||||
}
|
}
|
||||||
isRoot(path: AbsoluteFsPath): boolean { return this.dirname(path) === this.normalize(path); }
|
isRoot(path: AbsoluteFsPath): boolean {
|
||||||
isRooted(path: string): boolean { return p.isAbsolute(path); }
|
return this.dirname(path) === this.normalize(path);
|
||||||
|
}
|
||||||
|
isRooted(path: string): boolean {
|
||||||
|
return p.isAbsolute(path);
|
||||||
|
}
|
||||||
relative<T extends PathString>(from: T, to: T): PathSegment {
|
relative<T extends PathString>(from: T, to: T): PathSegment {
|
||||||
return relativeFrom(this.normalize(p.relative(from, to)));
|
return relativeFrom(this.normalize(p.relative(from, to)));
|
||||||
}
|
}
|
||||||
basename(filePath: string, extension?: string): PathSegment {
|
basename(filePath: string, extension?: string): PathSegment {
|
||||||
return p.basename(filePath, extension) as PathSegment;
|
return p.basename(filePath, extension) as PathSegment;
|
||||||
}
|
}
|
||||||
extname(path: AbsoluteFsPath|PathSegment): string { return p.extname(path); }
|
extname(path: AbsoluteFsPath|PathSegment): string {
|
||||||
realpath(path: AbsoluteFsPath): AbsoluteFsPath { return this.resolve(fs.realpathSync(path)); }
|
return p.extname(path);
|
||||||
|
}
|
||||||
|
realpath(path: AbsoluteFsPath): AbsoluteFsPath {
|
||||||
|
return this.resolve(fs.realpathSync(path));
|
||||||
|
}
|
||||||
getDefaultLibLocation(): AbsoluteFsPath {
|
getDefaultLibLocation(): AbsoluteFsPath {
|
||||||
return this.resolve(require.resolve('typescript'), '..');
|
return this.resolve(require.resolve('typescript'), '..');
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,8 @@ export function stripExtension(path: string): string {
|
||||||
export function getSourceFileOrError(program: ts.Program, fileName: AbsoluteFsPath): ts.SourceFile {
|
export function getSourceFileOrError(program: ts.Program, fileName: AbsoluteFsPath): ts.SourceFile {
|
||||||
const sf = program.getSourceFile(fileName);
|
const sf = program.getSourceFile(fileName);
|
||||||
if (sf === undefined) {
|
if (sf === undefined) {
|
||||||
throw new Error(
|
throw new Error(`Program does not contain "${fileName}" - available files are ${
|
||||||
`Program does not contain "${fileName}" - available files are ${program.getSourceFiles().map(sf => sf.fileName).join(', ')}`);
|
program.getSourceFiles().map(sf => sf.fileName).join(', ')}`);
|
||||||
}
|
}
|
||||||
return sf;
|
return sf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,37 +11,49 @@ import {absoluteFrom, relativeFrom, setFileSystem} from '../src/helpers';
|
||||||
import {NodeJSFileSystem} from '../src/node_js_file_system';
|
import {NodeJSFileSystem} from '../src/node_js_file_system';
|
||||||
|
|
||||||
describe('path types', () => {
|
describe('path types', () => {
|
||||||
beforeEach(() => { setFileSystem(new NodeJSFileSystem()); });
|
beforeEach(() => {
|
||||||
|
setFileSystem(new NodeJSFileSystem());
|
||||||
|
});
|
||||||
|
|
||||||
describe('absoluteFrom', () => {
|
describe('absoluteFrom', () => {
|
||||||
it('should not throw when creating one from an absolute path',
|
it('should not throw when creating one from an absolute path', () => {
|
||||||
() => { expect(() => absoluteFrom('/test.txt')).not.toThrow(); });
|
expect(() => absoluteFrom('/test.txt')).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
it('should not throw when creating one from a windows absolute path',
|
it('should not throw when creating one from a windows absolute path', () => {
|
||||||
() => { expect(absoluteFrom('C:\\test.txt')).toEqual('C:/test.txt'); });
|
expect(absoluteFrom('C:\\test.txt')).toEqual('C:/test.txt');
|
||||||
|
});
|
||||||
it('should not throw when creating one from a windows absolute path with POSIX separators',
|
it('should not throw when creating one from a windows absolute path with POSIX separators',
|
||||||
() => { expect(absoluteFrom('C:/test.txt')).toEqual('C:/test.txt'); });
|
() => {
|
||||||
it('should support windows drive letters',
|
expect(absoluteFrom('C:/test.txt')).toEqual('C:/test.txt');
|
||||||
() => { expect(absoluteFrom('D:\\foo\\test.txt')).toEqual('D:/foo/test.txt'); });
|
});
|
||||||
it('should convert Windows path separators to POSIX separators',
|
it('should support windows drive letters', () => {
|
||||||
() => { expect(absoluteFrom('C:\\foo\\test.txt')).toEqual('C:/foo/test.txt'); });
|
expect(absoluteFrom('D:\\foo\\test.txt')).toEqual('D:/foo/test.txt');
|
||||||
|
});
|
||||||
|
it('should convert Windows path separators to POSIX separators', () => {
|
||||||
|
expect(absoluteFrom('C:\\foo\\test.txt')).toEqual('C:/foo/test.txt');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should throw when creating one from a non-absolute path',
|
it('should throw when creating one from a non-absolute path', () => {
|
||||||
() => { expect(() => absoluteFrom('test.txt')).toThrow(); });
|
expect(() => absoluteFrom('test.txt')).toThrow();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('relativeFrom', () => {
|
describe('relativeFrom', () => {
|
||||||
it('should not throw when creating one from a relative path',
|
it('should not throw when creating one from a relative path', () => {
|
||||||
() => { expect(() => relativeFrom('a/b/c.txt')).not.toThrow(); });
|
expect(() => relativeFrom('a/b/c.txt')).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
it('should throw when creating one from an absolute path',
|
it('should throw when creating one from an absolute path', () => {
|
||||||
() => { expect(() => relativeFrom('/a/b/c.txt')).toThrow(); });
|
expect(() => relativeFrom('/a/b/c.txt')).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
it('should throw when creating one from a Windows absolute path',
|
it('should throw when creating one from a Windows absolute path', () => {
|
||||||
() => { expect(() => relativeFrom('C:/a/b/c.txt')).toThrow(); });
|
expect(() => relativeFrom('C:/a/b/c.txt')).toThrow();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,4 +10,4 @@ export {Folder, MockFileSystem} from './src/mock_file_system';
|
||||||
export {MockFileSystemNative} from './src/mock_file_system_native';
|
export {MockFileSystemNative} from './src/mock_file_system_native';
|
||||||
export {MockFileSystemPosix} from './src/mock_file_system_posix';
|
export {MockFileSystemPosix} from './src/mock_file_system_posix';
|
||||||
export {MockFileSystemWindows} from './src/mock_file_system_windows';
|
export {MockFileSystemWindows} from './src/mock_file_system_windows';
|
||||||
export {TestFile, initMockFileSystem, runInEachFileSystem} from './src/test_helper';
|
export {initMockFileSystem, runInEachFileSystem, TestFile} from './src/test_helper';
|
||||||
|
|
|
@ -21,9 +21,13 @@ export abstract class MockFileSystem implements FileSystem {
|
||||||
this._cwd = this.normalize(cwd);
|
this._cwd = this.normalize(cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCaseSensitive() { return this._isCaseSensitive; }
|
isCaseSensitive() {
|
||||||
|
return this._isCaseSensitive;
|
||||||
|
}
|
||||||
|
|
||||||
exists(path: AbsoluteFsPath): boolean { return this.findFromPath(path).entity !== null; }
|
exists(path: AbsoluteFsPath): boolean {
|
||||||
|
return this.findFromPath(path).entity !== null;
|
||||||
|
}
|
||||||
|
|
||||||
readFile(path: AbsoluteFsPath): string {
|
readFile(path: AbsoluteFsPath): string {
|
||||||
const {entity} = this.findFromPath(path);
|
const {entity} = this.findFromPath(path);
|
||||||
|
@ -142,7 +146,9 @@ export abstract class MockFileSystem implements FileSystem {
|
||||||
delete entity[basename];
|
delete entity[basename];
|
||||||
}
|
}
|
||||||
|
|
||||||
isRoot(path: AbsoluteFsPath): boolean { return this.dirname(path) === path; }
|
isRoot(path: AbsoluteFsPath): boolean {
|
||||||
|
return this.dirname(path) === path;
|
||||||
|
}
|
||||||
|
|
||||||
extname(path: AbsoluteFsPath|PathSegment): string {
|
extname(path: AbsoluteFsPath|PathSegment): string {
|
||||||
const match = /.+(\.[^.]*)$/.exec(path);
|
const match = /.+(\.[^.]*)$/.exec(path);
|
||||||
|
@ -159,9 +165,13 @@ export abstract class MockFileSystem implements FileSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pwd(): AbsoluteFsPath { return this._cwd; }
|
pwd(): AbsoluteFsPath {
|
||||||
|
return this._cwd;
|
||||||
|
}
|
||||||
|
|
||||||
chdir(path: AbsoluteFsPath): void { this._cwd = this.normalize(path); }
|
chdir(path: AbsoluteFsPath): void {
|
||||||
|
this._cwd = this.normalize(path);
|
||||||
|
}
|
||||||
|
|
||||||
getDefaultLibLocation(): AbsoluteFsPath {
|
getDefaultLibLocation(): AbsoluteFsPath {
|
||||||
// Mimic the node module resolution algorithm and start in the current directory, then look
|
// Mimic the node module resolution algorithm and start in the current directory, then look
|
||||||
|
@ -201,8 +211,12 @@ export abstract class MockFileSystem implements FileSystem {
|
||||||
abstract normalize<T extends PathString>(path: T): T;
|
abstract normalize<T extends PathString>(path: T): T;
|
||||||
protected abstract splitPath<T extends PathString>(path: T): string[];
|
protected abstract splitPath<T extends PathString>(path: T): string[];
|
||||||
|
|
||||||
dump(): Folder { return cloneFolder(this._fileTree); }
|
dump(): Folder {
|
||||||
init(folder: Folder): void { this._fileTree = cloneFolder(folder); }
|
return cloneFolder(this._fileTree);
|
||||||
|
}
|
||||||
|
init(folder: Folder): void {
|
||||||
|
this._fileTree = cloneFolder(folder);
|
||||||
|
}
|
||||||
|
|
||||||
protected findFromPath(path: AbsoluteFsPath, options?: {followSymLinks: boolean}): FindResult {
|
protected findFromPath(path: AbsoluteFsPath, options?: {followSymLinks: boolean}): FindResult {
|
||||||
const followSymLinks = !!options && options.followSymLinks;
|
const followSymLinks = !!options && options.followSymLinks;
|
||||||
|
@ -248,7 +262,9 @@ export interface FindResult {
|
||||||
entity: Entity|null;
|
entity: Entity|null;
|
||||||
}
|
}
|
||||||
export type Entity = Folder|File|SymLink;
|
export type Entity = Folder|File|SymLink;
|
||||||
export interface Folder { [pathSegments: string]: Entity; }
|
export interface Folder {
|
||||||
|
[pathSegments: string]: Entity;
|
||||||
|
}
|
||||||
export type File = string;
|
export type File = string;
|
||||||
export class SymLink {
|
export class SymLink {
|
||||||
constructor(public path: AbsoluteFsPath) {}
|
constructor(public path: AbsoluteFsPath) {}
|
||||||
|
@ -256,13 +272,21 @@ export class SymLink {
|
||||||
|
|
||||||
class MockFileStats implements FileStats {
|
class MockFileStats implements FileStats {
|
||||||
constructor(private entity: Entity) {}
|
constructor(private entity: Entity) {}
|
||||||
isFile(): boolean { return isFile(this.entity); }
|
isFile(): boolean {
|
||||||
isDirectory(): boolean { return isFolder(this.entity); }
|
return isFile(this.entity);
|
||||||
isSymbolicLink(): boolean { return isSymLink(this.entity); }
|
}
|
||||||
|
isDirectory(): boolean {
|
||||||
|
return isFolder(this.entity);
|
||||||
|
}
|
||||||
|
isSymbolicLink(): boolean {
|
||||||
|
return isSymLink(this.entity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockFileSystemError extends Error {
|
class MockFileSystemError extends Error {
|
||||||
constructor(public code: string, public path: string, message: string) { super(message); }
|
constructor(public code: string, public path: string, message: string) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isFile(item: Entity|null): item is File {
|
export function isFile(item: Entity|null): item is File {
|
||||||
|
|
|
@ -15,7 +15,9 @@ import {MockFileSystem} from './mock_file_system';
|
||||||
const isWindows = os.platform() === 'win32';
|
const isWindows = os.platform() === 'win32';
|
||||||
|
|
||||||
export class MockFileSystemNative extends MockFileSystem {
|
export class MockFileSystemNative extends MockFileSystem {
|
||||||
constructor(cwd: AbsoluteFsPath = '/' as AbsoluteFsPath) { super(undefined, cwd); }
|
constructor(cwd: AbsoluteFsPath = '/' as AbsoluteFsPath) {
|
||||||
|
super(undefined, cwd);
|
||||||
|
}
|
||||||
|
|
||||||
// Delegate to the real NodeJSFileSystem for these path related methods
|
// Delegate to the real NodeJSFileSystem for these path related methods
|
||||||
|
|
||||||
|
@ -36,9 +38,13 @@ export class MockFileSystemNative extends MockFileSystem {
|
||||||
return NodeJSFileSystem.prototype.basename.call(this, filePath, extension);
|
return NodeJSFileSystem.prototype.basename.call(this, filePath, extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCaseSensitive() { return NodeJSFileSystem.prototype.isCaseSensitive.call(this); }
|
isCaseSensitive() {
|
||||||
|
return NodeJSFileSystem.prototype.isCaseSensitive.call(this);
|
||||||
|
}
|
||||||
|
|
||||||
isRooted(path: string): boolean { return NodeJSFileSystem.prototype.isRooted.call(this, path); }
|
isRooted(path: string): boolean {
|
||||||
|
return NodeJSFileSystem.prototype.isRooted.call(this, path);
|
||||||
|
}
|
||||||
|
|
||||||
isRoot(path: AbsoluteFsPath): boolean {
|
isRoot(path: AbsoluteFsPath): boolean {
|
||||||
return NodeJSFileSystem.prototype.isRoot.call(this, path);
|
return NodeJSFileSystem.prototype.isRoot.call(this, path);
|
||||||
|
@ -57,5 +63,7 @@ export class MockFileSystemNative extends MockFileSystem {
|
||||||
return NodeJSFileSystem.prototype.normalize.call(this, path) as T;
|
return NodeJSFileSystem.prototype.normalize.call(this, path) as T;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected splitPath<T>(path: string): string[] { return path.split(/[\\\/]/); }
|
protected splitPath<T>(path: string): string[] {
|
||||||
|
return path.split(/[\\\/]/);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@ export class MockFileSystemPosix extends MockFileSystem {
|
||||||
return this.normalize(resolved) as AbsoluteFsPath;
|
return this.normalize(resolved) as AbsoluteFsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
dirname<T extends string>(file: T): T { return this.normalize(p.posix.dirname(file)) as T; }
|
dirname<T extends string>(file: T): T {
|
||||||
|
return this.normalize(p.posix.dirname(file)) as T;
|
||||||
|
}
|
||||||
|
|
||||||
join<T extends string>(basePath: T, ...paths: string[]): T {
|
join<T extends string>(basePath: T, ...paths: string[]): T {
|
||||||
return this.normalize(p.posix.join(basePath, ...paths)) as T;
|
return this.normalize(p.posix.join(basePath, ...paths)) as T;
|
||||||
|
@ -31,9 +33,13 @@ export class MockFileSystemPosix extends MockFileSystem {
|
||||||
return p.posix.basename(filePath, extension) as PathSegment;
|
return p.posix.basename(filePath, extension) as PathSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRooted(path: string): boolean { return path.startsWith('/'); }
|
isRooted(path: string): boolean {
|
||||||
|
return path.startsWith('/');
|
||||||
|
}
|
||||||
|
|
||||||
protected splitPath<T extends PathString>(path: T): string[] { return path.split('/'); }
|
protected splitPath<T extends PathString>(path: T): string[] {
|
||||||
|
return path.split('/');
|
||||||
|
}
|
||||||
|
|
||||||
normalize<T extends PathString>(path: T): T {
|
normalize<T extends PathString>(path: T): T {
|
||||||
return path.replace(/^[a-z]:\//i, '/').replace(/\\/g, '/') as T;
|
return path.replace(/^[a-z]:\//i, '/').replace(/\\/g, '/') as T;
|
||||||
|
|
|
@ -17,7 +17,9 @@ export class MockFileSystemWindows extends MockFileSystem {
|
||||||
return this.normalize(resolved as AbsoluteFsPath);
|
return this.normalize(resolved as AbsoluteFsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
dirname<T extends string>(path: T): T { return this.normalize(p.win32.dirname(path) as T); }
|
dirname<T extends string>(path: T): T {
|
||||||
|
return this.normalize(p.win32.dirname(path) as T);
|
||||||
|
}
|
||||||
|
|
||||||
join<T extends string>(basePath: T, ...paths: string[]): T {
|
join<T extends string>(basePath: T, ...paths: string[]): T {
|
||||||
return this.normalize(p.win32.join(basePath, ...paths)) as T;
|
return this.normalize(p.win32.join(basePath, ...paths)) as T;
|
||||||
|
@ -31,9 +33,13 @@ export class MockFileSystemWindows extends MockFileSystem {
|
||||||
return p.win32.basename(filePath, extension) as PathSegment;
|
return p.win32.basename(filePath, extension) as PathSegment;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRooted(path: string): boolean { return /^([A-Z]:)?([\\\/]|$)/i.test(path); }
|
isRooted(path: string): boolean {
|
||||||
|
return /^([A-Z]:)?([\\\/]|$)/i.test(path);
|
||||||
|
}
|
||||||
|
|
||||||
protected splitPath<T extends PathString>(path: T): string[] { return path.split(/[\\\/]/); }
|
protected splitPath<T extends PathString>(path: T): string[] {
|
||||||
|
return path.split(/[\\\/]/);
|
||||||
|
}
|
||||||
|
|
||||||
normalize<T extends PathString>(path: T): T {
|
normalize<T extends PathString>(path: T): T {
|
||||||
return path.replace(/^[\/\\]/i, 'C:/').replace(/\\/g, '/') as T;
|
return path.replace(/^[\/\\]/i, 'C:/').replace(/\\/g, '/') as T;
|
||||||
|
|
|
@ -47,7 +47,9 @@ function runInFileSystem(os: string, callback: (os: string) => void, error: bool
|
||||||
afterEach(() => setFileSystem(new InvalidFileSystem()));
|
afterEach(() => setFileSystem(new InvalidFileSystem()));
|
||||||
callback(os);
|
callback(os);
|
||||||
if (error) {
|
if (error) {
|
||||||
afterAll(() => { throw new Error(`runInFileSystem limited to ${os}, cannot pass`); });
|
afterAll(() => {
|
||||||
|
throw new Error(`runInFileSystem limited to ${os}, cannot pass`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -125,7 +127,9 @@ function monkeyPatchTypeScript(os: string, fs: MockFileSystem) {
|
||||||
return {files, directories};
|
return {files, directories};
|
||||||
}
|
}
|
||||||
|
|
||||||
function realPath(path: string): string { return fs.realpath(fs.resolve(path)); }
|
function realPath(path: string): string {
|
||||||
|
return fs.realpath(fs.resolve(path));
|
||||||
|
}
|
||||||
|
|
||||||
// Rather than completely re-implementing we are using the `ts.matchFiles` function,
|
// Rather than completely re-implementing we are using the `ts.matchFiles` function,
|
||||||
// which is internal to the `ts` namespace.
|
// which is internal to the `ts` namespace.
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export {AliasStrategy, AliasingHost, PrivateExportAliasingHost, UnifiedModulesAliasingHost} from './src/alias';
|
export {AliasingHost, AliasStrategy, PrivateExportAliasingHost, UnifiedModulesAliasingHost} from './src/alias';
|
||||||
export {ImportRewriter, NoopImportRewriter, R3SymbolsImportRewriter, validateAndRewriteCoreSymbol} from './src/core';
|
export {ImportRewriter, NoopImportRewriter, R3SymbolsImportRewriter, validateAndRewriteCoreSymbol} from './src/core';
|
||||||
export {DefaultImportRecorder, DefaultImportTracker, NOOP_DEFAULT_IMPORT_RECORDER} from './src/default';
|
export {DefaultImportRecorder, DefaultImportTracker, NOOP_DEFAULT_IMPORT_RECORDER} from './src/default';
|
||||||
export {AbsoluteModuleStrategy, ImportFlags, LocalIdentifierStrategy, LogicalProjectStrategy, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesStrategy} from './src/emitter';
|
export {AbsoluteModuleStrategy, ImportFlags, LocalIdentifierStrategy, LogicalProjectStrategy, ReferenceEmitStrategy, ReferenceEmitter, RelativePathStrategy, UnifiedModulesStrategy} from './src/emitter';
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {Expression, ExternalExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {UnifiedModulesHost} from '../../core/api';
|
import {UnifiedModulesHost} from '../../core/api';
|
||||||
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, isNamedClassDeclaration, ReflectionHost} from '../../reflection';
|
||||||
|
|
||||||
import {ImportFlags, ReferenceEmitStrategy} from './emitter';
|
import {ImportFlags, ReferenceEmitStrategy} from './emitter';
|
||||||
import {Reference} from './references';
|
import {Reference} from './references';
|
||||||
|
@ -203,7 +203,9 @@ export class PrivateExportAliasingHost implements AliasingHost {
|
||||||
*
|
*
|
||||||
* Thus, `getAliasIn` always returns `null`.
|
* Thus, `getAliasIn` always returns `null`.
|
||||||
*/
|
*/
|
||||||
getAliasIn(): null { return null; }
|
getAliasIn(): null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -36,11 +36,17 @@ export interface ImportRewriter {
|
||||||
* `ImportRewriter` that does no rewriting.
|
* `ImportRewriter` that does no rewriting.
|
||||||
*/
|
*/
|
||||||
export class NoopImportRewriter implements ImportRewriter {
|
export class NoopImportRewriter implements ImportRewriter {
|
||||||
shouldImportSymbol(symbol: string, specifier: string): boolean { return true; }
|
shouldImportSymbol(symbol: string, specifier: string): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
rewriteSymbol(symbol: string, specifier: string): string { return symbol; }
|
rewriteSymbol(symbol: string, specifier: string): string {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
rewriteSpecifier(specifier: string, inContextOfFile: string): string { return specifier; }
|
rewriteSpecifier(specifier: string, inContextOfFile: string): string {
|
||||||
|
return specifier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +76,9 @@ const CORE_MODULE = '@angular/core';
|
||||||
export class R3SymbolsImportRewriter implements ImportRewriter {
|
export class R3SymbolsImportRewriter implements ImportRewriter {
|
||||||
constructor(private r3SymbolsPath: string) {}
|
constructor(private r3SymbolsPath: string) {}
|
||||||
|
|
||||||
shouldImportSymbol(symbol: string, specifier: string): boolean { return true; }
|
shouldImportSymbol(symbol: string, specifier: string): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
rewriteSymbol(symbol: string, specifier: string): string {
|
rewriteSymbol(symbol: string, specifier: string): string {
|
||||||
if (specifier !== CORE_MODULE) {
|
if (specifier !== CORE_MODULE) {
|
||||||
|
@ -89,8 +97,8 @@ export class R3SymbolsImportRewriter implements ImportRewriter {
|
||||||
|
|
||||||
const relativePathToR3Symbols = relativePathBetween(inContextOfFile, this.r3SymbolsPath);
|
const relativePathToR3Symbols = relativePathBetween(inContextOfFile, this.r3SymbolsPath);
|
||||||
if (relativePathToR3Symbols === null) {
|
if (relativePathToR3Symbols === null) {
|
||||||
throw new Error(
|
throw new Error(`Failed to rewrite import inside ${CORE_MODULE}: ${inContextOfFile} -> ${
|
||||||
`Failed to rewrite import inside ${CORE_MODULE}: ${inContextOfFile} -> ${this.r3SymbolsPath}`);
|
this.r3SymbolsPath}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return relativePathToR3Symbols;
|
return relativePathToR3Symbols;
|
||||||
|
|
|
@ -127,7 +127,9 @@ export class DefaultImportTracker implements DefaultImportRecorder {
|
||||||
*/
|
*/
|
||||||
importPreservingTransformer(): ts.TransformerFactory<ts.SourceFile> {
|
importPreservingTransformer(): ts.TransformerFactory<ts.SourceFile> {
|
||||||
return (context: ts.TransformationContext) => {
|
return (context: ts.TransformationContext) => {
|
||||||
return (sf: ts.SourceFile) => { return this.transformSourceFile(sf); };
|
return (sf: ts.SourceFile) => {
|
||||||
|
return this.transformSourceFile(sf);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {Expression, ExternalExpr, ExternalReference, WrappedNodeExpr} from '@ang
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {UnifiedModulesHost} from '../../core/api';
|
import {UnifiedModulesHost} from '../../core/api';
|
||||||
import {LogicalFileSystem, LogicalProjectPath, PathSegment, absoluteFromSourceFile, dirname, relative} from '../../file_system';
|
import {absoluteFromSourceFile, dirname, LogicalFileSystem, LogicalProjectPath, PathSegment, relative} from '../../file_system';
|
||||||
import {stripExtension} from '../../file_system/src/util';
|
import {stripExtension} from '../../file_system/src/util';
|
||||||
import {ReflectionHost} from '../../reflection';
|
import {ReflectionHost} from '../../reflection';
|
||||||
import {getSourceFile, isDeclaration, isTypeDeclaration, nodeNameForError} from '../../util/src/typescript';
|
import {getSourceFile, isDeclaration, isTypeDeclaration, nodeNameForError} from '../../util/src/typescript';
|
||||||
|
@ -93,8 +93,8 @@ export class ReferenceEmitter {
|
||||||
return emitted;
|
return emitted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(`Unable to write a reference to ${nodeNameForError(ref.node)} in ${
|
||||||
`Unable to write a reference to ${nodeNameForError(ref.node)} in ${ref.node.getSourceFile().fileName} from ${context.fileName}`);
|
ref.node.getSourceFile().fileName} from ${context.fileName}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,11 +149,11 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
|
||||||
return null;
|
return null;
|
||||||
} else if (!isDeclaration(ref.node)) {
|
} else if (!isDeclaration(ref.node)) {
|
||||||
// It's not possible to import something which isn't a declaration.
|
// It's not possible to import something which isn't a declaration.
|
||||||
throw new Error(
|
throw new Error(`Debug assert: unable to import a Reference to non-declaration of type ${
|
||||||
`Debug assert: unable to import a Reference to non-declaration of type ${ts.SyntaxKind[ref.node.kind]}.`);
|
ts.SyntaxKind[ref.node.kind]}.`);
|
||||||
} else if ((importFlags & ImportFlags.AllowTypeImports) === 0 && isTypeDeclaration(ref.node)) {
|
} else if ((importFlags & ImportFlags.AllowTypeImports) === 0 && isTypeDeclaration(ref.node)) {
|
||||||
throw new Error(
|
throw new Error(`Importing a type-only declaration of type ${
|
||||||
`Importing a type-only declaration of type ${ts.SyntaxKind[ref.node.kind]} in a value position is not allowed.`);
|
ts.SyntaxKind[ref.node.kind]} in a value position is not allowed.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the exported name of the declaration, if one is available.
|
// Try to find the exported name of the declaration, if one is available.
|
||||||
|
@ -162,8 +162,9 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
|
||||||
if (symbolName === null) {
|
if (symbolName === null) {
|
||||||
// TODO(alxhub): make this error a ts.Diagnostic pointing at whatever caused this import to be
|
// TODO(alxhub): make this error a ts.Diagnostic pointing at whatever caused this import to be
|
||||||
// triggered.
|
// triggered.
|
||||||
throw new Error(
|
throw new Error(`Symbol ${ref.debugName} declared in ${
|
||||||
`Symbol ${ref.debugName} declared in ${getSourceFile(ref.node).fileName} is not exported from ${specifier} (import into ${context.fileName})`);
|
getSourceFile(ref.node).fileName} is not exported from ${specifier} (import into ${
|
||||||
|
context.fileName})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ExternalExpr(new ExternalReference(specifier, symbolName));
|
return new ExternalExpr(new ExternalReference(specifier, symbolName));
|
||||||
|
|
|
@ -80,7 +80,9 @@ export class Reference<T extends ts.Node = ts.Node> {
|
||||||
*
|
*
|
||||||
* See `bestGuessOwningModule`.
|
* See `bestGuessOwningModule`.
|
||||||
*/
|
*/
|
||||||
get hasOwningModuleGuess(): boolean { return this.bestGuessOwningModule !== null; }
|
get hasOwningModuleGuess(): boolean {
|
||||||
|
return this.bestGuessOwningModule !== null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A name for the node, if one is available.
|
* A name for the node, if one is available.
|
||||||
|
@ -93,14 +95,18 @@ export class Reference<T extends ts.Node = ts.Node> {
|
||||||
return id !== null ? id.text : null;
|
return id !== null ? id.text : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get alias(): Expression|null { return this._alias; }
|
get alias(): Expression|null {
|
||||||
|
return this._alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record a `ts.Identifier` by which it's valid to refer to this node, within the context of this
|
* Record a `ts.Identifier` by which it's valid to refer to this node, within the context of this
|
||||||
* `Reference`.
|
* `Reference`.
|
||||||
*/
|
*/
|
||||||
addIdentifier(identifier: ts.Identifier): void { this.identifiers.push(identifier); }
|
addIdentifier(identifier: ts.Identifier): void {
|
||||||
|
this.identifiers.push(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a `ts.Identifier` within this `Reference` that can be used to refer within the context of a
|
* Get a `ts.Identifier` within this `Reference` that can be used to refer within the context of a
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
import {ExternalExpr} from '@angular/compiler';
|
import {ExternalExpr} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {LogicalFileSystem, absoluteFrom as _} from '../../file_system';
|
import {absoluteFrom as _, LogicalFileSystem} from '../../file_system';
|
||||||
import {TestFile, runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem, TestFile} from '../../file_system/testing';
|
||||||
import {Declaration, TypeScriptReflectionHost} from '../../reflection';
|
import {Declaration, TypeScriptReflectionHost} from '../../reflection';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {AbsoluteModuleStrategy, ImportFlags, LogicalProjectStrategy} from '../src/emitter';
|
import {AbsoluteModuleStrategy, ImportFlags, LogicalProjectStrategy} from '../src/emitter';
|
||||||
|
@ -139,7 +139,9 @@ runInEachFileSystem(() => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const fakeExports = new Map<string, Declaration>();
|
const fakeExports = new Map<string, Declaration>();
|
||||||
realExports.forEach((decl, name) => { fakeExports.set(`test${name}`, decl); });
|
realExports.forEach((decl, name) => {
|
||||||
|
fakeExports.set(`test${name}`, decl);
|
||||||
|
});
|
||||||
return fakeExports;
|
return fakeExports;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,9 @@ export class FileDependencyGraph<T extends{fileName: string} = ts.SourceFile> im
|
||||||
DependencyTracker<T> {
|
DependencyTracker<T> {
|
||||||
private nodes = new Map<T, FileNode>();
|
private nodes = new Map<T, FileNode>();
|
||||||
|
|
||||||
addDependency(from: T, on: T): void { this.nodeFor(from).dependsOn.add(on.fileName); }
|
addDependency(from: T, on: T): void {
|
||||||
|
this.nodeFor(from).dependsOn.add(on.fileName);
|
||||||
|
}
|
||||||
|
|
||||||
addResourceDependency(from: T, resource: AbsoluteFsPath): void {
|
addResourceDependency(from: T, resource: AbsoluteFsPath): void {
|
||||||
this.nodeFor(from).usesResources.add(resource);
|
this.nodeFor(from).usesResources.add(resource);
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom} from '../../file_system';
|
import {absoluteFrom, AbsoluteFsPath} from '../../file_system';
|
||||||
import {ClassRecord, TraitCompiler} from '../../transform';
|
import {ClassRecord, TraitCompiler} from '../../transform';
|
||||||
import {IncrementalBuild} from '../api';
|
import {IncrementalBuild} from '../api';
|
||||||
|
|
||||||
|
@ -194,9 +194,13 @@ export class IncrementalDriver implements IncrementalBuild<ClassRecord> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
recordSuccessfulEmit(sf: ts.SourceFile): void { this.state.pendingEmit.delete(sf.fileName); }
|
recordSuccessfulEmit(sf: ts.SourceFile): void {
|
||||||
|
this.state.pendingEmit.delete(sf.fileName);
|
||||||
|
}
|
||||||
|
|
||||||
safeToSkipEmit(sf: ts.SourceFile): boolean { return !this.state.pendingEmit.has(sf.fileName); }
|
safeToSkipEmit(sf: ts.SourceFile): boolean {
|
||||||
|
return !this.state.pendingEmit.has(sf.fileName);
|
||||||
|
}
|
||||||
|
|
||||||
priorWorkFor(sf: ts.SourceFile): ClassRecord[]|null {
|
priorWorkFor(sf: ts.SourceFile): ClassRecord[]|null {
|
||||||
if (this.state.lastGood === null || this.logicalChanges === null) {
|
if (this.state.lastGood === null || this.logicalChanges === null) {
|
||||||
|
|
|
@ -43,13 +43,19 @@ interface ExpressionIdentifier extends TemplateIdentifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Describes a property accessed in a template. */
|
/** Describes a property accessed in a template. */
|
||||||
export interface PropertyIdentifier extends ExpressionIdentifier { kind: IdentifierKind.Property; }
|
export interface PropertyIdentifier extends ExpressionIdentifier {
|
||||||
|
kind: IdentifierKind.Property;
|
||||||
|
}
|
||||||
|
|
||||||
/** Describes a method accessed in a template. */
|
/** Describes a method accessed in a template. */
|
||||||
export interface MethodIdentifier extends ExpressionIdentifier { kind: IdentifierKind.Method; }
|
export interface MethodIdentifier extends ExpressionIdentifier {
|
||||||
|
kind: IdentifierKind.Method;
|
||||||
|
}
|
||||||
|
|
||||||
/** Describes an element attribute in a template. */
|
/** Describes an element attribute in a template. */
|
||||||
export interface AttributeIdentifier extends TemplateIdentifier { kind: IdentifierKind.Attribute; }
|
export interface AttributeIdentifier extends TemplateIdentifier {
|
||||||
|
kind: IdentifierKind.Attribute;
|
||||||
|
}
|
||||||
|
|
||||||
/** A reference to a directive node and its selector. */
|
/** A reference to a directive node and its selector. */
|
||||||
interface DirectiveReference {
|
interface DirectiveReference {
|
||||||
|
@ -96,7 +102,9 @@ export interface ReferenceIdentifier extends TemplateIdentifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Describes a template variable like "foo" in `<div *ngFor="let foo of foos"></div>`. */
|
/** Describes a template variable like "foo" in `<div *ngFor="let foo of foos"></div>`. */
|
||||||
export interface VariableIdentifier extends TemplateIdentifier { kind: IdentifierKind.Variable; }
|
export interface VariableIdentifier extends TemplateIdentifier {
|
||||||
|
kind: IdentifierKind.Variable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Identifiers recorded at the top level of the template, without any context about the HTML nodes
|
* Identifiers recorded at the top level of the template, without any context about the HTML nodes
|
||||||
|
|
|
@ -56,5 +56,7 @@ export class IndexingContext {
|
||||||
/**
|
/**
|
||||||
* Adds a component to the context.
|
* Adds a component to the context.
|
||||||
*/
|
*/
|
||||||
addComponent(info: ComponentInfo) { this.components.add(info); }
|
addComponent(info: ComponentInfo) {
|
||||||
|
this.components.add(info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,9 @@ class ExpressionVisitor extends RecursiveAstVisitor {
|
||||||
return visitor.identifiers;
|
return visitor.identifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
visit(ast: AST) { ast.visit(this); }
|
visit(ast: AST) {
|
||||||
|
ast.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
visitMethodCall(ast: MethodCall, context: {}) {
|
visitMethodCall(ast: MethodCall, context: {}) {
|
||||||
this.visitIdentifier(ast, IdentifierKind.Method);
|
this.visitIdentifier(ast, IdentifierKind.Method);
|
||||||
|
@ -144,16 +146,22 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
|
||||||
*
|
*
|
||||||
* @param boundTemplate bound template target
|
* @param boundTemplate bound template target
|
||||||
*/
|
*/
|
||||||
constructor(private boundTemplate: BoundTarget<ComponentMeta>) { super(); }
|
constructor(private boundTemplate: BoundTarget<ComponentMeta>) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visits a node in the template.
|
* Visits a node in the template.
|
||||||
*
|
*
|
||||||
* @param node node to visit
|
* @param node node to visit
|
||||||
*/
|
*/
|
||||||
visit(node: HTMLNode) { node.visit(this); }
|
visit(node: HTMLNode) {
|
||||||
|
node.visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
visitAll(nodes: TmplAstNode[]) { nodes.forEach(node => this.visit(node)); }
|
visitAll(nodes: TmplAstNode[]) {
|
||||||
|
nodes.forEach(node => this.visit(node));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an identifier for an HTML element and visit its children recursively.
|
* Add an identifier for an HTML element and visit its children recursively.
|
||||||
|
@ -204,8 +212,12 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
|
||||||
this.targetToIdentifier.bind(this));
|
this.targetToIdentifier.bind(this));
|
||||||
identifiers.forEach(id => this.identifiers.add(id));
|
identifiers.forEach(id => this.identifiers.add(id));
|
||||||
}
|
}
|
||||||
visitBoundEvent(attribute: TmplAstBoundEvent) { this.visitExpression(attribute.handler); }
|
visitBoundEvent(attribute: TmplAstBoundEvent) {
|
||||||
visitBoundText(text: TmplAstBoundText) { this.visitExpression(text.value); }
|
this.visitExpression(attribute.handler);
|
||||||
|
}
|
||||||
|
visitBoundText(text: TmplAstBoundText) {
|
||||||
|
this.visitExpression(text.value);
|
||||||
|
}
|
||||||
visitReference(reference: TmplAstReference) {
|
visitReference(reference: TmplAstReference) {
|
||||||
const referenceIdentifer = this.targetToIdentifier(reference);
|
const referenceIdentifer = this.targetToIdentifier(reference);
|
||||||
|
|
||||||
|
@ -254,7 +266,8 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
|
||||||
|
|
||||||
const identifier = {
|
const identifier = {
|
||||||
name,
|
name,
|
||||||
span: absoluteSpan, kind,
|
span: absoluteSpan,
|
||||||
|
kind,
|
||||||
attributes: new Set(attributes),
|
attributes: new Set(attributes),
|
||||||
usedDirectives: new Set(usedDirectives.map(dir => {
|
usedDirectives: new Set(usedDirectives.map(dir => {
|
||||||
return {
|
return {
|
||||||
|
@ -304,7 +317,8 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
|
||||||
identifier = {
|
identifier = {
|
||||||
name,
|
name,
|
||||||
span,
|
span,
|
||||||
kind: IdentifierKind.Reference, target,
|
kind: IdentifierKind.Reference,
|
||||||
|
target,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
identifier = {
|
identifier = {
|
||||||
|
|
|
@ -19,7 +19,8 @@ runInEachFileSystem(() => {
|
||||||
|
|
||||||
context.addComponent({
|
context.addComponent({
|
||||||
declaration,
|
declaration,
|
||||||
selector: 'c-selector', boundTemplate,
|
selector: 'c-selector',
|
||||||
|
boundTemplate,
|
||||||
templateMeta: {
|
templateMeta: {
|
||||||
isInline: false,
|
isInline: false,
|
||||||
file: new ParseSourceFile('<div></div>', util.getTestFilePath()),
|
file: new ParseSourceFile('<div></div>', util.getTestFilePath()),
|
||||||
|
@ -29,7 +30,8 @@ runInEachFileSystem(() => {
|
||||||
expect(context.components).toEqual(new Set([
|
expect(context.components).toEqual(new Set([
|
||||||
{
|
{
|
||||||
declaration,
|
declaration,
|
||||||
selector: 'c-selector', boundTemplate,
|
selector: 'c-selector',
|
||||||
|
boundTemplate,
|
||||||
templateMeta: {
|
templateMeta: {
|
||||||
isInline: false,
|
isInline: false,
|
||||||
file: new ParseSourceFile('<div></div>', util.getTestFilePath()),
|
file: new ParseSourceFile('<div></div>', util.getTestFilePath()),
|
||||||
|
|
|
@ -314,7 +314,8 @@ runInEachFileSystem(() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const refArray = Array.from(refs);
|
const refArray = Array.from(refs);
|
||||||
expect(refArray).toEqual(jasmine.arrayContaining([{
|
expect(refArray).toEqual(
|
||||||
|
jasmine.arrayContaining([{
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
kind: IdentifierKind.Reference,
|
kind: IdentifierKind.Reference,
|
||||||
span: new AbsoluteSourceSpan(6, 9),
|
span: new AbsoluteSourceSpan(6, 9),
|
||||||
|
@ -334,7 +335,8 @@ runInEachFileSystem(() => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const refArray = Array.from(refs);
|
const refArray = Array.from(refs);
|
||||||
expect(refArray).toEqual(jasmine.arrayContaining([{
|
expect(refArray).toEqual(
|
||||||
|
jasmine.arrayContaining([{
|
||||||
name: 'foo',
|
name: 'foo',
|
||||||
kind: IdentifierKind.Reference,
|
kind: IdentifierKind.Reference,
|
||||||
span: new AbsoluteSourceSpan(12, 15),
|
span: new AbsoluteSourceSpan(12, 15),
|
||||||
|
|
|
@ -6,9 +6,10 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {BoundTarget, CssSelector, ParseTemplateOptions, R3TargetBinder, SelectorMatcher, parseTemplate} from '@angular/compiler';
|
import {BoundTarget, CssSelector, parseTemplate, ParseTemplateOptions, R3TargetBinder, SelectorMatcher} from '@angular/compiler';
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
import {AbsoluteFsPath, absoluteFrom} from '../../file_system';
|
|
||||||
|
import {absoluteFrom, AbsoluteFsPath} from '../../file_system';
|
||||||
import {Reference} from '../../imports';
|
import {Reference} from '../../imports';
|
||||||
import {ClassDeclaration} from '../../reflection';
|
import {ClassDeclaration} from '../../reflection';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {Reference} from '../../imports';
|
import {Reference} from '../../imports';
|
||||||
import {ClassDeclaration, ReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
import {ClassDeclaration, isNamedClassDeclaration, ReflectionHost} from '../../reflection';
|
||||||
|
|
||||||
import {DirectiveMeta, MetadataReader, NgModuleMeta, PipeMeta} from './api';
|
import {DirectiveMeta, MetadataReader, NgModuleMeta, PipeMeta} from './api';
|
||||||
import {extractDirectiveGuards, extractReferencesFromType, readStringArrayType, readStringMapType, readStringType} from './util';
|
import {extractDirectiveGuards, extractReferencesFromType, readStringArrayType, readStringMapType, readStringType} from './util';
|
||||||
|
|
|
@ -31,9 +31,15 @@ export class LocalMetadataRegistry implements MetadataRegistry, MetadataReader {
|
||||||
return this.pipes.has(ref.node) ? this.pipes.get(ref.node)! : null;
|
return this.pipes.has(ref.node) ? this.pipes.get(ref.node)! : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerDirectiveMetadata(meta: DirectiveMeta): void { this.directives.set(meta.ref.node, meta); }
|
registerDirectiveMetadata(meta: DirectiveMeta): void {
|
||||||
registerNgModuleMetadata(meta: NgModuleMeta): void { this.ngModules.set(meta.ref.node, meta); }
|
this.directives.set(meta.ref.node, meta);
|
||||||
registerPipeMetadata(meta: PipeMeta): void { this.pipes.set(meta.ref.node, meta); }
|
}
|
||||||
|
registerNgModuleMetadata(meta: NgModuleMeta): void {
|
||||||
|
this.ngModules.set(meta.ref.node, meta);
|
||||||
|
}
|
||||||
|
registerPipeMetadata(meta: PipeMeta): void {
|
||||||
|
this.pipes.set(meta.ref.node, meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,7 +76,9 @@ export class InjectableClassRegistry {
|
||||||
|
|
||||||
constructor(private host: ReflectionHost) {}
|
constructor(private host: ReflectionHost) {}
|
||||||
|
|
||||||
registerInjectable(declaration: ClassDeclaration): void { this.classes.add(declaration); }
|
registerInjectable(declaration: ClassDeclaration): void {
|
||||||
|
this.classes.add(declaration);
|
||||||
|
}
|
||||||
|
|
||||||
isInjectable(declaration: ClassDeclaration): boolean {
|
isInjectable(declaration: ClassDeclaration): boolean {
|
||||||
// Figure out whether the class is injectable based on the registered classes, otherwise
|
// Figure out whether the class is injectable based on the registered classes, otherwise
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {Reference} from '../../imports';
|
import {Reference} from '../../imports';
|
||||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ReflectionHost, isNamedClassDeclaration, reflectTypeEntityToDeclaration} from '../../reflection';
|
import {ClassDeclaration, ClassMember, ClassMemberKind, isNamedClassDeclaration, ReflectionHost, reflectTypeEntityToDeclaration} from '../../reflection';
|
||||||
import {nodeDebugInfo} from '../../util/src/typescript';
|
import {nodeDebugInfo} from '../../util/src/typescript';
|
||||||
|
|
||||||
import {DirectiveMeta, MetadataReader, NgModuleMeta, PipeMeta, TemplateGuardMeta} from './api';
|
import {DirectiveMeta, MetadataReader, NgModuleMeta, PipeMeta, TemplateGuardMeta} from './api';
|
||||||
|
|
|
@ -13,7 +13,9 @@ import {ImportFlags, Reference, ReferenceEmitter} from '../../imports';
|
||||||
import {PartialEvaluator, ResolvedValueMap} from '../../partial_evaluator';
|
import {PartialEvaluator, ResolvedValueMap} from '../../partial_evaluator';
|
||||||
import {ReflectionHost} from '../../reflection';
|
import {ReflectionHost} from '../../reflection';
|
||||||
|
|
||||||
export interface DtsHandler { addTypeReplacement(node: ts.Declaration, type: Type): void; }
|
export interface DtsHandler {
|
||||||
|
addTypeReplacement(node: ts.Declaration, type: Type): void;
|
||||||
|
}
|
||||||
|
|
||||||
export class ModuleWithProvidersScanner {
|
export class ModuleWithProvidersScanner {
|
||||||
constructor(
|
constructor(
|
||||||
|
|
|
@ -15,6 +15,8 @@ export const NOOP_PERF_RECORDER: PerfRecorder = {
|
||||||
mark: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
mark: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
||||||
void => {},
|
void => {},
|
||||||
start: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
start: (name: string, node: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
||||||
number => { return 0;},
|
number => {
|
||||||
|
return 0;
|
||||||
|
},
|
||||||
stop: (span: number|false): void => {},
|
stop: (span: number|false): void => {},
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,9 @@ export class PerfTracker implements PerfRecorder {
|
||||||
|
|
||||||
private constructor(private zeroTime: HrTime) {}
|
private constructor(private zeroTime: HrTime) {}
|
||||||
|
|
||||||
static zeroedToNow(): PerfTracker { return new PerfTracker(mark()); }
|
static zeroedToNow(): PerfTracker {
|
||||||
|
return new PerfTracker(mark());
|
||||||
|
}
|
||||||
|
|
||||||
mark(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
mark(name: string, node?: ts.SourceFile|ts.Declaration, category?: string, detail?: string):
|
||||||
void {
|
void {
|
||||||
|
@ -73,7 +75,9 @@ export class PerfTracker implements PerfRecorder {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
asJson(): unknown { return this.log; }
|
asJson(): unknown {
|
||||||
|
return this.log;
|
||||||
|
}
|
||||||
|
|
||||||
serializeToFile(target: string, host: ts.CompilerHost): void {
|
serializeToFile(target: string, host: ts.CompilerHost): void {
|
||||||
const json = JSON.stringify(this.log, null, 2);
|
const json = JSON.stringify(this.log, null, 2);
|
||||||
|
|
|
@ -77,7 +77,9 @@ export class NgtscProgram implements api.Program {
|
||||||
new NgCompiler(this.host, options, this.tsProgram, reuseProgram, this.perfRecorder);
|
new NgCompiler(this.host, options, this.tsProgram, reuseProgram, this.perfRecorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTsProgram(): ts.Program { return this.tsProgram; }
|
getTsProgram(): ts.Program {
|
||||||
|
return this.tsProgram;
|
||||||
|
}
|
||||||
|
|
||||||
getTsOptionDiagnostics(cancellationToken?: ts.CancellationToken|
|
getTsOptionDiagnostics(cancellationToken?: ts.CancellationToken|
|
||||||
undefined): readonly ts.Diagnostic[] {
|
undefined): readonly ts.Diagnostic[] {
|
||||||
|
@ -137,8 +139,8 @@ export class NgtscProgram implements api.Program {
|
||||||
}
|
}
|
||||||
|
|
||||||
getNgSemanticDiagnostics(
|
getNgSemanticDiagnostics(
|
||||||
fileName?: string|undefined, cancellationToken?: ts.CancellationToken|
|
fileName?: string|undefined, cancellationToken?: ts.CancellationToken|undefined):
|
||||||
undefined): readonly(ts.Diagnostic|api.Diagnostic)[] {
|
readonly(ts.Diagnostic|api.Diagnostic)[] {
|
||||||
let sf: ts.SourceFile|undefined = undefined;
|
let sf: ts.SourceFile|undefined = undefined;
|
||||||
if (fileName !== undefined) {
|
if (fileName !== undefined) {
|
||||||
sf = this.tsProgram.getSourceFile(fileName);
|
sf = this.tsProgram.getSourceFile(fileName);
|
||||||
|
@ -161,14 +163,17 @@ export class NgtscProgram implements api.Program {
|
||||||
* This is used by the Angular CLI to allow for spawning (async) child compilations for things
|
* This is used by the Angular CLI to allow for spawning (async) child compilations for things
|
||||||
* like SASS files used in `styleUrls`.
|
* like SASS files used in `styleUrls`.
|
||||||
*/
|
*/
|
||||||
loadNgStructureAsync(): Promise<void> { return this.compiler.analyzeAsync(); }
|
loadNgStructureAsync(): Promise<void> {
|
||||||
|
return this.compiler.analyzeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
listLazyRoutes(entryRoute?: string|undefined): api.LazyRoute[] {
|
listLazyRoutes(entryRoute?: string|undefined): api.LazyRoute[] {
|
||||||
return this.compiler.listLazyRoutes(entryRoute);
|
return this.compiler.listLazyRoutes(entryRoute);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit(opts?: {
|
emit(opts?: {
|
||||||
emitFlags?: api.EmitFlags | undefined; cancellationToken?: ts.CancellationToken | undefined;
|
emitFlags?: api.EmitFlags|undefined;
|
||||||
|
cancellationToken?: ts.CancellationToken | undefined;
|
||||||
customTransformers?: api.CustomTransformers | undefined;
|
customTransformers?: api.CustomTransformers | undefined;
|
||||||
emitCallback?: api.TsEmitCallback | undefined;
|
emitCallback?: api.TsEmitCallback | undefined;
|
||||||
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined;
|
mergeEmitResultsCallback?: api.TsMergeEmitResultsCallback | undefined;
|
||||||
|
@ -221,7 +226,8 @@ export class NgtscProgram implements api.Program {
|
||||||
program: this.tsProgram,
|
program: this.tsProgram,
|
||||||
host: this.host,
|
host: this.host,
|
||||||
options: this.options,
|
options: this.options,
|
||||||
emitOnlyDtsFiles: false, writeFile,
|
emitOnlyDtsFiles: false,
|
||||||
|
writeFile,
|
||||||
customTransformers: {
|
customTransformers: {
|
||||||
before: beforeTransforms,
|
before: beforeTransforms,
|
||||||
after: customTransforms && customTransforms.afterTs,
|
after: customTransforms && customTransforms.afterTs,
|
||||||
|
@ -257,9 +263,14 @@ export class NgtscProgram implements api.Program {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultEmitCallback: api.TsEmitCallback =
|
const defaultEmitCallback: api.TsEmitCallback = ({
|
||||||
({program, targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles,
|
program,
|
||||||
customTransformers}) =>
|
targetSourceFile,
|
||||||
|
writeFile,
|
||||||
|
cancellationToken,
|
||||||
|
emitOnlyDtsFiles,
|
||||||
|
customTransformers
|
||||||
|
}) =>
|
||||||
program.emit(
|
program.emit(
|
||||||
targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
|
targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
|
||||||
|
|
||||||
|
|
|
@ -241,8 +241,7 @@ export interface ClassMember {
|
||||||
*/
|
*/
|
||||||
export type TypeValueReference = {
|
export type TypeValueReference = {
|
||||||
local: true; expression: ts.Expression; defaultImportStatement: ts.ImportDeclaration | null;
|
local: true; expression: ts.Expression; defaultImportStatement: ts.ImportDeclaration | null;
|
||||||
} |
|
}|{
|
||||||
{
|
|
||||||
local: false;
|
local: false;
|
||||||
name: string;
|
name: string;
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, Decorator, FunctionDefinition, Import, ReflectionHost, isDecoratorIdentifier} from './host';
|
import {ClassDeclaration, ClassMember, ClassMemberKind, CtorParameter, Declaration, Decorator, FunctionDefinition, Import, isDecoratorIdentifier, ReflectionHost} from './host';
|
||||||
import {typeToValue} from './type_to_value';
|
import {typeToValue} from './type_to_value';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,8 +76,10 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
nameNode: node.name, typeValueReference,
|
nameNode: node.name,
|
||||||
typeNode: originalTypeNode, decorators,
|
typeValueReference,
|
||||||
|
typeNode: originalTypeNode,
|
||||||
|
decorators,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -183,11 +185,17 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
return declaration.initializer || null;
|
return declaration.initializer || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getDtsDeclaration(_: ts.Declaration): ts.Declaration|null { return null; }
|
getDtsDeclaration(_: ts.Declaration): ts.Declaration|null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
getInternalNameOfClass(clazz: ClassDeclaration): ts.Identifier { return clazz.name; }
|
getInternalNameOfClass(clazz: ClassDeclaration): ts.Identifier {
|
||||||
|
return clazz.name;
|
||||||
|
}
|
||||||
|
|
||||||
getAdjacentNameOfClass(clazz: ClassDeclaration): ts.Identifier { return clazz.name; }
|
getAdjacentNameOfClass(clazz: ClassDeclaration): ts.Identifier {
|
||||||
|
return clazz.name;
|
||||||
|
}
|
||||||
|
|
||||||
protected getDirectImportOfIdentifier(id: ts.Identifier): Import|null {
|
protected getDirectImportOfIdentifier(id: ts.Identifier): Import|null {
|
||||||
const symbol = this.checker.getSymbolAtLocation(id);
|
const symbol = this.checker.getSymbolAtLocation(id);
|
||||||
|
@ -305,12 +313,14 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
if (symbol.valueDeclaration !== undefined) {
|
if (symbol.valueDeclaration !== undefined) {
|
||||||
return {
|
return {
|
||||||
node: symbol.valueDeclaration,
|
node: symbol.valueDeclaration,
|
||||||
known: null, viaModule,
|
known: null,
|
||||||
|
viaModule,
|
||||||
};
|
};
|
||||||
} else if (symbol.declarations !== undefined && symbol.declarations.length > 0) {
|
} else if (symbol.declarations !== undefined && symbol.declarations.length > 0) {
|
||||||
return {
|
return {
|
||||||
node: symbol.declarations[0],
|
node: symbol.declarations[0],
|
||||||
known: null, viaModule,
|
known: null,
|
||||||
|
viaModule,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
@ -342,7 +352,9 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
return {
|
return {
|
||||||
name: decoratorIdentifier.text,
|
name: decoratorIdentifier.text,
|
||||||
identifier: decoratorExpr,
|
identifier: decoratorExpr,
|
||||||
import: importDecl, node, args,
|
import: importDecl,
|
||||||
|
node,
|
||||||
|
args,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,8 +394,14 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
node,
|
node,
|
||||||
implementation: node, kind,
|
implementation: node,
|
||||||
type: node.type || null, name, nameNode, decorators, value, isStatic,
|
kind,
|
||||||
|
type: node.type || null,
|
||||||
|
name,
|
||||||
|
nameNode,
|
||||||
|
decorators,
|
||||||
|
value,
|
||||||
|
isStatic,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,7 +233,6 @@ runInEachFileSystem(() => {
|
||||||
expectParameter(args[0], 'bar', 'Bar');
|
expectParameter(args[0], 'bar', 'Bar');
|
||||||
expectParameter(args[1], 'baz', 'Baz');
|
expectParameter(args[1], 'baz', 'Baz');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -467,8 +466,8 @@ runInEachFileSystem(() => {
|
||||||
expect(param.typeValueReference.moduleName).toEqual(type.moduleName);
|
expect(param.typeValueReference.moduleName).toEqual(type.moduleName);
|
||||||
expect(param.typeValueReference.name).toEqual(type.name);
|
expect(param.typeValueReference.name).toEqual(type.name);
|
||||||
} else {
|
} else {
|
||||||
return fail(
|
return fail(`Mismatch between typeValueReference and expected type: ${param.name} / ${
|
||||||
`Mismatch between typeValueReference and expected type: ${param.name} / ${param.typeValueReference.local}`);
|
param.typeValueReference.local}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decorator !== undefined) {
|
if (decorator !== undefined) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import * as ts from 'typescript';
|
||||||
|
|
||||||
import {ResourceLoader} from '../../annotations';
|
import {ResourceLoader} from '../../annotations';
|
||||||
import {ExtendedTsCompilerHost} from '../../core/api';
|
import {ExtendedTsCompilerHost} from '../../core/api';
|
||||||
import {AbsoluteFsPath, PathSegment, join} from '../../file_system';
|
import {AbsoluteFsPath, join, PathSegment} from '../../file_system';
|
||||||
import {getRootDirs} from '../../util/src/typescript';
|
import {getRootDirs} from '../../util/src/typescript';
|
||||||
|
|
||||||
const CSS_PREPROCESSOR_EXT = /(\.scss|\.sass|\.less|\.styl)$/;
|
const CSS_PREPROCESSOR_EXT = /(\.scss|\.sass|\.less|\.styl)$/;
|
||||||
|
@ -176,7 +176,8 @@ export class HostResourceLoader implements ResourceLoader {
|
||||||
// clang-format on
|
// clang-format on
|
||||||
if (failedLookup.failedLookupLocations === undefined) {
|
if (failedLookup.failedLookupLocations === undefined) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Internal error: expected to find failedLookupLocations during resolution of resource '${url}' in context of ${fromFile}`);
|
`Internal error: expected to find failedLookupLocations during resolution of resource '${
|
||||||
|
url}' in context of ${fromFile}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return failedLookup.failedLookupLocations
|
return failedLookup.failedLookupLocations
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {ModuleResolver} from '../../imports';
|
||||||
import {PartialEvaluator} from '../../partial_evaluator';
|
import {PartialEvaluator} from '../../partial_evaluator';
|
||||||
|
|
||||||
import {scanForCandidateTransitiveModules, scanForRouteEntryPoints} from './lazy';
|
import {scanForCandidateTransitiveModules, scanForRouteEntryPoints} from './lazy';
|
||||||
import {RouterEntryPointManager, entryPointKeyFor} from './route';
|
import {entryPointKeyFor, RouterEntryPointManager} from './route';
|
||||||
|
|
||||||
export interface NgModuleRawRouteData {
|
export interface NgModuleRawRouteData {
|
||||||
sourceFile: ts.SourceFile;
|
sourceFile: ts.SourceFile;
|
||||||
|
@ -42,9 +42,12 @@ export class NgModuleRouteAnalyzer {
|
||||||
if (this.modules.has(key)) {
|
if (this.modules.has(key)) {
|
||||||
throw new Error(`Double route analyzing for '${key}'.`);
|
throw new Error(`Double route analyzing for '${key}'.`);
|
||||||
}
|
}
|
||||||
this.modules.set(
|
this.modules.set(key, {
|
||||||
key, {
|
sourceFile,
|
||||||
sourceFile, moduleName, imports, exports, providers,
|
moduleName,
|
||||||
|
imports,
|
||||||
|
exports,
|
||||||
|
providers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {Reference} from '../../imports';
|
||||||
import {ForeignFunctionResolver, PartialEvaluator, ResolvedValue} from '../../partial_evaluator';
|
import {ForeignFunctionResolver, PartialEvaluator, ResolvedValue} from '../../partial_evaluator';
|
||||||
|
|
||||||
import {NgModuleRawRouteData} from './analyzer';
|
import {NgModuleRawRouteData} from './analyzer';
|
||||||
import {RouterEntryPoint, RouterEntryPointManager, entryPointKeyFor} from './route';
|
import {entryPointKeyFor, RouterEntryPoint, RouterEntryPointManager} from './route';
|
||||||
|
|
||||||
const ROUTES_MARKER = '__ngRoutesMarker__';
|
const ROUTES_MARKER = '__ngRoutesMarker__';
|
||||||
|
|
||||||
|
@ -70,7 +70,9 @@ export function scanForRouteEntryPoints(
|
||||||
const resolvedTo = entryPointManager.resolveLoadChildrenIdentifier(loadChildren, ngModule);
|
const resolvedTo = entryPointManager.resolveLoadChildrenIdentifier(loadChildren, ngModule);
|
||||||
if (resolvedTo !== null) {
|
if (resolvedTo !== null) {
|
||||||
routes.push({
|
routes.push({
|
||||||
loadChildren, from, resolvedTo,
|
loadChildren,
|
||||||
|
from,
|
||||||
|
resolvedTo,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,16 +161,14 @@ function scanForLazyRoutes(routes: ResolvedValue[]): string[] {
|
||||||
const routerModuleFFR: ForeignFunctionResolver =
|
const routerModuleFFR: ForeignFunctionResolver =
|
||||||
function routerModuleFFR(
|
function routerModuleFFR(
|
||||||
ref: Reference<ts.FunctionDeclaration|ts.MethodDeclaration|ts.FunctionExpression>,
|
ref: Reference<ts.FunctionDeclaration|ts.MethodDeclaration|ts.FunctionExpression>,
|
||||||
args: ReadonlyArray<ts.Expression>): ts.Expression |
|
args: ReadonlyArray<ts.Expression>): ts.Expression|null {
|
||||||
null {
|
|
||||||
if (!isMethodNodeReference(ref) || !ts.isClassDeclaration(ref.node.parent)) {
|
if (!isMethodNodeReference(ref) || !ts.isClassDeclaration(ref.node.parent)) {
|
||||||
return null;
|
return null;
|
||||||
} else if (
|
} else if (
|
||||||
ref.bestGuessOwningModule === null ||
|
ref.bestGuessOwningModule === null ||
|
||||||
ref.bestGuessOwningModule.specifier !== '@angular/router') {
|
ref.bestGuessOwningModule.specifier !== '@angular/router') {
|
||||||
return null;
|
return null;
|
||||||
} else if (
|
} else if (ref.node.parent.name === undefined || ref.node.parent.name.text !== 'RouterModule') {
|
||||||
ref.node.parent.name === undefined || ref.node.parent.name.text !== 'RouterModule') {
|
|
||||||
return null;
|
return null;
|
||||||
} else if (
|
} else if (
|
||||||
!ts.isIdentifier(ref.node.name) ||
|
!ts.isIdentifier(ref.node.name) ||
|
||||||
|
|
|
@ -22,10 +22,14 @@ export abstract class RouterEntryPoint {
|
||||||
class RouterEntryPointImpl implements RouterEntryPoint {
|
class RouterEntryPointImpl implements RouterEntryPoint {
|
||||||
constructor(readonly filePath: string, readonly moduleName: string) {}
|
constructor(readonly filePath: string, readonly moduleName: string) {}
|
||||||
|
|
||||||
get name(): string { return this.moduleName; }
|
get name(): string {
|
||||||
|
return this.moduleName;
|
||||||
|
}
|
||||||
|
|
||||||
// For debugging purposes.
|
// For debugging purposes.
|
||||||
toString(): string { return `RouterEntryPoint(name: ${this.name}, filePath: ${this.filePath})`; }
|
toString(): string {
|
||||||
|
return `RouterEntryPoint(name: ${this.name}, filePath: ${this.filePath})`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RouterEntryPointManager {
|
export class RouterEntryPointManager {
|
||||||
|
|
|
@ -47,8 +47,8 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver {
|
||||||
const clazz = ref.node;
|
const clazz = ref.node;
|
||||||
const sourceFile = clazz.getSourceFile();
|
const sourceFile = clazz.getSourceFile();
|
||||||
if (!sourceFile.isDeclarationFile) {
|
if (!sourceFile.isDeclarationFile) {
|
||||||
throw new Error(
|
throw new Error(`Debug error: DtsModuleScopeResolver.read(${ref.debugName} from ${
|
||||||
`Debug error: DtsModuleScopeResolver.read(${ref.debugName} from ${sourceFile.fileName}), but not a .d.ts file`);
|
sourceFile.fileName}), but not a .d.ts file`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.cache.has(clazz)) {
|
if (this.cache.has(clazz)) {
|
||||||
|
|
|
@ -218,7 +218,8 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop
|
||||||
rawDeclarations: ts.Expression|null): void {
|
rawDeclarations: ts.Expression|null): void {
|
||||||
const declData: DeclarationData = {
|
const declData: DeclarationData = {
|
||||||
ngModule,
|
ngModule,
|
||||||
ref: decl, rawDeclarations,
|
ref: decl,
|
||||||
|
rawDeclarations,
|
||||||
};
|
};
|
||||||
|
|
||||||
// First, check for duplicate declarations of the same directive/pipe.
|
// First, check for duplicate declarations of the same directive/pipe.
|
||||||
|
@ -345,7 +346,9 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop
|
||||||
diagnostics.push(makeDiagnostic(
|
diagnostics.push(makeDiagnostic(
|
||||||
ErrorCode.NGMODULE_INVALID_DECLARATION, errorNode,
|
ErrorCode.NGMODULE_INVALID_DECLARATION, errorNode,
|
||||||
`The class '${decl.node.name.text}' is listed in the declarations ` +
|
`The class '${decl.node.name.text}' is listed in the declarations ` +
|
||||||
`of the NgModule '${ngModule.ref.node.name.text}', but is not a directive, a component, or a pipe. ` +
|
`of the NgModule '${
|
||||||
|
ngModule.ref.node.name
|
||||||
|
.text}', but is not a directive, a component, or a pipe. ` +
|
||||||
`Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.`,
|
`Either remove it from the NgModule's declarations, or add an appropriate Angular decorator.`,
|
||||||
[{node: decl.node.name, messageText: `'${decl.node.name.text}' is declared here.`}]));
|
[{node: decl.node.name, messageText: `'${decl.node.name.text}' is declared here.`}]));
|
||||||
continue;
|
continue;
|
||||||
|
@ -433,7 +436,9 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop
|
||||||
/**
|
/**
|
||||||
* Check whether a component requires remote scoping.
|
* Check whether a component requires remote scoping.
|
||||||
*/
|
*/
|
||||||
getRequiresRemoteScope(node: ClassDeclaration): boolean { return this.remoteScoping.has(node); }
|
getRequiresRemoteScope(node: ClassDeclaration): boolean {
|
||||||
|
return this.remoteScoping.has(node);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a component as requiring remote scoping.
|
* Set a component as requiring remote scoping.
|
||||||
|
@ -466,7 +471,8 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop
|
||||||
ErrorCode.NGMODULE_INVALID_EXPORT;
|
ErrorCode.NGMODULE_INVALID_EXPORT;
|
||||||
diagnostics.push(makeDiagnostic(
|
diagnostics.push(makeDiagnostic(
|
||||||
code, identifierOfNode(ref.node) || ref.node,
|
code, identifierOfNode(ref.node) || ref.node,
|
||||||
`Appears in the NgModule.${type}s of ${nodeNameForError(ownerForErrors)}, but could not be resolved to an NgModule`));
|
`Appears in the NgModule.${type}s of ${
|
||||||
|
nodeNameForError(ownerForErrors)}, but could not be resolved to an NgModule`));
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return this.dependencyScopeReader.resolve(ref);
|
return this.dependencyScopeReader.resolve(ref);
|
||||||
|
@ -553,7 +559,8 @@ function invalidRef(
|
||||||
type === 'import' ? ErrorCode.NGMODULE_INVALID_IMPORT : ErrorCode.NGMODULE_INVALID_EXPORT;
|
type === 'import' ? ErrorCode.NGMODULE_INVALID_IMPORT : ErrorCode.NGMODULE_INVALID_EXPORT;
|
||||||
const resolveTarget = type === 'import' ? 'NgModule' : 'NgModule, Component, Directive, or Pipe';
|
const resolveTarget = type === 'import' ? 'NgModule' : 'NgModule, Component, Directive, or Pipe';
|
||||||
let message =
|
let message =
|
||||||
`Appears in the NgModule.${type}s of ${nodeNameForError(clazz)}, but could not be resolved to an ${resolveTarget} class.` +
|
`Appears in the NgModule.${type}s of ${
|
||||||
|
nodeNameForError(clazz)}, but could not be resolved to an ${resolveTarget} class.` +
|
||||||
'\n\n';
|
'\n\n';
|
||||||
const library = decl.ownedByModuleGuess !== null ? ` (${decl.ownedByModuleGuess})` : '';
|
const library = decl.ownedByModuleGuess !== null ? ` (${decl.ownedByModuleGuess})` : '';
|
||||||
const sf = decl.node.getSourceFile();
|
const sf = decl.node.getSourceFile();
|
||||||
|
@ -573,8 +580,8 @@ function invalidRef(
|
||||||
} else {
|
} else {
|
||||||
// This is a monorepo style local dependency. Unfortunately these are too different to really
|
// This is a monorepo style local dependency. Unfortunately these are too different to really
|
||||||
// offer much more advice than this.
|
// offer much more advice than this.
|
||||||
message +=
|
message += `This likely means that the dependency${library} which declares ${
|
||||||
`This likely means that the dependency${library} which declares ${decl.debugName} has not been processed correctly by ngcc.`;
|
decl.debugName} has not been processed correctly by ngcc.`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return makeDiagnostic(code, identifierOfNode(decl.node) || decl.node, message);
|
return makeDiagnostic(code, identifierOfNode(decl.node) || decl.node, message);
|
||||||
|
@ -600,7 +607,8 @@ function invalidTransitiveNgModuleRef(
|
||||||
function invalidReexport(clazz: ts.Declaration, decl: Reference<ts.Declaration>): ts.Diagnostic {
|
function invalidReexport(clazz: ts.Declaration, decl: Reference<ts.Declaration>): ts.Diagnostic {
|
||||||
return makeDiagnostic(
|
return makeDiagnostic(
|
||||||
ErrorCode.NGMODULE_INVALID_REEXPORT, identifierOfNode(decl.node) || decl.node,
|
ErrorCode.NGMODULE_INVALID_REEXPORT, identifierOfNode(decl.node) || decl.node,
|
||||||
`Present in the NgModule.exports of ${nodeNameForError(clazz)} but neither declared nor imported`);
|
`Present in the NgModule.exports of ${
|
||||||
|
nodeNameForError(clazz)} but neither declared nor imported`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -609,11 +617,13 @@ function invalidReexport(clazz: ts.Declaration, decl: Reference<ts.Declaration>)
|
||||||
function reexportCollision(
|
function reexportCollision(
|
||||||
module: ClassDeclaration, refA: Reference<ClassDeclaration>,
|
module: ClassDeclaration, refA: Reference<ClassDeclaration>,
|
||||||
refB: Reference<ClassDeclaration>): ts.Diagnostic {
|
refB: Reference<ClassDeclaration>): ts.Diagnostic {
|
||||||
const childMessageText =
|
const childMessageText = `This directive/pipe is part of the exports of '${
|
||||||
`This directive/pipe is part of the exports of '${module.name.text}' and shares the same name as another exported directive/pipe.`;
|
module.name.text}' and shares the same name as another exported directive/pipe.`;
|
||||||
return makeDiagnostic(
|
return makeDiagnostic(
|
||||||
ErrorCode.NGMODULE_REEXPORT_NAME_COLLISION, module.name, `
|
ErrorCode.NGMODULE_REEXPORT_NAME_COLLISION, module.name,
|
||||||
There was a name collision between two classes named '${refA.node.name.text}', which are both part of the exports of '${module.name.text}'.
|
`
|
||||||
|
There was a name collision between two classes named '${
|
||||||
|
refA.node.name.text}', which are both part of the exports of '${module.name.text}'.
|
||||||
|
|
||||||
Angular generates re-exports of an NgModule's exported directives/pipes from the module's source file in certain cases, using the declared name of the class. If two classes of the same name are exported, this automatic naming does not work.
|
Angular generates re-exports of an NgModule's exported directives/pipes from the module's source file in certain cases, using the declared name of the class. If two classes of the same name are exported, this automatic naming does not work.
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,9 @@ function fakePipe(ref: Reference<ClassDeclaration>): PipeMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockDtsModuleScopeResolver implements DtsModuleScopeResolver {
|
class MockDtsModuleScopeResolver implements DtsModuleScopeResolver {
|
||||||
resolve(ref: Reference<ClassDeclaration>): null { return null; }
|
resolve(ref: Reference<ClassDeclaration>): null {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function scopeToRefs(scopeData: ScopeData): Reference<ClassDeclaration>[] {
|
function scopeToRefs(scopeData: ScopeData): Reference<ClassDeclaration>[] {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom, basename} from '../../file_system';
|
import {absoluteFrom, AbsoluteFsPath, basename} from '../../file_system';
|
||||||
import {ImportRewriter} from '../../imports';
|
import {ImportRewriter} from '../../imports';
|
||||||
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
||||||
|
|
||||||
|
@ -24,11 +24,17 @@ const STRIP_NG_FACTORY = /(.*)NgFactory$/;
|
||||||
export class FactoryGenerator implements ShimGenerator {
|
export class FactoryGenerator implements ShimGenerator {
|
||||||
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
||||||
|
|
||||||
get factoryFileMap(): Map<AbsoluteFsPath, AbsoluteFsPath> { return this.map; }
|
get factoryFileMap(): Map<AbsoluteFsPath, AbsoluteFsPath> {
|
||||||
|
return this.map;
|
||||||
|
}
|
||||||
|
|
||||||
get factoryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
|
get factoryFileNames(): AbsoluteFsPath[] {
|
||||||
|
return Array.from(this.map.keys());
|
||||||
|
}
|
||||||
|
|
||||||
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
|
recognize(fileName: AbsoluteFsPath): boolean {
|
||||||
|
return this.map.has(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
generate(genFilePath: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
generate(genFilePath: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
||||||
ts.SourceFile|null {
|
ts.SourceFile|null {
|
||||||
|
@ -71,8 +77,8 @@ export class FactoryGenerator implements ShimGenerator {
|
||||||
// This will encompass a lot of symbols which don't need factories, but that's okay
|
// This will encompass a lot of symbols which don't need factories, but that's okay
|
||||||
// because it won't miss any that do.
|
// because it won't miss any that do.
|
||||||
const varLines = symbolNames.map(
|
const varLines = symbolNames.map(
|
||||||
name =>
|
name => `export const ${
|
||||||
`export const ${name}NgFactory: i0.ɵNgModuleFactory<any> = new i0.ɵNgModuleFactory(${name});`);
|
name}NgFactory: i0.ɵNgModuleFactory<any> = new i0.ɵNgModuleFactory(${name});`);
|
||||||
sourceText += [
|
sourceText += [
|
||||||
// This might be incorrect if the current package being compiled is Angular core, but it's
|
// This might be incorrect if the current package being compiled is Angular core, but it's
|
||||||
// okay to leave in at type checking time. TypeScript can handle this reference via its path
|
// okay to leave in at type checking time. TypeScript can handle this reference via its path
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
import * as ts from 'typescript';
|
import * as ts from 'typescript';
|
||||||
|
|
||||||
import {AbsoluteFsPath, absoluteFrom} from '../../file_system';
|
import {absoluteFrom, AbsoluteFsPath} from '../../file_system';
|
||||||
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
import {isNonDeclarationTsPath} from '../../util/src/typescript';
|
||||||
|
|
||||||
import {ShimGenerator} from './api';
|
import {ShimGenerator} from './api';
|
||||||
|
@ -17,9 +17,13 @@ import {generatedModuleName} from './util';
|
||||||
export class SummaryGenerator implements ShimGenerator {
|
export class SummaryGenerator implements ShimGenerator {
|
||||||
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
private constructor(private map: Map<AbsoluteFsPath, AbsoluteFsPath>) {}
|
||||||
|
|
||||||
getSummaryFileNames(): AbsoluteFsPath[] { return Array.from(this.map.keys()); }
|
getSummaryFileNames(): AbsoluteFsPath[] {
|
||||||
|
return Array.from(this.map.keys());
|
||||||
|
}
|
||||||
|
|
||||||
recognize(fileName: AbsoluteFsPath): boolean { return this.map.has(fileName); }
|
recognize(fileName: AbsoluteFsPath): boolean {
|
||||||
|
return this.map.has(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
generate(genFilePath: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
generate(genFilePath: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
||||||
ts.SourceFile|null {
|
ts.SourceFile|null {
|
||||||
|
|
|
@ -22,7 +22,9 @@ import {ShimGenerator} from './api';
|
||||||
export class TypeCheckShimGenerator implements ShimGenerator {
|
export class TypeCheckShimGenerator implements ShimGenerator {
|
||||||
constructor(private typeCheckFile: AbsoluteFsPath) {}
|
constructor(private typeCheckFile: AbsoluteFsPath) {}
|
||||||
|
|
||||||
recognize(fileName: AbsoluteFsPath): boolean { return fileName === this.typeCheckFile; }
|
recognize(fileName: AbsoluteFsPath): boolean {
|
||||||
|
return fileName === this.typeCheckFile;
|
||||||
|
}
|
||||||
|
|
||||||
generate(genFileName: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
generate(genFileName: AbsoluteFsPath, readFile: (fileName: string) => ts.SourceFile | null):
|
||||||
ts.SourceFile|null {
|
ts.SourceFile|null {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue