summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean McDirmid <sean.mcdirmid@gmail.com>2005-11-29 18:19:38 +0000
committerSean McDirmid <sean.mcdirmid@gmail.com>2005-11-29 18:19:38 +0000
commit15724bed1b9211a260805af2e6005df8d0d39f56 (patch)
tree3d97e021455e98880e99f74aea190f5350a591ce
parent4cf6770e38bb7ab8654b6ce225d181f5e3ca51b4 (diff)
downloadscala-15724bed1b9211a260805af2e6005df8d0d39f56.tar.gz
scala-15724bed1b9211a260805af2e6005df8d0d39f56.tar.bz2
scala-15724bed1b9211a260805af2e6005df8d0d39f56.zip
* Added semantic token models to support Eclips...
* Added semantic token models to support Eclipse IDE. Fixed positions * to handle Windows newlines Fixed as much code generation line number * issues as possible, but some issues may remain.
-rw-r--r--.project11
-rw-r--r--Test.scala7
-rw-r--r--config/.cvsignore1
-rw-r--r--sources/scala/tools/nsc/Settings.scala12
-rw-r--r--sources/scala/tools/nsc/ast/Trees.scala141
-rw-r--r--sources/scala/tools/nsc/ast/parser/MarkupParsers.scala8
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Parsers.scala86
-rwxr-xr-xsources/scala/tools/nsc/ast/parser/Scanners.scala9
-rw-r--r--sources/scala/tools/nsc/backend/icode/Printers.scala4
-rw-r--r--sources/scala/tools/nsc/backend/jvm/GenJVM.scala7
-rw-r--r--sources/scala/tools/nsc/matching/CodeFactory.scala4
-rw-r--r--sources/scala/tools/nsc/models/Models.scala.xxx189
-rw-r--r--sources/scala/tools/nsc/models/SemanticTokens.scala477
-rw-r--r--sources/scala/tools/nsc/symtab/Flags.scala7
-rwxr-xr-xsources/scala/tools/nsc/symtab/Symbols.scala28
-rwxr-xr-xsources/scala/tools/nsc/transform/Erasure.scala2
-rwxr-xr-xsources/scala/tools/nsc/typechecker/Typers.scala20
-rw-r--r--sources/scala/tools/nsc/util/CharArrayReader.scala36
-rwxr-xr-xsources/scala/tools/nsc/util/Position.scala8
-rw-r--r--sources/scala/tools/nsc/util/SourceFile.scala66
20 files changed, 986 insertions, 137 deletions
diff --git a/.project b/.project
new file mode 100644
index 0000000000..841840050d
--- /dev/null
+++ b/.project
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>scala</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ </buildSpec>
+ <natures>
+ </natures>
+</projectDescription>
diff --git a/Test.scala b/Test.scala
new file mode 100644
index 0000000000..1d8d7afd76
--- /dev/null
+++ b/Test.scala
@@ -0,0 +1,7 @@
+object Test extends Application {
+ if (1 == 0) throw new Error();
+ bar;
+ def bar = foo;
+ def foo = if (true)
+ throw new Error();
+}
diff --git a/config/.cvsignore b/config/.cvsignore
index 0356d87225..0a3c6c7560 100644
--- a/config/.cvsignore
+++ b/config/.cvsignore
@@ -4,3 +4,4 @@ build.michelou.properties
build.paltherr.properties
build.unix.properties
build.win.properties
+build.mcdirmid.properties
diff --git a/sources/scala/tools/nsc/Settings.scala b/sources/scala/tools/nsc/Settings.scala
index 8e66ee3dac..97518f0ac9 100644
--- a/sources/scala/tools/nsc/Settings.scala
+++ b/sources/scala/tools/nsc/Settings.scala
@@ -99,12 +99,12 @@ class Settings(error: String => unit) {
def tryToSet(args: List[String]): List[String] = args match {
case n :: rest if (n == name) =>
if (rest.isEmpty) {
- error("missing argument");
- List()
- } else {
- value = rest.head;
- rest.tail
- }
+ error("missing argument");
+ List()
+ } else {
+ value = rest.head;
+ rest.tail
+ }
case _ => args
}
diff --git a/sources/scala/tools/nsc/ast/Trees.scala b/sources/scala/tools/nsc/ast/Trees.scala
index 1736d9d446..c23252131a 100644
--- a/sources/scala/tools/nsc/ast/Trees.scala
+++ b/sources/scala/tools/nsc/ast/Trees.scala
@@ -5,9 +5,10 @@
// $Id$
package scala.tools.nsc.ast;
+import scala.tools.nsc.symtab.Flags;
import java.io.StringWriter;
import java.io.PrintWriter;
-import scala.tools.nsc.util.Position;
+import scala.tools.nsc.util.{Position,SourceFile};
import symtab.Flags._;
[_trait_] abstract class Trees: Global {
@@ -19,10 +20,15 @@ import symtab.Flags._;
if (util.Statistics.enabled) nodeCount = nodeCount + 1;
- var pos: int = Position.NOPOS;
+ private var posx: int = Position.NOPOS;
+
+ def pos = posx;
+
+
+
var tpe: Type = _;
- def setPos(p: int): this.type = { pos = p; this }
+ def setPos(p: int): this.type = { posx = p; this }
def setType(tp: Type): this.type = { tpe = tp; this }
def symbol: Symbol = null;
@@ -53,7 +59,7 @@ import symtab.Flags._;
def duplicate: this.type = (duplicator transform this).asInstanceOf[this.type];
def copyAttrs(tree: Tree): this.type = {
- pos = tree.pos;
+ posx = tree.posx;
tpe = tree.tpe;
if (hasSymbol) symbol = tree.symbol;
this
@@ -65,8 +71,8 @@ import symtab.Flags._;
override var symbol: Symbol = NoSymbol;
}
- trait DefTree extends SymTree {
- override def isDef = true
+ abstract class DefTree(val name0 : Name) extends SymTree {
+ override def isDef = true;
}
trait TermTree extends Tree {
@@ -109,17 +115,43 @@ import symtab.Flags._;
override def isEmpty = true;
}
+ abstract class MemberDef(val mods0: int, name: Name) extends DefTree(name) {
+ def keyword : String;
+ def flags = new Flags.Flag(mods0);
+ final def hasFlag(mask: long): boolean = (mods0 & mask) != 0;
+
+ def namePos(source : SourceFile) : Int = if (pos == Position.NOPOS) Position.NOPOS else {
+ assert(keyword != null);
+ if (!source.beginsWith(pos, keyword + " ")) {
+ val p = new Position(source, pos);
+ // System.err.println("SYM=" + symbol + " KW=" + keyword + " LINE=" + p.lineContent + " TEXT=" + source.content(pos) + source.content(pos + 1));
+ if (true) return Position.NOPOS;
+ else throw new Error();
+ }
+ source.skipWhitespace(pos + keyword.length() + 1);
+ }
+ }
+
/** Package clause */
case class PackageDef(name: Name, stats: List[Tree])
- extends DefTree;
+ extends MemberDef(0, name) {
+ def keyword = "package";
+ }
def PackageDef(sym: Symbol, stats: List[Tree]): PackageDef =
PackageDef(sym.name, stats) setSymbol sym;
+
+
+ abstract class ImplDef(mods : int, name: Name, val impl0: Template) extends MemberDef(mods, name);
+
+
/** Class definition */
case class ClassDef(mods: int, name: Name, tparams: List[AbsTypeDef], tpt: Tree, impl: Template)
- extends DefTree;
+ extends ImplDef(mods, name, impl) {
+ def keyword = "class";
+ }
def ClassDef(sym: Symbol, impl: Template): ClassDef =
posAssigner.atPos(sym.pos) {
@@ -142,33 +174,49 @@ import symtab.Flags._;
/** Singleton object definition */
case class ModuleDef(mods: int, name: Name, impl: Template)
- extends DefTree;
+ extends ImplDef(mods, name, impl) {
+ def keyword = "object";
+ }
def ModuleDef(sym: Symbol, impl: Template): ModuleDef =
posAssigner.atPos(sym.pos) {
ModuleDef(flags2mods(sym.flags), sym.name, impl)
}
+
+ abstract class ValOrDefDef(mods: int, name: Name, val tpt0: Tree, val rhs0 : Tree) extends MemberDef(mods, name);
+
+
+
/** Value definition */
case class ValDef(mods: int, name: Name, tpt: Tree, rhs: Tree)
- extends DefTree {
+ extends ValOrDefDef(mods, name, tpt, rhs) {
assert(tpt.isType, tpt);
- assert(rhs.isTerm, rhs)
- }
+ assert(rhs.isTerm, rhs);
+ def keyword = if (flags.isVariable) "var" else "val";
+ override def namePos(source : SourceFile) =
+ if (pos == Position.NOPOS) Position.NOPOS;
+ else if (source.beginsWith(pos, "val ") || source.beginsWith(pos, "var ")) source.skipWhitespace(pos + ("val ").length());
+ else if (source.content(pos) == ',') source.skipWhitespace(pos + 1);
+ else pos;
+ }
- def ValDef(sym: Symbol, rhs: Tree): ValDef =
+
+ def ValDef(sym: Symbol, rhs: Tree): ValDef = {
posAssigner.atPos(sym.pos) {
ValDef(flags2mods(sym.flags), sym.name, TypeTree(sym.tpe), rhs) setSymbol sym
}
+ }
def ValDef(sym: Symbol): ValDef = ValDef(sym, EmptyTree);
/** Method definition */
case class DefDef(mods: int, name: Name, tparams: List[AbsTypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree)
- extends DefTree {
+ extends ValOrDefDef(mods, name, tpt, rhs) {
assert(tpt.isType);
assert(rhs.isTerm);
+ def keyword = "def";
}
def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
@@ -189,7 +237,15 @@ import symtab.Flags._;
/** Abstract type or type parameter */
case class AbsTypeDef(mods: int, name: Name, lo: Tree, hi: Tree)
- extends DefTree;
+ extends DefTree(name) {
+ def keyword = "";
+
+ override def setPos(pos : Int) : this.type = {
+ val ret = super.setPos(pos);
+ ret;
+ }
+ def namePos = pos - name.length;
+ }
def AbsTypeDef(sym: Symbol): AbsTypeDef =
posAssigner.atPos(sym.pos) {
@@ -199,7 +255,9 @@ import symtab.Flags._;
/** Type alias */
case class AliasTypeDef(mods: int, name: Name, tparams: List[AbsTypeDef], rhs: Tree)
- extends DefTree;
+ extends MemberDef(mods, name) {
+ def keyword = "type";
+ }
def AliasTypeDef(sym: Symbol, rhs: Tree): AliasTypeDef =
posAssigner.atPos(sym.pos) {
@@ -216,7 +274,7 @@ import symtab.Flags._;
* jumps within a Block.
*/
case class LabelDef(name: Name, params: List[Ident], rhs: Tree)
- extends DefTree with TermTree {
+ extends DefTree(name) with TermTree {
assert(rhs.isTerm);
}
@@ -245,7 +303,9 @@ import symtab.Flags._;
/** Instantiation template */
case class Template(parents: List[Tree], body: List[Tree])
- extends SymTree;
+ extends SymTree {
+ // System.err.println("TEMPLATE: " + parents);
+ }
def Template(parents: List[Tree], vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree]): Template = {
/** Add constructor to template */
@@ -290,7 +350,7 @@ import symtab.Flags._;
/** Bind of a variable to a rhs pattern, eliminated by TransMatch */
case class Bind(name: Name, body: Tree)
- extends DefTree;
+ extends DefTree(name);
def Bind(sym: Symbol, body: Tree): Bind =
Bind(sym.name, body) setSymbol sym;
@@ -353,16 +413,19 @@ import symtab.Flags._;
case class Typed(expr: Tree, tpt: Tree)
extends TermTree;
+ abstract class GenericApply(val fun0: Tree, val args0: List[Tree]) extends TermTree;
+
+
/** Type application */
case class TypeApply(fun: Tree, args: List[Tree])
- extends TermTree {
+ extends GenericApply(fun, args) {
override def symbol: Symbol = fun.symbol;
override def symbol_=(sym: Symbol): unit = { fun.symbol = sym }
}
/** Value application */
case class Apply(fun: Tree, args: List[Tree])
- extends TermTree {
+ extends GenericApply(fun, args) {
override def symbol: Symbol = fun.symbol;
override def symbol_=(sym: Symbol): unit = { fun.symbol = sym }
}
@@ -384,6 +447,17 @@ import symtab.Flags._;
extends SymTree {
override def isTerm = selector.isTermName;
override def isType = selector.isTypeName;
+
+ override def setPos(pos : Int) : this.type = {
+ val ret = super.setPos(pos);
+ if (pos == 23) {
+ //System.err.println("SELECT: " + this);
+ //Thread.dumpStack();
+ }
+ ret;
+ }
+
+
}
def Select(qualifier: Tree, sym: Symbol): Select =
@@ -394,6 +468,12 @@ import symtab.Flags._;
extends SymTree {
override def isTerm = name.isTermName;
override def isType = name.isTypeName;
+
+ override def setPos(p : Int) : this.type = {
+ val ret = super.setPos(p);
+ ret;
+ }
+
}
def Ident(sym: Symbol): Ident =
@@ -409,10 +489,27 @@ import symtab.Flags._;
/** General type term, introduced by RefCheck. */
case class TypeTree() extends TypTree {
+ var original : Tree = _;
+
+ def setOriginal(tree : Tree) : this.type = {
+ original = tree;
+ setPos(tree.pos);
+ }
+ override def setPos(pos : Int) : this.type = {
+ val ret = super.setPos(pos);
+ if (false && pos == 151 && original == null) {
+ System.err.println("TYPE: " + this + " POS=" + pos + " TPE=" + tpe);
+ Thread.dumpStack();
+ }
+ ret;
+ }
+
+
override def isEmpty = tpe == null || tpe == NoType;
}
def TypeTree(tp: Type): TypeTree = TypeTree() setType tp;
+ // def TypeTree(tp: Type, tree : Tree): TypeTree = TypeTree(tree) setType tp;
/** Singleton type, eliminated by RefCheck */
@@ -1114,7 +1211,7 @@ import symtab.Flags._;
private var pos: int = _;
override def traverse(t: Tree): unit =
if (t != EmptyTree && t.pos == Position.NOPOS) {
- t.pos = pos;
+ t.setPos(pos);
super.traverse(t);
}
def atPos[T <: Tree](pos: int)(tree: T): T = {
diff --git a/sources/scala/tools/nsc/ast/parser/MarkupParsers.scala b/sources/scala/tools/nsc/ast/parser/MarkupParsers.scala
index be25e8eefe..cf4244cb3f 100644
--- a/sources/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/sources/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -416,7 +416,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
def xLiteral: Tree = try {
init;
handle.isPattern = false;
- val pos = s.pos;
+ val pos = s.currentPos;
var tree = element;
xSpaceOpt;
// parse more XML ?
@@ -452,7 +452,7 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
init;
val oldMode = handle.isPattern;
handle.isPattern = true;
- val pos = s.pos;
+ val pos = s.currentPos;
var tree = xPattern; xSpaceOpt;
//if (ch == '<') {
var ts: List[Tree] = List();
@@ -508,13 +508,13 @@ class MarkupParser(unit: CompilationUnit, s: Scanner, p: Parser, presWS: boolean
//var ch: Char = _;
/** this method assign the next character to ch and advances in input */
- def nextch: Unit = { s.in.next; /*s.xNext;*/ ch = s.in.ch ; pos = s.pos; }
+ def nextch: Unit = { s.in.next; /*s.xNext;*/ ch = s.in.ch ; pos = s.currentPos; }
//def lookahead = { s.xLookahead }
def init: Unit = {
ch = s.in.ch;
- pos = s.pos;
+ pos = s.currentPos;
//Console.println("\ninit! ch = "+ch);
}
diff --git a/sources/scala/tools/nsc/ast/parser/Parsers.scala b/sources/scala/tools/nsc/ast/parser/Parsers.scala
index 08eac39340..0c926df35f 100755
--- a/sources/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/sources/scala/tools/nsc/ast/parser/Parsers.scala
@@ -97,7 +97,7 @@ import Tokens._;
}
def syntaxError(msg: String, skipIt: boolean): unit =
- syntaxError(in.pos, msg, skipIt);
+ syntaxError(in.currentPos, msg, skipIt);
def syntaxError(pos: int, msg: String, skipIt: boolean): unit = {
if (pos != in.errpos) {
@@ -108,20 +108,20 @@ import Tokens._;
}
def accept(token: int): int = {
- val pos = in.pos;
+ val pos = in.currentPos;
if (in.token != token)
syntaxError(
- if (Position.line(in.pos) > Position.line(in.lastpos)) in.lastpos
- else in.pos,
+ if (Position.line(in.currentPos) > Position.line(in.lastpos)) in.lastpos
+ else in.currentPos,
in.token2string(token) + " expected but " +
in.token2string(in.token) + " found.", true);
if (in.token == token) in.nextToken();
- pos
+ pos;
}
- def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.pos);
- def errorTermTree = Literal(Constant(null)).setPos(in.pos);
- def errorPatternTree = Ident(nme.WILDCARD).setPos(in.pos);
+ def errorTypeTree = TypeTree().setType(ErrorType).setPos(in.currentPos);
+ def errorTermTree = Literal(Constant(null)).setPos(in.currentPos);
+ def errorPatternTree = Ident(nme.WILDCARD).setPos(in.currentPos);
/////// TOKEN CLASSES //////////////////////////////////////////////////////
@@ -326,7 +326,7 @@ import Tokens._;
if (in.token == DOT)
t = atPos(in.skipToken()) { selectors(t, typeOK) }
} else {
- val i = atPos(in.pos) { Ident(ident()) }
+ val i = atPos(in.currentPos) { Ident(ident()) }
t = i;
if (in.token == DOT) {
val pos = in.skipToken();
@@ -381,7 +381,7 @@ import Tokens._;
/** QualId ::= Id {`.' Id}
*/
def qualId(): Tree = {
- val id = atPos(in.pos) { Ident(ident()) }
+ val id = atPos(in.currentPos) { Ident(ident()) }
if (in.token == DOT) atPos(in.skipToken()) { selectors(id, false) }
else id
}
@@ -391,7 +391,7 @@ import Tokens._;
* | null
*/
def literal(isPattern: boolean, isNegated: boolean): Tree = {
- def litToTree() = atPos(in.pos) {
+ def litToTree() = atPos(in.currentPos) {
Literal(
in.token match {
case CHARLIT =>
@@ -490,7 +490,7 @@ import Tokens._;
/** Type1 ::= SimpleType {with SimpleType} [Refinement]
*/
def type1(): Tree = {
- val pos = in.pos;
+ val pos = in.currentPos;
var ts = new ListBuffer[Tree] + simpleType();
while (in.token == WITH) {
in.nextToken(); ts += simpleType()
@@ -508,7 +508,7 @@ import Tokens._;
* | `(' Type `)'
*/
def simpleType(): Tree = {
- val pos = in.pos;
+ val pos = in.currentPos;
var t: Tree =
if (in.token == LPAREN) {
in.nextToken();
@@ -517,15 +517,17 @@ import Tokens._;
t
} else {
val r = stableRef(false, true);
- r match {
+ val x = r match {
case SingletonTypeTree(_) => r
case _ => convertToTypeId(r);
}
+ // System.err.println("SIMPLE_TYPE: " + r.pos + " " + r + " => " + x.pos + " " + x);
+ x;
}
while (true) {
if (in.token == HASH)
t = atPos(in.skipToken()) {
- SelectFromTypeTree(t, ident().toTypeName)
+ SelectFromTypeTree(t, ident().toTypeName);
}
else if (in.token == LBRACKET)
t = atPos(pos) { AppliedTypeTree(t, typeArgs()) }
@@ -683,7 +685,7 @@ import Tokens._;
Typed(t, atPos(pos1) { Ident(nme.WILDCARD_STAR.toTypeName) })
}
} else {
- syntaxError(in.pos, "`*' expected", true);
+ syntaxError(in.currentPos, "`*' expected", true);
}
} else {
t = atPos(pos) { Typed(t, type1()) }
@@ -715,7 +717,7 @@ import Tokens._;
while (in.token == IDENTIFIER) {
top = reduceStack(
true, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name));
- opstack = OpInfo(top, in.name, in.pos) :: opstack;
+ opstack = OpInfo(top, in.name, in.currentPos) :: opstack;
ident();
if (isExprIntro) {
top = prefixExpr();
@@ -737,10 +739,10 @@ import Tokens._;
val name = ident();
in.token match {
case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT => literal(false, true)
- case _ => atPos(in.pos) { Select(simpleExpr(), name) }
+ case _ => atPos(in.currentPos) { Select(simpleExpr(), name) }
}
} else if (in.token == IDENTIFIER && (in.name == PLUS || in.name == TILDE || in.name == BANG)) {
- val pos = in.pos;
+ val pos = in.currentPos;
val name = ident();
atPos(pos) { Select(simpleExpr(), name) }
} else {
@@ -820,12 +822,12 @@ import Tokens._;
case LBRACKET =>
t match {
case Ident(_) | Select(_, _) =>
- t = atPos(in.pos) { TypeApply(t, typeArgs()) }
+ t = atPos(in.currentPos) { TypeApply(t, typeArgs()) }
case _ =>
return t;
}
case LPAREN | LBRACE if (!isNew) =>
- t = atPos(in.pos) { Apply(t, argumentExprs()) }
+ t = atPos(in.currentPos) { Apply(t, argumentExprs()) }
case _ =>
return t
}
@@ -919,7 +921,7 @@ import Tokens._;
* SeqPattern ::= SeqPattern1 { `|' SeqPattern1 }
*/
def pattern(seqOK: boolean): Tree = {
- val pos = in.pos;
+ val pos = in.currentPos;
val t = pattern1(seqOK);
if (in.token == IDENTIFIER && in.name == BAR) {
val ts = new ListBuffer[Tree] + t;
@@ -941,7 +943,7 @@ import Tokens._;
*/
def pattern1(seqOK: boolean): Tree =
if (seqOK && !isExprIntro) {
- atPos(in.pos) { Sequence(List()) }
+ atPos(in.currentPos) { Sequence(List()) }
} else {
val p = pattern2(seqOK);
p match {
@@ -994,7 +996,7 @@ import Tokens._;
while (in.token == IDENTIFIER && in.name != BAR) {
top = reduceStack(
false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name));
- opstack = OpInfo(top, in.name, in.pos) :: opstack;
+ opstack = OpInfo(top, in.name, in.currentPos) :: opstack;
ident();
top = simplePattern(seqOK)
}
@@ -1108,7 +1110,7 @@ import Tokens._;
private def addMod(mods: int, mod: int): int = {
if ((mods & mod) != 0)
- syntaxError(in.pos, "repeated modifier", false);
+ syntaxError(in.currentPos, "repeated modifier", false);
in.nextToken();
mods | mod;
}
@@ -1126,7 +1128,7 @@ import Tokens._;
var implicitmod = 0;
var caseParam = ofCaseClass;
def param(): ValDef = {
- atPos(in.pos) {
+ atPos(in.currentPos) {
var mods = Flags.PARAM;
if (owner.isTypeName) {
mods = modifiers() | Flags.PARAMACCESSOR;
@@ -1159,7 +1161,7 @@ import Tokens._;
params.toList
}
val vds = new ListBuffer[List[ValDef]];
- val pos = in.pos;
+ val pos = in.currentPos;
while (implicitmod == 0 && in.token == LPAREN) {
in.nextToken();
vds += paramClause();
@@ -1214,7 +1216,7 @@ import Tokens._;
}
}
val pname = ident();
- val param = atPos(in.pos) { typeBounds(mods, pname) }
+ val param = atPos(in.currentPos) { typeBounds(mods, pname) }
if (in.token == VIEWBOUND && (implicitViews != null))
implicitViews += atPos(in.skipToken()) {
makeFunctionTypeTree(List(Ident(pname.toTypeName)), typ())
@@ -1262,15 +1264,15 @@ import Tokens._;
/** ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
*/
def importExpr(): Tree =
- atPos(in.pos) {
+ atPos(in.currentPos) {
var t: Tree = null;
var pos = 0;
if (in.token == THIS) {
- t = atPos(in.pos) { This(nme.EMPTY.toTypeName) }
+ t = atPos(in.currentPos) { This(nme.EMPTY.toTypeName) }
t = atPos(accept(DOT)) { Select(t, ident()) }
pos = accept(DOT);
} else {
- val i = atPos(in.pos) { Ident(ident()) }
+ val i = atPos(in.currentPos) { Ident(ident()) }
pos = accept(DOT);
if (in.token == THIS) {
in.nextToken();
@@ -1477,7 +1479,7 @@ import Tokens._;
* TypeDcl ::= Id TypeBounds
*/
def typeDefOrDcl(mods: int): Tree =
- atPos(in.pos) {
+ atPos(in.currentPos) {
val name = ident().toTypeName;
in.token match {
case LBRACKET =>
@@ -1541,13 +1543,15 @@ import Tokens._;
/** ClassTemplate ::= [`extends' TemplateParents] [TemplateBody]
* TemplateParents ::= SimpleType {`(' [Exprs] `)'} {`with' SimpleType}
*/
- def classTemplate(mods: int, name: Name, vparamss: List[List[ValDef]]): Template =
- atPos(in.pos) {
+ def classTemplate(mods: int, name: Name, vparamss: List[List[ValDef]]): Template = {
+ val ret = atPos(in.currentPos) {
val parents = new ListBuffer[Tree];
val argss = new ListBuffer[List[Tree]];
if (in.token == EXTENDS) {
in.nextToken();
- parents += simpleType();
+ val parent = simpleType();
+ // System.err.println("classTempl: " + parent);
+ parents += parent;
if (in.token == LPAREN)
do { argss += argumentExprs() } while (in.token == LPAREN)
else argss += List();
@@ -1571,6 +1575,8 @@ import Tokens._;
if ((mods & Flags.TRAIT) == 0) Template(ps, vparamss, argss.toList, body)
else Template(ps, body)
}
+ ret;
+ }
////////// TEMPLATES ////////////////////////////////////////////////////////////
@@ -1684,10 +1690,10 @@ import Tokens._;
/** Attribute ::= StableId [TypeArgs] [`(' [Exprs] `)']
*/
def attribute(): Tree = {
- val pos = in.pos;
+ val pos = in.currentPos;
var t: Tree = convertToTypeId(stableId());
if (in.token == LBRACKET)
- t = atPos(in.pos)(AppliedTypeTree(t, typeArgs()));
+ t = atPos(in.currentPos)(AppliedTypeTree(t, typeArgs()));
val args = if (in.token == LPAREN) argumentExprs() else List();
atPos(pos) { New(t, List(args)) }
}
@@ -1743,13 +1749,13 @@ import Tokens._;
stats ++= defOrDcl(0);
accept(SEMI);
if (in.token == RBRACE || in.token == CASE) {
- stats += Literal(()).setPos(in.pos)
+ stats += Literal(()).setPos(in.currentPos)
}
} else if (isLocalModifier) {
stats += tmplDef(localClassModifiers());
accept(SEMI);
if (in.token == RBRACE || in.token == CASE) {
- stats += Literal(()).setPos(in.pos)
+ stats += Literal(()).setPos(in.currentPos)
}
} else if (in.token == SEMI) {
in.nextToken();
@@ -1765,7 +1771,7 @@ import Tokens._;
* | TopStatSeq
*/
def compilationUnit(): Tree =
- atPos(in.pos) {
+ atPos(in.currentPos) {
if (in.token == PACKAGE) {
in.nextToken();
val pkg = qualId();
diff --git a/sources/scala/tools/nsc/ast/parser/Scanners.scala b/sources/scala/tools/nsc/ast/parser/Scanners.scala
index 0d0ede2d22..57f491cab5 100755
--- a/sources/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/sources/scala/tools/nsc/ast/parser/Scanners.scala
@@ -21,7 +21,10 @@ import scala.tools.nsc.util.CharArrayReader;
var token: int = EMPTY;
/** the token's position */
- var pos: int = 0;
+ protected var pos: int = 0;
+
+ def currentPos = pos - 1;
+
/** the name of an identifier or token */
var name: Name = null;
@@ -92,7 +95,9 @@ import scala.tools.nsc.util.CharArrayReader;
/** read next token and return last position
*/
def skipToken(): int = {
- val p = pos; nextToken(); p
+ val p = pos; nextToken();
+ // XXX: account for off by one error
+ p - 1
}
def nextToken(): unit = {
diff --git a/sources/scala/tools/nsc/backend/icode/Printers.scala b/sources/scala/tools/nsc/backend/icode/Printers.scala
index 8a562f73fd..dbc7badb9a 100644
--- a/sources/scala/tools/nsc/backend/icode/Printers.scala
+++ b/sources/scala/tools/nsc/backend/icode/Printers.scala
@@ -60,7 +60,9 @@ abstract class Printers {
}
+ private var clazz : IClass = _;
def printClass(cls: IClass): Unit = {
+ this.clazz = cls;
print(cls.symbol.toString()); print(" extends ");
printList(cls.symbol.info.parents, ", ");
indent; println(" {");
@@ -119,7 +121,7 @@ abstract class Printers {
def printInstruction(i: Instruction): Unit = {
if (settings.debug.value)
- print("/* " + Position.line(i.pos) + " */ ");
+ print("/* " + Position.line(clazz.cunit.source, i.pos) + " */ ");
println(i.toString());
}
}
diff --git a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
index 1aea04fa51..f2ac6135bb 100644
--- a/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/sources/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -558,8 +558,11 @@ abstract class GenJVM extends SubComponent {
crtPC = jcode.getPC();
val crtLine = try { clasz.cunit.position(instr.pos).line; } catch {
- case _: Error => -1;
+ case _: Error => Position.NOPOS;
}
+ //System.err.println("CRTLINE: " + instr.pos + " " +
+ // /* (if (instr.pos < clasz.cunit.source.content.length) clasz.cunit.source.content(instr.pos) else '*') + */ " " + crtLine);
+
if (crtLine != lastLineNr &&
crtPC > lastMappedPC) {
jcode.completeLineNumber(lastMappedPC, crtPC, crtLine);
@@ -697,7 +700,7 @@ abstract class GenJVM extends SubComponent {
log("Converting from: " + src + " to: " + dst);
if (dst == BOOL) {
Console.println("Illegal conversion at: " + clasz +
- " at: " + method.sourceFile + ":" + Position.line(pos));
+ " at: " + method.sourceFile + ":" + Position.line(clasz.cunit.source, pos));
} else
jcode.emitT2T(javaType(src), javaType(dst));
diff --git a/sources/scala/tools/nsc/matching/CodeFactory.scala b/sources/scala/tools/nsc/matching/CodeFactory.scala
index dbdd99ac09..0b8ecab71a 100644
--- a/sources/scala/tools/nsc/matching/CodeFactory.scala
+++ b/sources/scala/tools/nsc/matching/CodeFactory.scala
@@ -210,7 +210,7 @@ import scala.tools.nsc.util.Position;
),
List(
Literal(cunit.toString()),
- Literal(Position.line(pos))
+ Literal(Position.line(cunit.source, pos))
)
);
@@ -220,7 +220,7 @@ import scala.tools.nsc.util.Position;
gen.mkRef(definitions.MatchError_report),
List(
Literal(cunit.toString()),
- Literal(Position.line(pos)),
+ Literal(Position.line(cunit.source, pos)),
tree
)
);
diff --git a/sources/scala/tools/nsc/models/Models.scala.xxx b/sources/scala/tools/nsc/models/Models.scala.xxx
new file mode 100644
index 0000000000..680ca21680
--- /dev/null
+++ b/sources/scala/tools/nsc/models/Models.scala.xxx
@@ -0,0 +1,189 @@
+/* NSC -- new scala compiler
+ * Copyright 2005 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: Trees.scala,v 1.35 2005/11/14 16:58:21 mcdirmid Exp $
+package scala.tools.nsc.models;
+
+import scala.tools.nsc.Global;
+import scala.tools.nsc.ast.Trees;
+import scala.tools.nsc.symtab.Flags;
+import scala.tools.nsc.symtab.Names;
+
+[_trait_] abstract class Models {
+ val global : Global;
+
+ import global._;
+
+ abstract class Model {
+ }
+ abstract class HasTree extends Model {
+ var tree : Tree = _;
+ def update(tree0 : Tree): Boolean = {
+ tree = tree0;
+ false;
+ }
+ def replacedBy(tree0 : Tree) : Boolean = true;
+ }
+ class ImportMod extends HasTree {
+ def treex = tree.asInstanceOf[Import];
+
+ override def replacedBy(tree0 : Tree) : Boolean = if (super.replacedBy(tree0) && tree0.isInstanceOf[Import]) {
+ val tree1 = tree0.asInstanceOf[Import];
+ tree1.tpe == treex.tpe;
+ } else false;
+ }
+
+ abstract class Composite extends Model {
+ import scala.collection.mutable._;
+ class Members extends HashSet[HasTree] with ObservableSet[HasTree, Members] {
+ override def +=(elem: HasTree): Unit = super.+=(elem);
+ override def -=(elem: HasTree): Unit = super.-=(elem);
+ override def clear: Unit = super.clear;
+ }
+ object members extends Members;
+
+ def isMember(tree : Tree) : Boolean = false;
+
+ def update0(members1 : List[Tree]) : Boolean = {
+ val marked = new HashSet[HasTree];
+ var updated = false;
+ for (val mmbr1 <- members1) {
+ var found = false;
+ for (val mmbr <- members) if (!found && mmbr.replacedBy(mmbr1)) {
+ found = true;
+ updated = mmbr.update(mmbr1) || updated;
+ marked += mmbr;
+ }
+ if (!found) {
+ updated = true;
+ val add = modelFor(mmbr1);
+ add.update(mmbr1);
+ members += (add);
+ marked += add;
+ }
+ }
+ val sz = members.size;
+ members.intersect(marked);
+ updated = updated || sz < members.size;
+ // check if anything was removed!
+ updated;
+ }
+ }
+ abstract class MemberMod extends HasTree {
+ def treex = tree.asInstanceOf[MemberDef];
+ def flags = new Flags.Flag(treex.mods0);
+ def name : Name = { treex.name0; }
+
+ override def replacedBy(tree0 : Tree) : Boolean = if (super.replacedBy(tree0) && tree0.isInstanceOf[MemberDef]) {
+ val tree1 = tree0.asInstanceOf[MemberDef];
+ treex.name0 == tree1.name0;
+ } else false;
+
+ override def update(tree0 : Tree): Boolean = {
+ val updated = tree == null || (treex.mods0 != tree0.asInstanceOf[MemberDef].mods0);
+ super.update(tree0) || updated;
+ }
+ }
+ abstract class MemberComposite extends MemberMod with Composite;
+
+ abstract class HasClassObjects extends Composite {
+ override def isMember(tree : Tree) : Boolean = super.isMember(tree) || tree.isInstanceOf[ImplDef];
+ }
+ abstract class ValOrDefMod extends MemberComposite with HasClassObjects {
+ def treey = tree.asInstanceOf[ValOrDefDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[ValOrDefDef]);
+
+ override def update(tree0 : Tree): Boolean = {
+ val tree1 = tree0.asInstanceOf[ValOrDefDef];
+ val updated = tree == null || treex.tpe != tree1.tpe;
+ update0(flatten(tree1.rhs0, (tree2 : Tree) => isMember(tree2)));
+ super.update(tree0) || updated;
+ }
+ }
+ class ValMod extends ValOrDefMod {
+ def treez = tree.asInstanceOf[ValDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[ValDef]);
+ }
+ class DefMod extends ValOrDefMod {
+ def treez = tree.asInstanceOf[DefDef];
+
+ override def replacedBy(tree0 : Tree) : Boolean = if (super.replacedBy(tree0) && tree0.isInstanceOf[DefDef]) {
+ val tree1 = tree0.asInstanceOf[DefDef];
+ if (tree1.vparamss.length == treez.vparamss.length) {
+ val tpz = for (val vd <- treez.vparamss) yield for (val xd <- vd) yield xd.tpe;
+ val tp1 = for (val vd <- tree1.vparamss) yield for (val xd <- vd) yield xd.tpe;
+ tpz == tp1;
+ } else false;
+ } else false;
+ }
+ abstract class ImplMod extends MemberComposite with HasClassObjects {
+ def treey = tree.asInstanceOf[ImplDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[ImplDef]);
+ override def isMember(tree : Tree) : Boolean = super.isMember(tree) || tree.isInstanceOf[ValOrDefDef] || tree.isInstanceOf[AliasTypeDef];
+
+ override def update(tree0 : Tree): Boolean = {
+ val tree1 = tree0.asInstanceOf[ImplDef];
+
+ var updated = update0(tree1.impl0.body);
+
+ // XXX: ignore parents for now!
+
+ (super.update(tree0) || updated) && !flags.isPrivate;
+ }
+
+
+ }
+ class ClassMod extends ImplMod {
+ def treez = tree.asInstanceOf[ClassDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[ClassDef]);
+
+ override def update(tree0 : Tree): Boolean = {
+ // XXX: type parameters and this type!
+
+
+ super.update(tree0);
+ }
+ }
+ class ObjectMod extends ImplMod {
+ def treez = tree.asInstanceOf[ModuleDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[ModuleDef]);
+ }
+ class AliasTypeMod extends MemberMod {
+ def treey = tree.asInstanceOf[AliasTypeDef];
+ override def replacedBy(tree0 : Tree) : Boolean = (super.replacedBy(tree0) && tree0.isInstanceOf[AliasTypeDef]);
+ }
+ class SourceMod(val unit : CompilationUnit) extends Composite with HasClassObjects {
+ override def isMember(tree : Tree) : Boolean = super.isMember(tree) || tree.isInstanceOf[Import];
+ }
+
+
+ def flatten0(exprs : List[Tree], filter: (Tree) => Boolean) : List[Tree] =
+ for (val expr <- exprs; val t : Tree <- flatten(expr,filter)) yield t;
+
+ def flatten(expr : Tree, filter: (Tree) => Boolean) : List[Tree] =
+ if (filter(expr)) expr :: Nil; else expr match {
+ case Block(stats,last) => flatten0(stats, filter) ::: flatten(last, filter);
+ case If(cond,thenp,elsep) => flatten(cond,filter) ::: flatten(thenp,filter) ::: flatten(elsep,filter);
+ case Assign(lhs,rhs) => flatten(rhs,filter);
+ case CaseDef(pat,guard,body) => flatten(body,filter);
+ case Return(expr0) => flatten(expr0,filter);
+ case Throw(expr0) => flatten(expr0,filter);
+ case Try(block,catches,finalizer) => flatten(block,filter) ::: flatten(finalizer,filter) ::: flatten0(catches, filter);
+ case Match(selector,cases) => flatten(selector,filter) ::: flatten0(cases, filter);
+ case Apply(fun,args) => flatten(fun,filter) ::: flatten0(args,filter);
+ case TypeApply(fun,args) => flatten(fun,filter) ::: flatten0(args,filter);
+ case _ => Nil;
+ }
+
+
+ def modelFor(tree: Tree): HasTree = tree match {
+ case _: ValDef => new ValMod();
+ case _: DefDef => new DefMod();
+ case _: ClassDef => new ClassMod();
+ case _: ModuleDef => new ObjectMod();
+ case _: AliasTypeDef => new AliasTypeMod();
+ case _: Import => new ImportMod();
+ }
+
+}
diff --git a/sources/scala/tools/nsc/models/SemanticTokens.scala b/sources/scala/tools/nsc/models/SemanticTokens.scala
new file mode 100644
index 0000000000..6a4b14a3a2
--- /dev/null
+++ b/sources/scala/tools/nsc/models/SemanticTokens.scala
@@ -0,0 +1,477 @@
+
+package scala.tools.nsc.models;
+
+import scala.tools.nsc.{Global => Compiler};
+import scala.tools.nsc.symtab.{Flags,Names};
+import scala.tools.nsc.util.{NameTransformer,Position,SourceFile};
+import scala.collection.mutable.{HashMap,HashSet};
+
+
+
+class SemanticTokens(val compiler: Compiler) {
+ import compiler._;
+
+ abstract class Kind {}
+ object OBJECT extends Kind;
+ object CLASS extends Kind;
+ object DEF extends Kind;
+ object VAL extends Kind;
+ object VAR extends Kind;
+ object ARG extends Kind;
+ object TPARAM extends Kind;
+
+ // static constants here.
+
+ abstract class Token {
+ def length : Int;
+
+ def prev : HasNext;
+ def next : HasPrev;
+ }
+
+ [_trait_] abstract class HasNext extends Token {
+ var next0 : HasPrev = _;
+ def next = next0;
+ }
+ [_trait_] abstract class HasPrev extends Token {
+ var prev0 : HasNext = _;
+ def prev = prev0;
+ }
+ abstract class Actual extends HasNext with HasPrev {
+ def convertToGap : Pair[Int,Actual] = {
+ val nextGap = next.isInstanceOf[Gap];
+ val prevGap = prev.isInstanceOf[Gap];
+ if (prevGap) {
+ val ret = prev.length;
+ val gap = prev.asInstanceOf[Gap];
+ gap.setLength(gap.length + length);
+ if (nextGap) {
+ gap.setLength(gap.length + next.length);
+ gap.next0 = next.next;
+ next.next.prev0 = gap;
+ } else {
+ gap.next0 = next;
+ next.prev0 = gap;
+ }
+ new Pair(ret,gap);
+ } else if (nextGap) {
+ val gap = next.asInstanceOf[Gap];
+ gap.setLength(gap.length + length);
+ gap.prev0 = prev;
+ prev.next0 = gap;
+ new Pair(0,gap);
+ } else {
+ prev.next0 = next;
+ next.prev0 = prev;
+ val gap = new Gap(prev);
+ gap.setLength(length);
+ new Pair(0,gap);
+ }
+ }
+ }
+ final class Gap extends Actual {
+ def this(prev1 : HasNext) = {
+ this();
+ next0 = prev1.next;
+ prev0 = prev1;
+ prev0.next0 = this;
+ next0.prev0 = this;
+ }
+ override def toString() = "gap-" + length;
+
+
+ var length0 : Int = -1;
+ def length : Int = length0;
+ def setLength(length1 : Int) = length0 = length1;
+
+ // already gap
+ override def convertToGap : Pair[Int,Actual] = new Pair(0, this);
+ }
+ val sources = new HashMap[String /* path */, Process];
+ val reverse = new HashMap[Symbol, String /* path */];
+
+
+
+ class Process(val unit : CompilationUnit) {
+ def source = unit.source;
+
+ if (sources.contains(source.path)) {
+ for (val sym : Symbol <- sources(source.path).symbols.keys; reverse(sym) == source.path)
+ reverse -= sym;
+ sources -= source.path;
+ }
+ sources.update(source.path, this);
+
+ val symbols = new HashMap[Symbol,Info];
+
+
+ class Info(val symbol : Symbol) {
+ var defined : Def = _;
+ val uses = new HashSet[Use];
+ symbols.update(symbol, this);
+ }
+ def info(symbol : Symbol) : Info = if (symbols.contains(symbol)) symbols(symbol) else new Info(symbol);
+
+ abstract class Semantic(val symbol : Symbol) extends Actual {
+ val name = NameTransformer.decode(symbol.name.toString()).toString().trim();
+
+
+ def length = name.length();
+ def info : Info = if (symbols.contains(symbol)) symbols(symbol) else new Info(symbol);
+
+ def kind = {
+ val term0 = symbol;
+ if (false) null;
+ else if (term0.isVariable) VAR;
+ else if (term0.isValueParameter) ARG;
+ else if (term0.isMethod) DEF;
+ else if (term0.isClass) CLASS;
+ else if (term0.isModule) OBJECT;
+ else if (term0.isValue ) VAL;
+ else if (term0.isTypeParameter) TPARAM;
+ else {
+ System.err.println("UNRECOGNIZED SYMBOL: " + term0 + " " + name);
+ null;
+ }
+ };
+
+
+
+ }
+ class Def(tree0 : DefTree) extends Semantic(tree0.symbol) {
+ if (info.defined != null) throw new Error("old=" + info.defined + " vs. new=" + this);
+ info.defined = this;
+ reverse.update(symbol, source.path);
+
+ override def toString() = "def-" + name;
+
+ // if (name.equals("x$0")) throw new Error("SYM=" + symbol + " TREE: " + tree0);
+
+ }
+ class Use(symbol0 : Symbol) extends Semantic(symbol0) {
+ info.uses += this;
+
+ override def toString() = "use-" + name;
+ }
+
+
+
+ val list = new TokenList;
+
+ build(unit.body);
+
+ // ok start building....
+ def build[T <: Tree](trees : List[T]) : Unit = for (val tree : T <- trees) build(tree);
+
+ def build(tree0 : Tree) : Unit = if (tree0.pos != Position.NOPOS) tree0 match {
+ case tree : ImplDef =>
+ list.put(tree.namePos(unit.source), new Def(tree));
+ tree match {
+ case cdef : ClassDef => build(cdef.tparams);
+ case _ => ;
+ }
+ build(tree.impl0.parents);
+ build(tree.impl0.body);
+
+ case tree : ValOrDefDef =>
+ // System.err.println("VAL: " + tree + " @ " + tree.pos);
+
+
+ if (tree.name0.toString().equals("<init>")) {
+ //System.err.println("IGNORE: " + tree.name0.toString() + " " + tree.pos);
+ } else if (tree.symbol.hasFlag(Flags.ACCESSOR)) {
+ // ignore
+ ;
+ } else {
+ val pos = tree.namePos(unit.source);
+ if (pos != Position.NOPOS) {
+
+ if (!tree.hasFlag(Flags.SYNTHETIC))
+ list.put(pos, new Def(tree));
+
+ if (tree.isInstanceOf[DefDef]) {
+ val ddef = tree.asInstanceOf[DefDef];
+ build(ddef.tparams);
+
+ for (val l0 <- ddef.vparamss; val arg <- l0) {
+
+ val pos0 = if (!unit.source.beginsWith(arg.pos, "val ")) arg.pos;
+ else unit.source.skipWhitespace(arg.pos + ("val ").length());
+ list.put(pos0, new Def(arg));
+ build(arg.tpt0);
+ }
+ }
+ build(tree.tpt0);
+ build(tree.rhs0);
+ }
+ }
+ case tree : PackageDef =>
+ val pos = tree.namePos(unit.source);
+ list.put(pos, new Def(tree));
+ build(tree.stats);
+ case tree : Function =>
+ for (val arg <- tree.vparams) if (arg.pos != Position.NOPOS) {
+ val name = arg.name0.toString().trim();
+ val pos : Int =
+ if (unit.source.beginsWith(arg.pos, "val ")) unit.source.skipWhitespace(arg.pos + ("val ").length());
+ else if (unit.source.content(arg.pos) == ':') {
+ var posx = arg.pos;
+ while (Character.isWhitespace(unit.source.content(posx - 1))) posx = posx - 1;
+ posx - name.length();
+ } else arg.pos;
+ list.put(pos, new Def(arg));
+ build(arg.tpt0);
+ }
+ build(tree.body);
+ case tree : TypeTree =>
+ val tree1 = if (tree.original != null) tree.original; else tree;
+ build(tree1, tree.tpe);
+ def build( tree : Tree, tpe : Type) : Unit = if (tree.pos != Position.NOPOS) tpe match {
+ case tpe0 : TypeRef => tree match {
+ case apt : AppliedTypeTree =>
+ buildSym(tpe0.sym, apt.tpt.pos);
+ buildTs (apt.args, tpe0.args);
+ case ident : Ident => buildSym(tpe0.sym, ident.pos);
+ case select : Select =>
+ val pos = selectPos(select);
+ buildSym(tpe0.sym, pos);
+ case tpt : TypeTree =>
+ // System.err.println("UNKNOWN TPT: " + tree + " vs. " + tpe0 + " " + tpt.original + " " + unit.source.content(tree.pos));
+ case _ => System.err.println("UNKNOWN TPE: " + tree + " vs. " + tpe0 + " " + tree.getClass() + " " + unit.source.content(tree.pos));
+ }
+ case tpe0 : MethodType => tree match {
+ case tpt: TypeTree =>
+ if (tpt.original != null) build(tpt.original, tpe);
+ else {
+ System.err.println("UNKNOWN TPT: " + tree + " vs. " + tpe0 + " " + unit.source.content(tree.pos));
+ }
+ case ident : Ident => build(ident, tpe0.resultType);
+ case select : Select => build(select, tpe0.resultType);
+ case _ => System.err.println("UNKNOWN TPE: " + tree + " vs. " + tpe0 + " " + tree.getClass());
+ }
+ case _ => System.err.println("UNKNOWN: " + tree + " " + tree.getClass() + " vs. " + tpe + " " + tpe.getClass() + " " + tree.pos);
+ };
+ def buildTs(trees : List[Tree], types : List[Type]): Unit = if (!trees.isEmpty || !types.isEmpty) {
+ build (trees.head, types.head);
+ buildTs(trees.tail, types.tail);
+ };
+ case tree : AbsTypeDef =>
+ list.put(tree.namePos, new Def(tree));
+ case tree : Bind =>
+ list.put(tree.pos, new Def(tree));
+ build(tree.body);
+ case tree : Ident => buildSym(tree.symbol, tree.pos);
+ case tree : Select =>
+ build(tree.qualifier);
+ buildSym(tree.symbol, selectPos(tree));
+ case tree : GenericApply =>
+ // System.err.println("APPLY: " + tree.fun0 + " " + tree.args0);
+ build(tree.fun0); build(tree.args0);
+ case tree : Typed => build(tree.expr); build(tree.tpt);
+ case tree : Import => build(tree.expr);
+ case tree : Block => build(tree.stats); build(tree.expr);
+ case tree : CaseDef =>
+ build(tree.pat); build(tree.guard); build(tree.body);
+ case tree : Sequence => build(tree.trees);
+ case tree : Assign => build(tree.lhs); build(tree.rhs);
+ case tree : If => build(tree.cond); build(tree.thenp); build(tree.elsep);
+ case tree : Match => build(tree.selector); build(tree.cases);
+ case tree : Return => build(tree.expr);
+ case tree : Literal => ;
+ case tree : This => ;
+ case _ => ;
+ if (tree0 != EmptyTree)
+ System.err.println("BAIL: " + tree0.pos + " " + tree0 + " " + tree0.getClass());
+ }
+ def buildSym(term : Symbol, pos : Int) : Unit = {
+ val term0 = if (term.hasFlag(Flags.ACCESSOR)) term.accessed; else term;
+ val name = NameTransformer.decode(term0.name.toString()).toString().trim();
+ val buf = unit.source.content;
+
+ val cs = name.toChars;
+ var idx = 0;
+ if (cs.length + pos > buf.length) {
+ return;
+ }
+ else while (idx < cs.length)
+ if (buf(pos + idx) != cs(idx)) {
+ // System.err.println("BAD SYM: " + term + " " + term.getClass());
+ return;
+ }
+ else idx = idx + 1;
+
+ list.put(pos, new Use(term0));
+ }
+ def selectPos(tree : Select): Int = if (tree.pos == Position.NOPOS) Position.NOPOS else {
+ val buf = unit.source.content;
+ val pos =
+ if (buf(tree.pos) != '.') tree.pos;
+ else {
+ def f(x : Int) : Int = {
+ if (Character.isWhitespace(buf(x))) f(x + 1);
+ else x;
+ }
+ f(tree.pos + 1);
+ }
+ pos;
+ };
+ class TokenList {
+ object begin extends HasNext {
+ def prev = this;
+ def length = 0;
+ }
+ object end extends HasPrev {
+ def next = this;
+ def length = 0;
+ }
+ // initialize
+ begin.next0 = end;
+ end.prev0 = begin;
+
+ private var length : Int = 0;
+
+ def tokenAt(offset : Int) = if (offset >= length) null else {
+ //System.err.println("CURSOR-0: " + cursor.offset);
+ cursor.seek(offset);
+ //System.err.println("CURSOR-1: " + cursor.offset + " " + cursor.token + " " + offset);
+
+ if (cursor.token.isInstanceOf[Semantic]) cursor.token.asInstanceOf[Semantic];
+ else null;
+ };
+ def put(offset : Int, tok : Semantic) = {
+ grow(offset);
+ if (offset == length) append(tok);
+ else {
+ grow(offset + tok.length);
+ cursor.seek(offset);
+ assert(cursor.token.isInstanceOf[Gap]);
+ val gap = cursor.token.asInstanceOf[Gap];
+ if (!(offset - cursor.offset + tok.length <= gap.length)) {
+ System.err.println("LIST =" + this);
+ System.err.println("OFFSET=" + offset + " " + tok + " " + tok.length);
+ System.err.println(" " + cursor.offset + " " + gap.length);
+ throw new Error();
+ }
+ if (offset == cursor.offset) {
+ // replace or prepend
+ tok.prev0 = gap.prev0;
+ if (tok.length == gap.length) { // replace gap
+ tok.next0 = gap.next0;
+ } else {
+ gap.setLength(gap.length - tok.length);
+ tok.next0 = gap;
+ }
+ tok.next0.prev0 = tok;
+ tok.prev0.next0 = tok;
+ cursor.token = tok;
+ } else {
+ // append
+ val diff = (cursor.offset + gap.length) - (offset + tok.length);
+
+ gap.setLength(gap.length - tok.length - diff);
+ tok.prev0 = gap;
+ tok.next0 = gap.next;
+ tok.next0.prev0 = tok;
+ tok.prev0.next0 = tok;
+ if (diff != 0) {
+ val gap0 = new Gap(tok);
+ gap0.setLength(diff);
+ }
+ }
+ }
+ // System.err.println("PUT: " + this);
+ }
+ override def toString() = {
+ var node = begin.next;
+ var str = "";
+ while (node != end) {
+ str = str + " " + node;
+ node = node.next;
+ }
+ str;
+ };
+ def grow(length0 : Int) = if (length0 > length) {
+ if (false) {
+ System.err.println("GROW: " + length + " -> " + length0);
+ System.err.println(" " + this);
+ }
+
+ assert(length < length0);
+
+ if (end.prev.isInstanceOf[Gap]) {
+ val gap = end.prev.asInstanceOf[Gap];
+ gap.setLength(gap.length + (length0 - length));
+ } else {
+ val gap = new Gap;
+ gap.setLength(length0 - length);
+ gap.prev0 = end.prev;
+ gap.next0 = end;
+ gap.prev0.next0 = gap;
+ end.prev0 = gap;
+ }
+ if (cursor.token == end) {
+ assert(cursor.offset == length);
+ cursor.offset = length0;
+ }
+ length = length0;
+ }
+ def append(tok : Semantic) : Unit = {
+ tok.prev0 = end.prev;
+ tok.next0 = end;
+ tok.prev0.next0 = tok;
+ end.prev0 = tok;
+ length = length + tok.length;
+ if (cursor.token == end) cursor.offset = length;
+ }
+ private object cursor {
+ var token : Token = end;
+ var offset : Int = 0;
+
+ def next : Unit = if (token == end) end else {
+ offset = offset + token.length;
+ token = token.next;
+ }
+ def prev : Unit = if (token.prev == begin) token else {
+ offset = offset - token.prev.length;
+ token = token.prev;
+ }
+ def seek(soffset : Int) : Unit = if (soffset == 0) {
+ token = begin.next;
+ offset = 0;
+ } else if (soffset == length) {
+ token = end;
+ offset = length;
+ } else {
+ assert(soffset > 0);
+ assert(soffset < length);
+ while (offset > soffset) prev;
+ while (offset + token.length <= soffset) next;
+ }
+ def convertToGap = if (token.isInstanceOf[Actual]) {
+ val ret = token.asInstanceOf[Actual].convertToGap;
+ offset = offset - ret._1;
+ token = ret._2;
+ }
+ }
+ // add or delete characters
+ def adjust(offset: Int, /* where */
+ length: Int, /* how many characters are modified */
+ to : Int /* length of new string */) = {
+ cursor.seek(offset);
+ cursor.convertToGap;
+ while (cursor.offset + cursor.token.length < offset + length && cursor.token.next != end) {
+ val save = cursor.offset;
+ cursor.next;
+ cursor.convertToGap;
+ assert(cursor.offset == save);
+ }
+ if (length != to) {
+ val diff = to - length;
+ val gap = cursor.token.asInstanceOf[Gap];
+ gap.setLength(gap.length + diff);
+ };
+ }
+ };
+ }
+}
+
diff --git a/sources/scala/tools/nsc/symtab/Flags.scala b/sources/scala/tools/nsc/symtab/Flags.scala
index 3ea837bab2..92a4e05971 100644
--- a/sources/scala/tools/nsc/symtab/Flags.scala
+++ b/sources/scala/tools/nsc/symtab/Flags.scala
@@ -87,6 +87,7 @@ object Flags {
final val STATICMODULE = lateMODULE;
final val STATICMEMBER = notOVERRIDE;
+
// masks
/** This flags can be set when class or module symbol is first created. */
final val TopLevelCreationFlags =
@@ -170,4 +171,10 @@ object Flags {
case _ => ""
}
}
+ class Flag(mods : int) {
+ def isPrivate = ((mods & PRIVATE ) != 0);
+ def isProtected = ((mods & PROTECTED) != 0);
+ def isVariable = ((mods & MUTABLE) != 0);
+ def isPublic = !isPrivate && !isProtected;
+ }
}
diff --git a/sources/scala/tools/nsc/symtab/Symbols.scala b/sources/scala/tools/nsc/symtab/Symbols.scala
index 2f553b12e8..80b037e068 100755
--- a/sources/scala/tools/nsc/symtab/Symbols.scala
+++ b/sources/scala/tools/nsc/symtab/Symbols.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc.symtab;
import scala.tools.util.AbstractFile;
-import scala.tools.nsc.util.Position;
+import scala.tools.nsc.util.{Position, SourceFile};
import Flags._;
[_trait_] abstract class Symbols: SymbolTable {
@@ -37,6 +37,26 @@ import Flags._;
def pos = rawpos;
def setPos(pos: int): this.type = { this.rawpos = pos; this }
+ def namePos(source : SourceFile) = {
+ val buf = source.content;
+ if (pos == Position.NOPOS) Position.NOPOS;
+ else if (isTypeParameter) pos - name.length;
+ else if (isVariable || isMethod || isClass || isModule) {
+ var ret = pos;
+
+ if (buf(pos) == ',') ret = ret + 1;
+ else if (isClass) ret = ret + ("class").length();
+ else if (isModule) ret = ret + ("object").length();
+ else ret = ret + ("var").length();
+ while (Character.isWhitespace(buf(ret))) ret = ret + 1;
+ ret;
+ }
+ else if (isValue) pos;
+ else -1;
+ }
+
+
+
var attributes: List[AttrInfo] = List();
// Creators -------------------------------------------------------------------
@@ -116,7 +136,11 @@ import Flags._;
def isClass = false; //to be overridden
final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA));
- final def isVariable = isTerm && hasFlag(MUTABLE) && !isMethod;
+ final def isVariable = isTerm && hasFlag(MUTABLE) && !isMethod;
+
+ // XXX: Seems like this is what we really want for variables????
+ final def isVariableX = isTerm && hasFlag(MUTABLE);
+
final def isSetter = isTerm && hasFlag(ACCESSOR) && nme.isSetterName(name);
//todo: make independent of name, as this can be forged.
final def hasGetter = isTerm && nme.isLocalName(name);
diff --git a/sources/scala/tools/nsc/transform/Erasure.scala b/sources/scala/tools/nsc/transform/Erasure.scala
index e637f0bc26..b20aede4d3 100755
--- a/sources/scala/tools/nsc/transform/Erasure.scala
+++ b/sources/scala/tools/nsc/transform/Erasure.scala
@@ -363,7 +363,7 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
sym1 + ":" + tpe1 +
(if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
sym2 + ":" + tpe2 +
- (if (sym2.owner == root) " at line " + Position.line(sym2.pos) else sym2.locationString) +
+ (if (sym2.owner == root) " at line " + Position.line(unit.source, sym2.pos) else sym2.locationString) +
"\nhave same type" +
(if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
}
diff --git a/sources/scala/tools/nsc/typechecker/Typers.scala b/sources/scala/tools/nsc/typechecker/Typers.scala
index 829ff3a0d9..97a56f75f4 100755
--- a/sources/scala/tools/nsc/typechecker/Typers.scala
+++ b/sources/scala/tools/nsc/typechecker/Typers.scala
@@ -309,7 +309,7 @@ import collection.mutable.HashMap;
val tparams1 = cloneSymbols(tparams);
val tree1 = if (tree.isType) tree
else TypeApply(tree, tparams1 map (tparam =>
- TypeTree() setPos tree.pos setType tparam.tpe)) setPos tree.pos;
+ TypeTree(tparam.tpe) setPos tree.pos)) setPos tree.pos;
context.undetparams = context.undetparams ::: tparams1;
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt)
case mt: ImplicitMethodType if ((mode & (EXPRmode | FUNmode)) == EXPRmode) => // (4.1)
@@ -336,9 +336,9 @@ import collection.mutable.HashMap;
} else {
clazz.initialize;
if (clazz.hasFlag(CASE)) { // (5.1)
- val tree1 = TypeTree() setPos tree.pos
- setType
- clazz.primaryConstructor.tpe.asSeenFrom(tree.tpe.prefix, clazz.owner);
+ val tree1 = TypeTree(clazz.primaryConstructor.tpe.asSeenFrom(tree.tpe.prefix, clazz.owner)) setOriginal(tree);
+
+
// tree.tpe.prefix.memberType(clazz.primaryConstructor); //!!!
inferConstructorInstance(tree1, clazz.unsafeTypeParams, pt);
tree1
@@ -362,7 +362,7 @@ import collection.mutable.HashMap;
errorTree(tree, "" + clazz + " takes type parameters");
} else tree match { // (6)
case TypeTree() => tree
- case _ => TypeTree() setPos tree.pos setType tree.tpe
+ case _ => TypeTree(tree.tpe) setOriginal(tree)
}
} else if ((mode & (EXPRmode | FUNmode)) == (EXPRmode | FUNmode) &&
((mode & TAPPmode) == 0 || tree.tpe.typeParams.isEmpty) &&
@@ -513,8 +513,12 @@ import collection.mutable.HashMap;
val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope()))
.typedTemplate(cdef.impl, parentTypes(cdef.impl));
val impl2 = addSyntheticMethods(impl1, clazz);
- copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl2)
- setType NoType
+ val ret = copy.ClassDef(cdef, cdef.mods, cdef.name, tparams1, tpt1, impl2)
+ setType NoType;
+ //for (val p <- impl2.parents)
+ // System.err.println("AFTER: " + p + " " + p.pos);
+ // Thread.dumpStack();
+ ret;
}
def typedModuleDef(mdef: ModuleDef): Tree = {
@@ -1338,7 +1342,7 @@ import collection.mutable.HashMap;
val argtypes = args1 map (.tpe);
val owntype = if (tpt1.symbol.isClass) appliedType(tpt1.tpe, argtypes)
else tpt1.tpe.subst(tparams, argtypes);
- TypeTree() setPos tree.pos setType owntype
+ TypeTree(owntype) setOriginal(tree) // setPos tree.pos
} else if (tparams.length == 0) {
errorTree(tree, "" + tpt1.tpe + " does not take type parameters")
} else {
diff --git a/sources/scala/tools/nsc/util/CharArrayReader.scala b/sources/scala/tools/nsc/util/CharArrayReader.scala
index 31cc77ce0b..0ebfd2bd3e 100644
--- a/sources/scala/tools/nsc/util/CharArrayReader.scala
+++ b/sources/scala/tools/nsc/util/CharArrayReader.scala
@@ -7,11 +7,11 @@ 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,
+class CharArrayReader(buf: Array[char], start: int, /* startline: int, startcol: int, */
decodeUni: boolean, error: String => unit) {
def this(buf: Array[char], decodeUni: boolean, error: String => unit) =
- this(buf, 0, 1, 1, decodeUni, error);
+ this(buf, 0, /* 1, 1, */ decodeUni, error);
/** layout constant
*/
@@ -21,36 +21,36 @@ class CharArrayReader(buf: Array[char], start: int, startline: int, startcol: in
*/
var ch: char = _;
var bp = start;
- private var cline: int = _;
- private var ccol: int = _;
+ //private var cline: int = _;
+ //private var ccol: int = _;
def cpos = bp;
var isUnicode: boolean = _;
- private var nextline = startline;
- private var nextcol = startcol;
+ //private var nextline = startline;
+ //private var nextcol = startcol;
def hasNext: boolean = bp < buf.length;
def last: char = if(bp > start + 2) buf(bp - 2) else ' '; // XML literals
def next: unit = {
- cline = nextline;
- ccol = nextcol;
+ //cline = nextline;
+ //ccol = nextcol;
ch = buf(bp);
isUnicode = false;
bp = bp + 1;
ch match {
case '\t' =>
- nextcol = ((nextcol - 1) / tabinc * tabinc) + tabinc + 1;
+ // nextcol = ((nextcol - 1) / tabinc * tabinc) + tabinc + 1;
case CR =>
- nextline = nextline + 1;
- nextcol = 1;
+ //nextline = nextline + 1;
+ // nextcol = 1;
if (buf(bp) == LF) {
ch = LF;
bp = bp + 1
}
case LF | FF =>
- nextline = nextline + 1;
- nextcol = 1
+ //nextline = nextline + 1;
+ //nextcol = 1
case '\\' =>
def evenSlashPrefix: boolean = {
var p = bp - 2;
@@ -59,26 +59,26 @@ class CharArrayReader(buf: Array[char], start: int, startline: int, startcol: in
}
def udigit: int = {
val d = digit2int(buf(bp), 16);
- if (d >= 0) { bp = bp + 1; nextcol = nextcol + 1 }
+ if (d >= 0) { bp = bp + 1; /* nextcol = nextcol + 1 */ }
else error("error in unicode escape");
d
}
- nextcol = nextcol + 1;
+ // nextcol = nextcol + 1;
if (buf(bp) == 'u' && decodeUni && evenSlashPrefix) {
do {
- bp = bp + 1; nextcol = nextcol + 1;
+ bp = bp + 1; // nextcol = nextcol + 1;
} while (buf(bp) == 'u');
val code = udigit << 12 | udigit << 8 | udigit << 4 | udigit;
ch = code.asInstanceOf[char];
isUnicode = true
}
case _ =>
- nextcol = nextcol + 1
+ // nextcol = nextcol + 1
}
}
def copy: CharArrayReader =
- new CharArrayReader(buf, bp, nextcol, nextline, decodeUni, error);
+ new CharArrayReader(buf, bp, /* nextcol, nextline, */ decodeUni, error);
def digit2int(ch: char, base: int): int = {
if ('0' <= ch && ch <= '9' && ch < '0' + base)
diff --git a/sources/scala/tools/nsc/util/Position.scala b/sources/scala/tools/nsc/util/Position.scala
index 9a2072bbc8..f6bd6b2788 100755
--- a/sources/scala/tools/nsc/util/Position.scala
+++ b/sources/scala/tools/nsc/util/Position.scala
@@ -20,15 +20,15 @@ object Position {
def line(offset : Int) = offset;
+
+ def line(source : SourceFile, offset : Int) = (new Position(source, offset)).line;
}
-class Position(_source : SourceFile,_offset: Int) {
+class Position( val source : SourceFile, val offset: Int) {
import Position._;
- val offset = _offset;
- val source = _source;
- val tabInc = 8;
+ private val tabInc = 8;
def this(sourceName : String) = this(new SourceFile(sourceName, new Array[Char](0)), Position.NOPOS);
def this(sourceName : String, _offset : Int) = this(new SourceFile(sourceName, new Array[Char](0)), _offset);
diff --git a/sources/scala/tools/nsc/util/SourceFile.scala b/sources/scala/tools/nsc/util/SourceFile.scala
index ac6f2baf8c..0138f6a48c 100644
--- a/sources/scala/tools/nsc/util/SourceFile.scala
+++ b/sources/scala/tools/nsc/util/SourceFile.scala
@@ -38,7 +38,9 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) {
def this(sourceName: String, content : Array[Char]) =
this(new CharArrayFile(sourceName, content), content);
- def isLineBreak(idx : Int) = SourceFile.isLineBreak(content(idx));
+ def isLineBreak(idx : Int) = if (!SourceFile.isLineBreak(content(idx))) false;
+ else if (content(idx) == CR && idx + 1 < content.length && content(idx + 1) == LF) false;
+ else true;
def position(offset : Int) = new Position(this, offset);
@@ -54,43 +56,57 @@ class SourceFile(_file : AbstractFile, _content : Array[Char]) {
var index = 0;
var offset = 0;
- private def reset: Unit = {
- index = 0; offset = 0;
- }
-
def find(toFind : Int, isIndex : Boolean) : Int = {
+ if (toFind == 0) return 0;
+
if (!isIndex) assert(toFind != Position.NOPOS);
if ( isIndex) assert(toFind > Position.NOLINE - Position.FIRSTLINE);
if (!isIndex && (toFind >= content.length)) throw new Error(toFind + " not valid offset in " + file.getName() + ":" + content.length);
- if ( isIndex && toFind < index) reset;
- if (!isIndex && toFind < offset) reset;
- try {
- var seek = 0;
- var continue = true;
- while (continue) {
- if (false) {;}
- else if ( isIndex && seek == 0 && toFind == index ) continue = false;
- else if (!isIndex && toFind == offset + seek ) continue = false;
- else if (!isIndex && (toFind < (offset + seek))) throw new Error("HOW??? toFind=" + toFind + " offset=" + offset + " seek=" + seek);
- else if (isLineBreak(offset + seek)) {
- index = index + 1;
- offset = offset + seek + 1;
- seek = 0;
- } else seek = seek + 1;
+ def get(isIndex : Boolean) = if (isIndex) index else offset;
+
+ val isBackward = toFind <= get(isIndex);
+ 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);
+ offset = offset + increment;
+ if (!isBackward) assert(offset < content.length);
+
+ if (isLineBreak(offset + (if (isBackward) 0 else -1))) {
+ index = index + increment;
+ if (isIndex && index + oneIfBackward == toFind)
+ return offset + oneIfBackward;
}
- if (isIndex) offset else index;
- } catch {
- case ex: ArrayIndexOutOfBoundsException =>
- System.err.println("XXX: toFind=" + toFind + " isIndex=" + isIndex + " length=" + content.length);
- throw ex;
}
+ throw new Error();
}
}
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 = idx + 1;
+ }
+ return true;
+ }
+ def path = getFile().getPath();
+
+ def skipWhitespace(offset : Int): Int =
+ if (Character.isWhitespace(content(offset))) skipWhitespace(offset + 1) else offset;
+
+
def lineToString(index : Int) = {
var offset = lineToOffset(index);
val buf = new StringBuffer();