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

Особенно когда дело доходит до Scala, у нас также есть хороший репозиторий самодельных шаблонов. Поэтому нам нужно иметь возможность обрабатывать исходный код Scala. И под обработкой мы в основном подразумеваем преобразование исходного кода в абстрактные синтаксические деревья (AST).

Все, что вы здесь найдете, вы можете попробовать сами в репл. Обязательно добавьте следующие преобразователь и зависимости sbt

https://gist.github.com/johannegger/3226587d5ce3e66a8ad1

(Еще не устарело) scala.reflect

До сих пор мы использовали стандартный scala.reflect.api и предоставляемый им набор инструментов. Чтобы разобрать scala-код с помощью набора инструментов отражения, нам нужно запустить следующее:

https://gist.github.com/johannegger/ecc4c5a89f9363764046

Результирующая древовидная переменная имеет тип toolbox.u.Tree, и это структура, которую мы используем (d) для поиска проблемного кода. Вы могли бы сказать, что это не выглядит слишком сложным. Вы правы, но проблемы начинаются здесь. К сожалению, эти деревья очень сложны (в конце концов, они представляют собой полный AST вашей программы). Также скудная документация — как автору паттернов мне приходилось полагаться в основном на Scaladoc и частично на Reflection.

Примечание: файлы .scala в реальной жизни обычно находятся в пакетах, что означает, что типичный исходный файл будет начинаться с пакета foo... Однако текущая реализация набора инструментов не способна анализировать такие файлы. Мы были вынуждены реализовать обходной путь, который с тех пор не давал мне покоя.

Все это на самом деле не позволяет тому, кто не знает внутренностей scala.reflect.api, начать писать шаблоны с нуля. Но это именно то, что мы хотим. Мы хотим, чтобы наши пользователи могли создавать собственные шаблоны для своих задач.

scala.meta в помощь

Недавно у нас началось очень многообещающее сотрудничество с Еженем Бурмако и Матье Демарном из scala.meta. scala.meta был создан для упрощения метапрограммирования в scala и, надеюсь, станет преемником текущего scala.reflect. Для нас это уже есть. Попробуем получить scala.meta.Tree

https://gist.github.com/johannegger/6467eae9b1feb1be0e2b

И это все. (Теперь попробуйте разобрать правильный файл .scala, содержащий определение пакета — предупреждение о спойлере: это работает!) Но это еще не все, в scala.meta.tql мы находим аккуратный древовидный язык запросов, который помогает нам писать шаблоны. Давайте попробуем реализовать шаблон, который находит появление блоков try-catch. (На кодировках можно прочитать, почему их не стоит использовать)

https://gist.github.com/johannegger/051a6c125b00c412951f

Теперь мы можем передавать деревья в tryMatcher, давайте просто попробуем простой тестовый код:

https://gist.github.com/johannegger/c15090d300eea1f49365

И вуаля — реплика не врет — «виновник найден в строке 0»

Следите за новостями о будущем scala.meta на Codacy.

Редактировать: мы только что опубликовали электронную книгу The Ultimate Guide to Code Review на основе опроса 680+ разработчиков. Наслаждаться!

О кодировании

Codacy используется тысячами разработчиков для ежедневного анализа миллиардов строк кода!

Начать легко — и бесплатно! Просто используйте свою учетную запись GitHub, Bitbucket или Google для регистрации.

"НАЧАТЬ"

Первоначально опубликовано на странице https://www.codacy.com/blog/a-quick-look-at-scala-meta/ 4 июня 2015 г.