-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Analyzer.scala
147 lines (135 loc) · 5.18 KB
/
Analyzer.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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/
package scala.tools.nsc
package typechecker
import scala.collection.mutable.ArrayDeque
/** Defines the sub-components for the namer, packageobjects, and typer phases.
*/
trait Analyzer extends AnyRef
with Contexts
with Namers
with Typers
with Infer
with Implicits
with EtaExpansion
with SyntheticMethods
with Unapplies
with Macros
with NamesDefaults
with TypeDiagnostics
with ContextErrors
with StdAttachments
with MacroAnnotationAttachments
with AnalyzerPlugins
{
val global : Global
import global._
object namerFactory extends {
val global: Analyzer.this.global.type = Analyzer.this.global
} with SubComponent {
val phaseName = "namer"
val runsAfter = List[String]("parser")
val runsRightAfter = None
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
override val checkable = false
override def keepsTypeParams = false
def apply(unit: CompilationUnit): Unit = newNamer(rootContext(unit)).enterSym(unit.body)
}
}
object packageObjects extends {
val global: Analyzer.this.global.type = Analyzer.this.global
} with SubComponent {
val deferredOpen = perRunCaches.newSet[Symbol]()
val phaseName = "packageobjects"
val runsAfter = List[String]()
val runsRightAfter= Some("namer")
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
override val checkable = false
import global._
val openPackageObjectsTraverser = new InternalTraverser {
override def traverse(tree: Tree): Unit = tree match {
case ModuleDef(_, _, _) =>
if (tree.symbol.name == nme.PACKAGEkw) {
// we've actually got a source file
deferredOpen.subtractOne(tree.symbol.owner)
openPackageModule(tree.symbol, tree.symbol.owner)
}
case ClassDef(_, _, _, _) => () // make it fast
case _ => tree.traverse(this)
}
}
def apply(unit: CompilationUnit): Unit = {
openPackageObjectsTraverser(unit.body)
deferredOpen.foreach(openPackageModule(_))
deferredOpen.clear()
}
}
}
object typerFactory extends {
val global: Analyzer.this.global.type = Analyzer.this.global
} with SubComponent {
import global.statistics
val phaseName = "typer"
val runsAfter = List[String]()
val runsRightAfter = Some("packageobjects")
def newPhase(prev: Phase): StdPhase = new TyperPhase(prev)
final class TyperPhase(prev: Phase) extends StdPhase(prev) {
override def keepsTypeParams = false
override def shouldSkipThisPhaseForJava: Boolean = !settings.YpickleJava.value && !createJavadoc
resetTyper()
// the log accumulates entries over time, even though it should not (Adriaan, Martin said so).
// Lacking a better fix, we clear it here (before the phase is created, meaning for each
// compiler run). This is good enough for the resident compiler, which was the most affected.
undoLog.clear()
private val toCheckAfterTyper = ArrayDeque.empty[CompilationUnit.ToCheckAfterTyper]
def addCheckAfterTyper(check: CompilationUnit.ToCheckAfterTyper): Unit = toCheckAfterTyper.append(check)
override def run(): Unit = {
val start = if (settings.areStatisticsEnabled) statistics.startTimer(statistics.typerNanos) else null
global.echoPhaseSummary(this)
val units = currentRun.units
while (units.hasNext) {
applyPhase(units.next())
undoLog.clear()
}
finishComputeParamAlias()
try while (toCheckAfterTyper.nonEmpty) toCheckAfterTyper.removeHead().apply()
finally toCheckAfterTyper.clearAndShrink()
// defensive measure in case the bookkeeping in deferred macro expansion is buggy
clearDelayed()
if (settings.areStatisticsEnabled) statistics.stopTimer(statistics.typerNanos, start)
}
def apply(unit: CompilationUnit): Unit = {
try {
val typer = newTyper(rootContext(unit))
unit.body = typer.typed(unit.body)
// interactive typed may finish by throwing a `TyperResult`
if (!settings.Youtline.value) {
while (unit.toCheck.nonEmpty) {
unit.toCheck.removeHead() match {
case now: CompilationUnit.ToCheckAfterUnit => now()
case later: CompilationUnit.ToCheckAfterTyper => addCheckAfterTyper(later)
}
}
if (!settings.isScaladoc && settings.warnUnusedImport)
warnUnusedImports(unit)
if (!settings.isScaladoc && settings.warnUnused.isSetByUser)
new checkUnused(typer).apply(unit)
}
}
finally {
runReporting.reportSuspendedMessages(unit)
unit.toCheck.clearAndShrink()
}
}
}
}
}