diff --git a/lib/ast-converter.js b/lib/ast-converter.js index 437f0ec..98266b2 100644 --- a/lib/ast-converter.js +++ b/lib/ast-converter.js @@ -244,6 +244,34 @@ function fixExports(node, result, ast) { return result; } +/** + * Returns true if a given TSNode is a JSX token + * @param {TSNode} node TSNode to be checked + * @returns {boolean} is a JSX token + */ +function isJSXToken(node) { + return ( + node.kind >= SyntaxKind.JsxElement + && node.kind <= SyntaxKind.JsxAttribute + ); +} + +/** + * Returns true if a given TSNode has a JSX token within its hierarchy + * @param {TSNode} node TSNode to be checked + * @returns {boolean} has JSX ancestor + */ +function hasJSXAncestor(node) { + while (node) { + if (isJSXToken(node)) { + return true; + } + node = node.parent; + } + return false; +} + + /** * Extends and formats a given error object * @param {Object} error the error object @@ -331,12 +359,12 @@ function getTokenType(token) { // Some JSX tokens have to be determined based on their parent if (token.parent) { - if (token.kind === SyntaxKind.Identifier && token.parent.kind === SyntaxKind.FirstNode) { + if (token.kind === SyntaxKind.Identifier && token.parent.kind === SyntaxKind.PropertyAccessExpression && hasJSXAncestor(token)) { return "JSXIdentifier"; } - if (token.parent.kind >= SyntaxKind.JsxElement && token.parent.kind <= SyntaxKind.JsxAttribute) { - if (token.kind === SyntaxKind.FirstNode) { + if (isJSXToken(token.parent)) { + if (token.kind === SyntaxKind.PropertyAccessExpression) { return "JSXMemberExpression"; } @@ -616,12 +644,12 @@ module.exports = function(ast, extra) { if (tagNameToken.type === "JSXMemberExpression") { - var isNestedMemberExpression = (node.tagName.left.kind === SyntaxKind.FirstNode); + var isNestedMemberExpression = (node.tagName.expression.kind === SyntaxKind.PropertyAccessExpression); // Convert TSNode left and right objects into ESTreeNode object // and property objects - tagNameToken.object = convertChild(node.tagName.left); - tagNameToken.property = convertChild(node.tagName.right); + tagNameToken.object = convertChild(node.tagName.expression); + tagNameToken.property = convertChild(node.tagName.name); // Assign the appropriate types tagNameToken.object.type = (isNestedMemberExpression) ? "JSXMemberExpression" : "JSXIdentifier"; @@ -1626,12 +1654,24 @@ module.exports = function(ast, extra) { break; case SyntaxKind.PropertyAccessExpression: - assign(result, { - type: "MemberExpression", - object: convertChild(node.expression), - property: convertChild(node.name), - computed: false - }); + if (isJSXToken(parent)) { + var jsxMemberExpression = { + type: "MemberExpression", + object: convertChild(node.expression), + property: convertChild(node.name) + }; + var isNestedMemberExpression = (node.expression.kind === SyntaxKind.PropertyAccessExpression); + jsxMemberExpression.object.type = (isNestedMemberExpression) ? "MemberExpression" : "JSXIdentifier"; + jsxMemberExpression.property.type = "JSXIdentifier"; + assign(result, jsxMemberExpression); + } else { + assign(result, { + type: "MemberExpression", + object: convertChild(node.expression), + property: convertChild(node.name), + computed: false + }); + } break; case SyntaxKind.ElementAccessExpression: