Подтвердить что ты не робот

Scala Презентационный компилятор - минимальный пример

Может ли кто-нибудь предоставить минимальный пример использования текущего компилятора презентаций scala (т.е. scala.tools.nsc.interactive.Global), который выполняет следующие задачи?

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

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

4b9b3361

Ответ 1

Хорошо, одна неделя из 100 щедрот и до сих пор нет ответов, поэтому я попробую сам... Редактирование очень приветствуется!

Ключевым классом для компилятора представления является scala.tools.nsc.interactive.Global. Поэтому для начала нам нужно создать экземпляр компилятора.

import scala.tools.nsc.interactive.Global 
class PresentationCompiler {  // мы хотим, чтобы выход компилятора был виртуальным  val target = новый VirtualDirectory ( ", None)
 // необходимо настроить для работы с  //sbt. См. этот вопрос.  val settings = new Настройки()  // вывод на виртуальную цель  settings.outputDirs.setSingleOutput(цель)
 // может быть заменен специальным экземпляром  //AbstractReporter для получения контроля.  val reporter = new ConsoleReporter (настройки)
 val compiler = new Глобальный (настройки, репортер)
 ... }

Для настроек ссылка, предоставленная Abhishek, очень ценна.

Но теперь для интересной части:

1. скомпилировать один виртуальный исходный файл

Чтобы скомпилировать String, существует возможность создать BatchSourceFile с базовым VirtualFile. Здесь api отмечен экспериментально и кажется неоднородным.

def compile(code: String) {
  val source = new BatchSourceFile("<virtual>", code)
  val response = new Response[Unit]
  compiler.askReload(List(source), response)    
  response.get.left.foreach { _ =>
    // success
  }
}

2. получить полученную информацию для всех фаз из компилятора

Это сложная часть. Из-за многопоточной природы компилятора и того факта, что флаги повторно используются с разными значениями в разных фазах, невозможно сразу получить все сразу. В основном вам придется прибегнуть к методам askSomething, которые описаны в API. Например:

val tcompletion = new Response[List[global.Member]]      
val pos = compiler.ask(() => new OffsetPosition(source, p))
global.askTypeCompletion(pos, tcompletion)
tcompletion.get(5000).get match {
  case Left(members) => // do something with members
  case Right(e) =>
    e.printStackTrace
}

3. распространить изменение исходного файла на компилятор

Это интересная часть, о которой я хотел узнать по этому вопросу. Я действительно не понимаю этого, потому что BatchSourceFile описывается как файл, содержимое которого не изменяется со временем. Таким образом, потребуется выполнить пользовательскую реализацию SourceFile? Почему это не должно быть в пакете interactive. Я уверен, что я просто ничего не поймал.

Итак, теперь мое решение - снова вызвать метод компиляции.

Ответ 3

Не может быть именно то, что вы ищете, но одним из способов сделать это может быть:

  • напишите источник, который хотите скомпилировать во временный файл,

  • запустите компиляцию, суффиксирующую оператор > output.tmp (* nix) команде, которая должна выводить вывод компилятора в файл,

  • прочитайте этот файл и загрузите его в память...

  • и вы должны удалить оба файла tmp.

Я надеюсь, что это не единственное решение, но в случае, если ничего другого не возможно, по крайней мере это должно сработать...