diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..9a61f6bd7c5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - "0.10" \ No newline at end of file diff --git a/Jakefile b/Jakefile index 37242552526..a25fb8a9b0d 100644 --- a/Jakefile +++ b/Jakefile @@ -17,6 +17,9 @@ var LKGDirectory = "bin/"; var copyright = "CopyrightNotice.txt"; var thirdParty = "ThirdPartyNoticeText.txt"; +// add node_modules to path so we don't need global modules, prefer the modules by adding them first +process.env.path = path.resolve("./node_modules/.bin/") + path.delimiter + process.env.path; + var compilerSources = [ "core.ts", "sys.ts", diff --git a/package.json b/package.json index 809ba9074c4..71dba4fbefd 100644 --- a/package.json +++ b/package.json @@ -37,5 +37,8 @@ "mocha" : "latest", "chai" : "latest", "browserify" : "latest" + }, + "scripts": { + "test": "jake runtests" } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ffe79d7b48c..3c994fc3fe4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2978,6 +2978,33 @@ module ts { return type; } + function forEachMatchingParameterType(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) { + var sourceMax = source.parameters.length; + var targetMax = target.parameters.length; + var count: number; + if (source.hasRestParameter && target.hasRestParameter) { + count = sourceMax > targetMax ? sourceMax : targetMax; + sourceMax--; + targetMax--; + } + else if (source.hasRestParameter) { + sourceMax--; + count = targetMax; + } + else if (target.hasRestParameter) { + targetMax--; + count = sourceMax; + } + else { + count = sourceMax < targetMax ? sourceMax : targetMax; + } + for (var i = 0; i < count; i++) { + var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); + var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); + callback(s, t); + } + } + function createInferenceContext(typeParameters: TypeParameter[]): InferenceContext { var inferences: Type[][] = []; for (var i = 0; i < typeParameters.length; i++) inferences.push([]); @@ -3048,8 +3075,9 @@ module ts { inferFromProperties(source, target); inferFromSignatures(source, target, SignatureKind.Call); inferFromSignatures(source, target, SignatureKind.Construct); - inferFromIndexTypes(source, target, IndexKind.String); - inferFromIndexTypes(source, target, IndexKind.Number); + inferFromIndexTypes(source, target, IndexKind.String, IndexKind.String); + inferFromIndexTypes(source, target, IndexKind.Number, IndexKind.Number); + inferFromIndexTypes(source, target, IndexKind.String, IndexKind.Number); depth--; } } @@ -3073,42 +3101,19 @@ module ts { var targetLen = targetSignatures.length; var len = sourceLen < targetLen ? sourceLen : targetLen; for (var i = 0; i < len; i++) { - inferFromParameters(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i])); + inferFromSignature(getErasedSignature(sourceSignatures[sourceLen - len + i]), getErasedSignature(targetSignatures[targetLen - len + i])); } } - function inferFromParameters(source: Signature, target: Signature) { - var sourceMax = source.parameters.length; - var targetMax = target.parameters.length; - var checkCount: number; - if (!source.hasRestParameter && !target.hasRestParameter) { - checkCount = sourceMax < targetMax ? sourceMax : targetMax; - } - else if (source.hasRestParameter) { - sourceMax--; - checkCount = targetMax; - } - else if (target.hasRestParameter) { - targetMax--; - checkCount = sourceMax; - } - else { - checkCount = sourceMax > targetMax ? sourceMax : targetMax; - sourceMax--; - targetMax--; - } - for (var i = 0; i < checkCount; i++) { - var s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source); - var t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target); - inferFromTypes(s, t); - } + function inferFromSignature(source: Signature, target: Signature) { + forEachMatchingParameterType(source, target, inferFromTypes); inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target)); } - function inferFromIndexTypes(source: Type, target: Type, kind: IndexKind) { - var targetIndexType = getIndexTypeOfType(target, kind); + function inferFromIndexTypes(source: Type, target: Type, sourceKind: IndexKind, targetKind: IndexKind) { + var targetIndexType = getIndexTypeOfType(target, targetKind); if (targetIndexType) { - var sourceIndexType = getIndexTypeOfType(source, kind); + var sourceIndexType = getIndexTypeOfType(source, sourceKind); if (sourceIndexType) { inferFromTypes(sourceIndexType, targetIndexType); } @@ -3655,6 +3660,41 @@ module ts { return result; } + // If type has a single call signature and no other members, return that signature. Otherwise, return undefined. + function getSingleCallSignature(type: Type): Signature { + if (type.flags & TypeFlags.ObjectType) { + var resolved = resolveObjectTypeMembers(type); + if (resolved.callSignatures.length === 1 && resolved.constructSignatures.length === 0 && + resolved.properties.length === 0 && !resolved.stringIndexType && !resolved.numberIndexType) { + return resolved.callSignatures[0]; + } + } + return undefined; + } + + // Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec) + function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper: TypeMapper): Signature { + var context = createInferenceContext(signature.typeParameters); + forEachMatchingParameterType(contextualSignature, signature, (source, target) => { + // Type parameters from outer context referenced by source type are fixed by instantiation of the source type + inferTypes(context, instantiateType(source, contextualMapper), target); + }); + return getSignatureInstantiation(signature, getInferredTypes(context)); + } + + // Inferentially type an expression by a contextual parameter type (section 4.12.2 in TypeScript spec) + function inferentiallyTypeExpession(expr: Expression, contextualType: Type, contextualMapper: TypeMapper): Type { + var type = checkExpression(expr, contextualType, contextualMapper); + var signature = getSingleCallSignature(type); + if (signature && signature.typeParameters) { + var contextualSignature = getSingleCallSignature(contextualType); + if (contextualSignature && !contextualSignature.typeParameters) { + type = getOrCreateTypeFromSignature(instantiateSignatureInContextOf(signature, contextualSignature, contextualMapper)); + } + } + return type; + } + function inferTypeArguments(signature: Signature, args: Expression[], excludeArgument?: boolean[]): Type[] { var typeParameters = signature.typeParameters; var context = createInferenceContext(typeParameters); @@ -3663,7 +3703,7 @@ module ts { for (var i = 0; i < args.length; i++) { if (!excludeArgument || excludeArgument[i] === undefined) { var parameterType = getTypeAtPosition(signature, i); - inferTypes(context, checkExpression(args[i], parameterType, mapper), parameterType); + inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType); } } // Next, infer from those context sensitive arguments that are no longer excluded @@ -3671,7 +3711,7 @@ module ts { for (var i = 0; i < args.length; i++) { if (excludeArgument[i] === false) { var parameterType = getTypeAtPosition(signature, i); - inferTypes(context, checkExpression(args[i], parameterType, mapper), parameterType); + inferTypes(context, inferentiallyTypeExpession(args[i], parameterType, mapper), parameterType); } } } @@ -3932,12 +3972,10 @@ module ts { } // Aggregate the types of expressions within all the return statements. - var types: Type[] = []; - checkAndAggregateReturnExpressionTypes(func.body); + var types = checkAndAggregateReturnExpressionTypes(func.body, contextualType, contextualMapper); // Try to return the best common type if we have any return expressions. - if (types.length) { - + if (types.length > 0) { var commonType = getBestCommonType(types, /*contextualType:*/ undefined, /*candidatesOnly:*/ true); if (!commonType) { error(func, Diagnostics.No_best_common_type_exists_among_return_expressions); @@ -3963,16 +4001,18 @@ module ts { } return voidType; + } - function checkAndAggregateReturnExpressionTypes(node: Node) { + // WARNING: This has the same semantics as the forEach family of functions, + // in that traversal terminates in the event that 'visitor' supplies a truthy value. + function forEachReturnStatement(body: Block, visitor: (stmt: ReturnStatement) => T): T { + + return traverse(body); + + function traverse(node: Node): T { switch (node.kind) { case SyntaxKind.ReturnStatement: - var expr = (node).expression; - if (expr) { - var type = checkAndMarkExpression(expr, contextualType, contextualMapper); - if (!contains(types, type)) types.push(type); - } - break; + return visitor(node); case SyntaxKind.Block: case SyntaxKind.FunctionBlock: case SyntaxKind.IfStatement: @@ -3989,15 +4029,77 @@ module ts { case SyntaxKind.TryBlock: case SyntaxKind.CatchBlock: case SyntaxKind.FinallyBlock: - forEachChild(node, checkAndAggregateReturnExpressionTypes); - break; + return forEachChild(node, traverse); } } } + /// Returns a set of types relating to every return expression relating to a function block. + function checkAndAggregateReturnExpressionTypes(body: Block, contextualType?: Type, contextualMapper?: TypeMapper): Type[] { + var aggregatedTypes: Type[] = []; + + forEachReturnStatement(body, returnStatement => { + var expr = returnStatement.expression; + if (expr) { + var type = checkAndMarkExpression(expr, contextualType, contextualMapper); + if (!contains(aggregatedTypes, type)) { + aggregatedTypes.push(type); + } + } + }); + + return aggregatedTypes; + } + + function bodyContainsAReturnStatement(funcBody: Block) { + return forEachReturnStatement(funcBody, returnStatement => { + return true; + }); + } + + function bodyContainsSingleThrowStatement(body: Block) { + return (body.statements.length === 1) && (body.statements[0].kind === SyntaxKind.ThrowStatement) + } + + // TypeScript Specification 1.0 (6.3) - July 2014 + // An explicitly typed function whose return type isn't the Void or the Any type + // must have at least one return statement somewhere in its body. + // An exception to this rule is if the function implementation consists of a single 'throw' statement. + function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionDeclaration, returnType: Type): void { + // Functions that return 'void' or 'any' don't need any return expressions. + if (returnType === voidType || returnType === anyType) { + return; + } + + // If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check. + if (!func.body || func.body.kind !== SyntaxKind.FunctionBlock) { + return; + } + + var bodyBlock = func.body; + + // Ensure the body has at least one return expression. + if (bodyContainsAReturnStatement(bodyBlock)) { + return; + } + + // If there are no return expressions, then we need to check if + // the function body consists solely of a throw statement; + // this is to make an exception for unimplemented functions. + if (bodyContainsSingleThrowStatement(bodyBlock)) { + return; + } + + // This function does not conform to the specification. + error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement); + } + function checkFunctionExpression(node: FunctionExpression, contextualType?: Type, contextualMapper?: TypeMapper): Type { // The identityMapper object is used to indicate that function expressions are wildcards - if (contextualMapper === identityMapper) return anyFunctionType; + if (contextualMapper === identityMapper) { + return anyFunctionType; + } + var type = getTypeOfSymbol(node.symbol); var links = getNodeLinks(node); @@ -4015,6 +4117,9 @@ module ts { signature.resolvedReturnType = returnType; } } + else { + checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type)); + } } checkSignatureDeclaration(node); if (node.body.kind === SyntaxKind.FunctionBlock) { @@ -4587,28 +4692,9 @@ module ts { } function checkAccessorDeclaration(node: AccessorDeclaration) { - function checkGetterContainsSingleThrowStatement(node: AccessorDeclaration): boolean { - var block = node.body; - return block.statements.length === 1 && block.statements[0].kind === SyntaxKind.ThrowStatement; - } - - function checkGetterReturnsValue(n: Node): boolean { - switch (n.kind) { - case SyntaxKind.ReturnStatement: - return true; - // do not dive into function-like things - return statements there don't count - case SyntaxKind.FunctionExpression: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ArrowFunction: - case SyntaxKind.ObjectLiteral: - return false; - default: - return forEachChild(n, checkGetterReturnsValue); - } - } if (node.kind === SyntaxKind.GetAccessor) { - if (!isInAmbientContext(node) && node.body && !(checkGetterContainsSingleThrowStatement(node) || checkGetterReturnsValue(node))) { - error(node.name, Diagnostics.Getters_must_return_a_value); + if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(node.body) || bodyContainsSingleThrowStatement(node.body))) { + error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement); } } @@ -4837,8 +4923,6 @@ module ts { } } } - - // TODO: Check at least one return statement in non-void/any function (except single throw) } function checkFunctionDeclaration(node: FunctionDeclaration) { @@ -4850,7 +4934,11 @@ module ts { if (node === firstDeclaration) { checkFunctionOrConstructorSymbol(symbol); } + checkSourceElement(node.body); + if (node.type) { + checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type)); + } // If there is no body and no explicit return type, then report an error. if (program.getCompilerOptions().noImplicitAny && !node.body && !node.type) { @@ -5255,7 +5343,7 @@ module ts { // for interfaces property and indexer might be inherited from different bases // check if any base class already has both property and indexer. // check should be performed only if 'type' is the first type that brings property\indexer together - var someBaseClassHasBothPropertyAndIndexer = forEach((type).baseTypes, (base) => getPropertyOfType(base, prop.name) && getIndexTypeOfType(base, indexKind)); + var someBaseClassHasBothPropertyAndIndexer = forEach((type).baseTypes, base => getPropertyOfType(base, prop.name) && getIndexTypeOfType(base, indexKind)); errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : type.symbol.declarations[0]; } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index c2c422c64b6..8f58d9f3042 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -114,8 +114,9 @@ module ts { The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2117, category: DiagnosticCategory.Error, key: "The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter." }, The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number: { code: 2118, category: DiagnosticCategory.Error, key: "The left-hand side of an 'in' expression must be of types 'any', 'string' or 'number'." }, The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2119, category: DiagnosticCategory.Error, key: "The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter" }, - Getters_must_return_a_value: { code: 2126, category: DiagnosticCategory.Error, key: "Getters must return a value." }, + A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2126, category: DiagnosticCategory.Error, key: "A 'get' accessor must return a value or consist of a single 'throw' statement." }, Getter_and_setter_accessors_do_not_agree_in_visibility: { code: 2127, category: DiagnosticCategory.Error, key: "Getter and setter accessors do not agree in visibility." }, + A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2131, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." }, Untyped_function_calls_may_not_accept_type_arguments: { code: 2158, category: DiagnosticCategory.Error, key: "Untyped function calls may not accept type arguments." }, The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter: { code: 2120, category: DiagnosticCategory.Error, key: "The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter." }, The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type: { code: 2121, category: DiagnosticCategory.Error, key: "The right-hand side of an 'instanceof' expression must be of type 'any' or of a type assignable to the 'Function' interface type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ad5e89f2b38..b418ec7a404 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -449,7 +449,7 @@ "category": "Error", "code": 2119 }, - "Getters must return a value.": { + "A 'get' accessor must return a value or consist of a single 'throw' statement.": { "category": "Error", "code": 2126 }, @@ -457,6 +457,10 @@ "category": "Error", "code": 2127 }, + "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement.": { + "category": "Error", + "code": 2131 + }, "Untyped function calls may not accept type arguments.": { "category": "Error", "code": 2158 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index b132a7d13c1..0304586bbca 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -766,7 +766,7 @@ module ts { return false; } - // Parses a semicolon-delimited list of elements + // Parses a list of elements function parseList(kind: ParsingContext, parseElement: () => T): NodeArray { var saveParsingContext = parsingContext; parsingContext |= 1 << kind; @@ -1070,7 +1070,7 @@ module ts { return finishNode(node); } - function checkIndexSignature(node: SignatureDeclaration, indexerStart: number, indexerLength: number): boolean { + function checkIndexSignature(node: SignatureDeclaration, indexerStart: number, indexerLength: number): void { var parameter = node.parameters[0]; if (node.parameters.length !== 1) { var arityDiagnostic = Diagnostics.An_index_signature_must_have_exactly_one_parameter diff --git a/tests/baselines/reference/ParameterList5.errors.txt b/tests/baselines/reference/ParameterList5.errors.txt index 37487b5c319..412fb71eb14 100644 --- a/tests/baselines/reference/ParameterList5.errors.txt +++ b/tests/baselines/reference/ParameterList5.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/compiler/ParameterList5.ts (2 errors) ==== +==== tests/cases/compiler/ParameterList5.ts (3 errors) ==== function A(): (public B) => C { + ~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. ~~~~~~~~ !!! A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/ambientGetters.errors.txt b/tests/baselines/reference/ambientGetters.errors.txt index 05c40581074..a8c913b66c7 100644 --- a/tests/baselines/reference/ambientGetters.errors.txt +++ b/tests/baselines/reference/ambientGetters.errors.txt @@ -1,9 +1,11 @@ -==== tests/cases/compiler/ambientGetters.ts (2 errors) ==== +==== tests/cases/compiler/ambientGetters.ts (3 errors) ==== declare class A { get length() : number; ~ !!! '{' expected. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } declare class B { diff --git a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt index 85867f5e573..6bb45b67ee7 100644 --- a/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt +++ b/tests/baselines/reference/conflictingTypeAnnotatedVar.errors.txt @@ -1,8 +1,12 @@ -==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (2 errors) ==== +==== tests/cases/compiler/conflictingTypeAnnotatedVar.ts (4 errors) ==== var foo: string; function foo(): number { } ~~~ !!! Duplicate identifier 'foo'. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function foo(): number { } ~~~ -!!! Duplicate identifier 'foo'. \ No newline at end of file +!!! Duplicate identifier 'foo'. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/contextualSignatureInstantiation3.js b/tests/baselines/reference/contextualSignatureInstantiation3.js new file mode 100644 index 00000000000..44737476482 --- /dev/null +++ b/tests/baselines/reference/contextualSignatureInstantiation3.js @@ -0,0 +1,42 @@ +//// [contextualSignatureInstantiation3.ts] +function map(items: T[], f: (x: T) => U): U[]{ + return items.map(f); +} + +function identity(x: T) { + return x; +} + +function singleton(x: T) { + return [x]; +} + +var xs = [1, 2, 3]; + +// Have compiler check that we get the correct types +var v1: number[]; +var v1 = xs.map(identity); // Error if not number[] +var v1 = map(xs, identity); // Error if not number[] + +var v2: number[][]; +var v2 = xs.map(singleton); // Error if not number[][] +var v2 = map(xs, singleton); // Error if not number[][] + + +//// [contextualSignatureInstantiation3.js] +function map(items, f) { + return items.map(f); +} +function identity(x) { + return x; +} +function singleton(x) { + return [x]; +} +var xs = [1, 2, 3]; +var v1; +var v1 = xs.map(identity); +var v1 = map(xs, identity); +var v2; +var v2 = xs.map(singleton); +var v2 = map(xs, singleton); diff --git a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt index cb501a10e06..414fa7dc4c2 100644 --- a/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt +++ b/tests/baselines/reference/errorOnContextuallyTypedReturnType.errors.txt @@ -1,7 +1,9 @@ -==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (1 errors) ==== +==== tests/cases/compiler/errorOnContextuallyTypedReturnType.ts (2 errors) ==== var n1: () => boolean = function () { }; // expect an error here ~~ !!! Type '() => void' is not assignable to type '() => boolean': !!! Type 'void' is not assignable to type 'boolean'. var n2: () => boolean = function ():boolean { }; // expect an error here + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/functionImplementationErrors.errors.txt b/tests/baselines/reference/functionImplementationErrors.errors.txt index d9d35c555ad..3da56bd6818 100644 --- a/tests/baselines/reference/functionImplementationErrors.errors.txt +++ b/tests/baselines/reference/functionImplementationErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/functions/functionImplementationErrors.ts (6 errors) ==== +==== tests/cases/conformance/functions/functionImplementationErrors.ts (7 errors) ==== // FunctionExpression with no return type annotation with multiple return statements with unrelated types var f1 = function () { ~~~~~~~~~~~~~ @@ -47,6 +47,8 @@ // Function implemetnation with non -void return type annotation with no return function f5(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } var m; diff --git a/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt b/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt new file mode 100644 index 00000000000..b354a9f8852 --- /dev/null +++ b/tests/baselines/reference/functionWithThrowButNoReturn1.errors.txt @@ -0,0 +1,8 @@ +==== tests/cases/compiler/functionWithThrowButNoReturn1.ts (1 errors) ==== + function fn(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + throw new Error('NYI'); + var t; + } + \ No newline at end of file diff --git a/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt new file mode 100644 index 00000000000..6ddbc91db57 --- /dev/null +++ b/tests/baselines/reference/functionsMissingReturnStatementsAndExpressions.errors.txt @@ -0,0 +1,129 @@ +==== tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts (5 errors) ==== + + function f1(): string { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + // errors because there are no return statements + } + + function f2(): string { + // Permissible; returns undefined. + return; + } + + function f3(): string { + return "Okay, because this is a return expression."; + } + + function f4(): void { + // Fine since we are typed void. + } + + function f5(): void { + // Fine since we are typed void. + return; + } + + function f6(): void { + // Fine since we are typed void and return undefined + return undefined; + } + + function f7(): void { + // Fine since we are typed void and return null + return null; + } + + function f8(): void { + // Fine since are typed any. + return; + } + + function f9(): void { + // Fine since we are typed any and return undefined + return undefined; + } + + function f10(): void { + // Fine since we are typed any and return null + return null; + } + + function f11(): string { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f12(): void { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f13(): any { + // Fine since we consist of a single throw statement. + throw undefined; + } + + function f14(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are annotated. + throw undefined; + throw null; + } + + function f15(): number { + // Fine, since we have a return statement somewhere. + throw undefined; + throw null; + return; + } + + + function f16() { + // Okay; not type annotated. + } + + function f17() { + // Okay; not type annotated. + return; + } + + function f18() { + return "Okay, not type annotated."; + } + + + class C { + public get m1() { + ~~ +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. + // Errors; get accessors must return a value. + } + + public get m2() { + // Permissible; returns undefined. + return; + } + + public get m3() { + return "Okay, because this is a return expression."; + } + + public get m4() { + // Fine since this consists of a single throw statement. + throw null; + } + + public get m5() { + ~~ +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are a get accessor. + throw null; + throw undefined. + } + ~ +!!! Identifier expected. + } \ No newline at end of file diff --git a/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt b/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt index 71545ae7503..1320a21f46b 100644 --- a/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt +++ b/tests/baselines/reference/genericRecursiveImplicitConstructorErrors3.errors.txt @@ -1,8 +1,10 @@ -==== tests/cases/compiler/genericRecursiveImplicitConstructorErrors3.ts (7 errors) ==== +==== tests/cases/compiler/genericRecursiveImplicitConstructorErrors3.ts (8 errors) ==== module TypeScript { export class MemberName { static create(arg1: any, arg2?: any, arg3?: any): MemberName { ~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~~~~~~~ !!! Generic type 'MemberName' requires 3 type argument(s). } } diff --git a/tests/baselines/reference/getterMissingReturnError.errors.txt b/tests/baselines/reference/getterMissingReturnError.errors.txt index cf4f9b6b1a7..ae560c5de87 100644 --- a/tests/baselines/reference/getterMissingReturnError.errors.txt +++ b/tests/baselines/reference/getterMissingReturnError.errors.txt @@ -4,7 +4,7 @@ ~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } } diff --git a/tests/baselines/reference/gettersAndSettersErrors.errors.txt b/tests/baselines/reference/gettersAndSettersErrors.errors.txt index 1cfefea5202..dbd06a744f0 100644 --- a/tests/baselines/reference/gettersAndSettersErrors.errors.txt +++ b/tests/baselines/reference/gettersAndSettersErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/gettersAndSettersErrors.ts (9 errors) ==== +==== tests/cases/compiler/gettersAndSettersErrors.ts (10 errors) ==== class C { public get Foo() { return "foo";} // ok ~~~ @@ -16,6 +16,8 @@ public set Goo(v:string):string {} // error - setters must not specify a return type ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } class E { diff --git a/tests/baselines/reference/giant.errors.txt b/tests/baselines/reference/giant.errors.txt index 35dddbb324e..f6b6dd5c796 100644 --- a/tests/baselines/reference/giant.errors.txt +++ b/tests/baselines/reference/giant.errors.txt @@ -26,7 +26,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -40,7 +40,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -62,7 +62,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -128,7 +128,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -142,7 +142,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -164,7 +164,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -247,7 +247,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -261,7 +261,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -283,7 +283,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -456,7 +456,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -470,7 +470,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -492,7 +492,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -558,7 +558,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -572,7 +572,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -594,7 +594,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. @@ -677,7 +677,7 @@ ~~~ !!! Duplicate identifier 'pgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. public psF(param:any) { } ~~~~~~ !!! '{' expected. @@ -691,7 +691,7 @@ ~~~ !!! Duplicate identifier 'rgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. private rsF(param:any) { } ~~~~~~~ !!! '{' expected. @@ -713,7 +713,7 @@ ~~~ !!! Duplicate identifier 'tgF'. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } ~ !!! '{' expected. diff --git a/tests/baselines/reference/indexSignatureTypeInference.errors.txt b/tests/baselines/reference/indexSignatureTypeInference.errors.txt new file mode 100644 index 00000000000..097fef70921 --- /dev/null +++ b/tests/baselines/reference/indexSignatureTypeInference.errors.txt @@ -0,0 +1,23 @@ +==== tests/cases/compiler/indexSignatureTypeInference.ts (1 errors) ==== + interface NumberMap { + [index: number]: T; + } + + interface StringMap { + [index: string]: T; + } + + declare function numberMapToArray(object: NumberMap): T[]; + declare function stringMapToArray(object: StringMap): T[]; + + var numberMap: NumberMap; + var stringMap: StringMap; + + var v1: Function[]; + var v1 = numberMapToArray(numberMap); // Ok + var v1 = numberMapToArray(stringMap); // Ok + var v1 = stringMapToArray(numberMap); // Error expected here + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! Supplied parameters do not match any signature of call target. + var v1 = stringMapToArray(stringMap); // Ok + \ No newline at end of file diff --git a/tests/baselines/reference/indexSignatureTypeInference.js b/tests/baselines/reference/indexSignatureTypeInference.js new file mode 100644 index 00000000000..a4f79801258 --- /dev/null +++ b/tests/baselines/reference/indexSignatureTypeInference.js @@ -0,0 +1,30 @@ +//// [indexSignatureTypeInference.ts] +interface NumberMap { + [index: number]: T; +} + +interface StringMap { + [index: string]: T; +} + +declare function numberMapToArray(object: NumberMap): T[]; +declare function stringMapToArray(object: StringMap): T[]; + +var numberMap: NumberMap; +var stringMap: StringMap; + +var v1: Function[]; +var v1 = numberMapToArray(numberMap); // Ok +var v1 = numberMapToArray(stringMap); // Ok +var v1 = stringMapToArray(numberMap); // Error expected here +var v1 = stringMapToArray(stringMap); // Ok + + +//// [indexSignatureTypeInference.js] +var numberMap; +var stringMap; +var v1; +var v1 = numberMapToArray(numberMap); +var v1 = numberMapToArray(stringMap); +var v1 = stringMapToArray(numberMap); +var v1 = stringMapToArray(stringMap); diff --git a/tests/baselines/reference/invalidReturnStatements.errors.txt b/tests/baselines/reference/invalidReturnStatements.errors.txt index d870be638b9..ee371f5f000 100644 --- a/tests/baselines/reference/invalidReturnStatements.errors.txt +++ b/tests/baselines/reference/invalidReturnStatements.errors.txt @@ -1,9 +1,17 @@ -==== tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts (2 errors) ==== +==== tests/cases/conformance/statements/returnStatements/invalidReturnStatements.ts (6 errors) ==== // all the following should be error function fn1(): number { } + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn2(): string { } + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn3(): boolean { } + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn4(): Date { } + ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function fn7(): any { } // should be valid: any includes void interface I { id: number } diff --git a/tests/baselines/reference/missingReturnStatement.errors.txt b/tests/baselines/reference/missingReturnStatement.errors.txt new file mode 100644 index 00000000000..9a92adf4c03 --- /dev/null +++ b/tests/baselines/reference/missingReturnStatement.errors.txt @@ -0,0 +1,10 @@ +==== tests/cases/compiler/missingReturnStatement.ts (1 errors) ==== + module Test { + export class Bug { + public foo():string { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + } + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/missingReturnStatement1.errors.txt b/tests/baselines/reference/missingReturnStatement1.errors.txt new file mode 100644 index 00000000000..d1d47368bb1 --- /dev/null +++ b/tests/baselines/reference/missingReturnStatement1.errors.txt @@ -0,0 +1,9 @@ +==== tests/cases/compiler/missingReturnStatement1.ts (1 errors) ==== + class Foo { + foo(): number { + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + //return 4; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/multiLineErrors.errors.txt b/tests/baselines/reference/multiLineErrors.errors.txt index b01adc3bfb0..911c07731e3 100644 --- a/tests/baselines/reference/multiLineErrors.errors.txt +++ b/tests/baselines/reference/multiLineErrors.errors.txt @@ -1,10 +1,15 @@ -==== tests/cases/compiler/multiLineErrors.ts (1 errors) ==== +==== tests/cases/compiler/multiLineErrors.ts (2 errors) ==== var t = 32; function noReturn(): { + ~ n: string; + ~~~~~~~~~~~~~~ y: number; + ~~~~~~~~~~~~~~ } + ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. { var x = 4; var y = 10; diff --git a/tests/baselines/reference/parserAccessors1.errors.txt b/tests/baselines/reference/parserAccessors1.errors.txt index 4621637b211..76747e37104 100644 --- a/tests/baselines/reference/parserAccessors1.errors.txt +++ b/tests/baselines/reference/parserAccessors1.errors.txt @@ -2,5 +2,5 @@ class C { get Foo() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserAccessors3.errors.txt b/tests/baselines/reference/parserAccessors3.errors.txt index 4d722dd1310..dd1f2075ae6 100644 --- a/tests/baselines/reference/parserAccessors3.errors.txt +++ b/tests/baselines/reference/parserAccessors3.errors.txt @@ -1,4 +1,4 @@ ==== tests/cases/conformance/parser/ecmascript5/Accessors/parserAccessors3.ts (1 errors) ==== var v = { get Foo() { } }; ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserAccessors7.errors.txt b/tests/baselines/reference/parserAccessors7.errors.txt index 13597d19f71..cac6f016814 100644 --- a/tests/baselines/reference/parserAccessors7.errors.txt +++ b/tests/baselines/reference/parserAccessors7.errors.txt @@ -3,4 +3,4 @@ ~~~ !!! A 'get' accessor cannot have parameters. ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserES3Accessors1.errors.txt b/tests/baselines/reference/parserES3Accessors1.errors.txt index 3ab21b3001e..53bfc5e868e 100644 --- a/tests/baselines/reference/parserES3Accessors1.errors.txt +++ b/tests/baselines/reference/parserES3Accessors1.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserES3Accessors3.errors.txt b/tests/baselines/reference/parserES3Accessors3.errors.txt index 3678eb94dc1..74a79ccf6d8 100644 --- a/tests/baselines/reference/parserES3Accessors3.errors.txt +++ b/tests/baselines/reference/parserES3Accessors3.errors.txt @@ -3,4 +3,4 @@ ~~~ !!! Accessors are only available when targeting ECMAScript 5 and higher. ~~~ -!!! Getters must return a value. \ No newline at end of file +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt index 15bc9ad3385..354cfff1fdd 100644 --- a/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_Block3.errors.txt @@ -1,9 +1,13 @@ -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/Blocks/parserErrorRecovery_Block3.ts (3 errors) ==== class C { private a(): boolean { + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. private b(): boolean { ~~~~~~~ !!! Statement expected. + ~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } } \ No newline at end of file diff --git a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt index 2239f1ff993..574c03823df 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts1.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (10 errors) ==== class C extends A implements B { ~~~~ !!! Cannot find name 'A'. @@ -30,6 +30,8 @@ function f2(): F { ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~ !!! Cannot find name 'F'. } diff --git a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt index b99d6826169..f3b47f04368 100644 --- a/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt +++ b/tests/baselines/reference/parserGenericsInTypeContexts2.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (9 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts2.ts (10 errors) ==== class C extends A, Y>> implements B, Y>> { ~~~~~~~~~~~~~~~~ !!! Cannot find name 'A'. @@ -30,6 +30,8 @@ function f2(): F, Y>> { ~~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~~~~~~~~~~~~~ !!! Cannot find name 'F'. } diff --git a/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt b/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt index 33705621fb8..0f290dbd8ab 100644 --- a/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt +++ b/tests/baselines/reference/parserGetAccessorWithTypeParameters1.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! An accessor cannot have type parameters. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessor1.errors.txt b/tests/baselines/reference/parserMemberAccessor1.errors.txt index cc64233237b..c768b0ce2fe 100644 --- a/tests/baselines/reference/parserMemberAccessor1.errors.txt +++ b/tests/baselines/reference/parserMemberAccessor1.errors.txt @@ -2,6 +2,6 @@ class C { get foo() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. set foo(a) { } } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt index a052f03808e..403a30a67ae 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration1.errors.txt @@ -2,5 +2,5 @@ class C { get a() { } ~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt index 8ea973bbb29..a1b29085f5d 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration10.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'export' modifier cannot appear on a class element. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt index d3ca95a6bc2..7cbf2606274 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration12.errors.txt @@ -4,5 +4,5 @@ ~~~ !!! A 'get' accessor cannot have parameters. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt index 3cdd230ad65..1a32d342f1b 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration2.errors.txt @@ -2,5 +2,5 @@ class C { get "b"() { } ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt index 53a0dd84fac..dbf94b6420f 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration3.errors.txt @@ -2,5 +2,5 @@ class C { get 0() { } ~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt index 614c1251aa4..20ebd2f3583 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration7.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! Accessibility modifier already seen. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt index f28ee32f00e..f6d151bfb7f 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration8.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'static' modifier already seen. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt b/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt index d2a52098aa7..e4c88dfd57d 100644 --- a/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt +++ b/tests/baselines/reference/parserMemberAccessorDeclaration9.errors.txt @@ -4,5 +4,5 @@ ~~~~~~ !!! 'public' modifier must precede 'static' modifier. ~~~ -!!! Getters must return a value. +!!! A 'get' accessor must return a value or consist of a single 'throw' statement. } \ No newline at end of file diff --git a/tests/baselines/reference/parserParameterList5.errors.txt b/tests/baselines/reference/parserParameterList5.errors.txt index c8a9aa31b78..ccc5d8c0dbf 100644 --- a/tests/baselines/reference/parserParameterList5.errors.txt +++ b/tests/baselines/reference/parserParameterList5.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts (2 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ParameterLists/parserParameterList5.ts (3 errors) ==== function A(): (public B) => C { + ~~~~~~~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. ~~~~~~~~ !!! A parameter property is only allowed in a constructor implementation. ~ diff --git a/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt b/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt index 135f06cf304..f4898163e0f 100644 --- a/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt +++ b/tests/baselines/reference/parserSetAccessorWithTypeAnnotation1.errors.txt @@ -1,7 +1,9 @@ -==== tests/cases/conformance/parser/ecmascript5/Accessors/parserSetAccessorWithTypeAnnotation1.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/Accessors/parserSetAccessorWithTypeAnnotation1.ts (2 errors) ==== class C { set foo(v): number { ~~~ !!! A 'set' accessor cannot have a return type annotation. + ~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. } } \ No newline at end of file diff --git a/tests/baselines/reference/recursiveFunctionTypes.errors.txt b/tests/baselines/reference/recursiveFunctionTypes.errors.txt index e14d3a38a5c..833fcf386c0 100644 --- a/tests/baselines/reference/recursiveFunctionTypes.errors.txt +++ b/tests/baselines/reference/recursiveFunctionTypes.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/recursiveFunctionTypes.ts (10 errors) ==== +==== tests/cases/compiler/recursiveFunctionTypes.ts (12 errors) ==== function fn(): typeof fn { return 1; } ~ !!! Type 'number' is not assignable to type '() => typeof fn'. @@ -17,7 +17,11 @@ function f1(d: typeof f1) { } function f2(): typeof g2 { } + ~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function g2(): typeof f2 { } + ~~~~~~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. interface I { } function f3(): I { return f3; } diff --git a/tests/baselines/reference/returnTypeParameter.errors.txt b/tests/baselines/reference/returnTypeParameter.errors.txt index 1490825c77a..f8927fef427 100644 --- a/tests/baselines/reference/returnTypeParameter.errors.txt +++ b/tests/baselines/reference/returnTypeParameter.errors.txt @@ -1,5 +1,7 @@ -==== tests/cases/compiler/returnTypeParameter.ts (1 errors) ==== +==== tests/cases/compiler/returnTypeParameter.ts (2 errors) ==== function f(a: T): T { } // error, no return statement + ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. function f2(a: T): T { return T; } // bug was that this satisfied the return statement requirement ~ !!! Cannot find name 'T'. \ No newline at end of file diff --git a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt index 9903408f70b..da073522ae8 100644 --- a/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt +++ b/tests/baselines/reference/typeParameterUsedAsTypeParameterConstraint4.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/typeParameterUsedAsTypeParameterConstraint4.ts (25 errors) ==== +==== tests/cases/conformance/types/objectTypeLiteral/callSignatures/typeParameterUsedAsTypeParameterConstraint4.ts (29 errors) ==== // Type parameters are in scope in their own and other type parameter lists // Some negative cases @@ -35,9 +35,13 @@ ~~~~~~~~~~~ !!! Constraint of a type parameter cannot reference any type parameter from the same type parameter list. ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'V'. function bar(): X { // error ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'X'. function baz(a: X, b: Y): T { x = y; @@ -54,9 +58,13 @@ ~~~~~~~~~~~ !!! Constraint of a type parameter cannot reference any type parameter from the same type parameter list. ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'W'. function bar(): Y { // error ~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~ !!! Cannot find name 'Y'. function baz(a: X, b: Y): T { x = y; diff --git a/tests/baselines/reference/unknownSymbols1.errors.txt b/tests/baselines/reference/unknownSymbols1.errors.txt index 220d7ba0ddb..beb39743441 100644 --- a/tests/baselines/reference/unknownSymbols1.errors.txt +++ b/tests/baselines/reference/unknownSymbols1.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/unknownSymbols1.ts (13 errors) ==== +==== tests/cases/compiler/unknownSymbols1.ts (14 errors) ==== var x = asdf; ~~~~ !!! Cannot find name 'asdf'. @@ -10,6 +10,8 @@ ~~~~ !!! Cannot find name 'asdf'. ~~~~ +!!! A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement. + ~~~~ !!! Cannot find name 'asdf'. function foo2() { return asdf; diff --git a/tests/cases/compiler/contextualSignatureInstantiation3.ts b/tests/cases/compiler/contextualSignatureInstantiation3.ts new file mode 100644 index 00000000000..a71f08d209d --- /dev/null +++ b/tests/cases/compiler/contextualSignatureInstantiation3.ts @@ -0,0 +1,22 @@ +function map(items: T[], f: (x: T) => U): U[]{ + return items.map(f); +} + +function identity(x: T) { + return x; +} + +function singleton(x: T) { + return [x]; +} + +var xs = [1, 2, 3]; + +// Have compiler check that we get the correct types +var v1: number[]; +var v1 = xs.map(identity); // Error if not number[] +var v1 = map(xs, identity); // Error if not number[] + +var v2: number[][]; +var v2 = xs.map(singleton); // Error if not number[][] +var v2 = map(xs, singleton); // Error if not number[][] diff --git a/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts new file mode 100644 index 00000000000..81259fd7c0c --- /dev/null +++ b/tests/cases/compiler/functionsMissingReturnStatementsAndExpressions.ts @@ -0,0 +1,119 @@ +// @target: es5 + +function f1(): string { + // errors because there are no return statements +} + +function f2(): string { + // Permissible; returns undefined. + return; +} + +function f3(): string { + return "Okay, because this is a return expression."; +} + +function f4(): void { + // Fine since we are typed void. +} + +function f5(): void { + // Fine since we are typed void. + return; +} + +function f6(): void { + // Fine since we are typed void and return undefined + return undefined; +} + +function f7(): void { + // Fine since we are typed void and return null + return null; +} + +function f8(): void { + // Fine since are typed any. + return; +} + +function f9(): void { + // Fine since we are typed any and return undefined + return undefined; +} + +function f10(): void { + // Fine since we are typed any and return null + return null; +} + +function f11(): string { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f12(): void { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f13(): any { + // Fine since we consist of a single throw statement. + throw undefined; +} + +function f14(): number { + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are annotated. + throw undefined; + throw null; +} + +function f15(): number { + // Fine, since we have a return statement somewhere. + throw undefined; + throw null; + return; +} + + +function f16() { + // Okay; not type annotated. +} + +function f17() { + // Okay; not type annotated. + return; +} + +function f18() { + return "Okay, not type annotated."; +} + + +class C { + public get m1() { + // Errors; get accessors must return a value. + } + + public get m2() { + // Permissible; returns undefined. + return; + } + + public get m3() { + return "Okay, because this is a return expression."; + } + + public get m4() { + // Fine since this consists of a single throw statement. + throw null; + } + + public get m5() { + // Not fine, since we can *only* consist of a single throw statement + // if no return statements are present but we are a get accessor. + throw null; + throw undefined. + } +} \ No newline at end of file diff --git a/tests/cases/compiler/indexSignatureTypeInference.ts b/tests/cases/compiler/indexSignatureTypeInference.ts new file mode 100644 index 00000000000..66fcb53d76c --- /dev/null +++ b/tests/cases/compiler/indexSignatureTypeInference.ts @@ -0,0 +1,19 @@ +interface NumberMap { + [index: number]: T; +} + +interface StringMap { + [index: string]: T; +} + +declare function numberMapToArray(object: NumberMap): T[]; +declare function stringMapToArray(object: StringMap): T[]; + +var numberMap: NumberMap; +var stringMap: StringMap; + +var v1: Function[]; +var v1 = numberMapToArray(numberMap); // Ok +var v1 = numberMapToArray(stringMap); // Ok +var v1 = stringMapToArray(numberMap); // Error expected here +var v1 = stringMapToArray(stringMap); // Ok