Use jsdoc casts (#17251)

* Allow jsdoc casts of parenthesized expressions

* Feedback from #17211
This commit is contained in:
Wesley Wigham
2017-07-17 23:39:20 -07:00
committed by GitHub
parent de9a67f2f3
commit 8a1cd33451
6 changed files with 382 additions and 7 deletions

View File

@@ -16256,15 +16256,19 @@ namespace ts {
}
function checkAssertion(node: AssertionExpression) {
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(node.expression)));
return checkAssertionWorker(node, node.type, node.expression);
}
checkSourceElement(node.type);
const targetType = getTypeFromTypeNode(node.type);
function checkAssertionWorker(errNode: Node, type: TypeNode, expression: UnaryExpression | Expression, checkMode?: CheckMode) {
const exprType = getRegularTypeOfObjectLiteral(getBaseTypeOfLiteralType(checkExpression(expression, checkMode)));
checkSourceElement(type);
const targetType = getTypeFromTypeNode(type);
if (produceDiagnostics && targetType !== unknownType) {
const widenedType = getWidenedType(exprType);
if (!isTypeComparableTo(targetType, widenedType)) {
checkTypeComparableTo(exprType, targetType, node, Diagnostics.Type_0_cannot_be_converted_to_type_1);
checkTypeComparableTo(exprType, targetType, errNode, Diagnostics.Type_0_cannot_be_converted_to_type_1);
}
}
return targetType;
@@ -17735,6 +17739,18 @@ namespace ts {
return type;
}
function checkParenthesizedExpression(node: ParenthesizedExpression, checkMode?: CheckMode): Type {
if (isInJavaScriptFile(node) && node.jsDoc) {
const typecasts = flatMap(node.jsDoc, doc => filter(doc.tags, tag => tag.kind === SyntaxKind.JSDocTypeTag));
if (typecasts && typecasts.length) {
// We should have already issued an error if there were multiple type jsdocs
const cast = typecasts[0] as JSDocTypeTag;
return checkAssertionWorker(cast, cast.typeExpression.type, node.expression, checkMode);
}
}
return checkExpression(node.expression, checkMode);
}
function checkExpressionWorker(node: Expression, checkMode: CheckMode): Type {
switch (node.kind) {
case SyntaxKind.Identifier:
@@ -17774,7 +17790,7 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
return checkExpression((<ParenthesizedExpression>node).expression, checkMode);
return checkParenthesizedExpression(<ParenthesizedExpression>node, checkMode);
case SyntaxKind.ClassExpression:
return checkClassExpression(<ClassExpression>node);
case SyntaxKind.FunctionExpression:

View File

@@ -4342,7 +4342,7 @@ namespace ts {
parseExpected(SyntaxKind.OpenParenToken);
node.expression = allowInAnd(parseExpression);
parseExpected(SyntaxKind.CloseParenToken);
return finishNode(node);
return addJSDocComment(finishNode(node));
}
function parseSpreadElement(): Expression {

View File

@@ -640,7 +640,8 @@ namespace ts {
const commentRanges = (node.kind === SyntaxKind.Parameter ||
node.kind === SyntaxKind.TypeParameter ||
node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction) ?
node.kind === SyntaxKind.ArrowFunction ||
node.kind === SyntaxKind.ParenthesizedExpression) ?
concatenate(getTrailingCommentRanges(text, node.pos), getLeadingCommentRanges(text, node.pos)) :
getLeadingCommentRangesOfNodeFromText(node, text);
// True if the comment starts with '/**' but not if it is '/**/'