Code coverage report for harmonizer/transform/classes.js

Statements: 100% (74 / 74)      Branches: 100% (24 / 24)      Functions: 100% (4 / 4)      Lines: 100% (74 / 74)      Ignored: none     

All files » harmonizer/transform/ » classes.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98  1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 10 29 29 4   29 2   29 29 29 29 29 29 29 21         29       29 11 11 11 11 1 1   10 10   11 11 11 11 11 11   29 29 29 29 29 20   29 29 29 26           29 29 29 8 8 8 8 8 8 8 8 8   21 21   29 29 5       1
'use strict';
var objectPatternF = require('nodes');
var nodes = objectPatternF.nodes;
var syntax = require('nodes/syntax.json');
var objectPatternE = require('./spread');
var applyContext = objectPatternE.applyContext;
var objectPatternD = require('../util/insertion');
var insertAfter = objectPatternD.insertAfter;
var objectPatternC = require('../util/string');
var express = objectPatternC.express, upper = objectPatternC.upper;
var objectPatternB = require('../util/id');
var getUniqueId = objectPatternB.getUniqueId;
var objectPatternA = require('../util/extend');
var getExtendId = objectPatternA.getExtendId;
var objectPattern = require('../util/self');
var getSelfId = objectPattern.getSelfId;
function classify(program) {
  program.search('#Class').forEach(function (node) {
    var definitions = node.body.body;
    if (!node.id && node.parentNode.type === syntax.VariableDeclarator) {
      node.id = new nodes.Identifier({ name: upper(node.parentNode.id.name) });
    }
    if (!node.id) {
      node.id = getUniqueId(node, 'Class');
    }
    var name = node.id.name;
    var getPrototypeOfNamePrototype = 'Object.getPrototypeOf(' + name + '.prototype)';
    var getPrototypeOfName = 'Object.getPrototypeOf(' + name + ')';
    var extendId = getExtendId(program).clone();
    var superClass = node.superClass;
    var constructorMethod = !!definitions.search('> #MethodDefinition > key[name=constructor]').length;
    if (!constructorMethod) {
      definitions.unshift(new nodes.MethodDefinition({
        key: new nodes.Identifier({ name: 'constructor' }),
        value: express('(function () {\n        var proto = ' + getPrototypeOfNamePrototype + ';\n        if (proto !== null) proto.constructor.apply(this, arguments);\n      })').expression
      }));
    }
    var q = [
        '>> #CallExpression > callee#MemberExpression[computed=false] > object#Identifier[name=super]',
        '>> #CallExpression > callee#Identifier[name=super]'
      ];
    definitions.search(q).forEach(function (id) {
      var definition = id.parent('#MethodDefinition');
      var parentNode = id.parentNode;
      var callExpression, methodName;
      if (parentNode.type === syntax.MemberExpression) {
        callExpression = parentNode.parentNode;
        methodName = parentNode.property.name;
      } else {
        callExpression = parentNode;
        methodName = definition.key.name;
      }
      var superMethodXp = definition.static ? express(getPrototypeOfName + '.' + methodName).expression : express(getPrototypeOfNamePrototype + '.' + methodName).expression;
      var selfId;
      var definitionFunction = definition.value;
      selfId = id.scope() !== definitionFunction ? getSelfId(definitionFunction).clone() : new nodes.ThisExpression();
      callExpression.callee = superMethodXp;
      applyContext(callExpression, selfId);
    });
    var constructorFunction = definitions.search('> #MethodDefinition > key[name=constructor] < * > value')[0];
    constructorFunction.id = new nodes.Identifier({ name: name });
    definitions.removeChild(constructorFunction.parentNode);
    constructorFunction = new nodes.FunctionDeclaration(constructorFunction);
    if (!superClass) {
      superClass = new nodes.Identifier({ name: 'Object' });
    }
    var prototype = new nodes.ObjectExpression();
    var members = new nodes.ObjectExpression();
    definitions.forEach(function (definition) {
      (definition.static ? members : prototype).properties.push(new nodes.Property({
        key: definition.key,
        value: definition.value,
        kind: definition.kind || 'init'
      }));
    });
    var extendExpression = express(extendId.name + '()');
    var args = extendExpression.expression.arguments;
    if (node.type === syntax.ClassExpression) {
      var wrapper = express('(function(){})()').expression;
      wrapper.arguments.push(superClass);
      var body = wrapper.callee.body.body;
      var returnStatement = new nodes.ReturnStatement({ argument: extendExpression.expression });
      body.push(constructorFunction);
      body.push(returnStatement);
      node.parentNode.replaceChild(node, wrapper);
      superClass = getUniqueId(wrapper, 'Super' + upper(constructorFunction.id.name));
      wrapper.callee.params.push(superClass.clone());
    } else {
      node.parentNode.replaceChild(node, constructorFunction);
      insertAfter(constructorFunction, extendExpression);
    }
    args.push(superClass, constructorFunction.id.clone(), prototype);
    if (members.properties.length) {
      args.push(members);
    }
  });
}
exports.transform = classify;