Skip to content

Commit 0377e7a

Browse files
committed
Merge remote-tracking branch 'origin/master' into pathMappingModuleResolution
2 parents 62370a0 + b5c64ad commit 0377e7a

11 files changed

Lines changed: 738 additions & 35 deletions

src/compiler/checker.ts

Lines changed: 34 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4527,7 +4527,7 @@ namespace ts {
45274527
return links.resolvedType;
45284528
}
45294529

4530-
function getStringLiteralType(text: string): StringLiteralType {
4530+
function getStringLiteralTypeForText(text: string): StringLiteralType {
45314531
if (hasProperty(stringLiteralTypes, text)) {
45324532
return stringLiteralTypes[text];
45334533
}
@@ -4537,10 +4537,10 @@ namespace ts {
45374537
return type;
45384538
}
45394539

4540-
function getTypeFromStringLiteral(node: StringLiteral | StringLiteralTypeNode): Type {
4540+
function getTypeFromStringLiteralTypeNode(node: StringLiteralTypeNode): Type {
45414541
const links = getNodeLinks(node);
45424542
if (!links.resolvedType) {
4543-
links.resolvedType = getStringLiteralType(node.text);
4543+
links.resolvedType = getStringLiteralTypeForText(node.text);
45444544
}
45454545
return links.resolvedType;
45464546
}
@@ -4583,7 +4583,7 @@ namespace ts {
45834583
case SyntaxKind.ThisType:
45844584
return getTypeFromThisTypeNode(node);
45854585
case SyntaxKind.StringLiteralType:
4586-
return getTypeFromStringLiteral(<StringLiteralTypeNode>node);
4586+
return getTypeFromStringLiteralTypeNode(<StringLiteralTypeNode>node);
45874587
case SyntaxKind.TypeReference:
45884588
return getTypeFromTypeReference(<TypeReferenceNode>node);
45894589
case SyntaxKind.TypePredicate:
@@ -8790,7 +8790,7 @@ namespace ts {
87908790
// for the argument. In that case, we should check the argument.
87918791
if (argType === undefined) {
87928792
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
8793-
? getStringLiteralType((<StringLiteral>arg).text)
8793+
? getStringLiteralTypeForText((<StringLiteral>arg).text)
87948794
: checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
87958795
}
87968796

@@ -8985,7 +8985,7 @@ namespace ts {
89858985
case SyntaxKind.Identifier:
89868986
case SyntaxKind.NumericLiteral:
89878987
case SyntaxKind.StringLiteral:
8988-
return getStringLiteralType((<Identifier | LiteralExpression>element.name).text);
8988+
return getStringLiteralTypeForText((<Identifier | LiteralExpression>element.name).text);
89898989

89908990
case SyntaxKind.ComputedPropertyName:
89918991
const nameType = checkComputedPropertyName(<ComputedPropertyName>element.name);
@@ -9854,17 +9854,25 @@ namespace ts {
98549854
return aggregatedTypes;
98559855
}
98569856

9857-
// TypeScript Specification 1.0 (6.3) - July 2014
9858-
// An explicitly typed function whose return type isn't the Void or the Any type
9859-
// must have at least one return statement somewhere in its body.
9860-
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
9857+
/*
9858+
*TypeScript Specification 1.0 (6.3) - July 2014
9859+
* An explicitly typed function whose return type isn't the Void or the Any type
9860+
* must have at least one return statement somewhere in its body.
9861+
* An exception to this rule is if the function implementation consists of a single 'throw' statement.
9862+
* @param returnType - return type of the function, can be undefined if return type is not explicitly specified
9863+
*/
98619864
function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration, returnType: Type): void {
98629865
if (!produceDiagnostics) {
98639866
return;
98649867
}
98659868

9866-
// Functions that return 'void' or 'any' don't need any return expressions.
9867-
if (returnType === voidType || isTypeAny(returnType)) {
9869+
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
9870+
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
9871+
return;
9872+
}
9873+
9874+
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
9875+
if (!returnType && !compilerOptions.noImplicitReturns) {
98689876
return;
98699877
}
98709878

@@ -9874,13 +9882,14 @@ namespace ts {
98749882
return;
98759883
}
98769884

9877-
if (func.flags & NodeFlags.HasExplicitReturn) {
9885+
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
98789886
if (compilerOptions.noImplicitReturns) {
9879-
error(func.type, Diagnostics.Not_all_code_paths_return_a_value);
9887+
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
98809888
}
98819889
}
98829890
else {
98839891
// This function does not conform to the specification.
9892+
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
98849893
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
98859894
}
98869895
}
@@ -9955,14 +9964,10 @@ namespace ts {
99559964
emitAwaiter = true;
99569965
}
99579966

9958-
const returnType = node.type && getTypeFromTypeNode(node.type);
9959-
let promisedType: Type;
9960-
if (returnType && isAsync) {
9961-
promisedType = checkAsyncFunctionReturnType(node);
9962-
}
9963-
9964-
if (returnType && !node.asteriskToken) {
9965-
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
9967+
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
9968+
if (!node.asteriskToken) {
9969+
// return is not necessary in the body of generators
9970+
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
99669971
}
99679972

99689973
if (node.body) {
@@ -9985,13 +9990,13 @@ namespace ts {
99859990
// check assignability of the awaited type of the expression body against the promised type of
99869991
// its return type annotation.
99879992
const exprType = checkExpression(<Expression>node.body);
9988-
if (returnType) {
9993+
if (returnOrPromisedType) {
99899994
if (isAsync) {
99909995
const awaitedType = checkAwaitedType(exprType, node.body, Diagnostics.Expression_body_for_async_arrow_function_does_not_have_a_valid_callable_then_member);
9991-
checkTypeAssignableTo(awaitedType, promisedType, node.body);
9996+
checkTypeAssignableTo(awaitedType, returnOrPromisedType, node.body);
99929997
}
99939998
else {
9994-
checkTypeAssignableTo(exprType, returnType, node.body);
9999+
checkTypeAssignableTo(exprType, returnOrPromisedType, node.body);
999510000
}
999610001
}
999710002

@@ -10607,8 +10612,7 @@ namespace ts {
1060710612
function checkStringLiteralExpression(node: StringLiteral): Type {
1060810613
const contextualType = getContextualType(node);
1060910614
if (contextualType && contextualTypeIsStringLiteralType(contextualType)) {
10610-
// TODO (drosen): Consider using getTypeFromStringLiteral instead
10611-
return getStringLiteralType(node.text);
10615+
return getStringLiteralTypeForText(node.text);
1061210616
}
1061310617

1061410618
return stringType;
@@ -12132,14 +12136,9 @@ namespace ts {
1213212136
}
1213312137

1213412138
checkSourceElement(node.body);
12135-
if (node.type && !isAccessor(node.kind) && !node.asteriskToken) {
12136-
const returnType = getTypeFromTypeNode(node.type);
12137-
let promisedType: Type;
12138-
if (isAsync) {
12139-
promisedType = checkAsyncFunctionReturnType(node);
12140-
}
12141-
12142-
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, isAsync ? promisedType : returnType);
12139+
if (!isAccessor(node.kind) && !node.asteriskToken) {
12140+
const returnOrPromisedType = node.type && (isAsync ? checkAsyncFunctionReturnType(node) : getTypeFromTypeNode(node.type));
12141+
checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnOrPromisedType);
1214312142
}
1214412143

1214512144
if (produceDiagnostics && !node.type) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [a.js]
2+
let C = "sss";
3+
let C = 0; // Error: Cannot redeclare block-scoped variable 'C'.
4+
5+
function f() {
6+
return;
7+
return; // Error: Unreachable code detected.
8+
}
9+
10+
function b() {
11+
"use strict";
12+
var arguments = 0; // Error: Invalid use of 'arguments' in strict mode.
13+
}
14+
15+
//// [a.js]
16+
var C = "sss";
17+
var C = 0; // Error: Cannot redeclare block-scoped variable 'C'.
18+
function f() {
19+
return;
20+
return; // Error: Unreachable code detected.
21+
}
22+
function b() {
23+
"use strict";
24+
var arguments = 0; // Error: Invalid use of 'arguments' in strict mode.
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
=== tests/cases/compiler/a.js ===
2+
let C = "sss";
3+
>C : Symbol(C, Decl(a.js, 0, 3))
4+
5+
let C = 0; // Error: Cannot redeclare block-scoped variable 'C'.
6+
>C : Symbol(C, Decl(a.js, 1, 3))
7+
8+
function f() {
9+
>f : Symbol(f, Decl(a.js, 1, 10))
10+
11+
return;
12+
return; // Error: Unreachable code detected.
13+
}
14+
15+
function b() {
16+
>b : Symbol(b, Decl(a.js, 6, 1))
17+
18+
"use strict";
19+
var arguments = 0; // Error: Invalid use of 'arguments' in strict mode.
20+
>arguments : Symbol(arguments, Decl(a.js, 10, 7))
21+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
=== tests/cases/compiler/a.js ===
2+
let C = "sss";
3+
>C : string
4+
>"sss" : string
5+
6+
let C = 0; // Error: Cannot redeclare block-scoped variable 'C'.
7+
>C : number
8+
>0 : number
9+
10+
function f() {
11+
>f : () => void
12+
13+
return;
14+
return; // Error: Unreachable code detected.
15+
}
16+
17+
function b() {
18+
>b : () => void
19+
20+
"use strict";
21+
>"use strict" : string
22+
23+
var arguments = 0; // Error: Invalid use of 'arguments' in strict mode.
24+
>arguments : number
25+
>0 : number
26+
}

0 commit comments

Comments
 (0)