@@ -3,8 +3,9 @@ package plugins
33
44import core ._
55import Contexts ._
6- import dotty . tools . dotc . config .PathResolver
6+ import config .PathResolver
77import dotty .tools .io ._
8+ import Phases ._
89
910/** Support for run-time loading of compiler plugins.
1011 *
@@ -80,7 +81,7 @@ trait Plugins {
8081 }
8182 }
8283
83- val plugs = pick(roughPluginsList, Set () )
84+ val plugs = pick(roughPluginsList, ctx.phasePlan.flatten.map(_.phaseName).toSet )
8485
8586 // Verify required plugins are present.
8687 for (req <- ctx.settings.require.value ; if ! (plugs exists (_.name == req)))
@@ -113,4 +114,65 @@ trait Plugins {
113114 (for (plug <- roughPluginsList ; help <- plug.optionsHelp) yield {
114115 " \n Options for plugin '%s':\n %s\n " .format(plug.name, help)
115116 }).mkString
117+
118+ /** Add plugin phases to phase plan */
119+ def addPluginPhases (plan : List [List [Phase ]])(implicit ctx : Context ): List [List [Phase ]] = {
120+ import scala .collection .mutable .{ Set => MSet , Map => MMap }
121+ type OrderingReq = (MSet [Class [_]], MSet [Class [_]])
122+
123+ val orderRequirements = MMap [Class [_], OrderingReq ]()
124+
125+ def updateOrdering (phase : PluginPhase ): Unit = {
126+ val runsBefore : MSet [Class [_]] = MSet (phase.runsBefore.toSeq: _* )
127+ val runsAfter : MSet [Class [_]] = MSet (phase.runsAfter.toSeq: _* )
128+
129+ if (! orderRequirements.contains(phase.getClass)) {
130+ orderRequirements.update(phase.getClass, (runsBefore, runsAfter) )
131+ }
132+
133+ runsBefore.foreach { phaseClass =>
134+ if (! orderRequirements.contains(phaseClass))
135+ orderRequirements.update(phaseClass, (MSet .empty, MSet .empty))
136+ val (_, runsAfter) = orderRequirements(phaseClass)
137+ runsAfter += phase.getClass
138+ }
139+
140+ runsAfter.foreach { phaseClass =>
141+ if (! orderRequirements.contains(phaseClass))
142+ orderRequirements.update(phaseClass, (MSet .empty, MSet .empty))
143+ val (runsBefore, _) = orderRequirements(phaseClass)
144+ runsBefore += phase.getClass
145+ }
146+ }
147+
148+ // add non-research plugins
149+ var updatedPlan = plan
150+ plugins.filter(! _.research).foreach { plug =>
151+ plug.components.foreach { phase =>
152+ updateOrdering(phase)
153+
154+ val beforePhases : MSet [Class [_]] = MSet (phase.runsBefore.toSeq: _* )
155+ val afterPhases : MSet [Class [_]] = MSet (phase.runsAfter.toSeq: _* )
156+
157+ val (before, after) = updatedPlan.span { ps =>
158+ val classes = ps.map(_.getClass)
159+ afterPhases --= classes
160+ ! classes.exists(beforePhases.contains) // beforeReq satisfied
161+ }
162+
163+ // check afterReq
164+ // error can occur if: a < b, b < c, c < a
165+ after.foreach { ps =>
166+ val classes = ps.map(_.getClass)
167+ if (classes.exists(afterPhases)) // afterReq satisfied
168+ throw new Exception (s " Ordering conflict for plugin ${plug.name}" )
169+ }
170+
171+ updatedPlan = before ++ (List (phase) :: after)
172+ }
173+ }
174+
175+ // add research plugins
176+ ctx.plugins.filter(_.research).foldRight(updatedPlan) { (plug, plan) => plug.init(plan) }
177+ }
116178}
0 commit comments