diff options
author | Sean McDirmid <sean.mcdirmid@gmail.com> | 2007-09-17 16:36:10 +0000 |
---|---|---|
committer | Sean McDirmid <sean.mcdirmid@gmail.com> | 2007-09-17 16:36:10 +0000 |
commit | a205b6b06e705711308c9ad3abac74ba66b6266f (patch) | |
tree | 49aa189b4917b20d76c2da02cbf9475af5a49662 /src/compiler/scala/tools/nsc/util/SourceFile.scala | |
parent | 3f9b82c88d74c1b03daf5131b50c172213f40a63 (diff) | |
download | scala-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.scala | 185 |
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)) } } |