summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-08-06 14:24:42 +0000
committerPaul Phillips <paulp@improving.org>2011-08-06 14:24:42 +0000
commit4f4a80ad5b85ce3922c80bbc9524f2540918187e (patch)
treed56b411659069b7bcf841804875545ed0f8925da /src/compiler/scala
parent6d45fddd4c6537fb343e901d58491b81475e3786 (diff)
downloadscala-4f4a80ad5b85ce3922c80bbc9524f2540918187e.tar.gz
scala-4f4a80ad5b85ce3922c80bbc9524f2540918187e.tar.bz2
scala-4f4a80ad5b85ce3922c80bbc9524f2540918187e.zip
Don't want to chase NPEs around for the rest of...
Don't want to chase NPEs around for the rest of my life. Created "NoCompilationUnit" and "NoSourceFile" objects to represent not-present versions of these items. Seems a lot better than null. References SI-4859, got past NPE only to uncover the actual problem. No review.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala12
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala17
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
-rw-r--r--src/compiler/scala/tools/nsc/util/SourceFile.scala13
8 files changed, 40 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index aba17ca290..f5e32fbb09 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -5,12 +5,20 @@
package scala.tools.nsc
-import util.{ FreshNameCreator,Position,NoPosition,SourceFile }
+import util.{ FreshNameCreator, Position, NoPosition, SourceFile, NoSourceFile }
import scala.collection.mutable
import scala.collection.mutable.{ LinkedHashSet, ListBuffer }
trait CompilationUnits { self: Global =>
+ /** An object representing a missing compilation unit.
+ */
+ object NoCompilationUnit extends CompilationUnit(NoSourceFile) {
+ override lazy val isJava = false
+ override def exists = false
+ override def toString() = "NoCompilationUnit"
+ }
+
/** One unit of compilation that has been submitted to the compiler.
* It typically corresponds to a single file of source code. It includes
* error-reporting hooks. */
@@ -25,6 +33,8 @@ trait CompilationUnits { self: Global =>
/** the content of the compilation unit in tree form */
var body: Tree = EmptyTree
+ def exists = source != NoSourceFile && source != null
+
// def parseSettings() = {
// val argsmarker = "SCALAC_ARGS"
// if(comments nonEmpty) {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 76af2a7a03..75019f7624 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -48,7 +48,7 @@ abstract class GenICode extends SubComponent {
override def description = "Generate ICode from the AST"
- var unit: CompilationUnit = _
+ var unit: CompilationUnit = NoCompilationUnit
override def run() {
scalaPrimitives.init
@@ -61,7 +61,7 @@ abstract class GenICode extends SubComponent {
unit.icode.clear
informProgress("Generating icode for " + unit)
gen(unit.body)
- this.unit = null
+ this.unit = NoCompilationUnit
}
def gen(tree: Tree): Context = gen(tree, new Context())
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index fc53a34c45..3d7d14627c 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -205,7 +205,7 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
*/
override def signalDone(context: Context, old: Tree, result: Tree) {
if (interruptsEnabled && analyzer.lockedCount == 0) {
- if (context.unit != null &&
+ if (context.unit.exists &&
result.pos.isOpaqueRange &&
(result.pos includes context.unit.targetPos)) {
var located = new TypedLocator(context.unit.targetPos) locateIn result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 96b27b58ae..44c28cf2f5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -21,6 +21,7 @@ trait Contexts { self: Analyzer =>
val NoContext = new Context {
override def implicitss: List[List[ImplicitInfo]] = List()
outer = this
+ override def toString = "NoContext"
}
NoContext.enclClass = NoContext
NoContext.enclMethod = NoContext
@@ -89,7 +90,7 @@ trait Contexts { self: Analyzer =>
}
class Context private[typechecker] {
- var unit: CompilationUnit = _
+ var unit: CompilationUnit = NoCompilationUnit
var tree: Tree = _ // Tree associated with this context
var owner: Symbol = NoSymbol // The current owner
var scope: Scope = _ // The current scope
@@ -164,12 +165,11 @@ trait Contexts { self: Analyzer =>
*/
def make(unit: CompilationUnit, tree: Tree, owner: Symbol,
scope: Scope, imports: List[ImportInfo]): Context = {
- val c = new Context
- c.unit = unit
- c.tree = tree
+ val c = new Context
+ c.unit = unit
+ c.tree = tree
c.owner = owner
c.scope = scope
-
c.outer = this
tree match {
@@ -203,6 +203,7 @@ trait Contexts { self: Analyzer =>
c.retyping = this.retyping
c.openImplicits = this.openImplicits
registerContext(c.asInstanceOf[analyzer.Context])
+ debuglog("Created context: " + this + " ==> " + c)
c
}
@@ -364,11 +365,9 @@ trait Contexts { self: Analyzer =>
def nextEnclosing(p: Context => Boolean): Context =
if (this == NoContext || p(this)) this else outer.nextEnclosing(p)
- override def toString = (
- if (this == NoContext) "NoContext"
- else "Context(%s@%s scope=%s)".format(owner.fullName, tree.getClass.getName split "[.$]" last, scope.##)
+ override def toString = "Context(%s@%s unit=%s scope=%s)".format(
+ owner.fullName, tree.shortClass, unit, scope.##
)
-
/** Is `sub` a subclass of `base` or a companion object of such a subclass?
*/
def isSubClassOrCompanion(sub: Symbol, base: Symbol) =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 2a6fc122e2..7305cef34f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -249,7 +249,7 @@ trait Infer {
tree setSymbol sym setType ErrorType
} else {
val topClass = context.owner.toplevelClass
- if (context.unit != null)
+ if (context.unit.exists)
context.unit.depends += sym.toplevelClass
var sym1 = sym filter (alt => context.isAccessible(alt, pre, site.isInstanceOf[Super]))
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 513522e017..2c424d17d7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -414,7 +414,7 @@ trait TypeDiagnostics {
// Error suppression will squash some of these warnings unless we circumvent it.
// It is presumed if you are using a -Y option you would really like to hear
// the warnings you've requested.
- if (settings.warnDeadCode.value && context.unit != null && treeOK(tree) && exprOK) {
+ if (settings.warnDeadCode.value && context.unit.exists && treeOK(tree) && exprOK) {
val saved = context.reportGeneralErrors
try {
context.reportGeneralErrors = true
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index d8c09cc685..f305644837 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2101,7 +2101,7 @@ trait Typers extends Modes with Adaptations {
def typedStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = {
val inBlock = exprOwner == context.owner
def includesTargetPos(tree: Tree) =
- tree.pos.isRange && context.unit != null && (tree.pos includes context.unit.targetPos)
+ tree.pos.isRange && context.unit.exists && (tree.pos includes context.unit.targetPos)
val localTarget = stats exists includesTargetPos
def typedStat(stat: Tree): Tree = {
if (context.owner.isRefinementClass && !treeInfo.isDeclarationOrTypeDef(stat))
@@ -3779,7 +3779,7 @@ trait Typers extends Modes with Adaptations {
// compilation units. Defined symbols take precedence over erroneous imports.
if (defSym.definedInPackage &&
(!currentRun.compiles(defSym) ||
- (context.unit ne null) && defSym.sourceFile != context.unit.source.file))
+ context.unit.exists && defSym.sourceFile != context.unit.source.file))
defSym = NoSymbol
else if (impSym.isError || impSym.name == nme.CONSTRUCTOR)
impSym = NoSymbol
@@ -4328,8 +4328,7 @@ trait Typers extends Modes with Adaptations {
case ex: Exception =>
if (settings.debug.value) // @M causes cyclic reference error
Console.println("exception when typing "+tree+", pt = "+pt)
- if ((context ne null) && (context.unit ne null) &&
- (context.unit.source ne null) && (tree ne null))
+ if (context != null && context.unit.exists && tree != null)
logError("AT: " + (tree.pos).dbgString, ex)
throw ex
}
diff --git a/src/compiler/scala/tools/nsc/util/SourceFile.scala b/src/compiler/scala/tools/nsc/util/SourceFile.scala
index 44e06441ce..42489c5aaf 100644
--- a/src/compiler/scala/tools/nsc/util/SourceFile.scala
+++ b/src/compiler/scala/tools/nsc/util/SourceFile.scala
@@ -51,6 +51,19 @@ abstract class SourceFile {
def identifier(pos: Position): Option[String] = None
}
+/** An object representing a missing source file.
+ */
+object NoSourceFile extends SourceFile {
+ def content = Array()
+ def file = null // TODO: push NPE-defense out another level or two
+ def isLineBreak(idx: Int) = false
+ def isSelfContained = true
+ def length = -1
+ def offsetToLine(offset: Int) = -1
+ def lineToOffset(index : Int) = -1
+ override def toString = "NoSourceFile"
+}
+
object ScriptSourceFile {
/** Length of the script header from the given content, if there is one.
* The header begins with "#!" or "::#!" and ends with a line starting