Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
221 changes: 175 additions & 46 deletions android-static-binding-generator/project/parser/visitors/es5-visitors.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var es5_visitors = (function () {

var t = require("babel-types"),
var types = require("babel-types"),

defaultExtendDecoratorName = "JavaProxy",
columnOffset = 1,
Expand All @@ -12,6 +12,7 @@ var es5_visitors = (function () {
customExtendsArr = [],
normalExtendsArr = [],
interfacesArr = [],
UNSUPPORTED_TYPESCRIPT_EXTEND_FORMAT_MESSAGE = "[WARN] TypeScript-extended class has a super() call in an unsupported format.",

customExtendsArrGlobal = [];

Expand All @@ -35,18 +36,18 @@ var es5_visitors = (function () {

// ES5 Syntax
// anchor is extend (normal extend pattern + custom extend pattern)
if (t.isMemberExpression(path) && path.node.property.name === "extend") {
if (types.isMemberExpression(path) && path.node.property.name === "extend") {
traverseEs5Extend(path, config);
}

//anchor is new keyword (interface pattern)
if (t.isNewExpression(path)) {
if (types.isNewExpression(path)) {
traverseInterface(path, config);
}

// // Parsed Typescript to ES5 Syntax (normal extend pattern + custom extend pattern)
// // anchor is __extends
if (t.isIdentifier(path) && path.node.name === "__extends") {
if (types.isIdentifier(path) && path.node.name === "__extends") {
traverseTsExtend(path, config);
}
// Maybe it's not a good idea to expose this scenario because it can be explicitly covered
Expand Down Expand Up @@ -111,9 +112,13 @@ var es5_visitors = (function () {

var overriddenMethodNames = _getOverriddenMethodsTypescript(path, 3);

var extendParent = _getParrent(path, 1, config);
var extendPath = _getParent(path, 3, config);
var declaredClassName = "";
if (t.isCallExpression(extendParent)) {

var typescriptClassExtendSuperCallLocation = getTypeScriptExtendSuperCallLocation(extendPath, config);
var extendParent = _getParent(path, 1, config);

if (types.isCallExpression(extendParent)) {
declaredClassName = extendParent.node.arguments[0].name;
}

Expand All @@ -132,7 +137,7 @@ var es5_visitors = (function () {
if (decorateNodes) {
for (var i in decorateNodes) {
var currentDecorator = decorateNodes[i];
if (t.isCallExpression(currentDecorator)) {
if (types.isCallExpression(currentDecorator)) {
// Interfaces/Implements
if (currentDecorator.callee.name === config.interfacesDecoratorName) {
currentDecorator.callee.skipMeOnVisit = true;
Expand Down Expand Up @@ -161,7 +166,9 @@ var es5_visitors = (function () {
if (isDecoratedWithExtend) {
traverseJavaProxyExtend(customExtendDecoratorValue, config, customExtendDecoratorName, extendClass, overriddenMethodNames, implementedInterfaces);
} else {
var lineToWrite = _generateLineToWrite("", extendClass, overriddenMethodNames, TYPESCRIPT_EXTEND_STRING + DECLARED_CLASS_SEPARATOR + declaredClassName, "", implementedInterfaces);
var lineToWrite;

lineToWrite = _generateLineToWrite("", extendClass, overriddenMethodNames, `${FILE_SEPARATOR}${config.filePath}${LINE_SEPARATOR}${typescriptClassExtendSuperCallLocation.line}${COLUMN_SEPARATOR}${typescriptClassExtendSuperCallLocation.column}` + DECLARED_CLASS_SEPARATOR + declaredClassName, "", implementedInterfaces);

if (config.logger) {
config.logger.info(lineToWrite)
Expand All @@ -171,23 +178,145 @@ var es5_visitors = (function () {
}
}

function traverseForDecorate(path, config, depth) {
var iifeRoot = _getParrent(path, depth)
var body = iifeRoot.node.body;
for (var index in body) {
var ci = body[index];
if (isDecorateStatement(ci)) {
// returns the node of the decorate (node.expression.right.callee)
// __decorate([..])
return ci.expression.right.arguments[0].elements;
}
}

return null;
}
function getTypeScriptExtendSuperCallLocation(extendPath, config) {
var constructorFunctionName;
var returnIdentifierName;
var superCalleeStartColumn;
var superCalleeLine;
var locationAssigned = false;

// checks if constructor function and return identifiers match in a transpiled typescript class extend
if (extendPath.node.body && extendPath.node.body.length >= 3) {
if (types.isFunctionDeclaration(extendPath.node.body[1]) && extendPath.node.body[1].id)
constructorFunctionName = extendPath.node.body[1].id.name;
if (types.isReturnStatement(extendPath.node.body[extendPath.node.body.length - 1]))
returnIdentifierName = extendPath.node.body[extendPath.node.body.length - 1].argument.name;
}

// checks the typescript-extended class for a strict format, and a super call/apply inside
/**
* function MyBtn() {
var _this = _super.call(this) || this;
return global.__native(_this);
}

**UGLIFIED extended class**

function t(t) {
var r = e.call(this) || this;
r.textBase = t;
return global.__native(r);
}
*/
if (constructorFunctionName === returnIdentifierName && !!constructorFunctionName) {
var constructorFunctionScope = extendPath.node.body[1];
// the 'super' variable will always be passed as the second argument to the __extends call
// try to find the 'super' identifier which may be uglified
var superVariableIdentifier = getSuperVariableIdentifier(extendPath.node.body[0]);

//// helper functions to find the correct super.call(this) node
function getSuperVariableIdentifier(__extendsNode) {
if (types.isExpressionStatement(__extendsNode) && types.isCallExpression(__extendsNode.expression)) {
var __extendsCallArguments = __extendsNode.expression.arguments;
if (__extendsCallArguments.length == 2) {
return __extendsCallArguments[1].name;
}
}
}

/** Getting the super.call node from assignment
if expressionStatement => check possibleExpressionStatements[0]
if possibleExpressionStatements[0].expression is assignment expression
if possibleExpressionStatements[0].expression.right is logical expression
if possibleExpressionStatements[0].expression.right.left is Call expression
if possibleExpressionStatements[0].expression.right.left.callee.object.name === superVariableIdentifier
if the above is valid, then variableRHS = possibleVariableDeclarations[0].expression.right.left
*/
function getThisAssignmentSuperCallLineNode(nodes, superIdentifier) {
var matchingNodes = nodes.filter(
(node) => {
return types.isAssignmentExpression(node.expression)
&& types.isLogicalExpression(node.expression.right)
&& types.isCallExpression(node.expression.right.left)
&& node.expression.right.left.callee.object.name === superIdentifier;
});

return matchingNodes.length > 0 ? matchingNodes[0].expression.right.left : null;
}

/** Getting the super.call node from declaration
if variableDeclaration => check possibleVariableDeclarations[0].declarations[0].init isn't null
if possibleNodesForSuperCall[0].declarations[0].init is logical expression
if possibleNodesForSuperCall[0].declarations[0].init.left is Call Expression
if possibleNodesForSuperCall[0].declarations[0].init.left.callee.object.name === superVariableIdentifier
if the above is valid, then variableRHS = possibleVariableDeclarations[0].declarations[0].init.left
*/
function getThisDeclarationSuperCallLineNode(nodes, superIdentifier) {
var matchingNodes = nodes.filter(
(node) => {
return types.isLogicalExpression(node.declarations[0].init)
&& types.isCallExpression(node.declarations[0].init.left)
&& node.declarations[0].init.left.callee.object.name === superIdentifier;
});

return matchingNodes.length > 0 ? matchingNodes[0].declarations[0].init.left : null;
}
////

if (superVariableIdentifier) {
var possibleVariableDeclarations = [];
var possibleExpressionStatements = [];

constructorFunctionScope.body.body.forEach(node => {
if (types.isVariableDeclaration(node)) {
possibleVariableDeclarations.push(node);
} else if (types.isExpressionStatement(node)) {
possibleExpressionStatements.push(node);
}
});

if (possibleVariableDeclarations.length > 0 || possibleExpressionStatements.length > 0) {
var superCallRHS = getThisDeclarationSuperCallLineNode(possibleVariableDeclarations, superVariableIdentifier)
|| getThisAssignmentSuperCallLineNode(possibleExpressionStatements, superVariableIdentifier);

if (superCallRHS) {
var superCallee = superCallRHS.callee.property;
superCalleeStartColumn = superCallee.loc.start.column + 1;
superCalleeLine = superCallee.loc.start.line;

locationAssigned = true;
}
}
}
}

if (!locationAssigned) {
config.logger.info(UNSUPPORTED_TYPESCRIPT_EXTEND_FORMAT_MESSAGE + " ctor function name: " + constructorFunctionName);
}

return {
line: superCalleeLine,
column: superCalleeStartColumn
};
}

function traverseForDecorate(path, config, depth) {
var iifeRoot = _getParent(path, depth)
var body = iifeRoot.node.body;
for (var index in body) {
var ci = body[index];
if (isDecorateStatement(ci)) {
// returns the node of the decorate (node.expression.right.callee)
// __decorate([..])
return ci.expression.right.arguments[0].elements;
}
}

return null;
}

function traverseForDecorateSpecial(path, config, depth) {
var iifeRoot = _getParrent(path, depth);
var iifeRoot = _getParent(path, depth);

var sibling = iifeRoot.getSibling(iifeRoot.key + 1).node;
if (sibling) {
Expand All @@ -202,12 +331,12 @@ var es5_visitors = (function () {
}

function isDecorateStatement(node) {
return t.isExpressionStatement(node) &&
t.isAssignmentExpression(node.expression) &&
return types.isExpressionStatement(node) &&
types.isAssignmentExpression(node.expression) &&
node.expression.right.callee &&
node.expression.right.callee.name === "__decorate" &&
node.expression.right.arguments &&
t.isArrayExpression(node.expression.right.arguments[0])
types.isArrayExpression(node.expression.right.arguments[0])
}

/*
Expand Down Expand Up @@ -296,23 +425,23 @@ var es5_visitors = (function () {
var extendArguments = path.parent.arguments;
var arg0,
arg1;
if (extendArguments.length === 1 && t.isObjectExpression(arg0)) {
if (extendArguments.length === 1 && types.isObjectExpression(arg0)) {
arg0 = extendArguments[0];
}
else if (t.isStringLiteral(arg0)) {
else if (types.isStringLiteral(arg0)) {

}

var arg0 = "",
arg1;
if (extendArguments.length) {
// Get implementation object when there is only 1 argument
if (extendArguments.length === 1 && t.isObjectExpression(extendArguments[0])) {
if (extendArguments.length === 1 && types.isObjectExpression(extendArguments[0])) {
arg1 = extendArguments[0];
}
// Get the name of the extended class and the implementation object when both arguments are present
else if (extendArguments.length === 2) {
if (t.isStringLiteral(extendArguments[0]) && t.isObjectExpression(extendArguments[1])) {
if (types.isStringLiteral(extendArguments[0]) && types.isObjectExpression(extendArguments[1])) {
arg0 = extendArguments[0];
arg1 = extendArguments[1];
}
Expand Down Expand Up @@ -386,7 +515,7 @@ var es5_visitors = (function () {
*/
function _getOverriddenMethods(node, config) {
var overriddenMethodNames = [];
if (t.isObjectExpression(node)) {
if (types.isObjectExpression(node)) {
var objectProperties = node.properties;

for (var index in objectProperties) {
Expand All @@ -407,7 +536,7 @@ var es5_visitors = (function () {

var interfacesFound = false;

if (t.isObjectExpression(node)) {
if (types.isObjectExpression(node)) {
var objectProperties = node.properties;

/*
Expand All @@ -428,7 +557,7 @@ var es5_visitors = (function () {
// if the user has declared interfaces that he is implementing
if (!interfacesFound
&& objectProperties[index].key.name.toLowerCase() === "interfaces"
&& t.isArrayExpression(objectProperties[index].value)) {
&& types.isArrayExpression(objectProperties[index].value)) {
interfacesFound = true;
var interfaces = objectProperties[index].value.elements;

Expand All @@ -451,7 +580,7 @@ var es5_visitors = (function () {
function _getWholeInterfaceNameFromInterfacesNode(node) {
var interfaceName = "";

if (t.isMemberExpression(node)) {
if (types.isMemberExpression(node)) {
interfaceName += _resolveInterfacePath(node.object);
interfaceName += node.property.name;
}
Expand All @@ -462,8 +591,8 @@ var es5_visitors = (function () {
function _resolveInterfacePath(node) {
var subNode = "";

if (t.isMemberExpression(node)) {
if (t.isMemberExpression(node.object)) {
if (types.isMemberExpression(node)) {
if (types.isMemberExpression(node.object)) {
subNode += _resolveInterfacePath(node.object);
subNode += node.property.name + ".";
} else {
Expand All @@ -480,7 +609,7 @@ var es5_visitors = (function () {
isAndroidInterface = false;

while (node !== undefined) {
if (!t.isMemberExpression(node)) {
if (!types.isMemberExpression(node)) {
if (isAndroidInterface) {
arr.push(node.name)
}
Expand All @@ -498,10 +627,10 @@ var es5_visitors = (function () {
function _getArgumentFromNodeAsString(path, count, config) {

var extClassArr = [];
var extendedClass = _getParrent(path, count, config);
var extendedClass = _getParent(path, count, config);

if (extendedClass) {
if (t.isCallExpression(extendedClass.node)) {
if (types.isCallExpression(extendedClass.node)) {
var o = extendedClass.node.arguments[0];
}
else {
Expand All @@ -518,7 +647,7 @@ var es5_visitors = (function () {
}

function _getDecoratorArgument(path, config, customDecoratorName) {
if (path.parent && t.isCallExpression(path.parent)) {
if (path.parent && types.isCallExpression(path.parent)) {

if (path.parent.arguments && path.parent.arguments.length > 0) {

Expand Down Expand Up @@ -553,13 +682,13 @@ var es5_visitors = (function () {
function _getOverriddenMethodsTypescript(path, count) {
var overriddenMethods = [];

var cn = _getParrent(path, count)
var cn = _getParent(path, count)

// this pattern follows typescript generated syntax
for (var item in cn.node.body) {
var ci = cn.node.body[item];
if (t.isExpressionStatement(ci)) {
if (t.isAssignmentExpression(ci.expression)) {
if (types.isExpressionStatement(ci)) {
if (types.isAssignmentExpression(ci.expression)) {
if (ci.expression.left.property) {
overriddenMethods.push(ci.expression.left.property.name)
}
Expand All @@ -570,18 +699,18 @@ var es5_visitors = (function () {
return overriddenMethods;
}

function _getParrent(node, numberOfParrents, config) {
function _getParent(node, numberOfParents, config) {
if (!node) {
throw {
message: "No parent found for node in file: " + config.filePath,
errCode: 1
}
}
if (numberOfParrents === 0) {
if (numberOfParents === 0) {
return node;
}

return _getParrent(node.parentPath, --numberOfParrents)
return _getParent(node.parentPath, --numberOfParents)
}

function _testJavaProxyName(name) {
Expand Down
Loading