summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/util')
-rw-r--r--src/compiler/scala/tools/nsc/util/CharArrayReader.scala16
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala38
-rw-r--r--src/compiler/scala/tools/nsc/util/FreshNameCreator.scala10
-rw-r--r--src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala74
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala43
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala185
6 files changed, 246 insertions, 120 deletions
diff --git a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
index ba67c6e3ea..4f99ecc221 100644
--- a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
+++ b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
@@ -8,10 +8,10 @@ package scala.tools.nsc.util
import scala.tools.nsc.util.SourceFile.{LF, FF, CR, SU}
-class CharArrayReader(buf: Array[Char], start: Int, /* startline: Int, startcol: Int, */
- decodeUni: Boolean, error: String => Unit) extends Iterator[Char] {
+class CharArrayReader(buf: RandomAccessSeq[Char], start: Int, /* startline: int, startcol: int, */
+ decodeUni: Boolean, error: String => unit) extends Iterator[Char] {
- def this(buf: Array[Char], decodeUni: Boolean, error: String => Unit) =
+ def this(buf: RandomAccessSeq[Char], decodeUni: Boolean, error: String => unit) =
this(buf, 0, /* 1, 1, */ decodeUni, error)
/** layout constant
@@ -46,17 +46,21 @@ class CharArrayReader(buf: Array[Char], start: Int, /* startline: Int, startcol:
//nextcol = 1
}
- def hasNext: Boolean = bp < buf.length
+ def hasNext: Boolean = if (bp < buf.length) true
+ else {
+ assert(true)
+ false
+ }
def last: Char = if (bp > start + 2) buf(bp - 2) else ' ' // XML literals
def next: Char = {
//cline = nextline
//ccol = nextcol
+ val buf = this.buf.asInstanceOf[runtime.BoxedCharArray].value
if(!hasNext) {
- // there is an endless stream of SU's at the end
ch = SU
- return SU
+ return SU // there is an endless stream of SU's at the end
}
oldBp = bp
oldCh = ch
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 6ac66ae968..cb67f55c60 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -81,7 +81,9 @@ class ClassPath(onlyPresentation: Boolean) {
// assert(location != null, "cannot find classpath location")
// assert(location.getFile() != null, "cannot find classpath location " + " " + location + " " + location.getClass())
def source: Source
- override def toString() = location.toString()
+ override def toString() =
+ (if (location == null) "<none>" else location.toString) +
+ (if (source == null) "" else " source=" + source)
}
class Output(location0: AbstractFile, val sourceFile: AbstractFile) extends Entry(location0) {
@@ -100,7 +102,7 @@ class ClassPath(onlyPresentation: Boolean) {
if (entries.isEmpty) new Context(Nil)
else {
val ret = find0(entries.tail)
- val head = entries.head
+ val head = entries.head;
val name0 = name + (if (!isDir) ".class" else "")
val clazz = if (head.location eq null) null
else head.location.lookupPath(name0, isDir)
@@ -124,7 +126,9 @@ class ClassPath(onlyPresentation: Boolean) {
}
try {
//Console.err.println("this=" + this + "\nclazz=" + clazz + "\nsource0=" + source0 + "\n")
- new Context(entry :: ret.entries)
+
+ if (!isDir) new Context(entry :: Nil)
+ else new Context(entry :: ret.entries)
} catch {
case e: Error =>
throw e
@@ -192,7 +196,7 @@ class ClassPath(onlyPresentation: Boolean) {
val sourcePath0 = sourcePath
if (sourcePath0 ne null) {
if (!sourcePath0.isDirectory) {
- Console.err.println(""+sourcePath0 + " cannot be a directory")
+ Console.err.println(""+sourcePath0 + " should be a directory")
assert(false)
}
}
@@ -248,15 +252,35 @@ class ClassPath(onlyPresentation: Boolean) {
}
/**
- * @param classes ...
- * @param sources ...
+ * @param classes where the class files come from and are written to
+ * @param sources where the source files come from
+ */
+ def output(classes : String, sources : String) = {
+ assert(classes ne null)
+ assert(sources ne null)
+ val location = AbstractFile.getDirectory(classes)
+ val sources0 = AbstractFile.getDirectory(sources)
+ class Output0 extends Output(location, sources0)
+ entries += new Output0()
+ }
+ /**
+ * @param classes where the class files come from
+ * @param sources optional source file attachment, otherwise null
*/
def library(classes: String, sources: String) {
assert(classes ne null)
val location = AbstractFile.getDirectory(classes)
- val sourceFile0 =
+ var sourceFile0 =
if (sources ne null) AbstractFile.getDirectory(sources)
else null
+ if (sourceFile0 ne null) {
+ val file00 = sourceFile0.lookupPath("src", true)
+ if ((file00 ne null) && file00.isDirectory) {
+ assert(true)
+ sourceFile0 = file00
+ }
+ }
+
class Library0 extends Library(location) {
override def sourceFile = sourceFile0
}
diff --git a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
index d3e79969af..a4c257a996 100644
--- a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
+++ b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
@@ -8,7 +8,13 @@ package scala.tools.nsc.util
import scala.collection.mutable.HashMap
-class FreshNameCreator {
+trait FreshNameCreator {
+ def newName(prefix : String) : String
+ def newName() : String
+ def newName(pos : util.Position, prefix : String) : String
+}
+object FreshNameCreator {
+ class Default extends FreshNameCreator {
protected var counter = 0
protected val counters = new HashMap[String, Int]
@@ -26,9 +32,11 @@ class FreshNameCreator {
counters.update(prefix, count)
prefix + count
}
+ def newName(pos : util.Position, prefix : String) = newName(prefix)
def newName(): String = {
counter = counter + 1
"$" + counter + "$"
}
}
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala b/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala
new file mode 100644
index 0000000000..3f889587ed
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala
@@ -0,0 +1,74 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2006 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: CharArrayReader.scala 11142 2007-05-22 10:23:00Z mcdirmid $
+
+package scala.tools.nsc.util
+
+import scala.tools.nsc.util.SourceFile.{LF, FF, CR, SU}
+
+class NewCharArrayReader(val buf: RandomAccessSeq[Char], // should not change
+ decodeUni: Boolean, error: (Int,String) => unit) extends Iterator[Char] {
+ private var idx : Int = 0
+ private var isUnicode0 = false
+ def isUnicode = isUnicode0
+
+ private val bufLength = buf.length
+ def seek(offset : Int) = {
+ assert(offset <= bufLength)
+ idx = offset
+ }
+ def offset = idx
+ def withOffset = new Iterator[(Int,Char)] {
+ def hasNext = NewCharArrayReader.this.hasNext
+ def next = (offset, NewCharArrayReader.this.next)
+ }
+ override def hasNext = { // could be padded
+ if (idx == bufLength - 1) buf(idx) != SU
+ else idx < bufLength
+ }
+ override def next : Char = {
+ isUnicode0 = false
+ if (!hasNext) return SU
+ var ch = buf(idx)
+ idx = idx + 1
+ ch match {
+ case CR if buf.safeIs(idx + 1, LF) =>
+ idx += 1; ch = LF
+ case LF | FF =>
+ case '\\' =>
+ def evenSlashPrefix: Boolean = {
+ var p = idx - 2
+ while (p >= 0 && buf(p) == '\\') p = p - 1;
+ (idx - p) % 2 == 0
+ }
+ def udigit: Int = {
+ val d = digit2int(buf(idx), 16)
+ if (d >= 0) { idx = idx + 1 }
+ else if (error != null) error(idx, "error in unicode escape");
+ d
+ }
+ if (idx < bufLength && buf(idx) == 'u' && decodeUni && evenSlashPrefix) {
+ do {
+ idx = idx + 1; // nextcol = nextcol + 1;
+ } while (idx < bufLength && buf(idx) == 'u');
+ val code = udigit << 12 | udigit << 8 | udigit << 4 | udigit
+ isUnicode0 = true
+ ch = code.asInstanceOf[Char]
+ }
+ case _ =>
+ }
+ ch
+ }
+ def digit2int(ch: Char, base: Int): Int = {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ ch - '0'
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ ch - 'A' + 10
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ ch - 'a' + 10
+ else
+ -1
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index 144809ff6a..ae4cd55086 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -8,14 +8,19 @@
// $Id$
package scala.tools.nsc.util
-
+object Position {
+ // a static field
+ private val tabInc = 8
+}
trait Position {
+ import Position.tabInc
def offset : Option[Int] = None
- private val tabInc = 8
+ def source : Option[SourceFile] = None
+
def line : Option[Int] =
- if (source.isEmpty || offset.isEmpty) None else Some(source.get.offsetToLine(offset.get) + 1)
+ if (offset.isEmpty || source.isEmpty) None else Some(source.get.offsetToLine(offset.get) + 1)
def column : Option[Int] = {
- if (source.isEmpty || offset.isEmpty) return None
+ if (offset.isEmpty || source.isEmpty) return None
var column = 1
// find beginning offset for line
val line = source.get.offsetToLine(offset.get)
@@ -23,33 +28,39 @@ trait Position {
var continue = true
while (continue) {
if (coffset == offset.get(-1)) continue = false
- else if (source.get.content(coffset) == '\t') column = ((column - 1) / tabInc * tabInc) + tabInc + 1
+ else if (source.get.asInstanceOf[BatchSourceFile].content(coffset) == '\t')
+ column = ((column - 1) / tabInc * tabInc) + tabInc + 1
else column = column + 1
coffset = coffset + 1
}
Some(column)
}
- def source : Option[SourceFile] = None
- def lineContent: String =
- if (!line.isEmpty && !source.isEmpty) source.get.lineToString(line.get - 1)
+ def lineContent: String = {
+ val line = this.line
+ if (!line.isEmpty) source.get.lineToString(line.get - 1)
else "NO_LINE"
+ }
+
+
/** Map this position to a position in an original source
* file. If the SourceFile is a normal SourceFile, simply
* return this.
*/
- def inUltimateSource = if (!source.isEmpty) source.get.positionInUltimateSource(this)
- else this
+ def inUltimateSource(source : SourceFile) =
+ if (source == null) this else source.positionInUltimateSource(this)
def dbgString = {
(if (source.isEmpty) "" else "source-" + source.get.path) +
(if (line.isEmpty) "" else "line-" + line.get) +
- (if (offset.isEmpty || source.isEmpty) ""
- else if (offset.get >= source.get.content.length) "out-of-bounds-" + offset.get
+ (if (offset.isEmpty) ""
+ else if (offset.get >= source.get.length) "out-of-bounds-" + offset.get
else {
val ret = "offset=" + offset.get;
var add = "";
- while (offset.get + add.length < source.get.content.length &&
+ /*
+ while (offset.get + add.length < source.get.length &&
add.length < 10) add = add + source.get.content(offset.get + add.length());
+ */
ret + " c[0..9]=\"" + add + "\"";
})
}
@@ -59,14 +70,14 @@ trait Position {
object NoPosition extends Position;
case class FakePos(msg : String) extends Position;
-case class LinePosition(line0 : Int, override val source : Option[SourceFile]) extends Position {
- def this(line0 : Int) = this(line0, None)
+case class LinePosition(source0 : SourceFile, line0 : Int) extends Position {
assert(line0 >= 1)
override def offset = None
override def column = None
override def line = Some(line0)
+ override def source = Some(source0)
}
case class OffsetPosition(source0 : SourceFile, offset0 : Int) extends Position {
override def source = Some(source0)
override def offset = Some(offset0)
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index f810fe96f0..4f4694b6b7 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -6,72 +6,115 @@
// $Id$
package scala.tools.nsc.util
-
import scala.tools.nsc.io.{AbstractFile, VirtualFile}
-/** Uses positions that are offsets rather than line/column pairs.
- *
- */
object SourceFile {
val LF: Char = 0x0A
val FF: Char = 0x0C
val CR: Char = 0x0D
val SU: Char = 0x1A
- def isLineBreak(c: Char) = c == LF || c == FF || c == CR || c == SU
+ def isLineBreak(c: Int) = c match {
+ case LF|FF|CR|SU => true
+ case _ => false
+ }
}
-
-/** Uses positions that are offsets rather than line/column pairs.
- *
- * @author Sean McDirmid
- * @version 1.0
- */
-class SourceFile(val file: AbstractFile, _content: Array[Char]) {
+/** abstract base class of a source file used in the compiler */
+abstract class SourceFile {
import SourceFile._
+ //def content : Seq[Char] // normalized, must end in SU
+ def file : AbstractFile
+ def isLineBreak(idx : Int) : Boolean
+ def length : Int
+ def position(offset: Int) : Position = {
+ assert(offset < length)
+ new OffsetPosition(this, offset)
+ }
+ def position(line: Int, column: Int) : Position = new OffsetPosition(this, lineToOffset(line) + column)
+ def offsetToLine(offset: Int): Int
+ def lineToOffset(index : Int): Int
+ /** Map a position to a position in the underlying source file.
+ * For regular source files, simply return the argument.
+ */
+ def positionInUltimateSource(position: Position) = position
+ override def toString(): String = file.name /* + ":" + content.length */
+ def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString
+ def path = file.path
- def this(_file: AbstractFile) = this(_file, _file.toCharArray)
+ def beginsWith(offset: Int, text: String): Boolean
+ def skipWhitespace(offset: Int): Int
+ def lineToString(index: Int): String
+
+ def identifier(pos : Position, compiler : scala.tools.nsc.Global) : Option[String] = None
+}
+/** a file whose contents do not change over time */
+class BatchSourceFile(val file : AbstractFile, _content : Array[Char]) extends SourceFile {
+ import SourceFile._
+ def this(_file: AbstractFile) = this(_file, _file.toCharArray)
def this(sourceName: String, content: Array[Char]) =
this(new VirtualFile(sourceName), content)
+ override def equals(that : Any) = that match {
+ case that : BatchSourceFile => file == that.file
+ case _ => false
+ }
+ override def hashCode = file.hashCode
+
+ val content = _content // don't sweat it...
+ override val length = content.length
+ override def identifier(pos : Position, compiler : scala.tools.nsc.Global) = pos match {
+ case OffsetPosition(source,offset) if source == this =>
+ import java.lang.Character
+ var i = offset + 1
+ while (i < content.length &&
+ (compiler.syntaxAnalyzer.isOperatorPart(content(i)) ||
+ compiler.syntaxAnalyzer.isIdentifierPart(content(i)))) i = i + 1
+
+ assert(i > offset)
+ Some(new String(content, offset, i - offset))
+ case _ => super.identifier(pos, compiler)
+ }
- val content = normalize(_content)
-
- def getContent() = content
- def getFile() = file
def isLineBreak(idx: Int) =
- if (!SourceFile.isLineBreak(content(idx))) false
- else if (content(idx) == CR && idx + 1 < content.length && content(idx + 1) == LF) false
+ if (idx >= content.length) false
+ else if (!SourceFile.isLineBreak(content(idx))) false
+ else if (content(idx) == CR && content(idx + 1) == LF) false
else true
- def position(offset: Int) = new OffsetPosition(this, offset)
- def position(line: Int, column: Int) = new OffsetPosition(this, lineToOffset(line) + column)
-
- /** Map a position to a position in the underlying source file.
- * For regular source files, simply return the argument.
- */
- def positionInUltimateSource(position: Position) = position
-
- // constants
-
- // NOTE: all indexes are based on zero!!!!
- override def toString(): String = file.name /* + ":" + content.length */
-
- def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString
+ def beginsWith(offset: Int, text: String): Boolean = {
+ var idx = 0
+ while (idx < text.length()) {
+ if (offset + idx >= content.length) return false
+ if (content(offset + idx) != text.charAt(idx)) return false
+ idx += 1
+ }
+ return true
+ }
+ def skipWhitespace(offset: Int): Int =
+ if (content(offset).isWhitespace) skipWhitespace(offset + 1)
+ else offset
+ def lineToString(index: Int): String = {
+ var offset = lineToOffset(index)
+ val buf = new StringBuilder()
+ while (!isLineBreak(offset) && offset < content.length) {
+ buf.append(content(offset))
+ offset += 1
+ }
+ buf.toString()
+ }
object line {
var index = 0
var offset = 0
def find(toFind: Int, isIndex: Boolean): Int = {
if (toFind == 0) return 0
-
- //if (!isIndex) assert(toFind != -1)
- //if ( isIndex) assert(toFind > 0)
-
- if (!isIndex && (toFind >= content.length))
+ if (!isIndex && (toFind >= content.length)) {
+ assert(true)
throw new Error(toFind + " not valid offset in " +
file.name + ":" + content.length)
+ }
def get(isIndex : Boolean) = if (isIndex) index else offset
@@ -79,11 +122,7 @@ class SourceFile(val file: AbstractFile, _content: Array[Char]) {
val increment = if (isBackward) -1 else + 1
val oneIfBackward = if (isBackward) +1 else 0
- // System.err.println("FIND-0: " + toFind + " " + isIndex);
-
while (true) {
- // System.err.println("FIND-1: " + offset + " " + index);
-
if (!isIndex && offset == toFind) return index;
if (isBackward && offset <= 0)
throw new Error(offset + " " + index + " " + toFind + " " + isIndex);
@@ -102,52 +141,19 @@ class SourceFile(val file: AbstractFile, _content: Array[Char]) {
def offsetToLine(offset: Int): Int = line.find(offset, false)
def lineToOffset(index : Int): Int = line.find(index , true)
- def beginsWith(offset: Int, text: String): Boolean = {
- var idx = 0
- while (idx < text.length()) {
- if (offset + idx >= content.length) return false
- if (content(offset + idx) != text.charAt(idx)) return false
- idx += 1
- }
- return true
- }
- def path = getFile().path
+}
- def skipWhitespace(offset: Int): Int =
- if (content(offset).isWhitespace) skipWhitespace(offset + 1)
- else offset
- def lineToString(index: Int): String = {
- var offset = lineToOffset(index)
- val buf = new StringBuilder()
- while (!isLineBreak(offset) && offset < content.length) {
- buf.append(content(offset))
- offset += 1
- }
- buf.toString()
- }
-
- private def normalize(input : Array[Char]): Array[Char] =
- if (input.length > 0 && input(input.length - 1) == SU)
- input
- else {
- val content = new Array[Char](input.length + 1)
- Array.copy(input, 0, content, 0, input.length)
- content(input.length) = SU
- content
- }
-}
/** A source file composed of multiple other source files.
*
- * @author Sean McDirmid
* @version 1.0
*/
class CompoundSourceFile(
name: String,
- components: List[SourceFile],
+ components: List[BatchSourceFile],
contents: Array[Char])
-extends SourceFile(name, contents)
+extends BatchSourceFile(name, contents)
{
/** The usual constructor. Specify a name for the compound file and
* a list of component sources.
@@ -155,18 +161,18 @@ extends SourceFile(name, contents)
* @param name ...
* @param components ...
*/
- def this(name: String, components: SourceFile*) = {
+ def this(name: String, components: BatchSourceFile*) = {
/* Note that the contents leaves off the final SU character
* of all components */
this(
name,
components.toList,
Array.concat(components.toList.map(comp =>
- comp.content.subArray(0, comp.content.length-1)):_*))
+ comp.content.slice(0, comp.content.length-1).toArray):_*))
}
/** Create an instance with the specified components and a generic name. */
- def this(components: SourceFile*) =
+ def this(components: BatchSourceFile*) =
this("(virtual file)", components.toList:_*)
override def positionInUltimateSource(position: Position) = {
@@ -178,7 +184,7 @@ extends SourceFile(name, contents)
off = off - compsLeft.head.content.length + 1
compsLeft = compsLeft.tail
}
- compsLeft.head.positionInUltimateSource(new OffsetPosition(compsLeft.head, off))
+ compsLeft.head.positionInUltimateSource(new OffsetPosition(this, off))
}
}
}
@@ -190,21 +196,20 @@ extends SourceFile(name, contents)
*/
class SourceFileFragment(
name: String,
- underlyingFile: SourceFile,
+ underlyingFile: BatchSourceFile,
start: Int,
stop: Int,
contents: Array[Char])
-extends SourceFile(name, contents)
-{
- def this(name: String, underlyingFile: SourceFile, start: Int, stop: Int) =
+extends BatchSourceFile(name, contents) {
+ def this(name: String, underlyingFile: BatchSourceFile, start: Int, stop: Int) =
this(
name,
underlyingFile,
start,
stop,
- underlyingFile.content.subArray(start, stop))
+ underlyingFile.content.slice(start, stop).toArray)
- def this(underlyingFile: SourceFile, start: Int, stop: Int) =
+ def this(underlyingFile: BatchSourceFile, start: Int, stop: Int) =
this(
"(fragment of " + underlyingFile.file.name + ")",
underlyingFile,
@@ -214,7 +219,7 @@ extends SourceFile(name, contents)
override def positionInUltimateSource(position: Position) = {
if (position.offset.isEmpty)
super.positionInUltimateSource(position)
- else underlyingFile.positionInUltimateSource(
- new OffsetPosition(underlyingFile, position.offset.get + start))
+ else positionInUltimateSource(
+ new OffsetPosition(this, position.offset.get + start))
}
}