From 125e0adad89510a527a09de9cd81d6773bbbb72f Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Thu, 4 Feb 2010 22:08:17 -0500 Subject: [PATCH] Decrease compilation time of compiler interface by ~20% --- compile/interface/API.scala | 2 +- compile/interface/Analyzer.scala | 38 ++++++++++++++++----------- compile/interface/CompileLogger.scala | 17 ++++++------ 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/compile/interface/API.scala b/compile/interface/API.scala index caf4c8c53..d0261a635 100644 --- a/compile/interface/API.scala +++ b/compile/interface/API.scala @@ -9,7 +9,7 @@ import io.{AbstractFile, PlainFile, ZipArchive} import plugins.{Plugin, PluginComponent} import symtab.Flags import scala.collection.mutable.{HashMap, HashSet, ListBuffer} -import xsbti.api.{ClassLike, DefinitionType, PathComponent, SimpleType} +//import xsbti.api.{ClassLike, DefinitionType, PathComponent, SimpleType} object API { diff --git a/compile/interface/Analyzer.scala b/compile/interface/Analyzer.scala index 3f196b073..73f1c9f30 100644 --- a/compile/interface/Analyzer.scala +++ b/compile/interface/Analyzer.scala @@ -20,15 +20,6 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends { import global._ - /** After 2.8.0.Beta1, fullNameString was renamed fullName.*/ - private implicit def symName(sym: Symbol): WithString = new WithString(sym) - private final class WithString(s: Symbol) - { - def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly - def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly - private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.") - } - def newPhase(prev: Phase): Phase = new AnalyzerPhase(prev) private class AnalyzerPhase(prev: Phase) extends Phase(prev) { @@ -76,9 +67,9 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends { val isModule = sym.isModuleClass for(superclass <- superclasses.filter(sym.isSubClass)) - callback.foundSubclass(sourceFile, sym.fullNameString, superclass.fullNameString, isModule) + callback.foundSubclass(sourceFile, NameString(sym), NameString(superclass), isModule) if(isModule && hasMainMethod(sym)) - callback.foundApplication(sourceFile, sym.fullNameString) + callback.foundApplication(sourceFile, NameString(sym)) } } @@ -142,7 +133,7 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends private def moduleSuffix(sym: Symbol) = if (sym.hasFlag(Flags.MODULE) && !sym.isMethod && !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$" else ""; private def flatname(s: Symbol, separator: Char) = - atPhase(currentRun.flattenPhase.next) { s.fullNameString(separator) } + atPhase(currentRun.flattenPhase.next) { NameString(s, separator) } private def isTopLevelModule(sym: Symbol): Boolean = atPhase (currentRun.picklerPhase.next) { @@ -193,8 +184,8 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends } private class NewFinder extends ClassFinder { - class Compat27 { def findClass(name: String) = this; def flatMap(f: Compat27 => AnyRef) = Predef.error("Should never be called"); def binary = None } - implicit def compat27(any: AnyRef): Compat27 = new Compat27 + private class Compat27 { def findClass(name: String) = this; def flatMap(f: Compat27 => AnyRef) = Predef.error("Should never be called"); def binary = None } + private implicit def compat27(any: AnyRef): Compat27 = new Compat27 def classSeparator = '.' // 2.8 uses . when searching for classes def findClass(name: String): Option[AbstractFile] = @@ -202,8 +193,8 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends } private class LegacyFinder extends ClassFinder { - class Compat28 { def root: Compat28 = invalid; def find(n: String, b: Boolean) = this; def classFile = invalid; def invalid = Predef.error("Should never be called") } - implicit def compat28(any: AnyRef): Compat28 = new Compat28 + private class Compat28 { def root: Compat28 = invalid; def find(n: String, b: Boolean) = this; def classFile = invalid; def invalid = Predef.error("Should never be called") } + private implicit def compat28(any: AnyRef): Compat28 = new Compat28 def classSeparator = File.separatorChar // 2.7 uses / or \ when searching for classes private val root = classPath.root @@ -213,4 +204,19 @@ final class Analyzer(val global: Global, val callback: AnalysisCallback) extends if(entry eq null) None else Some(entry.classFile) } } +} +private object NameString +{ + def apply(s: Global#Symbol): String = s.fullNameString + def apply(s: Global#Symbol, sep: Char): String = s.fullNameString(sep) + + /** After 2.8.0.Beta1, fullNameString was renamed fullName.*/ + private implicit def symName(sym: Symbol): WithString = new WithString(sym) + private final class WithString(s: Symbol) + { + def fullNameString = s.fullName; def fullName = sourceCompatibilityOnly + def fullNameString(sep: Char) = s.fullName(sep); def fullName(sep: Char) = sourceCompatibilityOnly + private def sourceCompatibilityOnly = error("For source compatibility only: should not get here.") + } + } \ No newline at end of file diff --git a/compile/interface/CompileLogger.scala b/compile/interface/CompileLogger.scala index 43c3e123e..b81fdc0bc 100644 --- a/compile/interface/CompileLogger.scala +++ b/compile/interface/CompileLogger.scala @@ -40,33 +40,34 @@ private final class LoggerReporter(maximumErrors: Int, log: Logger) extends scal }) } + // the help keep source compatibility with the changes in 2.8 : Position.{source,line,column} are no longer Option[X]s, just plain Xs + // so, we normalize to Option[X] + private def o[T](t: Option[T]): Option[T] = t + private def o[T](t: T): Option[T] = Some(t) private def print(logger: F0[String] => Unit, posIn: Position, msg: String) { def log(s: => String) = logger(Message(s)) - // the implicits keep source compatibility with the changes in 2.8 : Position.{source,line,column} are no longer Options - implicit def anyToOption[T <: AnyRef](t: T): Option[T] = Some(t) - implicit def intToOption(t: Int): Option[Int] = Some(t) val pos = posIn match { case null | NoPosition => NoPosition case x: FakePos => x case x => - posIn.inUltimateSource(posIn.source.get) + posIn.inUltimateSource(o(posIn.source).get) } pos match { case NoPosition => log(msg) case FakePos(fmsg) => log(fmsg+" "+msg) case _ => - val sourcePrefix = pos.source.map(_.file.path).getOrElse("") - val lineNumberString = pos.line.map(line => ":" + line + ":").getOrElse(":") + " " + val sourcePrefix = o(pos.source).map(_.file.path).getOrElse("") + val lineNumberString = o(pos.line).map(line => ":" + line + ":").getOrElse(":") + " " log(sourcePrefix + lineNumberString + msg) - if (!pos.line.isEmpty) + if (!o(pos.line).isEmpty) { val lineContent = pos.lineContent.stripLineEnd log(lineContent) // source line with error/warning - for(offset <- pos.offset; src <- pos.source) + for(offset <- o(pos.offset); src <- o(pos.source)) { val pointer = offset - src.lineToOffset(src.offsetToLine(offset)) val pointerSpace = (lineContent: Seq[Char]).take(pointer).map { case '\t' => '\t'; case x => ' ' }