Skip to content
65 changes: 19 additions & 46 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3148,38 +3148,10 @@ namespace ts {
}

function getTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration) {
const jsDocType = getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration);
if (jsDocType) {
return getTypeFromTypeNode(jsDocType);
const jsdocType = getJSDocType(declaration);
if (jsdocType) {
return getTypeFromTypeNode(jsdocType);
}
}

function getJSDocTypeForVariableLikeDeclarationFromJSDocComment(declaration: VariableLikeDeclaration): JSDocType {
// First, see if this node has an @type annotation on it directly.
const typeTag = getJSDocTypeTag(declaration);
if (typeTag && typeTag.typeExpression) {
return typeTag.typeExpression.type;
}

if (declaration.kind === SyntaxKind.VariableDeclaration &&
declaration.parent.kind === SyntaxKind.VariableDeclarationList &&
declaration.parent.parent.kind === SyntaxKind.VariableStatement) {

// @type annotation might have been on the variable statement, try that instead.
const annotation = getJSDocTypeTag(declaration.parent.parent);
if (annotation && annotation.typeExpression) {
return annotation.typeExpression.type;
}
}
else if (declaration.kind === SyntaxKind.Parameter) {
// If it's a parameter, see if the parent has a jsdoc comment with an @param
// annotation.
const paramTag = getCorrespondingJSDocParameterTag(<ParameterDeclaration>declaration);
if (paramTag && paramTag.typeExpression) {
return paramTag.typeExpression.type;
}
}

return undefined;
}

Expand Down Expand Up @@ -3445,9 +3417,9 @@ namespace ts {
declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) {
// Use JS Doc type if present on parent expression statement
if (declaration.flags & NodeFlags.JavaScriptFile) {
const typeTag = getJSDocTypeTag(declaration.parent);
if (typeTag && typeTag.typeExpression) {
return links.type = getTypeFromTypeNode(typeTag.typeExpression.type);
const jsdocType = getJSDocType(declaration.parent);
if (jsdocType) {
return links.type = getTypeFromTypeNode(jsdocType);
}
}
const declaredTypes = map(symbol.declarations,
Expand Down Expand Up @@ -4882,15 +4854,16 @@ namespace ts {
if (node.type && node.type.kind === SyntaxKind.JSDocOptionalType) {
return true;
}
const paramTags = getJSDocParameterTag(node);
if (paramTags) {
for (const paramTag of paramTags) {
if (paramTag.isBracketed) {
return true;
}

const paramTag = getCorrespondingJSDocParameterTag(node);
if (paramTag) {
if (paramTag.isBracketed) {
return true;
}

if (paramTag.typeExpression) {
return paramTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
if (paramTag.typeExpression) {
return paramTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
}
}
}
}
Expand Down Expand Up @@ -10315,9 +10288,9 @@ namespace ts {
}

function getTypeForThisExpressionFromJSDoc(node: Node) {
const typeTag = getJSDocTypeTag(node);
if (typeTag && typeTag.typeExpression && typeTag.typeExpression.type && typeTag.typeExpression.type.kind === SyntaxKind.JSDocFunctionType) {
const jsDocFunctionType = <JSDocFunctionType>typeTag.typeExpression.type;
const jsdocType = getJSDocType(node);
if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) {
const jsDocFunctionType = <JSDocFunctionType>jsdocType;
if (jsDocFunctionType.parameters.length > 0 && jsDocFunctionType.parameters[0].type.kind === SyntaxKind.JSDocThisType) {
return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type);
}
Expand Down Expand Up @@ -13551,7 +13524,7 @@ namespace ts {
// the destructured type into the contained binding elements.
function assignBindingElementTypes(node: VariableLikeDeclaration) {
if (isBindingPattern(node.name)) {
for (const element of (<BindingPattern>node.name).elements) {
for (const element of node.name.elements) {
if (!isOmittedExpression(element)) {
if (element.name.kind === SyntaxKind.Identifier) {
getSymbolLinks(getSymbolOfNode(element)).type = getTypeForBindingElement(element);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ namespace ts {

function writeJsDocComments(declaration: Node) {
if (declaration) {
const jsDocComments = getJsDocCommentsFromText(declaration, currentText);
const jsDocComments = getJSDocCommentRanges(declaration, currentText);
emitNewLineBeforeLeadingComments(currentLineMap, writer, declaration, jsDocComments);
// jsDoc comments are emitted at /*leading comment1 */space/*leading comment*/space
emitComments(currentText, currentLineMap, writer, jsDocComments, /*leadingSeparator*/ false, /*trailingSeparator*/ true, newLine, writeCommentRange);
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,7 @@ namespace ts {


function addJSDocComment<T extends Node>(node: T): T {
const comments = getJsDocCommentsFromText(node, sourceFile.text);
const comments = getJSDocCommentRanges(node, sourceFile.text);
if (comments) {
for (const comment of comments) {
const jsDoc = JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos);
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ namespace ts {
/* @internal */ original?: Node; // The original node if this is an updated node.
/* @internal */ startsOnNewLine?: boolean; // Whether a synthesized node should start on a new line (used by transforms).
/* @internal */ jsDocComments?: JSDoc[]; // JSDoc for the node, if it has any.
/* @internal */ jsDocCache?: (JSDoc | JSDocParameterTag)[]; // JSDoc for the node, plus JSDoc retrieved from its parents
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment explaining that JSDocParameterTag is treated differently because we want to avoid redoing the mapping from each tag to each parameter declaration.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I improved the comment to explain that jsDoc[Comments] is the JSDoc syntactically on the node whereas jsDocCache is all applicable docs and @param tags.

/* @internal */ symbol?: Symbol; // Symbol declared by node (initialized by binding)
/* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding)
/* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding)
Expand Down
Loading