90 lines
2.9 KiB
TypeScript
90 lines
2.9 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* 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
|
|
*/
|
|
import * as ts from 'typescript';
|
|
|
|
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
|
import {MetadataReader} from '../../../src/ngtsc/metadata';
|
|
import {PartialEvaluator} from '../../../src/ngtsc/partial_evaluator';
|
|
import {ClassDeclaration, Decorator} from '../../../src/ngtsc/reflection';
|
|
import {HandlerFlags, TraitState} from '../../../src/ngtsc/transform';
|
|
import {NgccReflectionHost} from '../host/ngcc_host';
|
|
import {MigrationHost} from '../migrations/migration';
|
|
|
|
import {NgccTraitCompiler} from './ngcc_trait_compiler';
|
|
import {isWithinPackage} from './util';
|
|
|
|
/**
|
|
* The standard implementation of `MigrationHost`, which is created by the `DecorationAnalyzer`.
|
|
*/
|
|
export class DefaultMigrationHost implements MigrationHost {
|
|
constructor(
|
|
readonly reflectionHost: NgccReflectionHost, readonly metadata: MetadataReader,
|
|
readonly evaluator: PartialEvaluator, private compiler: NgccTraitCompiler,
|
|
private entryPointPath: AbsoluteFsPath) {}
|
|
|
|
injectSyntheticDecorator(clazz: ClassDeclaration, decorator: Decorator, flags?: HandlerFlags):
|
|
void {
|
|
const migratedTraits = this.compiler.injectSyntheticDecorator(clazz, decorator, flags);
|
|
|
|
for (const trait of migratedTraits) {
|
|
if (trait.state === TraitState.ERRORED) {
|
|
trait.diagnostics =
|
|
trait.diagnostics.map(diag => createMigrationDiagnostic(diag, clazz, decorator));
|
|
}
|
|
}
|
|
}
|
|
|
|
getAllDecorators(clazz: ClassDeclaration): Decorator[]|null {
|
|
return this.compiler.getAllDecorators(clazz);
|
|
}
|
|
|
|
isInScope(clazz: ClassDeclaration): boolean {
|
|
return isWithinPackage(this.entryPointPath, clazz.getSourceFile());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a diagnostic from another one, containing additional information about the synthetic
|
|
* decorator.
|
|
*/
|
|
function createMigrationDiagnostic(
|
|
diagnostic: ts.Diagnostic, source: ts.Node, decorator: Decorator): ts.Diagnostic {
|
|
const clone = {...diagnostic};
|
|
|
|
const chain: ts.DiagnosticMessageChain[] = [{
|
|
messageText: `Occurs for @${decorator.name} decorator inserted by an automatic migration`,
|
|
category: ts.DiagnosticCategory.Message,
|
|
code: 0,
|
|
}];
|
|
|
|
if (decorator.args !== null) {
|
|
const args = decorator.args.map(arg => arg.getText()).join(', ');
|
|
chain.push({
|
|
messageText: `@${decorator.name}(${args})`,
|
|
category: ts.DiagnosticCategory.Message,
|
|
code: 0,
|
|
});
|
|
}
|
|
|
|
if (typeof clone.messageText === 'string') {
|
|
clone.messageText = {
|
|
messageText: clone.messageText,
|
|
category: diagnostic.category,
|
|
code: diagnostic.code,
|
|
next: chain,
|
|
};
|
|
} else {
|
|
if (clone.messageText.next === undefined) {
|
|
clone.messageText.next = chain;
|
|
} else {
|
|
clone.messageText.next.push(...chain);
|
|
}
|
|
}
|
|
return clone;
|
|
}
|