Merge branch 'master' into reachabilityChecks

This commit is contained in:
Vladimir Matveev
2015-10-19 15:54:45 -07:00
78 changed files with 44712 additions and 40862 deletions
+130 -132
View File
@@ -3716,7 +3716,9 @@ namespace ts {
function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature {
let links = getNodeLinks(declaration);
if (!links.resolvedSignature) {
let classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface((<ClassDeclaration>declaration.parent).symbol) : undefined;
let classType = declaration.kind === SyntaxKind.Constructor ?
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
: undefined;
let typeParameters = classType ? classType.localTypeParameters :
declaration.typeParameters ? getTypeParametersFromDeclaration(declaration.typeParameters) : undefined;
let parameters: Symbol[] = [];
@@ -4897,7 +4899,7 @@ namespace ts {
if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) {
// Report structural errors only if we haven't reported any errors yet
let reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
if (result = objectTypeRelatedTo(apparentType, <ObjectType>target, reportStructuralErrors)) {
if (result = objectTypeRelatedTo(apparentType, source, target, reportStructuralErrors)) {
errorInfo = saveErrorInfo;
return result;
}
@@ -4919,7 +4921,7 @@ namespace ts {
return result;
}
}
return objectTypeRelatedTo(<ObjectType>source, <ObjectType>target, /*reportErrors*/ false);
return objectTypeRelatedTo(source, source, target, /*reportErrors*/ false);
}
if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
return typeParameterIdenticalTo(<TypeParameter>source, <TypeParameter>target);
@@ -5073,11 +5075,11 @@ namespace ts {
// Third, check if both types are part of deeply nested chains of generic type instantiations and if so assume the types are
// equal and infinitely expanding. Fourth, if we have reached a depth of 100 nested comparisons, assume we have runaway recursion
// and issue an error. Otherwise, actually compare the structure of the two types.
function objectTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
function objectTypeRelatedTo(apparentSource: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (overflow) {
return Ternary.False;
}
let id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
let id = relation !== identityRelation || apparentSource.id < target.id ? apparentSource.id + "," + target.id : target.id + "," + apparentSource.id;
let related = relation[id];
if (related !== undefined) {
// If we computed this relation already and it was failed and reported, or if we're not being asked to elaborate
@@ -5104,28 +5106,28 @@ namespace ts {
maybeStack = [];
expandingFlags = 0;
}
sourceStack[depth] = source;
sourceStack[depth] = apparentSource;
targetStack[depth] = target;
maybeStack[depth] = {};
maybeStack[depth][id] = RelationComparisonResult.Succeeded;
depth++;
let saveExpandingFlags = expandingFlags;
if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack, depth)) expandingFlags |= 1;
if (!(expandingFlags & 1) && isDeeplyNestedGeneric(apparentSource, sourceStack, depth)) expandingFlags |= 1;
if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack, depth)) expandingFlags |= 2;
let result: Ternary;
if (expandingFlags === 3) {
result = Ternary.Maybe;
}
else {
result = propertiesRelatedTo(source, target, reportErrors);
result = propertiesRelatedTo(apparentSource, target, reportErrors);
if (result) {
result &= signaturesRelatedTo(source, target, SignatureKind.Call, reportErrors);
result &= signaturesRelatedTo(apparentSource, target, SignatureKind.Call, reportErrors);
if (result) {
result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportErrors);
result &= signaturesRelatedTo(apparentSource, target, SignatureKind.Construct, reportErrors);
if (result) {
result &= stringIndexTypesRelatedTo(source, target, reportErrors);
result &= stringIndexTypesRelatedTo(apparentSource, originalSource, target, reportErrors);
if (result) {
result &= numberIndexTypesRelatedTo(source, target, reportErrors);
result &= numberIndexTypesRelatedTo(apparentSource, originalSource, target, reportErrors);
}
}
}
@@ -5456,12 +5458,17 @@ namespace ts {
return result;
}
function stringIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
function stringIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return indexTypesIdenticalTo(IndexKind.String, source, target);
}
let targetType = getIndexTypeOfType(target, IndexKind.String);
if (targetType && !(targetType.flags & TypeFlags.Any)) {
if (targetType) {
if ((targetType.flags & TypeFlags.Any) && !(originalSource.flags & TypeFlags.Primitive)) {
// non-primitive assignment to any is always allowed, eg
// `var x: { [index: string]: any } = { property: 12 };`
return Ternary.True;
}
let sourceType = getIndexTypeOfType(source, IndexKind.String);
if (!sourceType) {
if (reportErrors) {
@@ -5481,12 +5488,17 @@ namespace ts {
return Ternary.True;
}
function numberIndexTypesRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
function numberIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
if (relation === identityRelation) {
return indexTypesIdenticalTo(IndexKind.Number, source, target);
}
let targetType = getIndexTypeOfType(target, IndexKind.Number);
if (targetType && !(targetType.flags & TypeFlags.Any)) {
if (targetType) {
if ((targetType.flags & TypeFlags.Any) && !(originalSource.flags & TypeFlags.Primitive)) {
// non-primitive assignment to any is always allowed, eg
// `var x: { [index: number]: any } = { property: 12 };`
return Ternary.True;
}
let sourceStringType = getIndexTypeOfType(source, IndexKind.String);
let sourceNumberType = getIndexTypeOfType(source, IndexKind.Number);
if (!(sourceStringType || sourceNumberType)) {
@@ -8647,39 +8659,36 @@ namespace ts {
*/
function getEffectiveDecoratorFirstArgumentType(node: Node): Type {
// The first argument to a decorator is its `target`.
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
// For a class decorator, the `target` is the type of the class (e.g. the
// "static" or "constructor" side of the class)
if (node.kind === SyntaxKind.ClassDeclaration) {
// For a class decorator, the `target` is the type of the class (e.g. the
// "static" or "constructor" side of the class)
let classSymbol = getSymbolOfNode(node);
return getTypeOfSymbol(classSymbol);
}
if (node.kind === SyntaxKind.Parameter) {
// For a parameter decorator, the `target` is the parent type of the
// parameter's containing method.
node = node.parent;
if (node.kind === SyntaxKind.Constructor) {
let classSymbol = getSymbolOfNode(node);
return getTypeOfSymbol(classSymbol);
case SyntaxKind.Parameter:
// For a parameter decorator, the `target` is the parent type of the
// parameter's containing method.
node = node.parent;
if (node.kind === SyntaxKind.Constructor) {
let classSymbol = getSymbolOfNode(node);
return getTypeOfSymbol(classSymbol);
}
// fall-through
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// For a property or method decorator, the `target` is the
// "static"-side type of the parent of the member if the member is
// declared "static"; otherwise, it is the "instance"-side type of the
// parent of the member.
return getParentTypeOfClassElement(<ClassElement>node);
default:
Debug.fail("Unsupported decorator target.");
return unknownType;
}
}
if (node.kind === SyntaxKind.PropertyDeclaration ||
node.kind === SyntaxKind.MethodDeclaration ||
node.kind === SyntaxKind.GetAccessor ||
node.kind === SyntaxKind.SetAccessor) {
// For a property or method decorator, the `target` is the
// "static"-side type of the parent of the member if the member is
// declared "static"; otherwise, it is the "instance"-side type of the
// parent of the member.
return getParentTypeOfClassElement(<ClassElement>node);
}
Debug.fail("Unsupported decorator target.");
return unknownType;
}
/**
@@ -8699,57 +8708,54 @@ namespace ts {
*/
function getEffectiveDecoratorSecondArgumentType(node: Node) {
// The second argument to a decorator is its `propertyKey`
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
Debug.fail("Class decorators should not have a second synthetic argument.");
return unknownType;
if (node.kind === SyntaxKind.ClassDeclaration) {
Debug.fail("Class decorators should not have a second synthetic argument.");
return unknownType;
}
case SyntaxKind.Parameter:
node = node.parent;
if (node.kind === SyntaxKind.Constructor) {
// For a constructor parameter decorator, the `propertyKey` will be `undefined`.
return anyType;
}
if (node.kind === SyntaxKind.Parameter) {
node = node.parent;
if (node.kind === SyntaxKind.Constructor) {
// For a constructor parameter decorator, the `propertyKey` will be `undefined`.
return anyType;
}
// For a non-constructor parameter decorator, the `propertyKey` will be either
// a string or a symbol, based on the name of the parameter's containing method.
// fall-through
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// The `propertyKey` for a property or method decorator will be a
// string literal type if the member name is an identifier, number, or string;
// otherwise, if the member name is a computed property name it will
// be either string or symbol.
let element = <ClassElement>node;
switch (element.name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
return getStringLiteralType(<StringLiteral>element.name);
case SyntaxKind.ComputedPropertyName:
let nameType = checkComputedPropertyName(<ComputedPropertyName>element.name);
if (allConstituentTypesHaveKind(nameType, TypeFlags.ESSymbol)) {
return nameType;
}
else {
return stringType;
}
default:
Debug.fail("Unsupported property name.");
return unknownType;
}
default:
Debug.fail("Unsupported decorator target.");
return unknownType;
}
if (node.kind === SyntaxKind.PropertyDeclaration ||
node.kind === SyntaxKind.MethodDeclaration ||
node.kind === SyntaxKind.GetAccessor ||
node.kind === SyntaxKind.SetAccessor) {
// The `propertyKey` for a property or method decorator will be a
// string literal type if the member name is an identifier, number, or string;
// otherwise, if the member name is a computed property name it will
// be either string or symbol.
let element = <ClassElement>node;
switch (element.name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.NumericLiteral:
case SyntaxKind.StringLiteral:
return getStringLiteralType(<StringLiteral>element.name);
case SyntaxKind.ComputedPropertyName:
let nameType = checkComputedPropertyName(<ComputedPropertyName>element.name);
if (allConstituentTypesHaveKind(nameType, TypeFlags.ESSymbol)) {
return nameType;
}
else {
return stringType;
}
default:
Debug.fail("Unsupported property name.");
return unknownType;
}
}
Debug.fail("Unsupported decorator target.");
return unknownType;
}
/**
@@ -8762,31 +8768,32 @@ namespace ts {
function getEffectiveDecoratorThirdArgumentType(node: Node) {
// The third argument to a decorator is either its `descriptor` for a method decorator
// or its `parameterIndex` for a paramter decorator
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
Debug.fail("Class decorators should not have a third synthetic argument.");
return unknownType;
case SyntaxKind.Parameter:
// The `parameterIndex` for a parameter decorator is always a number
return numberType;
case SyntaxKind.PropertyDeclaration:
Debug.fail("Property decorators should not have a third synthetic argument.");
return unknownType;
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// The `descriptor` for a method decorator will be a `TypedPropertyDescriptor<T>`
// for the type of the member.
let propertyType = getTypeOfNode(node);
return createTypedPropertyDescriptorType(propertyType);
default:
Debug.fail("Unsupported decorator target.");
return unknownType;
if (node.kind === SyntaxKind.ClassDeclaration) {
Debug.fail("Class decorators should not have a third synthetic argument.");
return unknownType;
}
if (node.kind === SyntaxKind.Parameter) {
// The `parameterIndex` for a parameter decorator is always a number
return numberType;
}
if (node.kind === SyntaxKind.PropertyDeclaration) {
Debug.fail("Property decorators should not have a third synthetic argument.");
return unknownType;
}
if (node.kind === SyntaxKind.MethodDeclaration ||
node.kind === SyntaxKind.GetAccessor ||
node.kind === SyntaxKind.SetAccessor) {
// The `descriptor` for a method decorator will be a `TypedPropertyDescriptor<T>`
// for the type of the member.
let propertyType = getTypeOfNode(node);
return createTypedPropertyDescriptorType(propertyType);
}
Debug.fail("Unsupported decorator target.");
return unknownType;
}
/**
@@ -11043,7 +11050,13 @@ namespace ts {
function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags): NodeFlags {
let flags = getCombinedNodeFlags(n);
if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && isInAmbientContext(n)) {
// children of classes (even ambient classes) should not be marked as ambient or export
// because those flags have no useful semantics there.
if (n.parent.kind !== SyntaxKind.InterfaceDeclaration &&
n.parent.kind !== SyntaxKind.ClassDeclaration &&
n.parent.kind !== SyntaxKind.ClassExpression &&
isInAmbientContext(n)) {
if (!(flags & NodeFlags.Ambient)) {
// It is nested in an ambient context, which means it is automatically exported
flags |= NodeFlags.Export;
@@ -12866,11 +12879,6 @@ namespace ts {
}
checkClassLikeDeclaration(node);
// Interfaces cannot be merged with non-ambient classes.
if (getSymbolOfNode(node).flags & SymbolFlags.Interface && !isInAmbientContext(node)) {
error(node, Diagnostics.Only_an_ambient_class_can_be_merged_with_an_interface);
}
forEach(node.members, checkSourceElement);
}
@@ -13156,16 +13164,6 @@ namespace ts {
checkIndexConstraints(type);
}
}
// Interfaces cannot merge with non-ambient classes.
if (symbol && symbol.declarations) {
for (let declaration of symbol.declarations) {
if (declaration.kind === SyntaxKind.ClassDeclaration && !isInAmbientContext(declaration)) {
error(node, Diagnostics.Only_an_ambient_class_can_be_merged_with_an_interface);
break;
}
}
}
}
forEach(getInterfaceBaseTypeNodes(node), heritageElement => {
if (!isSupportedExpressionWithTypeArguments(heritageElement)) {
+50 -47
View File
@@ -430,63 +430,19 @@ namespace ts {
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse
* @param host Instance of ParseConfigHost used to enumerate files in folder.
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
*/
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine {
let errors: Diagnostic[] = [];
let { options, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath);
return {
options: getCompilerOptions(),
options,
fileNames: getFileNames(),
errors
};
function getCompilerOptions(): CompilerOptions {
let options: CompilerOptions = {};
let optionNameMap: Map<CommandLineOption> = {};
forEach(optionDeclarations, option => {
optionNameMap[option.name] = option;
});
let jsonOptions = json["compilerOptions"];
if (jsonOptions) {
for (let id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
let opt = optionNameMap[id];
let optType = opt.type;
let value = jsonOptions[id];
let expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) {
if (typeof optType !== "string") {
let key = value.toLowerCase();
if (hasProperty(optType, key)) {
value = optType[key];
}
else {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
value = 0;
}
}
if (opt.isFilePath) {
value = normalizePath(combinePaths(basePath, value));
if (value === "") {
value = ".";
}
}
options[opt.name] = value;
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
}
}
}
return options;
}
function getFileNames(): string[] {
let fileNames: string[] = [];
if (hasProperty(json, "files")) {
@@ -521,4 +477,51 @@ namespace ts {
return fileNames;
}
}
export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string): { options: CompilerOptions, errors: Diagnostic[] } {
let options: CompilerOptions = {};
let errors: Diagnostic[] = [];
if (!jsonOptions) {
return { options, errors };
}
let optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (let id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
let opt = optionNameMap[id];
let optType = opt.type;
let value = jsonOptions[id];
let expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) {
if (typeof optType !== "string") {
let key = value.toLowerCase();
if (hasProperty(optType, key)) {
value = optType[key];
}
else {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
value = 0;
}
}
if (opt.isFilePath) {
value = normalizePath(combinePaths(basePath, value));
if (value === "") {
value = ".";
}
}
options[opt.name] = value;
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));
}
}
return { options, errors };
}
}
-4
View File
@@ -1620,10 +1620,6 @@
"category": "Error",
"code":2517
},
"Only an ambient class can be merged with an interface.": {
"category": "Error",
"code": 2518
},
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
"category": "Error",
"code": 2520
+1 -1
View File
@@ -12,7 +12,7 @@ namespace ts {
let emptyArray: any[] = [];
export const version = "1.7.0";
export const version = "1.8.0";
export function findConfigFile(searchPath: string): string {
let fileName = "tsconfig.json";
+1 -1
View File
@@ -1309,7 +1309,7 @@ namespace ts {
getCurrentDirectory(): string;
}
export interface ParseConfigHost extends ModuleResolutionHost {
export interface ParseConfigHost {
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
}
+1 -1
View File
@@ -1210,7 +1210,7 @@ interface ArrayBuffer {
interface ArrayBufferConstructor {
prototype: ArrayBuffer;
new (byteLength: number): ArrayBuffer;
isView(arg: any): boolean;
isView(arg: any): arg is ArrayBufferView;
}
declare var ArrayBuffer: ArrayBufferConstructor;