Статический анализатор кода для встроенного языка 1С

Инструмент статического анализа модулей встроенного языка 1С

Назначение инструмента

Программа предназначена для статического анализа модулей встроенного языка 1С (файлов *.bsl).  

Зачем это нужно? Применение статического анализа при разработке позволяет сократить количество ошибок, выявляемых на этапе работы и сократить время, затрачиваемое на отладку за счёт выявления этих ошибок на этапе разработки.

В ходе работы проверяется в первую очередь корректность программы на встроенном языке (несколько строже, чем сам 1С), а так же ищутся ошибки в конструкциях программы, которые являются синтаксически правильными, но при этом содержат смысловые ошибки (см. список проверяемых ошибок ниже).

Возможности

Позволяет выполнить проверку файлов на наличие ошибок в интерактивном или пакетном режиме работы.

В интерактивном режиме предоставляется возможности:

  • загрузки и проверки файла на наличие ошибок с учётом задаваемых констант компиляции
  • отображения списка ошибок и переход из него к месту ошибки в редактируемом файле
  • загрузки файла для редактирования
  • сохранения файла
  • при запуске программы открывается последний редактируемый файл

В пакетном режиме предоставляется возможность проверки одного или нескольких файлов с учётом определённых констант препроцессора и вывод сообщений об ошибках в файл протокола

Запуск в пакетном режиме

bslsa.exe pathToLogFile [ —define=DEFINE […]] pathToFileToCheck1 [… pathToFileToCheckN]

где:

    pathToLogFile — путь к файлу протокола

    —define=DEFINE — определение требуемого символа препроцессора, например Клиент или Сервер

   pathToFileToCheck1 — путь к файлу или файлам, которые требуется проверить

Пример строки запуска в пакетном режиме

bslsa.exe c:check.log  —define=Клиент —define=Сервер d:cfgunload*.bsl

Планы по развитию

В перспективе планируется:

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

Ошибки и предложения

https://trello.com/b/mwACzUl2/estatico-analisis

Распознаваемые ошибки

  • Две последовательные переменные присваиваются через одно и то же выражение, что может являться логической ошибкой или неоптимизированным кодом.
  • Не все ветви выполнения в функции %1 возвращают какое-либо значение, что похоже на ошибку.
  • В функции ИМЯ отсутствует завершающий оператор ВОЗВРАТ (или ВЫЗВАТЬИСКЛЮЧЕНИЕ) что похоже на ошибку.
  • Результат вызова функции ‘%1’ не используется, что может являться ошибкой.
  • Функция ИМЯ возвращает одно и тоже значение ЗНАЧЕНИЕ во всех точках возврата, что похоже на ошибку.
  • Операторы функции ИМЯ1 полностью совпадают с операторами функции ИМЯ2.
  • Возможно конструкция A[B ОПЕРАТОР C] ошибочна и нужна была A[B] ОПЕРАТОР C.
  • Функция СтрДлина вызывается в цикле для константного выражения, что может сказываться на производительности.
  • В выражении используется неинициализированная локальная переменная %1, что похоже на ошибку.
  • Создаваемая переменная ИМЯ имеет тоже имя что и процедура, что может привести к ошибкам.
  • Переменная ИМЯ присваивается дважды подряд без её использования между присваиваниями, что похоже на ошибку.
  • Переменной ИМЯ присвоено значение, но оно нигде не используется, что похоже на ошибку.
  • Переменная ИМЯ имеет имя одинаковое с глобальной переменной, что может привести к ошибкам.
  • Переменная %1 переопределяет одноимённый параметр.
  • Инструкция ПРОДОЛЖИТЬ является последней в цикле. Она либо является лишней, либо это похоже на ошибку кодирования.
  • Отсутствуют какие-либо операторы внутри блока (ЦИКЛ|ЕСЛИ). Возможно это ошибка кодирования.
  • Переменная ИМЯ используется для счётчика цикла и в этом и внешнем цикле, что похоже на ошибку кодирования.
  • Этот и внешний циклы ДЛЯ КАЖДОГО реализуют обход по одной и той же коллекции %1, что может быть ошибкой.
  • Начальное и конечное значение цикла совпадают, что похоже на ошибку кодирования.
  • Безусловная операция ВОЗВРАТ внутри цикла. Это может указывать на логическую ошибку.
  • Недостижимый код.
  • Оператор ? вне зависимости от условия возвращает одинаковые значения.
  • Присвоение переменной ИМЯ самой себе похоже на ошибку кодирования.
  • Рекурсивная проверка ЕСЛИ (%1) ТОГДА ЕСЛИ (%1) … похожа на ошибку кодирования, так как условие уже проверено выше.
  • Обнаружены два взаимоисключающих условия (%1) и (%2). Второе условие всегда будет ложным.
  • Последний оператор ВОЗВРАТ в ветке ТОГДА|ИНАЧЕТОГДА|ИНАЧЕ идентичен оператору ВОЗВРАТ следующему после оператора ЕСЛИ. Похоже, что он не нужен или присутствует ошибка.
  • В первом из двух последовательных операторов ЕСЛИ с одинаковыми условиями содержится безусловный оператор ВОЗВРАТ. Второй оператор ЕСЛИ либо не нужен, либо его условие записано с ошибкой.
  • Конструкция ЕСЛИ (%1) ТОГДА … ИНАЧЕ ЕСЛИ (%1) … похожа на ошибку кодирования, так как оно никогда не будет выполнено.
  • Операторы в блоке ТОГДА полностью эквивалентны операторам в блоке ИНАЧЕ.
  • Выражение (%1) окружено бесполезными скобками. Может быть они не нужны или присутствует ошибка
  • Одинаковые выражения ‘%2’ слева и справа от оператора ‘%1’. Возможно это ошибка кодирования.

62 Comments

  1. ardn

    Возможна ли пакетная работа?

    Reply ↓
  2. Evil Beaver

    А без окошка, в командной строке работает?

    Reply ↓
  3. artbear

    Правильно я понимаю, что пока исследуется только независимый/отдельный модуль, без связей с соседними модулями, например, общие модули ?

    Reply ↓
  4. Evil Beaver

    (3) artbear, судя по диагностике «переменная дублирует глобальную переменную» — нет. Или под глобальной имеется в виду переменная уровня модуля?

    Reply ↓
  5. nixel

    Некорректно обрабатывает комментарии внутри многострочной строки вида:

    «Многострочная

    |строка

    // коммент +

    |с добавленным текстом, окруженным тегами

    // коммент —

    |завершение строки»;

    Ну и конечно же интересует запуск из командной строки. Плюс интересно взглянуть на исходники (желательно открытые) 🙂

    Спасибо за инструмент!

    Reply ↓
  6. so-quest

    winxp — не запустилось.

    С чем связан выбор qt?

    Reply ↓
  7. so-quest

    разбор по грамматике или руками? Поддержка препроцессора есть или планируется? Разделение по областям видимости — если сделана — то как? Обработка правил — как реализована (кодом или есть язык преобразований)? Сырцы — принципиально не открываешь или можно ожидать?

    Reply ↓
  8. honomer

    (1) ardn, Возможна. Посмотрить окно «О программе», там написано, как это сделать.

    Reply ↓
  9. honomer

    (2) Evil Beaver, Работает. Можно увидеть синтаксис командной строки вызвав программу с параметром /?

    Reply ↓
  10. honomer

    (3) artbear, Да, правильно. Пока только один модуль без связи с соседними. И это существенно сказывается на выводе типов.

    Reply ↓
  11. honomer

    (5) nixel, разбор многострочной строки на выходных попробую исправить.

    Reply ↓
  12. honomer

    (6) so-quest, на QT потому, что не охота было сильно заморачиваться с интерфейсом. А что пишет в WinXP — ошибка какая-то есть или совсем не запускается?

    Reply ↓
  13. honomer

    (7) so-quest, Препроцессор поддерживается. Про области видимости — не понял о чём речь.

    Разбор пока руками, может когда ANTLR v4 поддержит С++ перейдём на него.

    Исходники вам в данный момент зачем?

    Reply ↓
  14. Evil Beaver

    (13) нам в данный момент они (исходники) не зачем, но в перспективе мы хотим использовать открытый инструмент (если он будет открытым). Религия у нас такая тут… ))

    Кроме того, в открытый инструмент мы запросто сможем вложиться кодом, делая мир лучше.

    Reply ↓
  15. honomer

    (14) Evil Beaver, простите, я религии стараюсь обходить стороной. Пока открывать не готов, потом — подумаем.

    Reply ↓
  16. Evil Beaver

    (15) думайте, конечно. Просто когда надоест пилить в одиночку, вспомните мои слова )))

    Reply ↓
  17. honomer

    (16) Evil Beaver, под oneScript eго проще заново написать, чем этот переделывать.

    Reply ↓
  18. so-quest

    Да не в коде дело, а в правилах и модели на которой эти правила будете анализировать.

    (17) как совет — пока не поздно — уходи с С++ на языки с более простым циклом разработки

    Reply ↓
  19. Evil Beaver

    (17) я вовсе не в привязке к oscript спрашиваю)))

    Reply ↓
  20. honomer

    (19) Evil Beaver, да я, если честно, ни в чём плохом вас и не подозревал. Извините, действительно со стороны некрасиво получилось.

    Reply ↓
  21. honomer

    (18) so-quest, более простой цикл разработки — это какой-же? 🙂 Шарп, ява? Фреймворки у них мощные, а цикл разработки такой же — кодишь, дебажишь, тестишь.

    Reply ↓
  22. so-quest

    (21) лисп/кложура/схема : тест -> репл -> код и функции не будут такие большие

    Reply ↓
  23. artbear

    (21)

    цикл разработки такой же — кодишь, дебажишь, тестишь.

    ОФФ/2 А если юзать ТДД, то скорость будет выше 🙂

    Reply ↓
  24. lustin

    (22) so-quest, GoLang забыл

    Reply ↓
  25. Evil Beaver

    (24) lustin, кстати, да. Golang разработан, как конкурент C/C++, в нем авторы серьезно подумали над устранением атавизмов C++ и заявляют практически о будущем мировом господстве.

    Reply ↓
  26. premierex

    На Инфостарте уже был опубликован проект тестирования конфигураций. Реализован на wsh скриптах (vbs, js). Исходные коды открыты. Тесты легко подключаются буквально на лету, каждый тест снабжен документацией, в проекте принимало участие несколько разработчиков. Кому интересно, можно посмотреть по ссылке.

    Reply ↓
  27. honomer

    (26) premier,

    Больше инструментов, хороших и разных.

    Сайт программы недоступен.

    Reply ↓
  28. brr

    (26) premier, это разные вещи

    Reply ↓
  29. pro1c@inbox.ru

    Без раскраски кода не годится!

    Для такого инструмента, как статический анализатор кода, она обязательна должна быть!

    Reply ↓
  30. so-quest

    (29) — а подробнее? чем эта раскраска поможет?

    Reply ↓
  31. honomer

    (29) pro1c@inbox.ru, вот тоже хотелось бы узнать — чем поможет раскраска, если основной режим работы для не встроенного в Конфигуратор инструмента, вообще говоря, из командной строки.

    Reply ↓
  32. pro1c@inbox.ru

    (30) so-quest,

    Если я делаю, статический анализ кода, мне мало сообщений о потенциальных или существующих ошибках, а хотелось бы без труда охватить взглядом код!

    Ведь где то я могу согласится с анализатором, а где то нет, раскраска просто помогает мне визуально пробегать по коду взглядом, без лишнего труда выделять ключевые слова и т.д.

    Плюс, я могу просто начать писать какую-нибудь процедуру для своих тестов на анализ сразу в окне, хотелось бы иметь удобный редактор!

    Reply ↓
  33. so-quest

    (32) Подобные инструменты просто делают вывод (файл или консоль) а уж раскраской занимаются совсем другие программы. Основная задача анализатора — сообщить о проблеме (сообщение может быть и ложным, но если анализатор его нашел, значит текст попадает под правило анализа) Что делать с этой информаций дальше — анализатору пофиг. ведь вывод прогаммы можно и в dev/null отправить

    Reply ↓
  34. premierex

    (27) Сайт программы действительно недоступен, т.к. автор этот проект забросил, но я принимал активное участие в этом проекте (писал часть движка и некоторые тесты) и, думаю, смог бы убедить автора проекта «подарить» его сообществу. К тому же большинство исходных кодов сохранились, их можно на этом сайте скачать или у меня попросить (не уверен, правда, что самой последней версии) .

    (28) Уважаемый, Вы ошибаетесь. Эти проекты из одной и той же области — а именно: тестирование кода модулей на соответствие некоторым стандартам (кто уж какой придумает). Отличие от предлагаемого ПО в данной публикации (+ кстати забыл поставить, исправлюсь) — это открытость кодов и масштабируемость, т.е. возможность написать тест под какие-то свои стандарты оформления кода. Ну и возможность работы над проектом в команде.

    Reply ↓
  35. premierex

    Вот архив, который у меня сохранился, посмотрите, протестируйте…

    Reply ↓
  36. so-quest

    Как минимум неплохо бы документацию.

    Как максимум — подробную документацию.

    Reply ↓
  37. honomer

    (36) so-quest, как-то пока руки не дошли

    Reply ↓
  38. premierex

    (0) Автор, утверждение Конструкция ЕСЛИ (%1) ТОГДА … ИНАЧЕ ЕСЛИ (%1) … похожа на ошибку кодирования, так как оно никогда не будет выполнено. не совсем верно, так как ЕСЛИ (%1) = Истина то код, следующий за оператором ТОГДА будет выполняться всегда, а вот код, следующий за конструкцией ИНАЧЕ ЕСЛИ (%1) ТОГДА действительно никогда выполняться не будет.

    Reply ↓
  39. honomer

    (38) premier, спасибо. Переформулирую в следующей версии

    Reply ↓
  40. honomer

    Коллеги, вопрос: кроме понятного желания «больше правил» и хотелки «подкрашивающий редактор» есть ещё какие-то пожелания по функционалу, которые вы считаете важными, но они отсутствуют? Настройка списка правил для проверки и т.д.?

    Reply ↓
  41. so-quest

    1. Отдельно правила для лексера, парсера, преобразователя.

    2. Свое описание правил и соответственно интерпретатор этих правил.

    3. Возможность выключать проверку правила в коде

    4. Связь метаданных и кода

    5. Расчет метрик для кода

    Reply ↓
  42. so-quest

    6. Вывод лексем и ast в отдельный файл (даст возможность самому писать правила)

    Reply ↓
  43. so-quest

    7. Документировать все это

    Reply ↓
  44. so-quest

    8. Уйти от ручного разбора на генератор парсеров

    Reply ↓
  45. Zlohobbit

    Отличная доработка! Если возможно добавьте в следующих версиях поиск по анализируемому тексту! Нужно для анализа таких ошибок например как:»..похожа на ошибку кодирования, так как условие уже проверено выше.». И конечно же мечта это анализ cf -ников или для начала *.epf и *.erf))).

    А так суперская Приблуда! Спасибо!

    Reply ↓
  46. honomer

    (45) Zlohobbit, я подумывал сделать сортировку списка ошибок и его фильтрацию по типам и процедурам. Поиск, по-моему, тут не очень пригодится.

    Для анализа cf, epf, erf — их нужно распаковывать, а это уже другой компот: уже существуют такие инструменты, зачем писать ещё один.

    Reply ↓
  47. honomer

    (44) so-quest, про разбор я уже писал — antlr4 пока не поддерживает С++

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

    Пока хочется документировать нормально, сделать настройку списка проверяемых правил, исправить ошибки, внести новые 🙂 правила.

    Можно и расчет метрик кода.

    Остальное, как мне кажется, сейчас не так важно.

    Reply ↓
  48. so-quest

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

    Про генератор — кроме антлр есть море генераторов. Выгода от них — в более быстрой разработке — не надо думать про состояния и переходы. За тебя все сделают. Да и когда захочешь с С++ уйти — не придется много переписывать.

    Про правила — ты уверен что будешь успевать реагировать на все просьбы — добавь то или это? проще дать язык описания правил и на нем уже пусть пишут все что хотят. Внутри все равно примитивная перезапись термов и паттернматчинг .

    Reply ↓
  49. honomer

    (48) so-quest, Сделать вывод дерева — проблем нет. Как я уже выше спросил — какой в этом смысл? Кому это нужно и для чего? От этого зависит что и как выводить.

    Нужно ли, в конце концов, вообще тратить на это время?

    Про генераторы я в курсе. Flex, bison, flex++, bison++, spirit… и иже с ними. А так же про проблемы левой рекурсии и адские сообщения компилятора у некоторых.

    Что же про разработку основанную на правилах — считаю, что это ни разу не тривиальная задача по масштабам сравнивая и даже наверное больше с самим анализатором. Время затраченное на её разработку можно потратить довольно много и без особого успеха. Ведь это по сути — интерпретатор ещё одного языка, который будет описывать эти правила.

    Можете привести пример хотя бы одного анализатора, который использует такой подход? Я поглядел в википедии, но что-то ничего там такого не нашёл, хотя, нужно признаться, искал тоже не очень сильно.

    Reply ↓
  50. so-quest

    > Сделать вывод дерева — проблем нет. Как я уже выше спросил — какой в этом смысл? Кому это нужно и для чего?

    Сделай. Мне нужен этот вывод. Для собственных правил. Это же очевидно.

    > А так же про проблемы левой рекурсии …

    Ты грамматику С/С++ разбираешь? Это примитивный 1С. Тупо бейсик, без всяких извращений. Тебе грамматика наоборот поможет и спасет от проблем связанных с неоднозначностью разбора выражений

    > Что же про разработку основанную на правилах — считаю, что это ни разу не тривиальная задача

    Кто сказал что будет просто? Хотя там сложного ничего и нет . Вот пример простого правила для подобной твоей системы-

    (defrule :where ‘lexer
    :name ‘check-id-length
    :token ‘:identifier
    :description «Длинна переменной меньше 2 символов»
    :check #'(lambda (text type start end file index data)
    (> 2 (length text ))))
    

    Где сложность в реализации? Аналогично и для обхода AST строиться набор правил.

    Про построение статанализаторов кода — https://lvee.org/en/reports/LVEE_2012_01 и дальше по ссылкам.

    И просьба — сделай что бы под WinXP работала твоя разработка.

    Reply ↓
  51. eugeniezheludkov

    Начинал как то делать что-то подобное на регулярках в шарпе, просто была идея немного упростить труд КодРевьюверов ) и заодно «прошерстить» код от франчайзи. никакого статанализа не делал, только регулярка )

    https://github.com/znsoft/1SCodeAnalyze

    за код стыдно если честно. Последняя версия в ветви VS08.

    работает так: распаковываете все модули конфигурации в каталог,

    и в этом каталоге запускаете прогу .. а она в консоль выдает все найденные ошибки (имя объекта.имя модуля. имя метода. номер строки. кусок кода)

    Reply ↓
  52. honomer

    (50) so-quest,

    про вывод дерева понял. запишу себе в план.

    про то, где сложность реализации. Вот есть правило:

    (defrule :where ‘lexer

    :name ‘check-id-length

    :token ‘:identifier

    :description «Длинна переменной меньше 2 символов»

    :check #'(lambda (text type start end file index data)

    (> 2 (length text ))))

    сложность хотя бы в том, что в С++ нет возможности взять лямбду в виде куска кода из файлы и выполнить. Т.е. Нужно будет написать ещё один интерпретатор. или встроить какой-то, типа lua.

    про построение анализаторов — интересно, но примеров анализатора, основанного на правилах (о чём я собственно и задавал вопрос), которые мог бы задавать непосредственно пользователь я там что-то не обнаружил. Плохо искал?

    Reply ↓
  53. so-quest

    -> про вывод дерева понял. запишу себе в план.

    Ну хоть что-то 🙂 Когда ждать? Где будут обновления?

    -> сложность хотя бы в том, что в С++ нет возможности взять лямбду в виде куска кода из файлы и выполнить.

    <

    Reply ↓
  54. honomer

    (45) Zlohobbit, при клике на сообщении курсор переходит на строку, где диагностировали ошибку. Этого не достаточно?

    Reply ↓
  55. honomer

    (53) so-quest, ecl — это Embedable Common Lisp? Если да, ну и зачем оно мне — в QT уже есть встроенная поддержка QtScript.

    Reply ↓
  56. honomer

    (55) naf2000, Если вы серьёзно не понимаете зачем это, то дискуссия видится бессмысленной.

    Reply ↓
  57. so-quest

    (55) Тролишь? Или можешь привести доказательство того что 1С недоязык?

    (56) тогда непонятно что вsзвало проблему — » С++ нет возможности взять лямбду в виде куска кода из файлы и выполнить. Т.е. Нужно будет написать ещё один интерпретатор. или встроить какой-то, типа lua. » — если есть qtscript.

    Reply ↓
  58. honomer

    (58) so-quest, правила в приведённом виде — это не язык. и нужно будет делать их анализ и интерпретацию.

    В общем, я запишу и подумаю.

    Reply ↓
  59. 987ww765

    (59) Забросил проект?

    Reply ↓
  60. artbear

    Посмотрите наш проект https://silverbulleters.org/sonarqube/

    Тот самый крутой статический анализатор на базе AST-деревьев, кеша метаданных и т.п.

    Можно свои правила добавлять.

    Уже в куче разных компаний юзается, есть и облачные решения для клиентов

    По ссылке намного подробнее написано

    Reply ↓
  61. guy_septimiy

    Годная штука. Находит досадные недочеты

    Reply ↓
  62. gubanoff

    (0) (61) да, лучший вариант эти правила добавить в сонар. Можно в свободный плагин, который развивает сообщество https://github.com/1c-syntax/bsl-language-server

    Reply ↓

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *