From f30c0b0dba3889de9a9603761aec8a60a871fc85 Mon Sep 17 00:00:00 2001 From: Miles Sabin Date: Thu, 1 Oct 2009 15:20:56 +0000 Subject: 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. --- .../scala/tools/nsc/ast/parser/Parsers.scala | 107 +++++++++++---------- 1 file changed, 57 insertions(+), 50 deletions(-) (limited to 'src/compiler/scala/tools/nsc/ast/parser/Parsers.scala') 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() } -- cgit v1.2.3