diff --git a/build.sbt b/build.sbt index 5b82036c4c..4a002bbbc7 100644 --- a/build.sbt +++ b/build.sbt @@ -1,4 +1,4 @@ -import Util._ +import ZincBuildUtil._ import Dependencies._ import localzinc.Scripted, Scripted._ import com.typesafe.tools.mima.core._, ProblemFilters._ @@ -82,6 +82,8 @@ Global / concurrentRestrictions += Tags.limit(Tags.Test, 4) // Global / semanticdbVersion := "4.5.9" ThisBuild / Test / fork := true Global / excludeLintKeys += ideSkipProject +Global / resolvers += "scala-integration" at + "https://scala-ci.typesafe.com/artifactory/scala-integration/" def baseSettings: Seq[Setting[_]] = Seq( testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1", "-verbosity", "2"), @@ -131,6 +133,7 @@ def addBaseSettingsAndTestDeps(p: Project): Project = // zincRoot is now only 2.12 (2.11.x is not supported anymore) lazy val aggregated: Seq[ProjectReference] = compilerInterface.projectRefs ++ compilerBridge.projectRefs ++ + Seq(compilerBridge213_next: ProjectReference) ++ zincApiInfo.projectRefs ++ zincBenchmarks.projectRefs ++ zincClasspath.projectRefs ++ @@ -195,6 +198,13 @@ lazy val zinc = (projectMatrix in (zincRootPath / "zinc")) BuildInfoKey.map(compilerBridge213 / scalaVersion)("scalaVersion213" -> _._2), BuildInfoKey.map(compilerBridge213 / scalaInstance)("scalaJars213" -> _._2.allJars.toList), BuildInfoKey.map(compilerBridge213 / Compile / classDirectory)("classDirectory213" -> _._2), + BuildInfoKey.map(compilerBridge213_next / scalaVersion)("scalaVersion213_next" -> _._2), + BuildInfoKey.map(compilerBridge213_next / scalaInstance)( + "scalaJars213_next" -> _._2.allJars.toList + ), + BuildInfoKey.map(compilerBridge213_next / Compile / classDirectory)( + "classDirectory213_next" -> _._2 + ), ), Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat, // so we have full access to com.sun.tools.javac on JDK 17 @@ -280,7 +290,7 @@ lazy val zincPersist = (projectMatrix in internalPath / "zinc-persist") }), Test / classLoaderLayeringStrategy := ClassLoaderLayeringStrategy.Flat, mimaSettings, - mimaBinaryIssueFilters ++= Util.excludeInternalProblems, + mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, mimaBinaryIssueFilters ++= Seq( exclude[IncompatibleMethTypeProblem]("xsbti.*"), exclude[ReversedMissingMethodProblem]("xsbti.*"), @@ -363,7 +373,7 @@ lazy val zincCore = (projectMatrix in internalPath / "zinc-core") name := "zinc Core", compileOrder := sbt.CompileOrder.Mixed, mimaSettings, - mimaBinaryIssueFilters ++= Util.excludeInternalProblems, + mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, mimaBinaryIssueFilters ++= Seq( exclude[IncompatibleMethTypeProblem]("xsbti.*"), exclude[ReversedMissingMethodProblem]("xsbti.*"), @@ -432,7 +442,7 @@ lazy val zincCompileCore = (projectMatrix in internalPath / "zinc-compile-core") Compile / managedSourceDirectories += (Compile / generateContrabands / sourceManaged).value, Compile / generateContrabands / sourceManaged := (internalPath / "zinc-compile-core" / "src" / "main" / "contraband-java").getAbsoluteFile, mimaSettings, - mimaBinaryIssueFilters ++= Util.excludeInternalProblems, + mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, ) .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) .jvmPlatform(scalaVersions = List(scala212, scala213)) @@ -539,6 +549,30 @@ lazy val compilerBridge211 = compilerBridge.jvm(scala211) lazy val compilerBridge212 = compilerBridge.jvm(scala212) lazy val compilerBridge213 = compilerBridge.jvm(scala213) +lazy val compilerBridge213_next = (project in (file(".sbt") / "matrix" / "compilerBridge2_13_next")) + .dependsOn(compilerInterface.jvm(false)) + .settings( + scalaVersion := scala213_next, + autoScalaLibrary := false, + baseSettings, + compilerVersionDependentScalacOptions, + // We need this for import Compat._ + Compile / scalacOptions --= Seq("-Ywarn-unused-import", "-Xfatal-warnings"), + libraryDependencies += scalaCompiler.value % "provided", + exportJars := true, + Compile / unmanagedResourceDirectories ++= (compilerBridge213 / Compile / unmanagedResourceDirectories).value, + Compile / unmanagedSourceDirectories ++= (compilerBridge213 / Compile / unmanagedSourceDirectories).value, + Compile / sources := { + val xs = (Compile / sources).value + (xs.filterNot { x => x.getName() == "DelegatingReporter.scala" }) ++ + Seq( + (compilerBridge213 / Compile / scalaSource).value.getParentFile() / "resources" / "scala-2.13.12" / "DelegatingReporter.scala" + ) + }, + publishLocal / skip := false, + publish / skip := true, + ) + /** * Tests for the compiler bridge. * This is split into a separate subproject because testing introduces more dependencies @@ -656,7 +690,7 @@ lazy val zincClassfile = (projectMatrix in internalPath / "zinc-classfile") exclude[IncompatibleResultTypeProblem]("sbt.internal.inc.IndexBasedZipOps.*"), exclude[ReversedMissingMethodProblem]("sbt.internal.inc.IndexBasedZipOps.*"), ), - mimaBinaryIssueFilters ++= Util.excludeInternalProblems, + mimaBinaryIssueFilters ++= ZincBuildUtil.excludeInternalProblems, ) .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) .jvmPlatform(scalaVersions = scala212_213) @@ -680,7 +714,12 @@ lazy val zincScripted = (projectMatrix in internalPath / "zinc-scripted") .defaultAxes(VirtualAxis.jvm, VirtualAxis.scalaPartialVersion(scala212)) .jvmPlatform(scalaVersions = List(scala212)) .configure( - _.dependsOn(compilerBridge210, compilerBridge211, compilerBridge212, compilerBridge213) + _.dependsOn( + compilerBridge210, + compilerBridge211, + compilerBridge212, + compilerBridge213, + ) ) .configure(addSbtUtilScripted) @@ -688,13 +727,18 @@ lazy val zincScripted212 = zincScripted.jvm(scala212) def bridges = { if (sys.props("java.specification.version") == "1.8") { - List(compilerBridge210 / publishLocal, compilerBridge211 / publishLocal) + List( + compilerBridge210 / publishLocal, + compilerBridge211 / publishLocal, + compilerBridge213_next / publishLocal, + ) } else { List( compilerBridge210 / publishLocal, compilerBridge211 / publishLocal, compilerBridge212 / publishLocal, compilerBridge213 / publishLocal, + compilerBridge213_next / publishLocal, ) } } @@ -703,7 +747,8 @@ val publishBridges = taskKey[Unit]("") val crossTestBridges = taskKey[Unit]("") publishBridges := Def.task(()).dependsOn(bridges: _*).value -crossTestBridges := (compilerBridgeTest / Test / test).dependsOn(publishBridges).value +crossTestBridges := (compilerBridgeTest / Test / test) + .dependsOn(publishBridges).value addCommandAlias( "runBenchmarks", { diff --git a/internal/compiler-bridge/src/main/resources/scala-2.13.12/DelegatingReporter.scala b/internal/compiler-bridge/src/main/resources/scala-2.13.12/DelegatingReporter.scala new file mode 100644 index 0000000000..4715119ad9 --- /dev/null +++ b/internal/compiler-bridge/src/main/resources/scala-2.13.12/DelegatingReporter.scala @@ -0,0 +1,352 @@ +/* + * Zinc - The incremental compiler for Scala. + * Copyright Scala Center, Lightbend, and Mark Harrah + * + * Licensed under Apache License 2.0 + * SPDX-License-Identifier: Apache-2.0 + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package xsbt + +import java.io.File +import java.{ util => ju } +import ju.Optional + +import scala.reflect.internal.util.{ CodeAction, FakePos, NoPosition, Position } +import scala.collection.JavaConverters._ +import scala.reflect.io.AbstractFile +import xsbti.{ + Action, + DiagnosticCode => XDiagnosticCode, + DiagnosticRelatedInformation => XDiagnosticRelatedInformation, + Problem => XProblem, + Position => XPosition, + Severity => XSeverity, + TextEdit, + WorkspaceEdit +} + +/** + * This implements reporter/ concrete Problem data structure for + * the compiler bridge, in other words for each Scala versions + * that Zinc is capable of compiling. + * + * There's also sbt.util.InterfaceUtil, which is also used in + * Zinc in the Scala version Zinc uses. + */ +private object DelegatingReporter { + def apply(settings: scala.tools.nsc.Settings, delegate: xsbti.Reporter): DelegatingReporter = + new DelegatingReporter(settings.fatalWarnings.value, settings.nowarn.value, delegate) + + class PositionImpl( + sourcePath0: Option[String], + sourceFile0: Option[File], + line0: Option[Int], + lineContent0: String, + offset0: Option[Int], + pointer0: Option[Int], + pointerSpace0: Option[String], + startOffset0: Option[Int], + endOffset0: Option[Int], + startLine0: Option[Int], + startColumn0: Option[Int], + endLine0: Option[Int], + endColumn0: Option[Int] + ) extends xsbti.Position { + val line = o2oi(line0) + val lineContent = lineContent0 + val offset = o2oi(offset0) + val sourcePath = o2jo(sourcePath0) + val sourceFile = o2jo(sourceFile0) + val pointer = o2oi(pointer0) + val pointerSpace = o2jo(pointerSpace0) + override val startOffset = o2oi(startOffset0) + override val endOffset = o2oi(endOffset0) + override val startLine = o2oi(startLine0) + override val startColumn = o2oi(startColumn0) + override val endLine = o2oi(endLine0) + override val endColumn = o2oi(endColumn0) + override def toString = + (sourcePath0, line0) match { + case (Some(s), Some(l)) => s + ":" + l + case (Some(s), _) => s + ":" + case _ => "" + } + } + + object PositionImpl { + def empty: PositionImpl = + new PositionImpl(None, None, None, "", None, None, None, None, None, None, None, None, None) + } + + import java.lang.{ Integer => I } + private[xsbt] def o2oi(opt: Option[Int]): Optional[I] = { + opt match { + case Some(s) => Optional.ofNullable[I](s: I) + case None => Optional.empty[I] + } + } + + private[xsbt] def o2jo[A](o: Option[A]): Optional[A] = { + o match { + case Some(v) => Optional.ofNullable(v) + case None => Optional.empty[A]() + } + } + + private[xsbt] def l2jl[A](l: List[A]): ju.List[A] = { + val jl = new ju.ArrayList[A](l.size) + l.foreach(jl.add(_)) + jl + } + + private[xsbt] def jl2l[A](jl: ju.List[A]): List[A] = { + jl.asScala.toList + } + + private[xsbt] def convert(dirtyPos: Position): xsbti.Position = { + def cleanPos(pos: Position) = { + Option(pos) match { + case None | Some(NoPosition) => None + case Some(_: FakePos) => None + case _ => Option(pos.finalPosition) + } + } + + def makePosition(pos: Position): xsbti.Position = { + val src = pos.source + val sourcePath = src.file match { + case AbstractZincFile(virtualFile) => virtualFile.id + case af: AbstractFile => af.path + } + val sourceFile = new File(src.file.path) + val line = pos.line + val lineContent = pos.lineContent.stripLineEnd + val offset = pos.point + + // Same logic as Position#line + def lineOf(offset: Int) = src.offsetToLine(offset) + 1 + def columnOf(offset: Int) = offset - src.lineToOffset(src.offsetToLine(offset)) + + val pointer = columnOf(offset) + val pointerSpace = lineContent.toList.take(pointer).map { + case '\t' => '\t' + case _ => ' ' + } + + val startOffset = if (pos.isRange) Some(pos.start) else None + val endOffset = if (pos.isRange) Some(pos.end) else None + val startLine = if (pos.isRange) Some(lineOf(pos.start)) else None + val startColumn = if (pos.isRange) Some(columnOf(pos.start)) else None + val endLine = + if (pos.isRange) + try { + Some(lineOf(pos.end)) + } catch { + // work around for https://github.com/scala/bug/issues/11865 by falling back to start pos + case _: ArrayIndexOutOfBoundsException => + startLine + } + else None + val endColumn = + if (pos.isRange) + try { + Some(columnOf(pos.end)) + } catch { + // work around for https://github.com/scala/bug/issues/11865 by falling back to start pos + case _: ArrayIndexOutOfBoundsException => + startColumn + } + else None + + new PositionImpl( + Option(sourcePath), + Option(sourceFile), + Option(line), + lineContent, + Option(offset), + Option(pointer), + Option(pointerSpace.mkString), + startOffset, + endOffset, + startLine, + startColumn, + endLine, + endColumn + ) + } + + cleanPos(dirtyPos) match { + case None => PositionImpl.empty + case Some(cleanPos) => makePosition(cleanPos) + } + } +} + +// Copyright 2002-2009 LAMP/EPFL +// Original author: Martin Odersky +// Based on scala.tools.nsc.reporters.{AbstractReporter, ConsoleReporter} +private final class DelegatingReporter( + warnFatal: Boolean, + noWarn: Boolean, + private[this] var delegate: xsbti.Reporter +) extends scala.tools.nsc.reporters.Reporter { + import DelegatingReporter._ + + def dropDelegate(): Unit = { delegate = ReporterSink } + def error(msg: String): Unit = error(FakePos("scalac"), msg) + def printSummary(): Unit = delegate.printSummary() + + def problems = delegate.problems + override def hasErrors = delegate.hasErrors + override def hasWarnings = delegate.hasWarnings + override def comment(pos: Position, msg: String): Unit = + delegate.comment(DelegatingReporter.convert(pos), msg) + override def reset(): Unit = { + super.reset() + delegate.reset() + } + + override def doReport( + pos: Position, + msg: String, + rawSeverity: Severity, + actions: List[CodeAction] + ): Unit = { + val skip = rawSeverity == WARNING && noWarn + if (!skip) { + val severity = if (warnFatal && rawSeverity == WARNING) ERROR else rawSeverity + val pos1 = DelegatingReporter.convert(pos) + delegate.log(new CompileProblem( + pos = pos1, + msg = msg, + sev = convert(severity), + rendered0 = None, + diagnosticCode0 = None, + diagnosticRelatedInformation0 = Nil, + actions0 = actions.map(convertAction), + )) + } + } + + protected def info0(pos: Position, msg: String, rawSeverity: Severity, force: Boolean): Unit = + doReport(pos, msg, rawSeverity, Nil) + + import xsbti.Severity.{ Info, Warn, Error } + private[this] def convert(sev: Severity): xsbti.Severity = sev match { + case INFO => Info + case WARNING => Warn + case ERROR => Error + case x => throw new MatchError(x) + } + + // Define our own problem because the bridge should not depend on sbt util-logging. + private final class CompileProblem( + pos: XPosition, + msg: String, + sev: XSeverity, + rendered0: Option[String], + diagnosticCode0: Option[XDiagnosticCode], + diagnosticRelatedInformation0: List[XDiagnosticRelatedInformation], + actions0: List[Action] + ) extends XProblem { + override val category = "" + override val position = pos + override val message = msg + override val severity = sev + override def rendered = o2jo(rendered0) + override def toString = s"[$severity] $pos: $message" + override def diagnosticCode: Optional[XDiagnosticCode] = o2jo(diagnosticCode0) + override def diagnosticRelatedInformation(): ju.List[XDiagnosticRelatedInformation] = + l2jl(diagnosticRelatedInformation0) + override def actions(): ju.List[Action] = l2jl(actions0) + } + + private def convertAction(a: CodeAction): Action = + action( + title = a.title, + description = a.description, + edit = workspaceEdit(a.edits.map { edit => + textEdit(DelegatingReporter.convert(edit.position), edit.newText) + }), + ) + + private def action( + title: String, + description: Option[String], + edit: WorkspaceEdit + ): Action = + new ConcreteAction(title, description, edit) + + private def workspaceEdit(changes: List[TextEdit]): WorkspaceEdit = + new ConcreteWorkspaceEdit(changes) + + private def textEdit(position: XPosition, newText: String): TextEdit = + new ConcreteTextEdit(position, newText) + + private final class ConcreteAction( + title0: String, + description0: Option[String], + edit0: WorkspaceEdit + ) extends Action { + val title: String = title0 + val edit: WorkspaceEdit = edit0 + override def description(): Optional[String] = + o2jo(description0) + override def toString(): String = + s"Action($title0, $description0, $edit0)" + private def toTuple(a: Action) = + ( + a.title, + a.description, + a.edit + ) + override def hashCode: Int = toTuple(this).## + override def equals(o: Any): Boolean = o match { + case o: Action => toTuple(this) == toTuple(o) + case _ => false + } + } + + private final class ConcreteWorkspaceEdit(changes0: List[TextEdit]) extends WorkspaceEdit { + override def changes(): ju.List[TextEdit] = l2jl(changes0) + override def toString(): String = + s"WorkspaceEdit($changes0)" + private def toTuple(w: WorkspaceEdit) = jl2l(w.changes) + override def hashCode: Int = toTuple(this).## + override def equals(o: Any): Boolean = o match { + case o: WorkspaceEdit => toTuple(this) == toTuple(o) + case _ => false + } + } + + private final class ConcreteTextEdit(position0: XPosition, newText0: String) extends TextEdit { + val position: XPosition = position0 + val newText: String = newText0 + override def toString(): String = + s"TextEdit($position, $newText)" + private def toTuple(edit: TextEdit) = + ( + edit.position, + edit.newText + ) + override def hashCode: Int = toTuple(this).## + override def equals(o: Any): Boolean = o match { + case o: TextEdit => toTuple(this) == toTuple(o) + case _ => false + } + } +} + +private object ReporterSink extends xsbti.Reporter { + def reset() = () + def hasErrors() = false + def hasWarnings() = false + def printSummary() = () + def problems() = Array.empty[xsbti.Problem] + def log(problem: xsbti.Problem) = () + def comment(pos: xsbti.Position, msg: String) = () +} diff --git a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala index a856727211..de29643ac1 100644 --- a/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala +++ b/internal/zinc-scripted/src/test/scala/sbt/internal/inc/IncHandler.scala @@ -323,7 +323,7 @@ case class ProjectStructure( // We specify the class file manager explicitly even though it's noew possible // to specify it in the incremental option property file (this is the default for sbt) - val (incOptions, scalacOptions) = { + val (_incOptions, scalacOptions) = { val properties = loadIncProperties(baseDirectory) val (incOptions0, sco) = loadIncOptions(properties) val storeApis = Option(properties.getProperty("incOptions.storeApis")) @@ -340,6 +340,7 @@ case class ProjectStructure( .withStoreApis(storeApis) (incO, sco) } + override def incOptions = _incOptions val exportPipelining = incOptions.pipelining def prev(useCachedAnalysis: Boolean = true) = { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 3943aad06d..a757c6e21c 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -9,6 +9,7 @@ object Dependencies { val scala211 = "2.11.12" val scala212 = "2.12.18" val scala213 = "2.13.10" + val scala213_next = "2.13.12-bin-286f8d7" val defaultScalaVersion = scala212 val allScalaVersions = Seq(defaultScalaVersion, scala210, scala211, scala213) val scala212_213 = Seq(defaultScalaVersion, scala213) diff --git a/project/Util.scala b/project/ZincBuildUtil.scala similarity index 99% rename from project/Util.scala rename to project/ZincBuildUtil.scala index e0ac650f13..c752eed9d7 100644 --- a/project/Util.scala +++ b/project/ZincBuildUtil.scala @@ -2,7 +2,7 @@ import sbt._ import Keys._ import xsbti.compile.CompileAnalysis -object Util { +object ZincBuildUtil { lazy val apiDefinitions = TaskKey[Seq[File]]("api-definitions") lazy val genTestResTask = TaskKey[Seq[File]]("gen-test-resources") diff --git a/project/build.properties b/project/build.properties index 40b3b8e7b6..3c0b78a7c6 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.9.0 +sbt.version=1.9.1 diff --git a/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala b/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala index 8fafc985bc..b30b7b8531 100644 --- a/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala +++ b/zinc/src/test/scala/sbt/inc/BaseCompilerSpec.scala @@ -14,13 +14,12 @@ package sbt.inc import java.nio.file.{ Files, Path } import sbt.internal.inc.{ Analysis, BridgeProviderSpecification } -import sbt.util.Logger import xsbti.compile.{ CompileResult, IncOptions } class BaseCompilerSpec extends BridgeProviderSpecification { val scalaVersion: String = scala.util.Properties.versionNumberString - val incOptions: IncOptions = IncOptions.of().withPipelining(true) + override def incOptions: IncOptions = IncOptions.of().withPipelining(true) def assertExists(p: Path) = assert(Files.exists(p), s"$p does not exist") @@ -46,14 +45,4 @@ class BaseCompilerSpec extends BridgeProviderSpecification { val classes2 = classes(res2.analysis.asInstanceOf[Analysis]) classes2.collect { case (clazz, time) if !classes1.get(clazz).contains(time) => clazz }.toSet } - - implicit class ProjectSetupOps(setup: ProjectSetup) { - def createCompiler(): CompilerSetup = setup.createCompiler(scalaVersion, incOptions) - - private def createCompiler(sv: String, incOptions: IncOptions): CompilerSetup = { - val si = scalaInstance(sv, setup.baseDir, Logger.Null) - val bridge = getCompilerBridge(setup.baseDir, Logger.Null, sv) - setup.createCompiler(sv, si, bridge, incOptions, log) - } - } } diff --git a/zinc/src/test/scala/sbt/inc/ReporterTest.scala b/zinc/src/test/scala/sbt/inc/ReporterTest.scala new file mode 100644 index 0000000000..69750480a6 --- /dev/null +++ b/zinc/src/test/scala/sbt/inc/ReporterTest.scala @@ -0,0 +1,54 @@ +/* + * 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 sbt.inc + +import sbt.internal.inc.ZincBuildInfo._ +import sbt.internal.inc.{ BridgeProviderSpec, StringVirtualFile } +import sbt.io.IO.{ withTemporaryDirectory => withTmpDir } +import scala.collection.JavaConverters._ +import xsbti.Action + +object ReporterTest extends BridgeProviderSpec { + test("report action on procedure syntax") { + withCode("""def foo { print("") }""") { a => + assert(a.title == "procedure syntax (defn)") + } + } + + test("report action on missing parens") { + withCode("""println""") { a => + assert(a.title == "auto-application of empty-paren methods") + } + } + + def withCode(code: String)(f: Action => Unit): Unit = + withTmpDir { tmpDir => + val c1 = VirtualSubproject(tmpDir.toPath / "sub1") + .setup + .copy(scalacOptions = Seq("-deprecation")) + .createCompiler(scalaVersion213_next) + val reporter = c1.reporter + try { + val _ = c1.compile(StringVirtualFile( + "A.scala", + s"""class A { + $code +}""" + )) + assert(reporter.problems.length == 1) + val actions = reporter.problems.head.actions.asScala + assert(actions.length == 1) + val action = actions.head + f(action) + } finally c1.close() + } +} diff --git a/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala b/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala index 48c3f91367..8e02c2db9f 100644 --- a/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala +++ b/zinc/src/test/scala/sbt/inc/TestProjectSetup.scala @@ -65,6 +65,8 @@ case class CompilerSetup( val loaderCache = new ClassLoaderCache(new URLClassLoader(Array())) val scalac = new AnalyzingCompiler(si, bridgeProv, boot, _ => (), Some(loaderCache)) def toVf(p: Path) = converter.toVirtualFile(p) + val reporter = + new ManagedLoggedReporter(maxErrors, log, VirtualFileUtil.sourcePositionMapper(converter)) val setup = zinc.setup( perClasspathEntryLookup, @@ -72,7 +74,7 @@ case class CompilerSetup( tempDir.resolve("inc_compile"), CompilerCache.fresh, incOptions, - new ManagedLoggedReporter(maxErrors, log, VirtualFileUtil.sourcePositionMapper(converter)), + reporter, Some(progress), Some(FileAnalysisStore.getDefault(earlyAnalysisStoreLocation.toFile)), Array(InterfaceUtil.t2(("key", "value"))) diff --git a/zinc/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala b/zinc/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala index ae774d0bfa..9f00fa55bd 100644 --- a/zinc/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala +++ b/zinc/src/test/scala/sbt/internal/inc/BridgeProviderSpecification.scala @@ -12,20 +12,48 @@ package sbt.internal.inc import java.nio.file.Path -import sbt.inc.{ ScalaBridge, ConstantBridgeProvider } +import sbt.inc.{ CompilerSetup, ScalaBridge, ConstantBridgeProvider, ProjectSetup } import sbt.util.Logger -import xsbti.compile.CompilerBridgeProvider +import xsbti.compile.{ CompilerBridgeProvider, IncOptions } + +trait BridgeProviderSpec extends verify.BasicTestSuite with BridgeProviderTestkit class BridgeProviderSpecification extends UnitSpec with BridgeProviderTestkit {} trait BridgeProviderTestkit extends AbstractBridgeProviderTestkit { + def incOptions: IncOptions = IncOptions.of().withPipelining(true) + + implicit class ProjectSetupOps(setup: ProjectSetup) { + import sbt.internal.inc.ZincBuildInfo._ + + def createCompiler(): CompilerSetup = + createCompiler(scalaVersion213, incOptions) + + def createCompiler(scalaVersion: String): CompilerSetup = + createCompiler(scalaVersion, incOptions) + + private def createCompiler(sv: String, incOptions: IncOptions): CompilerSetup = { + val si = scalaInstance(sv, setup.baseDir, Logger.Null) + val bridge = getCompilerBridge(setup.baseDir, Logger.Null, sv) + setup.createCompiler(sv, si, bridge, incOptions, log) + } + } + lazy val bridges: List[ScalaBridge] = { import sbt.internal.inc.ZincBuildInfo._ val compilerBridge210 = ScalaBridge(scalaVersion210, scalaJars210.toList, classDirectory210) val compilerBridge211 = ScalaBridge(scalaVersion211, scalaJars211.toList, classDirectory211) val compilerBridge212 = ScalaBridge(scalaVersion212, scalaJars212.toList, classDirectory212) val compilerBridge213 = ScalaBridge(scalaVersion213, scalaJars213.toList, classDirectory213) - List(compilerBridge210, compilerBridge211, compilerBridge212, compilerBridge213) + val compilerBridge213_next = + ScalaBridge(scalaVersion213_next, scalaJars213_next.toList, classDirectory213_next) + List( + compilerBridge210, + compilerBridge211, + compilerBridge212, + compilerBridge213, + compilerBridge213_next + ) } // Create a provider that uses the bridges from the classes directory of the projects