Skip to content

Commit 0cbf5c6

Browse files
feat(ivy): ngcc: implement decorator analysis
1 parent e616af2 commit 0cbf5c6

4 files changed

Lines changed: 93 additions & 4 deletions

File tree

packages/compiler-cli/src/ngcc/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ ts_library(
1313
"//packages:types",
1414
"//packages/compiler-cli/src/ngtsc/host",
1515
"//packages/compiler-cli/src/ngtsc/metadata",
16+
"//packages/compiler-cli/src/ngtsc/transform",
17+
"//packages/compiler-cli/src/ngtsc/annotations",
1618
],
1719
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Angular Compatibility Compiler (ngcc)
2+
3+
This compiler will convert `node_modules` compiled with `ngc`, into `node_modules` which
4+
appear to have been compiled with `ngtsc`.
5+
6+
This conversion will allow such "legacy" packages to be used by the Ivy rendering engine.
7+
8+
## Building
9+
10+
The project is built using Bazel:
11+
12+
```bash
13+
bazel build //packages/compiler-cli/src/ngcc
14+
```
15+
16+
## Unit Testing
17+
18+
The unit tests are built and run using Bazel:
19+
20+
```bash
21+
bazel test //packages/compiler-cli/src/ngcc/test
22+
```
23+
24+
## Integration Testing
25+
26+
There are tests that check the behaviour of the overall executable:
27+
28+
```bash
29+
bazel test //packages/compiler-cli/test/ngcc
30+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @license
3+
* Copyright Google Inc. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
import {AnalysisOutput, DecoratorHandler} from '../../ngtsc/transform';
9+
import {DecoratedClass} from './parser/parser';
10+
11+
export interface AnalyzedClass extends AnalysisOutput<any> {
12+
clazz: DecoratedClass;
13+
}
14+
15+
export class Analyzer {
16+
constructor(private handlers: DecoratorHandler<any>[]) {}
17+
18+
analyze(clazz: DecoratedClass): AnalyzedClass|undefined {
19+
const detected = this.handlers
20+
.map(handler => ({ handler, decorator: handler.detect(clazz.decorators) }))
21+
.filter(detected => detected.decorator);
22+
23+
if (detected.length > 0) {
24+
if (detected.length > 1) {
25+
throw new Error('TODO.Diagnostic: Class has multiple Angular decorators.');
26+
}
27+
const analysisOutput = detected[0].handler.analyze(clazz.declaration, detected[0].decorator!);
28+
return { clazz, ...analysisOutput };
29+
}
30+
}
31+
}

packages/compiler-cli/src/ngcc/src/main.ts

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88

99
/* tslint:disable:no-console */
1010

11-
import { resolve } from 'path';
11+
import {resolve} from 'path';
1212
import * as ts from 'typescript';
13-
import { DecoratedClass } from './parser/parser';
14-
import { FlatEsm2015PackageParser } from './parser/flat_esm2015_parser';
15-
import { Esm2015ReflectionHost } from './host/esm2015_host';
13+
import {DecoratedClass} from './parser/parser';
14+
import {FlatEsm2015PackageParser} from './parser/flat_esm2015_parser';
15+
import {Esm2015ReflectionHost} from './host/esm2015_host';
16+
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, SelectorScopeRegistry} from '../../ngtsc/annotations';
17+
import {AnalyzedClass, Analyzer} from './analyzer';
1618

1719
export function mainNgcc(args: string[]): number {
1820
const rootPath = args[0];
@@ -30,6 +32,22 @@ export function mainNgcc(args: string[]): number {
3032
const decoratedClasses = parser.getDecoratedClasses(entryPointFile);
3133

3234
dumpDecoratedClasses(decoratedClasses);
35+
36+
const scopeRegistry = new SelectorScopeRegistry(typeChecker, reflectionHost);
37+
const handlers = [
38+
new ComponentDecoratorHandler(typeChecker, reflectionHost, scopeRegistry),
39+
new DirectiveDecoratorHandler(typeChecker, reflectionHost, scopeRegistry),
40+
new InjectableDecoratorHandler(reflectionHost),
41+
new NgModuleDecoratorHandler(typeChecker, scopeRegistry),
42+
];
43+
44+
const analyzer = new Analyzer(handlers);
45+
const analyzedClasses = decoratedClasses
46+
.map(decoratedClass => analyzer.analyze(decoratedClass))
47+
.filter(analysis => !!analysis) as AnalyzedClass[];
48+
49+
dumpAnalysis(analyzedClasses);
50+
3351
return 0;
3452
}
3553

@@ -44,4 +62,12 @@ function dumpDecoratedClasses(decoratedClasses: DecoratedClass[]) {
4462
}
4563
});
4664
});
65+
}
66+
67+
function dumpAnalysis(analyzedClasses: AnalyzedClass[]) {
68+
console.log('Analyzed classes');
69+
analyzedClasses.forEach(analyzedClass => {
70+
console.log(`- ${analyzedClass.clazz.name}`);
71+
console.log(` * ${analyzedClass.analysis.name}:`, analyzedClass.analysis);
72+
});
4773
}

0 commit comments

Comments
 (0)