mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into fixAsyncReferecedImport
This commit is contained in:
+24
-15
@@ -9871,31 +9871,39 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
|
||||
if (returnType && (returnType === voidType || isTypeAny(returnType))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if return type is not specified then we'll do the check only if 'noImplicitReturns' option is set
|
||||
if (!returnType && !compilerOptions.noImplicitReturns) {
|
||||
if (returnType === voidType || isTypeAny(returnType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If all we have is a function signature, or an arrow function with an expression body, then there is nothing to check.
|
||||
// also if HasImplicitReturnValue flags is not set this means that all codepaths in function body end with return of throw
|
||||
// also if HasImplicitReturn flag is not set this means that all codepaths in function body end with return or throw
|
||||
if (nodeIsMissing(func.body) || func.body.kind !== SyntaxKind.Block || !(func.flags & NodeFlags.HasImplicitReturn)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!returnType || func.flags & NodeFlags.HasExplicitReturn) {
|
||||
if (compilerOptions.noImplicitReturns) {
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// This function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
const hasExplicitReturn = func.flags & NodeFlags.HasExplicitReturn;
|
||||
|
||||
if (returnType && !hasExplicitReturn) {
|
||||
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
|
||||
// this function does not conform to the specification.
|
||||
// NOTE: having returnType !== undefined is a precondition for entering this branch so func.type will always be present
|
||||
error(func.type, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
|
||||
}
|
||||
else if (compilerOptions.noImplicitReturns) {
|
||||
if (!returnType) {
|
||||
// If return type annotation is omitted check if function has any explicit return statements.
|
||||
// If it does not have any - its inferred return type is void - don't do any checks.
|
||||
// Otherwise get inferred return type from function body and report error only if it is not void / anytype
|
||||
const inferredReturnType = hasExplicitReturn
|
||||
? getReturnTypeOfSignature(getSignatureFromDeclaration(func))
|
||||
: voidType;
|
||||
|
||||
if (inferredReturnType === voidType || isTypeAny(inferredReturnType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
error(func.type || func, Diagnostics.Not_all_code_paths_return_a_value);
|
||||
}
|
||||
}
|
||||
|
||||
function checkFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | MethodDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
@@ -14376,6 +14384,7 @@ namespace ts {
|
||||
emitExtends = false;
|
||||
emitDecorate = false;
|
||||
emitParam = false;
|
||||
emitAwaiter = false;
|
||||
potentialThisCollisions.length = 0;
|
||||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
|
||||
+26
-30
@@ -5307,10 +5307,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) {
|
||||
const decorators = node.decorators;
|
||||
const constructor = getFirstConstructorWithBody(node);
|
||||
const hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
|
||||
const firstParameterDecorator = constructor && forEach(constructor.parameters, parameter => parameter.decorators);
|
||||
|
||||
// skip decoration of the constructor if neither it nor its parameters are decorated
|
||||
if (!decorators && !hasDecoratedParameters) {
|
||||
if (!decorators && !firstParameterDecorator) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5326,28 +5326,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
//
|
||||
|
||||
writeLine();
|
||||
emitStart(node);
|
||||
emitStart(node.decorators || firstParameterDecorator);
|
||||
emitDeclarationName(node);
|
||||
write(" = __decorate([");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
const decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
|
||||
decorator => emit(decorator.expression));
|
||||
if (firstParameterDecorator) {
|
||||
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
|
||||
}
|
||||
emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("], ");
|
||||
emitDeclarationName(node);
|
||||
write(");");
|
||||
emitEnd(node);
|
||||
write(")");
|
||||
emitEnd(node.decorators || firstParameterDecorator);
|
||||
write(";");
|
||||
writeLine();
|
||||
}
|
||||
|
||||
@@ -5363,11 +5362,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip a member if it or any of its parameters are not decorated
|
||||
if (!nodeOrChildIsDecorated(member)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip an accessor declaration if it is not the first accessor
|
||||
let decorators: NodeArray<Decorator>;
|
||||
let functionLikeMember: FunctionLikeDeclaration;
|
||||
@@ -5394,6 +5388,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
functionLikeMember = <MethodDeclaration>member;
|
||||
}
|
||||
}
|
||||
const firstParameterDecorator = functionLikeMember && forEach(functionLikeMember.parameters, parameter => parameter.decorators);
|
||||
|
||||
// skip a member if it or any of its parameters are not decorated
|
||||
if (!decorators && !firstParameterDecorator) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Emit the call to __decorate. Given the following:
|
||||
//
|
||||
@@ -5427,29 +5427,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
//
|
||||
|
||||
writeLine();
|
||||
emitStart(member);
|
||||
emitStart(decorators || firstParameterDecorator);
|
||||
write("__decorate([");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
const decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true,
|
||||
decorator => emit(decorator.expression));
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
|
||||
if (firstParameterDecorator) {
|
||||
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
|
||||
}
|
||||
emitSerializedTypeMetadata(member, argumentsWritten > 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("], ");
|
||||
emitStart(member.name);
|
||||
emitClassMemberPrefix(node, member);
|
||||
write(", ");
|
||||
emitExpressionForPropertyName(member.name);
|
||||
emitEnd(member.name);
|
||||
|
||||
if (languageVersion > ScriptTarget.ES3) {
|
||||
if (member.kind !== SyntaxKind.PropertyDeclaration) {
|
||||
@@ -5464,8 +5461,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
}
|
||||
}
|
||||
|
||||
write(");");
|
||||
emitEnd(member);
|
||||
write(")");
|
||||
emitEnd(decorators || firstParameterDecorator);
|
||||
write(";");
|
||||
writeLine();
|
||||
}
|
||||
}
|
||||
@@ -5478,11 +5476,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
if (nodeIsDecorated(parameter)) {
|
||||
const decorators = parameter.decorators;
|
||||
argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
write(`__param(${parameterIndex}, `);
|
||||
emit(decorator.expression);
|
||||
write(")");
|
||||
emitEnd(decorator);
|
||||
});
|
||||
leadingComma = true;
|
||||
}
|
||||
|
||||
@@ -4902,7 +4902,7 @@ namespace ts {
|
||||
|
||||
if (!decorators) {
|
||||
decorators = <NodeArray<Decorator>>[];
|
||||
decorators.pos = scanner.getStartPos();
|
||||
decorators.pos = decoratorStart;
|
||||
}
|
||||
|
||||
const decorator = <Decorator>createNode(SyntaxKind.Decorator, decoratorStart);
|
||||
|
||||
@@ -251,7 +251,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitStart(range: TextRange) {
|
||||
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, range.pos) : -1);
|
||||
const rangeHasDecorators = !!(range as Node).decorators;
|
||||
emitPos(range.pos !== -1 ? skipTrivia(currentSourceFile.text, rangeHasDecorators ? (range as Node).decorators.end : range.pos) : -1);
|
||||
}
|
||||
|
||||
function emitEnd(range: TextRange) {
|
||||
|
||||
@@ -906,23 +906,6 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function childIsDecorated(node: Node): boolean {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return forEach((<ClassDeclaration>node).members, nodeOrChildIsDecorated);
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return forEach((<FunctionLikeDeclaration>node).parameters, nodeIsDecorated);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function nodeOrChildIsDecorated(node: Node): boolean {
|
||||
return nodeIsDecorated(node) || childIsDecorated(node);
|
||||
}
|
||||
|
||||
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
|
||||
return node.kind === SyntaxKind.PropertyAccessExpression;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace ts.BreakpointResolver {
|
||||
|
||||
let tokenAtLocation = getTokenAtPosition(sourceFile, position);
|
||||
let lineOfPosition = sourceFile.getLineAndCharacterOfPosition(position).line;
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart()).line > lineOfPosition) {
|
||||
if (sourceFile.getLineAndCharacterOfPosition(tokenAtLocation.getStart(sourceFile)).line > lineOfPosition) {
|
||||
// Get previous token if the token is returned starts on new line
|
||||
// eg: let x =10; |--- cursor is here
|
||||
// let y = 10;
|
||||
@@ -39,16 +39,23 @@ namespace ts.BreakpointResolver {
|
||||
return spanInNode(tokenAtLocation);
|
||||
|
||||
function textSpan(startNode: Node, endNode?: Node) {
|
||||
return createTextSpanFromBounds(startNode.getStart(), (endNode || startNode).getEnd());
|
||||
const start = startNode.decorators ?
|
||||
skipTrivia(sourceFile.text, startNode.decorators.end) :
|
||||
startNode.getStart(sourceFile);
|
||||
return createTextSpanFromBounds(start, (endNode || startNode).getEnd());
|
||||
}
|
||||
|
||||
function spanInNodeIfStartsOnSameLine(node: Node, otherwiseOnNode?: Node): TextSpan {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart()).line) {
|
||||
if (node && lineOfPosition === sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line) {
|
||||
return spanInNode(node);
|
||||
}
|
||||
return spanInNode(otherwiseOnNode);
|
||||
}
|
||||
|
||||
function spanInNodeArray<T>(nodeArray: NodeArray<T>) {
|
||||
return createTextSpanFromBounds(skipTrivia(sourceFile.text, nodeArray.pos), nodeArray.end);
|
||||
}
|
||||
|
||||
function spanInPreviousNode(node: Node): TextSpan {
|
||||
return spanInNode(findPrecedingToken(node.pos, sourceFile));
|
||||
}
|
||||
@@ -65,6 +72,11 @@ namespace ts.BreakpointResolver {
|
||||
return spanInPreviousNode(node);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.Decorator) {
|
||||
// Set breakpoint on the decorator emit
|
||||
return spanInNode(node.parent);
|
||||
}
|
||||
|
||||
if (node.parent.kind === SyntaxKind.ForStatement) {
|
||||
// For now lets set the span on this expression, fix it later
|
||||
return textSpan(node);
|
||||
@@ -207,6 +219,9 @@ namespace ts.BreakpointResolver {
|
||||
// span in statement
|
||||
return spanInNode((<WithStatement>node).statement);
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
return spanInNodeArray(node.parent.decorators);
|
||||
|
||||
// No breakpoint in interface, type alias
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
|
||||
Reference in New Issue
Block a user