-
Notifications
You must be signed in to change notification settings - Fork 315
/
ScalaCompilerAccess.scala
98 lines (82 loc) 路 3.03 KB
/
ScalaCompilerAccess.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package scala.meta.internal.pc
import java.util.concurrent.ScheduledExecutorService
import scala.concurrent.ExecutionContextExecutor
import scala.tools.nsc.interactive.ShutdownReq
import scala.tools.nsc.reporters.StoreReporter
import scala.util.control.NonFatal
import scala.meta.internal.metals.ReportContext
import scala.meta.pc.PresentationCompilerConfig
class ScalaCompilerWrapper(global: MetalsGlobal)
extends CompilerWrapper[StoreReporter, MetalsGlobal] {
override def compiler(files: OutlineFiles): MetalsGlobal = {
global.runOutline(files)
global
}
override def resetReporter(): Unit = global.reporter.reset()
override def reporterAccess: ReporterAccess[StoreReporter] =
new ReporterAccess[StoreReporter] {
def reporter = global.reporter.asInstanceOf[StoreReporter]
}
override def askShutdown(): Unit = {
global.askShutdown()
}
override def isAlive(): Boolean = {
global.presentationCompilerThread.isAlive()
}
override def stop(): Unit = {
global.presentationCompilerThread.stop()
}
override def presentationCompilerThread: Option[Thread] = {
Some(global.presentationCompilerThread)
}
}
class ScalaCompilerAccess(
config: PresentationCompilerConfig,
sh: Option[ScheduledExecutorService],
newCompiler: () => ScalaCompilerWrapper,
additionalReportingData: () => String
)(implicit ec: ExecutionContextExecutor, rc: ReportContext)
extends CompilerAccess[StoreReporter, MetalsGlobal](
config,
sh,
newCompiler,
shouldResetJobQueue = false,
additionalReportingData
) {
def newReporter = new StoreReporter
protected def handleSharedCompilerException(
t: Throwable
): Option[String] = {
t match {
case ShutdownReq =>
Some("an error in the Scala compiler")
case NonFatal(e) =>
val isParadiseRelated = e.getStackTrace
.exists(_.getClassName.startsWith("org.scalamacros"))
val isCompilerRelated = e.getStackTrace.headOption.exists { e =>
e.getClassName.startsWith("scala.tools") ||
e.getClassName.startsWith("scala.reflect")
}
if (isParadiseRelated) {
// NOTE(olafur) Metals disables macroparadise by default but other library
// clients of mtags may enable it.
// Testing shows that the scalamacro paradise plugin tends to crash
// easily in long-running sessions. We retry with a fresh compiler
// to see if that fixes the issue. This is a hacky solution that is
// slow because creating new compiler instances is expensive. A better
// long-term solution is to fix the paradise plugin implementation
// to be more resilient in long-running sessions.
Some("the org.scalamacros:paradise compiler plugin")
} else if (isCompilerRelated) {
Some("an error in the Scala compiler")
} else {
None
}
case t => throw t
}
}
protected def ignoreException(t: Throwable): Boolean =
t match {
case ShutdownReq => true
}
}