feat(tsc-wrapped): allow values to be substituted by collector clients
Also reenabled tests that were unintentionally disabled when they were moved from tools/@angular.
This commit is contained in:

committed by
Alex Rickabaugh

parent
381471d338
commit
67dff7bd5d
@ -26,7 +26,7 @@ const isStatic = (ts as any).ModifierFlags ?
|
||||
/**
|
||||
* A set of collector options to use when collecting metadata.
|
||||
*/
|
||||
export class CollectorOptions {
|
||||
export interface CollectorOptions {
|
||||
/**
|
||||
* Version of the metadata to collect.
|
||||
*/
|
||||
@ -42,6 +42,11 @@ export class CollectorOptions {
|
||||
* Do not simplify invalid expressions.
|
||||
*/
|
||||
verboseInvalidExpression?: boolean;
|
||||
|
||||
/**
|
||||
* An expression substitution callback.
|
||||
*/
|
||||
substituteExpression?: (value: MetadataValue, node: ts.Node) => MetadataValue;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -54,12 +59,25 @@ export class MetadataCollector {
|
||||
* Returns a JSON.stringify friendly form describing the decorators of the exported classes from
|
||||
* the source file that is expected to correspond to a module.
|
||||
*/
|
||||
public getMetadata(sourceFile: ts.SourceFile, strict: boolean = false): ModuleMetadata|undefined {
|
||||
public getMetadata(
|
||||
sourceFile: ts.SourceFile, strict: boolean = false,
|
||||
substituteExpression?: (value: MetadataValue, node: ts.Node) => MetadataValue): ModuleMetadata
|
||||
|undefined {
|
||||
const locals = new Symbols(sourceFile);
|
||||
const nodeMap =
|
||||
new Map<MetadataValue|ClassMetadata|InterfaceMetadata|FunctionMetadata, ts.Node>();
|
||||
const evaluator = new Evaluator(locals, nodeMap, this.options);
|
||||
const composedSubstituter = substituteExpression && this.options.substituteExpression ?
|
||||
(value: MetadataValue, node: ts.Node) =>
|
||||
this.options.substituteExpression !(substituteExpression(value, node), node) :
|
||||
substituteExpression;
|
||||
const evaluatorOptions = substituteExpression ?
|
||||
{...this.options, substituteExpression: composedSubstituter} :
|
||||
this.options;
|
||||
let metadata: {[name: string]: MetadataValue | ClassMetadata | FunctionMetadata}|undefined;
|
||||
const evaluator = new Evaluator(locals, nodeMap, evaluatorOptions, (name, value) => {
|
||||
if (!metadata) metadata = {};
|
||||
metadata[name] = value;
|
||||
});
|
||||
let exports: ModuleExportMetadata[]|undefined = undefined;
|
||||
|
||||
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
|
||||
|
@ -9,9 +9,10 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {CollectorOptions} from './collector';
|
||||
import {MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataSymbolicCallExpression, MetadataValue, isMetadataError, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression} from './schema';
|
||||
import {MetadataEntry, MetadataError, MetadataImportedSymbolReferenceExpression, MetadataSymbolicCallExpression, MetadataValue, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataModuleReferenceExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSpreadExpression} from './schema';
|
||||
import {Symbols} from './symbols';
|
||||
|
||||
|
||||
// In TypeScript 2.1 the spread element kind was renamed.
|
||||
const spreadElementSyntaxKind: ts.SyntaxKind =
|
||||
(ts.SyntaxKind as any).SpreadElement || (ts.SyntaxKind as any).SpreadElementExpression;
|
||||
@ -104,7 +105,8 @@ export function errorSymbol(
|
||||
export class Evaluator {
|
||||
constructor(
|
||||
private symbols: Symbols, private nodeMap: Map<MetadataEntry, ts.Node>,
|
||||
private options: CollectorOptions = {}) {}
|
||||
private options: CollectorOptions = {},
|
||||
private recordExport?: (name: string, value: MetadataValue) => void) {}
|
||||
|
||||
nameOf(node: ts.Node|undefined): string|MetadataError {
|
||||
if (node && node.kind == ts.SyntaxKind.Identifier) {
|
||||
@ -232,7 +234,14 @@ export class Evaluator {
|
||||
const t = this;
|
||||
let error: MetadataError|undefined;
|
||||
|
||||
function recordEntry<T extends MetadataEntry>(entry: T, node: ts.Node): T {
|
||||
function recordEntry(entry: MetadataValue, node: ts.Node): MetadataValue {
|
||||
if (t.options.substituteExpression) {
|
||||
const newEntry = t.options.substituteExpression(entry, node);
|
||||
if (t.recordExport && newEntry != entry && isMetadataGlobalReferenceExpression(newEntry)) {
|
||||
t.recordExport(newEntry.name, entry);
|
||||
}
|
||||
entry = newEntry;
|
||||
}
|
||||
t.nodeMap.set(entry, node);
|
||||
return entry;
|
||||
}
|
||||
@ -283,7 +292,7 @@ export class Evaluator {
|
||||
if (this.options.quotedNames && quoted.length) {
|
||||
obj['$quoted$'] = quoted;
|
||||
}
|
||||
return obj;
|
||||
return recordEntry(obj, node);
|
||||
case ts.SyntaxKind.ArrayLiteralExpression:
|
||||
let arr: MetadataValue[] = [];
|
||||
ts.forEachChild(node, child => {
|
||||
@ -308,7 +317,7 @@ export class Evaluator {
|
||||
arr.push(value);
|
||||
});
|
||||
if (error) return error;
|
||||
return arr;
|
||||
return recordEntry(arr, node);
|
||||
case spreadElementSyntaxKind:
|
||||
let spreadExpression = this.evaluateNode((node as any).expression);
|
||||
return recordEntry({__symbolic: 'spread', expression: spreadExpression}, node);
|
||||
|
Reference in New Issue
Block a user