summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala3
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala7
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala14
-rw-r--r--src/compiler/scala/tools/nsc/Properties.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala9
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala19
-rwxr-xr-xsrc/compiler/scala/tools/nsc/javac/JavaParsers.scala817
-rwxr-xr-xsrc/compiler/scala/tools/nsc/javac/JavaScanners.scala978
-rwxr-xr-xsrc/compiler/scala/tools/nsc/javac/JavaTokens.scala157
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala16
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala20
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala35
-rw-r--r--src/compiler/scala/tools/nsc/util/CharArrayReader.scala7
-rw-r--r--src/partest/scala/tools/partest/PartestTask.scala2
-rwxr-xr-xsrc/swing/scala/swing/test/ButtonApp.scala18
-rw-r--r--test/files/jvm5/annotations.scala14
-rw-r--r--test/files/jvm5/throws-annot.scala2
-rw-r--r--test/files/neg/t0606.check4
-rw-r--r--test/files/neg/t0606.scala6
23 files changed, 2106 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 2d2b849c90..48026e3b4a 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -69,6 +69,9 @@ trait CompilationUnits { self: Global =>
reporter.incompleteInputError((pos), msg)
}
+ /** Is this about a .java source file? */
+ def isJava = source.file.name.endsWith(".java")
+
override def toString() = source.toString()
def clear() = {
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index e005e0208e..9ad0bb2539 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -20,7 +20,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings,
val cmdName = "scalac"
/** The file extension of files that the compiler can process */
- def fileEnding = Properties.fileEndingString //todo: lazy val
+ lazy val fileEnding = Properties.fileEndingString
private val helpSyntaxColumnWidth: Int =
Iterable.max(settings.allSettings map (_.helpSyntax.length))
@@ -92,10 +92,11 @@ class CompilerCommand(arguments: List[String], val settings: Settings,
ok = false
}
}
- } else if ((settings.script.value != "") || args.head.endsWith(fileEnding)) {
+ } else if ((settings.script.value != "") ||
+ (fileEnding.split("\\|") exists (args.head.endsWith(_)))) {
fs = args.head :: fs
args = args.tail
- } else if (args.head.length == 0) {//quick fix
+ } else if (args.head.length == 0) {//quick fix [martin: for what?]
args = args.tail
} else {
error("don't know what to do with " + args.head)
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index cc75234b6a..454be7a667 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -249,12 +249,17 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
private val isFlat = prev.name == "flatten" || prev.flatClasses
override def flatClasses: Boolean = isFlat
+ /** Is current phase cancelled on this unit? */
+ def cancelled(unit: CompilationUnit) =
+ reporter.cancelled ||
+ unit.isJava && this.id > currentRun.namerPhase.id
+
final def applyPhase(unit: CompilationUnit) {
if (settings.debug.value) inform("[running phase " + name + " on " + unit + "]")
val unit0 = currentRun.currentUnit
currentRun.currentUnit = unit
reporter.setSource(unit.source)
- if (!reporter.cancelled) apply(unit)
+ if (!cancelled(unit)) apply(unit)
currentRun.advanceUnit
assert(currentRun.currentUnit == unit)
currentRun.currentUnit = unit0
@@ -489,9 +494,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
unitc += 1
refreshProgress
}
- private def refreshProgress = if (fileset.size > 0)
- progress((phasec * fileset.size) + unitc,
- (phaseDescriptors.length+1) * fileset.size)
+ private def refreshProgress =
+ if (fileset.size > 0)
+ progress((phasec * fileset.size) + unitc,
+ (phaseDescriptors.length+1) * fileset.size)
def phaseNamed(name: String): Phase = {
var p: Phase = firstPhase
diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala
index cc7f588789..f2ea31ed5d 100644
--- a/src/compiler/scala/tools/nsc/Properties.scala
+++ b/src/compiler/scala/tools/nsc/Properties.scala
@@ -45,7 +45,7 @@ object Properties {
}
val fileEndingString: String = {
- val defaultString = ".scala"
+ val defaultString = ".scala|.java"
props.getProperty("file.ending", defaultString)
}
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 3e177397bd..ab9804d613 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -150,7 +150,7 @@ class Settings(error: String => Unit) {
val Xcasetags = ChoiceSetting("-Ycasetags", "test integer tags for case classes", List("on","off"),
/*default*/"off")
-
+ val XnoVarargsConversion = BooleanSetting("-Xno-varargs-conversion", "disable varags conversion")
val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations")
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 970aa33a9a..2f699146cd 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -413,10 +413,10 @@ trait Trees {
case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree)
extends ValOrDefDef {
- assert(tpt.isType)
+ assert(tpt.isType, tpt)
//assert(kindingIrrelevant(tpt.tpe) || !tpt.tpe.isHigherKinded, tpt.tpe) //@M a method definition should never be typed with a higher-kinded type (values must be classified by types with kind *)
//tpt.kindStar=true //@M turn on consistency checking in Tree
- assert(rhs.isTerm)
+ assert(rhs.isTerm, rhs)
}
def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef =
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index baa7eabaef..577ca3c451 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -6,9 +6,11 @@
package scala.tools.nsc.ast.parser
+import javac._
+
/** An nsc sub-component.
*/
-abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParsers with NewScanners {
+abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParsers with NewScanners with JavaParsers with JavaScanners {
val phaseName = "parser"
@@ -17,8 +19,9 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse
class ParserPhase(prev: scala.tools.nsc.Phase) extends StdPhase(prev) {
def apply(unit: global.CompilationUnit) {
global.informProgress("parsing " + unit)
- val parser = new UnitParser(unit)
- unit.body = parser.parse()
+ unit.body =
+ if (unit.source.file.name.endsWith(".java")) new JavaUnitParser(unit).parse()
+ else new UnitParser(unit).parse()
}
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 280246a6bd..82631a5c2d 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -131,9 +131,10 @@ abstract class GenJVM extends SubComponent {
addScalaAttr(if (isTopLevelModule(sym)) sym.sourceModule else sym);
addInnerClasses
- val outfile = new DataOutputStream(getFile(jclass, ".class"))
- jclass.writeTo(outfile)
- outfile.close()
+ val outfile = getFile(jclass, ".class")
+ val outstream = new DataOutputStream(outfile.output)
+ jclass.writeTo(outstream)
+ outstream.close()
informProgress("wrote " + outfile)
}
@@ -280,9 +281,10 @@ abstract class GenJVM extends SubComponent {
jcode.emitRETURN()
// write the bean information class file.
- val outfile = new DataOutputStream(getFile(beanInfoClass, ".class"))
- beanInfoClass.writeTo(outfile)
- outfile.close()
+ val outfile = getFile(beanInfoClass, ".class")
+ val outstream = new DataOutputStream(outfile.output)
+ beanInfoClass.writeTo(outstream)
+ outstream.close()
informProgress("wrote BeanInfo " + outfile)
}
@@ -1520,14 +1522,13 @@ abstract class GenJVM extends SubComponent {
res
}
- def getFile(cls: JClass, suffix: String): OutputStream = {
+ def getFile(cls: JClass, suffix: String): AbstractFile = {
var dir: AbstractFile = outputDir
val pathParts = cls.getName().split("[./]").toList
for (part <- pathParts.init) {
dir = dir.subdirectoryNamed(part)
}
- val file = dir.fileNamed(pathParts.last + suffix)
- file.output
+ dir.fileNamed(pathParts.last + suffix)
}
/** Emit a Local variable table for debugging purposes.
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
new file mode 100755
index 0000000000..9d43b368df
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -0,0 +1,817 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2007 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: Parsers.scala 15004 2008-05-13 16:37:33Z odersky $
+//todo: allow infix type patterns
+
+
+package scala.tools.nsc.javac
+
+import scala.tools.nsc.util.{Position, OffsetPosition, NoPosition, BatchSourceFile}
+import scala.collection.mutable.ListBuffer
+import symtab.Flags
+import JavaTokens._
+
+trait JavaParsers extends JavaScanners {
+ val global : Global
+ import global._
+ import posAssigner.atPos
+ import definitions._
+
+ case class JavaOpInfo(operand: Tree, operator: Name, pos: Int)
+
+ class JavaUnitParser(val unit: global.CompilationUnit) extends JavaParser {
+ val in = new JavaUnitScanner(unit)
+ def freshName(pos : Position, prefix : String) = unit.fresh.newName(pos, prefix)
+ implicit def i2p(offset : Int) : Position = new OffsetPosition(unit.source,offset)
+ def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg)
+ def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg)
+ }
+
+ abstract class JavaParser {
+
+ val in: JavaScanner
+ protected def posToReport: Int = in.currentPos
+ protected def freshName(pos : Position, prefix : String): Name
+ protected implicit def i2p(offset : Int) : Position
+ private implicit def p2i(pos : Position) = pos.offset.getOrElse(-1)
+
+ /** The simple name of the package of the currently parsed file */
+ private var thisPackageName: Name = nme.EMPTY
+
+ /** this is the general parse method
+ */
+ def parse(): Tree = {
+ val t = compilationUnit()
+ accept(EOF)
+ t
+ }
+
+ // -------- error handling ---------------------------------------
+
+ private var lastErrorPos : Int = -1
+
+ protected def skip() {
+ var nparens = 0
+ var nbraces = 0
+ while (true) {
+ in.token match {
+ case EOF =>
+ return
+ case SEMI =>
+ if (nparens == 0 && nbraces == 0) return
+ case RPAREN =>
+ nparens -= 1
+ case RBRACE =>
+ if (nbraces == 0) return
+ nbraces -= 1
+ case LPAREN =>
+ nparens += 1
+ case LBRACE =>
+ nbraces += 1
+ case _ =>
+ }
+ in.nextToken
+ }
+ }
+
+ def warning(pos : Int, msg : String) : Unit
+ def syntaxError(pos: Int, msg: String) : Unit
+ def syntaxError(msg: String, skipIt: Boolean) {
+ syntaxError(in.currentPos, msg, skipIt)
+ }
+
+ def syntaxError(pos: Int, msg: String, skipIt: Boolean) {
+ if (pos > lastErrorPos) {
+ syntaxError(pos, msg)
+ // no more errors on this token.
+ lastErrorPos = in.currentPos
+ }
+ if (skipIt)
+ skip()
+ }
+ def warning(msg: String) : Unit = warning(in.currentPos, msg)
+
+ def errorTypeTree = TypeTree().setType(ErrorType).setPos((in.currentPos))
+ def errorTermTree = Literal(Constant(null)).setPos((in.currentPos))
+ def errorPatternTree = blankExpr.setPos((in.currentPos))
+
+ // --------- tree building -----------------------------
+
+ def scalaDot(name: Name): Tree =
+ Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
+
+ def javaLangDot(name: Name): Tree =
+ Select(
+ Select(
+ Select(Ident(nme.ROOTPKG), nme.java),
+ nme.lang),
+ name)
+
+ def javaLangObject(): Tree = javaLangDot(nme.Object.toTypeName)
+
+ def arrayOf(tpt: Tree) =
+ AppliedTypeTree(scalaDot(nme.Array.toTypeName), List(tpt))
+
+ def blankExpr = Ident(nme.WILDCARD)
+
+ def makePackaging(pkg: Tree, stats: List[Tree]): PackageDef = pkg match {
+ case Ident(name) =>
+ PackageDef(name, stats).setPos(pkg.pos)
+ case Select(qual, name) =>
+ makePackaging(qual, List(PackageDef(name, stats).setPos(pkg.pos)))
+ }
+
+ def makeTemplate(parents: List[Tree], stats: List[Tree]) =
+ Template(
+ parents,
+ emptyValDef,
+ if (treeInfo.firstConstructor(stats) == EmptyTree) makeConstructor(List()) :: stats
+ else stats)
+
+ def makeParam(name: Name, tpt: Tree) =
+ ValDef(Modifiers(Flags.JAVA | Flags.PARAM), name, tpt, EmptyTree)
+
+ def makeConstructor(formals: List[Tree]) = {
+ var count = 0
+ val vparams =
+ for (formal <- formals)
+ yield {
+ count += 1
+ makeParam(newTermName("x$"+count), formal)
+ }
+ DefDef(Modifiers(Flags.JAVA), nme.CONSTRUCTOR, List(), List(vparams), TypeTree(), blankExpr)
+ }
+
+ // ------------- general parsing ---------------------------
+
+ /** skip parent or brace enclosed sequence of things */
+ def skipAhead() {
+ var nparens = 0
+ var nbraces = 0
+ do {
+ in.token match {
+ case LPAREN =>
+ nparens += 1
+ case LBRACE =>
+ nbraces += 1
+ case _ =>
+ }
+ in.nextToken
+ in.token match {
+ case RPAREN =>
+ nparens -= 1
+ case RBRACE =>
+ nbraces -= 1
+ case _ =>
+ }
+ } while (in.token != EOF && (nparens > 0 || nbraces > 0))
+ println("Skipped: "+in)
+ }
+
+ def skipTo(tokens: Int*) {
+ while (!(tokens contains in.token) && in.token != EOF) {
+ if (in.token == LBRACE) { skipAhead(); accept(RBRACE) }
+ else if (in.token == LPAREN) { skipAhead(); accept(RPAREN) }
+ else in.nextToken
+ }
+ }
+
+ /** Consume one token of the specified type, or
+ * signal an error if it is not there.
+ */
+ def accept(token: Int): Int = {
+ val pos = in.currentPos
+ if (in.token != token) {
+ val posToReport =
+ //if (in.currentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0))
+ // in.lastPos
+ //else
+ in.currentPos
+ val msg =
+ JavaScannerConfiguration.token2string(token) + " expected but " +
+ JavaScannerConfiguration.token2string(in.token) + " found."
+
+ syntaxError(posToReport, msg, true)
+ }
+ if (in.token == token) in.nextToken
+ pos
+ }
+
+ def acceptClosingAngle() {
+ if (in.token == GTGTGTEQ) in.token = GTGTEQ
+ else if (in.token == GTGTGT) in.token = GTGT
+ else if (in.token == GTGTEQ) in.token = GTEQ
+ else if (in.token == GTGT) in.token = GT
+ else if (in.token == GTEQ) in.token = ASSIGN
+ else accept(GT)
+ }
+
+ def ident(): Name =
+ if (in.token == IDENTIFIER) {
+ val name = in.name
+ in.nextToken
+ name
+ } else {
+ accept(IDENTIFIER)
+ nme.ERROR
+ }
+
+ def repsep[T <: Tree](p: () => T, sep: Int): List[T] = {
+ val buf = new ListBuffer[T] + p()
+ while (in.token == sep) {
+ in.nextToken
+ buf += p()
+ }
+ buf.toList
+ }
+
+ /** Convert (qual)ident to type identifier
+ */
+ def convertToTypeId(tree: Tree): Tree = tree match {
+ case Ident(name) =>
+ Ident(name.toTypeName).setPos(tree.pos)
+ case Select(qual, name) =>
+ Select(qual, name.toTypeName).setPos(tree.pos)
+ case _ =>
+ syntaxError(tree.pos, "identifier expected", false)
+ errorTypeTree
+ }
+
+ // -------------------- specific parsing routines ------------------
+
+ def qualId(): Tree = {
+ var t: Tree = atPos(in.currentPos) { Ident(ident()) }
+ while (in.token == DOT) {
+ in.nextToken
+ t = atPos(in.currentPos) { Select(t, ident()) }
+ }
+ t
+ }
+
+ def optArrayBrackets(tpt: Tree): Tree =
+ if (in.token == LBRACKET) {
+ val tpt1 = atPos(in.pos) { arrayOf(tpt) }
+ in.nextToken
+ accept(RBRACKET)
+ optArrayBrackets(tpt1)
+ } else tpt
+
+ def basicType(): Tree =
+ atPos(in.pos) {
+ in.token match {
+ case BYTE => in.nextToken; TypeTree(ByteClass.tpe)
+ case SHORT => in.nextToken; TypeTree(ShortClass.tpe)
+ case CHAR => in.nextToken; TypeTree(CharClass.tpe)
+ case INT => in.nextToken; TypeTree(IntClass.tpe)
+ case LONG => in.nextToken; TypeTree(LongClass.tpe)
+ case FLOAT => in.nextToken; TypeTree(FloatClass.tpe)
+ case DOUBLE => in.nextToken; TypeTree(DoubleClass.tpe)
+ case BOOLEAN => in.nextToken; TypeTree(BooleanClass.tpe)
+ case _ => syntaxError("illegal start of type", true); errorTypeTree
+ }
+ }
+
+ def typ(): Tree =
+ optArrayBrackets {
+ if (in.token == IDENTIFIER) {
+ var t = typeArgs(atPos(in.currentPos)(Ident(ident())))
+ while (in.token == DOT) {
+ in.nextToken
+ t = typeArgs(atPos(in.currentPos)(Select(t, ident())))
+ }
+ convertToTypeId(t)
+ } else {
+ basicType()
+ }
+ }
+
+ def typeArgs(t: Tree): Tree = {
+ val wildcards = new ListBuffer[TypeDef]
+ def typeArg(): Tree =
+ if (in.token == QMARK) {
+ val pos = in.currentPos
+ in.nextToken
+ var lo: Tree = TypeTree(AllClass.tpe)
+ var hi: Tree = TypeTree(AnyClass.tpe)
+ if (in.token == EXTENDS) {
+ in.nextToken
+ hi = typ()
+ } else if (in.token == SUPER) {
+ in.nextToken
+ lo = typ()
+ }
+ val tdef = atPos(pos) {
+ TypeDef(
+ Modifiers(Flags.JAVA),
+ newTypeName("_$"+ (wildcards.length + 1)),
+ List(),
+ TypeBoundsTree(lo, hi))
+ }
+ wildcards += tdef
+ atPos(pos) { Ident(tdef.name) }
+ } else {
+ typ()
+ }
+ if (in.token == LT) {
+ in.nextToken
+ val args = repsep(typeArg, COMMA)
+ acceptClosingAngle()
+ val t1: Tree = AppliedTypeTree(t, args)
+ if (wildcards.isEmpty) t1
+ else ExistentialTypeTree(t1, wildcards.toList)
+ } else t
+ }
+
+ def annotations(): List[Annotation] = {
+ //var annots = new ListBuffer[Annotation]
+ while (in.token == AT) {
+ in.nextToken
+ annotation()
+ }
+ List() // don't pass on annotations for now
+ }
+
+ /** Annotation ::= TypeName [`(' AnnotationArgument {`,' AnnotationArgument} `)']
+ */
+ def annotation() {
+ val pos = in.currentPos
+ var t = typ()
+ if (in.token == LPAREN) { skipAhead(); accept(RPAREN) }
+ }
+/*
+ def annotationArg() = {
+ val pos = in.token
+ if (in.token == IDENTIFIER && in.lookaheadToken == ASSIGN) {
+ val name = ident()
+ accept(ASSIGN)
+ atPos(pos) {
+ ValDef(Modifiers(Flags.JAVA), name, TypeTree(), elementValue())
+ }
+ } else {
+ elementValue()
+ }
+ }
+
+ def elementValue(): Tree =
+ if (in.token == AT) annotation()
+ else if (in.token == LBRACE) elementValueArrayInitializer()
+ else expression1()
+
+ def elementValueArrayInitializer() = {
+ accept(LBRACE)
+ val buf = new ListBuffer[Tree]
+ def loop() =
+ if (in.token != RBRACE) {
+ buf += elementValue()
+ if (in.token == COMMA) {
+ in.nextToken
+ loop()
+ }
+ }
+ loop()
+ accept(RBRACE)
+ buf.toList
+ }
+ */
+
+ def modifiers(inInterface: Boolean): Modifiers = {
+ var flags: Long = Flags.JAVA
+ var privateWithin: Name =
+ if (inInterface) nme.EMPTY.toTypeName else thisPackageName
+ while (true) {
+ in.token match {
+ case AT if (in.lookaheadToken != INTERFACE) =>
+ in.nextToken
+ annotation()
+ case PUBLIC =>
+ privateWithin = nme.EMPTY.toTypeName
+ in.nextToken
+ case PROTECTED =>
+ flags |= Flags.PROTECTED
+ privateWithin = thisPackageName
+ in.nextToken
+ case PRIVATE =>
+ flags |= Flags.PRIVATE
+ privateWithin = nme.EMPTY.toTypeName
+ in.nextToken
+ case STATIC =>
+ flags |= Flags.STATIC
+ in.nextToken
+ case ABSTRACT =>
+ flags |= Flags.ABSTRACT
+ in.nextToken
+ case FINAL =>
+ flags |= Flags.FINAL
+ in.nextToken
+ case NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | STRICTFP =>
+ in.nextToken
+ case _ =>
+ return Modifiers(flags, privateWithin)
+ }
+ }
+ throw new Error("should not be here")
+ }
+
+ def typeParams(): List[TypeDef] =
+ if (in.token == LT) {
+ in.nextToken
+ val tparams = repsep(typeParam, COMMA)
+ acceptClosingAngle()
+ tparams
+ } else List()
+
+ def typeParam(): TypeDef =
+ atPos(in.currentPos) {
+ val name = ident()
+ val hi =
+ if (in.token == EXTENDS) {
+ in.nextToken
+ bound()
+ } else {
+ scalaDot(nme.Any.toTypeName)
+ }
+ TypeDef(Modifiers(Flags.JAVA), name, List(), TypeBoundsTree(scalaDot(nme.Nothing.toTypeName), hi))
+ }
+
+ def bound(): Tree =
+ atPos(in.currentPos) {
+ val buf = new ListBuffer[Tree] + typ()
+ while (in.token == AMP) {
+ in.nextToken
+ buf += typ()
+ }
+ val ts = buf.toList
+ if (ts.tail.isEmpty) ts.head
+ else CompoundTypeTree(Template(ts, emptyValDef, List()))
+ }
+
+ def formalParams(): List[ValDef] = {
+ accept(LPAREN)
+ val vparams = if (in.token == RPAREN) List() else repsep(formalParam, COMMA)
+ accept(RPAREN)
+ vparams
+ }
+
+ def formalParam(): ValDef = {
+ if (in.token == FINAL) in.nextToken
+ annotations()
+ var t = typ()
+ if (in.token == DOTDOTDOT) {
+ in.nextToken
+ t = atPos(t.pos) {
+ AppliedTypeTree(TypeTree(RepeatedParamClass.typeConstructor), List(t))
+ }
+ }
+ varDecl(in.currentPos, Modifiers(Flags.JAVA | Flags.PARAM), t, ident())
+ }
+
+ def optThrows() {
+ if (in.token == THROWS) {
+ in.nextToken
+ repsep(typ, COMMA)
+ }
+ }
+
+ def methodBody(): Tree = {
+ skipAhead()
+ accept(RBRACE) // skip block
+ blankExpr
+ }
+
+ def termDecl(mods: Modifiers, parentToken: Int): List[Tree] = {
+ val inInterface = parentToken == INTERFACE || parentToken == AT
+ var mods1 = mods
+ if (mods hasFlag Flags.ABSTRACT) mods1 = mods &~ Flags.ABSTRACT | Flags.DEFERRED
+ val tparams = if (in.token == LT) typeParams() else List()
+ val isVoid = in.token == VOID
+ var rtpt =
+ if (isVoid) {
+ in.nextToken
+ TypeTree(UnitClass.tpe) setPos in.pos
+ } else typ()
+ var pos = in.currentPos
+ val rtptName = rtpt match {
+ case Ident(name) => name
+ case _ => nme.EMPTY
+ }
+ if (in.token == LPAREN && rtptName != nme.EMPTY && !inInterface) {
+ // constructor declaration
+ val vparams = formalParams()
+ optThrows()
+ List {
+ atPos(pos) {
+ DefDef(mods1, nme.CONSTRUCTOR, tparams, List(vparams), TypeTree(), methodBody())
+ }
+ }
+ } else {
+ pos = in.currentPos
+ val name = ident()
+ if (in.token == LPAREN) {
+ // method declaration
+ val vparams = formalParams()
+ if (!isVoid) rtpt = optArrayBrackets(rtpt)
+ optThrows()
+ val body =
+ if (!inInterface && in.token == LBRACE) {
+ methodBody()
+ } else {
+ if (parentToken == AT && in.token == DEFAULT) {
+ val annot =
+ atPos(pos) {
+ Annotation(
+ New(
+ Select(Ident(nme.ROOTPKG), nme.AnnotationDefaultATTR.toTypeName),
+ List(List())),
+ List())
+ }
+ mods1 = Modifiers(mods1.flags, mods1.privateWithin, annot :: mods1.annotations)
+ skipTo(SEMI)
+ accept(SEMI)
+ blankExpr
+ } else {
+ accept(SEMI)
+ EmptyTree
+ }
+ }
+ List {
+ atPos(pos) {
+ DefDef(mods1, name, tparams, List(vparams), rtpt, body)
+ }
+ }
+ } else {
+ val result = fieldDecls(pos, mods1, rtpt, name)
+ accept(SEMI)
+ result
+ }
+ }
+ }
+
+ def fieldDecls(pos: Position, mods: Modifiers, tpt: Tree, name: Name): List[Tree] = {
+ val buf = new ListBuffer[Tree] + varDecl(pos, mods, tpt, name)
+ while (in.token == COMMA) {
+ in.nextToken
+ buf += varDecl(in.currentPos, mods, tpt.duplicate, ident())
+ }
+ buf.toList
+ }
+
+ def varDecl(pos: Position, mods: Modifiers, tpt: Tree, name: Name): ValDef = {
+ val tpt1 = optArrayBrackets(tpt)
+ if (in.token == ASSIGN && !(mods hasFlag Flags.PARAM)) skipTo(COMMA, SEMI)
+ val mods1 = if (mods hasFlag Flags.FINAL) mods &~ Flags.FINAL else mods | Flags.MUTABLE
+ atPos(pos) {
+ ValDef(mods1, name, tpt1, blankExpr)
+ }
+ }
+
+ def memberDecl(mods: Modifiers, parentToken: Int): List[Tree] = in.token match {
+ case CLASS | ENUM | INTERFACE | AT => typeDecl(mods)
+ case _ => termDecl(mods, parentToken)
+ }
+
+ def makeCompanionObject(cdef: ClassDef, statics: List[Tree]): Tree =
+ atPos(cdef.pos) {
+ ModuleDef(cdef.mods & (Flags.AccessFlags | Flags.JAVA), cdef.name.toTermName,
+ makeTemplate(List(javaLangObject()), statics))
+ }
+
+ def addCompanionObject(statics: List[Tree], cdef: ClassDef): List[Tree] =
+ if (statics.isEmpty) List(cdef)
+ else List(cdef, makeCompanionObject(cdef, statics))
+
+ def importDecl(): List[Tree] = {
+ accept(IMPORT)
+ val pos = in.currentPos
+ val buf = new ListBuffer[Name]
+ def collectIdents() {
+ if (in.token == ASTERISK) {
+ in.nextToken
+ buf += nme.WILDCARD
+ } else {
+ buf += ident()
+ if (in.token == DOT) {
+ in.nextToken
+ collectIdents()
+ }
+ }
+ }
+ if (in.token == STATIC) in.nextToken
+ else buf += nme.ROOTPKG
+ collectIdents()
+ accept(SEMI)
+ val names = buf.toList
+ if (names.length < 2) {
+ syntaxError(pos, "illegal import", false)
+ List()
+ } else {
+ val qual = ((Ident(names.head): Tree) /: names.tail.init) (Select(_, _))
+ val lastname = names.last
+ List {
+ atPos(pos) {
+ if (lastname == nme.WILDCARD) Import(qual, List((lastname, null)))
+ else Import(qual, List((lastname, lastname)))
+ }
+ }
+ }
+ }
+
+ def interfacesOpt() =
+ if (in.token == IMPLEMENTS) {
+ in.nextToken
+ repsep(typ, COMMA)
+ } else {
+ List()
+ }
+
+ def classDecl(mods: Modifiers): List[Tree] = {
+ accept(CLASS)
+ val pos = in.currentPos
+ val name = ident().toTypeName
+ val tparams = typeParams()
+ val superclass =
+ if (in.token == EXTENDS) {
+ in.nextToken
+ typ()
+ } else {
+ javaLangObject()
+ }
+ val interfaces = interfacesOpt()
+ val (statics, body) = typeBody(CLASS)
+ addCompanionObject(statics, atPos(pos) {
+ ClassDef(mods, name, tparams, makeTemplate(superclass :: interfaces, body))
+ })
+ }
+
+ def interfaceDecl(mods: Modifiers): List[Tree] = {
+ accept(INTERFACE)
+ val pos = in.currentPos
+ val name = ident().toTypeName
+ val tparams = typeParams()
+ val parents =
+ if (in.token == EXTENDS) {
+ in.nextToken
+ repsep(typ, COMMA)
+ } else {
+ List()
+ }
+ val (statics, body) = typeBody(INTERFACE)
+ addCompanionObject(statics, atPos(pos) {
+ ClassDef(mods | Flags.TRAIT | Flags.INTERFACE | Flags.ABSTRACT,
+ name, tparams,
+ makeTemplate(parents, body))
+ })
+ }
+
+ def typeBody(leadingToken: Int): (List[Tree], List[Tree]) = {
+ accept(LBRACE)
+ val defs = typeBodyDecls(leadingToken)
+ accept(RBRACE)
+ defs
+ }
+
+ def typeBodyDecls(parentToken: Int): (List[Tree], List[Tree]) = {
+ val inInterface = parentToken == INTERFACE || parentToken == AT
+ val statics = new ListBuffer[Tree]
+ val members = new ListBuffer[Tree]
+ while (in.token != RBRACE && in.token != EOF) {
+ val mods = modifiers(inInterface)
+ if (in.token == LBRACE) {
+ skipAhead() // skip init block, we just assume we have seen only static
+ accept(RBRACE)
+ } else if (in.token == SEMI) {
+ in.nextToken
+ } else {
+ (if (mods hasFlag STATIC) statics else members) ++= memberDecl(mods, parentToken)
+ }
+ }
+ (statics.toList, members.toList)
+ }
+
+ def annotationDecl(mods: Modifiers): List[Tree] = {
+ accept(AT)
+ accept(INTERFACE)
+ val pos = in.currentPos
+ val name = ident().toTypeName
+ val parents = List(scalaDot(newTypeName("Annotation")),
+ Select(javaLangDot(newTermName("annotation")), newTypeName("Annotation")),
+ scalaDot(newTypeName("ClassfileAnnotation")))
+ val (statics, body) = typeBody(AT)
+ def getValueMethodType(tree: Tree) = tree match {
+ case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate)
+ case _ => None
+ }
+ var templ = makeTemplate(parents, body)
+ for (stat <- templ.body; tpt <- getValueMethodType(stat))
+ templ = makeTemplate(parents, makeConstructor(List(tpt)) :: templ.body)
+ addCompanionObject(statics, atPos(pos) {
+ ClassDef(mods, name, List(), templ)
+ })
+ }
+
+ def enumDecl(mods: Modifiers): List[Tree] = {
+ accept(ENUM)
+ val pos = in.currentPos
+ val name = ident().toTypeName
+ def enumType = Ident(name)
+ val interfaces = interfacesOpt()
+ accept(LBRACE)
+ val buf = new ListBuffer[Tree]
+ def parseEnumConsts() {
+ if (in.token != RBRACE && in.token != SEMI && in.token != EOF) {
+ buf += enumConst(enumType)
+ if (in.token == COMMA) {
+ in.nextToken
+ parseEnumConsts()
+ }
+ }
+ }
+ parseEnumConsts()
+ val consts = buf.toList
+ val (statics, body) =
+ if (in.token == SEMI) {
+ in.nextToken
+ typeBodyDecls(ENUM)
+ } else {
+ (List(), List())
+ }
+ val predefs = List(
+ DefDef(
+ Modifiers(Flags.JAVA), newTermName("values"), List(),
+ List(List()),
+ arrayOf(enumType),
+ blankExpr),
+ DefDef(
+ Modifiers(Flags.JAVA), newTermName("valueOf"), List(),
+ List(List(makeParam(newTermName("x"), TypeTree(StringClass.tpe)))),
+ enumType,
+ blankExpr))
+ accept(RBRACE)
+ val superclazz =
+ AppliedTypeTree(javaLangDot(newTypeName("Enum")), List(enumType))
+ addCompanionObject(consts ::: statics ::: predefs, atPos(pos) {
+ ClassDef(mods, name, List(),
+ makeTemplate(superclazz :: interfaces, body))
+ })
+ }
+
+ def enumConst(enumType: Tree) = {
+ annotations()
+ atPos(in.currentPos) {
+ val name = ident()
+ if (in.token == LPAREN) {
+ // skip arguments
+ skipAhead()
+ accept(RPAREN)
+ }
+ if (in.token == LBRACE) {
+ // skip classbody
+ skipAhead()
+ accept(RBRACE)
+ }
+ ValDef(Modifiers(Flags.JAVA), name, enumType, blankExpr)
+ }
+ }
+
+ def typeDecl(mods: Modifiers): List[Tree] = in.token match {
+ case ENUM => enumDecl(mods)
+ case INTERFACE => interfaceDecl(mods)
+ case AT => annotationDecl(mods)
+ case CLASS => classDecl(mods)
+ case _ => in.nextToken; syntaxError("illegal start of type declaration", true); List(errorTypeTree)
+ }
+
+ /** CompilationUnit ::= [package QualId semi] TopStatSeq
+ */
+ def compilationUnit(): Tree = {
+ var pos = in.currentPos;
+ val pkg =
+ if (in.token == AT || in.token == PACKAGE) {
+ annotations()
+ pos = in.currentPos
+ accept(PACKAGE)
+ val pkg = qualId()
+ accept(SEMI)
+ pkg
+ } else {
+ Ident(nme.EMPTY_PACKAGE_NAME)
+ }
+ thisPackageName = pkg match {
+ case Ident(name) => name.toTypeName
+ case Select(_, name) => name.toTypeName
+ }
+ val buf = new ListBuffer[Tree]
+ while (in.token == IMPORT)
+ buf ++= importDecl()
+ while (in.token != EOF && in.token != RBRACE) {
+ while (in.token == SEMI) in.nextToken
+ buf ++= typeDecl(modifiers(false))
+ }
+ accept(EOF)
+ atPos(pos) {
+ makePackaging(pkg, buf.toList)
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
new file mode 100755
index 0000000000..7aacdc4559
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -0,0 +1,978 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2008 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc.javac
+
+import scala.tools.nsc.util._
+import SourceFile.{LF, FF, CR, SU}
+import JavaTokens._
+
+trait JavaScanners {
+ val global : Global
+ import global._
+ abstract class AbstractJavaTokenData {
+ def token: Int
+ type ScanPosition
+ val NoPos: ScanPosition
+ def pos: ScanPosition
+ def name: Name
+ }
+
+ /** A class for representing a token's data. */
+ trait JavaTokenData extends AbstractJavaTokenData {
+ type ScanPosition = Int
+
+ val NoPos: Int = -1
+ /** the next token */
+ var token: Int = EMPTY
+ /** the token's position */
+ var pos: Int = 0
+
+ /** the first character position after the previous token */
+ var lastPos: Int = 0
+
+ /** the name of an identifier or token */
+ var name: Name = null
+
+ /** the base of a number */
+ var base: Int = 0
+
+ def copyFrom(td: JavaTokenData) = {
+ this.token = td.token
+ this.pos = td.pos
+ this.lastPos = td.lastPos
+ this.name = td.name
+ this.base = td.base
+ }
+ }
+
+ /** ...
+ */
+ abstract class AbstractJavaScanner extends AbstractJavaTokenData {
+ implicit def p2g(pos: Position): ScanPosition
+ implicit def g2p(pos: ScanPosition): Position
+ def warning(pos: ScanPosition, msg: String): Unit
+ def error (pos: ScanPosition, msg: String): Unit
+ def incompleteInputError(pos: ScanPosition, msg: String): Unit
+ def deprecationWarning(pos: ScanPosition, msg: String): Unit
+ /** the last error position
+ */
+ var errpos: ScanPosition
+ var lastPos: ScanPosition
+ def skipToken: ScanPosition
+ def nextToken: Unit
+ def next: AbstractJavaTokenData
+ def intVal(negated: Boolean): Long
+ def floatVal(negated: Boolean): Double
+ def intVal: Long = intVal(false)
+ def floatVal: Double = floatVal(false)
+ //def token2string(token : Int) : String = configuration.token2string(token)
+ /** return recent scala doc, if any */
+ def flushDoc: String
+ def currentPos: Position
+ }
+
+ object JavaScannerConfiguration {
+// Keywords -----------------------------------------------------------------
+ /** Keyword array; maps from name indices to tokens */
+ private var key: Array[Byte] = _
+ private var maxKey = 0
+ private var tokenName = new Array[Name](128)
+
+ {
+ var tokenCount = 0
+
+ // Enter keywords
+
+ def enterKeyword(s: String, tokenId: Int) {
+ val n = newTermName(s)
+ while (tokenId >= tokenName.length) {
+ val newTokName = new Array[Name](tokenName.length * 2)
+ Array.copy(tokenName, 0, newTokName, 0, newTokName.length)
+ tokenName = newTokName
+ }
+ tokenName(tokenId) = n
+ if (n.start > maxKey) maxKey = n.start
+ if (tokenId >= tokenCount) tokenCount = tokenId + 1
+ }
+
+ enterKeyword("abstract", ABSTRACT)
+ enterKeyword("assert", ASSERT)
+ enterKeyword("boolean", BOOLEAN)
+ enterKeyword("break", BREAK)
+ enterKeyword("byte", BYTE)
+ enterKeyword("case", CASE)
+ enterKeyword("catch", CATCH)
+ enterKeyword("char", CHAR)
+ enterKeyword("class", CLASS)
+ enterKeyword("const", CONST)
+ enterKeyword("continue", CONTINUE)
+ enterKeyword("default", DEFAULT)
+ enterKeyword("do", DO)
+ enterKeyword("double", DOUBLE)
+ enterKeyword("else", ELSE)
+ enterKeyword("enum", ENUM)
+ enterKeyword("extends", EXTENDS)
+ enterKeyword("final", FINAL)
+ enterKeyword("finally", FINALLY)
+ enterKeyword("float", FLOAT)
+ enterKeyword("for", FOR)
+ enterKeyword("if", IF)
+ enterKeyword("goto", GOTO)
+ enterKeyword("implements", IMPLEMENTS)
+ enterKeyword("import", IMPORT)
+ enterKeyword("instanceof", INSTANCEOF)
+ enterKeyword("int", INT)
+ enterKeyword("interface", INTERFACE)
+ enterKeyword("long", LONG)
+ enterKeyword("native", NATIVE)
+ enterKeyword("new", NEW)
+ enterKeyword("package", PACKAGE)
+ enterKeyword("private", PRIVATE)
+ enterKeyword("protected", PROTECTED)
+ enterKeyword("public", PUBLIC)
+ enterKeyword("return", RETURN)
+ enterKeyword("short", SHORT)
+ enterKeyword("static", STATIC)
+ enterKeyword("strictfp", STRICTFP)
+ enterKeyword("super", SUPER)
+ enterKeyword("switch", SWITCH)
+ enterKeyword("synchronized", SYNCHRONIZED)
+ enterKeyword("this", THIS)
+ enterKeyword("throw", THROW)
+ enterKeyword("throws", THROWS)
+ enterKeyword("transient", TRANSIENT)
+ enterKeyword("try", TRY)
+ enterKeyword("void", VOID)
+ enterKeyword("volatile", VOLATILE)
+ enterKeyword("while", WHILE)
+
+ // Build keyword array
+ key = new Array[Byte](maxKey + 1)
+ for (i <- 0 to maxKey)
+ key(i) = IDENTIFIER
+ for (j <- 0 until tokenCount)
+ if (tokenName(j) ne null)
+ key(tokenName(j).start) = j.asInstanceOf[Byte]
+
+ }
+
+//Token representation -----------------------------------------------------
+
+ /** Convert name to token */
+ def name2token(name: Name): Int =
+ if (name.start <= maxKey) key(name.start) else IDENTIFIER
+
+ /** Returns the string representation of given token. */
+ def token2string(token: Int): String = token match {
+ case IDENTIFIER =>
+ "identifier"/* + \""+name+"\""*/
+ case CHARLIT =>
+ "character literal"
+ case INTLIT =>
+ "integer literal"
+ case LONGLIT =>
+ "long literal"
+ case FLOATLIT =>
+ "float literal"
+ case DOUBLELIT =>
+ "double literal"
+ case STRINGLIT =>
+ "string literal"
+ case COMMA => "`,'"
+ case SEMI => "`;'"
+ case DOT => "`.'"
+ case AT => "`@'"
+ case COLON => "`:'"
+ case ASSIGN => "`='"
+ case EQEQ => "`=='"
+ case BANGEQ => "`!='"
+ case LT => "`<'"
+ case GT => "`>'"
+ case LTEQ => "`<='"
+ case GTEQ => "`>='"
+ case BANG => "`!'"
+ case QMARK => "`?'"
+ case AMP => "`&'"
+ case BAR => "`|'"
+ case PLUS => "`+'"
+ case MINUS => "`-'"
+ case ASTERISK => "`*'"
+ case SLASH => "`/'"
+ case PERCENT => "`%'"
+ case HAT => "`^'"
+ case LTLT => "`<<'"
+ case GTGT => "`>>'"
+ case GTGTGT => "`>>>'"
+ case AMPAMP => "`&&'"
+ case BARBAR => "`||'"
+ case PLUSPLUS => "`++'"
+ case MINUSMINUS => "`--'"
+ case TILDE => "`~'"
+ case DOTDOTDOT => "`...'"
+ case AMPEQ => "`&='"
+ case BAREQ => "`|='"
+ case PLUSEQ => "`+='"
+ case MINUSEQ => "`-='"
+ case ASTERISKEQ => "`*='"
+ case SLASHEQ => "`/='"
+ case PERCENTEQ => "`%='"
+ case HATEQ => "`^='"
+ case LTLTEQ => "`<<='"
+ case GTGTEQ => "`>>='"
+ case GTGTGTEQ => "`>>>='"
+ case LPAREN => "`('"
+ case RPAREN => "`)'"
+ case LBRACE => "`{'"
+ case RBRACE => "`}'"
+ case LBRACKET => "`['"
+ case RBRACKET => "`]'"
+ case EOF => "eof"
+ case ERROR => "something"
+ case _ =>
+ try {
+ "`" + tokenName(token) + "'"
+ } catch {
+ case _: ArrayIndexOutOfBoundsException =>
+ "`<" + token + ">'"
+ case _: NullPointerException =>
+ "`<(" + token + ")>'"
+ }
+ }
+ }
+
+ /** A scanner for Java.
+ *
+ * @author Martin Odersky
+ */
+ abstract class JavaScanner extends AbstractJavaScanner with JavaTokenData with Cloneable {
+ override def intVal = super.intVal// todo: needed?
+ override def floatVal = super.floatVal
+ override var errpos: Int = NoPos
+ def currentPos: Position = g2p(pos - 1)
+
+ var in: CharArrayReader = _
+
+ def dup: JavaScanner = {
+ val dup = clone().asInstanceOf[JavaScanner]
+ dup.in = in.dup
+ dup
+ }
+
+ /** character buffer for literals
+ */
+ val cbuf = new StringBuilder()
+
+ /** append Unicode character to "lit" buffer
+ */
+ protected def putChar(c: Char) { cbuf.append(c) }
+
+ /** Clear buffer and set name */
+ private def setName() {
+ name = newTermName(cbuf.toString())
+ cbuf.setLength(0)
+ }
+
+ /** buffer for the documentation comment
+ */
+ var docBuffer: StringBuilder = null
+
+ def flushDoc = {
+ val ret = if (docBuffer != null) docBuffer.toString else null
+ docBuffer = null
+ ret
+ }
+
+ /** add the given character to the documentation buffer
+ */
+ protected def putDocChar(c: Char) {
+ if (docBuffer ne null) docBuffer.append(c)
+ }
+
+ private class JavaTokenData0 extends JavaTokenData
+
+ /** we need one token lookahead
+ */
+ val next : JavaTokenData = new JavaTokenData0
+ val prev : JavaTokenData = new JavaTokenData0
+
+// Get next token ------------------------------------------------------------
+
+ /** read next token and return last position
+ */
+ def skipToken: Int = {
+ val p = pos; nextToken
+ p - 1
+ }
+
+ def nextToken {
+ if (next.token == EMPTY) {
+ print("[")
+ val t = fetchToken()
+ print(this)
+ print("]")
+ t
+ } else {
+ this copyFrom next
+ next.token = EMPTY
+ }
+ }
+
+ def lookaheadToken: Int = {
+ prev copyFrom this
+ nextToken
+ val t = token
+ next copyFrom this
+ this copyFrom prev
+ t
+ }
+
+ private def afterLineEnd() = (
+ lastPos < in.lineStartPos &&
+ (in.lineStartPos <= pos ||
+ lastPos < in.lastLineStartPos && in.lastLineStartPos <= pos)
+ )
+
+ /** read next token
+ */
+ private def fetchToken() {
+ if (token == EOF) return
+ lastPos = in.cpos - 1 // Position.encode(in.cline, in.ccol)
+ //var index = bp
+ while (true) {
+ in.ch match {
+ case ' ' | '\t' | CR | LF | FF =>
+ in.next
+ case _ =>
+ pos = in.cpos // Position.encode(in.cline, in.ccol)
+ in.ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' | '_' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' =>
+ putChar(in.ch)
+ in.next
+ getIdentRest
+ return
+
+ case '0' =>
+ putChar(in.ch)
+ in.next
+ if (in.ch == 'x' || in.ch == 'X') {
+ in.next
+ base = 16
+ } else {
+ base = 8
+ }
+ getNumber
+ return
+
+ case '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ base = 10
+ getNumber
+ return
+
+ case '\"' =>
+ in.next
+ while (in.ch != '\"' && (in.isUnicode || in.ch != CR && in.ch != LF && in.ch != SU)) {
+ getlitch()
+ }
+ if (in.ch == '\"') {
+ token = STRINGLIT
+ setName()
+ in.next
+ } else {
+ syntaxError("unclosed string literal")
+ }
+ return
+
+ case '\'' =>
+ in.next
+ getlitch()
+ if (in.ch == '\'') {
+ in.next
+ token = CHARLIT
+ setName()
+ } else {
+ syntaxError("unclosed character literal")
+ }
+ return
+
+ case '=' =>
+ token = ASSIGN
+ in.next
+ if (in.ch == '=') {
+ token = EQEQ
+ in.next
+ }
+ return
+
+ case '>' =>
+ token = GT
+ in.next
+ if (in.ch == '=') {
+ token = GTEQ
+ in.next
+ } else if (in.ch == '>') {
+ token = GTGT
+ in.next
+ if (in.ch == '=') {
+ token = GTGTEQ
+ in.next
+ } else if (in.ch == '>') {
+ token = GTGTGT
+ in.next
+ if (in.ch == '=') {
+ token = GTGTGTEQ
+ in.next
+ }
+ }
+ }
+ return
+
+ case '<' =>
+ token = LT
+ in.next
+ if (in.ch == '=') {
+ token = LTEQ
+ in.next
+ } else if (in.ch == '<') {
+ token = LTLT
+ in.next
+ if (in.ch == '=') {
+ token = LTLTEQ
+ in.next
+ }
+ }
+ return
+
+ case '!' =>
+ token = BANG
+ in.next
+ if (in.ch == '=') {
+ token = BANGEQ
+ in.next
+ }
+ return
+
+ case '~' =>
+ token = TILDE
+ in.next
+ return
+
+ case '?' =>
+ token = QMARK
+ in.next
+ return
+
+ case ':' =>
+ token = COLON
+ in.next
+ return
+
+ case '@' =>
+ token = AT
+ in.next
+ return
+
+ case '&' =>
+ token = AMP
+ in.next
+ if (in.ch == '&') {
+ token = AMPAMP
+ in.next
+ } else if (in.ch == '=') {
+ token = AMPEQ
+ in.next
+ }
+ return
+
+ case '|' =>
+ token = BAR
+ in.next
+ if (in.ch == '|') {
+ token = BARBAR
+ in.next
+ } else if (in.ch == '=') {
+ token = BAREQ
+ in.next
+ }
+ return
+
+ case '+' =>
+ token = PLUS
+ in.next
+ if (in.ch == '+') {
+ token = PLUSPLUS
+ in.next
+ } else if (in.ch == '=') {
+ token = PLUSEQ
+ in.next
+ }
+ return
+
+ case '-' =>
+ token = MINUS
+ in.next
+ if (in.ch == '-') {
+ token = MINUSMINUS
+ in.next
+ } else if (in.ch == '=') {
+ token = MINUSEQ
+ in.next
+ }
+ return
+
+ case '*' =>
+ token = ASTERISK
+ in.next
+ if (in.ch == '=') {
+ token = ASTERISKEQ
+ in.next
+ }
+ return
+
+ case '/' =>
+ in.next
+ if (!skipComment()) {
+ token = SLASH
+ in.next
+ if (in.ch == '=') {
+ token = SLASHEQ
+ in.next
+ }
+ return
+ }
+
+ case '^' =>
+ token = HAT
+ in.next
+ if (in.ch == '=') {
+ token = HATEQ
+ in.next
+ }
+ return
+
+ case '%' =>
+ token = PERCENT
+ in.next
+ if (in.ch == '=') {
+ token = PERCENTEQ
+ in.next
+ }
+ return
+
+ case '.' =>
+ token = DOT
+ in.next
+ if ('0' <= in.ch && in.ch <= '9') {
+ putChar('.'); getFraction
+ } else if (in.ch == '.') {
+ in.next
+ if (in.ch == '.') {
+ in.next
+ token = DOTDOTDOT
+ } else syntaxError("`.' character expected")
+ }
+ return
+
+ case ';' =>
+ token = SEMI
+ in.next
+ return
+
+ case ',' =>
+ token = COMMA
+ in.next
+ return
+
+ case '(' =>
+ token = LPAREN
+ in.next
+ return
+
+ case '{' =>
+ token = LBRACE
+ in.next
+ return
+
+ case ')' =>
+ token = RPAREN
+ in.next
+ return
+
+ case '}' =>
+ token = RBRACE
+ in.next
+ return
+
+ case '[' =>
+ token = LBRACKET
+ in.next
+ return
+
+ case ']' =>
+ token = RBRACKET
+ in.next
+ return
+
+ case SU =>
+ if (!in.hasNext) token = EOF
+ else {
+ syntaxError("illegal character")
+ in.next
+ }
+ return
+
+ case _ =>
+ if (Character.isUnicodeIdentifierStart(in.ch)) {
+ putChar(in.ch)
+ in.next
+ getIdentRest
+ } else {
+ syntaxError("illegal character: "+in.ch.toInt)
+ in.next
+ }
+ return
+ }
+ }
+ }
+ }
+
+ private def skipComment(): Boolean = {
+ if (in.ch == '/') {
+ do {
+ in.next
+ } while ((in.ch != CR) && (in.ch != LF) && (in.ch != SU))
+ true
+ } else if (in.ch == '*') {
+ docBuffer = null
+ in.next
+ val scalaDoc = ("/**", "*/")
+ if (in.ch == '*' && onlyPresentation)
+ docBuffer = new StringBuilder(scalaDoc._1)
+ do {
+ do {
+ if (in.ch != '*' && in.ch != SU) {
+ in.next; putDocChar(in.ch)
+ }
+ } while (in.ch != '*' && in.ch != SU)
+ while (in.ch == '*') {
+ in.next; putDocChar(in.ch)
+ }
+ } while (in.ch != '/' && in.ch != SU)
+ if (in.ch == '/') in.next
+ else incompleteInputError("unclosed comment")
+ true
+ } else {
+ false
+ }
+ }
+
+// Identifiers ---------------------------------------------------------------
+
+ def isIdentStart(c: Char): Boolean = (
+ ('A' <= c && c <= 'Z') ||
+ ('a' <= c && c <= 'a') ||
+ (c == '_') || (c == '$') ||
+ Character.isUnicodeIdentifierStart(c)
+ )
+
+ def isIdentPart(c: Char) = (
+ isIdentStart(c) ||
+ ('0' <= c && c <= '9') ||
+ Character.isUnicodeIdentifierPart(c)
+ )
+
+ def isSpecial(c: Char) = {
+ val chtp = Character.getType(c)
+ chtp == Character.MATH_SYMBOL || chtp == Character.OTHER_SYMBOL
+ }
+
+ private def getIdentRest {
+ while (true) {
+ in.ch match {
+ case 'A' | 'B' | 'C' | 'D' | 'E' |
+ 'F' | 'G' | 'H' | 'I' | 'J' |
+ 'K' | 'L' | 'M' | 'N' | 'O' |
+ 'P' | 'Q' | 'R' | 'S' | 'T' |
+ 'U' | 'V' | 'W' | 'X' | 'Y' |
+ 'Z' | '$' |
+ 'a' | 'b' | 'c' | 'd' | 'e' |
+ 'f' | 'g' | 'h' | 'i' | 'j' |
+ 'k' | 'l' | 'm' | 'n' | 'o' |
+ 'p' | 'q' | 'r' | 's' | 't' |
+ 'u' | 'v' | 'w' | 'x' | 'y' |
+ 'z' |
+ '0' | '1' | '2' | '3' | '4' |
+ '5' | '6' | '7' | '8' | '9' =>
+ putChar(in.ch)
+ in.next
+
+ case '_' =>
+ putChar(in.ch)
+ in.next
+ getIdentRest
+ return
+ case SU =>
+ setName()
+ token = JavaScannerConfiguration.name2token(name)
+ return
+ case _ =>
+ if (Character.isUnicodeIdentifierPart(in.ch)) {
+ putChar(in.ch)
+ in.next
+ } else {
+ setName()
+ token = JavaScannerConfiguration.name2token(name)
+ return
+ }
+ }
+ }
+ }
+
+// Literals -----------------------------------------------------------------
+
+ /** read next character in character or string literal:
+ */
+ protected def getlitch() =
+ if (in.ch == '\\') {
+ in.next
+ if ('0' <= in.ch && in.ch <= '7') {
+ val leadch: Char = in.ch
+ var oct: Int = in.digit2int(in.ch, 8)
+ in.next
+ if ('0' <= in.ch && in.ch <= '7') {
+ oct = oct * 8 + in.digit2int(in.ch, 8)
+ in.next
+ if (leadch <= '3' && '0' <= in.ch && in.ch <= '7') {
+ oct = oct * 8 + in.digit2int(in.ch, 8)
+ in.next
+ }
+ }
+ putChar(oct.asInstanceOf[Char])
+ } else {
+ in.ch match {
+ case 'b' => putChar('\b')
+ case 't' => putChar('\t')
+ case 'n' => putChar('\n')
+ case 'f' => putChar('\f')
+ case 'r' => putChar('\r')
+ case '\"' => putChar('\"')
+ case '\'' => putChar('\'')
+ case '\\' => putChar('\\')
+ case _ =>
+ syntaxError(in.cpos - 1, "invalid escape character")
+ putChar(in.ch)
+ }
+ in.next
+ }
+ } else {
+ putChar(in.ch)
+ in.next
+ }
+
+ /** read fractional part and exponent of floating point number
+ * if one is present.
+ */
+ protected def getFraction {
+ token = DOUBLELIT
+ while ('0' <= in.ch && in.ch <= '9') {
+ putChar(in.ch)
+ in.next
+ }
+ if (in.ch == 'e' || in.ch == 'E') {
+ val lookahead = in.copy
+ lookahead.next
+ if (lookahead.ch == '+' || lookahead.ch == '-') {
+ lookahead.next
+ }
+ if ('0' <= lookahead.ch && lookahead.ch <= '9') {
+ putChar(in.ch)
+ in.next
+ if (in.ch == '+' || in.ch == '-') {
+ putChar(in.ch)
+ in.next
+ }
+ while ('0' <= in.ch && in.ch <= '9') {
+ putChar(in.ch)
+ in.next
+ }
+ }
+ token = DOUBLELIT
+ }
+ if (in.ch == 'd' || in.ch == 'D') {
+ putChar(in.ch)
+ in.next
+ token = DOUBLELIT
+ } else if (in.ch == 'f' || in.ch == 'F') {
+ putChar(in.ch)
+ in.next
+ token = FLOATLIT
+ }
+ setName()
+ }
+
+ /** convert name to long value
+ */
+ def intVal(negated: Boolean): Long = {
+ if (token == CHARLIT && !negated) {
+ if (name.length > 0) name(0) else 0
+ } else {
+ var value: Long = 0
+ val divider = if (base == 10) 1 else 2
+ val limit: Long =
+ if (token == LONGLIT) Math.MAX_LONG else Math.MAX_INT
+ var i = 0
+ val len = name.length
+ while (i < len) {
+ val d = in.digit2int(name(i), base)
+ if (d < 0) {
+ syntaxError("malformed integer number")
+ return 0
+ }
+ if (value < 0 ||
+ limit / (base / divider) < value ||
+ limit - (d / divider) < value * (base / divider) &&
+ !(negated && limit == value * base - 1 + d)) {
+ syntaxError("integer number too large")
+ return 0
+ }
+ value = value * base + d
+ i += 1
+ }
+ if (negated) -value else value
+ }
+ }
+
+
+ /** convert name, base to double value
+ */
+ def floatVal(negated: Boolean): Double = {
+ val limit: Double =
+ if (token == DOUBLELIT) Math.MAX_DOUBLE else Math.MAX_FLOAT
+ try {
+ val value: Double = java.lang.Double.valueOf(name.toString()).doubleValue()
+ if (value > limit)
+ syntaxError("floating point number too large")
+ if (negated) -value else value
+ } catch {
+ case _: NumberFormatException =>
+ syntaxError("malformed floating point number")
+ 0.0
+ }
+ }
+ /** read a number into name and set base
+ */
+ protected def getNumber {
+ while (in.digit2int(in.ch, if (base < 10) 10 else base) >= 0) {
+ putChar(in.ch)
+ in.next
+ }
+ token = INTLIT
+ if (base <= 10 && in.ch == '.') {
+ val lookahead = in.copy
+ lookahead.next
+ lookahead.ch match {
+ case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' |
+ '8' | '9' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F' =>
+ putChar(in.ch)
+ in.next
+ return getFraction
+ case _ =>
+ if (!isIdentStart(lookahead.ch)) {
+ putChar(in.ch)
+ in.next
+ return getFraction
+ }
+ }
+ }
+ if (base <= 10 &&
+ (in.ch == 'e' || in.ch == 'E' ||
+ in.ch == 'f' || in.ch == 'F' ||
+ in.ch == 'd' || in.ch == 'D')) {
+ return getFraction
+ }
+ setName()
+ if (in.ch == 'l' || in.ch == 'L') {
+ in.next
+ token = LONGLIT
+ }
+ }
+
+// Errors -----------------------------------------------------------------
+
+ /** generate an error at the given position
+ */
+ def syntaxError(pos: Int, msg: String) {
+ error(pos, msg)
+ token = ERROR
+ errpos = pos
+ }
+
+ /** generate an error at the current token position
+ */
+ def syntaxError(msg: String) { syntaxError(pos, msg) }
+
+ /** signal an error where the input ended in the middle of a token */
+ def incompleteInputError(msg: String) {
+ incompleteInputError(pos, msg)
+ token = EOF
+ errpos = pos
+ }
+
+ override def toString() = token match {
+ case IDENTIFIER =>
+ "id(" + name + ")"
+ case CHARLIT =>
+ "char(" + intVal + ")"
+ case INTLIT =>
+ "int(" + intVal + ")"
+ case LONGLIT =>
+ "long(" + intVal + ")"
+ case FLOATLIT =>
+ "float(" + floatVal + ")"
+ case DOUBLELIT =>
+ "double(" + floatVal + ")"
+ case STRINGLIT =>
+ "string(" + name + ")"
+ case SEMI =>
+ ";"
+ case COMMA =>
+ ","
+ case _ =>
+ JavaScannerConfiguration.token2string(token)
+ }
+
+ /** INIT: read lookahead character and token.
+ */
+ def init {
+ in.next
+ nextToken
+ }
+ }
+
+ /** ...
+ */
+ class JavaUnitScanner(unit: CompilationUnit) extends JavaScanner {
+ in = new CharArrayReader(unit.source.asInstanceOf[BatchSourceFile].content, !settings.nouescape.value, syntaxError)
+ init
+ def warning(pos: Int, msg: String) = unit.warning(pos, msg)
+ def error (pos: Int, msg: String) = unit. error(pos, msg)
+ def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg)
+ def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg)
+ implicit def p2g(pos: Position): Int = pos.offset.getOrElse(-1)
+ implicit def g2p(pos: Int): Position = new OffsetPosition(unit.source, pos)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaTokens.scala b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala
new file mode 100755
index 0000000000..53db4060b1
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/javac/JavaTokens.scala
@@ -0,0 +1,157 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2006 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: Tokens.scala 12886 2007-09-17 16:36:10Z mcdirmid $
+
+package scala.tools.nsc.javac
+
+object JavaTokens {
+
+ /** special tokens */
+ final val EMPTY = -3
+ final val UNDEF = -2
+ final val ERROR = -1
+ final val EOF = 0
+
+ /** literals */
+ final val CHARLIT = 1
+ final val INTLIT = 2
+ final val LONGLIT = 3
+ final val FLOATLIT = 4
+ final val DOUBLELIT = 5
+ final val STRINGLIT = 6
+ def isLiteral(code : Int) =
+ code >= CHARLIT && code <= STRINGLIT
+
+ /** identifiers */
+ final val IDENTIFIER = 10
+ def isIdentifier(code : Int) =
+ code == IDENTIFIER
+
+ /** keywords */
+ final val ABSTRACT = 20
+ final val ASSERT = 21
+ final val BOOLEAN = 22
+ final val BREAK = 23
+ final val BYTE = 24
+ final val CASE = 25
+ final val CATCH = 26
+ final val CHAR = 27
+ final val CLASS = 28
+ final val CONST = 29
+ final val CONTINUE = 30
+ final val DEFAULT = 31
+ final val DO = 32
+ final val DOUBLE = 33
+ final val ELSE = 34
+ final val ENUM = 35
+ final val EXTENDS = 36
+ final val FINAL = 37
+ final val FINALLY = 38
+ final val FLOAT = 39
+ final val FOR = 40
+ final val IF = 41
+ final val GOTO = 42
+ final val IMPLEMENTS = 43
+ final val IMPORT = 44
+ final val INSTANCEOF = 45
+ final val INT = 46
+ final val INTERFACE = 47
+ final val LONG = 48
+ final val NATIVE = 49
+ final val NEW = 50
+ final val PACKAGE = 51
+ final val PRIVATE = 52
+ final val PROTECTED = 53
+ final val PUBLIC = 54
+ final val RETURN = 55
+ final val SHORT = 56
+ final val STATIC = 57
+ final val STRICTFP = 58
+ final val SUPER = 59
+ final val SWITCH = 60
+ final val SYNCHRONIZED = 61
+ final val THIS = 62
+ final val THROW = 63
+ final val THROWS = 64
+ final val TRANSIENT = 65
+ final val TRY = 66
+ final val VOID = 67
+ final val VOLATILE = 68
+ final val WHILE = 69
+
+ def isKeyword(code : Int) =
+ code >= ABSTRACT && code <= WHILE
+
+ /** special symbols */
+ final val COMMA = 70
+ final val SEMI = 71
+ final val DOT = 72
+ final val AT = 73
+ final val COLON = 74
+ final val ASSIGN = 75
+ final val EQEQ = 76
+ final val BANGEQ = 77
+ final val LT = 78
+ final val GT = 79
+ final val LTEQ = 80
+ final val GTEQ = 81
+ final val BANG = 82
+ final val QMARK = 83
+ final val AMP = 84
+ final val BAR = 85
+ final val PLUS = 86
+ final val MINUS = 87
+ final val ASTERISK = 88
+ final val SLASH = 89
+ final val PERCENT = 90
+ final val HAT = 91
+ final val LTLT = 92
+ final val GTGT = 93
+ final val GTGTGT = 94
+ final val AMPAMP = 95
+ final val BARBAR = 96
+ final val PLUSPLUS = 97
+ final val MINUSMINUS = 98
+ final val TILDE = 99
+ final val DOTDOTDOT = 100
+ final val AMPEQ = 104
+ final val BAREQ = 105
+ final val PLUSEQ = 106
+ final val MINUSEQ = 107
+ final val ASTERISKEQ = 1010
+ final val SLASHEQ = 109
+ final val PERCENTEQ = 110
+ final val HATEQ = 111
+ final val LTLTEQ = 112
+ final val GTGTEQ = 113
+ final val GTGTGTEQ = 114
+
+ def isSymbol(code : Int) =
+ code >= COMMA && code <= GTGTGTEQ
+
+ /** parenthesis */
+ final val LPAREN = 115
+ final val RPAREN = 116
+ final val LBRACKET = 117
+ final val RBRACKET = 118
+ final val LBRACE = 119
+ final val RBRACE = 120
+
+ def isBrace(code : Int) =
+ code >= LPAREN && code <= RBRACE
+ def isOpenBrace(code : Int) = isBrace(code) && (code % 2 == 0)
+ def isCloseBrace(code : Int) = isBrace(code) && (code % 2 == 1)
+
+ def isSpace(at : Char) = at match {
+ case ' ' | '\t' => true
+ case _ => false
+ }
+ import scala.tools.nsc.util.SourceFile._
+
+ def isNewLine(at : Char) = at match {
+ case CR | LF | FF => true
+ case _ => false
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 7f7a15fac9..b5ba39021b 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -794,6 +794,11 @@ trait Definitions {
AnnotationDefaultAttr = newClass(RootClass,
nme.AnnotationDefaultATTR,
List(AnnotationClass.typeConstructor))
+ // This attribute needs a constructor so that modifiers in parsed
+ // Java code make sense
+ AnnotationDefaultAttr.info.decls.enter(
+ AnnotationDefaultAttr.newConstructor(NoPosition)
+ .setInfo(MethodType(List(), AnnotationDefaultAttr.tpe)))
} //init
var nbScalaCallers: Int = 0
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 8bccaf092b..7235c3341f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -440,11 +440,27 @@ abstract class ClassfileParser {
.newMethod(NoPosition, name).setFlag(sflags).setInfo(info)
setPrivateWithin(sym, jflags)
parseAttributes(sym, info)
+ if ((jflags & JAVA_ACC_VARARGS) != 0) {
+ sym.setInfo(arrayToRepeated(sym.info))
+ }
getScope(jflags).enter(sym)
}
}
}
+ /** Convert repeated parameters to arrays if they occur as part of a Java method
+ */
+ private def arrayToRepeated(tp: Type): Type = tp match {
+ case MethodType(formals, rtpe) =>
+ assert(formals.last.typeSymbol == definitions.ArrayClass)
+ MethodType(
+ formals.init :::
+ List(appliedType(definitions.RepeatedParamClass.typeConstructor, List(formals.last.typeArgs.head))),
+ rtpe)
+ case PolyType(tparams, rtpe) =>
+ PolyType(tparams, arrayToRepeated(rtpe))
+ }
+
private def sigToType(sym: Symbol, sig: Name): Type = {
var index = 0
val end = sig.length
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 04f7ae2eee..e971e4138d 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -94,13 +94,31 @@ abstract class UnCurry extends InfoTransform with TypingTransformers {
}
}
+ /** Convert repeated parameters to arrays if they occur as part of a Java method
+ */
+ private def repeatedToArray(tp: Type): Type = tp match {
+ case MethodType(formals, rtpe)
+ if (!formals.isEmpty && formals.last.typeSymbol == RepeatedParamClass) =>
+ MethodType(formals.init :::
+ List(appliedType(ArrayClass.typeConstructor, List(formals.last.typeArgs.head))),
+ rtpe)
+ case PolyType(tparams, rtpe) =>
+ val rtpe1 = repeatedToArray(rtpe)
+ if (rtpe1 eq rtpe) tp
+ else PolyType(tparams, rtpe1)
+ case _ =>
+ tp
+ }
+
/** - return symbol's transformed type,
* - if symbol is a def parameter with transformed type T, return () => T
*
* @MAT: starting with this phase, the info of every symbol will be normalized
*/
def transformInfo(sym: Symbol, tp: Type): Type =
- if (sym.isType) uncurryType(tp) else uncurry(tp)
+ if (sym.isType) uncurryType(tp)
+ else if (sym.isMethod && sym.hasFlag(JAVA)) uncurry(repeatedToArray(tp))
+ else uncurry(tp)
/** Traverse tree omitting local method definitions.
* If a `return' is encountered, set `returnFound' to true.
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index fd19bcd8b8..60f6336cd7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -217,7 +217,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
super.transform(tree)
case Apply(fn, args) =>
- assert(fn.tpe != null)
+ assert(fn.tpe != null, tree)
copy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
case Function(vparams, body) =>
withInvalidOwner {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 341131e48c..bce45e4b42 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -127,12 +127,20 @@ trait Typers { self: Analyzer =>
*/
val HKmode = 0x4000 // @M: could also use POLYmode | TAPPmode
+ /** The mode <code>JAVACALLmode</code> is set when we are typing a call to a Java method
+ * needed temporarily for vararg conversions
+ * !!!VARARG-CONVERSION!!!
+ */
+ val JAVACALLmode = 0x8000
+
private val stickyModes: Int = EXPRmode | PATTERNmode | TYPEmode | ALTmode
private def funMode(mode: Int) = mode & (stickyModes | SCCmode) | FUNmode | POLYmode
private def argMode(fun: Tree, mode: Int) =
- if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
+ if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode
+ else if (fun.symbol hasFlag JAVA) mode | JAVACALLmode // !!!VARARG-CONVERSION!!!
+ else mode
private val DivergentImplicit = new Exception()
@@ -1599,8 +1607,31 @@ trait Typers { self: Analyzer =>
val prefix =
List.map2(args take nonVarCount, adaptedFormals take nonVarCount) ((arg, formal) =>
typedArg(arg, mode, 0, formal))
+
+ // if array is passed into java vararg and formal's element is not an array,
+ // convert it to vararg by adding : _*
+ // this is a gross hack to enable vararg transition; remove it as soon as possible.
+ // !!!VARARG-CONVERSION!!!
+ def hasArrayElement(tpe: Type) =
+ tpe.typeArgs.length == 1 && tpe.typeArgs.head.typeSymbol == ArrayClass
+ var args0 = args
+ if ((mode & JAVACALLmode) != 0 &&
+ (args.length == originalFormals.length) &&
+ !hasArrayElement(adaptedFormals(nonVarCount)) &&
+ !settings.XnoVarargsConversion.value) {
+ val lastarg = typedArg(args(nonVarCount), mode, REGPATmode, WildcardType)
+ if (lastarg.tpe.typeSymbol == ArrayClass || lastarg.tpe.typeSymbol == AllRefClass) {
+ unit.warning(
+ lastarg.pos,
+ "I'm seeing an array passed into a Java vararg.\n"+
+ "I assume that the elements of this array should be passed as individual arguments to the vararg.\n"+
+ "Therefore I wrap the array in a `: _*', to mark it as a vararg argument.\n"+
+ "If that's not what you want, compile this file with option -Xno-varargs-conversion.")
+ args0 = args.init ::: List(atPos(lastarg.pos) { Typed(lastarg, Ident(nme.WILDCARD_STAR.toTypeName)) })
+ }
+ }
val suffix =
- List.map2(args drop nonVarCount, adaptedFormals drop nonVarCount) ((arg, formal) =>
+ List.map2(args0 drop nonVarCount, adaptedFormals drop nonVarCount) ((arg, formal) =>
typedArg(arg, mode, REGPATmode, formal))
prefix ::: suffix
} else {
diff --git a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
index dd971bc981..d0702ab969 100644
--- a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
+++ b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
@@ -9,11 +9,16 @@ package scala.tools.nsc.util
import scala.tools.nsc.util.SourceFile.{LF, FF, CR, SU}
class CharArrayReader(buf: RandomAccessSeq[Char], start: Int, /* startline: int, startcol: int, */
- decodeUni: Boolean, error: String => Unit) extends Iterator[Char] {
+ decodeUni: Boolean, error: String => Unit) extends Iterator[Char] with Cloneable {
def this(buf: RandomAccessSeq[Char], decodeUni: Boolean, error: String => Unit) =
this(buf, 0, /* 1, 1, */ decodeUni, error)
+ /** produce a duplicate of this char array reader which starts reading
+ * at current position, independent of what happens to original reader
+ */
+ def dup: CharArrayReader = clone().asInstanceOf[CharArrayReader]
+
/** layout constant
*/
val tabinc = 8
diff --git a/src/partest/scala/tools/partest/PartestTask.scala b/src/partest/scala/tools/partest/PartestTask.scala
index b2990fb4a5..92e9d8e185 100644
--- a/src/partest/scala/tools/partest/PartestTask.scala
+++ b/src/partest/scala/tools/partest/PartestTask.scala
@@ -128,7 +128,7 @@ class PartestTask extends Task {
val antRunner: AnyRef =
classloader.loadClass("scala.tools.partest.nest.AntRunner").newInstance().asInstanceOf[AnyRef]
val antFileManager: AnyRef =
- antRunner.getClass.getMethod("fileManager", Array()).invoke(antRunner, Array())
+ antRunner.getClass.getMethod("fileManager", Array[Class[_]]()).invoke(antRunner, Array[Object]())
val runMethod =
antRunner.getClass.getMethod("reflectiveRunTestsForFiles", Array(classOf[Array[File]], classOf[String]))
diff --git a/src/swing/scala/swing/test/ButtonApp.scala b/src/swing/scala/swing/test/ButtonApp.scala
new file mode 100755
index 0000000000..c6f3e5ec94
--- /dev/null
+++ b/src/swing/scala/swing/test/ButtonApp.scala
@@ -0,0 +1,18 @@
+import swing._, swing.event._
+
+object MyApp extends SimpleGUIApplication {
+ def top = new Frame {
+ title = "My Frame"
+ contents = new GridPanel(2, 2) {
+ hGap = 3
+ vGap = 3
+ contents += new Button {
+ text = "Press Me!"
+ reactions += {
+ case ButtonClicked(_) => text = "Hello Scala"
+ }
+ }
+ }
+ size = (300, 80)
+ }
+}
diff --git a/test/files/jvm5/annotations.scala b/test/files/jvm5/annotations.scala
index 98b82edad4..9af2d333ba 100644
--- a/test/files/jvm5/annotations.scala
+++ b/test/files/jvm5/annotations.scala
@@ -4,7 +4,7 @@ object Test1 {
def foo: Unit = ()
}
def run {
- val method = classOf[Foo].getMethod("foo", Array())
+ val method = classOf[Foo].getMethod("foo")
method.getExceptionTypes foreach println
}
}
@@ -18,7 +18,7 @@ object Test2 {
def read() = in.read()
}
def run {
- val method = classOf[Reader].getMethod("read", Array())
+ val method = classOf[Reader].getMethod("read")
method.getExceptionTypes foreach println
}
}
@@ -41,7 +41,7 @@ object Test3 {
def foo: Unit = ()
}
def run {
- val method = classOf[Foo].getMethod("foo", Array())
+ val method = classOf[Foo].getMethod("foo")
val annotation = method.getAnnotation(classOf[Deprecated])
println(annotation)
}
@@ -133,12 +133,12 @@ object Test5 {
private var count: Integer = 0
private val getter =
- getClass().getMethod("getCount", Array[java.lang.Class[T] forSome { type T }]())
+ getClass().getMethod("getCount")
private val setter =
- getClass().getMethod("setCount", Array(classOf[Integer]))
+ getClass().getMethod("setCount", classOf[Integer])
- def get = getter.invoke(this, Array()).asInstanceOf[Integer].intValue
- def set(n: Int) = setter.invoke(this, Array(new Integer(n)))
+ def get = getter.invoke(this).asInstanceOf[Integer].intValue
+ def set(n: Int) = setter.invoke(this, new Integer(n))
}
def run {
val count = new Count
diff --git a/test/files/jvm5/throws-annot.scala b/test/files/jvm5/throws-annot.scala
index 5f4dac07e8..90b58b9976 100644
--- a/test/files/jvm5/throws-annot.scala
+++ b/test/files/jvm5/throws-annot.scala
@@ -27,7 +27,7 @@ object TestThrows {
}
def checkMethod(cls: Class[_], name: String) {
- val method = cls.getMethod(name, Array())
+ val method = cls.getMethod(name)
println(name + " throws: " + method.getExceptionTypes.mkString("", ", ", ""))
println(name + " annotations: " + method.getDeclaredAnnotations.mkString("", ", ", ""))
}
diff --git a/test/files/neg/t0606.check b/test/files/neg/t0606.check
new file mode 100644
index 0000000000..fb83fca744
--- /dev/null
+++ b/test/files/neg/t0606.check
@@ -0,0 +1,4 @@
+t0606.scala:5: error: private value db escapes its defining scope as part of type Foo.this.db.Info
+ val info = new db.Info
+ ^
+one error found
diff --git a/test/files/neg/t0606.scala b/test/files/neg/t0606.scala
new file mode 100644
index 0000000000..e76ea810e5
--- /dev/null
+++ b/test/files/neg/t0606.scala
@@ -0,0 +1,6 @@
+class Database {
+ class Info
+}
+class Foo(db : Database) {
+ val info = new db.Info
+}