Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ addCommandAlias(
";scalafmtCheckAll; scalafmtSbtCheck; +test; +publishLocal; scripted"
)

// ScalaTest
libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.9" % Test
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.9" % Test
lazy val root = project.aggregate(compiler, `sbt-source-extract`)

lazy val dependencies = Seq(
"org.scalactic" %% "scalactic" % "3.2.9" % Test,
"org.scalatest" %% "scalatest" % "3.2.9" % Test,
"org.typelevel" %% "cats-core" % "2.4.0"
)

lazy val compilerClasspath = TaskKey[Classpath]("compiler-classpath")

inThisBuild(
List(
Expand All @@ -23,7 +29,7 @@ inThisBuild(
Developer(
"jisantuc",
"James Santucci",
"james.santucci@47deg.com",
"james.santucci@47d1eg.com",
url("https://github.com/jisantuc")
)
)
Expand All @@ -32,13 +38,33 @@ inThisBuild(

(console / initialCommands) := """import io.github.jisantuc.sbtse._"""

enablePlugins(ScriptedPlugin, SbtPlugin)
// set up 'scripted; sbt plugin for testing sbt plugins
scriptedLaunchOpts ++=
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)

ThisBuild / githubWorkflowBuild := Seq(
WorkflowStep.Sbt(List("ci-test"))
)

ThisBuild / githubWorkflowPublishTargetBranches := Seq.empty

lazy val `sbt-source-extract` = (project in file("sbtse"))
.settings(
compilerClasspath := { (compiler / Compile / fullClasspath) }.value,
buildInfoObject := "Meta",
buildInfoPackage := "io.github.jisantuc.sbtse",
buildInfoKeys := Seq(
version,
BuildInfoKey.map(compilerClasspath) { case (_, classFiles) ⇒
("compilerClasspath", classFiles.map(_.data))
}
),
libraryDependencies ++= dependencies,
// set up 'scripted; sbt plugin for testing sbt plugins
scriptedLaunchOpts ++=
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
)
.dependsOn(compiler)
.enablePlugins(BuildInfoPlugin, SbtPlugin, ScriptedPlugin)

lazy val compiler = (project in file("compiler"))
.settings(
libraryDependencies ++= dependencies
)
.enablePlugins(BuildInfoPlugin, SbtPlugin)
14 changes: 14 additions & 0 deletions compiler/src/main/scala/io/github/jisantuc/sbtse/Compiler.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.github.jisantuc.sbtse

class CompilerJava {
def compile(): Array[String] = {
locally(Compiler().test)
println("ok!")
Array.empty
}
}

final case class Compiler() {
lazy val extracter = new Extracter()
val test = extracter.testFn()
}
67 changes: 67 additions & 0 deletions compiler/src/main/scala/io/github/jisantuc/sbtse/Extracter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.github.jisantuc.sbtse

import java.io.File

import scala.annotation.tailrec
import scala.collection.compat._
import scala.reflect.internal.util.BatchSourceFile
import scala.tools.nsc._
import scala.tools.nsc.doc.{Settings => _, _}
import scala.tools.nsc.doc.base.comment.Comment

class Extracter {
private def classPathOfClass(className: String): List[String] = {
val resource = className.split('.').mkString("/", "/", ".class")
val path = getClass.getResource(resource).getPath
if (path.indexOf("file:") >= 0) {
val indexOfFile = path.indexOf("file:") + 5
val indexOfSeparator = path.lastIndexOf('!')
List(path.substring(indexOfFile, indexOfSeparator))
} else {
require(path.endsWith(resource))
List(path.substring(0, path.length - resource.length + 1))
}
}

private lazy val compilerPath =
try classPathOfClass("scala.tools.nsc.Interpreter")
catch {
case e: Throwable =>
throw new RuntimeException(
"Unable to load Scala interpreter from classpath (scala-compiler jar is missing?)",
e
)
}

private lazy val libPath =
try classPathOfClass("scala.AnyVal")
catch {
case e: Throwable =>
throw new RuntimeException(
"Unable to load scala base object from classpath (scala-library jar is missing?)",
e
)
}

lazy val paths: List[String] = compilerPath ::: libPath

// Same settings as
// https://github.com/scala-exercises/sbt-exercise/blob/v0.6.7/compiler/src/main/scala/org/scalaexercises/exercises/compiler/SourceTextExtraction.scal
// except usejavacp.value is set to false.
// that setting controls whether to "Utilize the java.class.path in classpath resolution."
// clearly that was interacting with _something_ poorly (buildinfo plugin? I don't know!)
// but it'll probably be a bit before I understand what.
val defaultSettings = new Settings {
embeddedDefaults[Global.type]
Yrangepos.value = true
usejavacp.value = false

bootclasspath.value = paths.mkString(File.pathSeparator)
classpath.value = paths.mkString(File.pathSeparator)
}
val global = new Global(defaultSettings)

def testFn(): global.Run = {
new global.Run()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.github.jisantuc.sbtse

import org.scalatest.funspec.AnyFunSpec
import org.scalatest.matchers.should.Matchers

class SourceExtractTest extends AnyFunSpec with Matchers {
describe("run without crashing when initialized without classpath hackery") {
it("should do that") {
new CompilerJava().compile()
}
}
}
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
addSbtPlugin("com.codecommit" % "sbt-github-actions" % "0.13.0")
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.10.0")
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package io.github.jisantuc.sbtse

import sbt._
import sbt.Keys._
import sbt.plugins.JvmPlugin

import cats.data.Ior
import cats.syntax.either._
import cats.syntax.monadError._
import scala.util.Random
import sbt.internal.inc.classpath.ClasspathUtil
import java.nio.file.Paths

object SourceExtractPlugin extends AutoPlugin {

override def trigger = allRequirements
override def requires = JvmPlugin

object autoImport {
val testInit =
TaskKey[Unit]("test-init", "run initialization to see if it crashes")
}

import autoImport._

override lazy val projectSettings = Seq(
testInit := locally(testTask.value)
)

override lazy val buildSettings = Seq()

override lazy val globalSettings = Seq()

private def catching[A](f: => A)(msg: => String) =
Either.catchNonFatal(f).leftMap(e => Ior.both(msg, e))

private val COMPILER_CLASS = "io.github.jisantuc.sbtse.CompilerJava"

private type COMPILER = {
def compile(): Array[String]
}

def testTask = Def.task {
val libraryClasspath = Attributed.data((Compile / fullClasspath).value)
val classpath = (Meta.compilerClasspath ++ libraryClasspath).distinct
val loader = ClasspathUtil.toLoader(
classpath.map(file => Paths.get(file.getAbsolutePath())),
null,
ClasspathUtil.createClasspathResources(
appPaths =
Meta.compilerClasspath.map(file => Paths.get(file.getAbsolutePath())),
bootPaths = scalaInstance.value.allJars.map(file =>
Paths.get(file.getAbsolutePath())
)
)
)

val compilerClass = loader.loadClass(COMPILER_CLASS)
val compiler = compilerClass.newInstance.asInstanceOf[COMPILER]
compiler.compile()
}
}
11 changes: 11 additions & 0 deletions sbtse/src/sbt-test/sbt-source-extract/simple/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
version := "0.1"
scalaVersion := "2.12.15"

lazy val simple = (project in file("."))
.settings(
resolvers ++= Seq(
Resolver.sonatypeRepo("snapshots"),
Resolver.defaultLocal
)
)
.enablePlugins(SourceExtractPlugin)
2 changes: 2 additions & 0 deletions sbtse/src/sbt-test/sbt-source-extract/simple/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# check whether the test task runs without crashing
> simple / testInit
30 changes: 0 additions & 30 deletions src/main/scala/io/github/jisantuc/sbtse/SourceextractPlugin.scala

This file was deleted.

4 changes: 0 additions & 4 deletions src/sbt-test/sbt-source-extract/simple/build.sbt

This file was deleted.

2 changes: 0 additions & 2 deletions src/sbt-test/sbt-source-extract/simple/test

This file was deleted.

This file was deleted.