Анализ сишных исходников через Тимсити
11.04.2018 23:56:28Я очень люблю и уважаю статический анализ кода. Когда-то прикручивал Кланг к сборкам, потом к нему добавился Сиппчек, сейчас я стараюсь оба анализатора использовать, хотя получается и не всегда. В прошлом году как раз прикручивал Сиппчек к нескольким проектам и возникла занятная задача интеграции с Тимсити.
Анализ должен прогоняться регулярно, так же, как и сборки. Поэтому возложить запуск анализа на Тимсити (ну или любой другой подобный инструмент, просто тут уж так сложилось, что у нас этим заведует именно Тимсити) выглядит вполне логичным. Вопрос в том, что потом делать с результатами.
С одной стороны, архив со сгенерированным веб-отчётом всегда можно положить в артефакты, но оттуда его надо доставать, открывать и вот это всё, не очень. С другой стороны, у Тимсити есть шикарная возможность интеграции веб-отчётов прямо во вкладки сборки, настраивается неприлично легко и вот, ура! результаты видны непосредственно в вебе, что гораздо приятнее.
Но всё-таки не идеально, ведь за результатами надо ещё и следить, а ну как кто набажит в новых коммитах, а никто не увидит? И вот тут-то мы и подбираемся к самому вкусному. На самом деле Тимсити умеет работать с выводом анализаторов кода, то есть, ему можно показать ошибки, а он будет вести их учёт, а раз он будет понимать, сколько там каких ошибок, он сможет, в том числе, реагировать на изменения показателей, например, считать сборку неуспешной при увеличении количества ошибок.
И всё бы хорошо, но, разумеется, в списке форматов, поддерживаемых Тимсити, нет Сиппчека. Однако, Сиппчек умеет выдавать ИксЭмЭль. И все прочие инструменты анализа, которые понимает Тимсити, тоже выдают ИксЭмЭль. Многие ИксЭмЭль почему-то не любят, а зря, потому что как раз для такого случая много лет назад придуман ИксСЛТ, позволяющий из исходного документа получить примерно всё, что угодно, причём, относительно недорого. В нашем случае из одного ИксЭмЭля другой.
В качестве целевого формата я выбрал Чекстайл, выбор ничем особым не обоснован, кроме того, что он мне показался наиболее простым и понятным (с документацией на эти форматы, кстати, не очень-то хорошо, хотя, казалось бы). В итоге, мне довольно быстро удалось соорудить конвертилку из сиппчекового формата в чекстайловый, выглядела она так:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="UTF-8" indent="yes" method="xml"></xsl:output> <xsl:template match="/"> <checkstyle version="1.67"> <xsl:for-each-group select="results/error" group-by="@file"> <file> <xsl:attribute name="name"> <xsl:value-of select="current-grouping-key()"/> </xsl:attribute> <xsl:for-each select="current-group()"> <error line="{@line}" message="{@msg}" severity="{@severity}" source="{@id}" /> </xsl:for-each> </file> </xsl:for-each-group> </checkstyle> </xsl:template> </xsl:stylesheet>
Но это больше для истории, так как по ошибке я взялся за первую версию иксэмэльного вывода самого Сиппчека, в норме, конечно, ориентироваться надо на вторую. Но и она несложна, буквально вот так преобразуется:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="UTF-8" indent="yes" method="xml"></xsl:output> <xsl:template match="/"> <checkstyle> <xsl:attribute name="version"> <xsl:value-of select="results/cppcheck[@version]"/> </xsl:attribute> <xsl:for-each-group select="results/errors/error" group-by="location/@file"> <file> <xsl:attribute name="name"> <xsl:value-of select="current-grouping-key()"/> </xsl:attribute> <xsl:for-each select="current-group()"> <error line="{location/@line}" message="{@msg}" severity="{@severity}" source="{@id}" /> </xsl:for-each> </file> </xsl:for-each-group> </checkstyle> </xsl:template> </xsl:stylesheet>
Единственный нюанс в том, что здесь используется стандарт XSLT 2.0, а как раз его совершенно не знает xsltproc, поэтому приходится работать через Саксон, выглядит это примерно так:
$ cppcheck --enable=all --xml --xml-version=2 . 2>cppcheck-report.xml $ saxonb-xslt cppcheck-report.xml cppcheck-2-to-checkstyle.xslt >cppcheck-checkstyle.xml
Полученный cppcheck-checkstyle.xml отдаётся на съедение Тимсити, а далее появляются симпатичные счётчики и возможность ронять сборку при их увеличении, чего изначально и хотелось.