From 7315339782f6e19ddd6199768352a91ef66eb27d Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Wed, 6 Jan 2010 18:48:13 +0000 Subject: scalac portion of fix for #2689. --- src/compiler/scala/tools/nsc/Settings.scala | 31 ++++++++++++++++++++++ .../scala/tools/nsc/symtab/SymbolLoaders.scala | 1 + .../nsc/symtab/classfile/ClassfileParser.scala | 12 ++++++++- 3 files changed, 43 insertions(+), 1 deletion(-) (limited to 'src/compiler') diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 23ceb37c95..b039a9e90d 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -372,6 +372,37 @@ object Settings { } } } + + /** Return the source file path(s) which correspond to the given + * classfile path and SourceFile attribute value, subject to the + * condition that source files are arranged in the filesystem + * according to Java package layout conventions. + * + * The given classfile path must be contained in at least one of + * the specified output directories. If it does not then this + * method returns Nil. + * + * Note that the source file is not required to exist, so assuming + * a valid classfile path this method will always return a list + * containing at least one element. + * + * Also that if two or more source path elements target the same + * output directory there will be two or more candidate source file + * paths. + */ + def srcFilesFor(classFile : AbstractFile, srcPath : String) : List[AbstractFile] = { + def isBelow(srcDir: AbstractFile, outDir: AbstractFile) = + classFile.path.startsWith(outDir.path) + + singleOutDir match { + case Some(d) => Nil + case None => + (outputs filter (isBelow _).tuple) match { + case Nil => Nil + case matches => matches.map(_._1.lookupPath(srcPath, false)) + } + } + } } // The Setting companion object holds all the factory methods diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 5d779e90a2..3daa4e8ac2 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -249,6 +249,7 @@ abstract class SymbolLoaders { classfileParser.parse(classfile, root) stopTimer(classReadNanos, start) } + override protected def sourcefile = classfileParser.srcfile } class MSILTypeLoader(typ: MSILType) extends SymbolLoader { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index da4e0aaa49..5c4679625b 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -8,7 +8,7 @@ package scala.tools.nsc package symtab package classfile -import java.io.IOException +import java.io.{ File, IOException } import java.lang.Integer.toHexString import scala.collection.immutable.{Map, ListMap} @@ -41,6 +41,9 @@ abstract class ClassfileParser { protected var busy: Option[Symbol] = None // lock to detect recursive reads private var externalName: Name = _ // JVM name of the current class protected var classTParams = Map[Name,Symbol]() + protected var srcfile0 : Option[AbstractFile] = None + + def srcfile = srcfile0 private object metaParser extends MetaParser { val global: ClassfileParser.this.global.type = ClassfileParser.this.global @@ -813,6 +816,13 @@ abstract class ClassfileParser { case nme.ExceptionsATTR if (!isScala) => parseExceptions(attrLen) + case nme.SourceFileATTR => + val srcfileLeaf = pool.getName(in.nextChar).toString.trim + val srcpath = sym.enclosingPackage match { + case NoSymbol => srcfileLeaf + case pkg => pkg.fullNameString(File.separatorChar)+File.separator+srcfileLeaf + } + srcfile0 = settings.outputDirs.srcFilesFor(in.file, srcpath).find(_.exists) case _ => in.skip(attrLen) } -- cgit v1.2.3