Skip to content

Commit

Permalink
removes some copy/paste from AnalyzerPlugins
Browse files Browse the repository at this point in the history
Abstracts away the foldLeft-based iteration pattern behind CumulativeOp[T].
In order to avoid performance regressions, `pluginsPt` and `pluginsTyped`
are special-cased for empty lists of analyzer plugins.
  • Loading branch information
xeno-by committed Dec 30, 2013
1 parent 9e14058 commit 447e737
Showing 1 changed file with 43 additions and 37 deletions.
80 changes: 43 additions & 37 deletions src/compiler/scala/tools/nsc/typechecker/AnalyzerPlugins.scala
Original file line number Diff line number Diff line change
Expand Up @@ -167,59 +167,65 @@ trait AnalyzerPlugins { self: Analyzer =>
analyzerPlugins = plugin :: analyzerPlugins
}

private abstract class CumulativeOp[T] {
def default: T
def accumulate: (T, AnalyzerPlugin) => T
}

private def invoke[T](op: CumulativeOp[T]): T = {
if (analyzerPlugins.isEmpty) op.default
else analyzerPlugins.foldLeft(op.default)((current, plugin) =>
if (!plugin.isActive()) current else op.accumulate(current, plugin))
}

/** @see AnalyzerPlugin.pluginsPt */
def pluginsPt(pt: Type, typer: Typer, tree: Tree, mode: Mode): Type =
// performance opt
if (analyzerPlugins.isEmpty) pt
else analyzerPlugins.foldLeft(pt)((pt, plugin) =>
if (!plugin.isActive()) pt else plugin.pluginsPt(pt, typer, tree, mode))
else invoke(new CumulativeOp[Type] {
def default = pt
def accumulate = (pt, p) => p.pluginsPt(pt, typer, tree, mode)
})

/** @see AnalyzerPlugin.pluginsTyped */
def pluginsTyped(tpe: Type, typer: Typer, tree: Tree, mode: Mode, pt: Type): Type = {
// support deprecated methods in annotation checkers
val annotCheckersTpe = addAnnotations(tree, tpe)
if (analyzerPlugins.isEmpty) annotCheckersTpe
else analyzerPlugins.foldLeft(annotCheckersTpe)((tpe, plugin) =>
if (!plugin.isActive()) tpe else plugin.pluginsTyped(tpe, typer, tree, mode, pt))
}
def pluginsTyped(tpe: Type, typer: Typer, tree: Tree, mode: Mode, pt: Type): Type =
// performance opt
if (analyzerPlugins.isEmpty) addAnnotations(tree, tpe)
else invoke(new CumulativeOp[Type] {
// support deprecated methods in annotation checkers
def default = addAnnotations(tree, tpe)
def accumulate = (tpe, p) => p.pluginsTyped(tpe, typer, tree, mode, pt)
})

/** @see AnalyzerPlugin.pluginsTypeSig */
def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type =
if (analyzerPlugins.isEmpty) tpe
else analyzerPlugins.foldLeft(tpe)((tpe, plugin) =>
if (!plugin.isActive()) tpe else plugin.pluginsTypeSig(tpe, typer, defTree, pt))
def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type = invoke(new CumulativeOp[Type] {
def default = tpe
def accumulate = (tpe, p) => p.pluginsTypeSig(tpe, typer, defTree, pt)
})

/** @see AnalyzerPlugin.pluginsTypeSigAccessor */
def pluginsTypeSigAccessor(tpe: Type, typer: Typer, tree: ValDef, sym: Symbol): Type =
if (analyzerPlugins.isEmpty) tpe
else analyzerPlugins.foldLeft(tpe)((tpe, plugin) =>
if (!plugin.isActive()) tpe else plugin.pluginsTypeSigAccessor(tpe, typer, tree, sym))
def pluginsTypeSigAccessor(tpe: Type, typer: Typer, tree: ValDef, sym: Symbol): Type = invoke(new CumulativeOp[Type] {
def default = tpe
def accumulate = (tpe, p) => p.pluginsTypeSigAccessor(tpe, typer, tree, sym)
})

/** @see AnalyzerPlugin.canAdaptAnnotations */
def canAdaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Boolean = {
def canAdaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Boolean = invoke(new CumulativeOp[Boolean] {
// support deprecated methods in annotation checkers
val annotCheckersExists = global.canAdaptAnnotations(tree, mode, pt)
annotCheckersExists || {
if (analyzerPlugins.isEmpty) false
else analyzerPlugins.exists(plugin =>
plugin.isActive() && plugin.canAdaptAnnotations(tree, typer, mode, pt))
}
}
def default = global.canAdaptAnnotations(tree, mode, pt)
def accumulate = (curr, p) => curr || p.canAdaptAnnotations(tree, typer, mode, pt)
})

/** @see AnalyzerPlugin.adaptAnnotations */
def adaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Tree = {
def adaptAnnotations(tree: Tree, typer: Typer, mode: Mode, pt: Type): Tree = invoke(new CumulativeOp[Tree] {
// support deprecated methods in annotation checkers
val annotCheckersTree = global.adaptAnnotations(tree, mode, pt)
if (analyzerPlugins.isEmpty) annotCheckersTree
else analyzerPlugins.foldLeft(annotCheckersTree)((tree, plugin) =>
if (!plugin.isActive()) tree else plugin.adaptAnnotations(tree, typer, mode, pt))
}
def default = global.adaptAnnotations(tree, mode, pt)
def accumulate = (tree, p) => p.adaptAnnotations(tree, typer, mode, pt)
})

/** @see AnalyzerPlugin.pluginsTypedReturn */
def pluginsTypedReturn(tpe: Type, typer: Typer, tree: Return, pt: Type): Type = {
val annotCheckersType = adaptTypeOfReturn(tree.expr, pt, tpe)
if (analyzerPlugins.isEmpty) annotCheckersType
else analyzerPlugins.foldLeft(annotCheckersType)((tpe, plugin) =>
if (!plugin.isActive()) tpe else plugin.pluginsTypedReturn(tpe, typer, tree, pt))
}
def pluginsTypedReturn(tpe: Type, typer: Typer, tree: Return, pt: Type): Type = invoke(new CumulativeOp[Type] {
def default = adaptTypeOfReturn(tree.expr, pt, tpe)
def accumulate = (tpe, p) => p.pluginsTypedReturn(tpe, typer, tree, pt)
})
}

0 comments on commit 447e737

Please sign in to comment.