diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e0611fd..d5a53fd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,24 +1,23 @@ name: CI on: push: - branches: - - main + tags: ["*"] + branches: ['**', '!update/**', '!pr/**'] pull_request: - branches: - - main + branches: ['**', '!update/**', '!pr/**'] + jobs: test: name: ${{ matrix.command }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: command: - - sbt "plugin/test" "^^0.13.17 profilingSbtPlugin/scripted" "^^1.1.1 profilingSbtPlugin/scripted compiler-profiling/*" - - sbt "showScalaInstances" "integrations/testOnly circe integration monocle better-files scalac" - - sbt "showScalaInstances" "integrations/testOnly scalatest shapeless" + - sbt "+plugin/test" "profilingSbtPlugin/scripted compiler-profiling/scripted" + - sbt "showScalaInstances" "integrations/testOnly integration better-files wartremover" steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true - uses: olafurpg/setup-scala@v13 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c898b57 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,23 @@ +name: Release +on: + push: + branches: [main] + tags: ["*"] +jobs: + publish: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - uses: actions/setup-java@v3 + with: + distribution: temurin + java-version: 8 + cache: sbt + - run: sbt ci-release + env: + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + PGP_SECRET: ${{ secrets.PGP_SECRET }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} diff --git a/.gitignore b/.gitignore index 95706fd..c196864 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,10 @@ project/plugins/project/ .hidden .profiledb_211 .proxy + +# metals vscode +.bloop +.bsp +.metals +.vscode +metals.sbt diff --git a/.gitmodules b/.gitmodules index 0ffb85a..364c380 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,7 @@ -[submodule "scalac"] - path = scalac - url = git@github.com:scalacenter/scala.git - branch = 2.12.x [submodule "vscode-scala"] path = vscode-scala url = git@github.com:scalacenter/vscode-scala-profiledb.git branch = profiledb-integration -[submodule "sbt-plugin/src/sbt-test/external-projects/circe"] - path = sbt-plugin/src/sbt-test/external-projects/circe - url = https://github.com/jvican/circe - branch = master-with-sbt-profiling [submodule "FlameGraph"] path = FlameGraph - url = git://github.com/jvican/FlameGraph.git + url = git@github.com:jvican/FlameGraph.git diff --git a/build.sbt b/build.sbt index f9b17cb..0cb24f3 100644 --- a/build.sbt +++ b/build.sbt @@ -7,48 +7,55 @@ ** ** \* */ +import xsbti.compile.CompileAnalysis + lazy val root = project .in(file(".")) .aggregate(profiledb, plugin, profilingSbtPlugin) .settings( - Seq( - name := "profiling-root", - publish := {}, - publishLocal := {}, - crossSbtVersions := List("0.13.17", "1.1.1"), - watchSources ++= - (watchSources in plugin).value ++ - (watchSources in profiledb).value ++ - (watchSources in integrations).value - ) + name := "profiling-root", + crossScalaVersions := bin212 ++ bin213, + publish := {}, + publishLocal := {}, + skip / publish := true, + watchSources ++= + (plugin / watchSources).value ++ + (profiledb / watchSources).value ++ + (integrations / watchSources).value ) -val metalsSettings = List( - scalacOptions ++= { - val version = Keys.scalaBinaryVersion.value - val toAdd = List("-Yrangepos", "-Xplugin-require:semanticdb") - if (version == "2.12") toAdd else Nil - }, - libraryDependencies ++= { - val version = Keys.scalaBinaryVersion.value - if (version == "2.12") - List(compilerPlugin("org.scalameta" % "semanticdb-scalac" % "2.1.5" cross CrossVersion.full)) - else Nil +val bin212 = Seq("2.12.18", "2.12.17", "2.12.16", "2.12.15", "2.12.14", "2.12.13") +val bin213 = Seq("2.13.12", "2.13.11", "2.13.10", "2.13.9", "2.13.8", "2.13.7", "2.13.6", "2.13.5") + +// Copied from +// https://github.com/scalameta/scalameta/blob/370e304b0d10db1dd65fc79a5abc1f39004aeffd/build.sbt#L724-L737 +lazy val fullCrossVersionSettings = Seq( + crossVersion := CrossVersion.full, + crossScalaVersions := bin212 ++ bin213, + Compile / unmanagedSourceDirectories += { + // NOTE: SBT 1.x provides cross-version support for Scala sources + // (https://www.scala-sbt.org/1.x/docs/Cross-Build.html#Scala-version+specific+source+directory). + // Unfortunately, it only includes directories like "scala_2.12" or "scala_2.13", + // not "scala_2.12.18" or "scala_2.13.12" that we need. + // That's why we have to work around here. + val base = (Compile/ sourceDirectory).value + val versionDir = scalaVersion.value.replaceAll("-.*", "") + base / ("scala-" + versionDir) } ) import _root_.ch.epfl.scala.profiling.build.BuildImplementation.BuildDefaults -import com.trueaccord.scalapb.compiler.Version.scalapbVersion +import scalapb.compiler.Version.scalapbVersion lazy val profiledb = project .in(file("profiledb")) //.settings(metalsSettings) .settings( // Specify scala version to allow third-party software to use this module - scalaVersion := "2.12.6", - crossScalaVersions := List(scalaVersion.value, "2.11.11"), + crossScalaVersions := bin212 ++ bin213, + scalaVersion := bin212.head, libraryDependencies += - "com.trueaccord.scalapb" %% "scalapb-runtime" % scalapbVersion % "protobuf", - PB.targets in Compile := Seq(scalapb.gen() -> (sourceManaged in Compile).value) + "com.thesamet.scalapb" %% "scalapb-runtime" % scalapbVersion % "protobuf", + Compile / PB.targets := Seq(scalapb.gen() -> (Compile / sourceManaged).value) ) // Do not change the lhs id of this plugin, `BuildPlugin` relies on it @@ -56,23 +63,27 @@ lazy val plugin = project .dependsOn(profiledb) //.settings(metalsSettings) .settings( + fullCrossVersionSettings, name := "scalac-profiling", libraryDependencies ++= List( - "com.lihaoyi" %% "pprint" % "0.5.3", + "com.lihaoyi" %% "pprint" % "0.5.7", scalaOrganization.value % "scala-compiler" % scalaVersion.value ), - libraryDependencies ++= testDependencies, - testOptions in Test ++= List(Tests.Argument("-v"), Tests.Argument("-s")), + libraryDependencies ++= List( + "junit" % "junit" % "4.12" % "test", + "com.novocode" % "junit-interface" % "0.11" % "test" + ), + Test / testOptions ++= List(Tests.Argument("-v"), Tests.Argument("-s")), allDepsForCompilerPlugin := { - val jar = (Keys.packageBin in Compile).value - val profileDbJar = (Keys.`package` in Compile in profiledb).value + val jar = (Compile / Keys.packageBin).value + val profileDbJar = (profiledb / Compile / Keys.`package`).value val absoluteJars = List(jar, profileDbJar).classpath - val pluginDeps = (managedClasspath in Compile).value + val pluginDeps = (Compile / managedClasspath).value (absoluteJars ++ pluginDeps) }, // Make the tests to compile with the plugin optionsForSourceCompilerPlugin := { - val jar = (Keys.packageBin in Compile).value + val jar = (Compile / Keys.packageBin).value val pluginAndDeps = allDepsForCompilerPlugin.value.map(_.data.getAbsolutePath()).mkString(":") val addPlugin = "-Xplugin:" + pluginAndDeps val dummy = "-Jdummy=" + jar.lastModified @@ -83,10 +94,10 @@ lazy val plugin = project //else List("-Xlog-implicits", "-Ystatistics:typer") Seq(addPlugin, dummy) ++ debuggingPluginOptions }, - scalacOptions in Test ++= optionsForSourceCompilerPlugin.value, + Test / scalacOptions ++= optionsForSourceCompilerPlugin.value, // Generate toolbox classpath while compiling for both configurations - resourceGenerators in Compile += generateToolboxClasspath.taskValue, - resourceGenerators in Test += Def.task { + Compile / resourceGenerators += generateToolboxClasspath.taskValue, + Test / resourceGenerators += Def.task { val options = scalacOptions.value val stringOptions = options.filterNot(_ == "-Ydebug").mkString(" ") val pluginOptionsFile = resourceManaged.value / "toolbox.plugin" @@ -96,175 +107,118 @@ lazy val plugin = project inCompileAndTest(unmanagedSourceDirectories ++= { val scalaPartialVersion = CrossVersion partialVersion scalaVersion.value scalaPartialVersion.collect { - case (2, y) if y == 11 => new File(scalaSource.value.getPath + "-2.11") - case (2, y) if y >= 12 => new File(scalaSource.value.getPath + "-2.12") + case (2, y) if y == 12 => new File(scalaSource.value.getPath + "-2.12") + case (2, y) if y >= 13 => new File(scalaSource.value.getPath + "-2.13") }.toList }), - Keys.packageBin in Compile := (assembly in Compile).value, - test in assembly := {}, - assemblyOption in assembly := - (assemblyOption in assembly).value - .copy(includeScala = false, includeDependency = true) + Compile / Keys.packageBin := (Compile / assembly).value, + assembly / test := {} ) // Trick to copy profiledb with Scala 2.11.11 so that vscode can depend on it -lazy val profiledb211 = profiledb - .copy(id = "profiledb-211") - .settings( - moduleName := "profiledb", - scalaVersion := (scalaVersion in VscodeImplementation).value, - // Redefining target so that sbt doesn't clash at runtime - // This makes sense, but we should get a more sensible error message. - target := (baseDirectory in profiledb).value./("target_211") - ) +// lazy val profiledb211 = profiledb +// .copy(id = "profiledb-211") +// .settings( +// moduleName := "profiledb", +// scalaVersion := (scalaVersion in VscodeImplementation).value, +// // Redefining target so that sbt doesn't clash at runtime +// // This makes sense, but we should get a more sensible error message. +// target := (baseDirectory in profiledb).value./("target_211") +// ) // This is the task to publish the vscode integration -val publishExtension = taskKey[Unit]("The task to publish the vscode extension.") +// val publishExtension = taskKey[Unit]("The task to publish the vscode extension.") // Has to be in independent project because uses different Scala version -lazy val vscodeIntegration = project - .in(file(".hidden")) - .dependsOn(VscodeImplementation, profiledb211) - .settings( - scalaVersion := (scalaVersion in VscodeImplementation).value, - libraryDependencies in VscodeImplementation += (projectID in profiledb211).value, - // Sbt bug: doing this for VscodeImplementation just doesn't work. - update := update.dependsOn(publishLocal in profiledb211).value, - publish := (publish in VscodeImplementation).dependsOn(publish in profiledb211).value, - publishLocal := - (publishLocal in VscodeImplementation).dependsOn(publishLocal in profiledb211).value, - publishExtension := (Def - .task { - val scalaExtensionDir = (baseDirectory in VscodeScala).value./("scala") - sys.process.Process(Seq("vsce", "package"), scalaExtensionDir).!! - }) - .dependsOn(publishLocal) - .value - ) - +// lazy val vscodeIntegration = project +// .in(file(".hidden")) +// .dependsOn(VscodeImplementation, profiledb211) +// .settings( +// scalaVersion := (scalaVersion in VscodeImplementation).value, +// libraryDependencies in VscodeImplementation += (projectID in profiledb211).value, +// // Sbt bug: doing this for VscodeImplementation just doesn't work. +// update := update.dependsOn(publishLocal in profiledb211).value, +// publish := (publish in VscodeImplementation).dependsOn(publish in profiledb211).value, +// publishLocal := +// (publishLocal in VscodeImplementation).dependsOn(publishLocal in profiledb211).value, +// publishExtension := (Def +// .task { +// val scalaExtensionDir = (baseDirectory in VscodeScala).value./("scala") +// sys.process.Process(Seq("vsce", "package"), scalaExtensionDir).!! +// }) +// .dependsOn(publishLocal) +// .value +// ) +// lazy val profilingSbtPlugin = project .in(file("sbt-plugin")) - //.settings(metalsSettings) .settings( name := "sbt-scalac-profiling", - sbtPlugin := true, - scalaVersion := BuildDefaults.fixScalaVersionForSbtPlugin.value, - ScriptedPlugin.scriptedSettings, + scalaVersion := bin212.head, scriptedLaunchOpts ++= Seq("-Xmx2048M", "-Xms1024M", "-Xss8M", s"-Dplugin.version=${version.value}"), scriptedBufferLog := false ) + .enablePlugins(SbtPlugin) // Source dependencies are specified in `project/BuildPlugin.scala` lazy val integrations = project .in(file("integrations")) - .dependsOn(Circe) .settings( - libraryDependencies += "com.github.alexarchambault" %% "case-app" % "1.2.0", - scalaHome := BuildDefaults.setUpScalaHome.value, - parallelExecution in Test := false, - scalacOptions in Compile := (Def.taskDyn { - val options = (Keys.scalacOptions in Compile).value + skip / publish := true, + libraryDependencies += "com.github.alexarchambault" %% "case-app" % "2.0.6", + Test / parallelExecution := false, + Compile / scalacOptions := (Def.taskDyn { + val options = (Compile / scalacOptions).value val ref = Keys.thisProjectRef.value Def.task(options ++ BuildDefaults.scalacProfilingScalacOptions(ref).value) }).value, clean := Def .sequential( clean, - (clean in Test in CirceTests), - (clean in Test in MonocleTests), - (clean in Test in MonocleExample), - (clean in Compile in ScalatestCore), - //(clean in Compile in MagnoliaTests), - (clean in ScalacCompiler) + (BetterFilesCore / Compile / clean), + (WartremoverCore / Compile / clean), ) .value, test := Def .sequential( - (showScalaInstances in ThisBuild), - (profilingWarmupCompiler in Compile), // Warmup example, classloader is the same for all - (compile in Compile), - (compile in Test in CirceTests), - (compile in Test in MonocleTests), - (compile in Test in MonocleExample), - (compile in Compile in ScalatestCore), - //(compile in Compile in MagnoliaTests), - (compile in ScalacCompiler) + (ThisBuild / showScalaInstances), + (Compile / compile), ) .value, testOnly := Def.inputTaskDyn { val keywords = keywordsSetting.parsed - val emptyAnalysis = Def.task(sbt.inc.Analysis.Empty) - val CirceTask = Def.taskDyn { - if (keywords.contains(Keywords.Circe)) - Def.sequential( - (compile in Test in CirceTests) - ) - else emptyAnalysis - } + val emptyAnalysis = Def.task[CompileAnalysis](sbt.internal.inc.Analysis.Empty) val IntegrationTask = Def.taskDyn { if (keywords.contains(Keywords.Integration)) Def.sequential( - (compile in Compile) - ) - else emptyAnalysis - } - val MonocleTask = Def.taskDyn { - if (keywords.contains(Keywords.Monocle)) - Def.sequential( - (compile in Test in MonocleTests), - (compile in Test in MonocleExample) - ) - else emptyAnalysis - } - val ScalatestTask = Def.taskDyn { - if (keywords.contains(Keywords.Scalatest)) - Def.sequential( - (compile in Compile in ScalatestCore), - (compile in Test in ScalatestTests) - ) - else emptyAnalysis - } - val ScalacTask = Def.taskDyn { - if (keywords.contains(Keywords.Scalac)) - Def.sequential( - (compile in Compile in ScalacCompiler) + (Compile / compile) ) else emptyAnalysis } val BetterFilesTask = Def.taskDyn { if (keywords.contains(Keywords.BetterFiles)) Def.sequential( - (compile in Compile in BetterFilesCore) + (BetterFilesCore / Compile / compile) ) else emptyAnalysis } - val ShapelessTask = Def.taskDyn { - if (keywords.contains(Keywords.Shapeless)) + val WartremoverTask = Def.taskDyn { + if (keywords.contains(Keywords.Wartremover)) Def.sequential( - (compile in Compile in ShapelessCore), - (compile in Test in ShapelessCore) - ) - else emptyAnalysis - } - val MagnoliaTask = Def.taskDyn { - if (keywords.contains(Keywords.Magnolia)) - Def.sequential( - (compile in Compile in MagnoliaTests) + (WartremoverCore / Compile / compile) ) else emptyAnalysis } + Def.sequential( - CirceTask, - MonocleTask, IntegrationTask, - ScalatestTask, - ScalacTask, BetterFilesTask, - ShapelessTask//,MagnoliaTask + WartremoverTask ) }.evaluated ) val proxy = project .in(file(".proxy")) - .aggregate(Circe, Monocle, Scalatest, Scalac, BetterFiles, Shapeless)//, Magnolia) + .aggregate(BetterFiles, Wartremover) + .settings(skip / publish := true) diff --git a/integrations/src/main/scala/profiling/integrations/caseapp/CliOptions.scala b/integrations/src/main/scala/profiling/integrations/caseapp/CliOptions.scala index d1fac90..cd42075 100644 --- a/integrations/src/main/scala/profiling/integrations/caseapp/CliOptions.scala +++ b/integrations/src/main/scala/profiling/integrations/caseapp/CliOptions.scala @@ -1,4 +1,4 @@ -package profiling.integrations +package profiling.integrations.caseapp import java.nio.file.Path diff --git a/integrations/src/main/scala/profiling/integrations/caseapp/Commands.scala b/integrations/src/main/scala/profiling/integrations/caseapp/Commands.scala index f81852e..1370235 100644 --- a/integrations/src/main/scala/profiling/integrations/caseapp/Commands.scala +++ b/integrations/src/main/scala/profiling/integrations/caseapp/Commands.scala @@ -1,10 +1,9 @@ -package profiling.integrations +package profiling.integrations.caseapp -import java.nio.file.Path +// import java.nio.file.Path +// import caseapp.{ArgsName, ExtraName, HelpMessage, Hidden} -import caseapp.core.ArgParser -import caseapp.{ArgsName, CommandName, ExtraName, HelpMessage, Hidden, Recurse} -import caseapp.core.CommandMessages +import caseapp.{CommandName, Recurse} object Commands { diff --git a/integrations/src/main/scala/profiling/integrations/caseapp/CommonOptions.scala b/integrations/src/main/scala/profiling/integrations/caseapp/CommonOptions.scala index 6f4b9fe..f760b07 100644 --- a/integrations/src/main/scala/profiling/integrations/caseapp/CommonOptions.scala +++ b/integrations/src/main/scala/profiling/integrations/caseapp/CommonOptions.scala @@ -1,4 +1,4 @@ -package profiling.integrations +package profiling.integrations.caseapp import java.io.{InputStream, PrintStream} import java.util.Properties @@ -33,14 +33,6 @@ object CommonOptions { } } - object PrettyProperties { - def from(p: Properties): PrettyProperties = { - val pp = new PrettyProperties() - pp.putAll(p) - pp - } - } - final lazy val currentEnv: PrettyProperties = { import scala.collection.JavaConverters._ System.getenv().asScala.foldLeft(new PrettyProperties()) { diff --git a/integrations/src/main/scala/profiling/integrations/caseapp/Parsers.scala b/integrations/src/main/scala/profiling/integrations/caseapp/Parsers.scala index 9669423..6a26094 100644 --- a/integrations/src/main/scala/profiling/integrations/caseapp/Parsers.scala +++ b/integrations/src/main/scala/profiling/integrations/caseapp/Parsers.scala @@ -1,95 +1,81 @@ -package profiling.integrations +package profiling.integrations.caseapp import java.io.{InputStream, PrintStream} import java.nio.file.{Path, Paths} import CommonOptions.PrettyProperties -import caseapp.{CaseApp, CommandParser} -import caseapp.util.{Implicit, AnnotationList} -import caseapp.core.{ArgParser, DefaultBaseCommand, HListParser, Parser, Default} -import shapeless.{Annotations, Coproduct, LabelledGeneric, Strict, Generic, HList} -import caseapp.{Name, ValueDescription, HelpMessage, Hidden, Recurse} +import caseapp.core.default.Default +import caseapp.core.Error.Other + +import caseapp.core.argparser.{ArgParser, SimpleArgParser} +import caseapp.core.parser.Parser +import shapeless.{LabelledGeneric, HList} import scala.util.Try trait CachedImplicits { - implicit val inputStreamRead: ArgParser[InputStream] = - ArgParser.instance[InputStream]("stdin")(_ => Right(System.in)) + implicit val inputStreamRead: ArgParser[InputStream] = + SimpleArgParser.from[InputStream]("stdin")(_ => Right(System.in)) implicit val printStreamRead: ArgParser[PrintStream] = - ArgParser.instance[PrintStream]("stdout")(_ => Right(System.out)) + SimpleArgParser.from[PrintStream]("stdout")(_ => Right(System.out)) - implicit val pathParser: ArgParser[Path] = ArgParser.instance("A filepath parser") { + implicit val pathParser: ArgParser[Path] = SimpleArgParser.from("A filepath parser") { case supposedPath: String => val toPath = Try(Paths.get(supposedPath)).toEither - toPath.left.map(t => s"The provided path ${supposedPath} is not valid: '${t.getMessage()}'.") + toPath.left.map(t => Other(s"The provided path ${supposedPath} is not valid: '${t.getMessage()}'.")) } implicit val propertiesParser: ArgParser[PrettyProperties] = { - ArgParser.instance("A properties parser") { - case whatever => Left("You cannot pass in properties through the command line.") + SimpleArgParser.from("A properties parser") { + _ => Left(Other("You cannot pass in properties through the command line.")) } } - import shapeless.{HNil, CNil, :+:, ::} - implicit val implicitHNil: Implicit[HNil] = Implicit.hnil - implicit val implicitNone: Implicit[None.type] = Implicit.instance(None) - implicit val implicitNoneCnil: Implicit[None.type :+: CNil] = - Implicit.instance(Coproduct(None)) + implicit val implicitHNil: shapeless.HNil = HList.apply() - implicit val implicitOptionDefaultString: Implicit[Option[Default[String]]] = - Implicit.instance(Some(caseapp.core.Defaults.string)) + implicit val implicitOptionDefaultString: Option[Default[String]] = + Some(Default("")) - implicit val implicitOptionDefaultInt: Implicit[Option[Default[Int]]] = - Implicit.instance(Some(caseapp.core.Defaults.int)) + implicit val implicitOptionDefaultInt: Option[Default[Int]] = + Some(Default(0)) - implicit val implicitOptionDefaultBoolean: Implicit[Option[Default[Boolean]]] = - Implicit.instance(Some(caseapp.core.Defaults.boolean)) + implicit val implicitOptionDefaultBoolean: Option[Default[Boolean]] = + Some(Default(true)) - implicit val implicitDefaultBoolean: Implicit[Default[Boolean]] = - Implicit.instance(caseapp.core.Defaults.boolean) + implicit val implicitDefaultBoolean: Default[Boolean] = + Default(true) - implicit val implicitOptionDefaultOptionPath: Implicit[Option[Default[Option[Path]]]] = - Implicit.instance(None) + implicit val implicitOptionDefaultOptionPath: Option[Default[Option[Path]]] = + Some(Default(None)) - implicit val implicitOptionDefaultPrintStream: Implicit[Option[Default[PrintStream]]] = - Implicit.instance(Some(Default.instance[PrintStream](System.out))) + implicit val implicitOptionDefaultPrintStream: Option[Default[PrintStream]] = + Some(Default[PrintStream](System.out)) - implicit val implicitOptionDefaultInputStream: Implicit[Option[Default[InputStream]]] = - Implicit.instance(Some(Default.instance[InputStream](System.in))) + implicit val implicitOptionDefaultInputStream: Option[Default[InputStream]] = + Some(Default[InputStream](System.in)) } object Parsers extends CachedImplicits { - import shapeless.{the, HNil, ::} - implicit val labelledGenericCommonOptions: LabelledGeneric.Aux[CommonOptions, _] = LabelledGeneric.materializeProduct - implicit val commonOptionsParser: Parser.Aux[CommonOptions, _] = Parser.generic + implicit val commonOptionsParser: Parser.Aux[CommonOptions, _] = Parser.derive implicit val labelledGenericCliOptions: LabelledGeneric.Aux[CliOptions, _] = LabelledGeneric.materializeProduct - implicit val cliOptionsParser: Parser.Aux[CliOptions, _] = Parser.generic - - implicit val strictAutocompleteParser: Parser.Aux[Commands.Autocomplete, _] = Parser.generic - implicit val strictAboutParser: Parser.Aux[Commands.About, _] = Parser.generic - implicit val strictBspParser: Parser.Aux[Commands.Bsp, _] = Parser.generic - implicit val strictCleanParser: Parser.Aux[Commands.Clean, _] = Parser.generic - implicit val strictCompileParser: Parser.Aux[Commands.Compile, _] = Parser.generic - implicit val strictConfigureParser: Parser.Aux[Commands.Configure, _] = Parser.generic - implicit val strictConsoleParser: Parser.Aux[Commands.Console, _] = Parser.generic - implicit val strictHelpParser: Parser.Aux[Commands.Help, _] = Parser.generic - implicit val strictProjectsParser: Parser.Aux[Commands.Projects, _] = Parser.generic - implicit val strictRunParser: Parser.Aux[Commands.Run, _] = Parser.generic - implicit val strictTestParser: Parser.Aux[Commands.Test, _] = Parser.generic - - val BaseMessages: caseapp.core.Messages[DefaultBaseCommand] = - caseapp.core.Messages[DefaultBaseCommand] - val CommandsMessages: caseapp.core.CommandsMessages[Commands.RawCommand] = - implicitly[caseapp.core.CommandsMessages[Commands.RawCommand]] - val CommandsParser: CommandParser[Commands.RawCommand] = - implicitly[caseapp.core.CommandParser[Commands.RawCommand]] + implicit val cliOptionsParser: Parser.Aux[CliOptions, _] = Parser.derive + + implicit val strictAutocompleteParser: Parser.Aux[Commands.Autocomplete, _] = Parser.derive + implicit val strictAboutParser: Parser.Aux[Commands.About, _] = Parser.derive + implicit val strictBspParser: Parser.Aux[Commands.Bsp, _] = Parser.derive + implicit val strictCleanParser: Parser.Aux[Commands.Clean, _] = Parser.derive + implicit val strictCompileParser: Parser.Aux[Commands.Compile, _] = Parser.derive + implicit val strictConfigureParser: Parser.Aux[Commands.Configure, _] = Parser.derive + implicit val strictConsoleParser: Parser.Aux[Commands.Console, _] = Parser.derive + implicit val strictHelpParser: Parser.Aux[Commands.Help, _] = Parser.derive + implicit val strictProjectsParser: Parser.Aux[Commands.Projects, _] = Parser.derive + implicit val strictRunParser: Parser.Aux[Commands.Run, _] = Parser.derive + implicit val strictTestParser: Parser.Aux[Commands.Test, _] = Parser.derive + } object Main extends App { - import Parsers._ -/* assert(CommandsParser != null) - assert(CommandsMessages != null)*/ println("Hello World!") } diff --git a/integrations/src/main/scala/profiling/integrations/circe/WebsiteExample.scala b/integrations/src/main/scala/profiling/integrations/circe/WebsiteExample.scala deleted file mode 100644 index bc69d0d..0000000 --- a/integrations/src/main/scala/profiling/integrations/circe/WebsiteExample.scala +++ /dev/null @@ -1,19 +0,0 @@ -/*import io.circe._ -import io.circe.generic.auto._ -import io.circe.parser._ -import io.circe.syntax._ - -sealed trait Foo -case class Bar(xs: List[String]) extends Foo -case class Qux(i: Int, d: Option[Double]) extends Foo - -object WebsiteExample extends App { - val foo: Foo = Qux(13, Some(14.0)) -/* implicit val ef: Encoder[Foo] = implicitly[Encoder[Foo]]*/ - foo.asJson.noSpaces - println(decode[Foo](foo.asJson.spaces4)) -/* - import io.circe.generic.semiauto._ - implicit val fooDecoder: Decoder[Foo] = deriveDecoder[Foo] - implicit val fooEncoder: Encoder[Foo] = deriveEncoder[Foo]*/ -}*/ diff --git a/plugin/src/main/scala-2.12.13/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.13/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..13f837e --- /dev/null +++ b/plugin/src/main/scala-2.12.13/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,9 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global +import scala.reflect.internal.util.StatisticsStatics + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + StatisticsStatics.areSomeColdStatsEnabled() && g.statistics.areStatisticsLocallyEnabled +} diff --git a/plugin/src/main/scala-2.12.14/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.14/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.12.14/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.12.15/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.15/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.12.15/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.12.16/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.16/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.12.16/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.12.17/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.17/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.12.17/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.12.18/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.12.18/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.12.18/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.10/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.10/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.10/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.11/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.11/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.11/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.12/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.12/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.12/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.5/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.5/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..13f837e --- /dev/null +++ b/plugin/src/main/scala-2.13.5/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,9 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global +import scala.reflect.internal.util.StatisticsStatics + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + StatisticsStatics.areSomeColdStatsEnabled() && g.statistics.areStatisticsLocallyEnabled +} diff --git a/plugin/src/main/scala-2.13.6/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.6/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.6/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.7/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.7/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.7/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.8/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.8/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.8/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala-2.13.9/ch/epfl/scala/profilers/tools/SettingsOps.scala b/plugin/src/main/scala-2.13.9/ch/epfl/scala/profilers/tools/SettingsOps.scala new file mode 100644 index 0000000..aadf96d --- /dev/null +++ b/plugin/src/main/scala-2.13.9/ch/epfl/scala/profilers/tools/SettingsOps.scala @@ -0,0 +1,8 @@ +package ch.epfl.scala.profilers.tools + +import scala.tools.nsc.Global + +object SettingsOps { + def areStatisticsEnabled(g: Global): Boolean = + g.settings.areStatisticsEnabled +} diff --git a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala index a3f3a6d..daa1f2e 100644 --- a/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala +++ b/plugin/src/main/scala/ch/epfl/scala/ProfilingPlugin.scala @@ -14,9 +14,9 @@ import java.nio.file.Files import ch.epfl.scala.profiledb.{ProfileDb, ProfileDbPath} import ch.epfl.scala.profiledb.utils.AbsolutePath import ch.epfl.scala.profilers.ProfilingImpl -import ch.epfl.scala.profilers.tools.Logger +import ch.epfl.scala.profilers.tools.{Logger, SettingsOps} -import scala.reflect.internal.util.{SourceFile, Statistics, StatisticsStatics} +import scala.reflect.internal.util.{SourceFile, Statistics} import scala.reflect.io.Path import scala.tools.nsc.io.AbstractFile import scala.tools.nsc.{Global, Phase} @@ -265,7 +265,7 @@ class ProfilingPlugin(val global: Global) extends Plugin { new java.io.File( global.settings.outputDirs.getSingleOutput .map(_.file.getAbsolutePath) - .getOrElse(global.settings.d.value) + .getOrElse(global.settings.outdir.value) ) ) @@ -273,8 +273,8 @@ class ProfilingPlugin(val global: Global) extends Plugin { override def newPhase(prev: Phase): Phase = { new StdPhase(prev) { override def apply(unit: global.CompilationUnit): Unit = { - if (StatisticsStatics.areSomeColdStatsEnabled() && - global.statistics.areStatisticsLocallyEnabled && + if ( + SettingsOps.areStatisticsEnabled(global) && !config.noDb) { val currentSourceFile = unit.source val compilationUnitEntry = profileDbEntryFor(currentSourceFile) diff --git a/plugin/src/main/scala/ch/epfl/scala/profilers/ProfilingImpl.scala b/plugin/src/main/scala/ch/epfl/scala/profilers/ProfilingImpl.scala index 41e78a9..c31cb53 100644 --- a/plugin/src/main/scala/ch/epfl/scala/profilers/ProfilingImpl.scala +++ b/plugin/src/main/scala/ch/epfl/scala/profilers/ProfilingImpl.scala @@ -15,9 +15,7 @@ import ch.epfl.scala.PluginConfig import ch.epfl.scala.profiledb.utils.AbsolutePath import scala.tools.nsc.Global -import ch.epfl.scala.profilers.tools.{Logger, QuantitiesHijacker} - -import scala.reflect.internal.util.StatisticsStatics +import ch.epfl.scala.profilers.tools.{Logger, QuantitiesHijacker, SettingsOps} final class ProfilingImpl[G <: Global]( override val global: G, @@ -72,8 +70,8 @@ final class ProfilingImpl[G <: Global]( def groupPerFile[V]( kvs: Map[Position, V] )(empty: V, aggregate: (V, V) => V): Map[SourceFile, V] = { - kvs.groupBy(_._1.source).mapValues { - case posInfos: Map[Position, V] => posInfos.valuesIterator.fold(empty)(aggregate) + kvs.groupBy(_._1.source).map { + case (sf, posInfos: Map[Position, V]) => sf -> posInfos.valuesIterator.fold(empty)(aggregate) } } @@ -81,7 +79,9 @@ final class ProfilingImpl[G <: Global]( import ProfilingMacroPlugin.macroInfos //, repeatedTrees} val perCallSite = macroInfos.toMap val perFile = groupPerFile(perCallSite)(MacroInfo.Empty, _ + _) - .mapValues(i => i.copy(expansionNanos = toMillis(i.expansionNanos))) + .map { + case (sf, mi) => sf -> mi.copy(expansionNanos = toMillis(mi.expansionNanos)) + } val inTotal = MacroInfo.aggregate(perFile.valuesIterator) /* val repeated = repeatedTrees.toMap.valuesIterator @@ -90,8 +90,9 @@ final class ProfilingImpl[G <: Global]( .toMap*/ // perFile and inTotal are already converted to millis - val callSiteNanos = perCallSite - .mapValues(i => i.copy(expansionNanos = toMillis(i.expansionNanos))) + val callSiteNanos = perCallSite.map { + case (pos, mi) => pos -> mi.copy(expansionNanos = toMillis(mi.expansionNanos)) + } MacroProfiler(callSiteNanos, perFile, inTotal, Map.empty) //repeated) } @@ -113,9 +114,13 @@ final class ProfilingImpl[G <: Global]( ) lazy val implicitProfiler: ImplicitProfiler = { - val perCallSite = implicitSearchesByPos.toMap.mapValues(ImplicitInfo.apply) + val perCallSite = implicitSearchesByPos.map { + case (pos, i) => pos -> ImplicitInfo.apply(i) + }.toMap val perFile = groupPerFile[ImplicitInfo](perCallSite)(ImplicitInfo.Empty, _ + _) - val perType = implicitSearchesByType.toMap.mapValues(ImplicitInfo.apply) + val perType = implicitSearchesByType.map { + case (pos, i) => pos -> ImplicitInfo.apply(i) + }.toMap val inTotal = ImplicitInfo.aggregate(perFile.valuesIterator) ImplicitProfiler(perCallSite, perFile, perType, inTotal) } @@ -258,7 +263,7 @@ final class ProfilingImpl[G <: Global]( } override def pluginsNotifyImplicitSearch(search: global.analyzer.ImplicitSearch): Unit = { - if (StatisticsStatics.areSomeColdStatsEnabled() && statistics.areStatisticsLocallyEnabled) { + if (SettingsOps.areStatisticsEnabled(global)) { val targetType = search.pt val targetPos = search.pos @@ -317,7 +322,7 @@ final class ProfilingImpl[G <: Global]( override def pluginsNotifyImplicitSearchResult(result: global.analyzer.SearchResult): Unit = { super.pluginsNotifyImplicitSearchResult(result) - if (StatisticsStatics.areSomeColdStatsEnabled() && statistics.areStatisticsLocallyEnabled) { + if (SettingsOps.areStatisticsEnabled(global)) { // 1. Get timer of the running search val (search, implicitTypeStart, searchStart) = implicitsStack.head val targetType = search.pt @@ -442,8 +447,8 @@ final class ProfilingImpl[G <: Global]( //private final val EmptyRepeatedValue = RepeatedValue(EmptyTree, EmptyTree, 0) //private[ProfilingImpl] val repeatedTrees = perRunCaches.newMap[RepeatedKey, RepeatedValue] - val macroInfos = perRunCaches.newAnyRefMap[Position, MacroInfo] - val searchIdsToMacroStates = perRunCaches.newMap[Int, List[MacroState]] + val macroInfos = perRunCaches.newAnyRefMap[Position, MacroInfo]() + val searchIdsToMacroStates = perRunCaches.newMap[Int, List[MacroState]]() private val macroIdsToTimers = perRunCaches.newMap[Int, statistics.Timer]() private val macroChildren = perRunCaches.newMap[Int, List[MacroEntry]]() private val stackedNanos = perRunCaches.newMap[Int, Long]() @@ -623,7 +628,7 @@ final class ProfilingImpl[G <: Global]( val macroTypeCounter = macrosByType.getOrElse(expandedType, 0) macrosByType.update(expandedType, macroTypeCounter + 1) - val callSitePos = expandee.pos + val callSitePos = this.expandee.pos /* val printedExpandee = showRaw(expandee) val printedExpanded = showRaw(expanded) val key = (printedExpandee, printedExpanded) diff --git a/plugin/src/main/scala/ch/epfl/scala/profilers/tools/Logger.scala b/plugin/src/main/scala/ch/epfl/scala/profilers/tools/Logger.scala index 2890af2..3109673 100644 --- a/plugin/src/main/scala/ch/epfl/scala/profilers/tools/Logger.scala +++ b/plugin/src/main/scala/ch/epfl/scala/profilers/tools/Logger.scala @@ -18,7 +18,7 @@ final class Logger[G <: scala.tools.nsc.Global](val global: G) { debug(wrap(msg, scala.Console.GREEN)) def info(msg: String): Unit = - global.reporter.info(NoPosition, msg, true) + global.reporter.echo(NoPosition, msg) def info[T: pprint.TPrint](header: String, value: T): Unit = { val tokens = pprint.tokenize(value, height = 100000000).mkString info(s"$header:\n$tokens") diff --git a/plugin/src/main/scala/ch/epfl/scala/profilers/tools/QuantitiesHijacker.scala b/plugin/src/main/scala/ch/epfl/scala/profilers/tools/QuantitiesHijacker.scala index cdf1305..15c051e 100644 --- a/plugin/src/main/scala/ch/epfl/scala/profilers/tools/QuantitiesHijacker.scala +++ b/plugin/src/main/scala/ch/epfl/scala/profilers/tools/QuantitiesHijacker.scala @@ -8,7 +8,13 @@ object QuantitiesHijacker { type Quantities = mutable.HashMap[String, Statistics#Quantity] def getRegisteredQuantities[G <: Global](global: G): Quantities = { val clazz = global.statistics.getClass() - val method = clazz.getMethod("scala$reflect$internal$util$Statistics$$qs") - method.invoke(global.statistics).asInstanceOf[Quantities] + try { // see: https://github.com/scalacenter/scalac-profiling/pull/32/files#r790111968 + val field = clazz.getField("scala$reflect$internal$util$Statistics$$qs") + field.get(global.statistics).asInstanceOf[Quantities] + } catch { + case _: NoSuchFieldException => + val method = clazz.getMethod("scala$reflect$internal$util$Statistics$$qs") + method.invoke(global.statistics).asInstanceOf[Quantities] + } } } diff --git a/plugin/src/test/scala/ch/epfl/scala/tools/TestUtil.scala b/plugin/src/test/scala/ch/epfl/scala/tools/TestUtil.scala index b72c531..a7773e1 100644 --- a/plugin/src/test/scala/ch/epfl/scala/tools/TestUtil.scala +++ b/plugin/src/test/scala/ch/epfl/scala/tools/TestUtil.scala @@ -37,20 +37,20 @@ object TestUtil { m.mkToolBox(options = compileOptions) } - def getResourceContent(resourceName: String) = { + def getResourceContent(resourceName: String): String = { val resource = getClass.getClassLoader.getResource(resourceName) val file = scala.io.Source.fromFile(resource.toURI) - file.getLines.mkString + file.getLines().mkString("") } - lazy val toolboxClasspath = getResourceContent("toolbox.classpath") - lazy val toolboxPluginOptions = getResourceContent("toolbox.extra") + lazy val toolboxClasspath: String = getResourceContent("toolbox.classpath") + lazy val toolboxPluginOptions: String = getResourceContent("toolbox.extra") def expectError( errorSnippet: String, compileOptions: String = "", baseCompileOptions: String = - s"-cp $toolboxClasspath $toolboxPluginOptions")(code: String) = { + s"-cp $toolboxClasspath $toolboxPluginOptions")(code: String): Unit = { val errorMessage = intercept[ToolBoxError] { eval(code, s"$compileOptions $baseCompileOptions") }.getMessage diff --git a/project/BuildPlugin.scala b/project/BuildPlugin.scala index 7f028e7..f995a50 100644 --- a/project/BuildPlugin.scala +++ b/project/BuildPlugin.scala @@ -9,11 +9,11 @@ package ch.epfl.scala.profiling.build -import sbt.{AutoPlugin, Def, Keys, PluginTrigger, Plugins, ProjectRef} +import sbt._ object BuildPlugin extends AutoPlugin { override def trigger: PluginTrigger = allRequirements - override def requires: Plugins = ch.epfl.scala.sbt.release.ReleaseEarlyPlugin + override def requires: Plugins = plugins.JvmPlugin val autoImport = BuildKeys override def globalSettings: Seq[Def.Setting[_]] = @@ -25,8 +25,6 @@ object BuildPlugin extends AutoPlugin { } object BuildKeys { - import sbt.{settingKey, taskKey, richFile, file, uri, toGroupID} - import sbt.{RootProject, ProjectRef, Setting, Compile, BuildRef, Reference} final val enableStatistics = settingKey[Boolean]("Enable performance debugging if true.") final val optionsForSourceCompilerPlugin = @@ -34,8 +32,6 @@ object BuildKeys { final val allDepsForCompilerPlugin = taskKey[Def.Classpath]("Return all dependencies for the source compiler plugin.") final val showScalaInstances = taskKey[Unit]("Show versions of all integration tests") - final val useScalacFork = - settingKey[Boolean]("Make every module use the Scala fork instead latest Scala 2.12.x.") // Refer to setting via reference because there is no dependency to the scalac build here. final val scalacVersionSuffix = sbt.SettingKey[String]("baseVersionSuffix") @@ -44,84 +40,42 @@ object BuildKeys { final val AbsolutePath = file(".").getCanonicalFile.getAbsolutePath final val HomeBuild = BuildRef(RootProject(file(AbsolutePath)).build) - // Source dependency is a submodule that we modify - final val Scalac = RootProject(file(s"$AbsolutePath/scalac")) - final val ScalacBuild = BuildRef(Scalac.build) - final val ScalacCompiler = ProjectRef(Scalac.build, "compiler") - final val ScalacLibrary = ProjectRef(Scalac.build, "library") - final val ScalacReflect = ProjectRef(Scalac.build, "reflect") - final val ScalacDist = ProjectRef(Scalac.build, "dist") - final val AllScalacProjects = List(ScalacCompiler, ScalacLibrary, ScalacReflect) - - final val VscodeScala = RootProject(file(s"$AbsolutePath/vscode-scala")) - final val VscodeImplementation = ProjectRef(VscodeScala.build, "ensime-lsp") + // final val VscodeScala = RootProject(file(s"$AbsolutePath/vscode-scala")) + // final val VscodeImplementation = ProjectRef(VscodeScala.build, "ensime-lsp") // Source dependencies from git are cached by sbt - val Circe = RootProject( - uri("git://github.com/jvican/circe.git#74daecae981ff5d7521824fea5304f9cb52dbac9") - ) - val Monocle = RootProject( - uri("git://github.com/jvican/Monocle.git#5da7c1ac8ffd3942a843dca9cd1fbb281ff08412") - ) - val Scalatest = RootProject( - uri("git://github.com/jvican/scalatest.git#c5fcbe35097a152a6595aa63ea25b15f237a7970") - ) val BetterFiles = RootProject( - uri("git://github.com/jvican/better-files.git#29270d200bdc5715be0fb6875b00718de2996641") + uri("https://git@github.com/pathikrit/better-files.git#6f2e3f1328b1b18eddce973510db71bc6c14fadb") // v3.9.2 ) - val Shapeless = RootProject( - uri("git://github.com/jvican/shapeless.git#a42cd4c1c99e4a7be36e0239d3ee944a6355e321") - ) - val Magnolia = RootProject( - uri("git://github.com/jvican/magnolia.git#249eb311a78b2967dcdf388576bd5eaa7c55c8fa") + val Wartremover = RootProject( + uri("https://git@github.com/wartremover/wartremover.git#29bb7b69ad49eb87c19d9ba865298071c2795bb7") // v3.1.4 ) - val CirceTests = ProjectRef(Circe.build, "tests") - val MonocleExample = ProjectRef(Monocle.build, "example") - val MonocleTests = ProjectRef(Monocle.build, "testJVM") - val ScalatestCore = ProjectRef(Scalatest.build, "scalatest") - val ScalatestTests = ProjectRef(Scalatest.build, "scalatest-test") val BetterFilesCore = ProjectRef(BetterFiles.build, "core") - val ShapelessCore = ProjectRef(Shapeless.build, "coreJVM") - val ShapelessExamples = ProjectRef(Shapeless.build, "examplesJVM") - val MagnoliaTests = ProjectRef(Magnolia.build, "tests") - - val IntegrationProjectsAndReferences = List( - CirceTests -> "CirceTests", - MonocleExample -> "MonocleExample", - MonocleTests -> "MonocleTests", - ScalatestCore -> "ScalatestCore", - ScalatestTests -> "ScalatestTests", + val WartremoverCore = ProjectRef(Wartremover.build, "core") + + val IntegrationProjectsAndReferences = List[(ProjectRef, String)]( BetterFilesCore -> "BetterFilesCore", - ShapelessCore -> "ShapelessCore", - ShapelessExamples -> "ShapelessExamples", - MagnoliaTests -> "MagnoliaTests" - // Enable the scalac compiler when it's not used as a fork - // ScalacCompiler, + WartremoverCore -> "WartremoverCore", ) val AllIntegrationProjects = IntegrationProjectsAndReferences.map(_._1) // Assumes that the previous scala version is the last bincompat version - final val ScalacVersion = Keys.version in BuildKeys.ScalacCompiler - final val ScalacScalaVersion = Keys.scalaVersion in BuildKeys.ScalacCompiler - - final val testDependencies = List( - "junit" % "junit" % "4.12" % "test", - "com.novocode" % "junit-interface" % "0.11" % "test" - ) + // final val ScalacVersion = Keys.version in BuildKeys.ScalacCompiler + // final val ScalacScalaVersion = Keys.scalaVersion in BuildKeys.ScalacCompiler /** Write all the compile-time dependencies of the compiler plugin to a file, * in order to read it from the created Toolbox to run the neg tests. */ lazy val generateToolboxClasspath = Def.task { - val scalaBinVersion = (Keys.scalaBinaryVersion in Compile).value - val targetDir = (Keys.target in Compile).value + val scalaBinVersion = (Compile / Keys.scalaBinaryVersion).value + val targetDir = (Compile / Keys.target).value val compiledClassesDir = targetDir / s"scala-$scalaBinVersion/classes" val testClassesDir = targetDir / s"scala-$scalaBinVersion/test-classes" val libraryJar = Keys.scalaInstance.value.libraryJar.getAbsolutePath - val deps = (Keys.libraryDependencies in Compile).value.mkString(":") + val deps = (Compile / Keys.libraryDependencies).value.mkString(":") val classpath = s"$compiledClassesDir:$testClassesDir:$libraryJar:$deps" - val resourceDir = (Keys.resourceManaged in Compile).value + val resourceDir = (Compile / Keys.resourceManaged).value val toolboxTestClasspath = resourceDir / "toolbox.classpath" sbt.IO.write(toolboxTestClasspath, classpath) List(toolboxTestClasspath.getAbsoluteFile) @@ -147,7 +101,7 @@ object BuildKeys { * at the project level, which is bad practice). So, finding a repro for this * is going to be fun. */ - final val hijacked = sbt.AttributeKey[Boolean]("The hijacked sexy option.") + final val hijacked = sbt.AttributeKey[Boolean]("the hijacked sexy option.") //////////////////////////////////////////////////////////////////////////////// @@ -157,33 +111,19 @@ object BuildKeys { def inProjectRefs(refs: Seq[Reference])(ss: Setting[_]*): Seq[Setting[_]] = refs.flatMap(inProject(_)(ss)) - private[build] def inScalacProjects(ss: Setting[_]*): Seq[Setting[_]] = - inProjectRefs(AllScalacProjects)(ss: _*) - def inCompileAndTest(ss: Setting[_]*): Seq[Setting[_]] = Seq(sbt.Compile, sbt.Test).flatMap(sbt.inConfig(_)(ss)) object Keywords { - val Circe = " circe" - val Monocle = " monocle" val Integration = " integration" - val Scalatest = " scalatest" - val Scalac = " scalac" val BetterFiles = " better-files" - val Shapeless = " shapeless" - val Magnolia = " magnolia" + val Wartremover = " wartremover" } - // Circe has to be always at the beginning private val AllKeywords = List( - Keywords.Circe, - Keywords.Monocle, Keywords.Integration, - Keywords.Scalatest, - Keywords.Scalac, Keywords.BetterFiles, - Keywords.Shapeless, - Keywords.Magnolia + Keywords.Wartremover, ) import sbt.complete.Parser @@ -196,8 +136,6 @@ object BuildKeys { } object BuildImplementation { - import sbt.{url, file, richFile, State, Logger} - import sbt.{Developer, Resolver, ThisBuild, Watched, Compile, Test} // This should be added to upstream sbt. def GitHub(org: String, project: String): java.net.URL = @@ -205,61 +143,28 @@ object BuildImplementation { def GitHubDev(handle: String, fullName: String, email: String) = Developer(handle, fullName, email, url(s"https://github.com/$handle")) - import com.typesafe.sbt.SbtPgp.autoImport.PgpKeys - import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{autoImport => ReleaseEarlyKeys} + // import ch.epfl.scala.sbt.release.ReleaseEarlyPlugin.{autoImport => ReleaseEarlyKeys} final val PluginProject = sbt.LocalProject("plugin") private final val ThisRepo = GitHub("scalacenter", "scalac-profiling") final val publishSettings: Seq[Def.Setting[_]] = Seq( Keys.startYear := Some(2017), Keys.autoAPIMappings := true, - Keys.publishMavenStyle := true, Keys.homepage := Some(ThisRepo), - Keys.publishArtifact in Test := false, + Test / Keys.publishArtifact := false, Keys.licenses := Seq("Apache-2.0" -> url("https://opensource.org/licenses/Apache-2.0")), Keys.developers := List(GitHubDev("jvican", "Jorge Vicente Cantero", "jorge@vican.me")), - PgpKeys.pgpPublicRing := { - if (sys.env.get("CI").isDefined) file("/drone/.gnupg/pubring.asc") - else PgpKeys.pgpPublicRing.value - }, - PgpKeys.pgpSecretRing := { - if (sys.env.get("CI").isDefined) file("/drone/.gnupg/secring.asc") - else PgpKeys.pgpSecretRing.value - }, - ReleaseEarlyKeys.releaseEarlyWith := ReleaseEarlyKeys.SonatypePublisher, + // ReleaseEarlyKeys.releaseEarlyWith := ReleaseEarlyKeys.SonatypePublisher, Keys.pomExtra := scala.xml.NodeSeq.Empty ) - // Paranoid level: removes doc generation by all means - final val scalacSettings: Seq[Def.Setting[_]] = BuildKeys.inScalacProjects( - Keys.aggregate in Keys.doc := false, - Keys.sources in Compile in Keys.doc := Seq.empty, - Keys.scalacOptions in Compile in Keys.doc := Seq.empty, - Keys.publishArtifact in Compile in Keys.packageDoc := false, - // Use snapshot only for local development plz. - // If placed in global settings, it's not applied. Sbt bug? Ordinary order init in sourcedeps bug. - BuildKeys.scalacVersionSuffix in BuildKeys.Scalac := BuildDefaults.scalacVersionSuffix.value - ) - object BuildDefaults { - final val scalacVersionSuffix = Def.setting { - val previousSuffix = (BuildKeys.scalacVersionSuffix in BuildKeys.Scalac).value - if (!previousSuffix.contains("stats")) s"stats-${previousSuffix}" else previousSuffix - } final val showScalaInstances: Def.Initialize[sbt.Task[Unit]] = Def.task { val logger = Keys.streams.value.log - logger.info((Keys.name in Test in BuildKeys.CirceTests).value) - logger.info((Keys.scalaInstance in Test in BuildKeys.CirceTests).value.toString) - logger.info((Keys.name in Test in BuildKeys.MonocleTests).value) - logger.info((Keys.scalaInstance in Test in BuildKeys.MonocleTests).value.toString) - logger.info((Keys.name in Test in BuildKeys.MonocleExample).value) - logger.info((Keys.scalaInstance in Test in BuildKeys.MonocleExample).value.toString) - logger.info((Keys.name in Test in BuildKeys.ScalatestCore).value) - logger.info((Keys.scalaInstance in Test in BuildKeys.ScalatestCore).value.toString) - logger.info((Keys.name in BuildKeys.ScalacCompiler).value) - logger.info((Keys.scalaInstance in BuildKeys.ScalacCompiler).value.toString) - logger.info((Keys.name in Test in BuildKeys.BetterFilesCore).value) - logger.info((Keys.scalaInstance in Test in BuildKeys.BetterFilesCore).value.toString) + logger.info((BuildKeys.BetterFilesCore / Test / Keys.name).value) + logger.info((BuildKeys.BetterFilesCore / Test / Keys.scalaInstance).value.toString) + logger.info((BuildKeys.WartremoverCore / Compile / Keys.name).value) + logger.info((BuildKeys.WartremoverCore / Compile / Keys.scalaInstance).value.toString) () } @@ -269,72 +174,22 @@ object BuildImplementation { sbt.WorkingPluginCross.pluginSwitch +: pruned } - val fixScalaVersionForSbtPlugin: Def.Initialize[String] = Def.setting { - val orig = Keys.scalaVersion.value - val is013 = (Keys.sbtVersion in Keys.pluginCrossBuild).value.startsWith("0.13") - if (is013) "2.10.6" else orig - } - type Hook = Def.Initialize[State => State] - private final val UnknownHash = "UNKNOWN" - final val publishForkScalac: Hook = Def.setting { (state: State) => - import sbt.IO - import com.typesafe.sbt.git.JGit - // Only publish scalac if file doesn't exist - val baseDirectory = (Keys.baseDirectory in ThisBuild).value - val scalacHashFile = baseDirectory./(".scalac-hash") - val repository = JGit(baseDirectory./("scalac")) - // If sha cannot be fetched, always force publishing of fork. - val currentHash = repository.headCommitSha.getOrElse(UnknownHash) - if (!repository.hasUncommittedChanges && - scalacHashFile.exists() && - currentHash == IO.read(scalacHashFile)) { - state - } else { - val logger = Keys.sLog.value - val extracted = sbt.Project.extract(state) - val buildData = extracted.structure.data - val maybeVersion = BuildKeys.ScalacVersion.get(buildData).get - val newState = publishCustomScalaFork(state, maybeVersion, logger) - if (currentHash != UnknownHash) - IO.write(scalacHashFile, currentHash) - newState - } - } - - private[build] val MinimumScalaVersion = "2.12.6" - def pickScalaVersion: Def.Initialize[String] = Def.settingDyn { - if (!BuildKeys.useScalacFork.value) Def.setting(MinimumScalaVersion) - // 2.12.3 has no statistics, so if scalaHome isn't used it will fail to compile - else Def.setting("2.12.3") - } - def scalacProfilingScalacOptions(ref: ProjectRef): Def.Initialize[sbt.Task[Seq[String]]] = { Def.task { val projectBuild = ref.build val workingDir = Keys.buildStructure.value.units(projectBuild).localBase.getAbsolutePath val sourceRoot = s"-P:scalac-profiling:sourceroot:$workingDir" val noProfileDb = s"-P:scalac-profiling:no-profiledb" - val pluginOpts = (BuildKeys.optionsForSourceCompilerPlugin in PluginProject).value + val pluginOpts = (PluginProject / BuildKeys.optionsForSourceCompilerPlugin).value noProfileDb +: sourceRoot +: pluginOpts } } - def setUpScalaHome: Def.Initialize[Option[sbt.File]] = Def.setting { - if (!BuildKeys.useScalacFork.value) None - else { - val pathToHome = new java.io.File(s"${BuildKeys.Scalac.build.toURL().getFile()}build/pack") - if (!pathToHome.exists()) { - Keys.sLog.value.warn(s"Scala home $pathToHome didn't exist yet.") - } - Some(pathToHome) - } - } - def setUpUnmanagedJars: Def.Initialize[sbt.Task[Def.Classpath]] = Def.task { - val previousJars = Keys.unmanagedJars.in(Compile).value - val allPluginDeps = BuildKeys.allDepsForCompilerPlugin.in(PluginProject).value + val previousJars = (Compile / Keys.unmanagedJars).value + val allPluginDeps = (PluginProject / BuildKeys.allDepsForCompilerPlugin).value previousJars ++ allPluginDeps } @@ -342,31 +197,25 @@ object BuildImplementation { private final val build = "_root_.ch.epfl.scala.profiling.build" def scalacProfilingScalacOptionsRef(ref: String): String = s"${build}.BuildImplementation.BuildDefaults.scalacProfilingScalacOptions($ref)" - final val setUpScalaHomeRef: String = - s"${build}.BuildImplementation.BuildDefaults.setUpScalaHome" final val setUpUnmanagedJarsRef: String = s"${build}.BuildImplementation.BuildDefaults.setUpUnmanagedJars" } def setUpSourceDependenciesCmd(refs: List[String]): Def.Initialize[String] = { Def.setting { - val scalaVersion = BuildDefaults.pickScalaVersion.value + val scalaV = Keys.scalaVersion.value def setScalaVersion(ref: String) = - s"""${Keys.scalaVersion.key.label} in $ref := "$scalaVersion"""" + s"""$ref / ${Keys.scalaVersion.key.label} := "$scalaV"""" def setScalacOptions(ref: String) = - s"""${Keys.scalacOptions.key.label} in $ref := ${MethodRefs.scalacProfilingScalacOptionsRef(ref)}.value""".stripMargin - def setScalaHome(ref: String) = - s"""${Keys.scalaHome.key.label} in $ref := ${MethodRefs.setUpScalaHomeRef}.value""" + s"""$ref / ${Keys.scalacOptions.key.label} := ${MethodRefs.scalacProfilingScalacOptionsRef(ref)}.value""".stripMargin def setUnmanagedJars(ref: String, config: String) = - s"""${Keys.unmanagedJars.key.label} in $config in $ref := ${MethodRefs.setUpUnmanagedJarsRef}.value""" - val msg = - if (!BuildKeys.useScalacFork.value) "The build integrations are set up." - else s"The build integrations are using a local Scalac home." - val setLoadMessage = s"""${Keys.onLoadMessage.key.label} in sbt.Global := "$msg"""" + s"""$ref / $config / ${Keys.unmanagedJars.key.label} := ${MethodRefs.setUpUnmanagedJarsRef}.value""" + val msg = "The build integrations are set up." + val setLoadMessage = s"""sbt.Global / ${Keys.onLoadMessage.key.label} := "$msg"""" val allSettingsRedefinitions = refs.flatMap { ref => val setsUnmanagedJars = List(setUnmanagedJars(ref, "Compile"), setUnmanagedJars(ref, "Test")) - List(setScalaVersion(ref), setScalacOptions(ref), setScalaHome(ref)) ++ setsUnmanagedJars + List(setScalaVersion(ref), setScalacOptions(ref)) ++ setsUnmanagedJars } ++ List(setLoadMessage) s"set List(${allSettingsRedefinitions.mkString(",")})" @@ -382,63 +231,50 @@ object BuildImplementation { } final val customOnLoad: Hook = Def.settingDyn { - if (!BuildKeys.useScalacFork.value) Def.setting(hijackScalaVersions.value) - else Def.setting(publishForkScalac.value andThen hijackScalaVersions.value) + Def.setting(hijackScalaVersions.value) } } final val globalSettings: Seq[Def.Setting[_]] = Seq( - Keys.testOptions in Test += sbt.Tests.Argument("-oD"), - BuildKeys.useScalacFork := false, + Test / Keys.testOptions += sbt.Tests.Argument("-oD"), + // BuildKeys.useScalacFork := false, Keys.commands ~= BuildDefaults.fixPluginCross _, Keys.onLoadMessage := Header.intro, Keys.onLoad := (Keys.onLoad in sbt.Global).value andThen (BuildDefaults.customOnLoad.value) ) final val commandAliases: Seq[Def.Setting[sbt.State => sbt.State]] = { - val scalacRef = sbt.Reference.display(BuildKeys.ScalacBuild) - val scalac = sbt.addCommandAlias("scalac", s"project ${scalacRef}") + // val scalacRef = sbt.Reference.display(BuildKeys.ScalacBuild) + // val scalac = sbt.addCommandAlias("scalac", s"project ${scalacRef}") val homeRef = sbt.Reference.display(BuildKeys.HomeBuild) val home = sbt.addCommandAlias("home", s"project ${homeRef}") - scalac ++ home + home } final val buildSettings: Seq[Def.Setting[_]] = Seq( Keys.organization := "ch.epfl.scala", Keys.resolvers += Resolver.jcenterRepo, Keys.updateOptions := Keys.updateOptions.value.withCachedResolution(true), - Keys.scalaVersion := BuildKeys.ScalacScalaVersion.value, - Keys.triggeredMessage := Watched.clearWhenTriggered, + Keys.scalaVersion := "2.12.18", + sbt.nio.Keys.watchTriggeredMessage := Watch.clearScreenOnTrigger, BuildKeys.enableStatistics := true, BuildKeys.showScalaInstances := BuildDefaults.showScalaInstances.value ) ++ publishSettings ++ commandAliases final val projectSettings: Seq[Def.Setting[_]] = Seq( - Keys.scalacOptions in Compile := reasonableCompileOptions, + Compile / Keys.scalacOptions := { + val base = ( + "-deprecation" :: "-encoding" :: "UTF-8" :: "-feature" :: "-language:existentials" :: + "-language:higherKinds" :: "-language:implicitConversions" :: "-unchecked" :: + "-Ywarn-numeric-widen" :: "-Xlint" :: Nil + ) + + if (Keys.scalaVersion.value.startsWith("2.13")) base else base :+ "-Xfuture" + }, // Necessary because the scalac version has to be always SNAPSHOT to avoid caching issues // Scope here is wrong -- we put it here temporarily until this is fixed upstream - ReleaseEarlyKeys.releaseEarlyBypassSnapshotCheck := true - ) ++ scalacSettings - - final val reasonableCompileOptions = ( - "-deprecation" :: "-encoding" :: "UTF-8" :: "-feature" :: "-language:existentials" :: - "-language:higherKinds" :: "-language:implicitConversions" :: "-unchecked" :: - "-Yno-adapted-args" :: "-Ywarn-numeric-widen" :: "-Xfuture" :: "-Xlint" :: Nil + // ReleaseEarlyKeys.releaseEarlyBypassSnapshotCheck := true ) - - private final val mkPack = sbt.taskKey[java.io.File]("mkPack") - // This is only used when we use the fork instead of upstream. As of 2.12.4, we use upstream. - private def publishCustomScalaFork(state0: State, version: String, logger: Logger): State = { - import sbt.{Project, Value, Inc, Incomplete} - logger.warn(s"Publishing Scala version $version from the fork...") - // Bah, reuse the same state for everything. - Project.runTask(mkPack in BuildKeys.ScalacDist, state0) match { - case None => sys.error(s"Key for publishing is not defined?") - case Some((newState, Value(v))) => newState - case Some((newState, Inc(inc))) => - sys.error(s"Got error when publishing the Scala fork: $inc") - } - } } object Header { diff --git a/project/WorkingPluginCross.scala b/project/WorkingPluginCross.scala index 07c0deb..5e0998a 100644 --- a/project/WorkingPluginCross.scala +++ b/project/WorkingPluginCross.scala @@ -3,8 +3,9 @@ package sbt import sbt.complete.Parser import sbt.complete.DefaultParsers._ import sbt.Keys._ -import sbt.CommandStrings._ +import sbt.internal.CommandStrings._ import Cross.{requireSession, spacedFirst} +import sbt.internal.SettingCompletions object WorkingPluginCross { final val oldPluginSwitch = sbt.PluginCross.pluginSwitch @@ -35,7 +36,7 @@ object WorkingPluginCross { inScope(GlobalScope.copy(project = Select(currentRef)))( Seq(scalaVersion := PluginCross.scalaVersionSetting.value) ) - val session = SettingCompletions.setThis(state, x, add, "").session + val session = SettingCompletions.setThis(x, add, "").session BuiltinCommands.reapply(session, structure, command :: state) } } diff --git a/project/build.properties b/project/build.properties index 133a8f1..2743082 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.17 +sbt.version=1.9.6 diff --git a/project/build.sbt b/project/build.sbt index 7efaf60..59c12ab 100644 --- a/project/build.sbt +++ b/project/build.sbt @@ -1,19 +1,14 @@ lazy val root = project .in(file(".")) .settings( - // Coursier bug: coursier fails to resolve source dependencies because - // it looks for the jar of the project name even if it is just a source dep - // addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC8"), - addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.9.3"), - addSbtPlugin("ch.epfl.scala" % "sbt-release-early" % "1.2.0"), - addSbtPlugin("com.thesamet" % "sbt-protoc" % "0.99.11"), - addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5"), - addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.0.0-M10"), - // Let's add our sbt plugin to the sbt too ;) - unmanagedSourceDirectories in Compile ++= { - val pluginMainDir = baseDirectory.value.getParentFile / "sbt-plugin" / "src" / "main" - List(pluginMainDir / "scala", pluginMainDir / s"scala-sbt-${Keys.sbtBinaryVersion.value}") - }, - libraryDependencies += "com.trueaccord.scalapb" %% "compilerplugin" % "0.6.2", - libraryDependencies += "org.scala-sbt" % "scripted-plugin" % sbtVersion.value + addSbtPlugin("com.github.sbt" % "sbt-git" % "2.0.1"), + addSbtPlugin("com.thesamet" % "sbt-protoc" % "1.0.6"), + addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "2.1.3"), + addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12"), + // // Let's add our sbt plugin to the sbt too ;) + // unmanagedSourceDirectories in Compile ++= { + // val pluginMainDir = baseDirectory.value.getParentFile / "sbt-plugin" / "src" / "main" + // List(pluginMainDir / "scala", pluginMainDir / s"scala-sbt-${Keys.sbtBinaryVersion.value}") + // }, + libraryDependencies += "com.thesamet.scalapb" %% "compilerplugin" % "0.11.13", ) diff --git a/project/project/build.properties b/project/project/build.properties index c091b86..2743082 100644 --- a/project/project/build.properties +++ b/project/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.16 +sbt.version=1.9.6 diff --git a/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/ProfilingSbtPlugin.scala b/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/ProfilingSbtPlugin.scala index 9fb735f..f8ca36e 100644 --- a/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/ProfilingSbtPlugin.scala +++ b/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/ProfilingSbtPlugin.scala @@ -10,8 +10,7 @@ package sbt.ch.epfl.scala import java.util.concurrent.ConcurrentHashMap - -import sbt.{AutoPlugin, Def, Keys, PluginTrigger} +import sbt.{AutoPlugin, Def, Keys, PluginTrigger, Select} object ProfilingSbtPlugin extends AutoPlugin { override def trigger: PluginTrigger = allRequirements @@ -35,7 +34,7 @@ object BuildKeys { object ProfilingPluginImplementation { import java.lang.{Long => BoxedLong} - import sbt.{Compile, Test, ConsoleLogger, Project, Task, ScopedKey, Tags} + import sbt.{Compile, Test, Project, Task, ScopedKey, Tags} private val timingsForCompilers = new ConcurrentHashMap[ClassLoader, BoxedLong]() private val timingsForKeys = new ConcurrentHashMap[ScopedKey[_], BoxedLong]() @@ -45,18 +44,18 @@ object ProfilingPluginImplementation { Keys.commands += BuildDefaults.profilingWarmupCommand, BuildKeys.profilingWarmupDuration := BuildDefaults.profilingWarmupDuration.value, Keys.concurrentRestrictions += Tags.limit(WarmupTag, 1), - Keys.executeProgress := { _ => - val debug = (Keys.logLevel in Keys.executeProgress).value == sbt.Level.Debug - new Keys.TaskProgress(new SbtTaskTimer(timingsForKeys, debug)) + Keys.progressReports := { + val debug = (Keys.progressReports / Keys.logLevel).value == sbt.Level.Debug + Seq(new Keys.TaskProgress(new SbtTaskTimer(timingsForKeys, debug))) }, - Keys.logLevel in Keys.executeProgress := sbt.Level.Info + Keys.progressReports / Keys.logLevel := sbt.Level.Info ) val buildSettings: Seq[Def.Setting[_]] = Nil val projectSettings: Seq[Def.Setting[_]] = List( - BuildKeys.profilingWarmupCompiler in Compile := + Compile / BuildKeys.profilingWarmupCompiler := BuildDefaults.profilingWarmupCompiler.tag(WarmupTag).value, - BuildKeys.profilingWarmupCompiler in Test := + Test / BuildKeys.profilingWarmupCompiler := BuildDefaults.profilingWarmupCompiler.tag(WarmupTag).value ) @@ -74,7 +73,7 @@ object ProfilingPluginImplementation { case Right(cmd) => cmd() case Left(msg) => sys.error(s"Invalid programmatic input:\n$msg") } - nextState.remainingCommands.toList match { + nextState.remainingCommands match { case Nil => nextState case head :: tail => runCommand(head, nextState.copy(remainingCommands = tail)) } @@ -132,14 +131,14 @@ object ProfilingPluginImplementation { val logger = st0.log val extracted = Project.extract(st0) - val (st1, compilers) = extracted.runTask(Keys.compilers in extracted.currentRef, st0) + val (st1, compilers) = extracted.runTask(extracted.currentRef / Keys.compilers, st0) val compilerLoader = compilers.scalac.scalaInstance.loader() val warmupDurationMs = extracted.get(BuildKeys.profilingWarmupDuration) * 1000 var currentDurationMs = getWarmupTime(compilerLoader) - val baseScope = Scope.ThisScope.in(currentProject) - val scope = currentConfigKey.map(k => baseScope.in(k)).getOrElse(baseScope) + val baseScope = Scope.ThisScope.copy(project = Select(currentProject)) + val scope = currentConfigKey.map(k => baseScope.copy(config = Select(k))).getOrElse(baseScope) val classDirectory = extracted.get(Keys.classDirectory.in(scope)) val compileKeyRef = Keys.compile.in(scope) // We get the scope from `taskDefinitionKey` to be the same than the timer uses. diff --git a/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/SbtTaskTimer.scala b/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/SbtTaskTimer.scala index d42d2c7..acab476 100644 --- a/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/SbtTaskTimer.scala +++ b/sbt-plugin/src/main/scala/sbt/ch/epfl/scala/SbtTaskTimer.scala @@ -16,7 +16,7 @@ import sbt.{ExecuteProgress, Result, Task, ScopedKey, Def} class SbtTaskTimer(timers: ConcurrentHashMap[ScopedKey[_], BoxedLong], isDebugEnabled: Boolean) extends ExecuteProgress[Task] { - override type S = Unit + type S = Unit override def initial: Unit = {} private def getKey(task: Task[_]): Option[ScopedKey[_]] = @@ -27,14 +27,14 @@ class SbtTaskTimer(timers: ConcurrentHashMap[ScopedKey[_], BoxedLong], isDebugEn import sbt.Task type Tasks = Iterable[sbt.Task[_]] - override def registered(state: Unit, task: Task[_], allDeps: Tasks, pendingDeps: Tasks): Unit = { + override def afterRegistered(task: Task[_], allDeps: Tasks, pendingDeps: Tasks): Unit = { getKey(task) match { case Some(key) => pending.put(key, System.currentTimeMillis()) case None => () } } - override def workFinished[T](task: Task[T], result: Either[Task[T], Result[T]]): Unit = { + override def afterCompleted[A](task: Task[A], result: Result[A]): Unit = { def finishTiming(scopedKey: ScopedKey[_]): Unit = { pending.get(scopedKey) match { case startTime: BoxedLong => @@ -56,13 +56,22 @@ class SbtTaskTimer(timers: ConcurrentHashMap[ScopedKey[_], BoxedLong], isDebugEn } getKey(task) match { - case Some(key) => finishTiming(key) + case Some(key) => { + println(key) + finishTiming(key) + } case None => () // Ignore tasks that do not have key information } + } def workStarting(task: Task[_]): Unit = () def allCompleted(state: Unit, results: sbt.RMap[Task, sbt.Result]): Unit = () def completed[T](state: Unit, task: Task[T], result: sbt.Result[T]): Unit = () def ready(state: Unit, task: Task[_]): Unit = () + def afterAllCompleted(results: sbt.internal.util.RMap[sbt.Task,sbt.Result]): Unit = () + def afterReady(task: sbt.Task[_]): Unit = () + def afterWork[A](task: sbt.Task[A],result: Either[sbt.Task[A],sbt.Result[A]]): Unit = () + def beforeWork(task: sbt.Task[_]): Unit = () + def stop(): Unit = () } diff --git a/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-compile/build.sbt b/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-compile/build.sbt index 32525b5..956f427 100644 --- a/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-compile/build.sbt +++ b/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-compile/build.sbt @@ -1,12 +1,12 @@ -scalaVersion := "2.12.4" +scalaVersion := "2.12.15" profilingWarmupDuration := 20 //////////////////////////////////////////////////////////// val checkCompilerIsWarmedUp = settingKey[Boolean]("") -checkCompilerIsWarmedUp in Global := false +Global / checkCompilerIsWarmedUp := false -compile in Compile := { +Compile / compile := { if (checkCompilerIsWarmedUp.value) sys.error("Compilation of files has been called again!") - (compile in Compile).value + (Compile / compile).value } diff --git a/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-test/build.sbt b/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-test/build.sbt index 1c409ff..1f22de4 100644 --- a/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-test/build.sbt +++ b/sbt-plugin/src/sbt-test/compiler-profiling/warmup-60-seconds-test/build.sbt @@ -1,12 +1,12 @@ -scalaVersion := "2.12.4" +scalaVersion := "2.12.15" profilingWarmupDuration := 20 //////////////////////////////////////////////////////////// val checkCompilerIsWarmedUp = settingKey[Boolean]("") -checkCompilerIsWarmedUp in Global := false +Global / checkCompilerIsWarmedUp := false -compile in Test := { +Test / compile := { if (checkCompilerIsWarmedUp.value) sys.error("Compilation of files has been called again!") - (compile in Test).value + (Test / compile).value } diff --git a/sbt-plugin/src/sbt-test/external-projects/circe b/sbt-plugin/src/sbt-test/external-projects/circe deleted file mode 160000 index 31eade4..0000000 --- a/sbt-plugin/src/sbt-test/external-projects/circe +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 31eade4809214a16041184a59d1f5498ad2f4b3a diff --git a/scalac b/scalac deleted file mode 160000 index d7ae7a8..0000000 --- a/scalac +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d7ae7a8b9668d52699d1e1c5066a22ec89a1d379 diff --git a/scalafix-rewrites/build.sbt b/scalafix-rewrites/build.sbt deleted file mode 100644 index 8d9524e..0000000 --- a/scalafix-rewrites/build.sbt +++ /dev/null @@ -1,29 +0,0 @@ -lazy val V = _root_.scalafix.Versions -// Use a scala version supported by scalafix. -scalaVersion in ThisBuild := V.scala212 - -lazy val rules = project.settings( - libraryDependencies += "ch.epfl.scala" %% "scalafix-core" % V.version -) - -lazy val input = project.settings( - scalafixSourceroot := sourceDirectory.in(Compile).value -) - -lazy val output = project - -lazy val tests = project - .settings( - libraryDependencies += "ch.epfl.scala" % "scalafix-testkit" % V.version % Test cross CrossVersion.full, - buildInfoPackage := "fix", - buildInfoKeys := Seq[BuildInfoKey]( - "inputSourceroot" -> - sourceDirectory.in(input, Compile).value, - "outputSourceroot" -> - sourceDirectory.in(output, Compile).value, - "inputClassdirectory" -> - classDirectory.in(input, Compile).value - ) - ) - .dependsOn(input, rules) - .enablePlugins(BuildInfoPlugin) diff --git a/scalafix-rewrites/input/src/main/scala/fix/InsertImport_v1_0.scala b/scalafix-rewrites/input/src/main/scala/fix/InsertImport_v1_0.scala deleted file mode 100644 index b1af761..0000000 --- a/scalafix-rewrites/input/src/main/scala/fix/InsertImport_v1_0.scala +++ /dev/null @@ -1,12 +0,0 @@ -/* -rule = "class:fix.InsertImport_v1_0" -*/ -package fix -package test - -import scala.Int -import scala.collection.immutable.Set - -object InsertImport_v1_0_Test { - // Add code that needs fixing here. -} diff --git a/scalafix-rewrites/output/src/main/scala/fix/InsertImport_v1_0.scala b/scalafix-rewrites/output/src/main/scala/fix/InsertImport_v1_0.scala deleted file mode 100644 index 478e901..0000000 --- a/scalafix-rewrites/output/src/main/scala/fix/InsertImport_v1_0.scala +++ /dev/null @@ -1,10 +0,0 @@ -package fix -package test - -import scala.Int -import scala.collection.immutable.Set -import _root_.org.scalatest.CachedImplicits - -object InsertImport_v1_0_Test { - // Add code that needs fixing here. -} diff --git a/scalafix-rewrites/project/build.properties b/scalafix-rewrites/project/build.properties deleted file mode 100644 index 133a8f1..0000000 --- a/scalafix-rewrites/project/build.properties +++ /dev/null @@ -1 +0,0 @@ -sbt.version=0.13.17 diff --git a/scalafix-rewrites/project/plugins.sbt b/scalafix-rewrites/project/plugins.sbt deleted file mode 100644 index 47f533f..0000000 --- a/scalafix-rewrites/project/plugins.sbt +++ /dev/null @@ -1,4 +0,0 @@ -addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.5.10") -addSbtPlugin("io.get-coursier" % "sbt-coursier" % "1.0.0-RC9") -addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1") - diff --git a/scalafix-rewrites/readme.md b/scalafix-rewrites/readme.md deleted file mode 100644 index e8f9d54..0000000 --- a/scalafix-rewrites/readme.md +++ /dev/null @@ -1,7 +0,0 @@ -# Scalafix rules for scalac-profiling-rules - -To develop rule: -``` -sbt ~tests/test -# edit rules/src/main/scala/fix/Scalacprofilingrules_v1_0.scala -``` diff --git a/scalafix-rewrites/rules/src/main/scala/fix/InsertImport_v1_0.scala b/scalafix-rewrites/rules/src/main/scala/fix/InsertImport_v1_0.scala deleted file mode 100644 index fe44c45..0000000 --- a/scalafix-rewrites/rules/src/main/scala/fix/InsertImport_v1_0.scala +++ /dev/null @@ -1,11 +0,0 @@ -package fix - -import scalafix._ -import scala.meta._ - -case object InsertImport_v1_0 extends Rule("InsertImport_v1_0") { - val importForCachedImplicits = q"import _root_.org.scalatest.CachedImplicits._".importers.head - override def fix(ctx: RuleCtx): Patch = { - ctx.addGlobalImport(importForCachedImplicits) - } -} diff --git a/scalafix-rewrites/tests/src/test/scala/fix/InsertImport_v1_0_Tests.scala b/scalafix-rewrites/tests/src/test/scala/fix/InsertImport_v1_0_Tests.scala deleted file mode 100644 index 7183d3a..0000000 --- a/scalafix-rewrites/tests/src/test/scala/fix/InsertImport_v1_0_Tests.scala +++ /dev/null @@ -1,14 +0,0 @@ -package fix - -import scala.meta._ -import scalafix._ -import scalafix.testkit._ - -class InsertImport_v1_0_Tests - extends SemanticRuleSuite( - SemanticdbIndex.load(Classpath(AbsolutePath(BuildInfo.inputClassdirectory))), - AbsolutePath(BuildInfo.inputSourceroot), - Seq(AbsolutePath(BuildInfo.outputSourceroot)) - ) { - runAllTests() -}