Можно ли при проверке кода внутри макроса обнаружить ошибку проверки типов, вызванную раскрытием макроса в этом коде?

Я хотел бы написать макрос, который компилирует код, который он получает как литерал String, и обнаруживает ошибку проверки типа в скомпилированном коде, которая возникает из-за сбоя расширения макроса (либо макрос был прерван, либо расширенный макрос не удалось проверить тип)

Я думал примерно так:

def myMacro(c: Context)(codeStringLiteral: c.Expr[String]): c.Expr[Unit] = {
    val codeString = getString(codeStringLiteral) // this part is easy
    val ast = c.parse(code)
    val actualCode = util.Try(c.typecheck(ast)).recover{ case t: TypecheckException =>
      if(t.isMacroExpansionFailure) doOneThing
      else doOtherThing
    }
    c.Expr(actualCode.get)
}

Это возможно?

Контекст

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

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

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


person jedesah    schedule 13.04.2015    source источник
comment
Это не то, о чем вы просите, но вы можете посмотреть на illTyped Shapeless для примера общего подхода.   -  person Travis Brown    schedule 13.04.2015


Ответы (1)


Для c.typecheck есть неясный флаг, который называется withMacrosDisabled. Если вы передадите туда true, это должно помешать раскрытию любого макроса. Теперь вы можете сравнить статус c.typecheck(withMacrosDisabled = false) и c.typecheck(withMacrosDisabled = true) и выполнить отправку соответственно.

Это не сработает для макросов белого ящика, потому что withMacrosDisabled = false может создать законный код, используя макросы белого ящика, чтобы не выполнить проверку типов, но для макросов черного ящика это должно быть более или менее нормально.

person Eugene Burmako    schedule 13.04.2015
comment
Но мое намерение состоит в том, чтобы выяснить, виноват ли макрос в ошибке проверки типов. c.typecheck(withMacrosDisabled = true) только сообщает мне, есть ли макрос в коде или нет (предположительно, в основном он есть, поскольку цель этого макроса - помочь протестировать другие макросы). Затем c.typecheck(withMacrosDisabled = false) затем только говорит мне, где все это проверяет тип или нет. Я что-то пропустил? - person jedesah; 13.04.2015
comment
Действительно, withMacrosDisabled не будет расширять макросы, но не приведет к сбою проверки типов, если в коде есть макросы. Если макрос черный ящик, то его можно проверить обычным методом, ничего не расширяя, что и сделает withMacrosDisabled. - person Eugene Burmako; 14.04.2015
comment
О, спасибо за уточнение! Я неправильно предположил, что он будет вести себя иначе. Да, я верю, что тогда это могло бы сработать. - person jedesah; 15.04.2015