diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/util/Position.scala | 8 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/util/SourceFile.scala | 67 |
2 files changed, 75 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala index fc3e358607..efa139876c 100644 --- a/src/compiler/scala/tools/nsc/util/Position.scala +++ b/src/compiler/scala/tools/nsc/util/Position.scala @@ -64,6 +64,11 @@ class Position( val source : SourceFile, val offset: Int) { column; } else 0; + /** Map this position to a position in an original source + * file. If the SourceFile is a normal SourceFile, simply + * return this. + */ + def inUltimateSource = source.positionInUltimateSource(this) def dbgString = { "source: " + (if (source == null) source else source . path) + " " + @@ -84,6 +89,9 @@ class Position( val source : SourceFile, val offset: Int) { /** Returns a string representation of the encoded position. */ override def toString(): String = { + if(inUltimateSource != this) + return inUltimateSource.toString + val sb = new StringBuffer(); if (source != null) { sb.append(source.file.path); diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala index cf0e71adfe..c065f61e8b 100644 --- a/src/compiler/scala/tools/nsc/util/SourceFile.scala +++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala @@ -51,6 +51,10 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { def position(offset : Int) = new Position(this, offset); def position(line : Int, column : Int) = new Position(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!!!! @@ -135,8 +139,71 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) { content(input.length) = SU; content; } +} + +/** A source file composed of multiple other source files. */ +class CompoundSourceFile( + name: String, + components: List[SourceFile], + contents: Array[Char]) +extends SourceFile(name, contents) +{ + /** The usual constructor. Specify a name for the compound file and + * a list of component sources */ + def this(name: String, components: SourceFile*) = { + /* 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)):_*)) + } + /** Create an instance with the specified components and a generic name. */ + def this(components: SourceFile*) = this("(virtual file)", components.toList:_*) + override def positionInUltimateSource(position: Position) = { + var off = position.offset + var compsLeft = components + while(compsLeft.head.content.length-1 <= off) { + off = off - compsLeft.head.content.length + 1 + compsLeft = compsLeft.tail + } + compsLeft.head.positionInUltimateSource(new Position(compsLeft.head, off)) + } +} +/** One portion of an underlying file. The fragment includes + * the indeces from the specified start (inclusively) to stop + * (not inclusively). + */ +class SourceFileFragment( + name: String, + underlyingFile: SourceFile, + start: Int, + stop: Int, + contents: Array[Char]) +extends SourceFile(name, contents) +{ + def this(name: String, underlyingFile: SourceFile, start: Int, stop: Int) = + this( + name, + underlyingFile, + start, + stop, + underlyingFile.content.subArray(start, stop)) + + def this(underlyingFile: SourceFile, start: Int, stop: Int) = + this( + "(fragment of " + underlyingFile.file.name + ")", + underlyingFile, + start, + stop) + + override def positionInUltimateSource(position: Position) = { + underlyingFile.positionInUltimateSource( + new Position(underlyingFile, position.offset + start)) + } } |