Подтвердить что ты не робот

Есть ли какой-либо статический Call-Graph и/или Control-Flow-Graph API для JavaScript?

Существуют ли генераторы Call-Graph и/или Control-Flow-Graph для JavaScript?

Диаграмма вызовов - http://en.wikipedia.org/wiki/Call_graph

График потока управления - http://en.wikipedia.org/wiki/Control_flow_graph

EDIT: Я ищу специально для статического инструмента, который позволяет мне получить доступ к графику с помощью некоторого API/кода

4b9b3361

Ответ 1

Для этого вам необходимо:

  • синтаксический анализ,
  • разрешение имен (область обработки)
  • (в то время как JavaScript, возможно, "динамически типизирован", существуют все типы типизированных констант, включая функциональные константы, которые здесь представляют особый интерес)
  • анализ потока управления (для создания структуры графиков потока управления внутри методов)
  • анализ потока данных (для отслеживания того, где эти типы создаются/используются)
  • то, что составляет глобальные точки - анализ (отслеживать функциональные константы, передаваемые между функциями как значения в точку приложения).

Как это сделать, это хорошо документировано в литературе компилятора. Однако, выполняя этот вопрос значительного пота, поэтому ответы на форму "вы можете использовать результат парсера, чтобы получить то, что хотите" скорее пропустите точку.

Если вы можете применить все это оборудование, то, что вы получите как практический результат, - это консервативный ответ, например, "A может называть B". Это все, что вы знаете в любом случае, подумайте

 void A(int x,y) { if (x>y) foo.B(); }

Поскольку инструмент когда-то просто не может рассуждать о сложной логике, вы можете получить "A может вызывать B", даже когда разработчик приложения знает, что это невозможно:

 void A(int x) // programmer asserts x<4
   { if (x>5) foo.B(); }

eval делает проблему хуже, потому что вам нужно отслеживать результаты строковых значений, которые поступают в команды eval, и анализировать их, чтобы получить какую-то подсказку относительно того, какой код обходится, и какие функции, которые может вызвать код eval'd. Все становится очень неприятным, если кто-то передает "eval" в строке для eval: - {Вам также, вероятно, потребуется смоделировать контекст выполнения программы; Я подозреваю, что есть много API-интерфейсов браузера, которые включают обратные вызовы.

Если кто-то предлагает вам инструмент, в котором есть все необходимое оборудование, полностью настроенное для решения вашей проблемы из коробки, это, очевидно, будет здорово. Мое подозрение в том, что вы не получите такого предложения, потому что такого инструмента не существует. Причина в том, что инфраструктура необходима; его трудно построить, и вряд ли кто-нибудь может оправдать его только одним инструментом. Даже "оптимизирующий компилятор JavaScript", если вы можете найти, вероятно, не будет иметь все это оборудование, особенно глобальный анализ, и то, что он делает, вряд ли будет упакован в форму, предназначенную для легкого потребления для вашей цели.

Я избивал голову над этой проблемой, так как начал программировать в 1969 году (некоторые из моих программ тогда были компиляторами, и я хотел все это). Единственный способ получить это - амортизировать стоимость всего этого оборудования по множеству инструментов.

Моя компания предлагает DMS Software Reengineering Toolkit - пакет общих аналитических и трансформационных машин для компиляторов с множеством промышленных интерфейсов компьютера langauge (в том числе C, С++, COBOL и да, JavaScript). DMS предлагает API-интерфейсы для создания настраиваемых инструментов на своих общих основаниях.

Общие механизмы, перечисленные в верхней части сообщения, присутствуют в DMS, включая график потока управления и анализ потока данных, доступный через чистый документированный API. Этот анализ потока должен быть привязан к конкретным языковым фронтам. Это требует некоторой работы, и поэтому мы еще не сделали этого для всех языков. Мы сделали это для C [тестировали на системах из 18 000 единиц компиляции как монолит, включая вычисление графика вызовов для 250 000 функций, включая косвенные вызовы функций!], COBOL и Java, и мы работаем над С++.

DMS имеет тот же ответ "парсер" JavaScript, что и другие ответы в этом потоке, и рассматриваемый именно с этой точки зрения. DMS не лучше, чем другие ответы, которые говорят "постройте его поверх анализатора". Различие должно быть ясным: механизм уже присутствует в DMS, поэтому работа не является частью механизма и привязки к парсеру; это просто привязка к парсеру. Это еще немного работы, но, черт возьми, намного меньше, чем если бы вы только начали с парсера.

Ответ 2

WALA - это платформа анализа программ с открытым исходным кодом, которая может создавать статические графики вызовов и графики потока управления для JavaScript:

http://wala.sourceforge.net/wiki/index.php/Main_Page

Одно из предостережений состоит в том, что в графах вызовов могут отсутствовать некоторые ребра в присутствии eval, with и других трудно анализируемых конструкций. Кроме того, мы все еще работаем над масштабируемостью; WALA еще не может анализировать jquery в разумные сроки, но некоторые другие структуры могут быть проанализированы. Кроме того, наша документация для построения графиков вызовов JavaScript на данный момент невелика (улучшение в моем списке TODO).

Мы активно работаем над этим кодом, поэтому, если вы попробуете его и столкнетесь с проблемами, вы можете отправить список рассылки WALA (https://lists.sourceforge.net/lists/listinfo/wala-wala) или свяжитесь со мной.

Ответ 3

В общем случае это невозможно. Причина в том, что функции являются первоклассными и динамически типизированными, например, например:

var xs = some_function();
var each = another_function();
xs.map(each);

Есть два неизвестных. Одним из них является версия "map", которая называется (поскольку полисарифм Javascript не может быть решен статически в общем случае), а другой - значение, присвоенное "каждому", которое также не может быть статически разрешено. Единственными статическими свойствами этого кода являются то, что некоторый метод "map" вызывается для некоторой функции, которую мы получили от "another_function".

Если, однако, достаточно информации, есть два ресурса, которые могут быть полезны. Один из них - это анализатор Javascript общего назначения, специально созданный с использованием комбинаторов парсеров (Chris Double jsparse - хороший). Это позволит вам аннотировать дерево разбора по мере его создания, и вы можете добавить настраиваемое правило к узлам вызова для записи краев графа.

Другим инструментом, который вы можете найти полезным (бесстыдный плагин), является компилятор Javascript-to-Javascript, который я написал под названием Caterwaul. Это позволяет вам сопоставлять шаблоны с деревьями синтаксиса и знает, как ходить по ним, что может быть полезно в вашем случае. Это также может помочь, если вы хотите построить динамическую трассировку из краткосрочного исполнения (вероятно, ваш лучший выбор, если вы хотите получить точный и подробный результат).

Ответ 4

Вот несколько решений, которые я вижу:

  • Использование Aptana Просмотр списка вызовов
    Aptana - это IDE, основанная на Eclipse, которая позволяет редактировать и отлаживать код Javascript.

  • Используйте Dynatrace
    Dynatrace - полезный инструмент, который позволяет вам отслеживать свой код и видеть график вызовов и горячие точки.

  • Используйте Firebug
    Знаменитый аддон разработчика на Firefox

Большинство графиков вызовов, созданных здесь, будут динамическими, т.е. вы увидите график вызовов для заданного набора действий. Если вы ищете статические графики вызовов, сначала проверьте Aptana. Графики статических вызовов могут не позволить вам видеть динамические вызовы (код работает через eval()).

Ответ 5

Я думаю, http://doctorjs.org/ может соответствовать вашим потребностям. Он имеет хороший API JSON, доступен на github, подкрепленный mozilla. Он написан в самой JS и, как правило, довольно хорошо работает (в том числе с полиморфизмом и т.д.).

Ответ 6

Для подхода js проверьте arguments.callee.caller. Он предоставляет вам функцию, называемую функцией, в которой вы находитесь, и вы можете пересчитать стек вызовов. В этом потоке есть пример http://bytes.com/topic/javascript/answers/470251-recursive-functions-arguments-callee-caller.

Помните, что это может не работать во всех браузерах, и вы можете столкнуться с некоторыми неожиданными вещами, когда вы попадаете в верхнюю часть "стека вызовов" или собственных функций, поэтому используйте их на свой страх и риск.

Мой собственный пример работает в IE9 и Chrome 10 (не тестировал другие браузеры).

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body onload="Function1()">
<form id="form1" runat="server">
<div>

</div>
</form>
</body>

<script type="text/javascript">

function Function1()
{
    Function2();
}

function Function2()
{
Function3();
}
function Function3()
{
Function4();
}
function Function4()
{
    var caller = arguments.callee.caller;
    var stack = [];
    while (caller != null)
    {
        stack.push(caller);//this is the text of the function.  You can probably write some code to parse out the name and parameters.
        var args = caller.arguments; //this is the arguments for that function.  You can get the actual values here and do something with them if you want.
        caller = caller.caller;
    }
    alert(stack);
}


</script>
</html>

Ответ 7

Ближайшая вещь, которую вы можете получить на Call Graph, - это манипулирование полным Javascript AST. Это возможно с Rhino, взгляните на эту статью: http://tagneto.blogspot.com/2010/03/requirejs-kicking-some-ast.html

Пример из сообщения:

//Set up shortcut to long Java package name,
//and create a Compiler instance.
var jscomp = Packages.com.google.javascript.jscomp,
  compiler = new jscomp.Compiler(),

  //The parse method returns an AST.
  //astRoot is a kind of Node for the AST.
  //Comments are not present as nodes in the AST.
  astRoot = compiler.parse(jsSourceFile),
  node = astRoot.getChildAtIndex(0);

//Use Node methods to get child nodes, and their types.
if (node.getChildAtIndex(1).getFirstChild().getType() === CALL) {
  //Convert this call node and its children to JS source.
  //This generated source does not have comments and
  //may not be space-formatted exactly the same as the input
  //source
  var codeBuilder = new jscomp.Compiler.CodeBuilder();
  compiler.toSource(codeBuilder, 1, node);

  //Return the JavaScript source.
  //Need to use String() to convert the Java String
  //to a JavaScript String.
  return String(codeBuilder.toString());
}

В Javascript или Java вы можете пройти AST, чтобы построить любой тип графика вызовов или цепочку зависимостей, которые вы хотели бы.

Ответ 8

Не связан непосредственно с NodeJS, но, как правило, с JavaScript, SAP выпустила веб-IDE, связанную с HANA (но также свободно доступную из облака HANA). Подробнее см. здесь http://scn.sap.com/community/developer-center/cloud-platform/blog/2014/04/15/sap-hana-web-ide-online-tutorial).

В этой веб-среде IDE существует служба на основе REST, которая анализирует содержимое JavaScript с основным фокусом (но не только) при создании диаграммы вызовов. Есть много потребителей этой услуги, например, Code Navigation.

Дополнительная информация здесь (см. раздел "Поток функций" ): http://scn.sap.com/community/developer-center/hana/blog/2014/12/02/sap-hana-sps-09-new-developer-features-sap-hana-web-based-development-workbench

Примечание. Я являюсь основным разработчиком этой службы.