-
Notifications
You must be signed in to change notification settings - Fork 121
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for VirtualFile in Scala 3
This commit add support for `VirtualFiles`, that has recently been added to Zinc, to the `scala3-compiler-bridge`. It fixes a bug that was reported in sbt/sbt#6007. Also it fixes a bug in the bug in the returned `CompileAnalysis` by populating the `SourceInfos`. The reported warnings were not returned back in `sbt-dotty` after a succefull compilation.
- Loading branch information
Showing
6 changed files
with
196 additions
and
85 deletions.
There are no files selected for viewing
41 changes: 41 additions & 0 deletions
41
internal/scala3-compiler-bridge/src/main/scala/xsbt/AbstractZincFile.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* Zinc - The incremental compiler for Scala. | ||
* Copyright Lightbend, Inc. and Mark Harrah | ||
* | ||
* Licensed under Apache License 2.0 | ||
* (http://www.apache.org/licenses/LICENSE-2.0). | ||
* | ||
* See the NOTICE file distributed with this work for | ||
* additional information regarding copyright ownership. | ||
*/ | ||
|
||
package xsbt | ||
|
||
import xsbti.{ PathBasedFile, VirtualFile } | ||
import dotty.tools.io | ||
|
||
private trait AbstractZincFile extends io.AbstractFile { | ||
def underlying: VirtualFile | ||
} | ||
|
||
private final class ZincPlainFile(val underlying: PathBasedFile) | ||
extends io.PlainFile(io.Path(underlying.toPath)) | ||
with AbstractZincFile | ||
|
||
private final class ZincVirtualFile(val underlying: VirtualFile) | ||
extends io.VirtualFile(underlying.name, underlying.id) | ||
with AbstractZincFile { | ||
io.Streamable.closing(output)(_.write(io.Streamable.bytes(underlying.input))) // fill in the content | ||
} | ||
|
||
private object AbstractZincFile { | ||
def apply(virtualFile: VirtualFile): AbstractZincFile = virtualFile match { | ||
case file: PathBasedFile => new ZincPlainFile(file) | ||
case _ => new ZincVirtualFile(virtualFile) | ||
} | ||
|
||
def unapply(file: io.AbstractFile): Option[VirtualFile] = file match { | ||
case wrapper: AbstractZincFile => Some(wrapper.underlying) | ||
case _ => None | ||
} | ||
} |
120 changes: 120 additions & 0 deletions
120
internal/scala3-compiler-bridge/src/main/scala/xsbt/CachedCompilerImpl.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* | ||
* Zinc - The incremental compiler for Scala. | ||
* Copyright Lightbend, Inc. and Mark Harrah | ||
* | ||
* Licensed under Apache License 2.0 | ||
* (http://www.apache.org/licenses/LICENSE-2.0). | ||
* | ||
* See the NOTICE file distributed with this work for | ||
* additional information regarding copyright ownership. | ||
*/ | ||
|
||
package xsbt | ||
|
||
import dotty.tools.dotc.Driver | ||
import dotty.tools.dotc.config.{Properties, Settings} | ||
import dotty.tools.dotc.core.Contexts.Context | ||
import dotty.tools.dotc.util.SourceFile | ||
import xsbt.Log.debug | ||
import xsbti.{ AnalysisCallback, Logger, Problem, Reporter } | ||
import xsbti.compile.{ Output, SingleOutput } | ||
|
||
private final class CachedCompilerImpl( | ||
options: Array[String], | ||
output: Output | ||
) extends Driver { | ||
private val args = output match { | ||
case output: SingleOutput => | ||
options ++ Seq("-d", output.getOutputDirectoryAsPath.toString) | ||
case _ => | ||
throw new IllegalArgumentException( | ||
s"output should be a SingleOutput, was a ${output.getClass.getName}" | ||
) | ||
} | ||
|
||
/** | ||
* `sourcesRequired` is set to false because `args` do not contain the sources | ||
* The sources are passed programmatically to the Scala 3 compiler | ||
*/ | ||
override def sourcesRequired: Boolean = false | ||
|
||
def run( | ||
sources: List[SourceFile], | ||
callback: AnalysisCallback, | ||
log: Logger, | ||
delegate: Reporter, | ||
): Unit = synchronized { | ||
val reporter = new DelegatingReporter(delegate) | ||
|
||
try { | ||
debug(log, infoOnCachedCompiler) | ||
|
||
val initialCtx = initCtx.fresh | ||
.setReporter(reporter) | ||
.setSbtCallback(callback) | ||
|
||
given Context = setup(args,initialCtx)(1) | ||
|
||
if (shouldStopWithInfo) { | ||
throw new InterfaceCompileFailed(options, Array(), StopInfoError) | ||
} | ||
|
||
val isCancelled = | ||
if (!delegate.hasErrors) { | ||
debug(log, prettyPrintCompilationArguments) | ||
val run = newCompiler.newRun | ||
run.compileSources(sources) | ||
// allConditionalWarning is not available in Scala 3 | ||
// processUnreportedWarnings(run) | ||
delegate.problems.foreach( | ||
p => callback.problem(p.category, p.position, p.message, p.severity, true) | ||
) | ||
|
||
run.isCancelled | ||
} else false | ||
|
||
delegate.printSummary() | ||
|
||
if (delegate.hasErrors) { | ||
debug(log, "Compilation failed (CompilerInterface)") | ||
throw new InterfaceCompileFailed(args, delegate.problems, "Compilation failed") | ||
} | ||
|
||
// the case where we cancelled compilation _after_ some compilation errors got reported | ||
// will be handled by line above so errors still will be reported properly just potentially not | ||
// all of them (because we cancelled the compilation) | ||
if (isCancelled) { | ||
debug(log, "Compilation cancelled (CompilerInterface)") | ||
throw new InterfaceCompileCancelled(args, "Compilation has been cancelled") | ||
} | ||
} finally { | ||
reporter.dropDelegate() | ||
} | ||
} | ||
|
||
private def shouldStopWithInfo(using ctx: Context) = { | ||
val settings = ctx.settings | ||
import settings._ | ||
Set(help, Xhelp, Yhelp, showPlugins, XshowPhases).exists(_.value(using ctx)) | ||
} | ||
|
||
private val StopInfoError: String = | ||
"Compiler option supplied that disabled Zinc compilation." | ||
|
||
private def infoOnCachedCompiler: String = { | ||
val compilerId = hashCode().toLong.toHexString | ||
s"[zinc] Running cached compiler $compilerId for Scala compiler ${Properties.versionString}" | ||
} | ||
|
||
private def prettyPrintCompilationArguments = | ||
options.mkString("[zinc] The Scala compiler is invoked with:\n\t", "\n\t", "") | ||
} | ||
|
||
class InterfaceCompileFailed( | ||
val arguments: Array[String], | ||
val problems: Array[Problem], | ||
override val toString: String | ||
) extends xsbti.CompileFailed | ||
|
||
class InterfaceCompileCancelled(val arguments: Array[String], override val toString: String) | ||
extends xsbti.CompileCancelled |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters