summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/util/SourceFile.scala
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2007-09-17 16:36:10 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2007-09-17 16:36:10 +0000
commita205b6b06e705711308c9ad3abac74ba66b6266f (patch)
tree49aa189b4917b20d76c2da02cbf9475af5a49662 /src/compiler/scala/tools/nsc/util/SourceFile.scala
parent3f9b82c88d74c1b03daf5131b50c172213f40a63 (diff)
downloadscala-a205b6b06e705711308c9ad3abac74ba66b6266f.tar.gz
scala-a205b6b06e705711308c9ad3abac74ba66b6266f.tar.bz2
scala-a205b6b06e705711308c9ad3abac74ba66b6266f.zip
Massive check-in for IDE.
Diffstat (limited to 'src/compiler/scala/tools/nsc/util/SourceFile.scala')
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala185
1 files changed, 95 insertions, 90 deletions
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))
}
}