@@ -22,10 +22,9 @@ import scala.util.Try
22
22
import scala .util .control .NonFatal
23
23
import scala .concurrent ._
24
24
import scala .concurrent .duration ._
25
- import scalaz .concurrent .{ Task => ZTask }
25
+ import scalaz .concurrent .Task
26
26
27
- import monix .eval .Task
28
- import monix .execution ._
27
+ import monix .execution .Scheduler
29
28
30
29
import com .twitter .util .Eval ; import Eval ._
31
30
@@ -48,14 +47,15 @@ object EvalResult {
48
47
case object Timeout extends EvalResult [Nothing ]
49
48
case class Success [T ](complilationInfos : CI , result : T , consoleOutput : String ) extends EvalResult [T ]
50
49
case class Timeout [T ]() extends EvalResult [T ]
50
+ case class UnresolvedDependency (error : coursier.FileError ) extends EvalResult [Nothing ]
51
51
case class EvalRuntimeError (complilationInfos : CI , runtimeError : Option [RuntimeError ]) extends EvalResult [Nothing ]
52
52
case class CompilationError (complilationInfos : CI ) extends EvalResult [Nothing ]
53
53
case class GeneralError (stack : Throwable ) extends EvalResult [Nothing ]
54
54
}
55
55
56
- class Evaluator (timeout : FiniteDuration = 20 .seconds) {
57
- implicit val scheduler : Scheduler = Scheduler .io( " evaluation-scheduler " )
58
-
56
+ class Evaluator (timeout : FiniteDuration = 20 .seconds)(
57
+ implicit S : Scheduler
58
+ ) {
59
59
type Dependency = (String , String , String )
60
60
type Remote = String
61
61
@@ -69,28 +69,27 @@ class Evaluator(timeout: FiniteDuration = 20.seconds) {
69
69
(sev, CompilationInfo (msg, Some (RangePosition (pos.start, pos.point, pos.end))) :: Nil )
70
70
}
71
71
72
- def resolveArtifacts (remotes : Seq [Remote ], dependencies : Seq [Dependency ]): Resolution = {
73
- val resolution = Resolution (
74
- dependencies.map(d => {
75
- Dependency (
76
- Module (d._1, d._2), d._3
77
- )
78
- }).toSet
72
+ def remoteToRepository (remote : Remote ): Repository =
73
+ MavenRepository (remote)
74
+
75
+ def dependencyToModule (dependency : Dependency ): coursier.Dependency =
76
+ coursier.Dependency (
77
+ Module (dependency._1, dependency._2), dependency._3
79
78
)
80
- val repositories : Seq [Repository ] = remotes.map(url => MavenRepository (url))
81
79
80
+ def resolveArtifacts (remotes : Seq [Remote ], dependencies : Seq [Dependency ]): Task [Resolution ] = {
81
+ val resolution = Resolution (dependencies.map(dependencyToModule).toSet)
82
+ val repositories : Seq [Repository ] = remotes.map(remoteToRepository)
82
83
val fetch = Fetch .from(repositories, Cache .fetch())
83
- resolution.process.run(fetch).run
84
+ resolution.process.run(fetch)
84
85
}
85
86
86
- def fetchArtifacts (resolution : Resolution ): List [coursier.FileError \/ File ] = {
87
- if (resolution.isDone)
88
- ZTask .gatherUnordered(
89
- resolution.artifacts.map(Cache .file(_).run)
90
- ).run
91
- else
92
- Nil
93
- }
87
+ def fetchArtifacts (remotes : Seq [Remote ], dependencies : Seq [Dependency ]): Task [coursier.FileError \/ List [File ]] = for {
88
+ resolution <- resolveArtifacts(remotes, dependencies)
89
+ artifacts <- Task .gatherUnordered(
90
+ resolution.artifacts.map(Cache .file(_).run)
91
+ )
92
+ } yield artifacts.sequenceU
94
93
95
94
def createEval (jars : Seq [File ]) = {
96
95
new Eval (jars = jars.toList) {
@@ -117,12 +116,12 @@ class Evaluator(timeout: FiniteDuration = 20.seconds) {
117
116
}
118
117
}
119
118
120
- private [this ] def performEval [T ](code : String , jars : Seq [File ]): EvalResult [T ] = {
119
+ private [this ] def evaluate [T ](code : String , jars : Seq [File ]): EvalResult [T ] = {
121
120
val eval = createEval(jars)
122
121
123
122
val result = for {
124
123
_ ← Try (eval.check(code))
125
- result ← Try (eval.applyProcessed [T ](code, resetState = true , jars = jars))
124
+ result ← Try (eval.execute [T ](code, resetState = true , jars = jars))
126
125
} yield result
127
126
128
127
val errors : Map [Severity , List [CompilationInfo ]] = eval.errors.toMap
@@ -137,22 +136,21 @@ class Evaluator(timeout: FiniteDuration = 20.seconds) {
137
136
}
138
137
}
139
138
140
- def eval [T ](code : String , remotes : Seq [Remote ] = Nil , dependencies : Seq [Dependency ] = Nil ): EvalResult [T ] = {
141
- // todo: don't take into account dependency resolution time in timeout
142
- val resolution = resolveArtifacts(remotes, dependencies)
143
- val allJars = fetchArtifacts(resolution).sequenceU
144
-
145
- val jars : Seq [File ] = allJars match {
146
- case \/- (jars) => jars
147
- case -\/ (fileError) => Nil // todo: handle errors
148
- }
149
-
150
- val evaluation = Task ({
151
- performEval(code, jars)
152
- }) // todo
153
-
154
- Try (
155
- Await .result(evaluation.runAsync, timeout)
156
- ).getOrElse(EvalResult .Timeout ())
139
+ def eval [T ](
140
+ code : String ,
141
+ remotes : Seq [Remote ] = Nil ,
142
+ dependencies : Seq [Dependency ] = Nil
143
+ ): Task [EvalResult [T ]] = {
144
+ for {
145
+ allJars <- fetchArtifacts(remotes, dependencies)
146
+ result <- allJars match {
147
+ case \/- (jars) => Task ({
148
+ evaluate(code, jars)
149
+ }).timed(timeout).handle({
150
+ case err : TimeoutException => EvalResult .Timeout [T ]()
151
+ })
152
+ case -\/ (fileError) => Task .now(EvalResult .UnresolvedDependency (fileError))
153
+ }
154
+ } yield result
157
155
}
158
156
}
0 commit comments