Handle PropertyAssignment in getCommentOwnerInfo (#25911)

This commit is contained in:
Andy 2018-07-24 17:43:46 -07:00 committed by GitHub
parent fd2eb4918d
commit e4d4b0ae4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 41 deletions

View File

@ -142,6 +142,16 @@ namespace ts {
return undefined;
}
export function forEachAncestor<T>(node: Node, callback: (n: Node) => T | undefined | "quit"): T | undefined {
while (true) {
const res = callback(node);
if (res === "quit") return undefined;
if (res !== undefined) return res;
if (isSourceFile(node)) return undefined;
node = node.parent;
}
}
/**
* Calls `callback` for each entry in the map, returning the first truthy result.
* Use `map.forEach` instead for normal iteration.

View File

@ -338,50 +338,54 @@ namespace ts.JsDoc {
readonly parameters?: ReadonlyArray<ParameterDeclaration>;
}
function getCommentOwnerInfo(tokenAtPos: Node): CommentOwnerInfo | undefined {
for (let commentOwner = tokenAtPos; commentOwner; commentOwner = commentOwner.parent) {
switch (commentOwner.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.Constructor:
case SyntaxKind.MethodSignature:
const { parameters } = commentOwner as FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature;
return { commentOwner, parameters };
return forEachAncestor(tokenAtPos, getCommentOwnerInfoWorker);
}
function getCommentOwnerInfoWorker(commentOwner: Node): CommentOwnerInfo | undefined | "quit" {
switch (commentOwner.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.Constructor:
case SyntaxKind.MethodSignature:
const { parameters } = commentOwner as FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | MethodSignature;
return { commentOwner, parameters };
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.TypeAliasDeclaration:
return { commentOwner };
case SyntaxKind.PropertyAssignment:
return getCommentOwnerInfoWorker((commentOwner as PropertyAssignment).initializer);
case SyntaxKind.VariableStatement: {
const varStatement = <VariableStatement>commentOwner;
const varDeclarations = varStatement.declarationList.declarations;
const parameters = varDeclarations.length === 1 && varDeclarations[0].initializer
? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer!)
: undefined;
return { commentOwner, parameters };
}
case SyntaxKind.SourceFile:
return undefined;
case SyntaxKind.ModuleDeclaration:
// If in walking up the tree, we hit a a nested namespace declaration,
// then we must be somewhere within a dotted namespace name; however we don't
// want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'.
return commentOwner.parent.kind === SyntaxKind.ModuleDeclaration ? undefined : { commentOwner };
case SyntaxKind.BinaryExpression: {
const be = commentOwner as BinaryExpression;
if (getSpecialPropertyAssignmentKind(be) === SpecialPropertyAssignmentKind.None) {
return undefined;
}
const parameters = isFunctionLike(be.right) ? be.right.parameters : emptyArray;
return { commentOwner, parameters };
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.PropertySignature:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.EnumMember:
case SyntaxKind.TypeAliasDeclaration:
return { commentOwner };
case SyntaxKind.VariableStatement: {
const varStatement = <VariableStatement>commentOwner;
const varDeclarations = varStatement.declarationList.declarations;
const parameters = varDeclarations.length === 1 && varDeclarations[0].initializer
? getParametersFromRightHandSideOfAssignment(varDeclarations[0].initializer!)
: undefined;
return { commentOwner, parameters };
}
case SyntaxKind.SourceFile:
return "quit";
case SyntaxKind.ModuleDeclaration:
// If in walking up the tree, we hit a a nested namespace declaration,
// then we must be somewhere within a dotted namespace name; however we don't
// want to give back a JSDoc template for the 'b' or 'c' in 'namespace a.b.c { }'.
return commentOwner.parent.kind === SyntaxKind.ModuleDeclaration ? undefined : { commentOwner };
case SyntaxKind.BinaryExpression: {
const be = commentOwner as BinaryExpression;
if (getSpecialPropertyAssignmentKind(be) === SpecialPropertyAssignmentKind.None) {
return "quit";
}
const parameters = isFunctionLike(be.right) ? be.right.parameters : emptyArray;
return { commentOwner, parameters };
}
}
}

View File

@ -10,6 +10,8 @@ const multiLineOffset = 12;
//// }
//// /*1*/
//// [1 + 2 + 3 + Math.rand()](x: number, y: string, z = true) { }
//// /*2*/
//// m: function(a) {}
////}
verify.docCommentTemplateAt("0", singleLineOffset, "/** */");
@ -21,3 +23,9 @@ verify.docCommentTemplateAt("1", multiLineOffset,
* @param y
* @param z
*/`);
verify.docCommentTemplateAt("2", multiLineOffset,
`/**
*
* @param a
*/`);