in sbt/sbt-impl/src/org/jetbrains/sbt/actions/SbtGenerateManagedSourcesAction.scala [30:199]
override def actionPerformed(e: AnActionEvent): Unit = {
val project = e.getProject
val task = new Task.Backgroundable(project, SbtBundle.message("sbt.generate.managed.sources.task.progress.title"), true) {
override def run(indicator: ProgressIndicator): Unit = {
val viewManager = project.getService(classOf[SyncViewManager])
val taskId = ExternalSystemTaskId.create(SbtProjectSystem.Id, ExternalSystemTaskType.EXECUTE_TASK, project)
val reporter = new GenerateManagedSourcesReporter()
val settings = SbtExternalSystemManager.executionSettingsFor(project)
val projectBasePath = Path.of(settings.realProjectPath)
val descriptor = new DefaultBuildDescriptor(taskId, SbtBundle.message("sbt.generate.managed.sources.action.title"), projectBasePath.toString, System.currentTimeMillis())
descriptor.setActivateToolWindowWhenAdded(false)
descriptor.setActivateToolWindowWhenFailed(true)
{
val event = BuildEvents.getInstance().startBuild()
.withBuildDescriptor(descriptor)
.withMessage(SbtBundle.message("sbt.generate.managed.sources.action.title"))
.build()
viewManager.onEvent(taskId, event)
}
def reportFailure(@Nullable throwable: Throwable): Unit = {
{
val sbtOutput = reporter.outputLines.mkString(start = "", sep = System.lineSeparator(), end = System.lineSeparator())
val event = BuildEvents.getInstance().output()
.withId(taskId)
.withMessage(sbtOutput)
.withOutputType(ProcessOutputType.STDOUT)
.build()
viewManager.onEvent(taskId, event)
}
{
val failureWord = SbtBundle.message("sbt.generate.managed.sources.task.result.failure")
val failureMessage = SbtBundle.message("sbt.generate.managed.sources.task.result.failure.message")
val failureResult = new FailureResultImpl(failureMessage, throwable)
val events = BuildEvents.getInstance().finishBuild()
.withStartBuildId(taskId)
.withTime(System.currentTimeMillis())
.withMessage(failureWord)
.withResult(failureResult)
.build()
viewManager.onEvent(taskId, events)
}
}
try {
val launcher = SbtUtil.getLauncherJar(settings)
val sbtVersion = SbtUtil.detectSbtVersion(projectBasePath, launcher)
val sbtStructurePluginBinVersion = SbtUtil.structurePluginBinaryVersion(sbtVersion)
val addPluginCommandSupported = SbtVersionCapabilities.isAddPluginCommandSupported(sbtVersion)
if (!addPluginCommandSupported) {
val notSupportedWord = SbtBundle.message("sbt.generate.managed.sources.action.not.supported")
val notSupportedMessage = SbtBundle.message("sbt.generate.managed.sources.action.not.supported.message", sbtVersion.minor)
val failureResult = new FailureResultImpl(notSupportedMessage)
val finishEvent = BuildEvents.getInstance().finishBuild()
.withStartBuildId(taskId)
.withTime(System.currentTimeMillis())
.withMessage(notSupportedWord)
.withResult(failureResult)
.build()
viewManager.onEvent(taskId, finishEvent)
return
}
val repoPath = SbtUtil.normalizePath(SbtUtil.getRepoDir)
val pluginsSbt =
raw"""resolvers += MavenCache("Scala Plugin Bundled Repository", file(raw"$repoPath"))
|
|addSbtPlugin("org.jetbrains.scala" % "sbt-structure-extractor" % "${BuildInfo.sbtStructureVersion}", "$sbtStructurePluginBinVersion")
|""".stripMargin
val tmpPluginsSbtFile = Files.createTempFile("idea-gen-managed-sources", ".sbt")
Files.writeString(tmpPluginsSbtFile, pluginsSbt)
val setupOptions = Seq(s"-addPluginSbtFile=${tmpPluginsSbtFile.toRealPath()}")
tmpPluginsSbtFile.toFile.deleteOnExit()
val generateCommand = "show " + SbtUtil.sbtStructureGlobalCommand("ideaGenerateAllManagedSources", sbtVersion)
val sbtResult = new SbtStructureDump().runSbt(
indicator,
projectBasePath,
settings.vmExecutable.toPath,
settings.vmOptions,
settings.userSetEnvironment,
launcher,
settings.sbtOptions,
setupOptions,
generateCommand,
SbtBundle.message("sbt.generate.managed.sources.task.progress.title"),
settings.passParentEnvironment,
)(using reporter)
sbtResult match {
case Success(buildMessages) if buildMessages.status == BuildMessages.Error => reportFailure(null)
case Success(buildMessages) if buildMessages.status == BuildMessages.Canceled =>
{
val canceledMessage = SbtBundle.message("sbt.generate.managed.sources.task.result.canceled.message")
val event = BuildEvents.getInstance().output()
.withId(taskId)
.withMessage(canceledMessage)
.withOutputType(ProcessOutputType.STDOUT)
.build()
viewManager.onEvent(taskId, event)
}
{
val canceledWord = SbtBundle.message("sbt.generate.managed.sources.task.result.canceled")
val finishEvent = BuildEvents.getInstance().finishBuild()
.withStartBuildId(taskId)
.withTime(System.currentTimeMillis())
.withMessage(canceledWord)
.withResult(new SkippedResultImpl())
.build()
viewManager.onEvent(taskId, finishEvent)
}
case Success(_) =>
val lines = reporter.outputLines
val containsErrors = lines.exists(_.startsWith("[error]"))
if (containsErrors) {
reportFailure(null)
} else {
try {
def realFile(path: Path): Boolean = Files.exists(path) && Files.isRegularFile(path)
val generatedSources = lines.collect { case s"[info] * $path" => path }
.flatMap(path => Try(Path.of(path).toRealPath()).filter(realFile).toOption)
val fileManager = VirtualFileManager.getInstance()
val virtualFiles = generatedSources.flatMap(p => Option(fileManager.refreshAndFindFileByNioPath(p)))
VfsUtil.markDirtyAndRefresh(false, false, true, virtualFiles*)
{
val output = lines.mkString(start = "", sep = System.lineSeparator(), end = System.lineSeparator())
val event = BuildEvents.getInstance().output()
.withId(taskId)
.withMessage(output)
.withOutputType(ProcessOutputType.STDOUT)
.build()
viewManager.onEvent(taskId, event)
}
{
val successEvent = BuildEvents.getInstance().finishBuild()
.withStartBuildId(taskId)
.withTime(System.currentTimeMillis())
.withMessage(SbtBundle.message("sbt.generate.managed.sources.task.result.success"))
.withResult(new SuccessResultImpl())
.build()
viewManager.onEvent(taskId, successEvent)
}
} catch {
case NonFatal(t) => reportFailure(t)
}
}
case Failure(exception) => reportFailure(exception)
}
} catch {
case NonFatal(t) => reportFailure(t)
}
}
}
// Make sure all modified files are saved to disk before invoking sbt.
FileDocumentManager.getInstance().saveAllDocuments()
task.queue()
}