Глубокая переработка своей консоли запросов подтолкнула меня к поиску, а затем и созданию, инструмента для анализа взаимосвязей процедур и функций модуля и различных форм обработки.
Я лучше воспринимаю графическое представление и для целей анализа структуры кода мне изначально подошла следующая обработка “Граф вызовов для модулей 1С…”, которая парсит предложенный текст на процедуры и функции, строит дерево взаимосвязей и рисует по полученным данным связанный граф в виде картинки.
Все прекрасно, но при большом объеме кода граф получается перегружен и не всегда удачно формируется с точки зрения визуализации.
Затем указанную обработку доработал Павел Заяш (Pavl0), добавив возможность выгрузки в формате gml. Это значительно повысило возможности визуализации полученного графа.
Но хотелось еще большего удобства 🙂
Так, было бы не плохо анализировать выбранный список функций и процедур, анализировать асинхронные вызовы, выводить граф используемых и/или использующих процедуры и/или функции из списка.
В итоге я решил создать свой велосипед, учитывающий эти хотелки, а заодно и ознакомиться с замечательным форматом yml.
Парсить код решил с помощью regexp. Для детального синтаксического разбора языка – это вряд ли лучший вариант, но для реализации моей задачи вполне походящее решение.
Шаблон для процедур и функций получил следующий: “^Процедура([^КонецПроцедуры].*\n+)+КонецПроцедуры
” и “^Функция([^КонецФункции].*\n+)+КонецФункции
”
Шаблон для процедур и функций с параметрами такой: “^Процедура([^\)])+\)
” и “^Функция([^\)])+\)
”
Шаблон для имени процедур и функций: “^Процедура([^\(])+\(
” и “^Функция([^\(])+\(
”
Формат gml достаточно хорошо описан здесь у разработчика программы yEd, читающей этот формат.
Для моих целей на текущий момент оказалось достаточно следующих блоков gml:
//Описание: http://docs.yworks.com/yfiles/doc/developers-guide/gml.html#HierarchyExtension.graph.interedge_level // node: type - "ellipse"/"oval"/"circle", "rectangle", "triangle", "parallelogram", "hexagon", "diamond", "octagon", "roundrectangle", "rectangle3d", "trapezoid", "trapezoid2" // edge: type - "arc", "spline", "bezier", or "quadCurve" // edge: targetArrow, sourceArrow - "delta", "standard", "diamond", "short", "white_delta", "white_diamond", or "none" // edge: arrow - "last", "first", or "both" Если ИмяШаблона = "СвязиСекции" Тогда Возврат " edge | [ | source ""%source%"" | target ""%target%"" | label ""%label%"" | graphics | [ | fill ""#000000"" | targetArrow ""standard"" | ] | ] |"; ИначеЕсли ИмяШаблона = "СодержимоеСекции" Тогда Возврат " node | [ | id ""%id%"" | label ""%label%"" | graphics | [ | type ""%type%"" | fill ""%fill%"" | outline ""#000000"" | outlineWidth %outlineWidth% | h %height% | w %width% | ] | %gid% | ] |"; ИначеЕсли ИмяШаблона = "ГруппаМодуль" Тогда Возврат " node | [ | id ""%id%"" | label ""%label%"" | isGroup 1 | ] |"; ИначеЕсли ИмяШаблона = "Общий" Тогда Возврат "Creator ""lavelin.ru/code_structure"" |Version 0.1 |graph |[ | hierarchic 1 | label """" | directed 1 |%СодержимоеСекций% |%СвязиСекций% |]"; Иначе Возврат "" КонецЕсли;
В итоге получил следующий инструмент “АнализПроцедурИФункций”: