В 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 г.