refactor(tsc-wrapped): update tsc-wrapped to pass strictNullCheck (#18160)

PR Close #18160
This commit is contained in:
Chuck Jazdzewski
2017-07-18 12:52:48 -07:00
committed by Miško Hevery
parent 619e625ee2
commit abee785821
18 changed files with 269 additions and 230 deletions

View File

@ -70,7 +70,9 @@ export interface BundledModule {
privates: BundlePrivateEntry[];
}
export interface MetadataBundlerHost { getMetadataFor(moduleName: string): ModuleMetadata; }
export interface MetadataBundlerHost {
getMetadataFor(moduleName: string): ModuleMetadata|undefined;
}
type StaticsMetadata = {
[name: string]: MetadataValue | FunctionMetadata;
@ -78,7 +80,7 @@ type StaticsMetadata = {
export class MetadataBundler {
private symbolMap = new Map<string, Symbol>();
private metadataCache = new Map<string, ModuleMetadata>();
private metadataCache = new Map<string, ModuleMetadata|undefined>();
private exports = new Map<string, Symbol[]>();
private rootModule: string;
private exported: Set<Symbol>;
@ -98,14 +100,14 @@ export class MetadataBundler {
const privates = Array.from(this.symbolMap.values())
.filter(s => s.referenced && s.isPrivate)
.map(s => ({
privateName: s.privateName,
name: s.declaration.name,
module: s.declaration.module
privateName: s.privateName !,
name: s.declaration !.name,
module: s.declaration !.module
}));
const origins = Array.from(this.symbolMap.values())
.filter(s => s.referenced && !s.reexport)
.reduce<{[name: string]: string}>((p, s) => {
p[s.isPrivate ? s.privateName : s.name] = s.declaration.module;
p[s.isPrivate ? s.privateName ! : s.name] = s.declaration !.module;
return p;
}, {});
const exports = this.getReExports(exportedSymbols);
@ -114,7 +116,7 @@ export class MetadataBundler {
__symbolic: 'module',
version: VERSION,
exports: exports.length ? exports : undefined, metadata, origins,
importAs: this.importAs
importAs: this.importAs !
},
privates
};
@ -124,7 +126,7 @@ export class MetadataBundler {
return resolveModule(importName, from);
}
private getMetadata(moduleName: string): ModuleMetadata {
private getMetadata(moduleName: string): ModuleMetadata|undefined {
let result = this.metadataCache.get(moduleName);
if (!result) {
if (moduleName.startsWith('.')) {
@ -138,7 +140,7 @@ export class MetadataBundler {
private exportAll(moduleName: string): Symbol[] {
const module = this.getMetadata(moduleName);
let result: Symbol[] = this.exports.get(moduleName);
let result = this.exports.get(moduleName);
if (result) {
return result;
@ -148,7 +150,7 @@ export class MetadataBundler {
const exportSymbol = (exportedSymbol: Symbol, exportAs: string) => {
const symbol = this.symbolOf(moduleName, exportAs);
result.push(symbol);
result !.push(symbol);
exportedSymbol.reexportedAs = symbol;
symbol.exports = exportedSymbol;
};
@ -266,7 +268,7 @@ export class MetadataBundler {
name = newPrivateName();
symbol.privateName = name;
}
result[name] = symbol.value;
result[name] = symbol.value !;
}
});
@ -279,9 +281,10 @@ export class MetadataBundler {
const exportAlls = new Set<string>();
for (const symbol of exportedSymbols) {
if (symbol.reexport) {
const declaration = symbol.declaration;
// symbol.declaration is guarenteed to be defined during the phase this method is called.
const declaration = symbol.declaration !;
const module = declaration.module;
if (declaration.name == '*') {
if (declaration !.name == '*') {
// Reexport all the symbols.
exportAlls.add(declaration.module);
} else {
@ -304,11 +307,13 @@ export class MetadataBundler {
}
private convertSymbol(symbol: Symbol) {
const canonicalSymbol = symbol.canonicalSymbol;
// canonicalSymbol is ensured to be defined before this is called.
const canonicalSymbol = symbol.canonicalSymbol !;
if (!canonicalSymbol.referenced) {
canonicalSymbol.referenced = true;
const declaration = canonicalSymbol.declaration;
// declaration is ensured to be definded before this method is called.
const declaration = canonicalSymbol.declaration !;
const module = this.getMetadata(declaration.module);
if (module) {
const value = module.metadata[declaration.name];
@ -336,10 +341,10 @@ export class MetadataBundler {
return {
__symbolic: 'class',
arity: value.arity,
extends: this.convertExpression(moduleName, value.extends),
extends: this.convertExpression(moduleName, value.extends) !,
decorators:
value.decorators && value.decorators.map(d => this.convertExpression(moduleName, d)),
members: this.convertMembers(moduleName, value.members),
value.decorators && value.decorators.map(d => this.convertExpression(moduleName, d) !),
members: this.convertMembers(moduleName, value.members !),
statics: value.statics && this.convertStatics(moduleName, value.statics)
};
}
@ -356,11 +361,11 @@ export class MetadataBundler {
private convertMember(moduleName: string, member: MemberMetadata) {
const result: MemberMetadata = {__symbolic: member.__symbolic};
result.decorators =
member.decorators && member.decorators.map(d => this.convertExpression(moduleName, d));
member.decorators && member.decorators.map(d => this.convertExpression(moduleName, d) !);
if (isMethodMetadata(member)) {
(result as MethodMetadata).parameterDecorators = member.parameterDecorators &&
member.parameterDecorators.map(
d => d && d.map(p => this.convertExpression(moduleName, p)));
d => d && d.map(p => this.convertExpression(moduleName, p) !));
if (isConstructorMetadata(member)) {
if (member.parameters) {
(result as ConstructorMetadata).parameters =
@ -397,7 +402,7 @@ export class MetadataBundler {
return this.convertError(moduleName, value);
}
if (isMetadataSymbolicExpression(value)) {
return this.convertExpression(moduleName, value);
return this.convertExpression(moduleName, value) !;
}
if (Array.isArray(value)) {
return value.map(v => this.convertValue(moduleName, v));
@ -413,8 +418,8 @@ export class MetadataBundler {
}
private convertExpression(
moduleName: string, value: MetadataSymbolicExpression|MetadataError|
undefined): MetadataSymbolicExpression|MetadataError|undefined {
moduleName: string, value: MetadataSymbolicExpression|MetadataError|null|
undefined): MetadataSymbolicExpression|MetadataError|undefined|null {
if (value) {
switch (value.__symbolic) {
case 'error':
@ -439,9 +444,9 @@ export class MetadataBundler {
}
private convertReference(moduleName: string, value: MetadataSymbolicReferenceExpression):
MetadataSymbolicReferenceExpression|MetadataError {
MetadataSymbolicReferenceExpression|MetadataError|undefined {
const createReference = (symbol: Symbol): MetadataSymbolicReferenceExpression => {
const declaration = symbol.declaration;
const declaration = symbol.declaration !;
if (declaration.module.startsWith('.')) {
// Reference to a symbol defined in the module. Ensure it is converted then return a
// references to the final symbol.
@ -450,11 +455,11 @@ export class MetadataBundler {
__symbolic: 'reference',
get name() {
// Resolved lazily because private names are assigned late.
const canonicalSymbol = symbol.canonicalSymbol;
const canonicalSymbol = symbol.canonicalSymbol !;
if (canonicalSymbol.isPrivate == null) {
throw Error('Invalid state: isPrivate was not initialized');
}
return canonicalSymbol.isPrivate ? canonicalSymbol.privateName : canonicalSymbol.name;
return canonicalSymbol.isPrivate ? canonicalSymbol.privateName ! : canonicalSymbol.name;
}
};
} else {
@ -564,7 +569,7 @@ export class CompilerHostAdapter implements MetadataBundlerHost {
constructor(private host: ts.CompilerHost) {}
getMetadataFor(fileName: string): ModuleMetadata {
getMetadataFor(fileName: string): ModuleMetadata|undefined {
const sourceFile = this.host.getSourceFile(fileName + '.ts', ts.ScriptTarget.Latest);
return this.collector.getMetadata(sourceFile);
}

View File

@ -6,8 +6,8 @@
* found in the LICENSE file at https://angular.io/license
*/
export class CliOptions {
public basePath: string;
constructor({basePath = null}: {basePath?: string}) { this.basePath = basePath; }
public basePath: string|null;
constructor({basePath = null}: {basePath?: string | null}) { this.basePath = basePath; }
}
export class I18nExtractionCliOptions extends CliOptions {
@ -28,18 +28,18 @@ export class I18nExtractionCliOptions extends CliOptions {
}
export class NgcCliOptions extends CliOptions {
public i18nFormat: string;
public i18nFile: string;
public locale: string;
public missingTranslation: string;
public i18nFormat: string|null;
public i18nFile: string|null;
public locale: string|null;
public missingTranslation: string|null;
constructor({i18nFormat = null, i18nFile = null, locale = null, missingTranslation = null,
basePath = null}: {
i18nFormat?: string,
i18nFile?: string,
locale?: string,
missingTranslation?: string,
basePath?: string
i18nFormat?: string | null,
i18nFile?: string|null,
locale?: string|null,
missingTranslation?: string|null,
basePath?: string|null
}) {
super({basePath: basePath});
this.i18nFormat = i18nFormat;

View File

@ -54,13 +54,13 @@ 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 {
public getMetadata(sourceFile: ts.SourceFile, strict: boolean = false): 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);
let metadata: {[name: string]: MetadataValue | ClassMetadata | FunctionMetadata}|undefined;
let exports: ModuleExportMetadata[];
let exports: ModuleExportMetadata[]|undefined = undefined;
function objFromDecorator(decoratorNode: ts.Decorator): MetadataSymbolicExpression {
return <MetadataSymbolicExpression>evaluator.evaluateNode(decoratorNode.expression);
@ -79,7 +79,7 @@ export class MetadataCollector {
function maybeGetSimpleFunction(
functionDeclaration: ts.FunctionDeclaration |
ts.MethodDeclaration): {func: FunctionMetadata, name: string}|undefined {
if (functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
if (functionDeclaration.name && functionDeclaration.name.kind == ts.SyntaxKind.Identifier) {
const nameNode = <ts.Identifier>functionDeclaration.name;
const functionName = nameNode.text;
const functionBody = functionDeclaration.body;
@ -107,7 +107,8 @@ export class MetadataCollector {
function classMetadataOf(classDeclaration: ts.ClassDeclaration): ClassMetadata {
const result: ClassMetadata = {__symbolic: 'class'};
function getDecorators(decorators: ts.Decorator[]): MetadataSymbolicExpression[] {
function getDecorators(decorators: ts.Decorator[] | undefined): MetadataSymbolicExpression[]|
undefined {
if (decorators && decorators.length)
return decorators.map(decorator => objFromDecorator(decorator));
return undefined;
@ -145,7 +146,7 @@ export class MetadataCollector {
}
// member decorators
let members: MetadataMap = null;
let members: MetadataMap|null = null;
function recordMember(name: string, metadata: MemberMetadata) {
if (!members) members = {};
const data = members.hasOwnProperty(name) ? members[name] : [];
@ -154,7 +155,7 @@ export class MetadataCollector {
}
// static member
let statics: {[name: string]: MetadataValue | FunctionMetadata} = null;
let statics: {[name: string]: MetadataValue | FunctionMetadata}|null = null;
function recordStaticMember(name: string, value: MetadataValue | FunctionMetadata) {
if (!statics) statics = {};
statics[name] = value;
@ -176,7 +177,8 @@ export class MetadataCollector {
}
const methodDecorators = getDecorators(method.decorators);
const parameters = method.parameters;
const parameterDecoratorData: (MetadataSymbolicExpression | MetadataError)[][] = [];
const parameterDecoratorData:
((MetadataSymbolicExpression | MetadataError)[] | undefined)[] = [];
const parametersData:
(MetadataSymbolicReferenceExpression | MetadataError |
MetadataSymbolicSelectExpression | null)[] = [];
@ -254,7 +256,8 @@ export class MetadataCollector {
const {moduleSpecifier, exportClause} = exportDeclaration;
if (!moduleSpecifier) {
exportClause.elements.forEach(spec => {
// If there is a module specifier there is also an exportClause
exportClause !.elements.forEach(spec => {
const exportedAs = spec.name.text;
const name = (spec.propertyName || spec.name).text;
exportMap.set(name, exportedAs);
@ -263,12 +266,13 @@ export class MetadataCollector {
}
});
const isExportedIdentifier = (identifier: ts.Identifier) => exportMap.has(identifier.text);
const isExportedIdentifier = (identifier?: ts.Identifier) =>
identifier && exportMap.has(identifier.text);
const isExported =
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
ts.EnumDeclaration) => isExport(node) || isExportedIdentifier(node.name);
const exportedIdentifierName = (identifier: ts.Identifier) =>
exportMap.get(identifier.text) || identifier.text;
const exportedIdentifierName = (identifier?: ts.Identifier) =>
identifier && (exportMap.get(identifier.text) || identifier.text);
const exportedName =
(node: ts.FunctionDeclaration | ts.ClassDeclaration | ts.InterfaceDeclaration |
ts.EnumDeclaration) => exportedIdentifierName(node.name);
@ -358,8 +362,11 @@ export class MetadataCollector {
const classDeclaration = <ts.ClassDeclaration>node;
if (classDeclaration.name) {
if (isExported(classDeclaration)) {
if (!metadata) metadata = {};
metadata[exportedName(classDeclaration)] = classMetadataOf(classDeclaration);
const name = exportedName(classDeclaration);
if (name) {
if (!metadata) metadata = {};
metadata[name] = classMetadataOf(classDeclaration);
}
}
}
// Otherwise don't record metadata for the class.
@ -368,8 +375,11 @@ export class MetadataCollector {
case ts.SyntaxKind.InterfaceDeclaration:
const interfaceDeclaration = <ts.InterfaceDeclaration>node;
if (interfaceDeclaration.name && isExported(interfaceDeclaration)) {
if (!metadata) metadata = {};
metadata[exportedName(interfaceDeclaration)] = {__symbolic: 'interface'};
const name = exportedName(interfaceDeclaration);
if (name) {
if (!metadata) metadata = {};
metadata[name] = {__symbolic: 'interface'};
}
}
break;
@ -378,11 +388,13 @@ export class MetadataCollector {
// names substitution will be performed by the StaticReflector.
const functionDeclaration = <ts.FunctionDeclaration>node;
if (isExported(functionDeclaration) && functionDeclaration.name) {
if (!metadata) metadata = {};
const name = exportedName(functionDeclaration);
const maybeFunc = maybeGetSimpleFunction(functionDeclaration);
metadata[name] =
maybeFunc ? recordEntry(maybeFunc.func, node) : {__symbolic: 'function'};
if (name) {
if (!metadata) metadata = {};
metadata[name] =
maybeFunc ? recordEntry(maybeFunc.func, node) : {__symbolic: 'function'};
}
}
break;
@ -400,7 +412,7 @@ export class MetadataCollector {
} else {
enumValue = evaluator.evaluateNode(member.initializer);
}
let name: string = undefined;
let name: string|undefined = undefined;
if (member.name.kind == ts.SyntaxKind.Identifier) {
const identifier = <ts.Identifier>member.name;
name = identifier.text;
@ -424,8 +436,10 @@ export class MetadataCollector {
}
}
if (writtenMembers) {
if (!metadata) metadata = {};
metadata[enumName] = recordEntry(enumValueHolder, node);
if (enumName) {
if (!metadata) metadata = {};
metadata[enumName] = recordEntry(enumValueHolder, node);
}
}
}
break;
@ -444,8 +458,11 @@ export class MetadataCollector {
let exported = false;
if (isExport(variableStatement) || isExport(variableDeclaration) ||
isExportedIdentifier(nameNode)) {
if (!metadata) metadata = {};
metadata[exportedIdentifierName(nameNode)] = recordEntry(varValue, node);
const name = exportedIdentifierName(nameNode);
if (name) {
if (!metadata) metadata = {};
metadata[name] = recordEntry(varValue, node);
}
exported = true;
}
if (typeof varValue == 'string' || typeof varValue == 'number' ||
@ -601,11 +618,11 @@ function validateMetadata(
}
if (classData.members) {
Object.getOwnPropertyNames(classData.members)
.forEach(name => classData.members[name].forEach((m) => validateMember(classData, m)));
.forEach(name => classData.members ![name].forEach((m) => validateMember(classData, m)));
}
if (classData.statics) {
Object.getOwnPropertyNames(classData.statics).forEach(name => {
const staticMember = classData.statics[name];
const staticMember = classData.statics ![name];
if (isFunctionMetadata(staticMember)) {
validateExpression(staticMember.value);
} else {
@ -628,7 +645,7 @@ function validateMetadata(
}
}
function shouldReportNode(node: ts.Node) {
function shouldReportNode(node: ts.Node | undefined) {
if (node) {
const nodeStart = node.getStart();
return !(

View File

@ -33,10 +33,10 @@ export abstract class DelegatingHost implements ts.CompilerHost {
(fileName: string, languageVersion: ts.ScriptTarget, onError?: (message: string) => void) =>
this.delegate.getSourceFile(fileName, languageVersion, onError);
getCancellationToken = () => this.delegate.getCancellationToken();
getCancellationToken = () => this.delegate.getCancellationToken !();
getDefaultLibFileName = (options: ts.CompilerOptions) =>
this.delegate.getDefaultLibFileName(options);
getDefaultLibLocation = () => this.delegate.getDefaultLibLocation();
getDefaultLibLocation = () => this.delegate.getDefaultLibLocation !();
writeFile: ts.WriteFileCallback = this.delegate.writeFile;
getCurrentDirectory = () => this.delegate.getCurrentDirectory();
getDirectories = (path: string): string[] =>
@ -46,8 +46,8 @@ export abstract class DelegatingHost implements ts.CompilerHost {
getNewLine = () => this.delegate.getNewLine();
fileExists = (fileName: string) => this.delegate.fileExists(fileName);
readFile = (fileName: string) => this.delegate.readFile(fileName);
trace = (s: string) => this.delegate.trace(s);
directoryExists = (directoryName: string) => this.delegate.directoryExists(directoryName);
trace = (s: string) => this.delegate.trace !(s);
directoryExists = (directoryName: string) => this.delegate.directoryExists !(directoryName);
}
const IGNORED_FILES = /\.ngfactory\.js$|\.ngstyle\.js$/;
@ -79,7 +79,8 @@ export class MetadataWriterHost extends DelegatingHost {
const metadata =
this.metadataCollector.getMetadata(collectableFile, !!this.ngOptions.strictMetadataEmit);
const metadata1 = this.metadataCollector1.getMetadata(collectableFile, false);
const metadatas: ModuleMetadata[] = [metadata, metadata1].filter(e => !!e);
const metadatas: ModuleMetadata[] =
[metadata, metadata1].filter(e => !!e) as ModuleMetadata[];
if (metadatas.length) {
const metadataText = JSON.stringify(metadatas);
writeFileSync(path, metadataText, {encoding: 'utf-8'});
@ -163,7 +164,7 @@ export class SyntheticIndexHost extends DelegatingHost {
normalize(sourceFiles[0].fileName) == this.normalSyntheticIndexName) {
// If we are writing the synthetic index, write the metadata along side.
const metadataName = fileName.replace(DTS, '.metadata.json');
writeFileSync(metadataName, this.indexMetadata, 'utf8');
writeFileSync(metadataName, this.indexMetadata, {encoding: 'utf8'});
}
}
}

View File

@ -68,7 +68,7 @@ export interface ImportMetadata {
}
function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
function getSourceFileOfNode(node: ts.Node | undefined): ts.SourceFile {
while (node && node.kind != ts.SyntaxKind.SourceFile) {
node = node.parent;
}
@ -79,7 +79,7 @@ function getSourceFileOfNode(node: ts.Node): ts.SourceFile {
export function errorSymbol(
message: string, node?: ts.Node, context?: {[name: string]: string},
sourceFile?: ts.SourceFile): MetadataError {
let result: MetadataError;
let result: MetadataError|undefined = undefined;
if (node) {
sourceFile = sourceFile || getSourceFileOfNode(node);
if (sourceFile) {
@ -106,15 +106,16 @@ export class Evaluator {
private symbols: Symbols, private nodeMap: Map<MetadataEntry, ts.Node>,
private options: CollectorOptions = {}) {}
nameOf(node: ts.Node): string|MetadataError {
if (node.kind == ts.SyntaxKind.Identifier) {
nameOf(node: ts.Node|undefined): string|MetadataError {
if (node && node.kind == ts.SyntaxKind.Identifier) {
return (<ts.Identifier>node).text;
}
const result = this.evaluateNode(node);
const result = node && this.evaluateNode(node);
if (isMetadataError(result) || typeof result === 'string') {
return result;
} else {
return errorSymbol('Name expected', node, {received: node.getText()});
return errorSymbol(
'Name expected', node, {received: (node && node.getText()) || '<missing>'});
}
}
@ -138,7 +139,7 @@ export class Evaluator {
return this.isFoldableWorker(node, new Map<ts.Node, boolean>());
}
private isFoldableWorker(node: ts.Node, folding: Map<ts.Node, boolean>): boolean {
private isFoldableWorker(node: ts.Node|undefined, folding: Map<ts.Node, boolean>): boolean {
if (node) {
switch (node.kind) {
case ts.SyntaxKind.ObjectLiteralExpression:
@ -518,11 +519,11 @@ export class Evaluator {
if (isDefined(operand) && isPrimitive(operand)) {
switch (prefixUnaryExpression.operator) {
case ts.SyntaxKind.PlusToken:
return +operand;
return +(operand as any);
case ts.SyntaxKind.MinusToken:
return -operand;
return -(operand as any);
case ts.SyntaxKind.TildeToken:
return ~operand;
return ~(operand as any);
case ts.SyntaxKind.ExclamationToken:
return !operand;
}
@ -661,8 +662,8 @@ function isPropertyAssignment(node: ts.Node): node is ts.PropertyAssignment {
return node.kind == ts.SyntaxKind.PropertyAssignment;
}
const empty = [] as ts.NodeArray<any>;
const empty = ts.createNodeArray<any>();
function arrayOrEmpty<T extends ts.Node>(v: ts.NodeArray<T>): ts.NodeArray<T> {
function arrayOrEmpty<T extends ts.Node>(v: ts.NodeArray<T>| undefined): ts.NodeArray<T> {
return v || empty;
}

View File

@ -41,9 +41,9 @@ export function createBundleIndexHost(
return {
host,
errors: [{
file: null,
start: null,
length: null,
file: null as any as ts.SourceFile,
start: null as any as number,
length: null as any as number,
messageText:
'Angular compiler option "flatModuleIndex" requires one and only one .ts file in the "files" field.',
category: ts.DiagnosticCategory.Error,
@ -58,7 +58,7 @@ export function createBundleIndexHost(
const metadataBundle = bundler.getMetadataBundle();
const metadata = JSON.stringify(metadataBundle.metadata);
const name =
path.join(path.dirname(indexModule), ngOptions.flatModuleOutFile.replace(JS_EXT, '.ts'));
path.join(path.dirname(indexModule), ngOptions.flatModuleOutFile !.replace(JS_EXT, '.ts'));
const libraryIndex = `./${path.basename(indexModule)}`;
const content = privateEntriesToIndex(libraryIndex, metadataBundle.privates);
host = new SyntheticIndexHost(host, {name, content, metadata});
@ -201,7 +201,7 @@ if (require.main === module) {
const project = options.project || '.';
// TODO(alexeagle): command line should be TSC-compatible, remove "CliOptions" here
const cliOptions = new CliOptions(require('minimist')(args));
main(project, cliOptions, null, options)
main(project, cliOptions, undefined, options)
.then((exitCode: any) => process.exit(exitCode))
.catch((e: any) => {
console.error(e.stack);

View File

@ -73,7 +73,7 @@ export function isMemberMetadata(value: any): value is MemberMetadata {
export interface MethodMetadata extends MemberMetadata {
__symbolic: 'constructor'|'method';
parameterDecorators?: (MetadataSymbolicExpression|MetadataError)[][];
parameterDecorators?: ((MetadataSymbolicExpression | MetadataError)[]|undefined)[];
}
export function isMethodMetadata(value: any): value is MethodMetadata {
return value && (value.__symbolic === 'constructor' || value.__symbolic === 'method');
@ -81,7 +81,7 @@ export function isMethodMetadata(value: any): value is MethodMetadata {
export interface ConstructorMetadata extends MethodMetadata {
__symbolic: 'constructor';
parameters?: (MetadataSymbolicExpression|MetadataError|null)[];
parameters?: (MetadataSymbolicExpression|MetadataError|null|undefined)[];
}
export function isConstructorMetadata(value: any): value is ConstructorMetadata {
return value && value.__symbolic === 'constructor';
@ -97,8 +97,8 @@ export function isFunctionMetadata(value: any): value is FunctionMetadata {
return value && value.__symbolic === 'function';
}
export type MetadataValue = string | number | boolean | MetadataObject | MetadataArray |
MetadataSymbolicExpression | MetadataError;
export type MetadataValue = string | number | boolean | undefined | null | MetadataObject |
MetadataArray | MetadataSymbolicExpression | MetadataError;
export interface MetadataObject { [name: string]: MetadataValue; }

View File

@ -49,23 +49,26 @@ export class Symbols {
ts.SyntaxKind.ExternalModuleReference) {
const externalReference =
<ts.ExternalModuleReference>importEqualsDeclaration.moduleReference;
// An `import <identifier> = require(<module-specifier>);
if (!externalReference.expression.parent) {
// The `parent` field of a node is set by the TypeScript binder (run as
// part of the type checker). Setting it here allows us to call `getText()`
// even if the `SourceFile` was not type checked (which looks for `SourceFile`
// in the parent chain). This doesn't damage the node as the binder unconditionally
// sets the parent.
externalReference.expression.parent = externalReference;
externalReference.parent = this.sourceFile as any;
if (externalReference.expression) {
// An `import <identifier> = require(<module-specifier>);
if (!externalReference.expression.parent) {
// The `parent` field of a node is set by the TypeScript binder (run as
// part of the type checker). Setting it here allows us to call `getText()`
// even if the `SourceFile` was not type checked (which looks for `SourceFile`
// in the parent chain). This doesn't damage the node as the binder unconditionally
// sets the parent.
externalReference.expression.parent = externalReference;
externalReference.parent = this.sourceFile as any;
}
const from = stripQuotes(externalReference.expression.getText());
symbols.set(
importEqualsDeclaration.name.text, {__symbolic: 'reference', module: from});
break;
}
const from = stripQuotes(externalReference.expression.getText());
symbols.set(importEqualsDeclaration.name.text, {__symbolic: 'reference', module: from});
} else {
symbols.set(
importEqualsDeclaration.name.text,
{__symbolic: 'error', message: `Unsupported import syntax`});
}
symbols.set(
importEqualsDeclaration.name.text,
{__symbolic: 'error', message: `Unsupported import syntax`});
break;
case ts.SyntaxKind.ImportDeclaration:
const importDecl = <ts.ImportDeclaration>node;

View File

@ -33,7 +33,7 @@ export class UserError extends Error {
super(message);
// Required for TS 2.1, see
// https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work
Object.setPrototypeOf(this, UserError.prototype);
(Object as any).setPrototypeOf(this, UserError.prototype);
const nativeError = new Error(message) as any as Error;
this._nativeError = nativeError;
@ -76,13 +76,14 @@ export function formatDiagnostics(diags: ts.Diagnostic[]): string {
.join('\n');
}
export function check(diags: ts.Diagnostic[]) {
export function check(diags: ts.Diagnostic[] | undefined) {
if (diags && diags.length && diags[0]) {
throw new UserError(formatDiagnostics(diags));
}
}
export function validateAngularCompilerOptions(options: AngularCompilerOptions): ts.Diagnostic[] {
export function validateAngularCompilerOptions(options: AngularCompilerOptions): ts.Diagnostic[]|
undefined {
if (options.annotationsAs) {
switch (options.annotationsAs) {
case 'decorators':
@ -90,9 +91,9 @@ export function validateAngularCompilerOptions(options: AngularCompilerOptions):
break;
default:
return [{
file: null,
start: null,
length: null,
file: null as any as ts.SourceFile,
start: null as any as number,
length: null as any as number,
messageText:
'Angular compiler options "annotationsAs" only supports "static fields" and "decorators"',
category: ts.DiagnosticCategory.Error,
@ -136,7 +137,7 @@ export class Tsc implements CompilerInterface {
return ts.readConfigFile(project, this.readFile);
}
})();
check([error]);
check([error !]);
const parsed =
ts.parseJsonConfigFileContent(config, this.parseConfigHost, basePath, existingOptions);