Skip to content

Commit f315fc1

Browse files
committed
Merge branch 'master' into noSourcemapNames
2 parents 322f084 + b40079e commit f315fc1

18 files changed

Lines changed: 802 additions & 328 deletions

src/compiler/checker.ts

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9871,31 +9871,39 @@ namespace ts {
98719871
}
98729872

98739873
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
9874-
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
9875-
return;
9876-
}
9877-
9878-
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
9879-
if (!returnType && !compilerOptions.noImplicitReturns) {
9874+
if (returnType === voidType || isTypeAny(returnType)) {
98809875
return;
98819876
}
98829877

98839878
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
9884-
// also if HasImplicitReturnValue flags is not set this means that all codepaths in function body end with return of throw
9879+
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
98859880
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
98869881
return;
98879882
}
98889883

9889-
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
9890-
if (compilerOptions.noImplicitReturns) {
9891-
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
9892-
}
9893-
}
9894-
else {
9895-
// This function does not conform to the specification.
9884+
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
9885+
9886+
if (returnType && !hasExplicitReturn) {
9887+
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
9888+
// this function does not conform to the specification.
98969889
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
98979890
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
98989891
}
9892+
else if (compilerOptions.noImplicitReturns) {
9893+
if (!returnType) {
9894+
// If return type annotation is omitted check if function has any explicit return statements.
9895+
// If it does not have any - its inferred return type is void - don't do any checks.
9896+
// Otherwise get inferred return type from function body and report error only if it is not void / anytype
9897+
const inferredReturnType = hasExplicitReturn
9898+
? getReturnTypeOfSignature(getSignatureFromDeclaration(func))
9899+
: voidType;
9900+
9901+
if (inferredReturnType === voidType || isTypeAny(inferredReturnType)) {
9902+
return;
9903+
}
9904+
}
9905+
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
9906+
}
98999907
}
99009908

99019909
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
@@ -12119,8 +12127,8 @@ namespace ts {
1211912127
const symbol = getSymbolOfNode(node);
1212012128
const localSymbol = node.localSymbol || symbol;
1212112129

12122-
// Since the javascript won't do semantic analysis like typescript,
12123-
// if the javascript file comes before the typescript file and both contain same name functions,
12130+
// Since the javascript won't do semantic analysis like typescript,
12131+
// if the javascript file comes before the typescript file and both contain same name functions,
1212412132
// checkFunctionOrConstructorSymbol wouldn't be called if we didnt ignore javascript function.
1212512133
const firstDeclaration = forEach(localSymbol.declarations,
1212612134
// Get first non javascript function declaration
@@ -14370,6 +14378,7 @@ namespace ts {
1437014378
emitExtends = false;
1437114379
emitDecorate = false;
1437214380
emitParam = false;
14381+
emitAwaiter = false;
1437314382
potentialThisCollisions.length = 0;
1437414383

1437514384
forEach(node.statements, checkSourceElement);

src/compiler/emitter.ts

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5292,10 +5292,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
52925292
function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) {
52935293
const decorators = node.decorators;
52945294
const constructor = getFirstConstructorWithBody(node);
5295-
const hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
5295+
const firstParameterDecorator = constructor && forEach(constructor.parameters, parameter => parameter.decorators);
52965296

52975297
// skip decoration of the constructor if neither it nor its parameters are decorated
5298-
if (!decorators && !hasDecoratedParameters) {
5298+
if (!decorators && !firstParameterDecorator) {
52995299
return;
53005300
}
53015301

@@ -5311,28 +5311,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
53115311
//
53125312

53135313
writeLine();
5314-
emitStart(node);
5314+
emitStart(node.decorators || firstParameterDecorator);
53155315
emitDeclarationName(node);
53165316
write(" = __decorate([");
53175317
increaseIndent();
53185318
writeLine();
53195319

53205320
const decoratorCount = decorators ? decorators.length : 0;
5321-
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
5322-
emitStart(decorator);
5323-
emit(decorator.expression);
5324-
emitEnd(decorator);
5325-
});
5326-
5327-
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
5321+
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
5322+
decorator => emit(decorator.expression));
5323+
if (firstParameterDecorator) {
5324+
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
5325+
}
53285326
emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);
53295327

53305328
decreaseIndent();
53315329
writeLine();
53325330
write("], ");
53335331
emitDeclarationName(node);
5334-
write(");");
5335-
emitEnd(node);
5332+
write(")");
5333+
emitEnd(node.decorators || firstParameterDecorator);
5334+
write(";");
53365335
writeLine();
53375336
}
53385337

@@ -5348,11 +5347,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
53485347
continue;
53495348
}
53505349

5351-
// skip a member if it or any of its parameters are not decorated
5352-
if (!nodeOrChildIsDecorated(member)) {
5353-
continue;
5354-
}
5355-
53565350
// skip an accessor declaration if it is not the first accessor
53575351
let decorators: NodeArray<Decorator>;
53585352
let functionLikeMember: FunctionLikeDeclaration;
@@ -5379,6 +5373,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
53795373
functionLikeMember = <MethodDeclaration>member;
53805374
}
53815375
}
5376+
const firstParameterDecorator = functionLikeMember && forEach(functionLikeMember.parameters, parameter => parameter.decorators);
5377+
5378+
// skip a member if it or any of its parameters are not decorated
5379+
if (!decorators && !firstParameterDecorator) {
5380+
continue;
5381+
}
53825382

53835383
// Emit the call to __decorate. Given the following:
53845384
//
@@ -5412,29 +5412,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
54125412
//
54135413

54145414
writeLine();
5415-
emitStart(member);
5415+
emitStart(decorators || firstParameterDecorator);
54165416
write("__decorate([");
54175417
increaseIndent();
54185418
writeLine();
54195419

54205420
const decoratorCount = decorators ? decorators.length : 0;
5421-
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
5422-
emitStart(decorator);
5423-
emit(decorator.expression);
5424-
emitEnd(decorator);
5425-
});
5421+
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
5422+
decorator => emit(decorator.expression));
54265423

5427-
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
5424+
if (firstParameterDecorator) {
5425+
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
5426+
}
54285427
emitSerializedTypeMetadata(member, argumentsWritten > 0);
54295428

54305429
decreaseIndent();
54315430
writeLine();
54325431
write("], ");
5433-
emitStart(member.name);
54345432
emitClassMemberPrefix(node, member);
54355433
write(", ");
54365434
emitExpressionForPropertyName(member.name);
5437-
emitEnd(member.name);
54385435

54395436
if (languageVersion > ScriptTarget.ES3) {
54405437
if (member.kind !== SyntaxKind.PropertyDeclaration) {
@@ -5449,8 +5446,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
54495446
}
54505447
}
54515448

5452-
write(");");
5453-
emitEnd(member);
5449+
write(")");
5450+
emitEnd(decorators || firstParameterDecorator);
5451+
write(";");
54545452
writeLine();
54555453
}
54565454
}
@@ -5463,11 +5461,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
54635461
if (nodeIsDecorated(parameter)) {
54645462
const decorators = parameter.decorators;
54655463
argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
5466-
emitStart(decorator);
54675464
write(`__param(${parameterIndex}, `);
54685465
emit(decorator.expression);
54695466
write(")");
5470-
emitEnd(decorator);
54715467
});
54725468
leadingComma = true;
54735469
}

src/compiler/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4902,7 +4902,7 @@ namespace ts {
49024902

49034903
if (!decorators) {
49044904
decorators = <NodeArray<Decorator>>[];
4905-
decorators.pos = scanner.getStartPos();
4905+
decorators.pos = decoratorStart;
49064906
}
49074907

49084908
const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);

src/compiler/sourcemap.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ namespace ts {
230230
}
231231

232232
function emitStart(range: TextRange) {
233-
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, range.pos) : -1);
233+
const rangeHasDecorators = !!(range as Node).decorators;
234+
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
234235
}
235236

236237
function emitEnd(range: TextRange) {

src/compiler/utilities.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -906,23 +906,6 @@ namespace ts {
906906
return false;
907907
}
908908

909-
export function childIsDecorated(node: Node): boolean {
910-
switch (node.kind) {
911-
case SyntaxKind.ClassDeclaration:
912-
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
913-
914-
case SyntaxKind.MethodDeclaration:
915-
case SyntaxKind.SetAccessor:
916-
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
917-
}
918-
919-
return false;
920-
}
921-
922-
export function nodeOrChildIsDecorated(node: Node): boolean {
923-
return nodeIsDecorated(node) || childIsDecorated(node);
924-
}
925-
926909
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
927910
return node.kind === SyntaxKind.PropertyAccessExpression;
928911
}

src/services/breakpoints.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {
1616

1717
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
1818
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
19-
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
19+
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
2020
// Get previous token if the token is returned starts on new line
2121
// eg: let x =10; |--- cursor is here
2222
// let y = 10;
@@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
3939
return spanInNode(tokenAtLocation);
4040

4141
function textSpan(startNode: Node, endNode?: Node) {
42-
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
42+
const start = startNode.decorators ?
43+
skipTrivia(sourceFile.text, startNode.decorators.end) :
44+
startNode.getStart(sourceFile);
45+
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
4346
}
4447

4548
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
46-
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
49+
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
4750
return spanInNode(node);
4851
}
4952
return spanInNode(otherwiseOnNode);
5053
}
5154

55+
function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
56+
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
57+
}
58+
5259
function spanInPreviousNode(node: Node): TextSpan {
5360
return spanInNode(findPrecedingToken(node.pos, sourceFile));
5461
}
@@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
6572
return spanInPreviousNode(node);
6673
}
6774

75+
if (node.parent.kind === SyntaxKind.Decorator) {
76+
// Set breakpoint on the decorator emit
77+
return spanInNode(node.parent);
78+
}
79+
6880
if (node.parent.kind === SyntaxKind.ForStatement) {
6981
// For now lets set the span on this expression, fix it later
7082
return textSpan(node);
@@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
207219
// span in statement
208220
return spanInNode((<WithStatement>node).statement);
209221

222+
case SyntaxKind.Decorator:
223+
return spanInNodeArray(node.parent.decorators);
224+
210225
// No breakpoint in interface, type alias
211226
case SyntaxKind.InterfaceDeclaration:
212227
case SyntaxKind.TypeAliasDeclaration:
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/conformance/async/es6/asyncMultiFile.ts] ////
2+
3+
//// [a.ts]
4+
async function f() {}
5+
//// [b.ts]
6+
function g() { }
7+
8+
//// [a.js]
9+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
10+
return new Promise(function (resolve, reject) {
11+
generator = generator.call(thisArg, _arguments);
12+
function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
13+
function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
14+
function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
15+
function step(verb, value) {
16+
var result = generator[verb](value);
17+
result.done ? resolve(result.value) : cast(result.value).then(onfulfill, onreject);
18+
}
19+
step("next", void 0);
20+
});
21+
};
22+
function f() {
23+
return __awaiter(this, void 0, Promise, function* () { });
24+
}
25+
//// [b.js]
26+
function g() { }
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/conformance/async/es6/a.ts ===
2+
async function f() {}
3+
>f : Symbol(f, Decl(a.ts, 0, 0))
4+
5+
=== tests/cases/conformance/async/es6/b.ts ===
6+
function g() { }
7+
>g : Symbol(g, Decl(b.ts, 0, 0))
8+
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
=== tests/cases/conformance/async/es6/a.ts ===
2+
async function f() {}
3+
>f : () => Promise<void>
4+
5+
=== tests/cases/conformance/async/es6/b.ts ===
6+
function g() { }
7+
>g : () => void
8+

0 commit comments

Comments
 (0)