summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.classpath3
-rw-r--r--META-INF/MANIFEST.MF56
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala18
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala32
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala25
-rw-r--r--src/compiler/scala/tools/nsc/ScriptRunner.scala9
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala27
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala32
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala174
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala870
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala535
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala89
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Tokens.scala46
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala29
-rw-r--r--src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala1
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Printers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocDriver.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/ModelFrames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala5
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala2
-rw-r--r--src/compiler/scala/tools/nsc/io/VirtualFile.scala10
-rw-r--r--src/compiler/scala/tools/nsc/io/ZipArchive.scala39
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala4
-rw-r--r--src/compiler/scala/tools/nsc/models/SemanticTokens.scala49
-rw-r--r--src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala26
-rw-r--r--src/compiler/scala/tools/nsc/reporters/Reporter.scala6
-rw-r--r--src/compiler/scala/tools/nsc/reporters/StoreReporter.scala24
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala546
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Scopes.scala22
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala45
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala33
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala94
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala12
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala16
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala38
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala13
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala44
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/LiftCode.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala217
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala26
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala276
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala9
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala49
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala256
-rw-r--r--src/compiler/scala/tools/nsc/util/CharArrayReader.scala16
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala38
-rw-r--r--src/compiler/scala/tools/nsc/util/FreshNameCreator.scala10
-rw-r--r--src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala74
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala43
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala185
-rw-r--r--src/library/scala/collection/jcl/BufferWrapper.scala2
-rw-r--r--src/library/scala/collection/jcl/IterableWrapper.scala4
-rw-r--r--src/library/scala/collection/jcl/Map.scala9
-rw-r--r--src/library/scala/collection/jcl/MapWrapper.scala4
-rw-r--r--src/library/scala/collection/jcl/MutableIterator.scala10
-rw-r--r--src/library/scala/collection/mutable/Map.scala19
-rw-r--r--src/library/scala/runtime/RichString.scala14
-rw-r--r--test/files/neg/abstract.check8
-rw-r--r--test/files/neg/accesses.check8
-rw-r--r--test/files/neg/badtok-1.check7
-rw-r--r--test/files/neg/badtok-2.check9
-rw-r--r--test/files/neg/bug1112.check2
-rw-r--r--test/files/neg/bug1183.check8
-rw-r--r--test/files/neg/bug200.check2
-rw-r--r--test/files/neg/bug391.check8
-rw-r--r--test/files/neg/bug415.check2
-rw-r--r--test/files/neg/bug515.check2
-rw-r--r--test/files/neg/bug520.check2
-rw-r--r--test/files/neg/bug521.check8
-rw-r--r--test/files/neg/bug545.check2
-rw-r--r--test/files/neg/bug550.check2
-rw-r--r--test/files/neg/bug558.check2
-rw-r--r--test/files/neg/bug576.check2
-rw-r--r--test/files/neg/bug585.check4
-rw-r--r--test/files/neg/bug588.check4
-rw-r--r--test/files/neg/bug591.check2
-rw-r--r--test/files/neg/bug630.check2
-rw-r--r--test/files/neg/bug631.check2
-rw-r--r--test/files/neg/bug649.check2
-rw-r--r--test/files/neg/bug663.check2
-rw-r--r--test/files/neg/bug664.check4
-rw-r--r--test/files/neg/bug691.check2
-rw-r--r--test/files/neg/bug696.check4
-rw-r--r--test/files/neg/bug700.check2
-rw-r--r--test/files/neg/bug712.check2
-rw-r--r--test/files/neg/bug715.check2
-rw-r--r--test/files/neg/bug729.check2
-rw-r--r--test/files/neg/bug779.check2
-rw-r--r--test/files/neg/bug836.check2
-rw-r--r--test/files/neg/bug839.check2
-rw-r--r--test/files/neg/bug856.check2
-rw-r--r--test/files/neg/bug876.check2
-rw-r--r--test/files/neg/bug877.check5
-rw-r--r--test/files/neg/bug960.check2
-rw-r--r--test/files/neg/bug961.check2
-rw-r--r--test/files/neg/bug987.check6
-rw-r--r--test/files/neg/bug997.check4
-rw-r--r--test/files/neg/checksensible.check2
-rw-r--r--test/files/neg/constrs.check4
-rw-r--r--test/files/neg/gadts1.check2
-rw-r--r--test/files/neg/overload.check2
-rw-r--r--test/files/neg/sabin2.check2
-rw-r--r--test/files/neg/scopes.check2
-rw-r--r--test/files/neg/tcpoly_variance.check2
-rw-r--r--test/files/neg/typeerror.check2
-rw-r--r--test/files/neg/variances.check2
-rw-r--r--test/files/neg/xmlcorner.check2
-rw-r--r--test/files/neg/xmltruncated1.check6
-rw-r--r--test/files/neg/xmltruncated2.check6
-rw-r--r--test/files/neg/xmltruncated3.check6
-rw-r--r--test/files/neg/xmltruncated4.check6
-rw-r--r--test/files/neg/xmltruncated5.check6
-rw-r--r--test/files/neg/xmltruncated6.check7
-rw-r--r--test/files/res/bug687.check2
127 files changed, 3294 insertions, 1207 deletions
diff --git a/.classpath b/.classpath
index 6494ce68fc..73b2108718 100644
--- a/.classpath
+++ b/.classpath
@@ -4,9 +4,12 @@
<classpathentry exported="true" kind="lib" path="build/quick/lib/compiler/"/>
<classpathentry exported="true" kind="lib" path="lib/fjbg.jar"/>
<classpathentry exported="true" kind="lib" path="lib/msil.jar"/>
+ <classpathentry exported="true" kind="lib" path="lib/jline.jar"/>
<classpathentry exported="true" kind="lib" path="lib/ant-contrib.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry exported="true" kind="lib" path="build/quick/lib/library" sourcepath="src/library"/>
+ <classpathentry exported="true" kind="lib" path="build/quick/lib/actors" sourcepath="src/actors"/>
+ <classpathentry exported="true" kind="lib" path="build/quick/lib/dbc" sourcepath="src/dbc"/>
<classpathentry kind="output" path="build/quick/lib/compiler"/>
</classpath>
diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF
index 65d696ebde..e0625c8cb1 100644
--- a/META-INF/MANIFEST.MF
+++ b/META-INF/MANIFEST.MF
@@ -1,22 +1,68 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: Scala Compiler
-Bundle-SymbolicName: nsc;singleton:=true
-Bundle-Version: 1.0.0
+Bundle-Name: Scala Distribution
+Bundle-SymbolicName: scala;singleton:=true
+Bundle-Version: 2.6.1.B1
Eclipse-LazyStart: true
Bundle-ClassPath: lib/fjbg.jar,
build/quick/lib/library/,
+ build/quick/lib/actors/,
+ build/quick/lib/dbc/,
build/quick/lib/compiler/
Export-Package: ch.epfl.lamp.fjbg,
scala,
+ scala.actors,
+ scala.actors.remote,
scala.collection,
- scala.runtime,
+ scala.collection.jcl,
scala.collection.immutable,
scala.collection.mutable,
- scala.collection.jcl,
+ scala.dbc,
+ scala.dbc.datatype,
+ scala.dbc.exception,
+ scala.dbc.result,
+ scala.dbc.statement,
+ scala.dbc.statement.expression,
+ scala.dbc.syntax,
+ scala.dbc.value,
+ scala.dbc.vendor,
+ scala.compat,
+ scala.concurrent,
+ scala.io,
+ scala.mobile,
+ scala.ref,
+ scala.reflect,
+ scala.runtime,
+ scala.testing,
+ scala.text,
scala.util,
+ scala.util.automata,
+ scala.util.grammar,
+ scala.util.logging,
+ scala.util.parsing,
+ scala.util.parsing.ast,
+ scala.util.parsing.combinator,
+ scala.util.parsing.combinator.lexical,
+ scala.util.parsing.combinator.syntactical,
+ scala.util.parsing.combinator.testing,
+ scala.util.parsing.combinator1,
+ scala.util.parsing.combinator1.lexical,
+ scala.util.parsing.combinator1.syntactical,
+ scala.util.parsing.combinator1.testing,
+ scala.util.parsing.input,
+ scala.util.parsing.json,
+ scala.util.parsing.syntax,
+ scala.util.regexp,
+ scala.xml,
+ scala.xml.dtd,
+ scala.xml.factory,
+ scala.xml.parsing,
+ scala.xml.path,
+ scala.xml.pull,
+ scala.xml.transform,
scala.tools.nsc,
scala.tools.nsc.util,
+ scala.tools.nsc.io,
scala.tools.nsc.typechecker,
scala.tools.nsc.symtab,
scala.tools.nsc.ast,
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 8822f52642..d0d66afb57 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -16,9 +16,8 @@ trait CompilationUnits { self: Global =>
* It typically corresponds to a single file of source code. It includes
* error-reporting hooks. */
class CompilationUnit(val source: SourceFile) extends CompilationUnitTrait {
-
/** the fresh name creator */
- var fresh = new FreshNameCreator
+ var fresh : FreshNameCreator = new FreshNameCreator.Default
/** the content of the compilation unit in tree form */
var body: Tree = EmptyTree
@@ -28,6 +27,9 @@ trait CompilationUnits { self: Global =>
*/
val depends = new HashSet[Symbol]
+ /** used to track changes in a signature */
+ var pickleHash : Long = 0
+
def position(pos: Int) = source.position(pos)
/** The icode representation of classes in this compilation unit.
@@ -38,14 +40,14 @@ trait CompilationUnits { self: Global =>
val errorPositions = new HashSet[Position]
def error(pos: Position, msg: String) =
- if (!(errorPositions contains pos)) {
- errorPositions += pos
+ if (inIDE || !(errorPositions contains pos)) {
+ if (!inIDE) errorPositions += pos
reporter.error((pos), msg)
}
def warning(pos: Position, msg: String) =
- if (!(errorPositions contains pos)) {
- errorPositions += pos
+ if (inIDE || !(errorPositions contains pos)) {
+ if (!inIDE) errorPositions += pos
reporter.warning((pos), msg)
}
@@ -58,8 +60,8 @@ trait CompilationUnits { self: Global =>
else currentRun.uncheckedWarnings = true
def incompleteInputError(pos: Position, msg:String) =
- if (!(errorPositions contains pos)) {
- errorPositions += pos
+ if (inIDE || !(errorPositions contains pos)) {
+ if (!inIDE) errorPositions += pos
reporter.incompleteInputError((pos), msg)
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 26d162cdeb..fa9354dc81 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -12,7 +12,7 @@ import java.nio.charset._
import compat.Platform.currentTime
import scala.tools.nsc.io.{SourceReader, AbstractFile}
import scala.tools.nsc.reporters._
-import scala.tools.nsc.util.{ClassPath, SourceFile}
+import scala.tools.nsc.util.{ClassPath, SourceFile, BatchSourceFile}
import scala.collection.mutable.{HashSet, HashMap, ListBuffer}
@@ -112,9 +112,9 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
else null
// reporting -------------------------------------------------------
-
- def error(msg: String) = reporter.error(null, msg)
- def warning(msg: String) = reporter.warning(null, msg)
+ import nsc.util.NoPosition
+ def error(msg: String) = reporter.error(NoPosition, msg)
+ def warning(msg: String) = reporter.warning(NoPosition, msg)
def inform(msg: String) = Console.err.println(msg)
def inform[T](msg: String, value: T): T = { inform(msg+value); value }
@@ -200,7 +200,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
}
def getSourceFile(f: AbstractFile): SourceFile =
- new SourceFile(f, reader.read(f))
+ new BatchSourceFile(f, reader.read(f))
def getSourceFile(name: String): SourceFile = {
val f = AbstractFile.getFile(name)
@@ -216,7 +216,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
getSourceFile(ret.sourceFile)
}
- object loaders extends SymbolLoaders {
+ val loaders = new SymbolLoaders {
val global: Global.this.type = Global.this
}
@@ -246,6 +246,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
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)
currentRun.advanceUnit
assert(currentRun.currentUnit == unit)
@@ -266,6 +267,10 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
val global: Global.this.type = Global.this
}
+ object generateIdeMaps extends GenerateIdeMaps {
+ val global: Global.this.type = Global.this
+ }
+
object superAccessors extends SuperAccessors {
val global: Global.this.type = Global.this
}
@@ -382,6 +387,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
protected def builtInPhaseDescriptors: List[SubComponent] = List(
analyzer.namerFactory: SubComponent, // note: types are there because otherwise
analyzer.typerFactory: SubComponent, // consistency check after refchecks would fail.
+ generateIdeMaps, // optionally generate .ide files from symbol info that can be used in the IDE
superAccessors, // add super accessors
pickler, // serializes symbol tables
refchecks, // perform reference and override checking, translate nested objects
@@ -503,7 +509,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
private def addUnit(unit: CompilationUnit) {
unitbuf += unit
- fileset += unit.source.getFile()
+ fileset += unit.source.file
}
def units: Iterator[CompilationUnit] = unitbuf.elements
@@ -587,8 +593,11 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
addUnit(unit)
var localPhase = firstPhase.asInstanceOf[GlobalPhase]
while ((localPhase.id < globalPhase.id || localPhase.id <= namerPhase.id) && !reporter.hasErrors) {
+ val oldSource = reporter.getSource
+ reporter.setSource(unit.source)
atPhase(localPhase)(localPhase.applyPhase(unit))
localPhase = localPhase.next.asInstanceOf[GlobalPhase]
+ reporter.setSource(oldSource)
}
refreshProgress
}
@@ -690,6 +699,11 @@ class Global(var settings: Settings, var reporter: Reporter) extends Trees
def forCLDC: Boolean = settings.target.value == "cldc"
def forMSIL: Boolean = settings.target.value == "msil"
def onlyPresentation = settings.doc.value
- // used to disable caching in lampion IDE.
- def inIDE = false
+
+ override def inIDE = false
+ private val unpickleIDEHook0 : (( => Type) => Type) = f => f
+ def unpickleIDEHook : (( => Type) => Type) = unpickleIDEHook0
+ def doPickleHash = false
+ /* hook for IDE to detect source from class dependencies */
+ def attachSourceToClass(clazz : ClassSymbol, tpe : LazyType, sourceFile : AbstractFile) = clazz.sourceFile = sourceFile
}
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 9f0b6ce7ab..06a16075ef 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -17,7 +17,7 @@ import scala.collection.mutable.{ListBuffer, HashSet, ArrayBuffer}
import io.PlainFile
import reporters.{ConsoleReporter, Reporter}
import symtab.Flags
-import util.{ClassPath, SourceFile}
+import util.{SourceFile,BatchSourceFile,ClassPath}
import nsc.{InterpreterResults=>IR}
/** <p>
@@ -59,6 +59,10 @@ import nsc.{InterpreterResults=>IR}
*/
class Interpreter(val settings: Settings, out: PrintWriter) {
import symtab.Names
+
+ /** the compiler to compile expressions with */
+ val compiler: scala.tools.nsc.Global = newCompiler(settings, reporter)
+
import compiler.Traverser
import compiler.{Tree, TermTree,
ValOrDefDef, ValDef, DefDef, Assign,
@@ -70,7 +74,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** construct an interpreter that reports to Console */
def this(settings: Settings) =
- this(settings, new PrintWriter(new ConsoleWriter, true))
+ this(settings,
+ new PrintWriter(new ConsoleWriter, true))
/** whether to print out result lines */
private var printResults: Boolean = true
@@ -95,8 +100,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** directory to save .class files to */
val classfilePath = File.createTempFile("scalaint", "")
- classfilePath.delete() // the file is created as a file; make it a directory
- classfilePath.mkdirs()
+ classfilePath.delete // the file is created as a file; make it a directory
+ classfilePath.mkdirs
/* set up the compiler's output directory */
settings.outdir.value = classfilePath.getPath
@@ -108,10 +113,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** Instantiate a compiler. Subclasses can override this to
* change the compiler class used by this interpreter. */
protected def newCompiler(settings: Settings, reporter: Reporter)
- = new Global(settings, reporter)
+ = new scala.tools.nsc.Global(settings, reporter)
- /** the compiler to compile expressions with */
- val compiler: Global = newCompiler(settings, reporter)
/** the compiler's classpath, as URL's */
val compilerClasspath: List[URL] =
@@ -350,7 +353,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
def simpleParse(code: String): List[Tree] = {
val unit =
new CompilationUnit(
- new SourceFile("<console>", code.toCharArray()))
+ new BatchSourceFile("<console>", code.toCharArray()))
val scanner = new compiler.syntaxAnalyzer.UnitParser(unit);
val xxx = scanner.templateStatSeq;
xxx._2
@@ -384,7 +387,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
* compilation errors, or false otherwise.
*/
def compileString(code: String): Boolean =
- compileSources(List(new SourceFile("<script>", code.toCharArray)))
+ compileSources(List(new BatchSourceFile("<script>", code.toCharArray)))
/** Build a request from the user. <code>trees</code> is <code>line</code>
* after being parsed.
@@ -701,7 +704,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
val objRun = new compiler.Run()
//println("source: "+objectSourceCode) //DEBUG
objRun.compileSources(
- List(new SourceFile("<console>", objectSourceCode.toCharArray))
+ List(new BatchSourceFile("<console>", objectSourceCode.toCharArray))
)
if (reporter.hasErrors) return false
@@ -711,7 +714,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
// compile the result-extraction object
new compiler.Run().compileSources(
- List(new SourceFile("<console>", resultObjectSourceCode.toCharArray))
+ List(new BatchSourceFile("<console>", resultObjectSourceCode.toCharArray))
)
// success
diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala
index 3266ec3799..e8f3cebb99 100644
--- a/src/compiler/scala/tools/nsc/ScriptRunner.scala
+++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala
@@ -14,7 +14,7 @@ import java.util.jar.{JarEntry, JarOutputStream}
import scala.tools.nsc.io.PlainFile
import scala.tools.nsc.reporters.{Reporter,ConsoleReporter}
-import scala.tools.nsc.util.{ClassPath, CompoundSourceFile, SourceFile, SourceFileFragment}
+import scala.tools.nsc.util.{ClassPath, CompoundSourceFile, BatchSourceFile, SourceFile, SourceFileFragment}
/** An object that runs Scala code in script files.
*
@@ -185,18 +185,17 @@ class ScriptRunner {
getSourceFile: PlainFile => SourceFile): SourceFile =
{
val preamble =
- new SourceFile("<script preamble>",
+ new BatchSourceFile("<script preamble>",
preambleCode(objectName).toCharArray)
val middle = {
val f = new File(filename)
new SourceFileFragment(
- getSourceFile(new PlainFile(f)),
+ getSourceFile(new PlainFile(f)).asInstanceOf[BatchSourceFile],
headerLength(filename),
f.length.asInstanceOf[Int])
}
-
- val end = new SourceFile("<script trailer>", endCode.toCharArray)
+ val end = new BatchSourceFile("<script trailer>", "\n} }\n".toCharArray)
new CompoundSourceFile(preamble, middle, end)
}
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index 9f656e7906..52258b3ae6 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -84,21 +84,22 @@ class Settings(error: String => Unit) {
new java.io.ByteArrayOutputStream()).getEncoding
val debuginfo = new DebugSetting ("-g", "Specify level of generated debugging info", List("none", "source", "line", "vars", "notc"), "vars", "vars")
- val nowarnings = BooleanSetting ("-nowarn", "Generate no warnings")
- val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing")
- val deprecation = BooleanSetting ("-deprecation", "Output source locations where deprecated APIs are used")
- val unchecked = BooleanSetting ("-unchecked", "Enable detailed unchecked warnings")
+ val nowarnings = BooleanSetting ("-nowarn", "Generate no warnings").hideToIDE
+ val verbose = BooleanSetting ("-verbose", "Output messages about what the compiler is doing").hideToIDE
+ val deprecation = BooleanSetting ("-deprecation", "Output source locations where deprecated APIs are used").hideToIDE
+ val unchecked = BooleanSetting ("-unchecked", "Enable detailed unchecked warnings").hideToIDE
+ val noide = BooleanSetting ("-noide", "Do not generate class-source mappings that are used by the Scala IDE").hideToIDE
val classpath = new StringSetting ("-classpath", "path", "Specify where to find user class files", classpathDefault) { override val abbreviation = "-cp" }
val sourcepath = StringSetting ("-sourcepath", "path", "Specify where to find input source files", "")
val bootclasspath = StringSetting ("-bootclasspath", "path", "Override location of bootstrap class files", bootclasspathDefault)
val extdirs = StringSetting ("-extdirs", "dirs", "Override location of installed extensions", extdirsDefault)
val outdir = StringSetting ("-d", "directory", "Specify where to place generated class files", ".")
- val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files", encodingDefault).showToIDE
+ val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files", encodingDefault)
val target = ChoiceSetting ("-target", "Specify for which target object files should be built", List("jvm-1.5", "jvm-1.4", "msil", "cldc"), "jvm-1.4")
- val printLate = BooleanSetting ("-print", "Print program with all Scala-specific features removed")
+ val printLate = BooleanSetting ("-print", "Print program with all Scala-specific features removed").hideToIDE
val XO = BooleanSetting ("-optimise", "Generates faster bytecode by applying optimisations to the program")
- val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail")
- val uniqid = BooleanSetting ("-uniqid", "Print identifiers with unique names for debugging")
+ val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail").hideToIDE
+ val uniqid = BooleanSetting ("-uniqid", "Print identifiers with unique names for debugging").hideToIDE
val version = BooleanSetting ("-version", "Print product version and exit").hideToIDE
val help = BooleanSetting ("-help", "Print a synopsis of standard options").hideToIDE
val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options").hideToIDE
@@ -113,18 +114,18 @@ class Settings(error: String => Unit) {
val Xplugtypes = BooleanSetting ("-Xplug-types", "Process annotations on types")
val plugin = MultiStringSetting("-Xplugin", "file", "Load a plugin from a file")
val disable = MultiStringSetting("-Xplugin-disable", "plugin", "Disable a plugin")
- val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins")
+ val showPlugins = BooleanSetting ("-Xplugin-list", "Print a synopsis of loaded plugins").hideToIDE
val pluginOptions = new MultiStringSetting("-P", "plugin:opt", "Pass an option to a plugin") { override def helpSyntax = "-P:<plugin>:<opt>" }
val require = MultiStringSetting("-Xplugin-require", "plugin", "Abort unless a plugin is available")
val pluginsDir = StringSetting ("-Xpluginsdir", "path", "Location to find compiler plugins", pluginsDirDefault)
val print = PhasesSetting ("-Xprint", "Print out program after")
- val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions (as offsets)")
+ val Xprintpos = BooleanSetting ("-Xprint-pos", "Print tree positions (as offsets)").hideToIDE
val printtypes = BooleanSetting ("-Xprint-types", "Print tree types (debugging option)").hideToIDE
val prompt = BooleanSetting ("-Xprompt", "Display a prompt after each error (debugging option)").hideToIDE
val resident = BooleanSetting ("-Xresident", "Compiler stays resident, files to compile are read from standard input").hideToIDE
val Xshowcls = StringSetting ("-Xshow-class", "class", "Show class info", "")
val Xshowobj = StringSetting ("-Xshow-object", "object", "Show object info", "")
- val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases")
+ val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases").hideToIDE
val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files", "scala.tools.nsc.io.SourceReader")
val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options").hideToIDE
@@ -141,12 +142,12 @@ class Settings(error: String => Unit) {
val inline = BooleanSetting ("-Yinline", "Perform inlining when possible")
val Xlinearizer = ChoiceSetting ("-Ylinearizer", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
val log = PhasesSetting ("-Ylog", "Log operations in")
- val logAll = BooleanSetting ("-Ylog-all", "Log all operations")
+ val logAll = BooleanSetting ("-Ylog-all", "Log all operations").hideToIDE
val Xmatchalgo = ChoiceSetting ("-Ymatch-algo", "which match algorithm to use", List("both","par","incr"), "both")
val noimports = BooleanSetting ("-Yno-imports", "Compile without any implicit imports")
val nopredefs = BooleanSetting ("-Yno-predefs", "Compile without any implicit predefined values")
val script = StringSetting ("-Xscript", "object", "compile as a script, wrapping the code into object.main()", "").hideToIDE
- val Xshowtrees = BooleanSetting ("-Yshow-trees", "Show detailed trees when used in connection with -print:phase")
+ val Xshowtrees = BooleanSetting ("-Yshow-trees", "Show detailed trees when used in connection with -print:phase").hideToIDE
val skip = PhasesSetting ("-Yskip", "Skip")
val Xsqueeze = ChoiceSetting ("-Ysqueeze", "if on, creates compact code in matching", List("on","on","off"), "on")
val statistics = BooleanSetting ("-Ystatistics", "Print compiler statistics").hideToIDE
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 1533013e21..05c65f4671 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -223,7 +223,8 @@ abstract class NodePrinters {
printcln("Super(\"" + qual + "\", \"" + mix + "\")" + nodeinfo2(tree))
case Template(parents, self, body) =>
println("Template(" + nodeinfo(tree))
- println(" " + parents.map(p => p.tpe.typeSymbol) + ", // parents")
+ println(" " + parents.map(p => if (p.tpe ne null) p.tpe.typeSymbol else "null-" + p) + ", // parents")
+ traverse(self, level + 2, true)
if (body.isEmpty)
println(" List() // no body")
else {
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index ef29cf04f9..2fa44c2dc8 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -293,7 +293,7 @@ abstract class TreePrinters {
print(fun); printRow(targs, "[", ", ", "]")
case Apply(fun, vargs) =>
- print(fun); printRow(vargs, "(", ", ", ")")
+ print(fun); print(vargs.mkString("(", ",", ")")) // printRow(vargs, "(", ", ", ")")
case ApplyDynamic(qual, vargs) =>
print("<apply-dynamic>("); print(qual); print("#"); print(tree.symbol.nameString)
@@ -362,6 +362,7 @@ abstract class TreePrinters {
print(tpt);
printColumn(whereClauses, " forSome { ", ";", "}")
+ case tree : StubTree => print(tree.toString)
case tree =>
print("<unknown tree of class "+tree.getClass+">")
}
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index acd3805ee7..1949c4cc7c 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -157,6 +157,26 @@ abstract class Trees extends SymbolTable {
case t: Tree => this eq t
case _ => false
}
+ def hashCodeStructure : Int = {
+ var hc = getClass.hashCode
+ def f(what : Any) : Unit = what match {
+ case what : Tree => hc += what.hashCodeStructure
+ case what : Iterable[_] => what.foreach(f)
+ case what : Product => g(what)
+ case null =>
+ case what => hc += what.hashCode
+ }
+ def g(what : Product) : Unit = {
+ hc += what.productArity
+ var i = 0
+ while (i < what.productArity) {
+ f(what.productElement(i))
+ i += 1
+ }
+ }
+ g(this.asInstanceOf[Product])
+ hc
+ }
def equalsStructure(that: Tree): Boolean = {
if (this == that) return true
@@ -181,8 +201,7 @@ abstract class Trees extends SymbolTable {
val results = for (i <- 0.until(this0.productArity).toList) yield
equals0(this0.productElement(i), that0.productElement(i))
val b = results.foldLeft(true)((x,y) => x && y)
- b && (if (tpe == null || tpe == NoType) that.tpe == null || that.tpe == NoType
- else tpe == that.tpe)
+ b // ignore type!
}
def duplicate: this.type =
@@ -465,6 +484,10 @@ abstract class Trees extends SymbolTable {
extends Tree {
override def symbol: Symbol = definition.symbol
override def symbol_=(sym: Symbol) { definition.symbol = sym }
+ // sean: seems to be important to the IDE
+ override def isDef = definition.isDef
+ override def isTerm = definition.isTerm
+ override def isType = definition.isType
}
/** Instantiation template
@@ -759,6 +782,9 @@ abstract class Trees extends SymbolTable {
case class ExistentialTypeTree(tpt: Tree, whereClauses: List[Tree])
extends TypTree
+ trait StubTree extends Tree {
+ override def equalsStructure(that: Tree): Boolean = this eq that
+ }
/* A standard pattern match
case EmptyTree =>
case PackageDef(name, stats) =>
@@ -1325,6 +1351,7 @@ abstract class Trees extends SymbolTable {
copy.TypeBoundsTree(tree, transform(lo), transform(hi))
case ExistentialTypeTree(tpt, whereClauses) =>
copy.ExistentialTypeTree(tree, transform(tpt), transformTrees(whereClauses))
+ case tree : StubTree => tree.duplicate
}
def transformTrees(trees: List[Tree]): List[Tree] =
@@ -1467,6 +1494,7 @@ abstract class Trees extends SymbolTable {
traverse(lo); traverse(hi)
case ExistentialTypeTree(tpt, whereClauses) =>
traverse(tpt); traverseTrees(whereClauses)
+ case tree : StubTree =>
}
def traverseTrees(trees: List[Tree]) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 038d993c45..a6c3d85d71 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc.ast.parser
import scala.collection.mutable
-import scala.tools.nsc.util.{Position,SourceFile}
+import scala.tools.nsc.util.{Position,NoPosition,SourceFile}
import scala.xml.{Text, TextBuffer}
import SourceFile.{SU,LF}
@@ -16,9 +16,7 @@ import SourceFile.{SU,LF}
* @author Burak Emir
* @version 1.0
*/
-trait MarkupParsers {
- self: SyntaxAnalyzer =>
-
+trait MarkupParsers {self: Parsers =>
case object MissingEndTagException extends RuntimeException {
override def getMessage = "start tag was here: "
}
@@ -34,32 +32,21 @@ trait MarkupParsers {
import global._
//import posAssigner.atPos
- class MarkupParser(p: UnitParser, presWS: Boolean) /*with scala.xml.parsing.MarkupParser[Tree,Tree] */{
+ class MarkupParser(parser: UnitParser, presWS: Boolean) /*with scala.xml.parsing.MarkupParser[Tree,Tree] */{
import Tokens.{EMPTY, LBRACE, RBRACE}
+ import parser.i2p
final val preserveWS = presWS
+ var input : ScannerInput = _
- import p.{symbXMLBuilder => handle}
- def s = p.in
- import p.in.g2p
- import p.in.p2g
- import p.in.token
-
- /** holds the position in the source file */
- /*[Duplicate]*/ var pos: Position = _
-
- /** holds temporary values of pos */
- /*[Duplicate]*/ var tmppos: Position = _
-
- /** holds the next character */
- /*[Duplicate]*/ var ch: Char = _
+ import parser.{symbXMLBuilder => handle}
- /** character buffer, for names */
- /*[Duplicate]*/ protected val cbuf = new StringBuilder()
-
- /** append Unicode character to name buffer*/
- /*[Duplicate]*/ protected def putChar(c: Char) = cbuf.append(c)
+ def pos : Int = input.offset
+ var tmppos : Position = NoPosition
+ def ch = input.head
+ /** this method assign the next character to ch and advances in input */
+ def nextch = input.next // { s.in.next; /*s.xNext;*/ ch = s.in.ch ; pos = s.in.cpos }
/*[Duplicate]*/ var xEmbeddedBlock = false
@@ -74,7 +61,7 @@ trait MarkupParsers {
else reportSyntaxError("'" + that + "' expected instead of '" + ch + "'")
}
- var debugLastStartElement = new mutable.Stack[(Position, String)]
+ var debugLastStartElement = new mutable.Stack[(Int, String)]
/** checks whether next character starts a Scala block, if yes, skip it.
* @return true if next character starts a scala block
@@ -109,7 +96,7 @@ trait MarkupParsers {
} catch {
case e =>
reportSyntaxError("error parsing attribute value")
- p.errorTermTree
+ parser.errorTermTree
}
case '{' =>
@@ -138,14 +125,14 @@ trait MarkupParsers {
* @param endch either ' or "
*/
/*[Duplicate]*/ def xAttributeValue(endCh: Char): String = {
+ val buf = new StringBuilder
while (ch != endCh) {
if (ch == SU)
throw TruncatedXML
- putChar(ch)
- nextch
+ buf append nextch
}
- val str = cbuf.toString()
- cbuf.length = 0
+ val str = buf.toString()
+
// @todo: normalize attribute value
// well-formedness constraint
if (str.indexOf('<') != -1) {
@@ -430,20 +417,19 @@ trait MarkupParsers {
/*[Duplicate]*/ def xName: String = {
if (ch == SU) {
throw TruncatedXML
- } else if ( !xml.Parsing.isNameStart(ch)) {
reportSyntaxError("name expected, but char '"+ch+"' cannot start a name")
return ""
}
+ val buf = new StringBuilder
do {
- putChar(ch)
- nextch
+ buf append nextch
} while (xml.Parsing.isNameChar(ch))
- if (':' == cbuf.charAt(cbuf.length-1)) {
+ if (':' == buf.last) {
reportSyntaxError( "name cannot end in ':'" )
- cbuf.length = cbuf.length - 1
+ buf.setLength(buf.length - 1)
}
- val n = cbuf.toString().intern()
- cbuf.length = 0
+ val n = buf.toString().intern()
+ //cbuf.length = 0
n
}
@@ -494,8 +480,9 @@ trait MarkupParsers {
// return ""
//} else {
var exit = false
+ val buf = new StringBuilder
while (!exit && (ch!=SU)) {
- putChar(ch)
+ buf append ch
val expectRBRACE = ch == '}'
// TODO check for "}}"
nextch
@@ -509,8 +496,8 @@ trait MarkupParsers {
}
exit = xCheckEmbeddedBlock ||(ch == '<') || (ch == '&')
}
- val str = cbuf.toString()
- cbuf.length = 0
+ val str = buf.toString()
+ //cbuf.length = 0
str
//}
}
@@ -525,64 +512,55 @@ trait MarkupParsers {
* precondition: s.xStartsXML == true
*/
def xLiteral: Tree = try {
- init; pushScannerState
+ input = parser.in.flush
handle.isPattern = false
- val pos = s.currentPos
- var lastend = 0
- var lastch = ch
+
+ //val pos = s.currentPos
var tree:Tree = null
val ts = new mutable.ArrayBuffer[Tree]()
- tmppos = pos // Iuli: added this line, as it seems content_LT uses tmppos when creating trees
+ tmppos = (pos) // Iuli: added this line, as it seems content_LT uses tmppos when creating trees
+ assert(nextch == '<')
content_LT(ts)
//Console.println("xLiteral:ts = "+ts.toList)
- lastend = s.in.bp
- lastch = s.in.ch
+ //lastend = s.in.bp
+ //lastch = s.in.ch
//if (settings.debug.value) {
// Console.println("DEBUG 1: I am getting char '"+ch+"' at lastend "+lastend+" pos = "+pos); // DEBUG
//}
+ val save = input.offset
xSpaceOpt
// parse more XML ?
if (ch == '<') {
- //val ts = new mutable.ArrayBuffer[Tree]();
- //ts.append( tree );
while (ch == '<') {
nextch
ts.append(element)
- lastend = s.in.bp
- lastch = s.in.ch
xSpaceOpt
}
tree = handle.makeXMLseq((pos), ts)
+ parser.in.resume(Tokens.XMLSTART)
} else {
+ parser.in.seek(save, Tokens.XMLSTART)
assert(ts.length == 1)
tree = ts(0)
}
- s.in.bp = lastend // ugly hack
- s.in.ch = lastch
- //if (settings.debug.value) {
- // Console.println("DEBUG 2: restoring char '"+lastch+"' at lastend "+lastend+" pos = "+pos); // DEBUG
- //}
- //Console.println("out of xLiteral, parsed:"+tree.toString());
- s.next.token = Tokens.EMPTY;
- s.nextToken
- popScannerState
tree
- }
- catch {
+ } catch {
case c @ TruncatedXML =>
- s.incompleteInputError(s.in.cpos-1, c.getMessage)
- s.nextToken
+ parser.incompleteInputError(c.getMessage)
+ parser.in.resume(Tokens.XMLSTART)
EmptyTree
case c @ (MissingEndTagException | ConfusedAboutBracesException) =>
- p.syntaxError((debugLastStartElement.top._1),
- c.getMessage + debugLastStartElement.top._2+">")
+ parser.syntaxError((debugLastStartElement.top._1):Int,
+ c.getMessage + debugLastStartElement.top._2+">")
+ parser.in.resume(Tokens.XMLSTART)
EmptyTree
case _:ArrayIndexOutOfBoundsException =>
- p.syntaxError((debugLastStartElement.top._1),
+ parser.syntaxError((debugLastStartElement.top._1),
"missing end tag in XML literal for <"
+debugLastStartElement.top._2+">");
+ parser.in.resume(Tokens.XMLSTART)
EmptyTree
}
@@ -591,92 +569,96 @@ trait MarkupParsers {
* precondition: s.xStartsXML == true
*/
def xLiteralPattern: Tree = try {
- init; pushScannerState
+ input = parser.in.flush
val oldMode = handle.isPattern;
handle.isPattern = true
+ assert(nextch == '<')
var tree = xPattern; xSpaceOpt;
handle.isPattern = oldMode;
- s.next.token = Tokens.EMPTY;
- s.nextToken
- popScannerState
+ parser.in.resume(Tokens.XMLSTART)
tree
} catch {
case c @ TruncatedXML =>
- s.incompleteInputError(s.in.cpos-1, c.getMessage)
- s.nextToken
+ parser.syntaxError(pos - 1, c.getMessage)
+ //s.nextToken
+ parser.in.resume(Tokens.XMLSTART)
EmptyTree
case c @ (MissingEndTagException | ConfusedAboutBracesException) =>
- p.syntaxError((debugLastStartElement.top._1),
+ parser.syntaxError((debugLastStartElement.top._1),
c.getMessage + debugLastStartElement.top._2+">")
EmptyTree
case _:ArrayIndexOutOfBoundsException =>
- p.syntaxError((debugLastStartElement.top._1),
+ parser.syntaxError((debugLastStartElement.top._1),
"missing end tag in XML literal for <"
+debugLastStartElement.top._2+">")
EmptyTree
}
def xEmbeddedExpr: Tree = {
- sync
- val b = p.block() //p.expr(true,false);
- if (s.in.ch == SU)
- throw TruncatedXML
- if (/*s.*/token != RBRACE) {
+ xEmbeddedBlock = false
+ parser.in.resume(LBRACE)
+ val b = parser.block() //p.expr(true,false);
+ if (parser.in.token != RBRACE) {
+ input = parser.in.flush
reportSyntaxError(" expected end of Scala block")
+ } else {
+ input = parser.in.flush
+ assert(nextch == '}')
}
- init
b
}
/** xScalaPatterns ::= patterns
*/
def xScalaPatterns: List[Tree] = {
- sync
- val b = p.patterns(true)
- if (s.in.ch == SU)
- throw TruncatedXML
- if (/*s.*/token != RBRACE) {
- reportSyntaxError(" expected end of Scala patterns")
+ xEmbeddedBlock = false
+ parser.in.resume(LBRACE)
+ val b = parser.patterns(true)
+ if (parser.in.token != RBRACE) {
+ input = parser.in.flush
+ reportSyntaxError(" expected end of Scala pattern")
+ } else {
+ input = parser.in.flush
+ assert(nextch == '}')
}
- init
b
}
//var ch: Char = _;
- /** this method assign the next character to ch and advances in input */
- def nextch { s.in.next; /*s.xNext;*/ ch = s.in.ch ; pos = s.in.cpos }
//def lookahead = { s.xLookahead }
var scannerState: List[List[Int]] = Nil
+/*
private def pushScannerState {
scannerState = s.sepRegions :: scannerState
s.sepRegions = Nil
}
-
private def popScannerState {
s.sepRegions = scannerState.head
scannerState = scannerState.tail
}
-
+ */
+/*
private def init {
ch = s.in.ch
pos = s.in.cpos
}
+ */
def reportSyntaxError(str: String) = {
- p.syntaxError(pos-1, "in XML literal: " + str)
+ parser.syntaxError(pos - 1, "in XML literal: " + str)
nextch
}
-
+/*
private def sync {
xEmbeddedBlock = false
s.xSync
}
-
+*/
/** '<' xPattern ::= Name [S] { xmlPattern | '{' pattern3 '}' } ETag
* | Name [S] '/' '>'
*/
@@ -710,7 +692,7 @@ trait MarkupParsers {
}
case '{' => // embedded Scala patterns
while (ch == '{') {
- s.in.next
+ nextch
ts ++= xScalaPatterns
}
// postcond: xEmbeddedBlock = false;
diff --git a/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala b/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala
new file mode 100644
index 0000000000..8b312cab1d
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/parser/NewScanners.scala
@@ -0,0 +1,870 @@
+package scala.tools.nsc.ast.parser
+import scala.tools.nsc.util.SourceFile._
+import scala.tools.nsc.util._
+
+trait NewScanners {
+ val global : Global
+ import global._
+ import Tokens._
+ trait CoreScannerInput extends BufferedIterator[Char] {
+ private[NewScanners] val scratch = new StringBuilder
+ def readIfStartsWith(c : Char) : Boolean =
+ if (head == c) { next; true } else false
+ def readIfStartsWith(c0 : Char, c1 : Char) : Boolean =
+ if (head == c0 && peek(1) == c1) {
+ next; next; true
+ } else false
+ def startsWith(c0: Char, c1 : Char) : Boolean = head == c0 && peek(1) == c1
+ def isUnicode : Boolean
+
+ def peek(idx : Int) : Char
+
+ def offset : Int
+ def error(offset : Int, msg : String) : Unit
+ def textFor(from : Int, until : Int) : RandomAccessSeq[Char]
+ }
+ trait ScannerInput extends CoreScannerInput {
+ def seek(offset : Int) : Unit
+ }
+ class DefaultInput(in : NewCharArrayReader) extends ScannerInput {
+ import scala.collection.mutable._
+ def seek(offset : Int) = in.seek(offset)
+ def offset = in.offset
+ def head = peek(0)
+ def next = in.next
+ def isUnicode : Boolean = in.isUnicode
+ def hasNext = in.hasNext
+ def peek(idx : Int) = {
+ val offset = in.offset
+ var jdx = idx
+ var result = in.next
+ while (jdx > 0) {
+ jdx = jdx - 1
+ result =in.next
+ }
+ in.seek(offset) // jump back to old position
+ result
+ }
+ def error(offset : Int, msg : String) : Unit = {}
+ def textFor(from : Int, until : Int) = in.buf.slice(from, until).mkString
+ }
+
+ abstract class ParserScanner extends BaseScanner {
+ def init = nextToken
+
+ private var doc : String = ""
+ var sepRegions : List[Int] = Nil
+ private val current = new TokenHolder
+ private val next = new TokenHolder
+ implicit def in : ScannerInput
+
+ var lastCode = EMPTY
+ next.code = EMPTY
+ current.code = EMPTY
+ def hasNext = in.hasNext || (next.code != EMPTY && next.code != EOF)
+ def flush : ScannerInput = {
+ assert(current.code != EMPTY)
+ in.seek(unadjust(current.offset))
+ current.code = EMPTY
+ next.code = EMPTY
+ in
+ }
+ def seek(offset : Int, lastCode : Int) = {
+ assert(current.code == EMPTY)
+ in.seek(unadjust(offset))
+ this.lastCode = lastCode
+ nextToken
+ }
+ def resume(lastCode : Int) = {
+ assert(current.code == EMPTY)
+ this.lastCode = lastCode
+ nextToken
+ }
+ /** read next token and return last position
+ */
+ def skipToken: Int = {
+ val p = current.offset; nextToken
+ // XXX: account for off by one error //???
+ p
+ }
+ def currentPos = {
+ assert(current.code != EMPTY)
+ current.offset
+ }
+ def fillNext : Boolean = {
+ assert(next.code == EMPTY)
+ var hasNewline = false
+ do {
+ fill(next)
+ } while (next.code match {
+ case NEWLINE|NEWLINES|WHITESPACE|COMMENT =>
+ assert((next.code != COMMENT) == (xmlOk))
+ hasNewline = hasNewline || next.code == NEWLINE || next.code == NEWLINES
+ if (next.code == COMMENT)
+ doc = next.value.asInstanceOf[Option[String]].getOrElse("")
+ true
+ case _ => false
+ })
+ hasNewline
+ }
+ def flushDoc = {
+ val ret = doc
+ doc = ""
+ ret
+ }
+
+ def nextToken : Unit = {
+ if (current.code == EOF) return // nothing more.
+ var lastIsComment = false
+ lastCode = current.code match {
+ case WHITESPACE|EMPTY => lastCode
+ case COMMENT => lastIsComment = true; lastCode
+ case code => code
+ }
+ // push on braces
+ val pushOn = current.code match {
+ case LBRACE => RBRACE
+ case LPAREN => RPAREN
+ case LBRACKET => RBRACKET
+ case CASE => ARROW
+ case RBRACE =>
+ while (!sepRegions.isEmpty && sepRegions.head != RBRACE)
+ sepRegions = sepRegions.tail
+ if (!sepRegions.isEmpty)
+ sepRegions = sepRegions.tail
+ EMPTY
+ case code @ (ARROW) if (!sepRegions.isEmpty && sepRegions.head == code) =>
+ sepRegions = sepRegions.tail
+ EMPTY
+ case code @ (RPAREN|RBRACKET) =>
+ if (!sepRegions.isEmpty && sepRegions.head == code)
+ sepRegions = sepRegions.tail
+ EMPTY
+ case _ => EMPTY
+ }
+ if (pushOn != EMPTY) sepRegions = pushOn :: sepRegions
+
+ if (next.code != EMPTY) {
+ current.copy(next)
+ next.code = EMPTY
+ } else fill(current)
+
+ def currentIsNext : Unit = {
+ assert(next.code != EMPTY)
+ return nextToken
+ }
+ current.code match {
+ case CASE|SEMI =>
+ fillNext
+ (current.code,next.code) match {
+ case (CASE,OBJECT) =>
+ assert(true)
+ current.code = CASEOBJECT; next.code = EMPTY
+ case (CASE, CLASS) => current.code = CASECLASS ; next.code = EMPTY
+ case (SEMI, ELSE ) => currentIsNext
+ case _ =>
+ }
+ case WHITESPACE|COMMENT =>
+ if (current.code == COMMENT)
+ doc = current.value.asInstanceOf[Option[String]].getOrElse("")
+ nextToken
+ case NEWLINE | NEWLINES =>
+ assert(xmlOk)
+ val headIsRBRACE = if (sepRegions.isEmpty) true else sepRegions.head == RBRACE
+ val hasNewline = fillNext
+ if (headIsRBRACE && ((inLastOfStat(lastCode) && inFirstOfStat(next.code)) || next.code == EOF)) {
+ //if (hasNewline) current.code = NEWLINES
+ } else {
+ currentIsNext
+ }
+ case _ =>
+ }
+ }
+ def token = {
+ assert(current.code != EMPTY)
+ current.code
+ }
+ def nextTokenCode = {
+ if (next.code == EMPTY) fillNext
+ next.code
+ }
+ def name = current.value.get.asInstanceOf[Name]
+ def charVal = current.value.get.asInstanceOf[Char]
+ def intVal(negated : Boolean) : Long = {
+ val base = current.value.asInstanceOf[Option[Int]].getOrElse(10)
+ intVal(current.offset, current.code, current.nLit(this), negated, base)
+ }
+ def intVal : Long = intVal(false)
+ def floatVal(negated: Boolean): Double = {
+ floatVal(current.offset, current.code, current.nLit(this), negated)
+ }
+ def floatVal : Double = floatVal(false)
+ def stringVal = current.value.get.asInstanceOf[String]
+ }
+
+ class TokenHolder {
+ var offset : Int = 0
+ var code : Int = 0
+ var length : Int = 0
+ var value : Option[Any] = None
+ def copy(from : TokenHolder) = {
+ this.offset = from.offset
+ this.code = from.code
+ this.length = from.length
+ this.value = from.value
+ }
+ def set(offset : Int, length : Int, code : Int) = {
+ this.offset = offset; this.length = length; this.code = code; this.value = None
+ }
+ def set(offset : Int, length : Int, code : Int, value : Any) = {
+ this.offset = offset; this.length = length; this.code = code; this.value = Some(value)
+ }
+ def nLit(implicit in : BaseScanner) = (in.in.textFor(in.unadjust(offset), in.unadjust(offset + length)))
+ }
+
+ trait BaseScanner {
+ implicit def in : CoreScannerInput
+ ScannerConfiguration.hashCode // forces initialization
+ import ScannerConfiguration._
+ var xmlOk = false
+
+ def iterator = new Iterator[(Int,Int,Int)] { // offset,length,code
+ val current = new TokenHolder
+ def hasNext = in.hasNext
+ def next = {
+ fill(current)
+ (current.offset, current.length, current.code)
+ }
+ }
+ // IDE hooks
+ def adjust(offset : Int) = offset
+ def unadjust(offset : Int) = offset
+ def identifier(name : Name) = name
+
+ protected def fill(current : TokenHolder) : Unit = {
+ if (!in.hasNext) {
+ current.offset = adjust(in.offset)
+ current.code = EOF
+ return
+ }
+ val oldXmlOk = xmlOk
+ xmlOk = false
+ val offset = in.offset // call "after" next
+ def escapeCode(offset : Int) : Char = in.next match {
+ case c if simpleEscape.isDefinedAt(c) => simpleEscape(c)
+ case c if isDigit(c) =>
+ val length = in.scratch.length
+ try {
+ assert(isDigit(c))
+ in.scratch append c
+ while (isDigit(in.head)) in.scratch append in.next
+ val n = Integer.parseInt(in.scratch.drop(length).mkString, 8)
+ if (n > 0377) {
+ in.error(offset, "malformed octal character code"); 0.toChar
+ } else n.toChar
+ } catch {
+ case ex : Exception => in.error(offset, "malformed octal character code"); 0.toChar
+ } finally {
+ in.scratch.setLength(length)
+ }
+ case c => in.error(offset, "unrecognized escape code \'" + c + "\'"); c
+ }
+ def getIdentRest : Unit = in.readIf{
+ case '_' =>
+ in.scratch append '_'
+ val c = in.head
+ if (isOperatorPart(c)) getOperatorRest else getIdentRest
+ case c if isIdentifierPart(c) =>
+ in.scratch append c; getIdentRest
+ }
+
+ val next = in.next
+ // called after everything is read.
+ def length = in.offset - offset
+
+ def value(code : Int, value : Any) : Int = {
+ current.value = Some(value)
+ code
+ }
+ def doOperator(c : Char) = {
+ in.scratch.setLength(0)
+ in.scratch append(c)
+ getOperatorRest
+ val name : Name = global.newTermName(in.scratch.toString)
+ value(name2token(name), (name))
+ }
+ current.offset = adjust(offset)
+ current.value = None
+ current.code = next match {
+ case ';' => (SEMI)
+ case ',' => (COMMA)
+ case '(' => xmlOk = true; (LPAREN)
+ case ')' => (RPAREN)
+ case '{' => xmlOk = true; (LBRACE)
+ case '}' => (RBRACE)
+ case '[' => (LBRACKET)
+ case ']' => (RBRACKET)
+ case SU => EOF
+ case '\u21D2' => (ARROW)
+ case '<' =>
+ if (oldXmlOk && (in.head match {
+ case ('!' | '?') => true
+ case c if xml.Parsing.isNameStart(c) => true
+ case _ => false
+ })) { in.next; XMLSTART }
+ else doOperator('<')
+ case ' ' | '\t' => in.readWhile(isSpace); xmlOk = true; (WHITESPACE)
+ case '/' =>
+ if (in.readIfStartsWith('/')) {
+ while (in.hasNext && !isNewLine(in.head)) in.next
+ (COMMENT)
+ } else if (in.readIfStartsWith('*')) {
+ val emptyOrDoc = in.readIfStartsWith('*')
+ val empty = emptyOrDoc && in.readIfStartsWith('/')
+ val isDoc = emptyOrDoc && !empty
+
+ if (isDoc)
+ in.scratch setLength 0
+
+ var count = 0
+ if (!empty) while (count != -1) in.next match {
+ case SU => in.error(offset, "unterminated comment"); count = -1
+ case '*' if in.readIfStartsWith('/') => count -= 1
+ case '/' if in.readIfStartsWith('*') => count += 1
+ case c =>
+ if (isDoc) in.scratch append c
+ }
+ if (!isDoc) (COMMENT) else value(COMMENT, in.scratch.toString)
+ } else doOperator('/')
+ case c @ ('~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | /* '<' | | '/' */
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '\\') => doOperator(c)
+ case c @
+ ('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') =>
+ in.scratch.setLength(0)
+ in.scratch.append(c : Char)
+ getIdentRest
+ val name = global.newTermName(in.scratch.toString)
+ in.scratch.setLength(0)
+ val code = name2token(name)
+ if (code == IDENTIFIER) value(code, identifier(name))
+ else value(code, (name))
+ case '0' =>
+ if (in.head match {
+ case 'x' | 'X' => true
+ case _ => false
+ }) { in.next; value(getNumber(offset, 16, "0x"), 16) }
+ else value(getNumber(offset, 8, "0"), 8)
+ case '1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => getNumber(offset, 10, "")
+ case '.' =>
+ val frac = getFraction(false)
+ val code = (frac getOrElse DOT)
+ code
+ case '\'' =>
+ def endQ(cvalue : Char) : Int = {
+ if (!in.readIfStartsWith('\'')) {
+ in.error(offset, "missing terminating quote")
+ }
+ value(CHARLIT, cvalue)
+ }
+ in.next match {
+ case CR|LF|FF|SU|EOF if !in.isUnicode =>
+ in.error(offset, "unterminated character literal")
+ value(CHARLIT, 0.toChar)
+ case '\'' =>
+ in.error(offset, "empty character literal")
+ value(CHARLIT, 0.toChar)
+ case c if (Character.isUnicodeIdentifierStart(c)||isIdentifierPart(c)||isOperatorPart(c)) && in.head != '\'' => // symbol
+ in.scratch.setLength(0)
+ in.scratch append c
+ in.readWhile(c => isIdentifierPart(c) || isOperatorPart(c))
+ if (in.readIfStartsWith('\'')) in.error(offset, "unexpected quote after symbol")
+ value(SYMBOLLIT, in.scratch.toString)
+ case '\\' => endQ(escapeCode(offset))
+ case c => endQ(c)
+ }
+ case '\"' =>
+ if (in.readIfStartsWith('\"')) {
+ if (in.readIfStartsWith('\"')) {
+ // multiline
+ in.scratch setLength 0
+ while (in.next match {
+ case SU if !in.isUnicode => in.error(offset, "unterminated multi-line string"); false
+ case '\"' if in.readIfStartsWith('\"') =>
+ if (in.readIfStartsWith('\"')) false
+ else {
+ in.scratch append "\"\""; true
+ }
+ case '\\' if false => // XXX: not for multi-line strings?
+ in.scratch append escapeCode(in.offset - 1)
+ true
+ case c => in.scratch append c; true
+ }) {}
+ val ret = value(STRINGLIT, in.scratch.toString)
+ in.scratch setLength 0
+ ret
+ } else value(STRINGLIT, "")
+ } else {
+ in.scratch setLength 0
+ while (in.next match {
+ case '\"' => false
+ case CR|LF|FF|SU if !in.isUnicode =>
+ in.error(offset, "unterminated string"); false
+ case '\\' =>
+ in.scratch append escapeCode(in.offset - 1); true
+ case c => in.scratch.append(c); true
+ }) {}
+ val ret = value(STRINGLIT, in.scratch.toString)
+ in.scratch setLength 0
+ ret
+ }
+ case '`' =>
+ in.scratch setLength 0
+ while (in.head match {
+ case '`' => in.next; false
+ case CR | LF | FF | SU | EOF =>
+ in.error(offset, "unterminated quoted identifier")
+ false
+ case _ => true
+ }) in.scratch append in.next
+ val name = global.newTermName(in.scratch.toString)
+ value(BACKQUOTED_IDENT, (name))
+ case c if (c == CR | c == LF | c == FF) =>
+ var multiple = false
+ in.readWhile{
+ case d if isNewLine(d) =>
+ multiple = multiple || d == c; true
+ case ' ' | '\t' => true // eat the whitespace after newlines.
+ case _ => false
+ }
+ xmlOk = true
+ (if (multiple) NEWLINES else NEWLINE)
+ case c =>
+ if (Character.isUnicodeIdentifierStart(c)) {
+ in.scratch.setLength(0)
+ in.scratch append c
+ getIdentRest
+ val name = global.newTermName(in.scratch.toString)
+ in.scratch.setLength(0)
+ val code = name2token(name)
+ value(code, (name))
+ } else if (isSpecial(c)) {
+ in.scratch.setLength(0)
+ in.scratch append c
+ getOperatorRest
+ val name = global.newTermName(in.scratch.toString)
+ in.scratch.setLength(0)
+ val code = name2token(name)
+ value(code, (name))
+ } else {
+ in.error(offset, "illegal character: \'" + c + "\'")
+ (ERROR)
+ }
+ }
+ current.length = length
+ }
+ def intVal(offset : Int, token : Int, name0 : RandomAccessSeq[Char], negated: Boolean, base : Int): Long = {
+ if (name0.length == 1 && name0(0) == '0') return 0
+
+ var name = name0
+ if (name.length > 2 && name(0) == '0' && (name(1) match {
+ case 'x'|'X' => true
+ case _ => false
+ })) name = name.drop(2)
+
+ while (name.last match {
+ case 'l'|'L' => true
+ case _ => false
+ }) name = name.take(name.length - 1)
+
+ 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 = digit2int(name(i), base)
+ if (d < 0) {
+ in.error(offset, "malformed integer number")
+ return 0
+ }
+ if (value < 0 ||
+ limit / (base / divider) < value ||
+ limit - (d / divider) < value * (base / divider) &&
+ !(negated && limit == value * base - 1 + d)) {
+ in.error(offset, "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(offset : Int, token : Int, name0 : RandomAccessSeq[Char], negated: Boolean): Double = {
+ var name = name0
+ while (name.last match {
+ case 'f'|'F'|'d'|'D' => true
+ case _ => false
+ }) name = name.take(name.length - 1)
+
+ val limit: Double =
+ if (token == DOUBLELIT) Math.MAX_DOUBLE else Math.MAX_FLOAT
+ try {
+ val value: Double = java.lang.Double.valueOf(name.mkString).doubleValue()
+ if (value > limit)
+ in.error(offset, "floating point number too large")
+ if (negated) -value else value
+ } catch {
+ case _: NumberFormatException =>
+ in.error(offset, "malformed floating point number")
+ 0.0
+ }
+ }
+ }
+
+
+ // utility functions
+ def isSpecial(c : Char) : Boolean = {
+ val chtp = Character.getType(c)
+ chtp == Character.MATH_SYMBOL || chtp == Character.OTHER_SYMBOL
+ }
+ def isDigit(c : Char) : Boolean = digit2int(c, 10) >= 0
+
+ def isIdentifierStart(c: Char): Boolean = c 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' | // scala-mode: need to understand multi-line case patterns
+ 'z' => true
+ case _ => false
+ }
+ def isIdentifierPart(c: Char) : Boolean = c 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') => true
+ case '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' => true
+ case c if Character.isUnicodeIdentifierPart(c) => true
+ case _ => false
+ }
+ //isIdentifierStart(c) || isDigit(c) || isUnicodeIdentifierPart(c)
+ def isOperatorPart(c : Char) : Boolean = c match {
+ case '~' | '!' | '@' | '#' | '%' |
+ '^' | '*' | '+' | '-' | '<' |
+ '>' | '?' | ':' | '=' | '&' |
+ '|' | '/' | '\\' => true
+ case c if isSpecial(c) => true
+ case _ => false
+ }
+
+ private def getOperatorRest(implicit in : CoreScannerInput) : Unit = {
+ in.readWhile{
+ case ('/') if in.startsWith('/','*') || in.startsWith('/','/') => false
+ case ('*') if in.startsWith('*','/') => false
+ case (c) if isOperatorPart(c) => in.scratch append c; true
+ case _ => false
+ }
+ }
+ private def isFraction(c0 : Char, c1 : Char) =
+ isDigit(c0) || (c0 match {
+ case 'd'|'D'|'f'|'F' if !isIdentifierPart(c1) => true
+ case 'e'|'E' if isDigit(c1) => true
+ case _ => false
+ })
+ private def getFraction(hasWhole : Boolean)(implicit in : CoreScannerInput) : Option[Int] = {
+ val hasDigits = in.readWhile(isDigit)
+ if (!hasDigits && !hasWhole) return None
+
+ def end(code : Int) : Option[Int] = {
+ if (!hasDigits && isIdentifierPart(in.peek(1))) None
+ else in.next; Some(code)
+ }
+ in.head match {
+ case 'f'|'F' => return end(FLOATLIT)
+ case 'd'|'D' => return end(DOUBLELIT)
+ case 'e'|'E' if {
+ val peek = in.peek(1)
+ peek == '-' || peek == '+' || isDigit(peek)
+ } =>
+ in.next // eat the e.
+ var hasDigit = isDigit(in.next) // eat +/-/digit
+ hasDigit = in.readWhile(isDigit) || hasDigit
+ in.readIf{ // eat an optional f or d
+ case 'f'|'F' => FLOATLIT
+ case 'd'|'D' => DOUBLELIT
+ } orElse Some(DOUBLELIT)
+ case _ if hasDigits => Some(DOUBLELIT)
+ case _ => None // we didn't read anything
+ }
+ }
+ private def getNumber(offset : Int, base : Int, prefix : String)(implicit in : CoreScannerInput) : Int = {
+ val hasBody = in.readWhile{
+ case at if at >= '0' && at <= '9' => true
+ case at if base == 16 && ((at >= 'a' && at <= 'f') || (at >= 'A' && at <= 'F')) => true
+ case _ => false
+ }
+ if (!hasBody) base match {
+ // because Java does this
+ case 16 =>
+ in.error(offset, "Invalid hex literal number")
+ return INTLIT
+ case _ =>
+ }
+ val code = if (in.head == '.') {
+ in.peek(1) match {
+ case c if isDigit(c) => in.next; getFraction(true).get
+ case 'f'|'F'|'d'|'D' if !isIdentifierPart(in.peek(2)) => in.next; getFraction(true).get
+ case 'e'|'E' if {
+ val peek = in.peek(2)
+ isDigit(peek) || peek == '-' || peek == '+'
+ } =>
+ in.next // consume the dot
+ in.next // consume the e
+ in.next // consume the +/-/digit
+ in.readWhile(isDigit) // consume remaining digits
+ in.readIf{
+ case 'f'|'F' => FLOATLIT
+ case 'd'|'D' => DOUBLELIT
+ } getOrElse DOUBLELIT
+ case c if isIdentifierStart(c) => INTLIT
+ case _ => in.next; DOUBLELIT
+ }
+ } else (in.readIf{
+ case 'l'|'L' => LONGLIT
+ case 'f'|'F' => FLOATLIT
+ case 'd'|'D' => DOUBLELIT
+ } getOrElse {
+ if (in.head == 'e' || in.head == 'E') {
+ in.next
+ if (in.head == '-' || in.head == '+') in.next
+ in.readWhile(isDigit)
+ in.readIf{
+ case 'f'|'F' => FLOATLIT
+ case 'd'|'D' => DOUBLELIT
+ } getOrElse DOUBLELIT
+ } else INTLIT
+ })
+ if (in.readWhile(isIdentifierPart))
+ in.error(offset, "Invalid literal number")
+ code
+ }
+ def inFirstOfStat(token: Int) = token match {
+ case EOF | /*CASE |*/ CATCH | ELSE | EXTENDS | FINALLY | MATCH | REQUIRES | WITH | YIELD |
+ COMMA | SEMI | NEWLINE | NEWLINES | DOT | USCORE | COLON | EQUALS | ARROW |
+ LARROW | SUBTYPE | VIEWBOUND | SUPERTYPE | HASH | // todo: add LBRACKET
+ RPAREN | RBRACKET | RBRACE => false
+ case _ => true
+ }
+ def inLastOfStat(token: Int) = token match {
+ case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT | SYMBOLLIT |
+ IDENTIFIER | BACKQUOTED_IDENT | THIS | NULL | TRUE | FALSE | RETURN | USCORE |
+ TYPE | XMLSTART | RPAREN | RBRACKET | RBRACE => true
+ case _ => false
+ }
+
+ def digit(c : Char, radix : Int) = c match {
+ case c if c >= '0' && c <= '7' => c - '0'
+ case c if c >= '8' && c <= '9' && radix >= 10 => c - '0'
+ case c if c >= '8' && c <= '9' && radix == 8 => throw new NumberFormatException("Malformed octal number")
+ case c if c >= 'a' && c <= 'f' && radix == 16 => c - 'a' + 9
+ case c if c >= 'A' && c <= 'F' && radix == 16 => c - 'A' + 9
+ }
+ private val simpleEscape : PartialFunction[Char,Char] = {
+ case 'b' => '\b'
+ case 't' => '\t'
+ case 'n' => '\n'
+ case 'f' => '\f'
+ case 'r' => '\r'
+ case '\"' => '\"'
+ case '\'' => '\''
+ case '\\' => '\\'
+ }
+
+ def digit2int(ch: Char, base: Int): Int = {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ ch - '0'
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ ch - 'A' + 10
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ ch - 'a' + 10
+ else
+ -1
+ }
+
+ object ScannerConfiguration {
+ private var key: Array[byte] = _
+ private var maxKey = 0
+ private var tokenName = new Array[global.Name](128);
+ {
+ var tokenCount = 0
+ // Enter keywords
+ def enterKeyword(n: global.Name, tokenId: Int) {
+ while (tokenId >= tokenName.length) {
+ val newTokName = new Array[global.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
+ }
+ import global.nme
+
+ enterKeyword(nme.ABSTRACTkw, ABSTRACT)
+ enterKeyword(nme.CASEkw, CASE)
+ enterKeyword(nme.CATCHkw, CATCH)
+ enterKeyword(nme.CLASSkw, CLASS)
+ enterKeyword(nme.DEFkw, DEF)
+ enterKeyword(nme.DOkw, DO)
+ enterKeyword(nme.ELSEkw, ELSE)
+ enterKeyword(nme.EXTENDSkw, EXTENDS)
+ enterKeyword(nme.FALSEkw, FALSE)
+ enterKeyword(nme.FINALkw, FINAL)
+ enterKeyword(nme.FINALLYkw, FINALLY)
+ enterKeyword(nme.FORkw, FOR)
+ enterKeyword(nme.FORSOMEkw, FORSOME)
+ enterKeyword(nme.IFkw, IF)
+ enterKeyword(nme.IMPLICITkw, IMPLICIT)
+ enterKeyword(nme.IMPORTkw, IMPORT)
+ enterKeyword(nme.LAZYkw, LAZY)
+ enterKeyword(nme.MATCHkw, MATCH)
+ enterKeyword(nme.NEWkw, NEW)
+ enterKeyword(nme.NULLkw, NULL)
+ enterKeyword(nme.OBJECTkw, OBJECT)
+ enterKeyword(nme.OVERRIDEkw, OVERRIDE)
+ enterKeyword(nme.PACKAGEkw, PACKAGE)
+ enterKeyword(nme.PRIVATEkw, PRIVATE)
+ enterKeyword(nme.PROTECTEDkw, PROTECTED)
+ enterKeyword(nme.REQUIRESkw, REQUIRES)
+ enterKeyword(nme.RETURNkw, RETURN)
+ enterKeyword(nme.SEALEDkw, SEALED)
+ enterKeyword(nme.SUPERkw, SUPER)
+ enterKeyword(nme.THISkw, THIS)
+ enterKeyword(nme.THROWkw, THROW)
+ enterKeyword(nme.TRAITkw, TRAIT)
+ enterKeyword(nme.TRUEkw, TRUE)
+ enterKeyword(nme.TRYkw, TRY)
+ enterKeyword(nme.TYPEkw, TYPE)
+ enterKeyword(nme.VALkw, VAL)
+ enterKeyword(nme.VARkw, VAR)
+ enterKeyword(nme.WHILEkw, WHILE)
+ enterKeyword(nme.WITHkw, WITH)
+ enterKeyword(nme.YIELDkw, YIELD)
+ enterKeyword(nme.DOTkw, DOT)
+ enterKeyword(nme.USCOREkw, USCORE)
+ enterKeyword(nme.COLONkw, COLON)
+ enterKeyword(nme.EQUALSkw, EQUALS)
+ enterKeyword(nme.ARROWkw, ARROW)
+ enterKeyword(nme.LARROWkw, LARROW)
+ enterKeyword(nme.SUBTYPEkw, SUBTYPE)
+ enterKeyword(nme.VIEWBOUNDkw, VIEWBOUND)
+ enterKeyword(nme.SUPERTYPEkw, SUPERTYPE)
+ enterKeyword(nme.HASHkw, HASH)
+ enterKeyword(nme.ATkw, AT)
+
+ // 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: global.Name): int =
+ if (name.start <= maxKey) key(name.start) else IDENTIFIER
+
+ def isKeyword(code : Int) = code match {
+ case code if code >= IF && code <= REQUIRES => true
+ case _ => false
+ }
+ /** Returns the string representation of given token. */
+ def token2string(token: int): String = token match {
+ case IDENTIFIER | BACKQUOTED_IDENT => "identifier"
+ 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 SYMBOLLIT => "symbol literal"
+ case LPAREN => "'('"
+ case RPAREN => "')'"
+ case LBRACE => "'{'"
+ case RBRACE => "'}'"
+ case LBRACKET => "'['"
+ case RBRACKET => "']'"
+ case EOF => "eof"
+ case ERROR => "something"
+ case SEMI => "';'"
+ case NEWLINE => "';'"
+ case NEWLINES => "';'"
+ case COMMA => "','"
+ case CASECLASS =>
+ "case class"
+ case CASEOBJECT =>
+ "case object"
+ case XMLSTART =>
+ "$XMLSTART$<"
+ case COMMENT => "cmnt"
+ case WHITESPACE => "ws"
+ case IGNORE => "ig"
+ case _ =>
+ try {
+ "'" + tokenName(token) + "'"
+ } catch {
+ case _: ArrayIndexOutOfBoundsException =>
+ "'<" + token + ">'"
+ case _: NullPointerException =>
+ "'<(" + token + ")>'"
+ }
+ }
+ }
+ class UnitScanner(unit: CompilationUnit) extends ParserScanner {
+ implicit val in =
+ new DefaultInput(new NewCharArrayReader(unit.source.asInstanceOf[BatchSourceFile].content, !settings.nouescape.value, error)) {
+ override def error(offset : Int, msg : String) : Unit = UnitScanner.this.error(offset, msg)
+ }
+ init
+ private def error(offset : Int, msg : String) : Unit = unit.error(new OffsetPosition(unit.source,offset), msg)
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index a820c985e6..582d4646e6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -8,7 +8,7 @@
package scala.tools.nsc.ast.parser
-import scala.tools.nsc.util.{ListBuffer, Position, OffsetPosition}
+import scala.tools.nsc.util.{ListBuffer, Position, OffsetPosition, NoPosition, BatchSourceFile}
import symtab.Flags
import Tokens._
@@ -49,76 +49,94 @@ import Tokens._
* </li>
* </ol>
*/
-trait Parsers {
- self: SyntaxAnalyzer =>
-
+trait Parsers extends NewScanners with MarkupParsers {
+ val global : Global
import global._
- //import RequiresIntsAsPositions._
+
private val glob: global.type = global
import global.posAssigner.atPos
+ case class OpInfo(operand: Tree, operator: Name, pos: Int)
/** ...
*
* @author Sean McDirmid
*/
- class UnitParser(unit: global.CompilationUnit) extends Parser {
+ class UnitParser(val unit: global.CompilationUnit) extends Parser {
val in = new UnitScanner(unit)
- in.init
- import in.ScanPosition
- def freshName(prefix : String) = unit.fresh.newName(prefix)
- import in.{p2g, g2p}
- def posToReport =
- if (!in.currentPos.line.isEmpty && !in.lastPos.line.isEmpty &&
- in.currentPos.line.get > in.lastPos.line.get) in.lastPos;
- else in.currentPos
+ 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 incompleteInputError(msg: String) : Unit =
+ unit.incompleteInputError(unit.source.asInstanceOf[BatchSourceFile].content.length - 1, msg)
+ def deprecationWarning(pos : Int, msg : String) : Unit = unit.deprecationWarning(pos, msg)
+ def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg)
+
+ /** the markup parser */
+ def xmlp = {
+ if (xmlp0 == null)
+ xmlp0 = new MarkupParser(this, true)
+ xmlp0
+ }
+ private var xmlp0: MarkupParser = null
+ def xmlLiteral : Tree = xmlp.xLiteral
+ def xmlLiteralPattern : Tree = xmlp.xLiteralPattern
+ object symbXMLBuilder extends SymbolicXMLBuilder(treeBuilder, UnitParser.this, true) { // DEBUG choices
+ val global: Parsers.this.global.type = Parsers.this.global
+ def freshName(prefix: String): Name = UnitParser.this.freshName(NoPosition, prefix)
+ }
+ }
+ // parser constants, here so they don't pollute parser debug listing
+ private object ParserConfiguration {
+ final val Local = 0
+ final val InBlock = 1
+ final val InTemplate = 2
+ final val MINUS: Name = "-"
+ final val PLUS : Name = "+"
+ final val BANG : Name = "!"
+ final val TILDE: Name = "~"
+ final val AMP : Name = "&"
+ final val SLASH: Name = "/"
+ final val STAR : Name = "*"
+ final val BAR : Name = "|"
+ final val OPT : Name = "?"
+ final val LT : Name = "<"
}
abstract class Parser {
- protected val in: AbstractScanner
- import in.ScanPosition
- protected def freshName(prefix: String): Name
- protected def posToReport: ScanPosition
- import in.{p2g, g2p}
+ ParserConfiguration.hashCode
+ import ParserConfiguration._
+ val in: ParserScanner
+ //val unit : CompilationUnit
+ //import in.ScanPosition
+ protected def freshName(pos : Position, prefix: String): Name
+ protected def posToReport: Int = in.currentPos
+
+ protected implicit def i2p(offset : Int) : Position
+ private implicit def p2i(pos : Position) = pos.offset.get
+
private def inToken = in.token
private def inSkipToken = in.skipToken
private def inNextToken = in.nextToken
private def inCurrentPos = in.currentPos
+ private def inNextTokenCode : Int = in.nextTokenCode
private def inName = in.name
- private def charVal = in.intVal.asInstanceOf[Char]
+ private def charVal = in.charVal
private def intVal(isNegated : Boolean) = in.intVal(isNegated).asInstanceOf[Int]
private def longVal(isNegated : Boolean) = in.intVal(isNegated)
private def floatVal(isNegated : Boolean) = in.floatVal(isNegated).asInstanceOf[Float]
private def doubleVal(isNegated : Boolean) = in.floatVal(isNegated)
- private def stringVal = inName.toString
- private def inNextTokenCode = in.next.token
+ private def stringVal = in.stringVal
/** whether a non-continuable syntax error has been seen */
- private var syntaxErrorSeen = false
-
- /** the markup parser */
- def xmlp = {
- if (xmlp0 == null)
- xmlp0 = this match {
- case in: UnitParser =>
- new MarkupParser(in, true)
- case _ =>
- Console.println("Cannot create XML PARSER " + in)
- null
- }
- xmlp0
- }
- private var xmlp0: MarkupParser = null
+ //private var syntaxErrorSeen = false
+ private var lastErrorPos : Int = -1
object treeBuilder extends TreeBuilder {
val global: Parsers.this.global.type = Parsers.this.global
- def freshName(prefix: String, pos : Position): Name = Parser.this.freshName(prefix)
+ def freshName(pos : Position, prefix: String): Name = Parser.this.freshName(pos, prefix)
}
import treeBuilder._
- object symbXMLBuilder extends SymbolicXMLBuilder(treeBuilder, Parser.this, true) { // DEBUG choices
- val global: Parsers.this.global.type = Parsers.this.global
- def freshName(prefix: String): Name = Parser.this.freshName(prefix)
- }
/** The implicit view parameters of the surrounding class */
var implicitClassViews: List[Tree] = Nil
@@ -180,7 +198,7 @@ trait Parsers {
/////// ERROR HANDLING //////////////////////////////////////////////////////
- private def skip() {
+ protected def skip() {
var nparens = 0
var nbraces = 0
while (true) {
@@ -207,60 +225,42 @@ trait Parsers {
inNextToken
}
}
-
+ def warning(pos : Int, msg : String) : Unit
+ def incompleteInputError(msg: String) : Unit
+ def deprecationWarning(pos : Int, msg : String) : Unit
+ def syntaxError(pos: Int, msg: String) : Unit
def syntaxError(msg: String, skipIt: Boolean) {
syntaxError(inCurrentPos, msg, skipIt)
}
- def syntaxError(pos: ScanPosition, msg: String) {
- in.error(pos, msg)
- }
- def syntaxError(pos: ScanPosition, msg: String, skipIt: Boolean) {
- if (pos != in.errpos) {
+
+ def syntaxError(pos: Int, msg: String, skipIt: Boolean) {
+ if (pos > lastErrorPos) {
syntaxError(pos, msg)
- in.errpos = pos
+ // no more errors on this token.
+ lastErrorPos = inCurrentPos
}
- if (skipIt) {
+ if (skipIt)
skip()
- }
- syntaxErrorSeen = true
- }
-
- def warning(msg: String) =
- if (inCurrentPos != in.errpos) {
- in.warning(inCurrentPos, msg)
- in.errpos = inCurrentPos
- }
-
- def incompleteInputError(pos: ScanPosition, msg: String) {
- if (pos == in.errpos) return
-
- if (syntaxErrorSeen)
- syntaxError(pos, msg, false)
- else {
- in.incompleteInputError(pos, msg)
- in.errpos = pos
- }
}
+ def warning(msg: String) : Unit = warning(inCurrentPos, msg)
- def incompleteInputError(msg: String) {
- incompleteInputError(inCurrentPos, msg) // inCurrentPos should be at the EOF
- }
def syntaxErrorOrIncomplete(msg: String, skipIt: Boolean) {
+ val inToken = this.inToken
if (inToken == EOF)
incompleteInputError(msg)
else
syntaxError(inCurrentPos, msg, skipIt)
}
-
+ // unused.
def mismatch(expected: Int, found: Int) {
val posToReport = this.posToReport
val msg =
- in.configuration.token2string(expected) + " expected but " +
- in.configuration.token2string(found) + " found."
+ ScannerConfiguration.token2string(expected) + " expected but " +
+ ScannerConfiguration.token2string(found) + " found."
if (found == EOF)
- incompleteInputError(posToReport, msg)
+ incompleteInputError(msg)
else
syntaxError(posToReport, msg, true)
}
@@ -268,33 +268,47 @@ trait Parsers {
/** Consume one token of the specified type, or
* signal an error if it is not there.
*/
- def accept(token: Int): ScanPosition = {
+ def accept(token: Int): Int = {
val pos = inCurrentPos
if (inToken != token) {
val posToReport =
- if (inCurrentPos.line.get(0) > in.lastPos.line.get(0))
- in.lastPos
- else
+ //if (inCurrentPos.line(unit.source).get(0) > in.lastPos.line(unit.source).get(0))
+ // in.lastPos
+ //else
inCurrentPos
val msg =
- in.configuration.token2string(token) + " expected but " +
- in.configuration.token2string(inToken) + " found."
+ ScannerConfiguration.token2string(token) + " expected but " +
+ ScannerConfiguration.token2string(inToken) + " found."
if (inToken == EOF)
- incompleteInputError(posToReport, msg)
+ incompleteInputError(msg)
else
syntaxError(posToReport, msg, true)
}
if (inToken == token) inNextToken
pos
}
+ def surround[T](open : Int, close : Int)(f : => T, orElse : T) : T = {
+ val wasOpened = inToken == open
+ accept(open)
+ if (wasOpened) {
+ val ret = f
+ accept(close)
+ ret
+ } else orElse
+ }
+
/** semi = nl {nl} | `;'
* nl = `\n' // where allowed
*/
- def acceptStatSep() {
- if (inToken == NEWLINE || inToken == NEWLINES) inNextToken
- else accept(SEMI)
+ def acceptStatSep() : Boolean = {
+ if (inToken == NEWLINE || inToken == NEWLINES) { inNextToken; true }
+ else {
+ val ret = inToken == SEMI
+ accept(SEMI)
+ ret
+ }
}
def errorTypeTree = TypeTree().setType(ErrorType).setPos((inCurrentPos))
@@ -355,7 +369,7 @@ trait Parsers {
*/
def joinComment(trees: => List[Tree]): List[Tree] = {
val buf = in.flushDoc
- if (buf ne null) trees map (t => DocDef(buf, t) setPos t.pos)
+ if ((buf ne null) && buf.length > 0) trees map (t => DocDef(buf, t) setPos t.pos)
else trees
}
@@ -377,8 +391,8 @@ trait Parsers {
tree match {
case Ident(name) =>
ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree)
- case Typed(Ident(name), tpe) if (tpe.isType) =>
- ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree)
+ case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident!
+ ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree).setPos(tree.pos)
case _ =>
syntaxError(tree.pos, "not a legal formal parameter", false)
ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree)
@@ -399,7 +413,7 @@ trait Parsers {
/** make closure from tree staring with a `.' */
def makeDotClosure(tree: Tree): Tree = {
- val pname = freshName("x$")
+ val pname = freshName(tree.pos, "x$")
def insertParam(tree: Tree): Tree = atPos(tree.pos) {
tree match {
case Ident(name) =>
@@ -420,7 +434,6 @@ trait Parsers {
/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
- case class OpInfo(operand: Tree, operator: Name, pos: ScanPosition)
var opstack: List[OpInfo] = Nil
def precedence(operator: Name): Int =
@@ -448,7 +461,7 @@ trait Parsers {
if (size > max) syntaxError("too many "+kind+", maximum = "+max, false)
}
- def checkAssoc(pos: ScanPosition, op: Name, leftAssoc: Boolean) =
+ def checkAssoc(pos: Int, op: Name, leftAssoc: Boolean) =
if (treeInfo.isLeftAssoc(op) != leftAssoc)
syntaxError(
pos, "left- and right-associative operators with same precedence may not be mixed", false)
@@ -470,16 +483,6 @@ trait Parsers {
/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////
- final val MINUS: Name = "-"
- final val PLUS : Name = "+"
- final val BANG : Name = "!"
- final val TILDE: Name = "~"
- final val AMP : Name = "&"
- final val SLASH: Name = "/"
- final val STAR : Name = "*"
- final val BAR : Name = "|"
- final val OPT : Name = "?"
- final val LT : Name = "<"
def ident(): Name =
if (inToken == IDENTIFIER || inToken == BACKQUOTED_IDENT) {
@@ -491,9 +494,9 @@ trait Parsers {
nme.ERROR
}
- def selector(t: Tree) = {
- Select(t, ident())
- }
+ def selector(t: Tree) =
+ atPos(inCurrentPos)(Select(t, ident()))
+
/** Path ::= StableId
* | [Ident `.'] this
@@ -503,11 +506,15 @@ trait Parsers {
var t: Tree = null
if (inToken == THIS) {
t = atPos(inSkipToken) { This(nme.EMPTY.toTypeName) }
- if (!thisOK || inToken == DOT)
+ if (!thisOK || inToken == DOT) {
t = selectors(t, typeOK, accept(DOT))
+ }
} else if (inToken == SUPER) {
- t = atPos(inSkipToken) {
- Super(nme.EMPTY.toTypeName, mixinQualifierOpt())
+ // val pos = inCurrentPos
+ val pos = inSkipToken
+ val (mix,usePos) = mixinQualifierOpt(pos)
+ t = atPos(usePos) {
+ Super(nme.EMPTY.toTypeName, mix)
}
t = atPos(accept(DOT)) { selector(t) }
if (inToken == DOT)
@@ -527,7 +534,8 @@ trait Parsers {
t = selectors(t, typeOK, accept(DOT))
} else if (inToken == SUPER) {
inNextToken
- t = atPos(i.pos) { Super(i.name.toTypeName, mixinQualifierOpt()) }
+ val (mix,pos) = mixinQualifierOpt(i.pos)
+ t = atPos(pos) { Super(i.name.toTypeName, mix) }
t = atPos(accept(DOT)) {selector(t)}
if (inToken == DOT)
t = selectors(t, typeOK, inSkipToken)
@@ -539,7 +547,7 @@ trait Parsers {
t
}
- def selectors(t: Tree, typeOK: Boolean, pos : ScanPosition): Tree =
+ def selectors(t: Tree, typeOK: Boolean, pos : Int): Tree =
if (typeOK && inToken == TYPE) {
inNextToken
atPos(pos) { SingletonTypeTree(t) }
@@ -551,14 +559,15 @@ trait Parsers {
/** MixinQualifier ::= `[' Id `]'
*/
- def mixinQualifierOpt(): Name =
+ def mixinQualifierOpt(pos : Position): (Name,Position) =
if (inToken == LBRACKET) {
inNextToken
+ val pos = inCurrentPos
val name = ident().toTypeName
accept(RBRACKET)
- name
+ (name,pos)
} else {
- nme.EMPTY.toTypeName
+ (nme.EMPTY.toTypeName,pos)
}
/** StableId ::= Id
@@ -645,7 +654,7 @@ trait Parsers {
*/
def requiresTypeOpt(): Tree =
if (inToken == REQUIRES) {
- in.deprecationWarning(in.pos, "`requires T' has been deprecated; use `{ self: T => ...' instead")
+ deprecationWarning(in.currentPos, "`requires T' has been deprecated; use `{ self: T => ...' instead")
inNextToken; placeholderTypeBoundary(annotType(false))
} else TypeTree()
@@ -655,9 +664,10 @@ trait Parsers {
def types(isPattern: Boolean, isTypeApply: Boolean, isFuncArg: Boolean): List[Tree] = {
val ts = new ListBuffer[Tree] + argType(isPattern, isTypeApply, isFuncArg)
while (inToken == COMMA) {
+ val pos = inCurrentPos
inNextToken
if (inToken == RPAREN) {
- in.deprecationWarning(in.pos, "Trailing commas have been deprecated")
+ deprecationWarning(pos, "Trailing commas have been deprecated")
return ts.toList
} else {
ts += argType(isPattern, isTypeApply, isFuncArg)
@@ -676,7 +686,6 @@ trait Parsers {
* | InfixType [ExistentialClause]
* ExistentialClause ::= forSome `{' ExistentialDcl {semi ExistentialDcl}} `}'
* ExistentialDcl ::= type TypeDcl | val ValDcl
- * XXX: Hook for IDE.
*/
def typ(): Tree = {
val t =
@@ -729,7 +738,7 @@ trait Parsers {
def infixTypeFirst(isPattern: Boolean) =
if (inToken == LBRACE) scalaAnyRefConstr else annotType(isPattern)
- def infixTypeRest(pos: ScanPosition, t0: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = {
+ def infixTypeRest(pos: Int, t0: Tree, isPattern: Boolean, mode: InfixMode.Value): Tree = {
val t = compoundTypeRest(pos, t0, isPattern)
if (isIdent && inName != nme.STAR) {
val opPos = inCurrentPos
@@ -752,7 +761,7 @@ trait Parsers {
def compoundType(isPattern: Boolean): Tree =
compoundTypeRest(inCurrentPos, infixTypeFirst(isPattern), isPattern)
- def compoundTypeRest(pos: ScanPosition, t: Tree, isPattern: Boolean): Tree = {
+ def compoundTypeRest(pos: Int, t: Tree, isPattern: Boolean): Tree = {
var ts = new ListBuffer[Tree] + t
while (inToken == WITH) {
inNextToken; ts += annotType(isPattern)
@@ -777,7 +786,7 @@ trait Parsers {
def annotType(isPattern: Boolean): Tree = {
val annots1 = annotations()
if (!annots1.isEmpty)
- in.deprecationWarning(
+ deprecationWarning(
annots1.head.pos,
"Type annotations should now follow the type")
// deprecated on August 13, 2007
@@ -805,18 +814,23 @@ trait Parsers {
(t /: annots) (makeAnnotated)
}
- def annotTypeRest(pos: ScanPosition, isPattern: Boolean, t: Tree): Tree =
- if (inToken == HASH)
- annotTypeRest(pos, isPattern, atPos(inSkipToken) { SelectFromTypeTree(t, ident().toTypeName) })
- else if (inToken == LBRACKET)
- annotTypeRest(pos, isPattern, atPos(pos) { AppliedTypeTree(t, typeArgs(isPattern, false)) })
+ def annotTypeRest(pos: Int, isPattern: Boolean, t: Tree): Tree =
+ if (inToken == HASH) {
+ inSkipToken
+ val posId = inCurrentPos
+ val id = ident
+ annotTypeRest(pos, isPattern, atPos(posId) { SelectFromTypeTree(t, id.toTypeName) })
+ } else if (inToken == LBRACKET) {
+ val usePos = if (t.pos != NoPosition) t.pos else i2p(pos)
+ annotTypeRest(pos, isPattern, atPos(usePos) { AppliedTypeTree(t, typeArgs(isPattern, false)) })
+ }
else
t
/** WildcardType ::= `_' TypeBounds
*/
- def wildcardType(pos: ScanPosition) = {
- val pname = freshName("_$").toTypeName
+ def wildcardType(pos: Int) = {
+ val pname = freshName(pos, "_$").toTypeName
val param = atPos(pos) { makeSyntheticTypeParam(pname, typeBounds()) }
placeholderTypes = param :: placeholderTypes
Ident(pname) setPos pos
@@ -919,9 +933,10 @@ trait Parsers {
def exprs(): List[Tree] = {
val ts = new ListBuffer[Tree] + expr()
while (inToken == COMMA) {
- inNextToken;
+ val pos = in.currentPos
+ inNextToken
if (inToken == RPAREN) {
- in.deprecationWarning(in.pos, "Trailing commas have been deprecated")
+ deprecationWarning(pos, "Trailing commas have been deprecated")
return ts.toList
} else {
ts += expr()
@@ -930,9 +945,6 @@ trait Parsers {
ts.toList
}
- private final val Local = 0
- private final val InBlock = 1
- private final val InTemplate = 2
/** Expr ::= (Bindings | Id) `=>' Expr
* | Expr1
@@ -956,8 +968,10 @@ trait Parsers {
* | `:' `_' `*'
*/
def expr(): Tree = expr(Local)
-
- /** XXX: Hook for IDE */
+ /* hook for IDE, unlike expression can be stubbed
+ * don't use for any tree that can be inspected in the parser!
+ */
+ def statement(location: Int): Tree = expr(location)
def expr(location: Int): Tree = {
def isWildcard(t: Tree): Boolean = t match {
case Ident(name1) if !placeholderParams.isEmpty && name1 == placeholderParams.head.name => true
@@ -970,9 +984,8 @@ trait Parsers {
var res = inToken match {
case IF =>
val pos = inSkipToken
- accept(LPAREN)
- val cond = expr()
- accept(RPAREN)
+
+ val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))
newLinesOpt()
val thenp = expr()
val elsep =
@@ -981,15 +994,11 @@ trait Parsers {
atPos(pos) { If(cond, thenp, elsep) }
case TRY =>
atPos(inSkipToken) {
- accept(LBRACE)
- val body = block()
- accept(RBRACE)
+ val body = surround(LBRACE,RBRACE)(block(), Literal(()))
val catches =
if (inToken == CATCH) {
inNextToken
- accept(LBRACE)
- val cases = caseClauses()
- accept(RBRACE)
+ val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)
cases
} else List()
val finalizer =
@@ -998,30 +1007,25 @@ trait Parsers {
Try(body, catches, finalizer)
}
case WHILE =>
- val lname: Name = freshName("while$")
val pos = inSkipToken
- accept(LPAREN)
- val cond = expr()
- accept(RPAREN)
+ val lname: Name = freshName(pos, "while$")
+ val cond = surround(LPAREN,RPAREN)(expr(),Literal(true))
newLinesOpt()
val body = expr()
atPos(pos) { makeWhile(lname, cond, body) }
case DO =>
- val lname: Name = freshName("doWhile$")
val pos = inSkipToken
+ val lname: Name = freshName(pos, "doWhile$")
val body = expr()
if (isStatSep) inNextToken
accept(WHILE)
- accept(LPAREN)
- val cond = expr()
- accept(RPAREN)
+ val cond = surround(LPAREN,RPAREN)(expr(), Literal(true))
atPos(pos) { makeDoWhile(lname, body, cond) }
case FOR =>
atPos(inSkipToken) {
val startToken = inToken
- accept(if (startToken == LBRACE) LBRACE else LPAREN)
- val enums = enumerators()
- accept(if (startToken == LBRACE) RBRACE else RPAREN)
+ val (open,close) = if (startToken == LBRACE) (LBRACE,RBRACE) else (LPAREN,RPAREN)
+ val enums = surround(open,close)(enumerators(), Nil)
newLinesOpt()
if (inToken == YIELD) {
inNextToken; makeForYield(enums, expr())
@@ -1036,7 +1040,7 @@ trait Parsers {
Throw(expr())
}
case DOT =>
- in.deprecationWarning(in.pos, "`.f' has been deprecated; use `_.f' instead")
+ deprecationWarning(in.currentPos, "`.f' has been deprecated; use `_.f' instead")
atPos(inSkipToken) {
if (isIdent) {
makeDotClosure(stripParens(simpleExpr()))
@@ -1085,9 +1089,7 @@ trait Parsers {
}
} else if (inToken == MATCH) {
t = atPos(inSkipToken) {
- accept(LBRACE)
- val cases = caseClauses()
- accept(RBRACE)
+ val cases = surround(LBRACE,RBRACE)(caseClauses(), Nil)
Match(stripParens(t), cases)
}
}
@@ -1100,7 +1102,7 @@ trait Parsers {
}
if (!placeholderParams.isEmpty)
if (isWildcard(res)) savedPlaceholderParams = placeholderParams ::: savedPlaceholderParams
- else res = Function(placeholderParams.reverse, res)
+ else res = atPos(res.pos){Function(placeholderParams.reverse, res)}
placeholderParams = savedPlaceholderParams
res
}
@@ -1147,7 +1149,7 @@ trait Parsers {
val name = unaryOp()
atPos(pos) { Select(stripParens(simpleExpr()), name) }
} else if (isIdent && inName == AMP) {
- in.deprecationWarning(in.pos, "`&f' has been deprecated; use `f _' instead")
+ deprecationWarning(in.currentPos, "`&f' has been deprecated; use `f _' instead")
val pos = inCurrentPos
val name = ident()
atPos(pos) { Typed(stripParens(simpleExpr()), Function(List(), EmptyTree)) }
@@ -1162,6 +1164,7 @@ trait Parsers {
simpleExpr()
}
}
+ def xmlLiteral(): Tree
/* SimpleExpr ::= new (ClassTemplate | TemplateBody)
* | BlockExpr
@@ -1181,14 +1184,12 @@ trait Parsers {
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT | STRINGLIT |
SYMBOLLIT | TRUE | FALSE | NULL =>
t = literal(false, false)
- case XMLSTART if xmlp != null =>
- assert(xmlp != null)
- t = xmlp.xLiteral
+ case XMLSTART => t = xmlLiteral()
case IDENTIFIER | BACKQUOTED_IDENT | THIS | SUPER =>
t = path(true, false)
case USCORE =>
- val pname = freshName("x$")
val pos = inSkipToken
+ val pname = freshName(pos, "x$")
val param = atPos(pos){ makeSyntheticParam(pname) }
placeholderParams = param :: placeholderParams
t = atPos(pos) { Ident(pname) }
@@ -1196,7 +1197,7 @@ trait Parsers {
val pos = inSkipToken
val ts = if (inToken == RPAREN) List() else exprs()
accept(RPAREN)
- t = Parens(ts) setPos g2p(pos)
+ t = Parens(ts) setPos (pos)
case LBRACE =>
t = blockExpr()
canApply = false
@@ -1222,12 +1223,15 @@ trait Parsers {
val t1 = stripParens(t)
t1 match {
case Ident(_) | Select(_, _) =>
- simpleExprRest(atPos(inCurrentPos) { TypeApply(t1, typeArgs(false, true)) }, true)
+ val pos = if (t1.pos == NoPosition) i2p(inCurrentPos) else t1.pos
+ simpleExprRest(atPos(pos) { TypeApply(t1, typeArgs(false, true)) }, true)
case _ =>
t1
}
case LPAREN | LBRACE if (canApply) =>
- simpleExprRest(atPos(inCurrentPos) { Apply(stripParens(t), argumentExprs()) }, true)
+ // again, position should be on idetifier, not (
+ var pos = if (t.pos == NoPosition) i2p(inCurrentPos) else t.pos
+ simpleExprRest(atPos(pos) { Apply(stripParens(t), argumentExprs()) }, true)
case USCORE =>
atPos(inSkipToken) { Typed(stripParens(t), Function(List(), EmptyTree)) }
case _ =>
@@ -1242,9 +1246,7 @@ trait Parsers {
if (inToken == LBRACE) {
List(blockExpr())
} else {
- accept(LPAREN)
- val ts = if (inToken == RPAREN) List() else exprs()
- accept(RPAREN)
+ val ts = surround(LPAREN,RPAREN)(if (inToken == RPAREN) List() else exprs(), List())
ts
}
}
@@ -1252,7 +1254,8 @@ trait Parsers {
/** BlockExpr ::= `{' (CaseClauses | Block) `}'
*/
def blockExpr(): Tree = {
- val res = atPos(accept(LBRACE)) {
+ assert(inToken == LBRACE)
+ val res = atPos(accept(LBRACE)) { // no need to surround
if (inToken == CASE) Match(EmptyTree, caseClauses())
else block()
}
@@ -1302,7 +1305,7 @@ trait Parsers {
inNextToken
if (newStyle) {
if (inToken == IF) enums += Filter(guard())
- else generator(enums, true)
+ else generator(enums, true)
} else {
if (inToken == VAL) generator(enums, true)
else enums += Filter(expr())
@@ -1314,8 +1317,8 @@ trait Parsers {
/** Generator ::= val Pattern1 `<-' Expr [Guard]
*/
def generator(enums: ListBuffer[Enumerator], eqOK: Boolean) {
- val pos = inCurrentPos;
if (inToken == VAL) inNextToken
+ val pos = inCurrentPos;
val pat = pattern1(false)
val tok = inToken
if (tok == EQUALS && eqOK) inNextToken
@@ -1335,9 +1338,10 @@ trait Parsers {
def patterns(seqOK: Boolean): List[Tree] = {
val ts = new ListBuffer[Tree] + pattern(seqOK)
while (inToken == COMMA) {
- inNextToken;
+ val pos = inCurrentPos
+ inNextToken
if (inToken == RPAREN) {
- in.deprecationWarning(in.pos, "Trailing commas have been deprecated")
+ deprecationWarning(pos, "Trailing commas have been deprecated")
return ts.toList
} else {
ts += pattern(seqOK)
@@ -1435,6 +1439,8 @@ trait Parsers {
stripParens(reduceStack(false, base, top, 0, true))
}
+ def xmlLiteralPattern() : Tree
+
/** SimplePattern ::= varid
* | `_'
* | literal
@@ -1474,7 +1480,7 @@ trait Parsers {
}
else */
if (inToken == LPAREN) {
- atPos(inCurrentPos) { Apply(t, argumentPatterns()) }
+ atPos(t.pos) { Apply(t, argumentPatterns()) }
} else t
case USCORE =>
atPos(inSkipToken) { Ident(nme.WILDCARD) }
@@ -1484,10 +1490,8 @@ trait Parsers {
val pos = inSkipToken
val ps = if (inToken == RPAREN) List() else patterns(false)
accept(RPAREN)
- Parens(ps) setPos g2p(pos)
- case XMLSTART if xmlp != null =>
- assert(xmlp != null)
- xmlp.xLiteralPattern
+ Parens(ps) setPos (pos)
+ case XMLSTART => xmlLiteralPattern()
case _ =>
syntaxErrorOrIncomplete("illegal start of simple pattern", true)
errorPatternTree
@@ -1597,7 +1601,7 @@ trait Parsers {
def annotations(): List[Annotation] = {
var annots = new ListBuffer[Annotation]
if (inToken == LBRACKET) {
- in.deprecationWarning(in.pos, "The [attribute] syntax has been deprecated; use @annotation instead")
+ deprecationWarning(in.currentPos, "The [attribute] syntax has been deprecated; use @annotation instead")
while (inToken == LBRACKET) {
inNextToken
annots += annotation()
@@ -1681,7 +1685,9 @@ trait Parsers {
var implicitmod = 0
var caseParam = ofCaseClass
def param(): ValDef = {
- atPos(inCurrentPos) {
+ var pos = inCurrentPos
+
+ {
val annots = annotations()
var mods = Modifiers(Flags.PARAM)
if (owner.isTypeName) {
@@ -1698,7 +1704,9 @@ trait Parsers {
}
if (caseParam) mods = mods | Flags.CASEACCESSOR
}
+ val namePos = inCurrentPos
val name = ident()
+ if (name != nme.ERROR) pos = namePos
var bynamemod = 0
val tpt =
if (settings.Xexperimental.value && !owner.isTypeName && inToken != COLON) {
@@ -1715,7 +1723,9 @@ trait Parsers {
}
paramType()
}
- ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, EmptyTree)
+ atPos(pos){
+ ValDef((mods | implicitmod | bynamemod) withAnnotations annots, name, tpt, EmptyTree)
+ }
}
}
def paramClause(): List[ValDef] = {
@@ -1751,7 +1761,7 @@ trait Parsers {
if (inToken == LBRACKET)
syntaxError(pos, "no type parameters allowed here", false)
else if(inToken == EOF)
- incompleteInputError(pos, "auxiliary constructor needs non-implicit parameter list")
+ incompleteInputError("auxiliary constructor needs non-implicit parameter list")
else
syntaxError(pos, "auxiliary constructor needs non-implicit parameter list", false)
addImplicitViews(owner, result, implicitViews)
@@ -1855,7 +1865,8 @@ trait Parsers {
def importExpr(): Tree =
atPos(inCurrentPos) {
var t: Tree = null
- var pos : ScanPosition = null.asInstanceOf[ScanPosition]
+ //var pos : ScanPosition = null.asInstanceOf[ScanPosition]
+ var pos : Int = -1
if (inToken == THIS) {
t = atPos(inCurrentPos) { This(nme.EMPTY.toTypeName) }
t = atPos(accept(DOT)) { selector(t) }
@@ -1879,7 +1890,9 @@ trait Parsers {
} else if (inToken == LBRACE) {
Import(t, importSelectors())
} else {
- val name = ident()
+ val identPos = inCurrentPos
+ val name = ident() // @S: use position of identifier, not dot!
+ pos = if (name == nme.ERROR) pos else identPos
if (inToken == DOT) {
t = atPos(pos) { Select(t, name) }
pos = accept(DOT)
@@ -1932,7 +1945,6 @@ trait Parsers {
* | var ValDcl
* | def FunDcl
* | type [nl] TypeDcl
- * XXX: Hook for IDE.
*/
def defOrDcl(mods: Modifiers): List[Tree] = {
if ((mods.hasFlag(Flags.LAZY)) && in.token != VAL)
@@ -1952,6 +1964,11 @@ trait Parsers {
List(tmplDef(mods))
}
}
+ /** IDE hook: for non-local defs or dcls with modifiers and annotations */
+ def nonLocalDefOrDcl : List[Tree] = {
+ val annots = annotations()
+ defOrDcl(modifiers() withAnnotations annots)
+ }
/** PatDef ::= Pattern2 {`,' Pattern2} [`:' Type] `=' Expr
* ValDcl ::= Id {`,' Id} `:' Type
@@ -1981,6 +1998,7 @@ trait Parsers {
newmods = newmods | Flags.DEFERRED
EmptyTree
}
+ var originalUsed = false
def mkDefs(p: Tree): List[Tree] = {
//Console.println("DEBUG: p = "+p.toString()); // DEBUG
val trees =
@@ -1989,7 +2007,12 @@ trait Parsers {
p
else
Typed(p, tp),
- rhs.duplicate) map atPos(p.pos)
+ if (inIDE && !originalUsed) {
+ // because duplicates have weaker status than originals
+ // need an original.
+ originalUsed = true
+ rhs
+ } else rhs.duplicate) map atPos(p.pos)
if (newmods.hasFlag(Flags.DEFERRED)) {
trees match {
case List(ValDef(_, _, _, EmptyTree)) =>
@@ -2009,9 +2032,10 @@ trait Parsers {
*/
def varDefOrDcl(mods: Modifiers): List[Tree] = {
var newmods = mods | Flags.MUTABLE
- val lhs = new ListBuffer[(ScanPosition, Name)]
+ val lhs = new ListBuffer[(Int, Name)]
do {
- lhs += (inSkipToken, ident())
+ inNextToken
+ lhs += (inCurrentPos, ident())
} while (inToken == COMMA)
val tp = typedOpt()
val rhs = if (tp.isEmpty || inToken == EQUALS) {
@@ -2026,8 +2050,13 @@ trait Parsers {
newmods = newmods | Flags.DEFERRED
EmptyTree
}
- for ((pos, name) <- lhs.toList) yield
- atPos(pos) { ValDef(newmods, name, tp.duplicate, rhs.duplicate) }
+ var originalUsed = false
+ for ((pos, name) <- lhs.toList) yield atPos(pos) {
+ if (inIDE && !originalUsed) {
+ originalUsed = true
+ ValDef(newmods, name, tp, rhs)
+ } else ValDef(newmods, name, tp.duplicate, rhs.duplicate)
+ }
}
/** FunDef ::= FunSig `:' Type `=' Expr
@@ -2036,18 +2065,23 @@ trait Parsers {
* FunDcl ::= FunSig [`:' Type]
* FunSig ::= id [FunTypeParamClause] ParamClauses
*/
- def funDefOrDcl(mods: Modifiers): Tree =
- atPos(inSkipToken) {
- if (inToken == THIS) {
+ def funDefOrDcl(mods: Modifiers): Tree = {
+ var pos = inSkipToken
+ if (inToken == THIS) {
+ atPos(inCurrentPos) {
inNextToken
val vparamss = paramClauses(nme.CONSTRUCTOR, implicitClassViews map (_.duplicate), false)
newLineOptWhenFollowedBy(LBRACE)
val rhs = if (inToken == LBRACE) constrBlock(vparamss)
else { accept(EQUALS); constrExpr(vparamss) }
DefDef(mods, nme.CONSTRUCTOR, List(), vparamss, TypeTree(), rhs)
- } else {
- var newmods = mods
- val name = ident()
+ }
+ } else {
+ var newmods = mods
+ val namePos = inCurrentPos
+ val name = ident()
+ if (name != nme.ERROR) pos = namePos
+ atPos(pos) {
val implicitViewBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, implicitViewBuf)
val vparamss = paramClauses(name, implicitViewBuf.toList, false)
@@ -2065,6 +2099,8 @@ trait Parsers {
DefDef(newmods, name, tparams, vparamss, restype, rhs)
}
}
+ }
+
/** ConstrExpr ::= SelfInvocation
* | ConstrBlock
@@ -2125,8 +2161,12 @@ trait Parsers {
}
}
- /** XXX: Hook for IDE? */
- def tmplDefHooked(mods: Modifiers): Tree = tmplDef(mods)
+ /** Hook for IDE, for top-level classes/objects */
+ def topLevelTmplDef: Tree = {
+ val annots = annotations()
+ val mods = modifiers() withAnnotations annots
+ tmplDef(mods)
+ }
/** TmplDef ::= [case] class ClassDef
* | [case] object ObjectDef
@@ -2155,9 +2195,12 @@ trait Parsers {
[AccessModifier] ClassParamClauses RequiresTypeOpt ClassTemplateOpt
* TraitDef ::= Id [TypeParamClause] RequiresTypeOpt TraitTemplateOpt
*/
- def classDef(mods: Modifiers): ClassDef =
- atPos(inSkipToken) {
- val name = ident().toTypeName
+ def classDef(mods: Modifiers): ClassDef = {
+ var pos = inSkipToken
+ var namePos = inCurrentPos
+ val name = ident().toTypeName
+ if (name != nme.ERROR) pos = namePos
+ atPos(pos) {
val savedViews = implicitClassViews
val implicitViewBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, implicitViewBuf)
@@ -2186,15 +2229,20 @@ trait Parsers {
implicitClassViews = savedViews
result
}
+ }
/** ObjectDef ::= Id ClassTemplateOpt
*/
- def objectDef(mods: Modifiers): ModuleDef =
- atPos(inSkipToken) {
- val name = ident()
+ def objectDef(mods: Modifiers): ModuleDef = {
+ var pos = inSkipToken
+ var namePos = inCurrentPos
+ val name = ident().toTermName
+ if (name != nme.ERROR) pos = namePos
+ atPos(pos) {
val template = templateOpt(mods, name, NoMods, List())
ModuleDef(mods, name, template)
}
+ }
/** ClassParents ::= AnnotType {`(' [Exprs [`,']] `)'} {with AnnotType}
@@ -2261,7 +2309,12 @@ trait Parsers {
var parents = parents0
if (name != nme.ScalaObject.toTypeName) parents = parents ::: List(scalaScalaObjectConstr)
if (mods.hasFlag(Flags.CASE)) parents = parents ::: List(productConstr)
- atPos(pos) { Template(parents, self, constrMods, vparamss, argss, body) }
+ val tree = Template(parents, self, constrMods, vparamss, argss, body)
+ // @S: if nothing parsed, don't use next position!
+ // @S: if primary constructor does not always have the same position, then the IDE gets confused.
+ // @S: since build compiler is used to generate IDE files, don't set position here!
+ tree
+ // if (pos == inCurrentPos || inIDE) tree else atPos(pos) {tree}
}
////////// TEMPLATES ////////////////////////////////////////////////////////////
@@ -2301,8 +2354,10 @@ trait Parsers {
/** Packaging ::= package QualId [nl] `{' TopStatSeq `}'
*/
def packaging(): Tree = {
- atPos(accept(PACKAGE)) {
- val pkg = qualId()
+ val pkgPos = accept(PACKAGE)
+ val pkg = qualId()
+ val pos = if (pkg.pos != NoPosition) pkg.pos else i2p(pkgPos)
+ atPos(pos) {
newLineOptWhenFollowedBy(LBRACE)
accept(LBRACE)
val stats = topStatSeq()
@@ -2324,6 +2379,7 @@ trait Parsers {
stats += packaging()
} else if (inToken == IMPORT) {
stats ++= importClause()
+ // XXX: IDE hook this all.
} else if (inToken == CLASS ||
inToken == CASECLASS ||
inToken == TRAIT ||
@@ -2332,8 +2388,7 @@ trait Parsers {
inToken == LBRACKET || //todo: remove
inToken == AT ||
isModifier) {
- val annots = annotations()
- stats ++ joinComment(List(tmplDefHooked(modifiers() withAnnotations annots)))
+ stats ++ joinComment(List(topLevelTmplDef))
} else if (!isStatSep) {
syntaxErrorOrIncomplete("expected class or object definition", true)
}
@@ -2354,11 +2409,11 @@ trait Parsers {
var self: ValDef = emptyValDef
val stats = new ListBuffer[Tree]
if (isExprIntro) {
- val first = expr(InTemplate)
+ val first = expr(InTemplate) // @S: first statement is potentially converted so cannot be stubbed.
if (inToken == ARROW) {
convertToParam(first) match {
- case ValDef(_, name, tpt, EmptyTree) if (name != nme.ERROR) =>
- self = makeSelfDef(name, tpt)
+ case tree @ ValDef(_, name, tpt, EmptyTree) if (name != nme.ERROR) =>
+ self = makeSelfDef(name, tpt).setPos(tree.pos)
case _ =>
}
inNextToken
@@ -2368,10 +2423,9 @@ trait Parsers {
if (inToken == IMPORT) {
stats ++= importClause()
} else if (isExprIntro) {
- stats += expr(InTemplate)
+ stats += statement(InTemplate)
} else if (isDefIntro || isModifier || inToken == LBRACKET /*todo: remove */ || inToken == AT) {
- val annots = annotations()
- stats ++ joinComment(defOrDcl(modifiers() withAnnotations annots))
+ stats ++= joinComment(nonLocalDefOrDcl)
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of definition", true)
}
@@ -2380,6 +2434,8 @@ trait Parsers {
(self, stats.toList)
}
+
+
/** RefineStatSeq ::= RefineStat {semi RefineStat}
* RefineStat ::= Dcl
* | type TypeDef
@@ -2388,7 +2444,7 @@ trait Parsers {
def refineStatSeq(): List[Tree] = checkNoEscapingPlaceholders {
val stats = new ListBuffer[Tree]
while (inToken != RBRACE && inToken != EOF) {
- if (isDclIntro) {
+ if (isDclIntro) { // don't IDE hook
stats ++= joinComment(defOrDcl(NoMods))
} else if (!isStatSep) {
syntaxErrorOrIncomplete("illegal start of declaration", true)
@@ -2398,6 +2454,14 @@ trait Parsers {
stats.toList
}
+ /** overridable IDE hook for local definitions of blockStatSeq */
+ def localDef : List[Tree] = {
+ val annots = annotations()
+ val mods = localModifiers() withAnnotations annots
+ if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) defOrDcl(mods)
+ else List(tmplDef(mods))
+ }
+
/** BlockStatSeq ::= { BlockStat semi } [ResultExpr]
* BlockStat ::= Import
* | Annotations [implicit] [lazy] Def
@@ -2406,27 +2470,20 @@ trait Parsers {
* |
*/
def blockStatSeq(stats: ListBuffer[Tree]): List[Tree] = checkNoEscapingPlaceholders {
- def localDef(mods: Modifiers) = {
- if (!(mods hasFlag ~(Flags.IMPLICIT | Flags.LAZY))) stats ++= defOrDcl(mods)
- else stats += tmplDefHooked(mods)
- if (inToken == RBRACE || inToken == CASE)
- syntaxError("block must end in result expression, not in definition", false)
- else
- acceptStatSep()
- if (inToken == RBRACE || inToken == CASE)
- stats += Literal(()).setPos(inCurrentPos)
- }
var last = false
while ((inToken != RBRACE) && (inToken != EOF) && (inToken != CASE) && !last) {
if (inToken == IMPORT) {
stats ++= importClause()
acceptStatSep()
} else if (isExprIntro) {
- stats += expr(InBlock)
+ stats += statement(InBlock)
if (inToken != RBRACE && inToken != CASE) acceptStatSep()
} else if (isDefIntro || isLocalModifier || in.token == AT) {
- val annots = annotations()
- localDef(localModifiers() withAnnotations annots)
+ stats ++= localDef
+ if (inToken == RBRACE || inToken == CASE) {
+ syntaxError("block must end in result expression, not in definition", false)
+ stats += Literal(()).setPos(inCurrentPos)
+ } else acceptStatSep()
} else if (isStatSep) {
inNextToken
} else {
@@ -2437,12 +2494,14 @@ trait Parsers {
}
/** CompilationUnit ::= [package QualId semi] TopStatSeq
- *
- * XXX: hook in IDE?
*/
- def compilationUnit(): Tree =
- atPos(inCurrentPos) {
+ def compilationUnit(): Tree = {
+ var pos = inCurrentPos;
+ {
val ts = new ListBuffer[Tree]
+ // @S: the IDE can insert phantom semi-colons before package during editing
+ // @S: just eat them (doesn't really change the grammar)
+ while (inToken == SEMI) inNextToken
if (inToken == PACKAGE) {
inNextToken
val pkg = qualId()
@@ -2464,10 +2523,12 @@ trait Parsers {
assert(placeholderParams.isEmpty)
assert(placeholderTypes.isEmpty)
val stats = ts.toList
- stats match {
+ val usePos = if (stats.isEmpty || stats.head.pos == NoPosition) i2p(pos) else stats.head.pos
+ atPos(usePos) { stats match {
case List(stat @ PackageDef(_, _)) => stat
case _ => makePackaging(Ident(nme.EMPTY_PACKAGE_NAME), stats)
- }
+ }}
}
+ }
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index d55f97ae08..2ac58e4a0d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -6,17 +6,13 @@
package scala.tools.nsc.ast.parser
-import scala.tools.nsc.util.{CharArrayReader, Position, OffsetPosition,
- SourceFile}
+import scala.tools.nsc.util._
import SourceFile.{LF, FF, CR, SU}
import Tokens._
trait Scanners {
- self: SyntaxAnalyzer =>
+ val global : Global
import global._
-
- /** ...
- */
abstract class AbstractTokenData {
def token: Int
type ScanPosition
@@ -60,7 +56,6 @@ trait Scanners {
abstract class AbstractScanner extends AbstractTokenData {
implicit def p2g(pos: Position): ScanPosition
implicit def g2p(pos: ScanPosition): Position
- def configuration: ScannerConfiguration
def warning(pos: ScanPosition, msg: String): Unit
def error (pos: ScanPosition, msg: String): Unit
def incompleteInputError(pos: ScanPosition, msg: String): Unit
@@ -81,7 +76,7 @@ trait Scanners {
def flushDoc: String
}
- trait ScannerConfiguration {
+ object ScannerConfiguration {
// Keywords -----------------------------------------------------------------
/** Keyword array; maps from name indices to tokens */
private var key: Array[Byte] = _
@@ -268,9 +263,6 @@ trait Scanners {
ret
}
- /** Process comments and strings in scanner */
- protected def matchInScanner = true
-
/** add the given character to the documentation buffer
*/
protected def putDocChar(c: Char) {
@@ -288,6 +280,16 @@ trait Scanners {
*/
var sepRegions: List[Int] = List()
+ /** A new line was inserted where in version 1.0 it would not be.
+ * Only significant if settings.migrate.value is set
+ */
+ var newNewLine = false
+
+ /** Parser is currently skipping ahead because of an error.
+ * Only significant if settings.migrate.value is set
+ */
+ var skipping = false
+
// Get next token ------------------------------------------------------------
/** read next token and return last position
@@ -421,23 +423,6 @@ trait Scanners {
in.next
getOperatorRest; // XXX
return
-
- case '/' if !matchInScanner =>
- in.next
- if (in.ch == '/') {
- in.next; token = LINE_COMMENT
- return
- } else if (in.ch == '*') {
- in.next
- if (in.ch == '*') {
- in.next; token = DOC_START
- } else token = COMMENT_START
- return
- } else {
- putChar('/')
- getOperatorRest
- return
- }
case '/' =>
in.next
if (!skipComment()) {
@@ -461,27 +446,10 @@ trait Scanners {
base = 10
getNumber
return
- case '`' if !matchInScanner =>
- in.next; token = BACK_QUOTE
- return
case '`' =>
in.next
getStringLit('`', BACKQUOTED_IDENT)
return
- case '\"' if !matchInScanner =>
- in.next
- if (in.ch == '\"') {
- in.next
- if (in.ch == '\"') {
- in.next; token = MULTI_QUOTE
- } else {
- token = throw new Error
- }
- return
- } else {
- token = DOUBLE_QUOTE
- return
- }
case '\"' =>
in.next
if (in.ch == '\"') {
@@ -577,7 +545,8 @@ trait Scanners {
in.next; token = RPAREN
return
case '}' =>
- in.next; token = RBRACE
+ in.next;
+ token = RBRACE
return
case '[' =>
in.next; token = LBRACKET
@@ -611,7 +580,6 @@ trait Scanners {
}
private def skipComment(): Boolean = {
- assert(matchInScanner)
if (in.ch == '/') {
do {
in.next
@@ -710,6 +678,7 @@ trait Scanners {
'5' | '6' | '7' | '8' | '9' =>
putChar(in.ch)
in.next
+
case '_' =>
putChar(in.ch)
in.next
@@ -717,7 +686,7 @@ trait Scanners {
return
case SU =>
setName
- token = configuration.name2token(name)
+ token = ScannerConfiguration.name2token(name)
return
case _ =>
if (Character.isUnicodeIdentifierPart(in.ch)) {
@@ -725,7 +694,7 @@ trait Scanners {
in.next
} else {
setName
- token = configuration.name2token(name)
+ token = ScannerConfiguration.name2token(name)
return
}
}
@@ -743,14 +712,9 @@ trait Scanners {
in.next
case '/' =>
in.next
- if (matchInScanner && skipComment) {
- setName
- token = configuration.name2token(name)
- return
- } else if (!matchInScanner && (in.ch == '*' || in.ch == '/')) {
- in.rewind
+ if (skipComment) {
setName
- token = configuration.name2token(name)
+ token = ScannerConfiguration.name2token(name)
return
} else putChar('/')
case _ =>
@@ -759,7 +723,7 @@ trait Scanners {
in.next
} else {
setName
- token = configuration.name2token(name)
+ token = ScannerConfiguration.name2token(name)
return
}
}
@@ -779,13 +743,12 @@ trait Scanners {
if (isSpecial(in.ch)) getOperatorRest
else {
setName
- token = configuration.name2token(name)
+ token = ScannerConfiguration.name2token(name)
}
}
}
private def getStringLit(delimiter: Char, litType: Int) {
- assert(matchInScanner)
//assert((litType==STRINGLIT) || (litType==IDENTIFIER))
while (in.ch != delimiter && (in.isUnicode || in.ch != CR && in.ch != LF && in.ch != SU)) {
getlitch()
@@ -801,7 +764,6 @@ trait Scanners {
}
private def getMultiLineStringLit {
- assert(matchInScanner)
if (in.ch == '\"') {
in.next
if (in.ch == '\"') {
@@ -1049,7 +1011,7 @@ trait Scanners {
case COMMA =>
","
case _ =>
- configuration.token2string(token)
+ ScannerConfiguration.token2string(token)
}
/** INIT: read lookahead character and token.
@@ -1062,9 +1024,8 @@ trait Scanners {
/** ...
*/
- class UnitScanner(unit: CompilationUnit) extends Scanner with ScannerConfiguration {
- override def configuration = this
- val in = new CharArrayReader(unit.source.getContent(), !settings.nouescape.value, syntaxError)
+ class UnitScanner(unit: CompilationUnit) extends Scanner {
+ val in = new CharArrayReader(unit.source.asInstanceOf[BatchSourceFile].content, !settings.nouescape.value, syntaxError)
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)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index 7d2e51b240..baa7eabaef 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc.ast.parser
/** An nsc sub-component.
*/
-abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParsers with Scanners {
+abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParsers with NewScanners {
val phaseName = "parser"
@@ -17,7 +17,8 @@ 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)
- unit.body = new UnitParser(unit).parse()
+ val parser = new UnitParser(unit)
+ unit.body = parser.parse()
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
index 959fba033e..1f04ad22de 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
@@ -31,6 +31,16 @@ object Tokens {
def isIdentifier(code : Int) =
code >= IDENTIFIER && code <= BACKQUOTED_IDENT
+ def canBeginExpression(code : Int) = code match {
+ case IDENTIFIER|BACKQUOTED_IDENT|USCORE => true
+ case LBRACE|LPAREN|LBRACKET|COMMENT|STRINGLIT => true
+ case IF|DO|WHILE|FOR|NEW|TRY|THROW => true
+ case NULL|THIS|TRUE|FALSE => true
+ case code if isLiteral(code) => true
+ case _ => false
+ }
+
+
/** keywords */
final val IF = 20
final val FOR = 21
@@ -79,6 +89,14 @@ object Tokens {
def isKeyword(code : Int) =
code >= IF && code <= LAZY
+ def isDefinition(code : Int) = code match {
+ case CLASS|TRAIT|OBJECT => true
+ case CASECLASS|CASEOBJECT => true
+ case DEF|VAL|VAR => true
+ case TYPE => true
+ case _ => false
+ }
+
/** special symbols */
final val COMMA = 70
@@ -100,7 +118,6 @@ object Tokens {
def isSymbol(code : Int) =
code >= COMMA && code <= VIEWBOUND
-
/** parenthesis */
final val LPAREN = 90
final val RPAREN = 91
@@ -109,24 +126,29 @@ object Tokens {
final val LBRACE = 94
final val RBRACE = 95
- def isParen(code : Int) =
+ 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)
/** XML mode */
final val XMLSTART = 96
/** for IDE only */
- final val LINE_COMMENT = 97
- final val COMMENT_START = 98
- final val COMMENT_END = 99
- final val DOC_START = 100
- final val DOUBLE_QUOTE = 101
- final val BACK_QUOTE = 102
- final val MULTI_QUOTE = 103
- //final val EMPTY_STRING = 104
+ final val COMMENT = 97
+
final val WHITESPACE = 105
final val IGNORE = 106
- final val XML_SINGLEEND = 107
- final val XML_STARTEND = 108
final val ESCAPE = 109
+
+ 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/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 0ba8c78e5d..240c2519d2 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -15,9 +15,8 @@ abstract class TreeBuilder {
val global: Global
import global._
import posAssigner.atPos;
- def freshName(prefix: String, pos: Position): Name
-
- def freshName(pos : Position): Name = freshName("x$", pos)
+ def freshName(pos : Position, prefix: String): Name
+ def freshName(pos : Position): Name = freshName(pos, "x$")
def scalaDot(name: Name): Tree =
Select(Ident(nme.scala_) setSymbol definitions.ScalaPackage, name)
@@ -57,16 +56,16 @@ abstract class TreeBuilder {
/** Traverse pattern and collect all variable names with their types in buffer */
private object getvarTraverser extends Traverser {
- val buf = new ListBuffer[(Name, Tree)]
+ val buf = new ListBuffer[(Name, Tree, Position)]
def init: Traverser = { buf.clear; this }
override def traverse(tree: Tree): Unit = tree match {
case Bind(name, Typed(tree1, tpt)) =>
if ((name != nme.WILDCARD) && (buf.elements forall (name !=)))
- buf += (name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt)
+ buf += (name, if (treeInfo.mayBeTypePat(tpt)) TypeTree() else tpt, tree.pos)
traverse(tree1)
case Bind(name, tree1) =>
if ((name != nme.WILDCARD) && (buf.elements forall (name !=)))
- buf += (name, TypeTree())
+ buf += (name, TypeTree(), tree.pos)
traverse(tree1)
case _ =>
super.traverse(tree)
@@ -76,7 +75,7 @@ abstract class TreeBuilder {
/** Returns list of all pattern variables, possibly with their types,
* without duplicates
*/
- private def getVariables(tree: Tree): List[(Name, Tree)] = {
+ private def getVariables(tree: Tree): List[(Name, Tree,Position)] = {
getvarTraverser.init.traverse(tree)
getvarTraverser.buf.toList
}
@@ -378,7 +377,7 @@ abstract class TreeBuilder {
/** Create visitor <x => x match cases> */
def makeVisitor(cases: List[CaseDef], checkExhaustive: Boolean, prefix: String): Tree = {
- val x = freshName(prefix, posAssigner.pos)
+ val x = freshName(posAssigner.pos, prefix)
val sel = if (checkExhaustive) Ident(x) else makeUnchecked(Ident(x))
Function(List(makeSyntheticParam(x)), Match(sel, cases))
}
@@ -394,7 +393,7 @@ abstract class TreeBuilder {
/** Create tree for pattern definition &lt;mods val pat0 = rhs&gt; */
def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): List[Tree] = matchVarPattern(pat) match {
case Some((name, tpt)) =>
- List(ValDef(mods, name, tpt, rhs))
+ List(ValDef(mods, name, tpt, rhs).setPos(pat.pos))
case None =>
// in case there are no variables in pattern
@@ -418,14 +417,14 @@ abstract class TreeBuilder {
vars match {
case List() =>
List(matchExpr)
- case List((vname, tpt)) =>
- List(ValDef(mods, vname, tpt, matchExpr))
+ case List((vname, tpt, pos)) =>
+ List(ValDef(mods, vname, tpt, matchExpr).setPos(pos))
case _ =>
val tmp = freshName(pat1.pos)
val firstDef = ValDef(Modifiers(PRIVATE | LOCAL | SYNTHETIC | (mods.flags & LAZY)),
tmp, TypeTree(), matchExpr)
var cnt = 0
- val restDefs = for (val (vname, tpt) <- vars) yield {
+ val restDefs = for (val (vname, tpt, pos) <- vars) yield atPos(pos) {
cnt = cnt + 1
ValDef(mods, vname, tpt, Select(Ident(tmp), newTermName("_" + cnt)))
}
@@ -446,7 +445,7 @@ abstract class TreeBuilder {
/** Append implicit view section if for `implicitViews' if nonempty */
def addImplicitViews(owner: Name, vparamss: List[List[ValDef]], implicitViews: List[Tree]): List[List[ValDef]] = {
val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM)
- def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName("view$", tpt.pos), tpt, EmptyTree)
+ def makeViewParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshName(tpt.pos, "view$"), tpt, EmptyTree)
if (implicitViews.isEmpty) vparamss
else vparamss ::: List(implicitViews map makeViewParam)
}
@@ -454,9 +453,9 @@ abstract class TreeBuilder {
/** Create a tree representing a packaging */
def makePackaging(pkg: Tree, stats: List[Tree]): PackageDef = pkg match {
case Ident(name) =>
- PackageDef(name, stats)
+ PackageDef(name, stats).setPos(pkg.pos)
case Select(qual, name) =>
- makePackaging(qual, List(PackageDef(name, stats)))
+ makePackaging(qual, List(PackageDef(name, stats).setPos(pkg.pos)))
}
case class Parens(args: List[Tree]) extends Tree
diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
index 90fec80c0b..a6a7174181 100644
--- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala
@@ -623,6 +623,7 @@ abstract class ScalaPrimitives {
}
case LENGTH =>
+ assert(elem != null)
toTypeKind(elem) match {
case BOOL => ZARRAY_LENGTH
case BYTE => BARRAY_LENGTH
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index ce917e5386..4d1e646b95 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -83,7 +83,7 @@ abstract class GenICode extends SubComponent {
addClassFields(ctx, tree.symbol);
classes += tree.symbol -> ctx.clazz
unit.icode += ctx.clazz
- gen(impl, ctx)
+ gen(impl, ctx)
ctx setClass null
// !! modules should be eliminated by refcheck... or not?
@@ -417,7 +417,7 @@ abstract class GenICode extends SubComponent {
var thenCtx = ctx.newBlock
var elseCtx = ctx.newBlock
val contCtx = ctx.newBlock
- genCond(cond, ctx, thenCtx, elseCtx)
+ genCond(cond, ctx, thenCtx, elseCtx)
val ifKind = toTypeKind(tree.tpe)
val thenKind = toTypeKind(thenp.tpe)
@@ -1427,6 +1427,8 @@ abstract class GenICode extends SubComponent {
ctx.method.symbol.newVariable(l.pos, eqEqTempName).setFlag(Flags.SYNTHETIC)
eqEqTempVar.setInfo(definitions.AnyRefClass.typeConstructor)
val local = ctx.method.addLocal(new Local(eqEqTempVar, REFERENCE(definitions.AnyRefClass), false))
+ assert(l.pos.source.get == unit.source)
+ assert(r.pos.source.get == unit.source)
local.start = (l.pos).line.get
local.end = (r.pos).line.get
local
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
index d5c158f3a6..d74b77efd6 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Printers.scala
@@ -127,7 +127,7 @@ trait Printers { self: ICodes =>
if (settings.Xdce.value)
print(if (i.useful) " " else " * ");
if (settings.debug.value)
- print(i.pos.line)
+ print(i.pos.line.map(_.toString).getOrElse("No line"))
println(i.toString());
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index d8a8d8b2c9..726bc6d69c 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -974,6 +974,8 @@ abstract class GenJVM extends SubComponent {
}
crtPC = jcode.getPC()
+
+ assert(instr.pos.source.isEmpty || instr.pos.source.get == (clasz.cunit.source), "sources don't match")
val crtLine = instr.pos.line.get(lastLineNr);
/*
val crtLine = try {
@@ -1148,7 +1150,7 @@ abstract class GenJVM extends SubComponent {
log("Converting from: " + src + " to: " + dst);
if (dst == BOOL) {
Console.println("Illegal conversion at: " + clasz +
- " at: " + method.sourceFile + ":" + pos.line.get(-1));
+ " at: " + pos.source.get + ":" + pos.line.get(-1));
} else
jcode.emitT2T(javaType(src), javaType(dst));
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 4111f2ec84..047bf656eb 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -1205,7 +1205,7 @@ abstract class GenMSIL extends SubComponent {
needAdditionalRet = false
- val currentLineNr = (instr.pos).line match {
+ val currentLineNr = (instr.pos).line match {
case Some(line) => line
case None =>
log("Warning: wrong position in: " + method)
@@ -1659,8 +1659,8 @@ abstract class GenMSIL extends SubComponent {
case DOUBLE => mcode.Emit(OpCodes.Conv_R8)
case _ =>
Console.println("Illegal conversion at: " + clasz +
- " at: " + method.sourceFile + ":" +
- pos.line.get)
+ " at: " + pos.source.get + ":" +
+ pos.line.get)
}
case ArrayLength(_) =>
diff --git a/src/compiler/scala/tools/nsc/doc/DocDriver.scala b/src/compiler/scala/tools/nsc/doc/DocDriver.scala
index 819591aaef..e4ee365c5d 100644
--- a/src/compiler/scala/tools/nsc/doc/DocDriver.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocDriver.scala
@@ -17,7 +17,6 @@ import scala.xml._
*/
abstract class DocDriver extends ModelFrames with ModelToXML {
import global._
-
object additions extends jcl.LinkedHashSet[Symbol]
object additions0 extends ModelAdditions(global) {
override def addition(sym: global.Symbol) = {
@@ -42,7 +41,7 @@ abstract class DocDriver extends ModelFrames with ModelToXML {
case _ =>
}
}
- def f(pkg: Package, tree: Tree): Unit = if (!tree.symbol.hasFlag(symtab.Flags.PRIVATE)) tree match {
+ def f(pkg: Package, tree: Tree): Unit = if (tree != EmptyTree && !tree.symbol.hasFlag(symtab.Flags.PRIVATE)) tree match {
case tree : PackageDef =>
val pkg1 = new Package(tree.symbol.asInstanceOf[ModuleSymbol]);
tree.stats.foreach(stat => f(pkg1, stat))
diff --git a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
index d2b86c3bd6..f93e502baf 100644
--- a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
+++ b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala
@@ -23,6 +23,7 @@ trait ModelFrames extends ModelExtractor {
val SyntheticClasses = new scala.collection.mutable.HashSet[global.Symbol];
{
import global.definitions._
+ global.definitions.init
SyntheticClasses ++= List(
AllClass, AllRefClass, AnyClass, AnyRefClass, AnyValClass,
//value classes
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
index 8c084c8266..36c17ef6c9 100644
--- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -102,7 +102,10 @@ abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
/** Returns the path of this abstract file. */
def path: String
- /** Returns the underlying File if any and <code>null</code> otherwise. */
+ /** Returns the containing directory of this abstract file */
+ def container : AbstractFile
+
+ /** Returns the underlying File if any and null otherwise. */
def file: File
/** Is this abstract file a directory? */
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
index c69123a19e..a8eba28f05 100644
--- a/src/compiler/scala/tools/nsc/io/PlainFile.scala
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -37,6 +37,8 @@ class PlainFile(val file: File) extends AbstractFile {
/** Returns the path of this abstract file. */
def path = file.getPath()
+ override def container : AbstractFile = new PlainFile(file.getParentFile)
+
override def input = new FileInputStream(file)
override def size = Some(file.length.toInt)
diff --git a/src/compiler/scala/tools/nsc/io/VirtualFile.scala b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
index c1a49067e8..ec1e4396c7 100644
--- a/src/compiler/scala/tools/nsc/io/VirtualFile.scala
+++ b/src/compiler/scala/tools/nsc/io/VirtualFile.scala
@@ -30,6 +30,12 @@ class VirtualFile(val name: String, _path: String) extends AbstractFile {
*/
def this(name: String) = this(name, name)
+ override def hashCode = name.hashCode
+ override def equals(that : Any) = that match {
+ case that : VirtualFile => name == that.name
+ case _ => false
+ }
+
//########################################################################
// Public Methods
@@ -38,7 +44,9 @@ class VirtualFile(val name: String, _path: String) extends AbstractFile {
/** Returns null. */
final def file: File = null
- def input: InputStream = throw new Error("not supported")
+ def input : InputStream = throw new Error("not supported");
+
+ def container : AbstractFile = throw new Error("not supported")
/** Is this abstract file a directory? */
def isDirectory: Boolean = false
diff --git a/src/compiler/scala/tools/nsc/io/ZipArchive.scala b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
index 575e2ec854..50c783857d 100644
--- a/src/compiler/scala/tools/nsc/io/ZipArchive.scala
+++ b/src/compiler/scala/tools/nsc/io/ZipArchive.scala
@@ -106,7 +106,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file)
/** Loads the archive and creates the root directory. */
private def load() {
- this.root = new DirEntry("<root>", "/")
+ this.root = new DirEntry(this, "<root>", "/")
// A path to DirEntry map
val dirs: Map[String, DirEntry] = new HashMap()
dirs.update("/", root)
@@ -126,7 +126,7 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file)
val home = if (index < 0) "/" else path.substring(0, index + 1)
val parent: DirEntry = getDir(dirs, home)
assert(!parent.entries.contains(path), this.toString() + " - " + path)
- parent.entries.update(name, new FileEntry(name, path, entry))
+ parent.entries.update(name, new FileEntry(parent, name, path, entry))
}
}
}
@@ -141,32 +141,33 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file)
dirs.get(path) match {
case Some(dir) => dir
case None =>
- val index = path.lastIndexOf('/', path.length() - 2)
- val name = if (index < 0) path else path.substring(index + 1)
- val home = if (index < 0) "/" else path.substring(0, index + 1)
- val parent: DirEntry = getDir(dirs, home)
- val dir = new DirEntry(name.substring(0, name.length() - 1), path)
- parent.entries.update(name, dir)
- dirs.update(path, dir)
+ val index = path.lastIndexOf('/', path.length() - 2);
+ val name = if (index < 0) path else path.substring(index + 1);
+ val home = if (index < 0) "/" else path.substring(0, index + 1);
+ val parent: DirEntry = getDir(dirs, home);
+ val dir = new DirEntry(parent, name.substring(0, name.length() - 1), path);
+ parent.entries.update(name, dir);
+ dirs.update(path, dir);
dir
- }
+ }
//########################################################################
// Private Class - Entry
/** Superclass of archive entries */
- abstract class Entry(name: String, path: String)
- extends VirtualFile(name, path) {
- final override def path = ZipArchive.this.toString() + "(" + super.path + ")"
+ abstract class Entry(override val container : AbstractFile, name: String, path: String)
+ extends VirtualFile(name, path) {
+ final override def path = ZipArchive.this.toString() + "(" + pathInArchive + ")"
final def getArchive = ZipArchive.this.archive
+ def pathInArchive = super.path
}
//########################################################################
// Private Class - DirEntry
/** A directory archive entry */
- private final class DirEntry(name: String, path: String)
- extends Entry(name, path)
+ private final class DirEntry(container : AbstractFile, name: String, path: String)
+ extends Entry(container, name, path)
{
val entries: Map[String, Entry] = new HashMap()
@@ -185,15 +186,15 @@ final class ZipArchive(file: File, val archive: ZipFile) extends PlainFile(file)
entries.get(if (directory) name + "/" else name) match {
case Some(dir) => dir
case None => null
- }
+ }
}
//########################################################################
// Private Class - FileEntry
/** A regular file archive entry */
- final class FileEntry(name: String, path: String, val entry: ZipEntry)
- extends Entry(name, path) {
+ final class FileEntry(container : AbstractFile, name: String, path: String, val entry: ZipEntry)
+ extends Entry(container, name, path) {
def archive = ZipArchive.this.archive
override def lastModified: Long = entry.getTime()
override def input = archive.getInputStream(entry)
@@ -213,6 +214,8 @@ final class URLZipArchive(url: URL) extends AbstractFile {
private var root: DirEntry = _
+ def container = throw new Error("unsupported")
+
def name: String = url.getFile()
def path: String = url.getPath()
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 5c0e05ebfc..ba7c802464 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -899,8 +899,8 @@ trait ParallelMatching {
//Console.println("case temps"+caseTemps.toString)
try{
- var vdefs = caseTemps map {
- case (tmp,accessorMethod) =>
+ var vdefs = caseTemps map {p =>
+ val tmp = p._1; val accessorMethod = p._2
//Console.println("tmp: "+tmp+":"+tmp.tpe)
//Console.println("accessorMethod: "+accessorMethod+":"+accessorMethod.tpe)
val untypedAccess = Apply(Select(mkIdent(casted), accessorMethod),List())
diff --git a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
index 61095aeb83..f8b6f26545 100644
--- a/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
+++ b/src/compiler/scala/tools/nsc/models/SemanticTokens.scala
@@ -11,7 +11,7 @@ import java.lang.Character.isJavaIdentifierPart
import scala.collection.mutable.{HashMap,HashSet}
import scala.tools.nsc.Global
import scala.tools.nsc.symtab.{Flags,Names}
-import scala.tools.nsc.util.{NameTransformer,Position,SourceFile,NoPosition}
+import scala.tools.nsc.util.{NameTransformer,Position,SourceFile,BatchSourceFile, NoPosition}
import scala.tools.nsc.symtab.Flags.DEFERRED
class SemanticTokens(val compiler: Global) {
@@ -35,10 +35,10 @@ class SemanticTokens(val compiler: Global) {
def next: HasPrev
}
- def eatKeyword(source: SourceFile, pos: Int, keywords: List[String]) : Int = {
+ def eatKeyword(source: BatchSourceFile, pos: Int, keywords: List[String]) : Int = {
if (keywords.isEmpty)
pos
- else if (pos == source.content.length)
+ else if (pos == source.length)
-1
else if (source.beginsWith(pos, " "))
eatKeywords(source, pos + 1)
@@ -48,7 +48,7 @@ class SemanticTokens(val compiler: Global) {
eatKeyword(source, pos, keywords.tail)
}
- def eatKeywords(source: SourceFile, pos: Int): Int = {
+ def eatKeywords(source: BatchSourceFile, pos: Int): Int = {
val keywords =
"package" :: "val" :: "var" :: "def" :: "class" :: "trait" :: "override" :: "case" ::
"object" :: "sealed" :: "private" :: "protected" :: Nil
@@ -202,12 +202,10 @@ class SemanticTokens(val compiler: Global) {
def build(tree0: Tree) : Unit = try {
/* if (tree0.pos != NoPosition) */ tree0 match {
case tree: ImplDef =>
- val pos = eatKeywords(unit.source, tree.pos.offset.get)
+ val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get)
if (pos == -1) {
- // inner types.
- // Console.err.println("NOPOS: " + tree.getClass() + " " + (new Position(unit.source, tree.pos)).dbgString);
- //Thread.dumpStack();
- } else buildDef(tree.symbol, eatKeywords(unit.source, tree.pos.offset.get));
+
+ } else buildDef(tree.symbol, eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get));
tree match {
case cdef: ClassDef => build(cdef.tparams)
case _ => ;
@@ -222,7 +220,7 @@ class SemanticTokens(val compiler: Global) {
// todo: review whether this is correct, or whether abstract getters should be included.
{
val pos : Int = if (tree.name.toString().equals("<init>")) -1 else
- eatKeywords(unit.source, tree.pos.offset.get);
+ eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get);
if (false) Console.err.println("VALDEF: tree=" + tree + " sym=" + tree.symbol + " pos0=" +
tree.symbol.pos + " alias=" + tree.symbol.alias + " pos1=" +
pos + " pos2=" + tree.pos.dbgString + " " + tree.symbol.hasFlag(Flags.SYNTHETIC));
@@ -261,7 +259,7 @@ class SemanticTokens(val compiler: Global) {
case tree: PackageDef =>
//Console.err.println("PACKAGE: " + tree.name);
if (false) {
- val pos = eatKeywords(unit.source, tree.pos.offset.get(-1))
+ val pos = eatKeywords(unit.source.asInstanceOf[BatchSourceFile], tree.pos.offset.get(-1))
if (pos != -1)
buildDef(tree.symbol, pos)
}
@@ -272,9 +270,9 @@ class SemanticTokens(val compiler: Global) {
val pos: Int =
if (unit.source.beginsWith(arg.pos.offset.get(-1), "val "))
unit.source.skipWhitespace(arg.pos.offset.get(-1) + ("val ").length())
- else if (unit.source.content(arg.pos.offset.get) == ':') {
+ else if (unit.source.asInstanceOf[BatchSourceFile].content(arg.pos.offset.get) == ':') {
var posx : Int = arg.pos.offset.get
- while (unit.source.content(posx - 1).isWhitespace) posx = posx - 1
+ while (unit.source.asInstanceOf[BatchSourceFile].content(posx - 1).isWhitespace) posx = posx - 1
posx - name.length()
} else arg.pos.offset.get
buildDef(arg.symbol, pos)
@@ -303,7 +301,6 @@ class SemanticTokens(val compiler: Global) {
case ident : Ident => buildUse(tpe0.sym, ident.pos.offset.get(-1), tpe0);
case select : Select =>
if (select.symbol == NoSymbol)
- if (false) Console.err.println("BUILD_SELECT: " + select + " @ " + tpe0 + " SYM=" + select.symbol + " " + (select.pos).dbgString);
try {
// build(select);
buildUse(tpe0.typeSymbol, selectPos(select), tpe0);
@@ -377,8 +374,6 @@ class SemanticTokens(val compiler: Global) {
}
case ctype : ConstantType =>
- if (false) Console.err.println("UNKNOWN CONSTANT_TYPE: " + tree + " " + ctype + " " + (tree.pos).dbgString);
-
case ErrorType =>
case _ => {
if (false) Console.err.println("UNKNOWN TPE4: " + tree + " " + tpe + " " + tpe.getClass() + " " + (tree.pos).dbgString);
@@ -419,7 +414,7 @@ class SemanticTokens(val compiler: Global) {
case e : Error => Console.err.println("SELECTQ: " + tree + " " + tree.qualifier + " " + (tree.qualifier.pos).dbgString); throw e;
}
try {
- if (tree.pos.offset.get >= unit.source.content.length) {
+ if (tree.pos.offset.get >= unit.source.length) {
if (false) Console.err.println("BAD_SELECT_QUALIFIER " + tree + " @ " + (tree.pos).dbgString);
} else {
@@ -437,11 +432,11 @@ class SemanticTokens(val compiler: Global) {
build(tree.fun)
build(tree.args)
case tree: Apply =>
- //Console.err.println("NORM_APPLY: " + tree + " " + tree.pos.dbgString);
+
build(tree.fun)
build(tree.args)
case tree: GenericApply =>
- //Console.err.println("GEN_APPLY: " + tree + " " + tree.pos.dbgString);
+
build(tree.fun)
build(tree.args)
case tree: Typed =>
@@ -472,7 +467,7 @@ class SemanticTokens(val compiler: Global) {
case tree : Try => build(tree.block); build(tree.catches); build(tree.finalizer);
case tree : Alternative => build(tree.trees);
case tree : This =>
- //Console.err.println("THIS: " + tree.symbol + " " + tree.qual + " " + tree.pos.dbgString + " " + tree.tpe);
+
if (tree.symbol ne null) buildUse(tree.symbol, tree.pos.offset.get(-1), tree.tpe);
//Thread.dumpStack();
case tree : TypeDef =>
@@ -506,7 +501,7 @@ class SemanticTokens(val compiler: Global) {
}
else if (term != NoSymbol) {
val name = NameTransformer.decode(term.name.toString()).toString().trim()
- val buf = unit.source.content
+ val buf = unit.source.asInstanceOf[BatchSourceFile].content
val cs = name.toChars
var idx = 0
if (cs.length + pos > buf.length) return
@@ -532,7 +527,7 @@ class SemanticTokens(val compiler: Global) {
}
def selectPos(tree : Select): Int = if (tree.pos == NoPosition) -1 else {
- val buf = unit.source.content
+ val buf = unit.source.asInstanceOf[BatchSourceFile].content
if (tree.pos.offset.get >= buf.length) {
if (false) {
Console.err.println("" + tree + "@" + tree.pos + " not in " +
@@ -598,16 +593,6 @@ class SemanticTokens(val compiler: Global) {
if (sem.symbol != tok.symbol &&
sem.symbol.getClass() == tok.symbol.getClass() &&
sem.symbol.pos == tok.symbol.pos) return;
-
- if (false) {
- Console.err.println("NOT_GAP: " + sem.symbol + " " + sem.symbol.getClass() + " " + (sem.symbol.pos).dbgString + " " + sem.symbol.flags);
- Console.err.println("NOT_GAP: " + tok.symbol + " " + tok.symbol.getClass() + " " + (tok.symbol.pos).dbgString + " " + tok.symbol.flags);
- Console.err.println("LIST: " + this);
- Console.err.println("POS: " + unit.source.dbg(offset));
-
- Thread.dumpStack();
- throw new Error();
- }
} else {
val gap = cursor.token.asInstanceOf[Gap];
if (!(offset - cursor.offset + tok.length <= gap.length)) {
diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
index 536cbe7e15..7ec8b688e7 100644
--- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
@@ -44,9 +44,11 @@ abstract class AbstractReporter extends Reporter {
*/
private def testAndLog(pos: Position): Boolean = {
if (pos eq null) return false
- if (pos.column == 0) return false
+ if (pos.offset.isEmpty) return false
if (positions contains pos) return true
+ //Console.println("ERROR @ " + pos + " into " + positions)
positions += pos
+
return false
}
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index a038959056..519ae106f7 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc.reporters
import java.io.{BufferedReader, InputStreamReader, IOException, PrintWriter}
-import util.{FakePos,Position,NoPosition}
+import util._
import compat.StringBuilder
@@ -48,20 +48,24 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
/** Prints the message with the given position indication. */
def printMessage(posIn: Position, msg: String): Unit =
if (posIn ne null) {
- val pos = posIn.inUltimateSource
+ val pos = posIn.inUltimateSource(posIn.source.getOrElse(null))
val buf = new StringBuilder(msg)
- buf.insert(0, " ")
- buf.insert(0, pos.line.map(ln => ":" + pos.line.get + ":").get(":"))
+ if (!pos.source.isEmpty) {
+ buf.insert(0, " ")
+ buf.insert(0, pos.line.map(ln => ":" + pos.line.get + ":").get(":"))
+ }
+ //println(getSource.file)
pos match {
- case NoPosition =>
- case FakePos(msg) =>
- buf.insert(0, msg)
- case _ if !pos.source.isEmpty =>
- val file = pos.source.get.file
- buf.insert(0, if (shortname) file.name else file.path)
+ case FakePos(msg) =>
+ buf.insert(0, msg)
+ case _ if !pos.source.isEmpty =>
+ val file = pos.source.get.file
+ buf.insert(0, if (shortname) file.name else file.path)
+ case _ =>
}
printMessage(buf.toString())
- printSourceLine(pos)
+ if (!pos.line.isEmpty)
+ printSourceLine(pos)
} else
printMessage(msg)
diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
index 5a65087a70..6eb4401c49 100644
--- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc.reporters
-import scala.tools.nsc.util.Position
+import scala.tools.nsc.util._
/**
* This interface provides methods to issue information, warning and
@@ -37,6 +37,10 @@ abstract class Reporter {
protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit
+ private var source : SourceFile = _
+ def setSource(source : SourceFile) : Unit = this.source = source
+ def getSource : SourceFile = source
+
def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force)
def warning(pos: Position, msg: String ): Unit = info0(pos, msg, WARNING, false)
def error(pos: Position, msg: String ): Unit = info0(pos, msg, ERROR, false)
diff --git a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala
index 26453c7748..41f1bde6da 100644
--- a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala
@@ -6,13 +6,13 @@
// $Id$
-package scala.tools.nsc.reporters;
-import scala.collection.mutable.HashSet;
-import scala.tools.nsc.util.Position
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.io.PrintWriter;
+package scala.tools.nsc.reporters
+import scala.collection.mutable.HashSet
+import scala.tools.nsc.util.{Position,SourceFile}
+import java.io.BufferedReader
+import java.io.InputStreamReader
+import java.io.IOException
+import java.io.PrintWriter
/**
* This class implements a Reporter that displays messages on a text
@@ -20,17 +20,15 @@ import java.io.PrintWriter;
*/
class StoreReporter extends Reporter {
class Info(val pos: Position, val msg: String, val severity: Severity) {
- override def toString() = "pos: " + pos + " " + msg + " " + severity;
+ override def toString() = "pos: " + pos + " " + msg + " " + severity
}
-
val infos = new HashSet[Info];
-
protected def info0(pos : Position, msg : String, severity : Severity, force : Boolean) : Unit = if (!force) {
- infos += new Info(pos, msg, severity);
+ infos += new Info(pos, msg, severity)
(severity).count = severity.count + 1
}
override def reset = {
- super.reset;
- infos.clear;
+ super.reset
+ infos.clear
}
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index fc3572b8f1..13180aade2 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -356,7 +356,7 @@ trait Definitions {
private def newClass(owner: Symbol, name: Name, parents: List[Type]): Symbol = {
val clazz = owner.newClass(NoPosition, name.toTypeName)
- clazz.setInfo(ClassInfoType(parents, newScope, clazz))
+ clazz.setInfo(ClassInfoType(parents, newClassScope, clazz))
owner.info.decls.enter(clazz)
clazz
}
@@ -367,7 +367,7 @@ trait Definitions {
clazz.setInfo(
PolyType(
List(tparam),
- ClassInfoType(List(parent(tparam)), newScope, clazz)))
+ ClassInfoType(List(parent(tparam)), newClassScope, clazz)))
}
private def newAlias(owner: Symbol, name: Name, alias: Type): Symbol = {
@@ -442,7 +442,7 @@ trait Definitions {
val module = ScalaPackageClass.newModule(NoPosition, name)
ScalaPackageClass.info.decls.enter(module)
val mclass = module.moduleClass
- mclass.setInfo(ClassInfoType(List(), newScope, mclass))
+ mclass.setInfo(ClassInfoType(List(), newClassScope, mclass))
module.setInfo(mclass.tpe)
val box = newMethod(mclass, nme.box, List(clazz.typeConstructor),
@@ -645,7 +645,7 @@ trait Definitions {
if (isInitialized) return
isInitialized = true
- EmptyPackageClass.setInfo(ClassInfoType(List(), newScope, EmptyPackageClass))
+ EmptyPackageClass.setInfo(ClassInfoType(List(), newClassScope, EmptyPackageClass))
EmptyPackage.setInfo(EmptyPackageClass.tpe)
RootClass.info.decls.enter(EmptyPackage)
RootClass.info.decls.enter(RootPackage)
@@ -696,7 +696,7 @@ trait Definitions {
EqualsPatternClass.setInfo(
PolyType(
List(tparam),
- ClassInfoType(List(AnyClass.typeConstructor), newScope, EqualsPatternClass)))
+ ClassInfoType(List(AnyClass.typeConstructor), newClassScope, EqualsPatternClass)))
}
/* <unapply> */
diff --git a/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala b/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala
new file mode 100644
index 0000000000..6f265a379f
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/symtab/GenerateIdeMaps.scala
@@ -0,0 +1,546 @@
+package scala.tools.nsc.symtab;
+import scala.tools.nsc.io.{PlainFile,AbstractFile}
+import scala.tools.nsc.util._
+import java.io._
+import java.util.zip._
+import scala.collection.jcl.{LinkedHashMap,LinkedHashSet}
+import scala.tools.nsc.symtab.Flags._
+
+abstract class GenerateIdeMaps extends SubComponent {
+ val phaseName = "gen-ide-map"
+ def newPhase(prev: Phase): StdPhase = new GenIdeMapPhase(prev)
+ import global._
+ private def assert(b : Boolean) : Unit = {
+ if (!b) {
+ assert(true)
+ throw new AssertionError
+ }
+ }
+
+ object sourceFiles extends LinkedHashMap[AbstractFile,AbstractFile] {
+ override def update(sourceFile : AbstractFile, classDir : AbstractFile) = {
+ ideMaps.get(sourceFile) match {
+ case Some(map) if map.isEmpty => ideMaps.removeKey(sourceFile)
+ case _ =>
+ }
+ super.update(sourceFile, classDir)
+ }
+ }
+ object ideMaps extends LinkedHashMap[AbstractFile, LinkedHashMap[Int,IdeRef]]
+ def getIdeMap(sourceFile : SourceFile, pkg : => Option[String], defaultClassDir : => Option[AbstractFile]) = ideMaps.get(sourceFile.file) match {
+ case Some(map) if !map.isEmpty => map
+ case _ =>
+ val ret0 = try {
+ readIdeMap(sourceFile, pkg, defaultClassDir)
+ } catch {
+ case _ => Nil
+ }
+ val ret = new LinkedHashMap[Int,IdeRef]
+ ret0.foreach{
+ case (offset,ref) => ret(offset) = ref
+ }
+ //if (!ret.isEmpty)
+ ideMaps(sourceFile.file) = ret
+ ret
+ }
+ def symToPackage(sym : Symbol) : String = {
+ var pkg = sym.fullNameString
+ if (pkg.indexOf('$') != -1) pkg = pkg.substring(pkg.indexOf('$'))
+ if (pkg.indexOf('.') != -1) pkg = pkg.substring(pkg.lastIndexOf('.'))
+ pkg
+ }
+
+ abstract class IdeRef
+ object NoRef extends IdeRef
+ case class Internal(offset : Int) extends IdeRef
+ case class External(sym : Symbol) extends IdeRef
+ class Definition(sym : Symbol) extends External(sym) {
+ override def toString = "Definition(" + sym + ")"
+ }
+ def readIdeMap(sourceFile : SourceFile, pkg : => Option[String], defaultClassDir : => Option[AbstractFile]) : List[(Int,IdeRef)] = {
+ // need to find the place where the class file was loaded....
+ var name = sourceFile.file.name
+ assert(name.endsWith(".scala"))
+ name = name.substring(0, name.length - (".scala").length) + ".ide"
+ val classDir= sourceFiles.get(sourceFile.file) orElse ((defaultClassDir,pkg) match {
+ case (Some(root),Some(pkg)) =>
+ var file = root
+ pkg.split('.').foreach{name =>
+ if (file != null) file = file.lookupName(name, true)
+ }
+ if (file != null) Some(file) else None
+ case _ => None
+ })
+ if (classDir.isEmpty) return Nil
+ val ideFile = classDir.get.lookupPath(name, false)
+ if (ideFile == null) return Nil
+ try {
+ val fis = new ByteArrayInputStream(ideFile.toByteArray)
+ val gis = new GZIPInputStream(fis)
+ val array = new Array[Byte](100)
+ val buf = new scala.collection.mutable.ArrayBuffer[Byte]
+ while ({
+ val read = gis.read(array)
+ if (read == -1) false else {
+ buf ++= array.projection.take(read)
+ true
+ }
+ }) {}
+ val input = new ObjectInputStream(new ByteArrayInputStream(buf.toArray))
+ def read : List[(Int,String)] = {
+ val array0 = input.readObject.asInstanceOf[Array[Int]]
+ val array1 = input.readObject.asInstanceOf[Array[String]]
+ assert(array0.length == array1.length)
+ val buf = new ListBuffer[(Int,String)]
+ val i = array0.elements
+ val j = array1.elements
+ while (i.hasNext) buf += (i.next,j.next)
+ buf.toList
+ }
+ val uses = read
+ val defs = read
+ val defs0 = new LinkedHashMap[Int,Symbol]
+ val ret = new scala.collection.jcl.LinkedHashMap[Int,IdeRef]
+ implicit val cache = new LinkedHashMap[String,Symbol]
+ defs.foreach{
+ case (offset,url) =>
+ val sym = url2sym(url)
+ //assert(sym != null)
+ if (sym != null) {
+ sym.setPos(new OffsetPosition(sourceFile, offset))
+ ret += ((offset,new Definition(sym)))
+ defs0(offset) = sym
+ } else {
+ assert(true)
+ assert(true)
+ }
+ if (sym != null) {
+ }
+ }
+ uses.foreach{
+ case (offset,url) =>
+ if (url.startsWith(":")) {
+ val offset0 = Integer.parseInt(url.substring(1))
+ ret(offset) = (defs0.get(offset0) match {
+ case Some(sym) => new Definition(sym)
+ case None => Internal(offset0)
+ })
+ } else {
+ val sym = url2sym(url)
+ if (sym != null) {
+ ret(offset) = (External(sym))
+ } else {
+ assert(true)
+ assert(true)
+ }
+ }
+ }
+ ret.toList
+ } catch {
+ case ex =>
+ //ex.printStackTrace
+ Nil
+ }
+ }
+
+ def decodeIdeName(string : String) : (Name,String) = {
+ val idx = string.indexOf('[')
+ if (idx != -1) { // a method
+ return (newTermName(string.substring(0, idx)), string.substring(idx))
+ } else if (string.endsWith(";")) {
+ return (newTermName(string.substring(0, string.length - (";").length)), null)
+ } else return (newTypeName(string), null)
+ }
+ def lookupIdeName(owner : Symbol, scope : Scope, string : String) : Symbol = {
+ val (name,params) = decodeIdeName(string)
+ var e = scope.lookupEntry(name)
+ while ((e ne null) && params != null && methodSig(e.sym.info) != params)
+ e = scope.lookupNextEntry(e)
+ if (e != null) return (e.sym)
+ val isPC = owner.isPackageClass
+ if (isPC) {
+ assert(params == null)
+ assert(true)
+ val info = owner.info.asInstanceOf[PackageClassInfoType]
+ val loader = info.loader.asInstanceOf[global.loaders.PackageLoader]
+ if (loader ne null) loader.refresh
+ e = scope.lookupEntry(name)
+ if (e ne null) return (e.sym)
+ }
+ assert(true) // not found!
+ return null
+ }
+ def walk(sourceFile : SourceFile, tree: Tree, uses : scala.collection.mutable.Map[Position,Symbol], defs : LinkedHashMap[Symbol,Position]) : Unit = {
+ def f(t : Tree) : Unit = {
+ def fs(l : List[Tree]) : Unit = {
+ val i = l.elements
+ while (i.hasNext) f(i.next)
+ }
+ def fss(l : List[List[Tree]]) : Unit = {
+ val i = l.elements
+ while (i.hasNext) fs(i.next)
+ }
+ if (t.isInstanceOf[StubTree]) return
+ def asTypeRef = t.tpe.asInstanceOf[TypeRef]
+ val sym = (t,t.tpe) match {
+ case (Super(_,_),SuperType(_,supertp)) if supertp.typeSymbol != NoSymbol && supertp.typeSymbol != null => supertp.typeSymbol
+ case _ if t.symbol != NoSymbol && t.symbol != null => t.symbol
+ case (t : TypeTree, tp) if tp != null && tp.typeSymbol != null && tp.typeSymbol != NoSymbol => tp.typeSymbol
+ case (t : TypeTree, tp) if tp != null && tp.resultType != null && tp.resultType.typeSymbol != null => tp.resultType.typeSymbol
+ case (t, tpe : Type) if tpe != null && (t.symbol eq NoSymbol) && t.isTerm && tpe.termSymbol != null =>
+ assert(true)
+ tpe.termSymbol
+ case (t, tpe : Type) if tpe != null && (t.symbol eq NoSymbol) && tpe.typeSymbol != null =>
+ if (t.tpe.isInstanceOf[TypeRef]) asTypeRef.sym // XXX: looks like a bug
+ else tpe.typeSymbol
+ case _ => NoSymbol
+ }
+ if (sym != null && sym != NoSymbol /* && !sym.hasFlag(SYNTHETIC) */) {
+ var id = sourceFile.identifier(t.pos, global)
+ val doAdd = if (id.isDefined) {
+ if (id.get.charAt(0) == '`') id = Some(id.get.substring(1, id.get.length - 1))
+ val name = sym.name.decode.trim
+ if (name == id.get) true
+ else if (name.endsWith("_=")) {
+ val name1 = name.substring(0, name.length - ("_=").length)
+ name1 == id.get
+ } else false
+ //if (sym.name.toString.contains(id.get)) true else false
+ } else false
+ if (doAdd) {
+
+ if (!uses.contains(t.pos)) {
+ uses(t.pos) = sym
+ } else {
+ val existing = uses(t.pos)
+ if (sym.sourceFile != existing.sourceFile || sym.pos != existing.pos) {
+ (sym,existing) match {
+ case (sym,existing) if sym.pos == existing.pos =>
+ case (sym : TypeSymbol ,_ : ClassSymbol) => uses(t.pos) = sym
+ case (_ : ClassSymbol,_ : TypeSymbol) => // nothing
+ case _ if sym.isModule && existing.isValue => // nothing
+ case _ if sym.isClass && existing.isMethod => // nothing
+ case _ =>
+ assert(true)
+ }
+ }
+ }}
+ }
+ assert(true)
+ t match {
+ case t : DefTree if defs != null && t.symbol != NoSymbol =>
+ if (t.pos != NoPosition)
+ defs.put(t.symbol, t.pos)
+ if (t.symbol.isClass) {
+ val factory = t.symbol.caseFactory
+ if (factory != NoSymbol) {
+ assert(true)
+ defs.put(factory, t.pos)
+ }
+ }
+ else {
+ assert(true)
+ assert(true)
+ }
+ case t : TypeBoundsTree => f(t.lo); f(t.hi)
+ case t : TypeTree if t.original != null =>
+ def h(original : Tree, tpe : Type): Unit = try {
+ if (original.tpe == null)
+ original.tpe = tpe
+ (original) match {
+ case (AppliedTypeTree(_,trees)) if tpe.isInstanceOf[TypeRef] =>
+ val types = tpe.asInstanceOf[TypeRef].args
+ trees.zip(types).foreach{
+ case (tree,tpe) => assert(tree != null && tpe != null); h(tree, tpe)
+ case _ =>
+ }
+ case _ =>
+ }
+ }
+ if (t.original.tpe == null) {
+ val dup = t.original.duplicate
+ h(dup,t.tpe)
+ f(dup)
+ } else f(t.original)
+ ()
+ case _ =>
+ }
+ (t) match {
+ case (t : MemberDef) if t.symbol != null && t.symbol != NoSymbol =>
+ val annotated = if (sym.isModule) sym.moduleClass else sym
+ val i = t.mods.annotations.elements
+ val j = annotated.attributes.elements
+ while (i.hasNext && j.hasNext) {
+ val tree = i.next.constr
+ val ainfo = j.next
+ val sym = ainfo.atp.typeSymbol
+ tree.setType(ainfo.atp)
+ tree.setSymbol(sym)
+ f(tree)
+ }
+
+ case _ =>
+ }
+ t match {
+ case tree: ImplDef =>
+ fs(tree.impl.parents); f(tree.impl.self); fs(tree.impl.body)
+ tree match {
+ case tree : ClassDef => fs(tree.tparams)
+ case _ =>
+ }
+ case tree: PackageDef => fs(tree.stats)
+ case tree: ValOrDefDef =>
+ f(tree.rhs);
+ if (tree.tpt != null) {
+ assert(true)
+ f(tree.tpt)
+ }
+ tree match {
+ case tree : DefDef => fs(tree.tparams); fss(tree.vparamss)
+ case _ =>
+ }
+ case tree: Function => fs(tree.vparams); f(tree.body)
+ case tree : Bind => f(tree.body)
+ case tree : Select =>
+ val qualifier = if (tree.tpe != null && tree.qualifier.tpe == null) {
+ val pre = tree.tpe.prefix
+ val qualifier = tree.qualifier.duplicate
+ qualifier.tpe = pre
+ qualifier
+ } else tree.qualifier
+
+ f(qualifier)
+ case tree : Annotation => f(tree.constr)
+ case tree : Annotated => f(tree.annot); f(tree.arg)
+ case tree : GenericApply => f(tree.fun); fs(tree.args)
+ case tree : UnApply => f(tree.fun); fs(tree.args)
+ case tree : AppliedTypeTree =>
+ if (tree.tpe != null) {
+ val i = tree.tpe.typeArgs.elements
+ val j = tree.args.elements
+ while (i.hasNext && j.hasNext) {
+ val tpe = i.next
+ val arg = j.next
+ if (arg.tpe == null) {
+ arg.tpe = tpe
+ }
+ }
+ }
+ f(tree.tpt); fs(tree.args)
+ case tree : SingletonTypeTree =>
+ if (tree.ref.tpe == null) {
+ val dup = tree.ref.duplicate
+ dup.tpe = tree.tpe
+ f(dup)
+ } else f(tree.ref)
+ case tree : SelectFromTypeTree => f(tree.qualifier)
+ case tree : Typed => f(tree.expr); f(tree.tpt)
+ case tree : Block => fs(tree.stats); f(tree.expr)
+ case tree: CaseDef => f(tree.pat);f(tree.guard);f(tree.body)
+ case tree : Sequence => fs(tree.trees);
+ case tree : Assign => f(tree.lhs); f(tree.rhs);
+ case tree : If => f(tree.cond); f(tree.thenp); f(tree.elsep);
+ case tree : New => f(tree.tpt);
+ case tree : Match => f(tree.selector); fs(tree.cases);
+ case tree : Return => f(tree.expr);
+ case tree : LabelDef => f(tree.rhs);
+ case tree : Throw => f(tree.expr);
+ case tree : Try => f(tree.block); fs(tree.catches); f(tree.finalizer);
+ case tree : Alternative => fs(tree.trees);
+ case tree : TypeDef => f(tree.rhs); fs(tree.tparams)
+ case tree : DocDef => f(tree.definition);
+ case tree: Import => f(tree.expr)
+ case _ =>
+ }
+ }
+ f(tree)
+ }
+ def isRoot(sym : Symbol) = sym == definitions.RootPackage || sym == definitions.RootClass || sym == NoSymbol
+ private var depth = 0
+
+ def methodSig(info : Type) : String = info match {
+ case PolyType(_, result) => methodSig(result)
+ case info =>
+ info.paramTypes.map{t =>
+ if (depth >= 10) {
+ assert(true)
+ assert(true)
+ }
+ assert(!isRoot(t.typeSymbol))
+ //assert(t.symbol != sym && t.symbol != sym.owner)
+ depth += 1
+ val ret = sym2url(t.typeSymbol) +
+ (t match {
+ case TypeRef(_,_,tparams) if !tparams.isEmpty =>
+ tparams.map{t => sym2url(t.typeSymbol)}.mkString("<",":",">")
+ case _ => ""
+ })
+ depth -= 1
+ ret
+ }.mkString("[",":","]") + (info.resultType match {
+ case MethodType(args,result) => "*"
+ case tpe => sym2url(tpe.typeSymbol)
+ })
+ }
+
+ def sym2url(sym : Symbol) : String = {
+ assert(!isRoot(sym))
+ assert(sym != sym.owner)
+ if (sym.isModuleClass) {
+ if (sym.linkedModuleOfClass eq NoSymbol) {
+ if (isRoot(sym.owner)) {
+ return sym.name.toString
+ }
+ throw new Error(sym + " " + sym.moduleClass + " " + sym.isPackage + " " + sym.owner)
+ }
+ return sym2url(sym.linkedModuleOfClass)
+ }
+ (if (isRoot(sym.owner) || sym.owner.isTerm) ""
+ else sym2url(sym.owner) + ".") + sym.name.toString + {
+ //assert(!sym.owner.isTerm)
+ if (sym.isMethod) methodSig(sym.info)
+ else if (!sym.name.isTypeName) ";" else ""
+ }
+ }
+ def url2sym(paths : List[String], owner : Symbol) : Symbol = {
+ if (paths.isEmpty) owner
+ else {
+ // decode name
+ val owner0 = if (owner.isModule) {
+ assert(owner.moduleClass ne NoSymbol)
+ owner.moduleClass
+ } else owner
+
+ val sym = lookupIdeName(owner0, owner0.info.decls, paths.head)
+ if (sym == null) {
+ assert(true)
+ return null
+ }
+ else url2sym(paths.tail, sym)
+ }
+ }
+ def url2sym(url : String)(implicit cache : LinkedHashMap[String,Symbol]) : Symbol = {
+ if (cache != null) cache.get(url) match {
+ case Some(sym) => return sym
+ case _ =>
+ }
+
+
+ // decode the string.
+ var url0 = url
+ var idx = url.lastIndexOf('[') // could be method
+ val paths = new scala.collection.mutable.ListBuffer[String]
+ while (url0 ne null) {
+ val jdx = url0.indexOf('.')
+ if (jdx == -1 || (idx != -1 && jdx > idx)) {
+ paths append url0
+ url0 = null
+ } else {
+ paths append url0.substring(0, jdx)
+ if (idx != -1) idx = idx - (jdx + 1)
+ url0 = url0.substring(jdx + 1)
+ }
+ }
+ if (definitions.RootClass eq null) new global.Run
+ val result = url2sym(paths.toList, definitions.RootClass)
+ if (result != null && cache != null) cache(url) = result
+ return result
+ }
+ class GenIdeMapPhase(prev: Phase) extends StdPhase(prev) {
+ def apply(unit: global.CompilationUnit): Unit = {
+ if (global.settings.noide.value) return
+ global.informProgress("gen-ide-map for " + unit)
+ val path = unit.source.file match {
+ case file : PlainFile => file.path
+ case _ => return // don't do anything.
+ }
+ assert(path.endsWith(".scala"))
+
+ val sources = global.settings.sourcepath.value.split(File.pathSeparator)
+ val i = sources.elements
+ while (i.hasNext) {
+ val sourcePath = i.next
+ if (path.startsWith(sourcePath)) {
+ val usePath = path.substring(sourcePath.length, path.length - (".scala").length) + ".ide"
+ val uses = new LinkedHashMap[Position,Symbol]
+ val defs = new LinkedHashMap[Symbol,Position]
+ walk(unit.source, unit.body, uses, defs)
+ // all populated, now what?
+ // populate ownerTree
+
+ val writeUses = uses.projection.filter(_._1 != NoPosition).map{
+ case (p : OffsetPosition, sym) =>
+ (p.offset0, if (sym.sourceFile == unit.source.file) {
+ // internal reference
+ if (!sym.pos.offset.isDefined) Console.println("ERROR: " + sym + " in " + sym.sourceFile)
+ ":" + sym.pos.offset.getOrElse(0)
+ } else {
+ val url = sym2url(sym)
+ url
+ })
+ }.toList
+ object okDefs extends LinkedHashMap[Symbol,Boolean] {
+ def has(sym : Symbol) : Boolean = get(sym) match {
+ case Some(value) => value
+ case _ =>
+ if (sym eq definitions.RootClass) return true
+ if (sym.isModuleClass) {
+ if (sym.linkedModuleOfClass ne NoSymbol)
+ return has(sym.linkedModuleOfClass)
+ //System.err.println(sym + " is module class")
+ return false
+ }
+ val owner = sym.owner
+ if (owner eq NoSymbol) return false
+ if (!owner.isClass && !owner.isStable) return false
+ def fail = {
+ put(sym, false)
+ false
+ }
+ if (!has(owner)) return fail
+ var e = owner.info.decls.lookupEntry(sym.name)
+ while (e != null&&e.sym != sym) e = owner.info.decls.lookupNextEntry(e)
+ if (e == null) return fail
+ put(sym, true)
+ return true
+ }
+ }
+
+ val writeDefs = defs.projection.filter{
+ case (sym,OffsetPosition(_,_)) if okDefs.has(sym) => true
+ case _ => false
+ }.map{
+ case (sym,OffsetPosition(source,offset)) if unit.source == source => (offset,sym2url(sym))
+ }.toList
+
+ val file = new File(global.settings.outdir.value, usePath)
+ file.mkdirs
+ if (file.exists) file.delete
+
+ val out = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(file)))
+ //Console.println("GZIP: " + out)
+ def write(list : List[(Int,String)]) = {
+ val array0 = list.projection.map(_._1).toArray
+ val array1 = list.projection.map(_._2).toArray
+ out.writeObject(array0)
+ out.writeObject(array1)
+ }
+ write(writeUses)
+ write(writeDefs)
+ out.close
+ ideMaps.removeKey(unit.source.file)
+ return
+ }
+ }
+ //Console.println("Cannot find root source of " + path + " so cannot generate map file")
+ }
+ }
+ case class ProjectAdapter(other : Global) {
+ def translate(sym : global.Symbol) : other.Symbol = {
+ assert(sym != NoSymbol)
+ val from = sym2url(sym)
+ // ya, its this easy!
+ return other.generateIdeMaps.url2sym(from)(null)
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/symtab/Scopes.scala b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
index c0817a65e8..afdd284629 100644
--- a/src/compiler/scala/tools/nsc/symtab/Scopes.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Scopes.scala
@@ -10,10 +10,6 @@ trait Scopes {
self: SymbolTable =>
class ScopeEntry(val sym: Symbol, val owner: Scope) {
- /** hook to notify IDE that new symbol has been added to this scope */
- owner.enter00(sym);
-
-
/** the next entry in the hash bucket
*/
var tail: ScopeEntry = _
@@ -46,13 +42,16 @@ trait Scopes {
*/
def newScope(initElems: ScopeEntry): Scope = new NormalScope(initElems)
final def newScope: Scope = newScope(null: ScopeEntry)
- //final def newScope(base: Scope) : Scope = newScope(base.elems)
- final def newScope(base: Scope) : Scope = if(base eq null) newScope else newScope(base.elems)
+ def newClassScope = newScope // for use in ClassInfoType creation
+ def newTempScope = newScope(null : ScopeEntry)
+
+ final def newScope(base: Scope) : Scope = newScope(base.elems)
final def newScope(decls: List[Symbol]) : Scope = {
val ret = newScope
decls.foreach(d => ret.enter(d))
ret
}
+ def newThrowAwayScope(decls : List[Symbol]) : Scope = newScope(decls)
private class NormalScope(initElems: ScopeEntry) extends Scope(initElems)
@@ -60,11 +59,6 @@ trait Scopes {
var elems: ScopeEntry = initElems
- /** hook for IDE
- */
- protected def enter0(sym: Symbol) {}
- private[Scopes] def enter00(sym: Symbol) = enter0(sym)
-
/** The number of times this scope is neted in another
*/
private var nestinglevel = 0
@@ -104,13 +98,13 @@ trait Scopes {
def this(decls: List[Symbol]) = {
this()
- decls foreach enter
+ decls.foreach(sym => enter(sym))
}
/** Returns a new scope with the same content as this one. */
def cloneScope: Scope = {
val clone = newScope
- this.toList foreach clone.enter
+ this.toList.foreach(sym => clone.enter(sym))
clone
}
@@ -147,7 +141,7 @@ trait Scopes {
*
* @param sym ...
*/
- def enter(sym: Symbol) { enter(newScopeEntry(sym, this)) }
+ def enter(sym: Symbol) : Symbol = { enter(newScopeEntry(sym, this)); sym }
/** enter a symbol, asserting that no symbol with same name exists in scope
*
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 450695b80e..3f251d477a 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -99,6 +99,9 @@ abstract class SymbolLoaders {
protected var root: Symbol = _
def enterPackage(name: String, completer: SymbolLoader) {
+ if (inIDE && root.info.decls.lookup(newTermName(name)) != NoSymbol) {
+ return // refresh
+ }
val pkg = root.newPackage(NoPosition, newTermName(name))
pkg.moduleClass.setInfo(completer)
pkg.setInfo(pkg.moduleClass.tpe)
@@ -109,6 +112,10 @@ abstract class SymbolLoaders {
def enterClassAndModule(name: String, completer: SymbolLoader): Symbol = {
val owner = if (root.isRoot) definitions.EmptyPackageClass else root
val className = newTermName(name)
+ if (inIDE && owner.info.decls.lookup(name) != NoSymbol) {
+ // refresh
+ return owner.info.decls.lookup(name)
+ }
assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullNameString + "." + name)
val clazz = owner.newClass(NoPosition, name.toTypeName)
val module = owner.newModule(NoPosition, name)
@@ -126,13 +133,20 @@ abstract class SymbolLoaders {
//System.out.println("Added class " + clazz.fullNameString);
clazz
}
-
+ def checkAdd(name0 : String) = {
+ var name = name0
+ while (name.indexOf('$') != -1) {
+ name = name.substring(0, name.indexOf('$'))
+ }
+ }
protected def doComplete(root: Symbol) {
assert(root.isPackageClass, root)
this.root = root
val scope = newScope
- root.setInfo(new PackageClassInfoType(scope, root))
-
+ root.setInfo(new PackageClassInfoType(scope, root, this))
+ refresh
+ }
+ def refresh = {
/** Is the given name a valid input file base name? */
def isValid(name: String): Boolean =
name.length() > 0 && !name.endsWith("$class") && (settings.XbytecodeRead.value ||
@@ -246,23 +260,31 @@ abstract class SymbolLoaders {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
}
protected def doComplete(root: Symbol) {
- typeParser.parse(typ, root)
+ typeParser.parse(typ, root.asInstanceOf)
}
protected def kindString: String = typ.FullName
protected def sourceString = typ.Assembly.FullName
}
+ // IDE hook.
+ protected def completeClassfile(root : Symbol, loader : ClassfileLoader)(f : => Unit) : Unit = f
+ protected def completeSourcefile(root : Symbol, loader : SourcefileLoader)(f : => Unit) : Unit = f
- class ClassfileLoader(classFile: AbstractFile, override val sourceFile: AbstractFile, sourcePath0: AbstractFile) extends SymbolLoader {
- //throw new Error("classfile = " + classFile + "; sourcefile = " + sourceFile + "; sourcepath = " + sourcePath0)
+ class ClassfileLoader(val classFile: AbstractFile, override val sourceFile: AbstractFile, sourcePath0: AbstractFile) extends SymbolLoader {
private object classfileParser extends ClassfileParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
override def sourcePath = sourcePath0 /* could be null */
}
protected def doComplete(root: Symbol) {
- classfileParser.parse(classFile, root)
- if (sourceFile ne null) root match {
- case clazz : ClassSymbol => clazz.sourceFile = sourceFile
- case _ =>
+ completeClassfile(root, this) {
+ classfileParser.parse(classFile, root)
+ }
+ root match {
+ case clazz : ClassSymbol =>
+ global.attachSourceToClass(clazz, this, if (sourceFile ne null) sourceFile else clazz.sourceFile)
+ case _ =>
+ }
+ if (root.sourceFile ne null) {
+ global.generateIdeMaps.sourceFiles(root.sourceFile) = classFile.container
}
}
protected def kindString: String = "class file"
@@ -275,8 +297,9 @@ abstract class SymbolLoaders {
}
*/
class SourcefileLoader(override val sourceFile: AbstractFile) extends SymbolLoader {
- protected def doComplete(root: Symbol): Unit =
+ protected def doComplete(root: Symbol): Unit = completeSourcefile(root, this){
global.currentRun.compileLate(sourceFile)
+ }
protected def kindString: String = "source file"
protected def sourceString = sourceFile.toString()
}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index 87808a45fb..d324bf6312 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -28,8 +28,10 @@ abstract class SymbolTable extends Names
/** Are we compiling for .NET*/
def forMSIL: Boolean
- /** are we in a lampion presentation compiler? then disable caching. */
+ /** are we in a lampion presentation compiler? cannot get inIDE flag from global */
def inIDE : Boolean
+ protected def trackTypeIDE(sym : Symbol) : Boolean = true
+ protected def recycle(sym : Symbol) : Symbol = sym
/** A period is an ordinal number for a phase in a run.
* Phases in later runs have higher periods than phases in earlier runs.
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index 5cba998f38..cb990a0d27 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc.symtab
import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.util.{Position, NoPosition, SourceFile}
+import scala.tools.nsc.util.{Position, NoPosition, SourceFile, BatchSourceFile}
import Flags._
trait Symbols {
@@ -50,7 +50,7 @@ trait Symbols {
def pos = rawpos
def setPos(pos: Position): this.type = { this.rawpos = pos; this }
- def namePos(source: SourceFile) = {
+ def namePos(source: BatchSourceFile) = {
val pos: Int = this.pos.offset.get(-1)
val buf = source.content
if (pos == -1) -1
@@ -496,6 +496,9 @@ trait Symbols {
this
}
+ /** check if info has been set before, used in the IDE */
+ def rawInfoSafe : Option[Type] = if (infos == null) None else Some(rawInfo)
+
/** Return info without checking for initialization or completing */
def rawInfo: Type = {
var infos = this.infos
@@ -503,7 +506,7 @@ trait Symbols {
val curPeriod = currentPeriod
val curPid = phaseId(curPeriod)
- if (validTo != NoPeriod) {
+ if (!inIDE && validTo != NoPeriod) {
// skip any infos that concern later phases
while (curPid < phaseId(infos.validFrom) && infos.prev != null)
@@ -670,6 +673,10 @@ trait Symbols {
def suchThat(cond: Symbol => Boolean): Symbol = {
val result = filter(cond)
+ // @S: seems like NoSymbol has the overloaded flag????
+ if (inIDE && (this eq result) && result != NoSymbol && (result hasFlag OVERLOADED)) {
+ return result
+ }
assert(!(result hasFlag OVERLOADED), result.alternatives)
result
}
@@ -698,10 +705,12 @@ trait Symbols {
/** The primary constructor of a class */
def primaryConstructor: Symbol = {
- val c = info.decl(
+ var c = info.decl(
if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR
else nme.CONSTRUCTOR)
- if (c hasFlag OVERLOADED) c.alternatives.head else c
+ c = if (c hasFlag OVERLOADED) c.alternatives.head else c
+ //assert(c != NoSymbol)
+ c
}
/** The self symbol of a class with explicit self type, or else the
@@ -953,8 +962,15 @@ trait Symbols {
newTermName(fullNameString('$') + nme.EXPAND_SEPARATOR_STRING + name)
}
- def sourceFile: AbstractFile =
- (if (isModule) moduleClass else toplevelClass).sourceFile
+ def sourceFile: AbstractFile = {
+ var ret = (if (isModule) moduleClass else toplevelClass).sourceFile
+ if (ret == null && inIDE && !isModule) this match {
+ case sym : ModuleSymbol if sym.referenced != null =>
+ ret = sym.referenced.sourceFile
+ case _ =>
+ }
+ ret
+ }
def sourceFile_=(f: AbstractFile): Unit =
throw new Error("sourceFile_= inapplicable for " + this)
@@ -1164,7 +1180,8 @@ trait Symbols {
}
def setLazyAccessor(sym: Symbol): TermSymbol = {
- assert(hasFlag(LAZY) && referenced == NoSymbol, this)
+ // @S: in IDE setLazyAccessor can be called multiple times on same sym
+ assert(hasFlag(LAZY) && (referenced == NoSymbol || referenced == sym), this)
referenced = sym
this
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 3cdcc226e8..af9d7550ad 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -125,8 +125,12 @@ trait Types {
override def isError = underlying.isError
override def isErroneous = underlying.isErroneous
override def isStable: Boolean = underlying.isStable
+ override def finalResultType = underlying.finalResultType
+ override def paramSectionCount = underlying.paramSectionCount
+ override def paramTypes = underlying.paramTypes
override def termSymbol = underlying.termSymbol
override def termSymbolDirect = underlying.termSymbolDirect
+ override def typeParams = underlying.typeParams
override def typeSymbol = underlying.typeSymbol
override def typeSymbolDirect = underlying.typeSymbolDirect
@deprecated override def symbol = underlying.symbol
@@ -389,6 +393,7 @@ trait Types {
/** The type of `sym', seen as a member of this type. */
def memberType(sym: Symbol): Type = {
+ trackTypeIDE(sym)
//@M don't prematurely instantiate higher-kinded types, they will be instantiated by transform, typedTypeApply, etc. when really necessary
sym.tpeHK match {
case ov @ OverloadedType(pre, alts) =>
@@ -596,7 +601,7 @@ trait Types {
e = decls.lookupNextEntry(e)
}
if (alts.isEmpty) sym
- else baseClasses.head.newOverloaded(this, alts)
+ else (baseClasses.head.newOverloaded(this, alts))
}
/**
@@ -648,7 +653,7 @@ trait Types {
if (self eq null) self = this.narrow;
(self.memberType(member) matches self.memberType(sym))
})) {
- members = newScope(List(member, sym))
+ members = newThrowAwayScope(List(member, sym))
}
} else {
var prevEntry = members lookupEntry sym.name
@@ -684,7 +689,7 @@ trait Types {
} else {
if (util.Statistics.enabled) multMemberCount = multMemberCount + 1;
//val pre = if (this.typeSymbol.isClass) this.typeSymbol.thisType else this;
- baseClasses.head.newOverloaded(this, members.toList)
+ (baseClasses.head.newOverloaded(this, members.toList))
}
}
@@ -724,7 +729,11 @@ trait Types {
override def baseType(clazz: Symbol): Type = supertype.baseType(clazz)
override def closure: Array[Type] = supertype.closure
override def closureDepth: Int = supertype.closureDepth
- override def baseClasses: List[Symbol] = supertype.baseClasses
+ override def baseClasses: List[Symbol] = {
+ val supertype = this.supertype
+ if (inIDE && supertype == null) Nil
+ else supertype.baseClasses
+ }
override def isNotNull = supertype.isNotNull
}
@@ -852,6 +861,7 @@ trait Types {
private var underlyingCache: Type = _
private var underlyingPeriod = NoPeriod
override def underlying: Type = {
+ // this kind of caching here won't work in the IDE
if (inIDE) return pre.memberType(sym).resultType
val period = underlyingPeriod
if (period != currentPeriod) {
@@ -998,7 +1008,7 @@ trait Types {
"\n --- because ---\n" + ex.getMessage())
}
val period = closurePeriod;
- if (period != currentPeriod) {
+ if (period != currentPeriod) { // no caching in IDE
closurePeriod = currentPeriod
if (!isValidForBaseClasses(period)) {
closureCache = null
@@ -1234,7 +1244,7 @@ trait Types {
override def kind = "ClassInfoType"
}
- class PackageClassInfoType(decls: Scope, clazz: Symbol)
+ class PackageClassInfoType(decls: Scope, clazz: Symbol, val loader : LazyType)
extends ClassInfoType(List(), decls, clazz)
/** A class representing a constant type.
@@ -1562,6 +1572,10 @@ A type's typeSymbol should never be inspected directly.
override def baseType(clazz: Symbol): Type = resultType.baseType(clazz)
override def narrow: Type = resultType.narrow
+ override def deconst =
+ if (inIDE) PolyType(typeParams, resultType.deconst)
+ else super.deconst
+
override def finalResultType: Type = resultType.finalResultType
/** @M: abstractTypeSig now wraps a TypeBounds in a PolyType
@@ -1780,8 +1794,10 @@ A type's typeSymbol should never be inspected directly.
}
/** The canonical creator for this-types */
- def mkThisType(sym: Symbol): Type =
- if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType)
+ def mkThisType(sym: Symbol): Type = {
+ class UniqueThisType extends ThisType(sym) with UniqueType
+ if (phase.erasedTypes) sym.tpe else unique(new UniqueThisType)
+ }
/** The canonical creator for single-types */
def singleType(pre: Type, sym: Symbol): Type = {
@@ -1795,32 +1811,41 @@ A type's typeSymbol should never be inspected directly.
if (pre1 ne pre) sym1 = rebind(pre1, sym1)
if (checkMalformedSwitch && !pre1.isStable && !pre1.isError)
throw new MalformedType(pre, sym.nameString)
- else
- unique(new SingleType(pre1, sym1) with UniqueType)
+ else {
+ class UniqueSingleType extends SingleType(pre1, sym1) with UniqueType
+ unique(new UniqueSingleType)
+ }
}
}
/** The canonical creator for super-types */
def mkSuperType(thistp: Type, supertp: Type): Type =
if (phase.erasedTypes) supertp
- else unique(new SuperType(thistp, supertp) with UniqueType)
+ else {
+ class UniqueSuperType extends SuperType(thistp, supertp) with UniqueType
+ unique(new UniqueSuperType)
+ }
/** The canonical creator for type bounds */
- def mkTypeBounds(lo: Type, hi: Type): TypeBounds =
- unique(new TypeBounds(lo, hi) with UniqueType)
+ def mkTypeBounds(lo: Type, hi: Type): TypeBounds = {
+ class UniqueTypeBounds extends TypeBounds(lo, hi) with UniqueType
+ unique(new UniqueTypeBounds)
+ }
- def refinementOfClass(clazz: Symbol, parents: List[Type], decls: Scope) =
- new RefinedType(parents, decls) {
+ def refinementOfClass(clazz: Symbol, parents: List[Type], decls: Scope) = {
+ class RefinementOfClass extends RefinedType(parents, decls) {
override def typeSymbol: Symbol = clazz
@deprecated override def symbol: Symbol = clazz
}
+ new RefinementOfClass
+ }
/** the canonical creator for a refined type with a given scope */
def refinedType(parents: List[Type], owner: Symbol, decls: Scope): Type = {
if (phase.erasedTypes)
if (parents.isEmpty) ObjectClass.tpe else parents.head
else {
- val clazz = owner.newRefinementClass(NoPosition)
+ val clazz = recycle(owner.newRefinementClass(if (inIDE) owner.pos else NoPosition))
val result = refinementOfClass(clazz, parents, decls)
clazz.setInfo(result)
result
@@ -1834,7 +1859,7 @@ A type's typeSymbol should never be inspected directly.
* @return ...
*/
def refinedType(parents: List[Type], owner: Symbol): Type =
- refinedType(parents, owner, newScope)
+ refinedType(parents, owner, newTempScope)
def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) =
if ((parents eq original.parents) && (decls eq original.decls)) original
@@ -1851,8 +1876,10 @@ A type's typeSymbol should never be inspected directly.
}
/** the canonical creator for a constant type */
- def mkConstantType(value: Constant): ConstantType =
- unique(new ConstantType(value) with UniqueType)
+ def mkConstantType(value: Constant): ConstantType = {
+ class UniqueConstantType extends ConstantType(value) with UniqueType
+ unique(new UniqueConstantType)
+ }
/** The canonical creator for typerefs
* todo: see how we can clean this up a bit
@@ -1892,8 +1919,10 @@ A type's typeSymbol should never be inspected directly.
}
/** create a type-ref as found, without checks or rebinds */
- def rawTypeRef(pre: Type, sym: Symbol, args: List[Type]): Type =
- unique(new TypeRef(pre, sym, args) with UniqueType)
+ def rawTypeRef(pre: Type, sym: Symbol, args: List[Type]): Type = {
+ class rawTypeRef extends TypeRef(pre, sym, args) with UniqueType
+ unique(new rawTypeRef)
+ }
/** The canonical creator for implicit method types */
def ImplicitMethodType(paramTypes: List[Type], resultType: Type): ImplicitMethodType =
@@ -2279,9 +2308,14 @@ A type's typeSymbol should never be inspected directly.
if ((pre eq NoType) || (pre eq NoPrefix) || !clazz.isClass) mapOver(tp)
//@M! see test pos/tcpoly_return_overriding.scala why mapOver is necessary
else {
- def throwError =
- throw new Error("" + tp + sym.locationString +
- " cannot be instantiated from " + pre.widen);
+ def throwError : Nothing =
+ // IDE: in the IDE, this will occur because we complete everything
+ // too eagerly. It doesn't matter, the error will be fixed when
+ // the node is re-typed.
+ if (inIDE) throw new TypeError("internal error: " + tp + " in " + sym.owner +
+ " cannot be instantiated from " + pre.widen)
+ else throw new Error("" + tp + sym.locationString +
+ " cannot be instantiated from " + pre.widen)
def instParam(ps: List[Symbol], as: List[Type]): Type =
if (ps.isEmpty) throwError
else if (sym eq ps.head)
@@ -2564,7 +2598,8 @@ A type's typeSymbol should never be inspected directly.
object adaptToNewRunMap extends TypeMap {
private def adaptToNewRun(pre: Type, sym: Symbol): Symbol = {
- if (sym.isModuleClass && !phase.flatClasses) {
+ if (inIDE) sym // dependecies adapted at a finer granularity in IDE
+ else if (sym.isModuleClass && !phase.flatClasses) {
adaptToNewRun(pre, sym.sourceModule).moduleClass
} else if ((pre eq NoPrefix) || (pre eq NoType) || sym.owner.isPackageClass) {
sym
@@ -2972,8 +3007,6 @@ A type's typeSymbol should never be inspected directly.
if (subsametypeRecursions == 0) undoLog = List()
}
- /** hook for IDE */
- protected def trackTypeIDE(sym : Symbol) : Boolean = true;
/** Does this type have a prefix that begins with a type variable */
def beginsWithTypeVar(tp: Type): Boolean = tp match {
@@ -3473,7 +3506,7 @@ A type's typeSymbol should never be inspected directly.
else {
def lubBounds(bnds: List[TypeBounds]): TypeBounds =
mkTypeBounds(glb(bnds map (_.lo), depth-1), lub(bnds map (_.hi), depth-1))
- proto.owner.newAbstractType(proto.pos, proto.name)
+ recycle(proto.owner.newAbstractType(proto.pos, proto.name))
.setInfo(lubBounds(symtypes map (_.bounds)))
}
}
@@ -3656,10 +3689,11 @@ A type's typeSymbol should never be inspected directly.
val g = glb(as, depth-1)
if (l <:< g) l
else {
+ val owner = commonOwner(as)
val qvar =
- commonOwner(as).newAbstractType(NoPosition, freshTypeName())
+ recycle(owner.newAbstractType(if (inIDE) owner.pos else NoPosition, freshTypeName()).setFlag(EXISTENTIAL))
.setInfo(TypeBounds(g, l))
- .setFlag(EXISTENTIAL)
+
capturedParams += qvar
qvar.tpe
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index bf3118b07f..ec00809529 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -49,7 +49,7 @@ abstract class ClassfileParser {
protected var hasMeta: Boolean = _ // does class file contain jaco meta attribute?s
protected var busy: Boolean = false // lock to detect recursive reads
protected var classTParams = Map[Name,Symbol]()
- protected val fresh = new FreshNameCreator
+ protected val fresh = new FreshNameCreator.Default
private object metaParser extends MetaParser {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
@@ -59,7 +59,7 @@ abstract class ClassfileParser {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
- def parse(file: AbstractFile, root: Symbol) {
+ def parse(file: AbstractFile, root: Symbol) = try {
def handleError(e: Exception) = {
if (settings.debug.value) e.printStackTrace() //debug
throw new IOException("class file '" + in.file + "' is broken\n(" + {
@@ -96,6 +96,7 @@ abstract class ClassfileParser {
case e: FatalError => handleError(e)
case e: RuntimeException => handleError(e)
}
+ } finally {
busy = false
}
@@ -345,8 +346,8 @@ abstract class ClassfileParser {
if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
val parents = superType :: ifaces
- instanceDefs = newScope
- staticDefs = newScope
+ instanceDefs = newClassScope
+ staticDefs = newClassScope
val classInfo = ClassInfoType(parents, instanceDefs, clazz)
val staticInfo = ClassInfoType(List(), staticDefs, statics)
@@ -632,7 +633,8 @@ abstract class ClassfileParser {
if ((sourceFile0 ne null) && (clazz.sourceFile eq null)) {
clazz.sourceFile = sourceFile0
}
- staticModule.moduleClass.sourceFile = clazz.sourceFile
+ if (!inIDE || staticModule.moduleClass != NoSymbol)
+ staticModule.moduleClass.sourceFile = clazz.sourceFile
}
case nme.AnnotationDefaultATTR =>
sym.attributes =
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 84f7d37f83..a60333f005 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -47,6 +47,14 @@ abstract class Pickler extends SubComponent {
add(sym, pickle)
add(sym.linkedSym, pickle)
pickle.finish
+ val doPickleHash = global.doPickleHash
+ if (doPickleHash) {
+ var i = 0
+ while (i < pickle.writeIndex) {
+ unit.pickleHash += pickle.bytes(i).toLong // toLong needed to work around bug
+ i = i + 1
+ }
+ }
case _ =>
}
}
@@ -56,10 +64,10 @@ abstract class Pickler extends SubComponent {
private class Pickle(rootName: Name, rootOwner: Symbol)
extends PickleBuffer(new Array[Byte](4096), -1, 0) {
- import scala.collection.mutable.HashMap
+ import scala.collection.jcl.LinkedHashMap
private var entries = new Array[AnyRef](256)
private var ep = 0
- private val index = new HashMap[AnyRef, int]
+ private val index = new LinkedHashMap[AnyRef, int]
/** Is root in symbol.owner*?
*
@@ -326,10 +334,6 @@ abstract class Pickler extends SubComponent {
*/
private def writeSymInfo(sym: Symbol): Int = {
var posOffset = 0
- if (sym.pos != NoPosition && sym.owner.isClass && !sym.pos.offset.isEmpty) {
- writeNat(sym.pos.offset.get)
- posOffset = PosOffset
- }
writeRef(sym.name)
writeRef(sym.owner)
writeNat((sym.flags & PickledFlags).asInstanceOf[int])
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
index b140da032c..c8fbe40009 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/UnPickler.scala
@@ -66,8 +66,8 @@ abstract class UnPickler {
}
/** The scope associated with given symbol */
- private def symScope(sym: Symbol) = symScopes.get(sym) match {
- case None => val s = newScope; symScopes(sym) = s; s
+ private def symScope(sym: Symbol)(f : => Scope) = symScopes.get(sym) match {
+ case None => val s = f; symScopes(sym) = s; s
case Some(s) => s
}
@@ -164,7 +164,6 @@ abstract class UnPickler {
if (tag > PosOffset) readNat
else -1
}
- val pos: Position = NoPosition
val name = readNameRef()
val owner = readSymbolRef()
val flags = readNat()
@@ -176,17 +175,17 @@ abstract class UnPickler {
}
(tag % PosOffset) match {
case TYPEsym =>
- sym = owner.newAbstractType(pos, name)
+ sym = owner.newAbstractType(NoPosition, name)
case ALIASsym =>
- sym = owner.newAliasType(pos, name)
+ sym = owner.newAliasType(NoPosition, name)
case CLASSsym =>
sym =
if (name == classRoot.name && owner == classRoot.owner)
(if ((flags & MODULE) != 0) moduleRoot.moduleClass
- else classRoot).setPos(pos)
+ else classRoot)
else
- if ((flags & MODULE) != 0) owner.newModuleClass(pos, name)
- else owner.newClass(pos, name)
+ if ((flags & MODULE) != 0) owner.newModuleClass(NoPosition, name)
+ else owner.newClass(NoPosition, name)
if (readIndex != end) sym.typeOfThis = new LazyTypeRef(readNat())
case MODULEsym =>
val clazz = at(inforef, readType).typeSymbol
@@ -195,13 +194,13 @@ abstract class UnPickler {
else {
assert(clazz.isInstanceOf[ModuleClassSymbol], clazz)
val mclazz = clazz.asInstanceOf[ModuleClassSymbol]
- val m = owner.newModule(pos, name, mclazz)
+ val m = owner.newModule(NoPosition, name, mclazz)
mclazz.setSourceModule(m)
m
}
case VALsym =>
sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot.resetFlag(MODULE)
- else owner.newValue(pos, name)
+ else owner.newValue(NoPosition, name)
case _ =>
errorBadSignature("bad symbol tag: " + tag)
}
@@ -214,7 +213,7 @@ abstract class UnPickler {
else new LazyTypeRef(inforef))
if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&
!sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter)
- symScope(sym.owner) enter sym
+ symScope(sym.owner)(newScope) enter sym
}
sym
}
@@ -245,13 +244,13 @@ abstract class UnPickler {
val dcls = symScope(clazz)
new RefinedType(ps, dcls) { override def symbol = clazz }
*/
- new RefinedType(until(end, readTypeRef), symScope(clazz)) {
- @deprecated override def symbol = clazz
- override def typeSymbol = clazz
+ new RefinedType(until(end, readTypeRef), symScope(clazz)(newTempScope)) {
+ @deprecated override def symbol = clazz
+ override def typeSymbol = clazz
}
case CLASSINFOtpe =>
val clazz = readSymbolRef()
- ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)
+ ClassInfoType(until(end, readTypeRef), symScope(clazz)(newClassScope), clazz)
case METHODtpe =>
val restpe = readTypeRef()
MethodType(until(end, readTypeRef), restpe)
@@ -556,14 +555,17 @@ abstract class UnPickler {
at(readNat(), readTreeAttrib)
private def errorBadSignature(msg: String) =
- throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
+ if (inIDE) throw new TypeError(msg)
+ else throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
private class LazyTypeRef(i: Int) extends LazyType {
private val definedAtRunId = currentRunId
+ // In IDE, captures class files dependencies so they can be reloaded when their dependencies change.
+ private val ideHook = unpickleIDEHook
override def complete(sym: Symbol) {
- val tp = at(i, readType)
+ val tp = ideHook(at(i, readType))
sym setInfo tp
- if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
+ if (!inIDE && currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))
}
override def load(sym: Symbol) { complete(sym) }
}
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 784a89658a..26747e58dc 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -20,9 +20,8 @@ import classfile.UnPickler
abstract class TypeParser {
val global: Global
-
- import global._
- import loaders.clrTypes
+ import global.loaders.clrTypes
+ import clrTypes.global._
//##########################################################################
@@ -75,7 +74,7 @@ abstract class TypeParser {
val a = attrs(0).asInstanceOf[MSILAttribute];
assert (a.getConstructor() == clrTypes.SYMTAB_CONSTR);
val symtab = a.getConstructorArguments()(0).asInstanceOf[Array[Byte]]
- unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName);
+ unpickler.unpickle(symtab, 0, clazz.asInstanceOf, staticModule.asInstanceOf, typ.FullName);
val mClass = clrTypes.getType(typ.FullName + "$");
if (mClass != null) {
clrTypes.types(statics) = mClass;
@@ -91,8 +90,8 @@ abstract class TypeParser {
else if (typ.IsInterface()) definitions.ObjectClass.tpe
else definitions.AnyClass.tpe; // this is System.Object
val parents = superType :: ifaces.map(getCLRType).toList
- instanceDefs = newScope
- staticDefs = newScope
+ instanceDefs = newClassScope
+ staticDefs = newClassScope
val classInfo = ClassInfoType(parents, instanceDefs, clazz)
val staticInfo = ClassInfoType(List(), staticDefs, statics)
@@ -110,7 +109,7 @@ abstract class TypeParser {
|| ntype.IsNestedFamANDAssem)
|| ntype.IsInterface)
{
- val loader = new loaders.MSILTypeLoader(ntype)
+ val loader = new global.loaders.MSILTypeLoader(ntype)
val nclazz = statics.newClass(NoPosition, ntype.Name.toTypeName)
val nmodule = statics.newModule(NoPosition, ntype.Name)
nclazz.setInfo(loader)
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 5efd37cf68..2bff857011 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -14,7 +14,10 @@ import Flags._
abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
import global._ // the global environment
import definitions._ // standard classes and methods
- import typer.{typed} // methods to type trees
+ // @S: XXX: why is this here? earsure is a typer, if you comment this
+ // out erasure still works, uses its own typed methods.
+ lazy val typerXXX = this.typer
+ import typerXXX.{typed} // methods to type trees
import posAssigner.atPos // for filling in tree positions
val phaseName: String = "erasure"
@@ -501,6 +504,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
//if (settings.debug.value)
Console.println("exception when typing " + tree);
throw ex
+ case er: TypeError =>
+ Console.println("exception when typing " + tree)
+ Console.println(er.msg + " in file " + context.owner.sourceFile)
+ er.printStackTrace
+ throw new Error
}
def adaptCase(cdef: CaseDef): CaseDef = {
val body1 = adaptToType(cdef.body, tree1.tpe)
@@ -560,16 +568,16 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
val tpe2 = atPhase(currentRun.refchecksPhase.next)(root.thisType.memberType(sym2))
if (!tpe1.isErroneous && !tpe2.isErroneous)
unit.error(
- if (sym1.owner == root) sym1.pos else root.pos,
- (if (sym1.owner == sym2.owner) "double definition:\n"
- else if (sym1.owner == root) "name clash between defined and inherited member:\n"
- else "name clash between inherited members:\n") +
- sym1 + ":" + tpe1 +
- (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
- sym2 + ":" + tpe2 +
- (if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) +
- "\nhave same type" +
- (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
+ if (sym1.owner == root) sym1.pos else root.pos,
+ (if (sym1.owner == sym2.owner) "double definition:\n"
+ else if (sym1.owner == root) "name clash between defined and inherited member:\n"
+ else "name clash between inherited members:\n") +
+ sym1 + ":" + tpe1 +
+ (if (sym1.owner == root) "" else sym1.locationString) + " and\n" +
+ sym2 + ":" + tpe2 +
+ (if (sym2.owner == root) " at line " + (sym2.pos).line.get else sym2.locationString) +
+ "\nhave same type" +
+ (if (tpe1 =:= tpe2) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe)))
sym1.setInfo(ErrorType)
}
@@ -873,7 +881,19 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer {
tpt.tpe = erasure(tree.symbol.tpe).resultType
result
case _ =>
- super.transform(tree1) setType null
+ case class MyError(count : Int, ex : AssertionError) extends Error(ex.getMessage)
+ try {
+ super.transform(tree1) setType null
+ } catch {
+ case e @ MyError(n, ex) if n > 5 => throw e
+ case MyError(n,ex) =>
+ Console.println(tree1)
+ throw MyError(n + 1, ex)
+ case ex : AssertionError =>
+ Console.println(tree1)
+ throw MyError(0, ex)
+ case ex => throw ex
+ }
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index ccf14b17c6..8c6a5a585c 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -309,9 +309,11 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter
if (mixinClass.owner.isTerm) gen.mkAttributedThis(mixinClass.owner.enclClass)
else gen.mkAttributedQualifier(currentClass.thisType.baseType(mixinClass).prefix)
val rhs = ExplicitOuterTransformer.this.transform(path)
+ rhs.setPos(currentClass.pos) // see note below
localTyper.typed {
atPos(currentClass.pos) {
- DefDef(outerAcc, {vparamss=>rhs})
+ // @S: atPos not good enough because of nested atPos in DefDef method, which gives position from wrong class!
+ DefDef(outerAcc, {vparamss=>rhs}).setPos(currentClass.pos)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index b66be5d98c..ae695f587f 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -41,7 +41,7 @@ abstract class Flatten extends InfoTransform {
var parents1 = parents
val decls1 = newScope
if (clazz.isPackageClass) {
- atPhase(phase.next)(decls.toList foreach (decls1 enter))
+ atPhase(phase.next)(decls.toList foreach (sym => decls1 enter sym))
} else {
val oldowner = clazz.owner
atPhase(phase.next)(oldowner.info)
diff --git a/src/compiler/scala/tools/nsc/transform/LiftCode.scala b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
index ccd35442fb..91caf14b8c 100644
--- a/src/compiler/scala/tools/nsc/transform/LiftCode.scala
+++ b/src/compiler/scala/tools/nsc/transform/LiftCode.scala
@@ -88,6 +88,7 @@ abstract class LiftCode extends Transform {
if (rsym == reflect.NoSymbol) throw new TypeError("cannot reify symbol: " + tree.symbol)
else reflect.Select(reify(qual), reify(tree.symbol))
+ case _ : StubTree => reflect.Literal(0)
case Literal(constant) =>
reflect.Literal(constant.value)
@@ -250,7 +251,7 @@ abstract class LiftCode extends Transform {
new Reifier(new ReifyEnvironment(), reflect.NoSymbol).reify(tree)
def inject(code: reflect.Tree): Tree =
- new Injector(ListMap.empty, new FreshNameCreator).inject(code)
+ new Injector(ListMap.empty, new FreshNameCreator.Default).inject(code)
def codify (tree: Tree): Tree =
New(TypeTree(appliedType(definitions.CodeClass.typeConstructor,
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 6d95b1a762..1ec4da1a54 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -26,7 +26,7 @@ trait Analyzer extends AnyRef
val phaseName = "namer"
def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
def apply(unit: CompilationUnit): unit =
- new Namer(rootContext(unit)).enterSym(unit.body)
+ newNamer(rootContext(unit)).enterSym(unit.body)
}
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 734c29e2cf..ee1637c65a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -86,9 +86,12 @@ trait Contexts { self: Analyzer =>
sc = sc.outer
}
}
- class Context {
+ // IDE hooks
+ protected def sanitize(tree : Tree) : Tree = tree
+ protected def scopeFor(old : Scope, tree : Tree) : Scope = newScope(old)
+ class Context private[typechecker] {
var unit: CompilationUnit = _
- var tree: Tree = _ // Tree associated with this context
+ var tree: Tree = _ // Tree associated with this context
var owner: Symbol = NoSymbol// The current owner
var scope: Scope = _ // The current scope
var outer: Context = _ // The next outer context
@@ -113,39 +116,88 @@ trait Contexts { self: Analyzer =>
var savedTypeBounds: List[(Symbol, Type)] = List()
- override def equals(that : Any) = that match {
- case that if (super.equals(that)) => true
- case NoContext => false
+
+ def intern0 : Context = {
+ if (this eq NoContext) return this
+ val txt = new Context
+ txt.unit = unit
+ txt.tree = tree
+ txt.owner = owner
+ txt.scope = scope
+ assert(outer ne this) // stupid
+ txt.outer = outer // already interned
+ def f(what : Context) =
+ if (what eq this) txt
+ else what
+ txt.enclClass = f(enclClass)
+ txt.enclMethod = f(enclMethod)
+ txt.implicitsEnabled = implicitsEnabled
+ txt.variance = variance
+ txt._undetparams = _undetparams
+ txt.depth = depth
+ txt.imports = imports
+ txt.prefix = prefix
+ txt.inConstructorSuffix = inConstructorSuffix
+ txt.returnsSeen = returnsSeen
+ txt.reportGeneralErrors = reportGeneralErrors
+ txt.checking = checking
+ txt.retyping = retyping
+ txt.savedTypeBounds = savedTypeBounds
+ txt
+ }
+ override def equals(that : Any) : Boolean = that match {
+ case that : AnyRef if (this eq that) => true
+ case that if !inIDE => super.equals(that)
+ //case NoContext => false
case that : Context =>
- val a0 = if (tree eq null) tree == that.tree else tree equalsStructure that.tree;
- val a1 = owner == that.owner
- val a2 = scope == that.scope
- val a3 = outer == that.outer
- val a4 = {
- if (enclClass eq this) {
- that.enclClass eq that;
- } else enclClass == that.enclClass;
+ if (that eq NoContext) return this eq NoContext
+ assert(that ne NoContext)
+ if (this eq NoContext) return false
+ assert(inIDE)
+ def eq[T](x : T, y : T) = x == y
+ val a0 = {
+ if (tree ne null) tree.setType(null)
+ if ((tree eq null) || (that.tree eq null)) tree == that.tree else
+ tree equalsStructure that.tree;
+ }
+ val a1 = eq(owner, that.owner)
+ val a2 = eq(scope, that.scope)
+ def f(txt0 : Context, txt1 : Context) =
+ ((this eq txt0) && (that eq txt1)) || (txt0 eq txt1)
+
+ val a3 = f(outer, that.outer)
+ val a4 = f(enclClass, that.enclClass)
+ val a5 = f(enclMethod, that.enclMethod)
+ val a6 = eq(variance, that.variance)
+ val a7 = eq(_undetparams, that._undetparams)
+ val a8 = eq(depth, that.depth)
+ val a9 = eq(imports, that.imports)
+
+ val a10 = eq(prefix, that.prefix)
+ val a11 = eq(inConstructorSuffix, that.inConstructorSuffix)
+ val a12 = eq(implicitsEnabled, that.implicitsEnabled)
+ val a13 = eq(checking, that.checking)
+ val a14 = eq(retyping, that.retyping)
+ val a15 = eq(savedTypeBounds, that.savedTypeBounds)
+ val a16 = eq(unit, that.unit)
+ val ret = a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15 && a16
+ val a17 = {
+ if (implicitsRunId > that.implicitsRunId) {
+ that.implicitsRunId = NoRunId
+ that.implicitsCache = null
+ }
+ else if (that.implicitsRunId > implicitsRunId) {
+ implicitsRunId = NoRunId
+ implicitsCache = null
+ }
+ implicitsCache == that.implicitsCache
}
- val a5 = {
- if (enclMethod eq this)
- that.enclMethod eq that;
- else enclMethod == that.enclMethod;
+ if (ret) {
+ if (!a17) {
+ assert(this.implicitsCache == null || that.implicitsCache == null)
+ }
}
- val a6 = variance == that.variance;
- val a7 = _undetparams == that._undetparams;
- val a8 = depth == that.depth;
- val a9 = if (imports.length != that.imports.length) false else
- (for (x <- imports.zip(that.imports)) yield
- (x._1.tree equalsStructure x._2.tree) && x._1.depth == x._2.depth).
- foldLeft(true)((x,y) => x && y);
-
- val a10 = prefix == that.prefix
- val a11 = inConstructorSuffix == that.inConstructorSuffix
- val a12 = implicitsEnabled == that.implicitsEnabled
- val a13 = checking == that.checking
- val a14 = retyping == that.retyping
- val a15 = savedTypeBounds == that.savedTypeBounds
- a0 && a1 && a2 && a3 && a4 && a5 && a6 && a7 && a8 && a9 && a10 && a11 && a12 && a13 && a14 && a15
+ ret
case _ => false
}
@@ -168,16 +220,23 @@ trait Contexts { self: Analyzer =>
scope: Scope, imports: List[ImportInfo]): Context = {
val c = new Context
c.unit = unit
- c.tree = tree
+ c.tree = sanitize(tree)
c.owner = owner
c.scope = scope
+
+ c.outer = intern(this)
+ def internIf(txt : Context) = {
+ if (txt eq this) c.outer // already interned!
+ else txt
+ }
+
tree match {
case Template(_, _, _) | PackageDef(_, _) =>
c.enclClass = c
c.prefix = c.owner.thisType
c.inConstructorSuffix = false
case _ =>
- c.enclClass = this.enclClass
+ c.enclClass = internIf(this.enclClass)
c.prefix =
if (c.owner != this.owner && c.owner.isTerm) NoPrefix
else this.prefix
@@ -187,7 +246,7 @@ trait Contexts { self: Analyzer =>
case DefDef(_, _, _, _, _, _) =>
c.enclMethod = c
case _ =>
- c.enclMethod = this.enclMethod
+ c.enclMethod = internIf(this.enclMethod)
}
c.variance = this.variance
c.depth = if (scope == this.scope) this.depth else this.depth + 1
@@ -197,7 +256,6 @@ trait Contexts { self: Analyzer =>
c.implicitsEnabled = this.implicitsEnabled
c.checking = this.checking
c.retyping = this.retyping
- c.outer = this
c
}
@@ -212,14 +270,21 @@ trait Contexts { self: Analyzer =>
def makeNewImport(imp: Import): Context =
make(unit, imp, owner, scope, new ImportInfo(imp, depth) :: imports)
- def make(tree: Tree, owner: Symbol, scope: Scope): Context =
+
+
+ def make(tree: Tree, owner: Symbol, scope: Scope): Context = {
+ if (tree == this.tree && owner == this.owner && scope == this.scope) this
+ else make0(tree, owner, scope)
+ }
+ private def make0(tree : Tree, owner : Symbol, scope : Scope) : Context = {
make(unit, tree, owner, scope, imports)
+ }
def makeNewScope(tree: Tree, owner: Symbol): Context =
- make(tree, owner, newScope(scope))
+ make(tree, owner, scopeFor(scope, tree))
def make(tree: Tree, owner: Symbol): Context =
- make(tree, owner, scope)
+ make0(tree, owner, scope)
def make(tree: Tree): Context =
make(tree, owner)
@@ -242,7 +307,7 @@ trait Contexts { self: Analyzer =>
//todo: find out why we need next line
while (baseContext.tree.isInstanceOf[Template])
baseContext = baseContext.outer
- val argContext = Contexts.this.makeNewScope(baseContext, tree, owner)
+ val argContext = baseContext.makeNewScope(tree, owner)
argContext.reportGeneralErrors = this.reportGeneralErrors
argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
def enterElems(c: Context) {
@@ -364,6 +429,8 @@ trait Contexts { self: Analyzer =>
def accessWithin(owner: Symbol): Boolean = {
var c = this
while (c != NoContext && c.owner != owner) {
+ if (false && inIDE) // XXX: we didn't get to update these syms....
+ assert(c.owner.fullNameString != owner.fullNameString)
if (c.outer eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug
if (c.outer.enclClass eq null) assert(false, "accessWithin(" + owner + ") " + c);//debug
c = c.outer.enclClass
@@ -422,6 +489,11 @@ trait Contexts { self: Analyzer =>
private var implicitsCache: List[List[ImplicitInfo]] = null
private var implicitsRunId = NoRunId
+ def resetCache : Unit = {
+ implicitsRunId = NoRunId
+ implicitsCache = null
+ if (outer != null && outer != this) outer.resetCache
+ }
private def collectImplicits(syms: List[Symbol], pre: Type): List[ImplicitInfo] =
for (sym <- syms if sym.hasFlag(IMPLICIT) && isAccessible(sym, pre, false))
yield new ImplicitInfo(sym.name, pre, sym)
@@ -473,10 +545,33 @@ trait Contexts { self: Analyzer =>
}
implicitsCache
}
- }
+ override def hashCode = {
+ var hc = 0
+ implicit def b2i(b : Boolean) = if (b) 1 else 0
+ // assum enclClass/enclMethod/outer are all interned already.
+ hc += tree.hashCodeStructure
+ def f(txt : Context) = if (txt eq this) 0 else System.identityHashCode(txt)
+ hc += f(enclClass)
+ hc += f(enclMethod)
+ hc += f(outer)
+ hc += owner.hashCode
+ hc += scope.hashCode
+ hc += variance.hashCode
+ hc += _undetparams.hashCode
+ hc += depth
+ hc += imports.hashCode
+ hc += prefix.hashCode
+ hc += inConstructorSuffix
+ hc += checking
+ hc += retyping
+ hc += savedTypeBounds.hashCode
+ hc += (if (unit eq null) 0 else unit.hashCode)
+ hc
+ }
+ }
+ def notifyImport(what : Name, container : Type, from : Name, to : Name) : Unit = {}
class ImportInfo(val tree: Import, val depth: Int) {
-
/** The prefix expression */
def qual: Tree = tree.symbol.info match {
case ImportType(expr) => expr
@@ -495,6 +590,9 @@ trait Contexts { self: Analyzer =>
var renamed = false
var selectors = tree.selectors
while (selectors != Nil && result == NoSymbol) {
+ if (selectors.head._1 != nme.WILDCARD)
+ notifyImport(name, qual.tpe, selectors.head._1, selectors.head._2)
+
if (selectors.head._2 == name.toTermName)
result = qual.tpe.member(
if (name.isTypeName) selectors.head._1.toTypeName else selectors.head._1)
@@ -508,6 +606,13 @@ trait Contexts { self: Analyzer =>
}
override def toString() = tree.toString()
+
+ override def hashCode = tree.hashCodeStructure + depth
+ override def equals(that : Any) = that match {
+ case that : ImportInfo =>
+ depth == that.depth && (tree equalsStructure that.tree)
+ case _ => false
+ }
}
class ImplicitInfo(val name: Name, val pre: Type, val sym: Symbol) {
@@ -521,5 +626,31 @@ trait Contexts { self: Analyzer =>
val NoImplicitInfo = new ImplicitInfo(null, null, null)
- case class ImportType(expr: Tree) extends Type
+ case class ImportType(expr: Tree) extends Type {
+ override def equals(that : Any) = that match {
+ case ImportType(expr) =>
+ if (inIDE) this.expr equalsStructure expr
+ else this.expr == expr
+ case _ => false
+ }
+ override def hashCode = if (inIDE) expr.hashCodeStructure else expr.hashCode
+ }
+
+ /* APIs for interning contexts */
+ import scala.collection.jcl
+ import scala.ref
+ protected def intern(txt : Context) = txt
+ class ContextInternMap extends jcl.WeakHashMap[Context,ref.WeakReference[Context]] {
+ var last : Context = _
+ override def default(txt : Context) : ref.WeakReference[Context] = {
+ if (txt eq NoContext) new ref.WeakReference(NoContext)
+ val txt0 = txt.intern0
+ last = txt0 // to prevent collection
+ val ret = new ref.WeakReference(txt0)
+ this(txt0) = ret
+ ret
+ }
+ def intern(txt : Context) = this(txt).get.get
+ }
+
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
index 1cdcf6210a..938a07f5bf 100644
--- a/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/EtaExpansion.scala
@@ -34,10 +34,21 @@ trait EtaExpansion { self: Analyzer =>
* tree is already attributed
* </p>
*/
- def etaExpand(tree: Tree): Tree = {
+ def etaExpand(unit : CompilationUnit, tree: Tree): Tree = {
val tpe = tree.tpe
- var cnt = 0
- def freshName() = { cnt = cnt + 1; newTermName("eta$" + cnt) }
+ val symbolHash = if (!inIDE) "" else Integer.toString(tree.symbol.hashCode, 10 + ('z' - 'a')) + "$"
+ var cnt = 0 // for NoPosition
+ def freshName(pos : util.Position, n : Int) = {
+ cnt += 1
+ if (pos == util.NoPosition) {
+ newTermName("eta$" + symbolHash + (cnt - 1))
+ } else if (n == 0) {
+ newTermName(unit.fresh.newName(pos, "eta$" + symbolHash))
+ } else {
+ newTermName(unit.fresh.newName(pos, "eta$" + symbolHash + n + "$"))
+ }
+ }
+ // { cnt = cnt + 1; newTermName("eta$" + cnt) }
val defs = new ListBuffer[Tree]
/** Append to <code>defs</code> value definitions for all non-stable
@@ -50,7 +61,7 @@ trait EtaExpansion { self: Analyzer =>
def liftout(tree: Tree): Tree =
if (treeInfo.isPureExpr(tree)) tree
else {
- val vname: Name = freshName()
+ val vname: Name = freshName(tree.pos, 0)
defs += atPos(tree.pos)(ValDef(Modifiers(SYNTHETIC), vname, TypeTree(), tree))
Ident(vname) setPos tree.pos
}
@@ -76,8 +87,13 @@ trait EtaExpansion { self: Analyzer =>
case mt: ImplicitMethodType =>
tree
case MethodType(formals, restpe) =>
+ var cnt0 = 0
+ def cnt = {
+ cnt0 += 1
+ cnt0 - 1
+ }
val params = formals map (formal =>
- ValDef(Modifiers(SYNTHETIC | PARAM), freshName(), TypeTree()
+ ValDef(Modifiers(SYNTHETIC | PARAM), freshName(tree.pos, cnt), TypeTree()
.setType(formal), EmptyTree))
val args = params map (param => Ident(param.name))
val applyArgs =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index b79fca75f9..015c0636c8 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -245,7 +245,7 @@ trait Infer {
private def withDisambiguation[T](tp1: Type, tp2: Type)(op: => T): T = {
def explainName(sym: Symbol) = {
- if (!sym.name.toString.endsWith(")")) {
+ if (!sym.name.toString.endsWith(")") && !inIDE) {
sym.name = newTypeName(sym.name.toString+"(in "+sym.owner+")")
}
}
@@ -259,7 +259,7 @@ trait Infer {
val name = sym1.name
explainName(sym1)
explainName(sym2)
- if (sym1.owner == sym2.owner) sym2.name = newTypeName("(some other)"+sym2.name)
+ if (sym1.owner == sym2.owner && !inIDE) sym2.name = newTypeName("(some other)"+sym2.name)
patches += (sym1, sym2, name)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9138b2d412..a6409c6398 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -39,14 +39,18 @@ trait Namers { self: Analyzer =>
}
}
/** overridden by IDE to not manually enter value parameters */
- protected final def doEnterValueParams = !inIDE;
- protected def inIDE = false;
+ protected final def doEnterValueParams = true // !inIDE;
+ // can't use the other ones.
+ protected def newDecls(classSym : Symbol) : Scope = newClassScope
- class Namer(val context: Context) {
+ private class NormalNamer(context : Context) extends Namer(context)
+ def newNamer(context : Context) : Namer = new NormalNamer(context)
+
+ abstract class Namer(val context: Context) {
val typer = newTyper(context)
- def setPrivateWithin(tree: Tree, sym: Symbol, mods: Modifiers): Symbol = {
+ def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym = {
if (!mods.privateWithin.isEmpty)
sym.privateWithin = typer.qualifyingClassContext(tree, mods.privateWithin).owner
sym
@@ -75,6 +79,10 @@ trait Namers { self: Analyzer =>
}
private var innerNamerCache: Namer = null
+ protected def makeConstructorScope(classContext : Context) : Context = {
+ val outerContext = classContext.outer.outer
+ outerContext.makeNewScope(outerContext.tree, outerContext.owner)
+ }
def namerOf(sym: Symbol): Namer = {
@@ -82,46 +90,51 @@ trait Namers { self: Analyzer =>
if (innerNamerCache eq null)
innerNamerCache =
if (!isTemplateContext(context)) this
- else new Namer(context.make(context.tree, context.owner, newScope))
+ else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree)))
innerNamerCache
}
def primaryConstructorParamNamer: Namer = { //todo: can we merge this with SCCmode?
val classContext = context.enclClass
- val outerContext = classContext.outer.outer
- val paramContext = outerContext.makeNewScope(outerContext.tree, outerContext.owner)
- classContext.owner.unsafeTypeParams foreach(sym => paramContext.scope.enter(sym))
- new Namer(paramContext)
- }
-
- if (sym.isTerm &&
- (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor || sym.hasFlag(PARAMACCESSOR)))
- primaryConstructorParamNamer
- else
- innerNamer
+ val paramContext = makeConstructorScope(classContext)
+ val unsafeTypeParams = context.owner.unsafeTypeParams
+ unsafeTypeParams foreach(sym => paramContext.scope.enter(sym))
+ newNamer(paramContext)
+ }
+ if (sym.isTerm) {
+ if (sym.hasFlag(PARAM) && sym.owner.isPrimaryConstructor)
+ primaryConstructorParamNamer
+ else if (sym.hasFlag(PARAMACCESSOR) && !inIDE)
+ primaryConstructorParamNamer
+ else innerNamer
+ } else innerNamer
}
+ protected def conflict(newS : Symbol, oldS : Symbol) : Boolean = {
+ (!oldS.isSourceMethod ||
+ nme.isSetterName(newS.name) ||
+ newS.owner.isPackageClass) &&
+ !((newS.owner.isTypeParameter || newS.owner.isAbstractType) &&
+ newS.name.length==1 && newS.name(0)=='_') //@M: allow repeated use of `_' for higher-order type params
+ }
+ protected def setInfo[Sym <: Symbol](sym : Sym)(tpe : LazyType) : Sym = sym.setInfo(tpe)
private def doubleDefError(pos: Position, sym: Symbol) {
context.error(pos,
sym.name.toString() + " is already defined as " +
(if (sym.hasFlag(CASE)) "case class " + sym.name else sym.toString()))
}
- def enterInScope[A <: Symbol](sym: A): A = {
+ def enterInScope(sym: Symbol): Symbol = {
// allow for overloaded methods
if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) {
val prev = context.scope.lookupEntry(sym.name);
- if ((prev ne null) && prev.owner == context.scope &&
- (!prev.sym.isSourceMethod ||
- nme.isSetterName(sym.name) ||
- sym.owner.isPackageClass) &&
- !((sym.owner.isTypeParameter || sym.owner.isAbstractType)
- && sym.name.length==1 && sym.name(0)=='_')) { //@M: allow repeated use of `_' for higher-order type params
+ if ((prev ne null) && prev.owner == context.scope && conflict(sym, prev.sym)) {
doubleDefError(sym.pos, prev.sym)
- sym setInfo ErrorType
+ if (!inIDE) sym setInfo ErrorType // don't do this in IDE for stability
+ context.scope unlink prev.sym
+ context.scope enter sym
} else context.scope enter sym
} else context.scope enter sym
- sym
}
def enterPackageSymbol(pos: Position, name: Name): Symbol = {
@@ -133,79 +146,102 @@ trait Namers { self: Analyzer =>
} else {
val cowner = if (context.owner == EmptyPackageClass) RootClass else context.owner
val pkg = cowner.newPackage(pos, name)
- pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass))
+ // IDE: newScope should be ok because packages are never destroyed.
+ if (inIDE) assert(pkg.moduleClass.rawInfoSafe.isEmpty || !pkg.moduleClass.rawInfo.isComplete)
+ pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass, null))
pkg.setInfo(pkg.moduleClass.tpe)
enterInScope(pkg)
}
}
- def inConstructorFlag: long =
+ def inConstructorFlag: Long =
if (context.owner.isConstructor && !context.inConstructorSuffix || context.owner.isEarly) INCONSTRUCTOR
else 0l
- private def enterClassSymbol(pos: Position, flags: long, name: Name): Symbol = {
- var c: Symbol = context.scope.lookup(name)
- if (c.isType && !currentRun.compiles(c) && context.scope == c.owner.info.decls) {
- updatePosFlags(c, pos, flags)
+ def enterClassSymbol(tree : ClassDef): Symbol = {
+ var c: Symbol = context.scope.lookup(tree.name);
+ // Never take the first path in the IDE because we could be completing c.owner's type!
+ // the other path will handle symbol re-use well enough.
+ if (!inIDE && c.isType && context.scope == c.owner.info.decls && !currentRun.compiles(c)) {
+ updatePosFlags(c, tree.pos, tree.mods.flags)
+ setPrivateWithin(tree, c, tree.mods)
} else {
- c = enterInScope(context.owner.newClass(pos, name)).setFlag(flags | inConstructorFlag)
+ //if (inIDE && c != NoSymbol) currentRun.compiles(c) // in IDE, will unload/save non-source symbol
+ var sym = context.owner.newClass(tree.pos, tree.name)
+ sym = sym.setFlag(tree.mods.flags | inConstructorFlag)
+ sym = setPrivateWithin(tree, sym, tree.mods)
+ c = enterInScope(sym)
}
if (c.owner.isPackageClass) {
- val file = context.unit.source.getFile()
+ val file = context.unit.source.file
val clazz = c.asInstanceOf[ClassSymbol]
if (settings.debug.value && (clazz.sourceFile ne null) && !clazz.sourceFile.equals(file)) {
Console.err.println("SOURCE MISMATCH: " + clazz.sourceFile + " vs. " + file + " SYM=" + c);
}
clazz.sourceFile = file
if (clazz.sourceFile ne null) {
- assert(!currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c));
+ assert(inIDE || !currentRun.compiles(clazz) || clazz.sourceFile == currentRun.symSource(c));
currentRun.symSource(c) = clazz.sourceFile
}
}
+ assert(c.name.toString.indexOf('(') == -1)
c
}
-
- private def enterModuleSymbol(pos: Position, flags: long, name: Name): Symbol = {
- var m: Symbol = context.scope.lookup(name)
- if (m.isModule && !m.isPackage && !currentRun.compiles(m) &&
- (context.scope == m.owner.info.decls)) {
- updatePosFlags(m, pos, flags)
+ def enterModuleSymbol(tree : ModuleDef): Symbol = {
+ // .pos, mods.flags | MODULE | FINAL, name
+ assert(tree.name.isTermName)
+ var m: Symbol = context.scope.lookup(tree.name)
+ if (!inIDE && m.isModule && !m.isPackage && (context.scope == m.owner.info.decls) &&
+ !currentRun.compiles(m)) {
+ updatePosFlags(m, tree.pos, tree.mods.flags|MODULE|FINAL)
+ setPrivateWithin(tree, m, tree.mods)
} else {
- if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && (context.scope == m.owner.info.decls))
+ if (m.isTerm && !m.isPackage && currentRun.compiles(m) && (context.scope == m.owner.info.decls))
context.scope.unlink(m)
- m = context.owner.newModule(pos, name)
- m.setFlag(flags)
- m.moduleClass.setFlag(flags | inConstructorFlag)
- enterInScope(m)
+
+ m = context.owner.newModule(tree.pos, tree.name)
+ m.setFlag(tree.mods.flags)
+ m = setPrivateWithin(tree, m, tree.mods)
+ m = enterInScope(m)
+
+ m.moduleClass.setFlag(tree.mods.flags|MODULE|FINAL| inConstructorFlag)
+ setPrivateWithin(tree, m.moduleClass, tree.mods)
}
if (m.owner.isPackageClass) {
- m.moduleClass.sourceFile = context.unit.source.getFile()
+ m.moduleClass.sourceFile = context.unit.source.file
currentRun.symSource(m) = m.moduleClass.sourceFile
}
m
}
- private def enterCaseFactorySymbol(pos: Position, flags: long, name: Name): Symbol = {
+ def enterCaseFactorySymbol(tree : ClassDef): Symbol = {
+ val pos = tree.pos
+ val flags = tree.mods.flags & AccessFlags | METHOD | CASE
+ val name = tree.name.toTermName
var m: Symbol = context.scope.lookup(name)
- if (m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) {
+ if (!inIDE && m.isTerm && !m.isPackage && !currentRun.compiles(m) && context.scope == m.owner.info.decls) {
updatePosFlags(m, pos, flags)
+ setPrivateWithin(tree, m, tree.mods)
} else {
- m = enterInScope(context.owner.newMethod(pos, name)).setFlag(flags)
+ // recycle the old fashion way.
+ m = enterInScope{
+ var sym = context.owner.newMethod(pos, name).setFlag(flags)
+ sym = setPrivateWithin(tree, sym, tree.mods)
+ sym
+ }
}
if (m.owner.isPackageClass)
- currentRun.symSource(m) = context.unit.source.getFile()
+ currentRun.symSource(m) = context.unit.source.file
m
}
-
def enterSyms(trees: List[Tree]): Namer = {
var namer : Namer = this
for (tree <- trees) {
val txt = namer.enterSym(tree)
- if (!(txt eq namer.context)) namer = new Namer(txt)
+ if (!(txt eq namer.context)) namer = newNamer(txt)
}
namer
}
-
def newTypeSkolems(tparams: List[Symbol]): List[Symbol] = {
val tskolems = tparams map (_.newTypeSkolem)
val ltp = new LazyType {
@@ -216,7 +252,6 @@ trait Namers { self: Analyzer =>
tskolems foreach (_.setInfo(ltp))
tskolems
}
-
/** Replace type parameters with their TypeSkolems, which can later be deskolemized to the original type param
* (a skolem is a representation of a bound variable when viewed outside its scope)
*/
@@ -237,10 +272,15 @@ trait Namers { self: Analyzer =>
override val typeParams: List[Symbol]= tparams map (_.symbol) //@M
override def complete(sym: Symbol) {
if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ?
- new Namer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
+ newNamer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
restp.complete(sym)
}
}
+ def reuse[T <: Tree](tree: T) = if (!inIDE) tree else {
+ val tree0 = tree.duplicate
+ //tree0.symbol = tree.symbol
+ tree0
+ }
def enterSym(tree: Tree): Context = {
@@ -253,11 +293,11 @@ trait Namers { self: Analyzer =>
//@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x
//@M x is only in scope in `A[x <: B]'
if(!sym.isAbstractType) //@M TODO: change to isTypeMember ?
- new Namer(context.makeNewScope(tree, sym)).enterSyms(tparams)
+ newNamer(context.makeNewScope(tree, sym)).enterSyms(tparams)
ltype = new LazyPolyType(tparams, ltype, tree, sym, context) //@M
if (sym.isTerm) skolemize(tparams)
}
- sym.setInfo(ltype)
+ setInfo(sym)(ltype)
}
def finish = finishWith(List())
@@ -267,45 +307,43 @@ trait Namers { self: Analyzer =>
tree match {
case PackageDef(name, stats) =>
tree.symbol = enterPackageSymbol(tree.pos, name)
- val namer = new Namer(
+ val namer = newNamer(
context.make(tree, tree.symbol.moduleClass, tree.symbol.info.decls))
namer.enterSyms(stats)
- case ClassDef(mods, name, tparams, impl) =>
+ case tree @ ClassDef(mods, name, tparams, impl) =>
+ tree.symbol = enterClassSymbol(tree)
+ finishWith(tparams)
if ((mods.flags & CASE) != 0) { // enter case factory method.
- tree.symbol = enterCaseFactorySymbol(
- tree.pos, mods.flags & AccessFlags | METHOD | CASE, name.toTermName)
- tree.symbol.setInfo(namerOf(tree.symbol).caseFactoryCompleter(tree))
- setPrivateWithin(tree, tree.symbol, mods)
+ val sym = enterCaseFactorySymbol(tree)
+ setInfo(sym)(namerOf(sym).caseFactoryCompleter(reuse(tree)))
}
- tree.symbol = enterClassSymbol(tree.pos, mods.flags, name)
- setPrivateWithin(tree, tree.symbol, mods)
- finishWith(tparams)
- case ModuleDef(mods, name, _) =>
- tree.symbol = enterModuleSymbol(tree.pos, mods.flags | MODULE | FINAL, name)
- setPrivateWithin(tree, tree.symbol, mods)
- setPrivateWithin(tree, tree.symbol.moduleClass, mods)
- tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter(tree))
+ case tree @ ModuleDef(mods, name, _) =>
+ tree.symbol = enterModuleSymbol(tree)
+ // IDE: do not use the setInfo call for the module class as it is initialized
+ // through module symbol
+ tree.symbol.moduleClass.setInfo(namerOf(tree.symbol).moduleClassTypeCompleter(reuse(tree)))
finish
+
case ValDef(mods, name, tp, rhs) =>
if (context.owner.isClass && (mods.flags & (PRIVATE | LOCAL)) != (PRIVATE | LOCAL)
|| (mods.flags & LAZY) != 0) {
val accflags: Long = ACCESSOR |
(if ((mods.flags & MUTABLE) != 0) mods.flags & ~MUTABLE & ~PRESUPER
else mods.flags & ~PRESUPER | STABLE)
- val getter = owner.newMethod(tree.pos, name).setFlag(accflags)
- getter.setInfo(namerOf(getter).getterTypeCompleter(tree))
+ var getter = owner.newMethod(tree.pos, name).setFlag(accflags)
setPrivateWithin(tree, getter, mods)
- enterInScope(getter)
+ getter = enterInScope(getter).asInstanceOf[TermSymbol]
+ setInfo(getter)(namerOf(getter).getterTypeCompleter(tree))
if ((mods.flags & MUTABLE) != 0) {
- val setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
+ var setter = owner.newMethod(tree.pos, nme.getterToSetter(name))
.setFlag(accflags & ~STABLE & ~CASEACCESSOR)
- setter.setInfo(namerOf(setter).setterTypeCompleter(tree))
setPrivateWithin(tree, setter, mods)
- enterInScope(setter)
+ setter = enterInScope(setter).asInstanceOf[TermSymbol]
+ setInfo(setter)(namerOf(setter).setterTypeCompleter(tree))
}
tree.symbol =
- if ((mods.flags & DEFERRED) == 0) {
- val vsym =
+ if ((mods.flags & DEFERRED) == 0) { // not deferred
+ var vsym =
if (!context.owner.isClass) {
assert((mods.flags & LAZY) != 0) // if not a field, it has to be a lazy val
owner.newValue(tree.pos, name + "$lzy" ).setFlag(mods.flags | MUTABLE)
@@ -313,39 +351,39 @@ trait Namers { self: Analyzer =>
owner.newValue(tree.pos, nme.getterToLocal(name))
.setFlag(mods.flags & FieldFlags | PRIVATE | LOCAL | (if ((mods.flags & LAZY) != 0) MUTABLE else 0))
}
- val value = enterInScope(vsym)
- value.setInfo(namerOf(value).typeCompleter(tree))
+ vsym = enterInScope(vsym).asInstanceOf[TermSymbol]
+ setInfo(vsym)(namerOf(vsym).typeCompleter(tree))
if ((mods.flags & LAZY) != 0)
- value.setLazyAccessor(getter)
- value
+ vsym.setLazyAccessor(getter)
+ vsym
} else getter;
} else {
- tree.symbol = enterInScope(owner.newValue(tree.pos, name))
- .setFlag(mods.flags)
+ tree.symbol = enterInScope(owner.newValue(tree.pos, name)
+ .setFlag(mods.flags))
finish
}
case DefDef(mods, nme.CONSTRUCTOR, tparams, _, _, _) =>
- tree.symbol = enterInScope(owner.newConstructor(tree.pos))
- .setFlag(mods.flags | owner.getFlag(ConstrFlags))
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym = owner.newConstructor(tree.pos).setFlag(mods.flags | owner.getFlag(ConstrFlags))
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case DefDef(mods, name, tparams, _, _, _) =>
- tree.symbol = enterInScope(owner.newMethod(tree.pos, name))
- .setFlag(mods.flags)
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym = (owner.newMethod(tree.pos, name)).setFlag(mods.flags)
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case TypeDef(mods, name, tparams, _) =>
var flags: Long = mods.flags
if ((flags & PARAM) != 0) flags |= DEFERRED
- tree.symbol = enterInScope(new TypeSymbol(owner, tree.pos, name))
- .setFlag(flags)
- setPrivateWithin(tree, tree.symbol, mods)
+ var sym =new TypeSymbol(owner, tree.pos, name).setFlag(flags)
+ setPrivateWithin(tree, sym, mods)
+ tree.symbol = enterInScope(sym)
finishWith(tparams)
case DocDef(_, defn) =>
enterSym(defn)
case imp @ Import(_, _) =>
tree.symbol = NoSymbol.newImport(tree.pos)
- tree.symbol.setInfo(namerOf(tree.symbol).typeCompleter(tree))
+ setInfo(tree.symbol)(namerOf(tree.symbol).typeCompleter(tree))
return (context.makeNewImport(imp))
case _ =>
}
@@ -451,11 +489,20 @@ trait Namers { self: Analyzer =>
def enterValueParams(owner: Symbol, vparamss: List[List[ValDef]]): List[List[Symbol]] = {
def enterValueParam(param: ValDef): Symbol = if (doEnterValueParams) {
- param.symbol = owner.newValueParameter(param.pos, param.name)
- .setInfo(typeCompleter(param))
- .setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
- setPrivateWithin(param, param.symbol, param.mods)
- enterInScope(param.symbol)
+ if (inIDE) param.symbol = {
+ var sym = owner.newValueParameter(param.pos, param.name).
+ setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
+ setPrivateWithin(param, sym, param.mods)
+ sym = enterInScope(sym).asInstanceOf[TermSymbol]
+ if (!sym.rawInfoSafe.isDefined || sym.rawInfo.isComplete)
+ setInfo(sym)(typeCompleter(param))
+ sym
+ } else param.symbol = setInfo(
+ enterInScope{
+ val sym = owner.newValueParameter(param.pos, param.name).
+ setFlag(param.mods.flags & (BYNAMEPARAM | IMPLICIT))
+ setPrivateWithin(param, sym, param.mods)
+ })(typeCompleter(param))
param.symbol
} else param.symbol
vparamss.map(_.map(enterValueParam))
@@ -477,7 +524,7 @@ trait Namers { self: Analyzer =>
def enterSelf(self: ValDef) {
if (!self.tpt.isEmpty) {
clazz.typeOfThis = selfTypeCompleter(self.tpt)
- self.symbol = clazz.thisSym
+ self.symbol = clazz.thisSym.setPos(self.pos)
} else {
self.tpt.tpe = NoType
if (self.name != nme.WILDCARD) {
@@ -489,13 +536,13 @@ trait Namers { self: Analyzer =>
}
if (self.name != nme.WILDCARD) {
self.symbol.name = self.name
- context.scope enter self.symbol
+ self.symbol = context.scope enter self.symbol
}
}
val parents = typer.parentTypes(templ) map checkParent
enterSelf(templ.self)
- val decls = newDecls(templ, clazz)
- new Namer(context.make(templ, clazz, decls)).enterSyms(templ.body)
+ val decls = newDecls(clazz)
+ newNamer(context.make(templ, clazz, decls)).enterSyms(templ.body)
ClassInfoType(parents, decls, clazz)
}
@@ -507,7 +554,14 @@ trait Namers { self: Analyzer =>
val meth = context.owner
val tparamSyms = typer.reenterTypeParams(tparams)
- var vparamSymss = enterValueParams(meth, vparamss)
+ var vparamSymss =
+ if (inIDE && meth.isPrimaryConstructor) {
+ // @S: because they have already been entered this way....
+ assert(true)
+ enterValueParams(meth.owner.owner, vparamss)
+ } else {
+ enterValueParams(meth, vparamss)
+ }
if (tpt.isEmpty && meth.name == nme.CONSTRUCTOR) tpt.tpe = context.enclClass.owner.tpe
if (onlyPresentation)
@@ -700,7 +754,7 @@ trait Namers { self: Analyzer =>
val ainfos = for {
annot <- defn.mods.annotations
val ainfo = typer.typedAnnotation(annot)
- if !ainfo.atp.isError
+ if !ainfo.atp.isError && annot != null
} yield ainfo
if (!ainfos.isEmpty) {
val annotated = if (sym.isModule) sym.moduleClass else sym
@@ -712,17 +766,17 @@ trait Namers { self: Analyzer =>
try {
tree match {
case ClassDef(_, _, tparams, impl) =>
- new Namer(makeNewScope(context, tree, sym)).classSig(tparams, impl)
+ newNamer(context.makeNewScope(tree, sym)).classSig(tparams, impl)
case ModuleDef(_, _, impl) =>
val clazz = sym.moduleClass
- clazz.setInfo(new Namer(makeNewScope(context, tree, clazz)).templateSig(impl))
+ clazz.setInfo(newNamer(context.makeNewScope(tree, clazz)).templateSig(impl))
//clazz.typeOfThis = singleType(sym.owner.thisType, sym);
clazz.tpe;
case DefDef(_, _, tparams, vparamss, tpt, rhs) =>
val result =
- new Namer(makeNewScope(context, tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
+ newNamer(context.makeNewScope(tree, sym)).methodSig(tparams, vparamss, tpt, rhs);
checkContractive(sym, result)
case vdef @ ValDef(mods, _, tpt, rhs) =>
@@ -741,7 +795,7 @@ trait Namers { self: Analyzer =>
} else typer1.typedType(tpt).tpe
case TypeDef(_, _, tparams, rhs) =>
- new Namer(makeNewScope(context, tree, sym)).typeDefSig(sym, tparams, rhs) //@M!
+ newNamer(context.makeNewScope(tree, sym)).typeDefSig(sym, tparams, rhs) //@M!
case Import(expr, selectors) =>
val expr1 = typer.typedQualifier(expr)
@@ -813,7 +867,7 @@ trait Namers { self: Analyzer =>
}
if (sym.hasFlag(IMPLICIT) && !sym.isTerm)
context.error(sym.pos, "`implicit' modifier can be used only for values, variables and methods")
- if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass)
+ if (sym.hasFlag(IMPLICIT) && sym.owner.isPackageClass && !inIDE)
context.error(sym.pos, "`implicit' modifier cannot be used for top-level objects")
if (sym.hasFlag(ABSTRACT) && !sym.isClass)
context.error(sym.pos, "`abstract' modifier can be used only for classes; " +
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index aa5a2909e1..7323529d94 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -84,7 +84,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
}
- override def transform(tree: Tree): Tree = tree match {
+ override def transform(tree: Tree): Tree = try { tree match {
case ClassDef(_, _, _, _) =>
checkCompanionNameClashes(tree.symbol)
val decls = tree.symbol.info.decls
@@ -181,6 +181,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
super.transform(tree)
case Apply(fn, args) =>
+ assert(fn.tpe != null)
copy.Apply(tree, transform(fn), transformArgs(args, fn.tpe.paramTypes))
case Function(vparams, body) =>
withInvalidOwner {
@@ -188,6 +189,12 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
}
case _ =>
super.transform(tree)
+ }} catch {
+ case ex : AssertionError =>
+ if (tree.symbol != null && tree.symbol != NoSymbol)
+ Console.println("TRANSFORM: " + tree.symbol.sourceFile)
+ Console.println("TREE: " + tree)
+ throw ex
}
override def atOwner[A](owner: Symbol)(trans: => A): A = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index 8fb892670b..d9ee9071cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -29,7 +29,11 @@ import scala.collection.mutable.ListBuffer
trait SyntheticMethods { self: Analyzer =>
import global._ // the global environment
import definitions._ // standard classes and methods
- import typer.{typed} // methods to type trees
+ //import global.typer.{typed} // methods to type trees
+ // @S: type hack: by default, we are used from global.analyzer context
+ // so this cast won't fail. If we aren't in global.analyzer, we have
+ // to override this method anyways.
+ protected def typer : Typer = global.typer.asInstanceOf[Typer]
/**
* @param templ ...
@@ -42,15 +46,15 @@ trait SyntheticMethods { self: Analyzer =>
val localContext = if (reporter.hasErrors) context.makeSilent(false) else context
val localTyper = newTyper(localContext)
- def hasImplementation(name: Name): Boolean = {
+ def hasImplementation(name: Name): Boolean = if (inIDE) true else {
val sym = clazz.info.nonPrivateMember(name)
sym.isTerm && !(sym hasFlag DEFERRED)
}
- def hasOverridingImplementation(meth: Symbol): Boolean = {
+ def hasOverridingImplementation(meth: Symbol): Boolean = if (inIDE) true else {
val sym = clazz.info.nonPrivateMember(meth.name)
sym.alternatives exists { sym =>
- sym != meth && !(sym hasFlag DEFERRED) &&
+ sym != meth && !(sym hasFlag DEFERRED) && !(sym hasFlag SYNTHETIC) &&
(clazz.thisType.memberType(sym) matches clazz.thisType.memberType(meth))
}
}
@@ -59,8 +63,11 @@ trait SyntheticMethods { self: Analyzer =>
newSyntheticMethod(name, flags | OVERRIDE, tpe)
def newSyntheticMethod(name: Name, flags: Int, tpe: Type) = {
- val method = clazz.newMethod(clazz.pos, name) setFlag (flags) setInfo tpe
- clazz.info.decls.enter(method)
+ var method = clazz.newMethod(clazz.pos, name) setFlag ({
+ if (inIDE) flags | SYNTHETIC
+ else flags
+ }) setInfo tpe
+ method = clazz.info.decls.enter(method).asInstanceOf[TermSymbol]
method
}
@@ -72,18 +79,18 @@ trait SyntheticMethods { self: Analyzer =>
*/
def productPrefixMethod: Tree = {
val method = syntheticMethod(nme.productPrefix, FINAL, PolyType(List(), StringClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
}
def productArityMethod(nargs:Int ): Tree = {
val method = syntheticMethod(nme.productArity, FINAL, PolyType(List(), IntClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(nargs))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(nargs))))
}
def productElementMethod(accs: List[Symbol]): Tree = {
//val retTpe = lub(accs map (_.tpe.resultType))
val method = syntheticMethod(nme.productElement, FINAL, MethodType(List(IntClass.tpe), AnyClass.tpe/*retTpe*/))
- typed(DefDef(method, vparamss => Match(Ident(vparamss.head.head), {
+ typer.typed(DefDef(method, vparamss => Match(Ident(vparamss.head.head), {
(for ((sym,i) <- accs.zipWithIndex) yield {
CaseDef(Literal(Constant(i)),EmptyTree, Ident(sym))
}):::List(CaseDef(Ident(nme.WILDCARD), EmptyTree,
@@ -95,12 +102,12 @@ trait SyntheticMethods { self: Analyzer =>
def moduleToStringMethod: Tree = {
val method = syntheticMethod(nme.toString_, FINAL, MethodType(List(), StringClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.name.decode))))
}
def tagMethod: Tree = {
val method = syntheticMethod(nme.tag, FINAL, MethodType(List(), IntClass.tpe))
- typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
+ typer.typed(DefDef(method, vparamss => Literal(Constant(clazz.tag))))
}
def forwardingMethod(name: Name): Tree = {
@@ -110,7 +117,7 @@ trait SyntheticMethods { self: Analyzer =>
else target.tpe.paramTypes.tail
val method = syntheticMethod(
name, 0, MethodType(paramtypes, target.tpe.resultType))
- typed(DefDef(method, vparamss =>
+ typer.typed(DefDef(method, vparamss =>
Apply(gen.mkAttributedRef(target), This(clazz) :: (vparamss.head map Ident))))
}
@@ -148,7 +155,7 @@ trait SyntheticMethods { self: Analyzer =>
val (pat, guard) = {
val guards = new ListBuffer[Tree]
val params = for ((acc, cpt) <- clazz.caseFieldAccessors zip constrParamTypes) yield {
- val name = context.unit.fresh.newName(acc.name+"$")
+ val name = context.unit.fresh.newName(clazz.pos, acc.name+"$")
val isVarArg = cpt.typeSymbol == RepeatedParamClass
guards += Apply(
Select(
@@ -185,16 +192,16 @@ trait SyntheticMethods { self: Analyzer =>
// but then it is renamed !!!
val method = newSyntheticMethod(nme.readResolve, PROTECTED,
MethodType(List(), ObjectClass.tpe))
- typed(DefDef(method, vparamss => gen.mkAttributedRef(clazz.sourceModule)))
+ typer.typed(DefDef(method, vparamss => gen.mkAttributedRef(clazz.sourceModule)))
}
def newAccessorMethod(tree: Tree): Tree = tree match {
case DefDef(_, _, _, _, _, rhs) =>
- val newAcc = tree.symbol.cloneSymbol
- newAcc.name = context.unit.fresh.newName(tree.symbol.name + "$")
+ var newAcc = tree.symbol.cloneSymbol
+ newAcc.name = context.unit.fresh.newName(tree.symbol.pos, tree.symbol.name + "$")
newAcc.setFlag(SYNTHETIC).resetFlag(ACCESSOR | PARAMACCESSOR | PRIVATE)
- newAcc.owner.info.decls enter newAcc
- val result = typed(DefDef(newAcc, vparamss => rhs.duplicate))
+ newAcc = newAcc.owner.info.decls enter newAcc
+ val result = typer.typed(DefDef(newAcc, vparamss => rhs.duplicate))
log("new accessor method " + result)
result
}
@@ -226,7 +233,7 @@ trait SyntheticMethods { self: Analyzer =>
def addBeanGetterMethod(sym: Symbol) = {
val getter = beanSetterOrGetter(sym)
if (getter != NoSymbol)
- ts += typed(DefDef(
+ ts += typer.typed(DefDef(
getter,
vparamss => if (sym hasFlag DEFERRED) EmptyTree else gen.mkAttributedRef(sym)))
}
@@ -234,7 +241,7 @@ trait SyntheticMethods { self: Analyzer =>
def addBeanSetterMethod(sym: Symbol) = {
val setter = beanSetterOrGetter(sym)
if (setter != NoSymbol)
- ts += typed(DefDef(
+ ts += typer.typed(DefDef(
setter,
vparamss =>
if (sym hasFlag DEFERRED) EmptyTree
@@ -257,7 +264,7 @@ trait SyntheticMethods { self: Analyzer =>
}
}
- if (clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
+ if (!inIDE && clazz.info.nonPrivateDecl(nme.tag) == NoSymbol) ts += tagMethod
if (clazz.isModuleClass) {
if (!hasOverridingImplementation(Object_toString)) ts += moduleToStringMethod
} else {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index cd852c8b50..1ef6b935e7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -44,7 +44,6 @@ trait Typers { self: Analyzer =>
superDefs.clear
}
- def newTyper(context: Context): Typer = new Typer(context)
object UnTyper extends Traverser {
override def traverse(tree: Tree) = {
@@ -53,12 +52,20 @@ trait Typers { self: Analyzer =>
super.traverse(tree)
}
}
- def makeNewScope(txt: Context, tree: Tree, sym: Symbol) =
- txt.makeNewScope(tree, sym)
+ // IDE hooks
+ def newTyper(context: Context): Typer = new NormalTyper(context)
+ private class NormalTyper(context : Context) extends Typer(context)
+ def scopeFor(tree : Tree) : Scope = newScope
+ def newLocalDummy(clazz : Symbol, pos : Position) = clazz.newLocalDummy(pos)
+ def recycle(sym : Symbol) : Symbol = sym
+ // hooks for auto completion
+ def compare(sym : Symbol, name : Name) = sym.name == name
+ def verifyAndPrioritize[T](g : Symbol => Symbol)(pt : Type)(f : => T) = f
+ def trackSetInfo[T <: Symbol](sym : T)(info : Type) : T = {
+ sym.setInfo(info)
+ sym
+ }
- def newDecls(tree: CompoundTypeTree) = newScope
- def newDecls(tree: Template, clazz: Symbol) = newScope
- def newTemplateScope(impl: Template, clazz: Symbol) = newScope
// Mode constants
@@ -132,7 +139,7 @@ trait Typers { self: Analyzer =>
private def argMode(fun: Tree, mode: Int) =
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode else mode
- class Typer(context0: Context) {
+ abstract class Typer(context0: Context) {
import context0.unit
val infer = new Inferencer(context0) {
@@ -177,9 +184,10 @@ trait Typers { self: Analyzer =>
*/
private def inferView(pos: Position, from: Type, name: Name, tp: Type, reportAmbiguous: Boolean): Tree = {
val to = refinedType(List(WildcardType), NoSymbol)
- val psym = (if (name.isTypeName) to.typeSymbol.newAbstractType(pos, name)
- else to.typeSymbol.newValue(pos, name)) setInfo tp
- to.decls.enter(psym)
+ var psym = (if (name.isTypeName) to.typeSymbol.newAbstractType(pos, name)
+ else to.typeSymbol.newValue(pos, name))
+ psym = to.decls enter psym
+ psym setInfo tp
inferView(pos, from, to, reportAmbiguous)
}
@@ -188,7 +196,7 @@ trait Typers { self: Analyzer =>
private var namerCache: Namer = null
def namer = {
if ((namerCache eq null) || namerCache.context != context)
- namerCache = new Namer(context)
+ namerCache = newNamer(context)
namerCache
}
@@ -346,7 +354,7 @@ trait Typers { self: Analyzer =>
this.scope = scope
hiddenSymbols = List()
val tp1 = apply(tree.tpe)
- if (hiddenSymbols.isEmpty) tree setType tp1
+ if (hiddenSymbols.isEmpty || inIDE) tree setType tp1 // @S: because arguments of classes are owned by the classes' owner
else if (hiddenSymbols exists (_.isErroneous)) setError(tree)
else if (isFullyDefined(pt)) tree setType pt //todo: eliminate
else if (tp1.typeSymbol.isAnonymousClass) // todo: eliminate
@@ -412,7 +420,10 @@ trait Typers { self: Analyzer =>
def reenterTypeParams(tparams: List[TypeDef]): List[Symbol] =
for (tparam <- tparams) yield {
- context.scope enter tparam.symbol
+ val rawInfo = tparam.symbol.rawInfo
+ tparam.symbol = context.scope enter tparam.symbol
+ // hack, because the skolems are reused.
+ if (inIDE) tparam.symbol.setInfo(rawInfo)
tparam.symbol.deSkolemize
}
@@ -446,7 +457,7 @@ trait Typers { self: Analyzer =>
*/
def labelTyper(ldef: LabelDef): Typer =
if (ldef.symbol == NoSymbol) { // labeldef is part of template
- val typer1 = newTyper(makeNewScope(context, ldef, context.owner))
+ val typer1 = newTyper(context.makeNewScope(ldef, context.owner))
typer1.enterLabelDef(ldef)
typer1
} else this
@@ -597,7 +608,7 @@ trait Typers { self: Analyzer =>
* If all this fails, error
*/
protected def adapt(tree: Tree, mode: int, pt: Type): Tree = tree.tpe match {
- case ct @ ConstantType(value) if ((mode & TYPEmode) == 0 && (ct <:< pt)) => // (0)
+ case ct @ ConstantType(value) if ((mode & TYPEmode) == 0 && (ct <:< pt) && !inIDE) => // (0)
copy.Literal(tree, value)
case OverloadedType(pre, alts) if ((mode & FUNmode) == 0) => // (1)
inferExprAlternative(tree, pt)
@@ -641,7 +652,7 @@ trait Typers { self: Analyzer =>
(pt <:< functionType(mt.paramTypes map (t => WildcardType), WildcardType))) { // (4.2)
if (settings.debug.value) log("eta-expanding "+tree+":"+tree.tpe+" to "+pt)
checkParamsConvertible(tree.pos, tree.tpe)
- typed(etaExpand(tree), mode, pt)
+ typed(etaExpand(context.unit, tree), mode, pt)
} else if (!meth.isConstructor && mt.paramTypes.isEmpty) { // (4.3)
adapt(typed(Apply(tree, List()) setPos tree.pos), mode, pt)
} else if (context.implicitsEnabled) {
@@ -781,9 +792,6 @@ trait Typers { self: Analyzer =>
}
}
}
-// Console.println("adapt "+tree+":"+tree.tpe+", mode = "+mode+", pt = "+pt)
-// adapt(tree, mode, pt)
-// }
/**
* @param tree ...
@@ -820,7 +828,8 @@ trait Typers { self: Analyzer =>
if (member(qual, name) != NoSymbol) qual
else adaptToMember(qual, name, WildcardType)
- private def typePrimaryConstrBody(cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
+ private def typePrimaryConstrBody(clazz : Symbol, cbody: Tree, tparams: List[Symbol], enclTparams: List[Symbol], vparamss: List[List[ValDef]]): Tree = {
+ // XXX: see about using the class's symbol....
enclTparams foreach (sym => context.scope.enter(sym))
namer.enterValueParams(context.owner, vparamss)
typed(cbody)
@@ -879,8 +888,8 @@ trait Typers { self: Analyzer =>
val outercontext = context.outer
val cbody2 =
- newTyper(makeNewScope(outercontext, constr, outercontext.owner))
- .typePrimaryConstrBody(
+ newTyper(outercontext.makeNewScope(constr, outercontext.owner))
+ .typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
scall match {
@@ -952,7 +961,8 @@ trait Typers { self: Analyzer =>
//Console.println(context.owner);//DEBUG
//Console.println(context.owner.unsafeTypeParams);//DEBUG
//Console.println(List.fromArray(context.owner.info.closure));//DEBUG
- error(parent.pos, "illegal inheritance;\n self-type "+
+ // disable in IDE, don't know how else to avoid it on refresh
+ if (!inIDE) error(parent.pos, "illegal inheritance;\n self-type "+
selfType+" does not conform to "+parent +
"'s selftype "+parent.tpe.typeOfThis)
if (settings.explaintypes.value) explainTypes(selfType, parent.tpe.typeOfThis)
@@ -992,10 +1002,15 @@ trait Typers { self: Analyzer =>
def typedClassDef(cdef: ClassDef): Tree = {
// attributes(cdef)
val typedMods = typedModifiers(cdef.mods)
- val clazz = cdef.symbol
+ val clazz = cdef.symbol;
+ if (inIDE && clazz == NoSymbol) {
+ assert(true)
+ throw new TypeError("type signature typing failed")
+ }
+ assert(clazz != NoSymbol)
reenterTypeParams(cdef.tparams)
val tparams1 = List.mapConserve(cdef.tparams)(typedTypeDef)
- val impl1 = newTyper(context.make(cdef.impl, clazz, newTemplateScope(cdef.impl, clazz)))
+ val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl)))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
copy.ClassDef(cdef, typedMods, cdef.name, tparams1, impl2)
@@ -1011,7 +1026,9 @@ trait Typers { self: Analyzer =>
// attributes(mdef)
val typedMods = typedModifiers(mdef.mods)
val clazz = mdef.symbol.moduleClass
- val impl1 = newTyper(context.make(mdef.impl, clazz, newTemplateScope(mdef.impl, clazz)))
+ if (inIDE && clazz == NoSymbol) throw new TypeError("bad signature")
+ assert(clazz != NoSymbol)
+ val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl)))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
@@ -1029,7 +1046,10 @@ trait Typers { self: Analyzer =>
&& !stat.symbol.hasFlag(LAZY) =>
val vdef = copy.ValDef(stat, mods | PRIVATE | LOCAL, nme.getterToLocal(name), tpt, rhs)
val value = vdef.symbol
- val getter = if ((mods hasFlag DEFERRED) || inIDE) value else value.getter(value.owner)
+ val getter = if ((mods hasFlag DEFERRED)) value else value.getter(value.owner)
+ // XXX:
+ if (inIDE && getter == NoSymbol)
+ return Nil
assert(getter != NoSymbol, stat)
if (getter hasFlag OVERLOADED)
error(getter.pos, getter+" is defined twice")
@@ -1080,7 +1100,7 @@ trait Typers { self: Analyzer =>
protected def enterSym(txt: Context, tree: Tree): Context =
if (txt eq context) namer.enterSym(tree)
- else new Namer(txt).enterSym(tree)
+ else newNamer(txt).enterSym(tree)
/**
* @param templ ...
@@ -1090,7 +1110,7 @@ trait Typers { self: Analyzer =>
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
val clazz = context.owner
if (templ.symbol == NoSymbol)
- templ setSymbol clazz.newLocalDummy(templ.pos)
+ templ setSymbol newLocalDummy(clazz, templ.pos)
val self1 = templ.self match {
case vd @ ValDef(mods, name, tpt, EmptyTree) =>
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
@@ -1102,9 +1122,12 @@ trait Typers { self: Analyzer =>
intersectionType(clazz.info.parents, clazz.owner)
else clazz.typeOfThis
// the following is necessary for templates generated later
- enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templ.body)
+ assert(clazz.info.decls != EmptyScope)
+ // XXX: let namer in typeSig be definitive, duplicate to ensure typer context doesn't stick.
+ val templBody = if (inIDE) templ.body.map(_.duplicate : Tree) else templ.body
+ enterSyms(context.outer.make(templ, clazz, clazz.info.decls), templBody)
validateParentClasses(parents1, selfType)
- if (!phase.erasedTypes)
+ if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members
checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType])
val body =
if (phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
@@ -1131,7 +1154,10 @@ trait Typers { self: Analyzer =>
val typer1 = constrTyperIf(sym.hasFlag(PARAM) && sym.owner.isConstructor)
val typedMods = typedModifiers(vdef.mods)
- val tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
+ var tpt1 = checkNoEscaping.privates(sym, typer1.typedType({
+ if (inIDE) vdef.tpt.duplicate // avoids wrong context sticking
+ else vdef.tpt
+ }))
checkNonCyclic(vdef, tpt1)
val rhs1 =
if (vdef.rhs.isEmpty) {
@@ -1139,7 +1165,9 @@ trait Typers { self: Analyzer =>
error(vdef.pos, "local variables must be initialized")
vdef.rhs
} else {
- newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(vdef.rhs, tpt1.tpe)
+ //assert(vdef.rhs.tpe == null)
+ val rhs = if (inIDE && vdef.rhs.tpe != null) vdef.rhs.duplicate else vdef.rhs
+ newTyper(typer1.context.make(vdef, sym)).transformedOrTyped(rhs, tpt1.tpe)
}
copy.ValDef(vdef, typedMods, vdef.name, tpt1, checkDead(rhs1)) setType NoType
}
@@ -1155,11 +1183,14 @@ trait Typers { self: Analyzer =>
def decompose(call: Tree): (Tree, List[Tree]) = call match {
case Apply(fn, args) =>
val (superConstr, args1) = decompose(fn)
- val formals = fn.tpe.paramTypes
+ val formals = (if (fn.tpe == null && inIDE) ErrorType else fn.tpe).paramTypes
val args2 = if (formals.isEmpty || formals.last.typeSymbol != RepeatedParamClass) args
else args.take(formals.length - 1) ::: List(EmptyTree)
- if (args2.length != formals.length)
- assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ if (args2.length != formals.length) {
+ if (!inIDE)
+ assert(false, "mismatch " + clazz + " " + formals + " " + args2);//debug
+ else error(call.pos, "XXX: mismatch " + clazz + " " + formals + " " + args2)
+ }
(superConstr, args1 ::: args2)
case Block(stats, expr) if !stats.isEmpty =>
decompose(stats.last)
@@ -1198,6 +1229,12 @@ trait Typers { self: Analyzer =>
}
()
}
+ } else if (inIDE) { // XXX: maybe add later
+ Console.println("" + superClazz + ":" +
+ superClazz.info.decls.toList.filter(_.hasFlag(PARAMACCESSOR)))
+ error(rhs.pos, "mismatch: " + superParamAccessors +
+ ";" + rhs + ";" + superClazz.info.decls)//debug
+ return
}
}
}
@@ -1215,6 +1252,7 @@ trait Typers { self: Analyzer =>
*/
def typedDefDef(ddef: DefDef): DefDef = {
val meth = ddef.symbol
+ if (inIDE && meth == NoSymbol) throw new TypeError("bad signature")
reenterTypeParams(ddef.tparams)
reenterValueParams(ddef.vparamss)
val tparams1 = List.mapConserve(ddef.tparams)(typedTypeDef)
@@ -1240,7 +1278,8 @@ trait Typers { self: Analyzer =>
error(ddef.pos, "constructor definition not allowed here")
typed(ddef.rhs)
} else {
- transformedOrTyped(ddef.rhs, tpt1.tpe)
+ if (inIDE && ddef.rhs == EmptyTree) EmptyTree
+ else transformedOrTyped(ddef.rhs, tpt1.tpe)
}
if (meth.isPrimaryConstructor && meth.isClassConstructor &&
phase.id <= currentRun.typerPhase.id && !reporter.hasErrors)
@@ -1310,8 +1349,7 @@ trait Typers { self: Analyzer =>
if (stat.isDef) context.scope.enter(stat.symbol)
}
}
- if (!inIDE)
- namer.enterSyms(block.stats)
+ namer.enterSyms(block.stats)
block.stats foreach enterLabelDef
val stats1 = typedStats(block.stats, context.owner)
val expr1 = typed(block.expr, mode & ~(FUNmode | QUALmode), pt)
@@ -1359,7 +1397,7 @@ trait Typers { self: Analyzer =>
def typedCases(tree: Tree, cases: List[CaseDef], pattp0: Type, pt: Type): List[CaseDef] = {
var pattp = pattp0
List.mapConserve(cases) ( cdef =>
- newTyper(makeNewScope(context, cdef, context.owner)).typedCase(cdef, pattp, pt))
+ newTyper(context.makeNewScope(cdef, context.owner)).typedCase(cdef, pattp, pt))
/* not yet!
cdef.pat match {
case Literal(Constant(null)) =>
@@ -1410,8 +1448,6 @@ trait Typers { self: Analyzer =>
vparam.symbol
}
// XXX: here to for IDE hooks.
- if (inIDE) // HACK to process arguments types in IDE.
- typedFunctionIDE(fun, context);
val vparams = List.mapConserve(fun.vparams)(typedValDef)
// for (val vparam <- vparams) {
// checkNoEscaping.locals(context.scope, WildcardType, vparam.tpt); ()
@@ -1430,8 +1466,7 @@ trait Typers { self: Analyzer =>
}
def typedRefinement(stats: List[Tree]): List[Tree] = {
- if (!inIDE)
- namer.enterSyms(stats)
+ namer.enterSyms(stats)
val stats1 = typedStats(stats, NoSymbol)
for (stat <- stats1 if stat.isDef) {
val member = stat.symbol
@@ -1457,14 +1492,21 @@ trait Typers { self: Analyzer =>
context = context.makeNewImport(imp0)
imp0.symbol.initialize
}
- EmptyTree
+ if ((imp0 ne null) && inIDE) {
+ imp0.symbol.info match {
+ case ImportType(exr) =>
+ imp0.expr.tpe = exr.tpe
+ case _ =>
+ }
+ imp0
+ } else EmptyTree
case _ =>
val localTyper = if (inBlock || (stat.isDef && !stat.isInstanceOf[LabelDef])) this
else newTyper(context.make(stat, exprOwner))
val result = checkDead(localTyper.typed(stat))
if (treeInfo.isSelfOrSuperConstrCall(result)) {
context.inConstructorSuffix = true
- if (treeInfo.isSelfConstrCall(result) && result.symbol.pos.offset.get(0) >= exprOwner.enclMethod.pos.offset.get(0))
+ if (!inIDE && treeInfo.isSelfConstrCall(result) && result.symbol.pos.offset.get(0) >= exprOwner.enclMethod.pos.offset.get(0))
error(stat.pos, "called constructor's definition must precede calling constructor's definition")
}
result
@@ -1482,7 +1524,7 @@ trait Typers { self: Analyzer =>
while ((e1 ne null) && e1.owner == scope) {
if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
(e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
- if (!e.sym.isErroneous && !e1.sym.isErroneous)
+ if (!e.sym.isErroneous && !e1.sym.isErroneous && !inIDE)
error(e.sym.pos, e1.sym+" is defined twice"+
{if(!settings.debug.value) "" else " in "+unit.toString});
e1 = scope.lookupNextEntry(e1);
@@ -1593,7 +1635,7 @@ trait Typers { self: Analyzer =>
}
}
- if (fun.symbol == List_apply && args.isEmpty) {
+ if (!inIDE && fun.symbol == List_apply && args.isEmpty) {
atPos(tree.pos) { gen.mkNil setType restpe }
} else
constfold(copy.Apply(tree, fun, args2).setType(ifPatternSkipFormals(restpe)))
@@ -1618,8 +1660,9 @@ trait Typers { self: Analyzer =>
else {
if (settings.debug.value) log("infer method inst "+fun+", tparams = "+tparams+", args = "+args2.map(_.tpe)+", pt = "+pt+", lobounds = "+tparams.map(_.tpe.bounds.lo)+", parambounds = "+tparams.map(_.info));//debug
val undetparams = inferMethodInstance(fun, tparams, args2, pt)
- val result = doTypedApply(tree, fun, args2, mode, pt)
- context.undetparams = undetparams
+ val result = if (!inIDE) doTypedApply(tree, fun, args2, mode, pt)
+ else doTypedApply(tree.duplicate,fun.duplicate,args2.map(_.duplicate),mode,pt)
+ context.undetparams = undetparams
result
}
}
@@ -1637,6 +1680,7 @@ trait Typers { self: Analyzer =>
assert(unapp.exists, tree)
val unappType = otpe.memberType(unapp)
val argDummyType = pt // was unappArg
+ // @S: do we need to memoize this?
val argDummy = context.owner.newValue(fun.pos, nme.SELECTOR_DUMMY)
.setFlag(SYNTHETIC)
.setInfo(argDummyType)
@@ -1659,7 +1703,7 @@ trait Typers { self: Analyzer =>
val (unappFormal, freeVars) = freshArgType(unappType)
val context1 = context.makeNewScope(context.tree, context.owner)
freeVars foreach(sym => context1.scope.enter(sym))
- val typer1 = new Typer(context1)
+ val typer1 = newTyper(context1)
arg.tpe = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
//todo: replace arg with arg.asInstanceOf[inferTypedPattern(unappFormal, arg.tpe)] instead.
argDummy.setInfo(arg.tpe) // bq: this line fixed #1281. w.r.t. comment ^^^, maybe good enough?
@@ -1833,10 +1877,10 @@ trait Typers { self: Analyzer =>
val typeParams: List[Symbol] = rawSyms map { sym =>
val name = if (sym.isType) sym.name else newTypeName(sym.name+".type")
val bound = existentialBound(sym)
- val quantified: Symbol = sym.owner.newAbstractType(sym.pos, name)
- quantified setFlag EXISTENTIAL setInfo bound.cloneInfo(quantified)
+ val quantified: Symbol = recycle(sym.owner.newAbstractType(sym.pos, name))
+ trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified))
}
- val typeParamTypes = typeParams map (_.tpe)
+ val typeParamTypes = typeParams map (_.tpe) // don't trackSetInfo here, since type already set!
for (tparam <- typeParams) tparam.setInfo(tparam.info.subst(rawSyms, typeParamTypes))
(typeParams, tp.subst(rawSyms, typeParamTypes))
}
@@ -1916,10 +1960,9 @@ trait Typers { self: Analyzer =>
case t =>
t
}
- val local = sym.owner.newAbstractType(
- sym.pos, unit.fresh.newName(sym.name.toString))
- .setFlag(sym.flags)
- .setInfo(bound)
+ val local = trackSetInfo(recycle(sym.owner.newAbstractType(
+ sym.pos, unit.fresh.newName(sym.pos, sym.name.toString))
+ .setFlag(sym.flags)))(bound)
localInstances += (inst -> local)
addLocals(bound)
}
@@ -2015,8 +2058,10 @@ trait Typers { self: Analyzer =>
else
context.owner.newAbstractType(tree.pos, name) setInfo
mkTypeBounds(AllClass.tpe, AnyClass.tpe)
- if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
- else namer.enterInScope(vble)
+ val rawInfo = vble.rawInfo
+ vble = if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
+ else namer.enterInScope(vble)
+ trackSetInfo(vble)(rawInfo) // vble could have been recycled, detect changes in type
tree setSymbol vble setType vble.tpe
} else {
if (vble == NoSymbol)
@@ -2031,10 +2076,10 @@ trait Typers { self: Analyzer =>
*/
if ((mode & ALTmode) != 0)
error(tree.pos, "illegal variable in pattern alternative")
- namer.enterInScope(vble)
+ vble = namer.enterInScope(vble)
}
val body1 = typed(body, mode, pt)
- vble.setInfo(
+ trackSetInfo(vble)(
if (treeInfo.isSequenceValued(body)) seqType(body1.tpe)
else body1.tpe)
copy.Bind(tree, name, body1) setSymbol vble setType body1.tpe // buraq, was: pt
@@ -2100,12 +2145,17 @@ trait Typers { self: Analyzer =>
errorTree(tree, "return outside method definition")
} else {
val DefDef(_, _, _, _, restpt, _) = enclMethod.tree
- if (restpt.tpe eq null) {
- errorTree(tree, "method " + enclMethod.owner +
+ var restpt0 = restpt
+ if (inIDE && (restpt0.tpe eq null)) {
+ assert(true)
+ restpt0 = typed(restpt0, TYPEmode, WildcardType)
+ }
+ if (restpt0.tpe eq null) {
+ errorTree(tree, "" + enclMethod.owner +
" has return statement; needs result type")
} else {
context.enclMethod.returnsSeen = true
- val expr1: Tree = typed(expr, restpt.tpe)
+ val expr1: Tree = typed(expr, restpt0.tpe)
copy.Return(tree, checkDead(expr1)) setSymbol enclMethod.owner setType AllClass.tpe
}
}
@@ -2372,7 +2422,7 @@ trait Typers { self: Analyzer =>
if ((mode & SUPERCONSTRmode) != 0) clazz.info.parents.head
else intersectionType(clazz.info.parents)
else {
- val ps = clazz.info.parents filter (p => p.typeSymbol.name == mix)
+ val ps = clazz.info.parents filter (p => compare(p.typeSymbol, mix))
if (ps.isEmpty) {
if (settings.debug.value)
Console.println(clazz.info.parents map (_.typeSymbol.name))//debug
@@ -2429,7 +2479,8 @@ trait Typers { self: Analyzer =>
}
tree.symbol
} else {
- member(qual, name)
+ if (!inIDE) member(qual, name)
+ else verifyAndPrioritize(_ filter (alt => context.isAccessible(alt, qual.tpe, qual.isInstanceOf[Super])))(pt)(member(qual,name))
}
if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
val qual1 = adaptToName(qual, name)
@@ -2510,6 +2561,7 @@ trait Typers { self: Analyzer =>
((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) ||
!sym.isSourceMethod || sym.isCaseFactory)
+
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
@@ -2520,22 +2572,23 @@ trait Typers { self: Analyzer =>
while (defSym == NoSymbol && cx != NoContext) {
pre = cx.enclClass.prefix
- defEntry = cx.scope.lookupEntry(name)
- if (inIDE && (defEntry ne null) && defEntry.sym.exists) {
- val sym = defEntry.sym
- val namePos : Position = tree.pos
- val symPos : Position = sym.pos
- if (namePos.offset.get < symPos.offset.get) defEntry = null
- }
+ defEntry = if (!inIDE) cx.scope.lookupEntry(name)
+ else verifyAndPrioritize(sym => sym)(pt)(cx.scope.lookupEntry(name))
if ((defEntry ne null) && qualifies(defEntry.sym)) {
defSym = defEntry.sym
- } else if (inIDE) {
- if (cx.outer == cx.enclClass) {
- cx = cx.enclClass
- defSym = pre.member(name) filter (
- sym => sym.exists && context.isAccessible(sym, pre, false))
+ } else if (inIDE) { // IDE: cannot rely on linked scopes.
+ if (cx.outer.owner eq cx.enclClass.owner) {
+ //cx = cx.outer
+ defSym =
+ verifyAndPrioritize{ // enables filtering of auto completion
+ _ filter (sym => qualifies(sym) && context.isAccessible(sym, pre, false))
+ }(pt)(pre.member(name) filter (
+ sym => qualifies(sym) && context.isAccessible(sym, pre, false)))
}
- if (defSym == NoSymbol) cx = cx.outer
+ val oldScope = cx.scope
+ cx = cx.outer
+ while (cx.scope == oldScope && !(cx.outer.owner eq cx.enclClass.owner)) // can't skip
+ cx = cx.outer
} else {
cx = cx.enclClass
defSym = pre.member(name) filter (
@@ -2562,7 +2615,7 @@ trait Typers { self: Analyzer =>
// imported symbols take precedence over package-owned symbols in different
// compilation units. Defined symbols take precedence over errenous imports.
if (defSym.owner.isPackageClass &&
- (!currentRun.compiles(defSym) ||
+ ((!inIDE && !currentRun.compiles(defSym)) ||
(context.unit ne null) && defSym.sourceFile != context.unit.source.file))
defSym = NoSymbol
else if (impSym.isError)
@@ -2614,9 +2667,14 @@ trait Typers { self: Analyzer =>
}
}
if (defSym.owner.isPackageClass) pre = defSym.owner.thisType
- if (defSym.isThisSym) typed1(This(defSym.owner) setPos tree.pos, mode, pt)
+ if (defSym.isThisSym) {
+ val tree1 = typed1(This(defSym.owner) setPos tree.pos, mode, pt)
+ if (inIDE) {
+ Ident(defSym.name) setType tree1.tpe setSymbol defSym setPos tree.pos
+ } else tree1
+ }
else {
- val tree1 = if (qual == EmptyTree) tree
+ var tree1 = if (qual == EmptyTree) tree
else atPos(tree.pos)(Select(qual, name))
// atPos necessary because qualifier might come from startContext
stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt)
@@ -2627,7 +2685,7 @@ trait Typers { self: Analyzer =>
val parents1 = List.mapConserve(templ.parents)(typedType)
if (parents1 exists (_.tpe.isError)) tree setType ErrorType
else {
- val decls = newDecls(tree.asInstanceOf[CompoundTypeTree])
+ val decls = scopeFor(tree)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
tree setType self
@@ -2636,6 +2694,8 @@ trait Typers { self: Analyzer =>
def typedAppliedTypeTree(tpt: Tree, args: List[Tree]) = {
val tpt1 = typed1(tpt, mode | FUNmode | TAPPmode, WildcardType)
+ // @S: shouldn't be necessary now, fixed a problem with SimpleTypeProxy not relaying typeParams calls.
+ // if (inIDE) tpt1.symbol.info // @S: seems like typeParams call doesn't force completion of symbol type in IDE.
val tparams = tpt1.symbol.typeParams
if (tpt1.tpe.isError) {
@@ -2654,7 +2714,7 @@ trait Typers { self: Analyzer =>
// note: can't use args1 in selector, because Bind's got replaced
case Bind(_, _) =>
if (arg.symbol.isAbstractType)
- arg.symbol setInfo
+ arg.symbol setInfo // XXX, feedback. don't trackSymInfo here!
TypeBounds(lub(List(arg.symbol.info.bounds.lo, tparam.info.bounds.lo)),
glb(List(arg.symbol.info.bounds.hi, tparam.info.bounds.hi)))
case _ =>
@@ -2675,24 +2735,25 @@ trait Typers { self: Analyzer =>
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
tree match {
case PackageDef(name, stats) =>
+ assert(sym.moduleClass ne NoSymbol)
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(stats, NoSymbol)
copy.PackageDef(tree, name, stats1) setType NoType
case tree @ ClassDef(_, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedClassDef(tree)
+ newTyper(context.makeNewScope(tree, sym)).typedClassDef(tree)
case tree @ ModuleDef(_, _, _) =>
- newTyper(makeNewScope(context, tree, sym.moduleClass)).typedModuleDef(tree)
+ newTyper(context.makeNewScope(tree, sym.moduleClass)).typedModuleDef(tree)
case vdef @ ValDef(_, _, _, _) =>
typedValDef(vdef)
case ddef @ DefDef(_, _, _, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedDefDef(ddef)
+ newTyper(context.makeNewScope(tree, sym)).typedDefDef(ddef)
case tdef @ TypeDef(_, _, _, _) =>
- newTyper(makeNewScope(context, tree, sym)).typedTypeDef(tdef)
+ newTyper(context.makeNewScope(tree, sym)).typedTypeDef(tdef)
case ldef @ LabelDef(_, _, _) =>
labelTyper(ldef).typedLabelDef(ldef)
@@ -2712,7 +2773,7 @@ trait Typers { self: Analyzer =>
typedAnnotated(annot, typed(arg, mode, pt))
case tree @ Block(_, _) =>
- newTyper(makeNewScope(context, tree, context.owner))
+ newTyper(context.makeNewScope(tree, context.owner))
.typedBlock(tree, mode, pt)
case Sequence(elems) =>
@@ -2753,9 +2814,9 @@ trait Typers { self: Analyzer =>
case tree @ Function(_, _) =>
if (tree.symbol == NoSymbol)
- tree.symbol = context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
- .setFlag(SYNTHETIC).setInfo(NoType)
- newTyper(makeNewScope(context, tree, tree.symbol)).typedFunction(tree, mode, pt)
+ tree.symbol = recycle(context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
+ .setFlag(SYNTHETIC).setInfo(NoType))
+ newTyper(context.makeNewScope(tree, tree.symbol)).typedFunction(tree, mode, pt)
case Assign(lhs, rhs) =>
typedAssign(lhs, rhs)
@@ -2763,11 +2824,12 @@ trait Typers { self: Analyzer =>
case If(cond, thenp, elsep) =>
typedIf(cond, thenp, elsep)
- case Match(selector, cases) =>
+ case tree @ Match(selector, cases) =>
if (selector == EmptyTree) {
val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1
val params = for (i <- List.range(0, arity)) yield
- ValDef(Modifiers(PARAM | SYNTHETIC), unit.fresh.newName("x$"), TypeTree(), EmptyTree)
+ ValDef(Modifiers(PARAM | SYNTHETIC),
+ unit.fresh.newName(tree.pos, "x" + i + "$"), TypeTree(), EmptyTree)
val ids = for (p <- params) yield Ident(p.name)
val selector1 = atPos(tree.pos) { if (arity == 1) ids.head else gen.mkTuple(ids) }
val body = copy.Match(tree, selector1, cases)
@@ -2920,14 +2982,14 @@ trait Typers { self: Analyzer =>
copy.TypeBoundsTree(tree, lo1, hi1) setType mkTypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
- newTyper(makeNewScope(context, tree, context.owner)).typedExistentialTypeTree(etpt)
+ newTyper(context.makeNewScope(tree, context.owner)).typedExistentialTypeTree(etpt)
case TypeTree() =>
// we should get here only when something before failed
// and we try again (@see tryTypedApply). In that case we can assign
// whatever type to tree; we just have to survive until a real error message is issued.
tree setType AnyClass.tpe
-
+ case EmptyTree if inIDE => EmptyTree // just tolerate it in the IDE.
case _ =>
throw new Error("unexpected tree: " + tree.getClass + "\n" + tree)//debug
}
diff --git a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
index ba67c6e3ea..4f99ecc221 100644
--- a/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
+++ b/src/compiler/scala/tools/nsc/util/CharArrayReader.scala
@@ -8,10 +8,10 @@ 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, */
- decodeUni: Boolean, error: String => Unit) extends Iterator[Char] {
+class CharArrayReader(buf: RandomAccessSeq[Char], start: Int, /* startline: int, startcol: int, */
+ decodeUni: Boolean, error: String => unit) extends Iterator[Char] {
- def this(buf: Array[Char], decodeUni: Boolean, error: String => Unit) =
+ def this(buf: RandomAccessSeq[Char], decodeUni: Boolean, error: String => unit) =
this(buf, 0, /* 1, 1, */ decodeUni, error)
/** layout constant
@@ -46,17 +46,21 @@ class CharArrayReader(buf: Array[Char], start: Int, /* startline: Int, startcol:
//nextcol = 1
}
- def hasNext: Boolean = bp < buf.length
+ def hasNext: Boolean = if (bp < buf.length) true
+ else {
+ assert(true)
+ false
+ }
def last: Char = if (bp > start + 2) buf(bp - 2) else ' ' // XML literals
def next: Char = {
//cline = nextline
//ccol = nextcol
+ val buf = this.buf.asInstanceOf[runtime.BoxedCharArray].value
if(!hasNext) {
- // there is an endless stream of SU's at the end
ch = SU
- return SU
+ return SU // there is an endless stream of SU's at the end
}
oldBp = bp
oldCh = ch
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index 6ac66ae968..cb67f55c60 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -81,7 +81,9 @@ class ClassPath(onlyPresentation: Boolean) {
// assert(location != null, "cannot find classpath location")
// assert(location.getFile() != null, "cannot find classpath location " + " " + location + " " + location.getClass())
def source: Source
- override def toString() = location.toString()
+ override def toString() =
+ (if (location == null) "<none>" else location.toString) +
+ (if (source == null) "" else " source=" + source)
}
class Output(location0: AbstractFile, val sourceFile: AbstractFile) extends Entry(location0) {
@@ -100,7 +102,7 @@ class ClassPath(onlyPresentation: Boolean) {
if (entries.isEmpty) new Context(Nil)
else {
val ret = find0(entries.tail)
- val head = entries.head
+ val head = entries.head;
val name0 = name + (if (!isDir) ".class" else "")
val clazz = if (head.location eq null) null
else head.location.lookupPath(name0, isDir)
@@ -124,7 +126,9 @@ class ClassPath(onlyPresentation: Boolean) {
}
try {
//Console.err.println("this=" + this + "\nclazz=" + clazz + "\nsource0=" + source0 + "\n")
- new Context(entry :: ret.entries)
+
+ if (!isDir) new Context(entry :: Nil)
+ else new Context(entry :: ret.entries)
} catch {
case e: Error =>
throw e
@@ -192,7 +196,7 @@ class ClassPath(onlyPresentation: Boolean) {
val sourcePath0 = sourcePath
if (sourcePath0 ne null) {
if (!sourcePath0.isDirectory) {
- Console.err.println(""+sourcePath0 + " cannot be a directory")
+ Console.err.println(""+sourcePath0 + " should be a directory")
assert(false)
}
}
@@ -248,15 +252,35 @@ class ClassPath(onlyPresentation: Boolean) {
}
/**
- * @param classes ...
- * @param sources ...
+ * @param classes where the class files come from and are written to
+ * @param sources where the source files come from
+ */
+ def output(classes : String, sources : String) = {
+ assert(classes ne null)
+ assert(sources ne null)
+ val location = AbstractFile.getDirectory(classes)
+ val sources0 = AbstractFile.getDirectory(sources)
+ class Output0 extends Output(location, sources0)
+ entries += new Output0()
+ }
+ /**
+ * @param classes where the class files come from
+ * @param sources optional source file attachment, otherwise null
*/
def library(classes: String, sources: String) {
assert(classes ne null)
val location = AbstractFile.getDirectory(classes)
- val sourceFile0 =
+ var sourceFile0 =
if (sources ne null) AbstractFile.getDirectory(sources)
else null
+ if (sourceFile0 ne null) {
+ val file00 = sourceFile0.lookupPath("src", true)
+ if ((file00 ne null) && file00.isDirectory) {
+ assert(true)
+ sourceFile0 = file00
+ }
+ }
+
class Library0 extends Library(location) {
override def sourceFile = sourceFile0
}
diff --git a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
index d3e79969af..a4c257a996 100644
--- a/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
+++ b/src/compiler/scala/tools/nsc/util/FreshNameCreator.scala
@@ -8,7 +8,13 @@ package scala.tools.nsc.util
import scala.collection.mutable.HashMap
-class FreshNameCreator {
+trait FreshNameCreator {
+ def newName(prefix : String) : String
+ def newName() : String
+ def newName(pos : util.Position, prefix : String) : String
+}
+object FreshNameCreator {
+ class Default extends FreshNameCreator {
protected var counter = 0
protected val counters = new HashMap[String, Int]
@@ -26,9 +32,11 @@ class FreshNameCreator {
counters.update(prefix, count)
prefix + count
}
+ def newName(pos : util.Position, prefix : String) = newName(prefix)
def newName(): String = {
counter = counter + 1
"$" + counter + "$"
}
}
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala b/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala
new file mode 100644
index 0000000000..3f889587ed
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/NewCharArrayReader.scala
@@ -0,0 +1,74 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2006 LAMP/EPFL
+ * @author Martin Odersky
+ */
+// $Id: CharArrayReader.scala 11142 2007-05-22 10:23:00Z mcdirmid $
+
+package scala.tools.nsc.util
+
+import scala.tools.nsc.util.SourceFile.{LF, FF, CR, SU}
+
+class NewCharArrayReader(val buf: RandomAccessSeq[Char], // should not change
+ decodeUni: Boolean, error: (Int,String) => unit) extends Iterator[Char] {
+ private var idx : Int = 0
+ private var isUnicode0 = false
+ def isUnicode = isUnicode0
+
+ private val bufLength = buf.length
+ def seek(offset : Int) = {
+ assert(offset <= bufLength)
+ idx = offset
+ }
+ def offset = idx
+ def withOffset = new Iterator[(Int,Char)] {
+ def hasNext = NewCharArrayReader.this.hasNext
+ def next = (offset, NewCharArrayReader.this.next)
+ }
+ override def hasNext = { // could be padded
+ if (idx == bufLength - 1) buf(idx) != SU
+ else idx < bufLength
+ }
+ override def next : Char = {
+ isUnicode0 = false
+ if (!hasNext) return SU
+ var ch = buf(idx)
+ idx = idx + 1
+ ch match {
+ case CR if buf.safeIs(idx + 1, LF) =>
+ idx += 1; ch = LF
+ case LF | FF =>
+ case '\\' =>
+ def evenSlashPrefix: Boolean = {
+ var p = idx - 2
+ while (p >= 0 && buf(p) == '\\') p = p - 1;
+ (idx - p) % 2 == 0
+ }
+ def udigit: Int = {
+ val d = digit2int(buf(idx), 16)
+ if (d >= 0) { idx = idx + 1 }
+ else if (error != null) error(idx, "error in unicode escape");
+ d
+ }
+ if (idx < bufLength && buf(idx) == 'u' && decodeUni && evenSlashPrefix) {
+ do {
+ idx = idx + 1; // nextcol = nextcol + 1;
+ } while (idx < bufLength && buf(idx) == 'u');
+ val code = udigit << 12 | udigit << 8 | udigit << 4 | udigit
+ isUnicode0 = true
+ ch = code.asInstanceOf[Char]
+ }
+ case _ =>
+ }
+ ch
+ }
+ def digit2int(ch: Char, base: Int): Int = {
+ if ('0' <= ch && ch <= '9' && ch < '0' + base)
+ ch - '0'
+ else if ('A' <= ch && ch < 'A' + base - 10)
+ ch - 'A' + 10
+ else if ('a' <= ch && ch < 'a' + base - 10)
+ ch - 'a' + 10
+ else
+ -1
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index 144809ff6a..ae4cd55086 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -8,14 +8,19 @@
// $Id$
package scala.tools.nsc.util
-
+object Position {
+ // a static field
+ private val tabInc = 8
+}
trait Position {
+ import Position.tabInc
def offset : Option[Int] = None
- private val tabInc = 8
+ def source : Option[SourceFile] = None
+
def line : Option[Int] =
- if (source.isEmpty || offset.isEmpty) None else Some(source.get.offsetToLine(offset.get) + 1)
+ if (offset.isEmpty || source.isEmpty) None else Some(source.get.offsetToLine(offset.get) + 1)
def column : Option[Int] = {
- if (source.isEmpty || offset.isEmpty) return None
+ if (offset.isEmpty || source.isEmpty) return None
var column = 1
// find beginning offset for line
val line = source.get.offsetToLine(offset.get)
@@ -23,33 +28,39 @@ trait Position {
var continue = true
while (continue) {
if (coffset == offset.get(-1)) continue = false
- else if (source.get.content(coffset) == '\t') column = ((column - 1) / tabInc * tabInc) + tabInc + 1
+ else if (source.get.asInstanceOf[BatchSourceFile].content(coffset) == '\t')
+ column = ((column - 1) / tabInc * tabInc) + tabInc + 1
else column = column + 1
coffset = coffset + 1
}
Some(column)
}
- def source : Option[SourceFile] = None
- def lineContent: String =
- if (!line.isEmpty && !source.isEmpty) source.get.lineToString(line.get - 1)
+ def lineContent: String = {
+ val line = this.line
+ if (!line.isEmpty) source.get.lineToString(line.get - 1)
else "NO_LINE"
+ }
+
+
/** Map this position to a position in an original source
* file. If the SourceFile is a normal SourceFile, simply
* return this.
*/
- def inUltimateSource = if (!source.isEmpty) source.get.positionInUltimateSource(this)
- else this
+ def inUltimateSource(source : SourceFile) =
+ if (source == null) this else source.positionInUltimateSource(this)
def dbgString = {
(if (source.isEmpty) "" else "source-" + source.get.path) +
(if (line.isEmpty) "" else "line-" + line.get) +
- (if (offset.isEmpty || source.isEmpty) ""
- else if (offset.get >= source.get.content.length) "out-of-bounds-" + offset.get
+ (if (offset.isEmpty) ""
+ else if (offset.get >= source.get.length) "out-of-bounds-" + offset.get
else {
val ret = "offset=" + offset.get;
var add = "";
- while (offset.get + add.length < source.get.content.length &&
+ /*
+ while (offset.get + add.length < source.get.length &&
add.length < 10) add = add + source.get.content(offset.get + add.length());
+ */
ret + " c[0..9]=\"" + add + "\"";
})
}
@@ -59,14 +70,14 @@ trait Position {
object NoPosition extends Position;
case class FakePos(msg : String) extends Position;
-case class LinePosition(line0 : Int, override val source : Option[SourceFile]) extends Position {
- def this(line0 : Int) = this(line0, None)
+case class LinePosition(source0 : SourceFile, line0 : Int) extends Position {
assert(line0 >= 1)
override def offset = None
override def column = None
override def line = Some(line0)
+ override def source = Some(source0)
}
case class OffsetPosition(source0 : SourceFile, offset0 : Int) extends Position {
override def source = Some(source0)
override def offset = Some(offset0)
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index f810fe96f0..4f4694b6b7 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -6,72 +6,115 @@
// $Id$
package scala.tools.nsc.util
-
import scala.tools.nsc.io.{AbstractFile, VirtualFile}
-/** Uses positions that are offsets rather than line/column pairs.
- *
- */
object SourceFile {
val LF: Char = 0x0A
val FF: Char = 0x0C
val CR: Char = 0x0D
val SU: Char = 0x1A
- def isLineBreak(c: Char) = c == LF || c == FF || c == CR || c == SU
+ def isLineBreak(c: Int) = c match {
+ case LF|FF|CR|SU => true
+ case _ => false
+ }
}
-
-/** Uses positions that are offsets rather than line/column pairs.
- *
- * @author Sean McDirmid
- * @version 1.0
- */
-class SourceFile(val file: AbstractFile, _content: Array[Char]) {
+/** abstract base class of a source file used in the compiler */
+abstract class SourceFile {
import SourceFile._
+ //def content : Seq[Char] // normalized, must end in SU
+ def file : AbstractFile
+ def isLineBreak(idx : Int) : Boolean
+ def length : Int
+ def position(offset: Int) : Position = {
+ assert(offset < length)
+ new OffsetPosition(this, offset)
+ }
+ def position(line: Int, column: Int) : Position = new OffsetPosition(this, lineToOffset(line) + column)
+ def offsetToLine(offset: Int): Int
+ def lineToOffset(index : Int): Int
+ /** Map a position to a position in the underlying source file.
+ * For regular source files, simply return the argument.
+ */
+ def positionInUltimateSource(position: Position) = position
+ override def toString(): String = file.name /* + ":" + content.length */
+ def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString
+ def path = file.path
- def this(_file: AbstractFile) = this(_file, _file.toCharArray)
+ def beginsWith(offset: Int, text: String): Boolean
+ def skipWhitespace(offset: Int): Int
+ def lineToString(index: Int): String
+
+ def identifier(pos : Position, compiler : scala.tools.nsc.Global) : Option[String] = None
+}
+/** a file whose contents do not change over time */
+class BatchSourceFile(val file : AbstractFile, _content : Array[Char]) extends SourceFile {
+ import SourceFile._
+ def this(_file: AbstractFile) = this(_file, _file.toCharArray)
def this(sourceName: String, content: Array[Char]) =
this(new VirtualFile(sourceName), content)
+ override def equals(that : Any) = that match {
+ case that : BatchSourceFile => file == that.file
+ case _ => false
+ }
+ override def hashCode = file.hashCode
+
+ val content = _content // don't sweat it...
+ override val length = content.length
+ override def identifier(pos : Position, compiler : scala.tools.nsc.Global) = pos match {
+ case OffsetPosition(source,offset) if source == this =>
+ import java.lang.Character
+ var i = offset + 1
+ while (i < content.length &&
+ (compiler.syntaxAnalyzer.isOperatorPart(content(i)) ||
+ compiler.syntaxAnalyzer.isIdentifierPart(content(i)))) i = i + 1
+
+ assert(i > offset)
+ Some(new String(content, offset, i - offset))
+ case _ => super.identifier(pos, compiler)
+ }
- val content = normalize(_content)
-
- def getContent() = content
- def getFile() = file
def isLineBreak(idx: Int) =
- if (!SourceFile.isLineBreak(content(idx))) false
- else if (content(idx) == CR && idx + 1 < content.length && content(idx + 1) == LF) false
+ if (idx >= content.length) false
+ else if (!SourceFile.isLineBreak(content(idx))) false
+ else if (content(idx) == CR && content(idx + 1) == LF) false
else true
- def position(offset: Int) = new OffsetPosition(this, offset)
- def position(line: Int, column: Int) = new OffsetPosition(this, lineToOffset(line) + column)
-
- /** Map a position to a position in the underlying source file.
- * For regular source files, simply return the argument.
- */
- def positionInUltimateSource(position: Position) = position
-
- // constants
-
- // NOTE: all indexes are based on zero!!!!
- override def toString(): String = file.name /* + ":" + content.length */
-
- def dbg(offset: Int) = (new OffsetPosition(this, offset)).dbgString
+ 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 += 1
+ }
+ return true
+ }
+ def skipWhitespace(offset: Int): Int =
+ if (content(offset).isWhitespace) skipWhitespace(offset + 1)
+ else offset
+ def lineToString(index: Int): String = {
+ var offset = lineToOffset(index)
+ val buf = new StringBuilder()
+ while (!isLineBreak(offset) && offset < content.length) {
+ buf.append(content(offset))
+ offset += 1
+ }
+ buf.toString()
+ }
object line {
var index = 0
var offset = 0
def find(toFind: Int, isIndex: Boolean): Int = {
if (toFind == 0) return 0
-
- //if (!isIndex) assert(toFind != -1)
- //if ( isIndex) assert(toFind > 0)
-
- if (!isIndex && (toFind >= content.length))
+ if (!isIndex && (toFind >= content.length)) {
+ assert(true)
throw new Error(toFind + " not valid offset in " +
file.name + ":" + content.length)
+ }
def get(isIndex : Boolean) = if (isIndex) index else offset
@@ -79,11 +122,7 @@ class SourceFile(val file: AbstractFile, _content: Array[Char]) {
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);
@@ -102,52 +141,19 @@ class SourceFile(val file: AbstractFile, _content: Array[Char]) {
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 += 1
- }
- return true
- }
- def path = getFile().path
+}
- def skipWhitespace(offset: Int): Int =
- if (content(offset).isWhitespace) skipWhitespace(offset + 1)
- else offset
- def lineToString(index: Int): String = {
- var offset = lineToOffset(index)
- val buf = new StringBuilder()
- while (!isLineBreak(offset) && offset < content.length) {
- buf.append(content(offset))
- offset += 1
- }
- buf.toString()
- }
-
- private def normalize(input : Array[Char]): Array[Char] =
- if (input.length > 0 && input(input.length - 1) == SU)
- input
- else {
- val content = new Array[Char](input.length + 1)
- Array.copy(input, 0, content, 0, input.length)
- content(input.length) = SU
- content
- }
-}
/** A source file composed of multiple other source files.
*
- * @author Sean McDirmid
* @version 1.0
*/
class CompoundSourceFile(
name: String,
- components: List[SourceFile],
+ components: List[BatchSourceFile],
contents: Array[Char])
-extends SourceFile(name, contents)
+extends BatchSourceFile(name, contents)
{
/** The usual constructor. Specify a name for the compound file and
* a list of component sources.
@@ -155,18 +161,18 @@ extends SourceFile(name, contents)
* @param name ...
* @param components ...
*/
- def this(name: String, components: SourceFile*) = {
+ def this(name: String, components: BatchSourceFile*) = {
/* Note that the contents leaves off the final SU character
* of all components */
this(
name,
components.toList,
Array.concat(components.toList.map(comp =>
- comp.content.subArray(0, comp.content.length-1)):_*))
+ comp.content.slice(0, comp.content.length-1).toArray):_*))
}
/** Create an instance with the specified components and a generic name. */
- def this(components: SourceFile*) =
+ def this(components: BatchSourceFile*) =
this("(virtual file)", components.toList:_*)
override def positionInUltimateSource(position: Position) = {
@@ -178,7 +184,7 @@ extends SourceFile(name, contents)
off = off - compsLeft.head.content.length + 1
compsLeft = compsLeft.tail
}
- compsLeft.head.positionInUltimateSource(new OffsetPosition(compsLeft.head, off))
+ compsLeft.head.positionInUltimateSource(new OffsetPosition(this, off))
}
}
}
@@ -190,21 +196,20 @@ extends SourceFile(name, contents)
*/
class SourceFileFragment(
name: String,
- underlyingFile: SourceFile,
+ underlyingFile: BatchSourceFile,
start: Int,
stop: Int,
contents: Array[Char])
-extends SourceFile(name, contents)
-{
- def this(name: String, underlyingFile: SourceFile, start: Int, stop: Int) =
+extends BatchSourceFile(name, contents) {
+ def this(name: String, underlyingFile: BatchSourceFile, start: Int, stop: Int) =
this(
name,
underlyingFile,
start,
stop,
- underlyingFile.content.subArray(start, stop))
+ underlyingFile.content.slice(start, stop).toArray)
- def this(underlyingFile: SourceFile, start: Int, stop: Int) =
+ def this(underlyingFile: BatchSourceFile, start: Int, stop: Int) =
this(
"(fragment of " + underlyingFile.file.name + ")",
underlyingFile,
@@ -214,7 +219,7 @@ extends SourceFile(name, contents)
override def positionInUltimateSource(position: Position) = {
if (position.offset.isEmpty)
super.positionInUltimateSource(position)
- else underlyingFile.positionInUltimateSource(
- new OffsetPosition(underlyingFile, position.offset.get + start))
+ else positionInUltimateSource(
+ new OffsetPosition(this, position.offset.get + start))
}
}
diff --git a/src/library/scala/collection/jcl/BufferWrapper.scala b/src/library/scala/collection/jcl/BufferWrapper.scala
index 1a3e9a35e6..b1b388ed19 100644
--- a/src/library/scala/collection/jcl/BufferWrapper.scala
+++ b/src/library/scala/collection/jcl/BufferWrapper.scala
@@ -40,7 +40,7 @@ trait BufferWrapper[A] extends Buffer[A] with CollectionWrapper[A] {
}
override def elements = super[BufferWrapper].elements;
}
- class IteratorWrapper(underlying : java.util.ListIterator) extends super.IteratorWrapper(underlying) with BufferIterator[Int,A] {
+ class IteratorWrapper(underlying : java.util.ListIterator) extends MutableIterator.Wrapper[A](underlying) with BufferIterator[Int,A] {
def add(a : A) = underlying.add(a);
def set(a : A) = underlying.set(a);
def hasPrevious = underlying.hasPrevious;
diff --git a/src/library/scala/collection/jcl/IterableWrapper.scala b/src/library/scala/collection/jcl/IterableWrapper.scala
index c89d7bf748..a0c1c1d51a 100644
--- a/src/library/scala/collection/jcl/IterableWrapper.scala
+++ b/src/library/scala/collection/jcl/IterableWrapper.scala
@@ -28,12 +28,14 @@ trait IterableWrapper[A] extends MutableIterable[A] {
override def size = underlying.size;
override def isEmpty = underlying.isEmpty;
override def clear = underlying.clear;
- override def elements : MutableIterator[A] = new IteratorWrapper(underlying.iterator);
+ override def elements : MutableIterator[A] = new MutableIterator.Wrapper[A](underlying.iterator);
+/* moved to MutableIterator
class IteratorWrapper(underlying : java.util.Iterator) extends MutableIterator[A] {
// val underlying = IterableWrapper.this.underlying.iterator;
def hasNext = underlying.hasNext;
def next = underlying.next.asInstanceOf[A];
def remove = underlying.remove;
}
+*/
}
diff --git a/src/library/scala/collection/jcl/Map.scala b/src/library/scala/collection/jcl/Map.scala
index 40b2bcaf9c..a702fb15f1 100644
--- a/src/library/scala/collection/jcl/Map.scala
+++ b/src/library/scala/collection/jcl/Map.scala
@@ -23,10 +23,13 @@ trait Map[K,E] extends MutableIterable[Tuple2[K,E]] with scala.collection.mutabl
removals from the returned collection will remove the element from this map.
@returns a projection of this map's elements. */
def valueSet : MutableIterable.Projection[E] = projection.map(_._2);
- def put(key : K, elem : E) : Option[E];
- def putAll(that : Iterable[Tuple2[K,E]]) : Unit =
+
+ override def put(key : K, elem : E) : Option[E] = throw new java.lang.AbstractMethodError
+
+ override def ++=(that : Iterable[(K,E)]) : Unit =
that.foreach(p => put(p._1, p._2));
- def removeKey(key : K) : Option[E] = {
+
+ override def removeKey(key : K) : Option[E] = {
val i = elements;
while (!i.hasNext) {
val result = i.next;
diff --git a/src/library/scala/collection/jcl/MapWrapper.scala b/src/library/scala/collection/jcl/MapWrapper.scala
index 48e4b47003..7e6c491289 100644
--- a/src/library/scala/collection/jcl/MapWrapper.scala
+++ b/src/library/scala/collection/jcl/MapWrapper.scala
@@ -29,9 +29,9 @@ trait MapWrapper[K,E] extends jcl.Map[K,E] {
if (ret == null) None else Some(ret.asInstanceOf[E]);
}
- override def putAll(that : Iterable[Tuple2[K,E]]) : Unit = that match {
+ override def ++=(that : Iterable[Tuple2[K,E]]) : Unit = that match {
case that : MapWrapper[_,_] => underlying.putAll(that.underlying);
- case _ => super.putAll(that);
+ case _ => super.++=(that);
}
override def removeKey(key : K) = {
val ret = underlying.remove(key);
diff --git a/src/library/scala/collection/jcl/MutableIterator.scala b/src/library/scala/collection/jcl/MutableIterator.scala
index d82368698e..d90545c7a2 100644
--- a/src/library/scala/collection/jcl/MutableIterator.scala
+++ b/src/library/scala/collection/jcl/MutableIterator.scala
@@ -10,6 +10,14 @@
package scala.collection.jcl;
+object MutableIterator {
+ class Wrapper[A](val underlying : java.util.Iterator) extends MutableIterator[A] {
+ def hasNext = underlying.hasNext;
+ def next = underlying.next.asInstanceOf[A];
+ def remove = underlying.remove;
+ }
+}
+
/** An iterator that supports the remove operation.
* These iterators wrap Java iterators, and so have the same fail fast
* behavior when dealing with concurrent modifications.
@@ -26,7 +34,7 @@ trait MutableIterator[A] extends Iterator[A] {
override def map[B](f: A => B) : MutableIterator[B] = new Map(f);
/** A type-safe version of contains.
-b **/
+ **/
def has(a: A) = exists(b => a == a);
/** Finds and removes the first instance of "a" through the iterator.
diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala
index ca1dd9d62e..1f065cb6eb 100644
--- a/src/library/scala/collection/mutable/Map.scala
+++ b/src/library/scala/collection/mutable/Map.scala
@@ -133,6 +133,25 @@ trait Map[A, B] extends AnyRef
*/
def - (key: A): Map[A, B] = { this -= key; this }
+ /** Remove <code>key</code> from this map and return the element
+ * that the key was previously mapped to (if any).
+ */
+ def removeKey(key : A) : Option[B] = {
+ val ret = get(key)
+ this -= key
+ ret
+ }
+
+ /** Map <code>key</code> to <code>elem</code> in this map and return the element
+ * that the key was previously mapped to (if any).
+ */
+ def put(key : A, elem : B) : Option[B] = {
+ val ret = get(key)
+ this(key) = elem
+ ret
+ }
+
+
/** Remove two or more keys from this map
* @param key1 the first key to be removed
* @param key2 the second key to be removed
diff --git a/src/library/scala/runtime/RichString.scala b/src/library/scala/runtime/RichString.scala
index c109b9c9cb..a16c550786 100644
--- a/src/library/scala/runtime/RichString.scala
+++ b/src/library/scala/runtime/RichString.scala
@@ -15,6 +15,7 @@ package scala.runtime
import Predef._
final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char] with Ordered[String] {
+ import RichString._
override def apply(n: Int) = self charAt n
override def length = self.length
override def toString = self
@@ -59,10 +60,6 @@ final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char
override def compare(other: String) = self compareTo other
- private final val LF: Char = 0x0A
- private final val FF: Char = 0x0C
- private final val CR: Char = 0x0D
- private final val SU: Char = 0x1A
private def isLineBreak(c: Char) = c == LF || c == FF
@@ -182,5 +179,12 @@ final class RichString(val self: String) extends Proxy with RandomAccessSeq[Char
def toLong: Long = java.lang.Long.parseLong(self)
def toFloat: Float = java.lang.Float.parseFloat(self)
def toDouble: Double = java.lang.Double.parseDouble(self)
-
}
+object RichString {
+ // just statics for rich string.
+ private final val LF: Char = 0x0A
+ private final val FF: Char = 0x0C
+ private final val CR: Char = 0x0D
+ private final val SU: Char = 0x1A
+}
+
diff --git a/test/files/neg/abstract.check b/test/files/neg/abstract.check
index f67cc2bbbd..c33011bb55 100644
--- a/test/files/neg/abstract.check
+++ b/test/files/neg/abstract.check
@@ -1,19 +1,19 @@
abstract.scala:5: error: method bar cannot be accessed in A.this.T
because its instance type ()A.this.T#T contains a malformed type: A.this.T#T
def foo1: A = bar().bar();
- ^
+ ^
abstract.scala:6: error: type mismatch;
found : A
required: A.this.T
def foo2: T = bar().baz();
- ^
+ ^
abstract.scala:8: error: method bar cannot be accessed in A
because its instance type ()A#T contains a malformed type: A#T
def foo4: A = baz().bar();
- ^
+ ^
abstract.scala:9: error: type mismatch;
found : A
required: A.this.T
def foo5: T = baz().baz();
- ^
+ ^
four errors found
diff --git a/test/files/neg/accesses.check b/test/files/neg/accesses.check
index 2fa78ffc50..11d313e534 100644
--- a/test/files/neg/accesses.check
+++ b/test/files/neg/accesses.check
@@ -1,17 +1,17 @@
accesses.scala:23: error: error overriding method f2 in class A of type => unit;
method f2 has weaker access privileges; it should not be private
private def f2: unit = ()
- ^
+ ^
accesses.scala:24: error: error overriding method f3 in class A of type => unit;
method f3 has weaker access privileges; it should be at least protected
private[p2] def f3: unit = ()
- ^
+ ^
accesses.scala:25: error: error overriding method f4 in class A of type => unit;
method f4 has weaker access privileges; it should be at least private[p1]
private[p2] def f4: unit
- ^
+ ^
accesses.scala:26: error: error overriding method f5 in class A of type => unit;
method f5 has weaker access privileges; it should be at least protected[p1]
protected[p2] def f5: unit
- ^
+ ^
four errors found
diff --git a/test/files/neg/badtok-1.check b/test/files/neg/badtok-1.check
index 6523358c79..27c7587828 100644
--- a/test/files/neg/badtok-1.check
+++ b/test/files/neg/badtok-1.check
@@ -1,7 +1,4 @@
-badtok-1.scala:2: error: expected class or object definition
+badtok-1.scala:2: error: unexpected quote after symbol
'42'
^
-badtok-1.scala:2: error: unclosed character literal
-'42'
- ^
-two errors found
+one error found
diff --git a/test/files/neg/badtok-2.check b/test/files/neg/badtok-2.check
index 4b142c37a1..6364b857a1 100644
--- a/test/files/neg/badtok-2.check
+++ b/test/files/neg/badtok-2.check
@@ -1,10 +1,7 @@
-badtok-2.scala:3: error: unclosed quoted identifier
-`x
- ^
-badtok-2.scala:3: error: illegal start of definition
+badtok-2.scala:3: error: unterminated quoted identifier
`x
^
badtok-2.scala:3: error: '}' expected but eof found.
`x
- ^
-three errors found
+ ^
+two errors found
diff --git a/test/files/neg/bug1112.check b/test/files/neg/bug1112.check
index 3be45a87fe..9aedff2de9 100644
--- a/test/files/neg/bug1112.check
+++ b/test/files/neg/bug1112.check
@@ -1,4 +1,4 @@
bug1112.scala:12: error: wrong number of arguments for method call: (int)(=> () => unit)unit
call(0,() => System.out.println("here we are"))
- ^
+ ^
one error found
diff --git a/test/files/neg/bug1183.check b/test/files/neg/bug1183.check
index 50b236187e..ebbf8aca23 100644
--- a/test/files/neg/bug1183.check
+++ b/test/files/neg/bug1183.check
@@ -1,17 +1,17 @@
bug1183.scala:10: error: name clash: class Foo defines object Baz
and its companion object Foo also defines class Baz
object Baz
- ^
+ ^
bug1183.scala:11: error: name clash: class Foo defines class Bam
and its companion object Foo also defines object Bam
class Bam
- ^
+ ^
bug1183.scala:12: error: name clash: class Foo defines object Bar
and its companion object Foo also defines class Bar
object Bar
- ^
+ ^
bug1183.scala:13: error: name clash: class Foo defines class Bar
and its companion object Foo also defines class Bar
case class Bar(i:Int)
- ^
+ ^
four errors found
diff --git a/test/files/neg/bug200.check b/test/files/neg/bug200.check
index bfce301807..d3670060cd 100644
--- a/test/files/neg/bug200.check
+++ b/test/files/neg/bug200.check
@@ -1,4 +1,4 @@
bug200.scala:7: error: method foo is defined twice
def foo: Int;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug391.check b/test/files/neg/bug391.check
index 4db19a39c4..18f36a5757 100644
--- a/test/files/neg/bug391.check
+++ b/test/files/neg/bug391.check
@@ -1,13 +1,13 @@
bug391.scala:2: error: identifier expected but 'def' found.
def fun1(def x: Int): Int = x; // the "def x" is illegal
^
-bug391.scala:3: error: ':' expected but '}' found.
- def fun2(val x: Int): Int = x; // the "val x" is illegal
- ^
+bug391.scala:4: error: ':' expected but '}' found.
+}
+^
bug391.scala:6: error: identifier expected but 'def' found.
class E(def x: Int); // the "def x" is illegal
^
bug391.scala:6: error: ':' expected but eof found.
class E(def x: Int); // the "def x" is illegal
- ^
+ ^
four errors found
diff --git a/test/files/neg/bug415.check b/test/files/neg/bug415.check
index c834a328eb..a1c68954cb 100644
--- a/test/files/neg/bug415.check
+++ b/test/files/neg/bug415.check
@@ -1,5 +1,5 @@
bug415.scala:8: error: method x cannot be accessed in A
because its instance type => A#T contains a malformed type: A#T
val y: String = a.x;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug515.check b/test/files/neg/bug515.check
index 28cdd48927..fff96a563d 100644
--- a/test/files/neg/bug515.check
+++ b/test/files/neg/bug515.check
@@ -2,5 +2,5 @@ bug515.scala:7: error: type mismatch;
found : java.lang.String
required: Test.this.Truc
val parent: Truc = file.getMachin
- ^
+ ^
one error found
diff --git a/test/files/neg/bug520.check b/test/files/neg/bug520.check
index 258f8112e3..6768ebb5fc 100644
--- a/test/files/neg/bug520.check
+++ b/test/files/neg/bug520.check
@@ -1,4 +1,4 @@
bug520.scala:8: error: overloaded method verifyKeyword needs result type
verifyKeyword("", source, pos);
- ^
+ ^
one error found
diff --git a/test/files/neg/bug521.check b/test/files/neg/bug521.check
index 80a1931231..1b05acae18 100644
--- a/test/files/neg/bug521.check
+++ b/test/files/neg/bug521.check
@@ -1,15 +1,15 @@
bug521.scala:10: error: class PlainFile needs to be abstract, since method path in class AbstractFile of type => String is not defined
class PlainFile(val file : File) extends AbstractFile {}
-^
+ ^
bug521.scala:13: error: error overriding value file in class PlainFile of type java.io.File;
value file needs `override' modifier
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
- ^
+ ^
bug521.scala:13: error: class ZipArchive needs to be abstract, since method path in class AbstractFile of type => String is not defined
final class ZipArchive(val file : File, archive : ZipFile) extends PlainFile(file) {
- ^
+ ^
bug521.scala:15: error: error overriding value path in class VirtualFile of type String;
method path needs to be an immutable value
override def path = "";
- ^
+ ^
four errors found
diff --git a/test/files/neg/bug545.check b/test/files/neg/bug545.check
index f349c084fc..892a66dfc6 100644
--- a/test/files/neg/bug545.check
+++ b/test/files/neg/bug545.check
@@ -1,6 +1,6 @@
bug545.scala:4: error: value blah is not a member of Test.this.Foo
val x = foo.blah match {
- ^
+ ^
bug545.scala:5: error: recursive value x needs type
case List(x) => x
^
diff --git a/test/files/neg/bug550.check b/test/files/neg/bug550.check
index 6c8580091c..8f1a5c0e5a 100644
--- a/test/files/neg/bug550.check
+++ b/test/files/neg/bug550.check
@@ -3,5 +3,5 @@ bug550.scala:6: error: class List takes type parameters
^
bug550.scala:8: error: no implicit argument matching parameter type Monoid[Nothing] was found.
sum(List(1,2,3))
- ^
+ ^
two errors found
diff --git a/test/files/neg/bug558.check b/test/files/neg/bug558.check
index a51856f0e6..061f64f7bb 100644
--- a/test/files/neg/bug558.check
+++ b/test/files/neg/bug558.check
@@ -1,4 +1,4 @@
bug558.scala:13: error: value file is not a member of NewModel.this.RootURL
final val source = top.file;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug576.check b/test/files/neg/bug576.check
index b496ccafd4..72d5d258d2 100644
--- a/test/files/neg/bug576.check
+++ b/test/files/neg/bug576.check
@@ -1,4 +1,4 @@
bug576.scala:14: error: overloaded method insert needs result type
if (true) sibling.insert(node);
- ^
+ ^
one error found
diff --git a/test/files/neg/bug585.check b/test/files/neg/bug585.check
index 4e2f72a941..af66898383 100644
--- a/test/files/neg/bug585.check
+++ b/test/files/neg/bug585.check
@@ -1,4 +1,4 @@
-bug585.scala:1: error: unclosed comment
+bug585.scala:1: error: unterminated comment
/*
- ^
+^
one error found
diff --git a/test/files/neg/bug588.check b/test/files/neg/bug588.check
index b1e5340c91..59e4229192 100644
--- a/test/files/neg/bug588.check
+++ b/test/files/neg/bug588.check
@@ -3,11 +3,11 @@ method visit:((int) => String)boolean and
method visit:((int) => unit)boolean at line 2
have same type after erasure: (Function1)Boolean
def visit(f: int => String): boolean
- ^
+ ^
bug588.scala:10: error: double definition:
method f:(Test.this.TypeB)Unit and
method f:(Test.this.TypeA)Unit at line 9
have same type after erasure: (Test#TraitA)Unit
def f(brac : TypeB) : Unit;
- ^
+ ^
two errors found
diff --git a/test/files/neg/bug591.check b/test/files/neg/bug591.check
index 7a1a38f52b..2c2e08da99 100644
--- a/test/files/neg/bug591.check
+++ b/test/files/neg/bug591.check
@@ -1,4 +1,4 @@
bug591.scala:38: error: method input_= is defined twice
def input_=(in : Input) = {}
- ^
+ ^
one error found
diff --git a/test/files/neg/bug630.check b/test/files/neg/bug630.check
index 600a999d20..f1ac0da57f 100644
--- a/test/files/neg/bug630.check
+++ b/test/files/neg/bug630.check
@@ -1,5 +1,5 @@
bug630.scala:20: error: error overriding value foo in trait Bar of type Req2;
object foo has incompatible type object Test.this.foo
object foo extends Req1
- ^
+ ^
one error found
diff --git a/test/files/neg/bug631.check b/test/files/neg/bug631.check
index cb18e1d397..0650c701d9 100644
--- a/test/files/neg/bug631.check
+++ b/test/files/neg/bug631.check
@@ -1,4 +1,4 @@
bug631.scala:1: error: `implicit' modifier cannot be used for top-level objects
implicit object Test {
- ^
+ ^
one error found
diff --git a/test/files/neg/bug649.check b/test/files/neg/bug649.check
index 80220e1af2..a5b97b72d1 100644
--- a/test/files/neg/bug649.check
+++ b/test/files/neg/bug649.check
@@ -1,4 +1,4 @@
bug649.scala:3: error: illegal cyclic reference involving method foo
def foo[A] = foo[A]
- ^
+ ^
one error found
diff --git a/test/files/neg/bug663.check b/test/files/neg/bug663.check
index 55b0b8f7bb..d1ef2ae09d 100644
--- a/test/files/neg/bug663.check
+++ b/test/files/neg/bug663.check
@@ -3,5 +3,5 @@ method asMatch:(Test.this.Node)Any and
method asMatch:(Test.this.Matchable)Any in trait MatchableImpl
have same type after erasure: (test.Test#NodeImpl)java.lang.Object
def asMatch(m : Node) : Any = {
- ^
+ ^
one error found
diff --git a/test/files/neg/bug664.check b/test/files/neg/bug664.check
index 176058d962..c29f9b6c7c 100644
--- a/test/files/neg/bug664.check
+++ b/test/files/neg/bug664.check
@@ -1,7 +1,7 @@
bug664.scala:4: error: type Foo is not a member of test.Test with ScalaObject
trait Foo extends super.Foo {
- ^
+ ^
bug664.scala:5: error: type Bar is not a member of AnyRef with ScalaObject
trait Bar extends super.Bar;
- ^
+ ^
two errors found
diff --git a/test/files/neg/bug691.check b/test/files/neg/bug691.check
index 47ac8c3888..f811fc3559 100644
--- a/test/files/neg/bug691.check
+++ b/test/files/neg/bug691.check
@@ -1,4 +1,4 @@
bug691.scala:27: error: ambiguous parent class qualifier
trait TiC extends super[Arrow].Ti2 with super[AssignArrow].Ti1;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug696.check b/test/files/neg/bug696.check
index a2f31702b7..28ce342cf1 100644
--- a/test/files/neg/bug696.check
+++ b/test/files/neg/bug696.check
@@ -2,8 +2,8 @@ bug696.scala:3: error: implicit method WithType is not contractive,
because the implicit parameter type TypeUtil0.this.Type[S]
is not strictly contained in the signature TypeUtil0.this.Type[S with T]
implicit def WithType[S,T](implicit tpeS : Type[S], tpeT : Type[T]) : Type[S with T] = null
- ^
+ ^
bug696.scala:4: error: no implicit argument matching parameter type TypeUtil0.this.Type[Any] was found.
as[Any](null);
- ^
+ ^
two errors found
diff --git a/test/files/neg/bug700.check b/test/files/neg/bug700.check
index 149a1564a9..33a67e5094 100644
--- a/test/files/neg/bug700.check
+++ b/test/files/neg/bug700.check
@@ -1,4 +1,4 @@
bug700.scala:6: error: method foobar in trait Foo is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'
def foobar: unit = super.foobar
- ^
+ ^
one error found
diff --git a/test/files/neg/bug712.check b/test/files/neg/bug712.check
index 59620d59cf..532eb4aec0 100644
--- a/test/files/neg/bug712.check
+++ b/test/files/neg/bug712.check
@@ -1,4 +1,4 @@
bug712.scala:10: error: value self is not a member of B.this.ParentImpl
implicit def coerce(p : ParentImpl) = p.self;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug715.check b/test/files/neg/bug715.check
index 7029220258..8ea1ddb0eb 100644
--- a/test/files/neg/bug715.check
+++ b/test/files/neg/bug715.check
@@ -1,4 +1,4 @@
bug715.scala:12: error: method chilren in trait NodeImpl is accessed from super. It may not be abstract unless it is overridden by a member declared `abstract' and `override'
override def children = super.chilren;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug729.check b/test/files/neg/bug729.check
index ae00d309b1..0b38b9bc1d 100644
--- a/test/files/neg/bug729.check
+++ b/test/files/neg/bug729.check
@@ -2,5 +2,5 @@ bug729.scala:20: error: type mismatch;
found : ScalaParserAutoEdit.this.NodeImpl(in trait Parser)
required: ScalaParserAutoEdit.this.NodeImpl(in trait ScalaParserAutoEdit)
val yyy : NodeImpl = link.from;
- ^
+ ^
one error found
diff --git a/test/files/neg/bug779.check b/test/files/neg/bug779.check
index 180fa3824e..941951900e 100644
--- a/test/files/neg/bug779.check
+++ b/test/files/neg/bug779.check
@@ -1,4 +1,4 @@
-bug779.scala:6: error: method method ast has return statement; needs result type
+bug779.scala:6: error: method ast has return statement; needs result type
override def ast = return null
^
one error found
diff --git a/test/files/neg/bug836.check b/test/files/neg/bug836.check
index 10a707ec93..1fcae2ecb3 100644
--- a/test/files/neg/bug836.check
+++ b/test/files/neg/bug836.check
@@ -1,5 +1,5 @@
bug836.scala:6: error: type S cannot be accessed in A.this.MyObj
because its instance type A.this.MyObj#S is malformed
type S = MyObj#S
- ^
+ ^
one error found
diff --git a/test/files/neg/bug839.check b/test/files/neg/bug839.check
index fa161de5a5..2f22e26d44 100644
--- a/test/files/neg/bug839.check
+++ b/test/files/neg/bug839.check
@@ -1,5 +1,5 @@
bug839.scala:25: error: method set cannot be accessed in object Test.this.FileImpl#treeBuilder
because its instance type (Test.this.Global#Tree)Unit contains a malformed type: Test.this.Global#Tree
file.treeBuilder.set(nsc.get);
- ^
+ ^
one error found
diff --git a/test/files/neg/bug856.check b/test/files/neg/bug856.check
index 80c4deeea2..3ab4ce6c70 100644
--- a/test/files/neg/bug856.check
+++ b/test/files/neg/bug856.check
@@ -1,4 +1,4 @@
bug856.scala:3: error: class ComplexRect needs to be abstract, since method _2 in trait Product2 of type => double is not defined
class ComplexRect(val _1:double, _2:double) extends Complex {
-^
+ ^
one error found
diff --git a/test/files/neg/bug876.check b/test/files/neg/bug876.check
index e7d5d5d78f..c08d4c7de8 100644
--- a/test/files/neg/bug876.check
+++ b/test/files/neg/bug876.check
@@ -1,4 +1,4 @@
bug876.scala:25: error: wrong number of arguments for method apply: (AssertionError.this.A)manager.B in trait Map
assert(manager.map(A2) == List(manager.map(A2, A1)))
- ^
+ ^
one error found
diff --git a/test/files/neg/bug877.check b/test/files/neg/bug877.check
index 6c262cdcb9..e71041348c 100644
--- a/test/files/neg/bug877.check
+++ b/test/files/neg/bug877.check
@@ -1,4 +1,7 @@
bug877.scala:3: error: parents of traits may not have parameters
trait Foo extends A(22A, Bug!) {}
^
-one error found
+bug877.scala:3: error: Invalid literal number
+trait Foo extends A(22A, Bug!) {}
+ ^
+two errors found
diff --git a/test/files/neg/bug960.check b/test/files/neg/bug960.check
index fc944bf879..c947223aa3 100644
--- a/test/files/neg/bug960.check
+++ b/test/files/neg/bug960.check
@@ -3,5 +3,5 @@ bug960.scala:18: error: cannot resolve overloaded unapply
^
bug960.scala:12: error: method unapply is defined twice
def unapply[a](xs: List[a]): Option[Null] = xs match {
- ^
+ ^
two errors found
diff --git a/test/files/neg/bug961.check b/test/files/neg/bug961.check
index 559dd93d6f..ef7e54d712 100644
--- a/test/files/neg/bug961.check
+++ b/test/files/neg/bug961.check
@@ -1,4 +1,4 @@
bug961.scala:11: error: Temp.this.B of type object Temp.this.B does not take parameters
B() match {
- ^
+ ^
one error found
diff --git a/test/files/neg/bug987.check b/test/files/neg/bug987.check
index d850f39fd9..5da1e1cbe3 100644
--- a/test/files/neg/bug987.check
+++ b/test/files/neg/bug987.check
@@ -2,17 +2,17 @@ bug987.scala:15: error: illegal inheritance;
class E inherits different type instances of trait B:
B[C] and B[D]
class E extends D
-^
+ ^
bug987.scala:20: error: illegal inheritance;
class F inherits different type instances of trait B:
B[C] and B[D]
class F extends D
-^
+ ^
bug987.scala:25: error: illegal inheritance;
class D inherits different type instances of trait B:
B[C] and B[D]
abstract class D extends C with B[D] {}
- ^
+ ^
bug987.scala:25: error: type arguments [D] do not conform to trait B's type parameter bounds [T <: B[T]]
abstract class D extends C with B[D] {}
^
diff --git a/test/files/neg/bug997.check b/test/files/neg/bug997.check
index 44e383228d..e3c86c96a4 100644
--- a/test/files/neg/bug997.check
+++ b/test/files/neg/bug997.check
@@ -1,12 +1,12 @@
bug997.scala:7: error: wrong number of arguments for object Foo
"x" match { case Foo(a) => Console.println(a) }
- ^
+ ^
bug997.scala:7: error: not found: value a
"x" match { case Foo(a) => Console.println(a) }
^
bug997.scala:13: error: wrong number of arguments for object Foo
"x" match { case Foo(a, b, c) => Console.println((a,b,c)) }
- ^
+ ^
bug997.scala:13: error: not found: value a
"x" match { case Foo(a, b, c) => Console.println((a,b,c)) }
^
diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check
index 7c0c71c803..47abfe3589 100644
--- a/test/files/neg/checksensible.check
+++ b/test/files/neg/checksensible.check
@@ -1,6 +1,6 @@
checksensible.scala:1: error: class Test needs to be abstract, since method isabstract is not defined
class Test {
-^
+ ^
checksensible.scala:3: warning: comparing values of types Ordered[Unit] and Unit using `>' will always yield false
println((c = 1) > 0)
^
diff --git a/test/files/neg/constrs.check b/test/files/neg/constrs.check
index 3680f292b2..606565d42e 100644
--- a/test/files/neg/constrs.check
+++ b/test/files/neg/constrs.check
@@ -1,9 +1,9 @@
constrs.scala:6: error: type T is not a member of object test
def this(y: int)(z: int)(t: this.T) = { this(this.u + y + z); Console.println(x) }
- ^
+ ^
constrs.scala:6: error: value u is not a member of object test
def this(y: int)(z: int)(t: this.T) = { this(this.u + y + z); Console.println(x) }
- ^
+ ^
constrs.scala:10: error: called constructor's definition must precede calling constructor's definition
def this() = this("abc")
^
diff --git a/test/files/neg/gadts1.check b/test/files/neg/gadts1.check
index 151cfad712..b16cbaf11d 100644
--- a/test/files/neg/gadts1.check
+++ b/test/files/neg/gadts1.check
@@ -2,5 +2,5 @@ gadts1.scala:15: error: type mismatch;
found : Test.this.Double
required: a
case NumTerm(n) => c.x = Double(1.0)
- ^
+ ^
one error found
diff --git a/test/files/neg/overload.check b/test/files/neg/overload.check
index f3d3454116..5f7644eda7 100644
--- a/test/files/neg/overload.check
+++ b/test/files/neg/overload.check
@@ -3,5 +3,5 @@ most specific definition is: method f in class C of type (int)Unit,
yet alternative definition method f in class D of type (Any)Unit
is defined in a subclass
(new D).f(1)
- ^
+ ^
one error found
diff --git a/test/files/neg/sabin2.check b/test/files/neg/sabin2.check
index e127cc67a2..cd45905df2 100644
--- a/test/files/neg/sabin2.check
+++ b/test/files/neg/sabin2.check
@@ -1,5 +1,5 @@
sabin2.scala:22: error: method set cannot be accessed in Test.this.Base#Inner
because its instance type (Test.this.Base#T)Unit contains a malformed type: Test.this.Base#T
a.set(b.get()) // Error
- ^
+ ^
one error found
diff --git a/test/files/neg/scopes.check b/test/files/neg/scopes.check
index b312893044..13f728b01c 100644
--- a/test/files/neg/scopes.check
+++ b/test/files/neg/scopes.check
@@ -18,7 +18,7 @@ scopes.scala:14: error: y is already defined as value y
^
scopes.scala:15: error: x is already defined as value x
val closure = (x: int, x: float) => x
- ^
+ ^
scopes.scala:17: error: x is already defined as value x
case x::x => x
^
diff --git a/test/files/neg/tcpoly_variance.check b/test/files/neg/tcpoly_variance.check
index 61d7094437..146240ac9b 100644
--- a/test/files/neg/tcpoly_variance.check
+++ b/test/files/neg/tcpoly_variance.check
@@ -1,5 +1,5 @@
tcpoly_variance.scala:6: error: error overriding method str in class A of type => m[java.lang.Object];
method str has incompatible type => m[String]
override def str: m[String] = error("foo") // since x in m[x] is invariant, ! m[String] <: m[Object]
- ^
+ ^
one error found
diff --git a/test/files/neg/typeerror.check b/test/files/neg/typeerror.check
index c087ba594b..3e21a79ad5 100644
--- a/test/files/neg/typeerror.check
+++ b/test/files/neg/typeerror.check
@@ -2,5 +2,5 @@ typeerror.scala:6: error: type mismatch;
found : Long(in method add)
required: Long(in package scala)
else add2(x.head, y.head) :: add(x.tail, y.tail)
- ^
+ ^
one error found
diff --git a/test/files/neg/variances.check b/test/files/neg/variances.check
index 4934053706..f335035b5b 100644
--- a/test/files/neg/variances.check
+++ b/test/files/neg/variances.check
@@ -15,6 +15,6 @@ variances.scala:14: error: covariant type A occurs in contravariant position in
^
variances.scala:16: error: covariant type A occurs in invariant position in type test.C[A] with ScalaObject{def this(): object Foo.this.Baz} of object Baz
object Baz extends C[A]
- ^
+ ^
three warnings found
three errors found
diff --git a/test/files/neg/xmlcorner.check b/test/files/neg/xmlcorner.check
index 8791829e50..5d3e9288d5 100644
--- a/test/files/neg/xmlcorner.check
+++ b/test/files/neg/xmlcorner.check
@@ -3,5 +3,5 @@ xmlcorner.scala:2: error: illegal start of simple expression
^
xmlcorner.scala:5: error: in XML literal: name cannot end in ':'
val wrong = <bla: />
- ^
+ ^
two errors found
diff --git a/test/files/neg/xmltruncated1.check b/test/files/neg/xmltruncated1.check
index 0014ef4011..36daa342e5 100644
--- a/test/files/neg/xmltruncated1.check
+++ b/test/files/neg/xmltruncated1.check
@@ -1,4 +1,4 @@
-xmltruncated1.scala:3: error: input ended while parsing XML
-
-^
+xmltruncated1.scala:2: error: input ended while parsing XML
+ val stuff = <a>
+ ^
one error found
diff --git a/test/files/neg/xmltruncated2.check b/test/files/neg/xmltruncated2.check
index cb7949d25f..f1de059f84 100644
--- a/test/files/neg/xmltruncated2.check
+++ b/test/files/neg/xmltruncated2.check
@@ -1,4 +1,4 @@
-xmltruncated2.scala:3: error: input ended while parsing XML
-
-^
+xmltruncated2.scala:2: error: input ended while parsing XML
+ val stuff = <![CDATA[aoeu
+ ^
one error found
diff --git a/test/files/neg/xmltruncated3.check b/test/files/neg/xmltruncated3.check
index 3c7e31912f..76851bd365 100644
--- a/test/files/neg/xmltruncated3.check
+++ b/test/files/neg/xmltruncated3.check
@@ -1,4 +1,4 @@
-xmltruncated3.scala:3: error: input ended while parsing XML
-
-^
+xmltruncated3.scala:2: error: input ended while parsing XML
+ val stuff = <a unclosedattr="aaaa
+ ^
one error found
diff --git a/test/files/neg/xmltruncated4.check b/test/files/neg/xmltruncated4.check
index c78c222ca7..4a3265d273 100644
--- a/test/files/neg/xmltruncated4.check
+++ b/test/files/neg/xmltruncated4.check
@@ -1,4 +1,4 @@
-xmltruncated4.scala:3: error: input ended while parsing XML
-
-^
+xmltruncated4.scala:2: error: input ended while parsing XML
+ val stuff = <!-- comment starts but never ends...
+ ^
one error found
diff --git a/test/files/neg/xmltruncated5.check b/test/files/neg/xmltruncated5.check
index d6f5742eab..cd13200b86 100644
--- a/test/files/neg/xmltruncated5.check
+++ b/test/files/neg/xmltruncated5.check
@@ -1,4 +1,4 @@
-xmltruncated5.scala:4: error: input ended while parsing XML
-
-^
+xmltruncated5.scala:3: error: input ended while parsing XML
+ case <a>
+ ^
one error found
diff --git a/test/files/neg/xmltruncated6.check b/test/files/neg/xmltruncated6.check
index 82d62cae5a..f638f2f090 100644
--- a/test/files/neg/xmltruncated6.check
+++ b/test/files/neg/xmltruncated6.check
@@ -1,7 +1,4 @@
-xmltruncated6.scala:2: error: ';' expected but eof found.
+xmltruncated6.scala:2: error: in XML literal: expected end of Scala block
val stuff = <a>{ "no closing brace"
^
-xmltruncated6.scala:3: error: input ended while parsing XML
-
-^
-two errors found
+one error found
diff --git a/test/files/res/bug687.check b/test/files/res/bug687.check
index 803edbbf4f..92e5e4e75d 100644
--- a/test/files/res/bug687.check
+++ b/test/files/res/bug687.check
@@ -5,7 +5,7 @@ method equals:(java.lang.Object)Boolean and
method equals:(Any)Boolean in class Any
have same type after erasure: (java.lang.Object)Boolean
override def equals(o : Object) = false;
- ^
+ ^
nsc>
nsc> \ No newline at end of file