Показать сообщение отдельно
  #164 (permalink)  
Старый 10.12.2013, 15:42
Кандидат Javascript-наук
Посмотреть профиль Найти все сообщения от Maxmaxmaximus4
 
Регистрация: 08.12.2013
Сообщений: 142

оч просто, я создал сервис который это делает $parseController =) пока это, быдлокод и я еще не рефакторил.
на 172 строчке часть которая тебя интересует.

ui.service('$parseController', function() {


  function getParams(code) {
    return code.match(/\(([\s\S]*?)\)/)[1].match(/[$\w]+/img) || [];
  }


  function asyncServices(code) {
    var reg = /^\s*(.+?)=\s*([$\w]+).+?(?=\n)/igm;
    var params = getParams(code);

    function isService(service) {return ~params.indexOf(service) || /^\$/.test(service) }

    return code.replace(reg, function(match, exp, service) {
      if (!isService(service)) return match;
      return ';' + service + '.$async = function($$val){' + exp + '=$$val;$$scope.$digest()};\n' +
             match;
    });
  }


  function globalsToScope(code) {
    var parsedFunc = getFunction(code);
    var funcHead = parsedFunc.head;
    var funcBody = parsedFunc.body;
    var localVars = getLocalVarNames(funcHead, funcBody);
    var functions = getFunctions(funcBody);
    var newFuncBody = functions.length ? '' : replaceGlobalVars(funcBody, localVars);

    for (var i = 0; i < functions.length; i++) {
      var fun = functions[i];
      var start = (i === 0) ? 0 : functions[i - 1].closeBlock;
      var q = funcBody.slice(start, fun.open);
      newFuncBody += replaceGlobalVars(q, localVars);
      newFuncBody += globalsToScope(fun.code);

      if (i === (functions.length - 1)) {
        newFuncBody += replaceGlobalVars(funcBody.slice(fun.closeBlock), localVars);
      }
    }

    return funcHead + newFuncBody;
  }


  function replaceGlobalVars(code, localVars) {
    return code = code.replace(/([\n;]\s*)([$_\w]+)\s*=/img, function(match, space, varName) {
      if (~localVars.indexOf(varName)) return match;
      return space + '$$self.' + varName + '=';
    });
  }


  function getLocalVarNames(funcHead, funcBody) {
    var paramNames = funcHead.match(/\(([\s\S]*?)\)/)[1].match(/[$_\w]+/img) || [];
    var declarationRegExp = /var\s+([$_\w]+(?:\s*,\s*[$_\w]+)*)/img;
    var varNameRegExp = /[$_\w]+/img;
    var varNames = paramNames;

    clearFromFunctions(funcBody).replace(declarationRegExp, function(match, declaration) {
      [].push.apply(varNames, declaration.match(varNameRegExp));
    });

    return varNames;
  }


  function clearFromFunctions(code) {
    var functions = getFunctions(code);
    each(functions, function(func) { code = code.replace(func.code, '') });
    return code;
  }



  function clearFromComments(code) {
    return code.replace(/(\/\*[\s\S]*?\*\/)|(\/\/[\s\S]*?(?=\n))/img, '');
  }


  function getFunctions(code) {
    var index = 0;
    var functions = [];
    while (true) {
      var foundFunction = getFunction(code, index);
      if (!foundFunction) break;
      index = foundFunction.closeBlock;
      functions.push(foundFunction);
    }
    return functions;
  }



  function getFunction(code, index) {
    var open = /function\s*[$_\w]*\s*\([\s\S]*?\)\s*?\{/img;
    var reg = /(\{)|(\})/img;
    return findBlock(code, open, reg, index);
  }



  function bracketCells(code) {
    var bracketCells = getBracketCells(code);
    var regExp = /(?:([$\w]+)\s*\.\s*)?([$\w]+)\s*=\s*\(([\s\S]*)\)/im;

    for (var i = 0; i < bracketCells.length; i++) {
      var bracketCell = bracketCells[i];
      code = code.replace(bracketCell.code, function(subStr) {
        var match = subStr.match(regExp);
        var cell = match[2];
        var exp = match[3];
        return '\n;$$scope.$cell("' + cell + '",function(){return ' + exp + '}.bind(this));';
      });
    }

    return code;
  }



  function getBracketCells(code) {
    var index = 0;
    var cells = [];
    while (true) {
      var foundCell = findBlock(code, /[\n;]\s*.+?=\s*?\(/img, /(\()|(\))/img, index);
      if (!foundCell) break;
      index = foundCell.closeBlock;
      cells.push(foundCell);
    }
    return cells;
  }



  function findBlock(code, openRegExp, bracketRegExp, index) {
    index = index || 0;

    openRegExp.lastIndex = index;
    var bracketCnt = 0;
    var headEntry = openRegExp.exec(code);
    if (!headEntry) return null;
    var head = headEntry[0].slice(0, -1);
    var startIndex = headEntry.index;
    var openBlockIndex = headEntry.index + head.length;
    bracketRegExp.lastIndex = openBlockIndex;

    do {
      var find = bracketRegExp.exec(code);
      if (!find) return null;
      if (find[1]) bracketCnt++;
      else bracketCnt--;
    } while (bracketCnt);

    return {
      open      : startIndex,
      openBlock : openBlockIndex,
      closeBlock: bracketRegExp.lastIndex,
      head      : head,
      body      : code.slice(openBlockIndex, bracketRegExp.lastIndex),
      code      : code.slice(startIndex, bracketRegExp.lastIndex)
    }
  }


  return  function(controller) {
    var regExp = /function\s*[$_\w]*\s*\(([\s\S]*?)\)\s*\{([\s\S]*)\}/;
    var code = controller.toString();

    code = clearFromComments(code);
    code = globalsToScope(code);
    code = bracketCells(code);
    code = asyncServices(code);

    var match = code.match(regExp)
    var params = match[1];
    var body = 'var $$self=this;with($$self){' + match[2] + '}';
    var inject = controller['$inject'];


    if (!inject) inject = params.match(/[$_\w]+/img) || [];
    inject.push('$scope');
    params = params ? params + ',$$scope' : '$$scope';

    var newController = new Function(params, body);
    newController.prototype = controller.prototype;
    newController['$inject'] = inject;
    return newController;
  };

});

Последний раз редактировалось Maxmaxmaximus4, 10.12.2013 в 15:45.
Ответить с цитированием