summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala14
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala19
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala26
-rw-r--r--src/library/scala/Predef.scala8
-rw-r--r--src/reflect/scala/reflect/internal/Definitions.scala6
-rw-r--r--src/reflect/scala/reflect/internal/Mirrors.scala3
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Trees.scala2
9 files changed, 80 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 15d365ab8c..b52e6fdf57 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -34,6 +34,20 @@ trait CompilationUnits { self: Global =>
/** the content of the compilation unit in tree form */
var body: Tree = EmptyTree
+ /** The position of the first xml literal encountered while parsing this compilation unit.
+ * NoPosition if there were none. Write-once.
+ */
+ private[this] var _firstXmlPos: Position = NoPosition
+
+ /** Record that we encountered XML. Should only be called once. */
+ protected[nsc] def encounteredXml(pos: Position) = _firstXmlPos = pos
+
+ /** Does this unit contain XML? */
+ def hasXml = _firstXmlPos ne NoPosition
+
+ /** Position of first XML literal in this unit. */
+ def firstXmlPos = _firstXmlPos
+
def exists = source != NoSourceFile && source != null
/** Note: depends now contains toplevel classes.
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index 692afbac66..c28a6ba337 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -19,11 +19,20 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
import global._
import definitions._
- /** Builds a fully attributed wildcard import node.
+ /** Builds a fully attributed, synthetic wildcard import node.
*/
- def mkWildcardImport(pkg: Symbol): Import = {
- assert(pkg ne null, this)
- val qual = gen.mkAttributedStableRef(pkg)
+ def mkWildcardImport(pkg: Symbol): Import =
+ mkImportFromSelector(pkg, ImportSelector.wildList)
+
+ /** Builds a fully attributed, synthetic import node.
+ * import `qualSym`.{`name` => `toName`}
+ */
+ def mkImport(qualSym: Symbol, name: Name, toName: Name): Import =
+ mkImportFromSelector(qualSym, ImportSelector(name, 0, toName, 0) :: Nil)
+
+ private def mkImportFromSelector(qualSym: Symbol, selector: List[ImportSelector]): Import = {
+ assert(qualSym ne null, this)
+ val qual = gen.mkAttributedStableRef(qualSym)
val importSym = (
NoSymbol
newImport NoPosition
@@ -31,7 +40,7 @@ abstract class TreeGen extends scala.reflect.internal.TreeGen with TreeDSL {
setInfo analyzer.ImportType(qual)
)
val importTree = (
- Import(qual, ImportSelector.wildList)
+ Import(qual, selector)
setSymbol importSym
setType NoType
)
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index fc532f5d44..ef5872986c 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -166,13 +166,20 @@ self =>
def syntaxError(offset: Int, msg: String): Unit = throw new MalformedInput(offset, msg)
def incompleteInputError(msg: String): Unit = throw new MalformedInput(source.content.length - 1, msg)
- /** the markup parser */
- lazy val xmlp = new MarkupParser(this, preserveWS = true)
-
object symbXMLBuilder extends SymbolicXMLBuilder(this, preserveWS = true) { // DEBUG choices
val global: self.global.type = self.global
}
+ /** the markup parser
+ * The first time this lazy val is accessed, we assume we were trying to parse an xml literal.
+ * The current position is recorded for later error reporting if it turns out
+ * that we don't have the xml library on the compilation classpath.
+ */
+ private[this] lazy val xmlp = {
+ currentUnit.encounteredXml(o2p(in.offset))
+ new MarkupParser(this, preserveWS = true)
+ }
+
def xmlLiteral() : Tree = xmlp.xLiteral
def xmlLiteralPattern() : Tree = xmlp.xLiteralPattern
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 61967d4cee..1f4ff7cc2d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -16,7 +16,7 @@ import scala.reflect.internal.util.shortClassOfInstance
*/
trait Contexts { self: Analyzer =>
import global._
- import definitions.{ JavaLangPackage, ScalaPackage, PredefModule }
+ import definitions.{ JavaLangPackage, ScalaPackage, PredefModule, ScalaXmlTopScope, ScalaXmlPackage }
import ContextMode._
object NoContext
@@ -93,9 +93,31 @@ trait Contexts { self: Analyzer =>
else RootImports.completeList
}
+
def rootContext(unit: CompilationUnit, tree: Tree = EmptyTree, erasedTypes: Boolean = false): Context = {
val rootImportsContext = (startContext /: rootImports(unit))((c, sym) => c.make(gen.mkWildcardImport(sym)))
- val c = rootImportsContext.make(tree, unit = unit)
+
+ // there must be a scala.xml package when xml literals were parsed in this unit
+ if (unit.hasXml && ScalaXmlPackage == NoSymbol)
+ unit.error(unit.firstXmlPos, "XML literals may only be used if the package scala.xml is present in the compilation classpath.")
+
+ // TODO: remove the def below and drop `|| predefDefinesDollarScope` in the condition for `contextWithXML`
+ // as soon as 2.11.0-M4 is released and used as STARR (and $scope is no longer defined in Predef)
+ // Until then, to allow compiling quick with pre-2.11.0-M4 STARR,
+ // which relied on Predef defining `val $scope`, we've left it in place.
+ // Since the new scheme also imports $scope (as an alias for scala.xml.TopScope),
+ // we must check whether it is still there and not import the alias to avoid ambiguity.
+ // (All of this is only necessary to compile the full quick stage with STARR.
+ // if using locker, Predef.$scope is no longer needed.)
+ def predefDefinesDollarScope = definitions.getMemberIfDefined(PredefModule, nme.dollarScope) != NoSymbol
+
+ // hack for the old xml library (detected by looking for scala.xml.TopScope, which needs to be in scope as $scope)
+ // import scala.xml.{TopScope => $scope}
+ val contextWithXML =
+ if (!unit.hasXml || ScalaXmlTopScope == NoSymbol || predefDefinesDollarScope) rootImportsContext
+ else rootImportsContext.make(gen.mkImport(ScalaXmlPackage, nme.TopScope, nme.dollarScope))
+
+ val c = contextWithXML.make(tree, unit = unit)
if (erasedTypes) c.setThrowErrors() else c.setReportErrors()
c(EnrichmentEnabled | ImplicitsEnabled) = !erasedTypes
c
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index 5ba38600b6..a188602543 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -134,7 +134,13 @@ object Predef extends LowPriorityImplicits with DeprecatedPredef {
@inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero`
@inline def locally[T](x: T): T = x // to communicate intent and avoid unmoored statements
- // Apparently needed for the xml library
+ // TODO: remove `val $scope = ...` as soon as 2.11.0-M4 is released and used as STARR
+ // As it has a '$' in its name, we don't have to deprecate first.
+ // The compiler now aliases `scala.xml.TopScope` to `$scope` (unless Predef.$scope is still there).
+ // This definition left in place for older compilers and to compile quick with pre-2.11.0-M4 STARR.
+ // In principle we don't need it to compile library/reflect/compiler (there's no xml left there),
+ // so a new locker can be built without this definition, and locker can build quick
+ // (partest, scaladoc still require xml).
val $scope = scala.xml.TopScope
// errors and asserts -------------------------------------------------
diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala
index 4f2b7e2642..3470b05495 100644
--- a/src/reflect/scala/reflect/internal/Definitions.scala
+++ b/src/reflect/scala/reflect/internal/Definitions.scala
@@ -16,7 +16,7 @@ import scala.reflect.api.{Universe => ApiUniverse}
trait Definitions extends api.StandardDefinitions {
self: SymbolTable =>
- import rootMirror.{getModule, getPackage, getClassByName, getRequiredClass, getRequiredModule, getClassIfDefined, getModuleIfDefined, getPackageObject, getPackageObjectIfDefined, requiredClass, requiredModule}
+ import rootMirror.{getModule, getPackage, getClassByName, getRequiredClass, getRequiredModule, getClassIfDefined, getModuleIfDefined, getPackageObject, getPackageIfDefined, getPackageObjectIfDefined, requiredClass, requiredModule}
object definitions extends DefinitionsClass
@@ -471,6 +471,10 @@ trait Definitions extends api.StandardDefinitions {
def methodCache_find = getMemberMethod(MethodCacheClass, nme.find_)
def methodCache_add = getMemberMethod(MethodCacheClass, nme.add_)
+ // XML
+ lazy val ScalaXmlTopScope = getModuleIfDefined("scala.xml.TopScope")
+ lazy val ScalaXmlPackage = getPackageIfDefined("scala.xml")
+
// scala.reflect
lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type]
lazy val ReflectApiPackage = getPackageObjectIfDefined("scala.reflect.api") // defined in scala-reflect.jar, so we need to be careful
diff --git a/src/reflect/scala/reflect/internal/Mirrors.scala b/src/reflect/scala/reflect/internal/Mirrors.scala
index bf38c3bf1e..6ed9de8e20 100644
--- a/src/reflect/scala/reflect/internal/Mirrors.scala
+++ b/src/reflect/scala/reflect/internal/Mirrors.scala
@@ -176,6 +176,9 @@ trait Mirrors extends api.Mirrors {
def getPackage(fullname: TermName): ModuleSymbol =
ensurePackageSymbol(fullname.toString, getModuleOrClass(fullname), allowModules = true)
+ def getPackageIfDefined(fullname: TermName): Symbol =
+ wrapMissing(getPackage(fullname))
+
@deprecated("Use getPackage", "2.11.0") def getRequiredPackage(fullname: String): ModuleSymbol =
getPackage(newTermNameCached(fullname))
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 81fffc833c..30aaaa1f3a 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -599,6 +599,7 @@ trait StdNames {
val currentMirror: NameType = "currentMirror"
val delayedInit: NameType = "delayedInit"
val delayedInitArg: NameType = "delayedInit$body"
+ val dollarScope: NameType = "$scope"
val drop: NameType = "drop"
val elem: NameType = "elem"
val emptyValDef: NameType = "emptyValDef"
@@ -684,6 +685,7 @@ trait StdNames {
val thisPrefix : NameType = "thisPrefix"
val toArray: NameType = "toArray"
val toObjectArray : NameType = "toObjectArray"
+ val TopScope: NameType = "TopScope"
val toString_ : NameType = "toString"
val toTypeConstructor: NameType = "toTypeConstructor"
val tpe : NameType = "tpe"
diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala
index 8781423a6d..ceb3b383d7 100644
--- a/src/reflect/scala/reflect/internal/Trees.scala
+++ b/src/reflect/scala/reflect/internal/Trees.scala
@@ -327,7 +327,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int) extends ImportSelectorApi
object ImportSelector extends ImportSelectorExtractor {
val wild = ImportSelector(nme.WILDCARD, -1, null, -1)
- val wildList = List(wild)
+ val wildList = List(wild) // OPT This list is shared for performance.
}
case class Import(expr: Tree, selectors: List[ImportSelector])