Skip to content

Commit

Permalink
Merge pull request #19355 from Microsoft/sandersn/fix-getParameterSym…
Browse files Browse the repository at this point in the history
…bolFromJSDoc

fix getParameterSymbolFromJSDoc
  • Loading branch information
sandersn authored Oct 20, 2017
2 parents 8a22767 + 8cc2af5 commit 1ea1254
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 32 deletions.
75 changes: 43 additions & 32 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1538,6 +1538,34 @@ namespace ts {
return getJSDocCommentsAndTags(node);
}

export function getSourceOfAssignment(node: Node): Node {
return isExpressionStatement(node) &&
node.expression && isBinaryExpression(node.expression) &&
node.expression.operatorToken.kind === SyntaxKind.EqualsToken &&
node.expression.right;
}

export function getSingleInitializerOfVariableStatement(node: Node, child?: Node): Node {
return isVariableStatement(node) &&
node.declarationList.declarations.length > 0 &&
(!child || node.declarationList.declarations[0].initializer === child) &&
node.declarationList.declarations[0].initializer;
}

export function getSingleVariableOfVariableStatement(node: Node, child?: Node): Node {
return isVariableStatement(node) &&
node.declarationList.declarations.length > 0 &&
(!child || node.declarationList.declarations[0] === child) &&
node.declarationList.declarations[0];
}

export function getNestedModuleDeclaration(node: Node): Node {
return node.kind === SyntaxKind.ModuleDeclaration &&
(node as ModuleDeclaration).body &&
(node as ModuleDeclaration).body.kind === SyntaxKind.ModuleDeclaration &&
(node as ModuleDeclaration).body;
}

export function getJSDocCommentsAndTags(node: Node): (JSDoc | JSDocTag)[] {
let result: (JSDoc | JSDocTag)[] | undefined;
getJSDocCommentsAndTagsWorker(node);
Expand All @@ -1551,35 +1579,15 @@ namespace ts {
// * @returns {number}
// */
// var x = function(name) { return name.length; }
const isInitializerOfVariableDeclarationInStatement =
isVariableLike(parent) &&
parent.initializer === node &&
parent.parent.parent.kind === SyntaxKind.VariableStatement;
const isVariableOfVariableDeclarationStatement = isVariableLike(node) &&
parent.parent.kind === SyntaxKind.VariableStatement;
const variableStatementNode =
isInitializerOfVariableDeclarationInStatement ? parent.parent.parent :
isVariableOfVariableDeclarationStatement ? parent.parent :
undefined;
if (variableStatementNode) {
getJSDocCommentsAndTagsWorker(variableStatementNode);
if (parent && (parent.kind === SyntaxKind.PropertyAssignment || getNestedModuleDeclaration(parent))) {
getJSDocCommentsAndTagsWorker(parent);
}

// Also recognize when the node is the RHS of an assignment expression
const isSourceOfAssignmentExpressionStatement =
parent && parent.parent &&
parent.kind === SyntaxKind.BinaryExpression &&
(parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken &&
parent.parent.kind === SyntaxKind.ExpressionStatement;
if (isSourceOfAssignmentExpressionStatement) {
if (parent && parent.parent &&
(getSingleVariableOfVariableStatement(parent.parent, node) || getSourceOfAssignment(parent.parent))) {
getJSDocCommentsAndTagsWorker(parent.parent);
}

const isModuleDeclaration = node.kind === SyntaxKind.ModuleDeclaration &&
parent && parent.kind === SyntaxKind.ModuleDeclaration;
const isPropertyAssignmentExpression = parent && parent.kind === SyntaxKind.PropertyAssignment;
if (isModuleDeclaration || isPropertyAssignmentExpression) {
getJSDocCommentsAndTagsWorker(parent);
if (parent && parent.parent && parent.parent.parent && getSingleInitializerOfVariableStatement(parent.parent.parent, node)) {
getJSDocCommentsAndTagsWorker(parent.parent.parent);
}

// Pull parameter comments from declaring function as well
Expand All @@ -1606,13 +1614,16 @@ namespace ts {
return undefined;
}
const name = node.name.escapedText;
const func = getJSDocHost(node);
if (!isFunctionLike(func)) {
return undefined;
const host = getJSDocHost(node);
const decl = getSourceOfAssignment(host) ||
getSingleInitializerOfVariableStatement(host) ||
getSingleVariableOfVariableStatement(host) ||
getNestedModuleDeclaration(host) ||
host;
if (decl && isFunctionLike(decl)) {
const parameter = find(decl.parameters, p => p.name.kind === SyntaxKind.Identifier && p.name.escapedText === name);
return parameter && parameter.symbol;
}
const parameter = find(func.parameters, p =>
p.name.kind === SyntaxKind.Identifier && p.name.escapedText === name);
return parameter && parameter.symbol;
}

export function getJSDocHost(node: JSDocTag): HasJSDoc {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//// [0.js]
// @ts-check
/**
* @param {number=} n
* @param {string} [s]
*/
var x = function foo(n, s) {}
var y;
/**
* @param {boolean!} b
*/
y = function bar(b) {}

/**
* @param {string} s
*/
var one = function (s) { }, two = function (untyped) { };


//// [0.js]
// @ts-check
/**
* @param {number=} n
* @param {string} [s]
*/
var x = function foo(n, s) { };
var y;
/**
* @param {boolean!} b
*/
y = function bar(b) { };
/**
* @param {string} s
*/
var one = function (s) { }, two = function (untyped) { };
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
=== tests/cases/conformance/jsdoc/0.js ===
// @ts-check
/**
* @param {number=} n
* @param {string} [s]
*/
var x = function foo(n, s) {}
>x : Symbol(x, Decl(0.js, 5, 3))
>foo : Symbol(foo, Decl(0.js, 5, 7))
>n : Symbol(n, Decl(0.js, 5, 21))
>s : Symbol(s, Decl(0.js, 5, 23))

var y;
>y : Symbol(y, Decl(0.js, 6, 3))

/**
* @param {boolean!} b
*/
y = function bar(b) {}
>y : Symbol(y, Decl(0.js, 6, 3))
>bar : Symbol(bar, Decl(0.js, 10, 3))
>b : Symbol(b, Decl(0.js, 10, 17))

/**
* @param {string} s
*/
var one = function (s) { }, two = function (untyped) { };
>one : Symbol(one, Decl(0.js, 15, 3))
>s : Symbol(s, Decl(0.js, 15, 20))
>two : Symbol(two, Decl(0.js, 15, 27))
>untyped : Symbol(untyped, Decl(0.js, 15, 44))

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
=== tests/cases/conformance/jsdoc/0.js ===
// @ts-check
/**
* @param {number=} n
* @param {string} [s]
*/
var x = function foo(n, s) {}
>x : (n?: number, s?: string) => void
>function foo(n, s) {} : (n?: number, s?: string) => void
>foo : (n?: number, s?: string) => void
>n : number
>s : string

var y;
>y : any

/**
* @param {boolean!} b
*/
y = function bar(b) {}
>y = function bar(b) {} : (b: boolean) => void
>y : any
>function bar(b) {} : (b: boolean) => void
>bar : (b: boolean) => void
>b : boolean

/**
* @param {string} s
*/
var one = function (s) { }, two = function (untyped) { };
>one : (s: string) => void
>function (s) { } : (s: string) => void
>s : string
>two : (untyped: any) => void
>function (untyped) { } : (untyped: any) => void
>untyped : any

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// @allowJS: true
// @suppressOutputPathCheck: true

// @filename: 0.js
// @ts-check
/**
* @param {number=} n
* @param {string} [s]
*/
var x = function foo(n, s) {}
var y;
/**
* @param {boolean!} b
*/
y = function bar(b) {}

/**
* @param {string} s
*/
var one = function (s) { }, two = function (untyped) { };

0 comments on commit 1ea1254

Please sign in to comment.