summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
diff options
context:
space:
mode:
authorMiles Sabin <miles@milessabin.com>2009-10-01 15:20:56 +0000
committerMiles Sabin <miles@milessabin.com>2009-10-01 15:20:56 +0000
commitf30c0b0dba3889de9a9603761aec8a60a871fc85 (patch)
tree180ba59ecb3057a21eb878be6f5e247f38c2d1c3 /src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
parentdbf87324a09e84755cc5ff8827f46c59b8a6e4ca (diff)
downloadscala-f30c0b0dba3889de9a9603761aec8a60a871fc85.tar.gz
scala-f30c0b0dba3889de9a9603761aec8a60a871fc85.tar.bz2
scala-f30c0b0dba3889de9a9603761aec8a60a871fc85.zip
Fix and tests for positions issues with context...
Fix and tests for positions issues with context/view bounds and multiple definitions; extended the ranges for defns/decls to cover their introducing keywords; removed an unused IDE hook; some whitespace cleanup.
Diffstat (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala')
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala107
1 files changed, 57 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 4b051ef08a..1e118e38cc 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1952,39 +1952,38 @@ self =>
* | def FunDcl
* | type [nl] TypeDcl
*/
- def defOrDcl(mods: Modifiers): List[Tree] = {
+ def defOrDcl(pos: Int, mods: Modifiers): List[Tree] = {
if ((mods hasFlag Flags.LAZY) && in.token != VAL)
syntaxError("lazy not allowed here. Only vals can be lazy", false)
in.token match {
case VAL =>
- patDefOrDcl(mods)
+ patDefOrDcl(pos, mods)
case VAR =>
- patDefOrDcl(mods | Flags.MUTABLE)
+ patDefOrDcl(pos, mods | Flags.MUTABLE)
case DEF =>
- List(funDefOrDcl(mods))
+ List(funDefOrDcl(pos, mods))
case TYPE =>
- List(typeDefOrDcl(mods))
+ List(typeDefOrDcl(pos, mods))
case _ =>
- List(tmplDef(mods))
+ List(tmplDef(pos, mods))
}
}
- /** IDE hook: for non-local defs or dcls with modifiers and annotations */
+
def nonLocalDefOrDcl : List[Tree] = {
val annots = annotations(true, false)
- defOrDcl(modifiers() withAnnotations annots)
- }
- /** not hooked by the IDE, will not undergo stubbing. Used for early initialization blocks. */
- def preNonLocalDefOrDcl : List[Tree] = {
- val annots = annotations(true, false)
- defOrDcl(modifiers() withAnnotations annots)
+ val pos =
+ if (in.token == CASECLASS || in.token == CASEOBJECT)
+ in.prev.offset
+ else
+ in.offset
+ defOrDcl(pos, modifiers() withAnnotations annots)
}
-
/** PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
* ValDcl ::= Id {`,' Id} `:' Type
* VarDef ::= PatDef | Id {`,' Id} `:' Type `=' `_'
*/
- def patDefOrDcl(mods: Modifiers): List[Tree] = {
+ def patDefOrDcl(pos : Int, mods: Modifiers): List[Tree] = {
var newmods = mods
val lhsBuf = new ListBuffer[Tree]
do {
@@ -2025,7 +2024,11 @@ self =>
}
trees
}
- (lhs.toList.init flatMap (mkDefs(_, tp.duplicate, rhs.duplicate))) ::: mkDefs(lhs.last, tp, rhs)
+ val trees = (lhs.toList.init flatMap (mkDefs(_, tp.duplicate, rhs.duplicate))) ::: mkDefs(lhs.last, tp, rhs)
+ val hd = trees.head
+ hd setPos hd.pos.withStart(pos)
+ ensureNonOverlapping(hd, trees.tail)
+ trees
}
/** VarDef ::= PatDef
@@ -2060,8 +2063,8 @@ self =>
* FunDcl ::= FunSig [`:' Type]
* FunSig ::= id [FunTypeParamClause] ParamClauses
*/
- def funDefOrDcl(mods: Modifiers): Tree = {
- val start = in.skipToken()
+ def funDefOrDcl(start : Int, mods: Modifiers): Tree = {
+ in.nextToken
if (in.token == THIS) {
atPos(start, in.skipToken()) {
val vparamss = paramClauses(nme.CONSTRUCTOR, classContextBounds map (_.duplicate), false)
@@ -2139,8 +2142,8 @@ self =>
/** TypeDef ::= type Id [TypeParamClause] `=' Type
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
*/
- def typeDefOrDcl(mods: Modifiers): Tree = {
- val start = in.skipToken()
+ def typeDefOrDcl(start: Int, mods: Modifiers): Tree = {
+ in.nextToken
newLinesOpt()
atPos(start, in.offset) {
val name = ident().toTypeName
@@ -2162,27 +2165,28 @@ self =>
/** Hook for IDE, for top-level classes/objects */
def topLevelTmplDef: Tree = {
val annots = annotations(true, false)
+ val pos = in.offset
val mods = modifiers() withAnnotations annots
- tmplDef(mods)
+ tmplDef(pos, mods)
}
/** TmplDef ::= [case] class ClassDef
* | [case] object ObjectDef
* | [override] trait TraitDef
*/
- def tmplDef(mods: Modifiers): Tree = {
+ def tmplDef(pos: Int, mods: Modifiers): Tree = {
if (mods.hasFlag(Flags.LAZY)) syntaxError("classes cannot be lazy", false)
in.token match {
case TRAIT =>
- classDef(mods | Flags.TRAIT | Flags.ABSTRACT)
+ classDef(pos, mods | Flags.TRAIT | Flags.ABSTRACT)
case CLASS =>
- classDef(mods)
+ classDef(pos, mods)
case CASECLASS =>
- classDef(mods | Flags.CASE)
+ classDef(pos, mods | Flags.CASE)
case OBJECT =>
- objectDef(mods)
+ objectDef(pos, mods)
case CASEOBJECT =>
- objectDef(mods | Flags.CASE)
+ objectDef(pos, mods | Flags.CASE)
case _ =>
syntaxErrorOrIncomplete("expected start of definition", true)
EmptyTree
@@ -2193,8 +2197,8 @@ self =>
[AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplateOpt
* TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt
*/
- def classDef(mods: Modifiers): ClassDef = {
- val start = in.skipToken()
+ def classDef(start: Int, mods: Modifiers): ClassDef = {
+ in.nextToken
val nameOffset = in.offset
val name = ident().toTypeName
atPos(start, if (name == nme.ERROR.toTypeName) start else nameOffset) {
@@ -2220,6 +2224,10 @@ self =>
val template = templateOpt(mods1, name, constrMods withAnnotations constrAnnots, vparamss, tstart)
if (isInterface(mods1, template.body)) mods1 |= Flags.INTERFACE
val result = ClassDef(mods1, name, tparams, template)
+ // Context bounds generate implicit parameters (part of the template) with types
+ // from tparams: we need to ensure these don't overlap
+ if (!classContextBounds.isEmpty)
+ ensureNonOverlapping(template, tparams)
classContextBounds = savedContextBounds
result
}
@@ -2227,8 +2235,8 @@ self =>
/** ObjectDef ::= Id ClassTemplateOpt
*/
- def objectDef(mods: Modifiers): ModuleDef = {
- val start = in.skipToken()
+ def objectDef(start: Int, mods: Modifiers): ModuleDef = {
+ in.nextToken
val nameOffset = in.offset
val name = ident()
val tstart = in.offset
@@ -2304,9 +2312,9 @@ self =>
in.nextToken()
template(mods hasFlag Flags.TRAIT)
} else if ((in.token == SUBTYPE) && (mods hasFlag Flags.TRAIT)) {
- in.nextToken()
+ in.nextToken()
template(true)
- } else {
+ } else {
newLineOptWhenFollowedBy(LBRACE)
val (self, body) = templateBodyOpt(false)
(List(), List(List()), self, body)
@@ -2406,9 +2414,9 @@ self =>
while (in.token != RBRACE && in.token != EOF) {
if (in.token == PACKAGE) {
val start = in.skipToken()
- stats += {
- if (in.token == OBJECT) makePackageObject(start, objectDef(NoMods))
- else packaging(start)
+ stats += {
+ if (in.token == OBJECT) makePackageObject(start, objectDef(in.offset, NoMods))
+ else packaging(start)
}
} else if (in.token == IMPORT) {
stats ++= importClause()
@@ -2467,9 +2475,7 @@ self =>
} else if (isExprIntro) {
stats += statement(InTemplate)
} else if (isDefIntro || isModifier || in.token == LBRACKET /*todo: remove */ || in.token == AT) {
- if (isPre) // @S: avoid caching by calling a different method that does the same thing (except in the IDE)
- stats ++= joinComment(preNonLocalDefOrDcl)
- else stats ++= joinComment(nonLocalDefOrDcl)
+ stats ++= joinComment(nonLocalDefOrDcl)
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of definition", true)
}
@@ -2489,7 +2495,7 @@ self =>
val stats = new ListBuffer[Tree]
while (in.token != RBRACE && in.token != EOF) {
if (isDclIntro) { // don't IDE hook
- stats ++= joinComment(defOrDcl(NoMods))
+ stats ++= joinComment(defOrDcl(in.offset, NoMods))
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of declaration", true)
}
@@ -2514,9 +2520,10 @@ self =>
def localDef : List[Tree] = {
val annots = annotations(true, false)
+ val pos = in.offset
val mods = localModifiers() withAnnotations annots
- if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(mods)
- else List(tmplDef(mods))
+ if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(pos, mods)
+ else List(tmplDef(pos, mods))
}
/** BlockStatSeq ::= { BlockStat semi } [ResultExpr]
@@ -2558,13 +2565,13 @@ self =>
val start = in.offset
if (in.token == PACKAGE) {
in.nextToken()
- if (in.token == OBJECT) {
- ts += makePackageObject(start, objectDef(NoMods))
- if (in.token != EOF) {
- acceptStatSep()
- ts ++= topStatSeq()
- }
- } else {
+ if (in.token == OBJECT) {
+ ts += makePackageObject(start, objectDef(in.offset, NoMods))
+ if (in.token != EOF) {
+ acceptStatSep()
+ ts ++= topStatSeq()
+ }
+ } else {
val pkg = qualId()
newLineOptWhenFollowedBy(LBRACE)
if (in.token == EOF) {
@@ -2578,7 +2585,7 @@ self =>
accept(RBRACE)
ts ++= topStatSeq()
}
- }
+ }
} else {
ts ++= topStatSeq()
}