From 76b511c18b7c45417e2b2e65cf53bb50c7d7d420 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 14 May 2008 16:50:54 +0000 Subject: 1. ConsoleReporter stops after 100 error messages. 2. Outer field from an inner class is now suppressed if it is not referenced. Reviewed by: Gilles --- .../tools/nsc/reporters/ConsoleReporter.scala | 6 ++++- .../scala/tools/nsc/reporters/Reporter.scala | 10 ++++---- src/compiler/scala/tools/nsc/symtab/Symbols.scala | 6 +++++ .../scala/tools/nsc/transform/Constructors.scala | 29 +++++++++++++++++----- .../scala/tools/nsc/transform/ExplicitOuter.scala | 25 ++++++++++++++++--- 5 files changed, 60 insertions(+), 16 deletions(-) (limited to 'src/compiler/scala/tools') diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 2ebe82509c..439aca2107 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -17,6 +17,9 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr /** Whether a short file name should be displayed before errors */ var shortname: Boolean = false + /** maximal number of error messages to be printed */ + final val ERROR_LIMIT = 100 + private def label(severity: Severity): String = severity match { case ERROR => "error" case WARNING => "warning" @@ -103,7 +106,8 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr def display(pos: Position, msg: String, severity: Severity) { severity.count += 1 - print(pos, msg, severity) + if (severity != ERROR || severity.count <= ERROR_LIMIT) + print(pos, msg, severity) } def displayPrompt: Unit = try { diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index aaecb06332..9501ce6363 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -14,12 +14,13 @@ import scala.tools.nsc.util._ */ abstract class Reporter { object severity extends Enumeration - abstract class Severity extends severity.Value { + class Severity(_id: Int) extends severity.Value { var count: Int = 0 + def id = _id } - object INFO extends Severity { def id = 0 } - object WARNING extends Severity { def id = 1 } - object ERROR extends Severity { def id = 2 } + val INFO = new Severity(0) + val WARNING = new Severity(1) + val ERROR = new Severity(2) def reset: Unit = { INFO.count = 0 @@ -28,7 +29,6 @@ abstract class Reporter { cancelled = false } - var cancelled: Boolean = false def hasErrors: Boolean = ERROR.count != 0 || cancelled diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 7d96c3acbd..b72f9c9908 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -259,6 +259,12 @@ trait Symbols { name.toString.startsWith(nme.INTERPRETER_LINE_PREFIX) && name.toString.endsWith(nme.INTERPRETER_WRAPPER_SUFFIX) + /** Is this symbol an accessor method for outer? */ + final def isOuterAccessor = { + hasFlag(STABLE | SYNTHETIC) && + originalName == nme.OUTER + } + /** Does this symbol denote a stable value? */ final def isStable = isTerm && !hasFlag(MUTABLE) && (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index d7150d981f..c191b5ed23 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -173,27 +173,44 @@ abstract class Constructors extends Transform { constrStatBuf += intoConstructor(impl.symbol, stat) } - val accessed = new TreeSet[Symbol]((x, y) => x isLess y) + val accessedSyms = new TreeSet[Symbol]((x, y) => x isLess y) + /** list of outer accessor symbols and their bodies */ + var outerAccessors: List[(Symbol, Tree)] = List() + + /** Is symbol known to be accessed outside of the primary constructor, + * or is it a symbol whose definition cannot be omitted anyway? */ def isAccessed(sym: Symbol) = sym.owner != clazz || - !(sym hasFlag PARAMACCESSOR) || - !sym.isPrivateLocal || - (accessed contains sym) + !((sym hasFlag PARAMACCESSOR) && sym.isPrivateLocal || + sym.isOuterAccessor && sym.owner == clazz && sym.owner.isFinal && sym.allOverriddenSymbols.isEmpty) || + (accessedSyms contains sym) val accessTraverser = new Traverser { override def traverse(tree: Tree) = { tree match { + case DefDef(_, _, _, _, _, body) + if (tree.symbol.isOuterAccessor && tree.symbol.owner == clazz && clazz.isFinal) => + outerAccessors ::= (tree.symbol, body) case Select(_, _) => - if (!isAccessed(tree.symbol)) accessed addEntry tree.symbol + if (!isAccessed(tree.symbol)) accessedSyms addEntry tree.symbol + super.traverse(tree) case _ => + super.traverse(tree) } - super.traverse(tree) } } + // first traverse all definitions except outeraccesors + // (outeraccessors are avoided in accessTraverser) for (stat <- defBuf.elements) accessTraverser.traverse(stat) + // then traverse all bodies of outeraccessors which are accessed themselves + // note: this relies on the fact that an outer accessor never calls another + // outer accessor in the same class. + for ((accSym, accBody) <- outerAccessors) + if (isAccessed(accSym)) accessTraverser.traverse(accBody) + val paramInits = for (acc <- paramAccessors if isAccessed(acc)) yield copyParam(acc, parameter(acc)) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 8e940f51df..56c20854db 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -123,9 +123,10 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType decls1 enter clazz.newOuterAccessor(clazz.pos).setInfo(MethodType(List(), restpe)) if (hasOuterField(clazz)) { //2 + val access = if (clazz.isFinal) PRIVATE | LOCAL else PROTECTED decls1 enter ( clazz.newValue(clazz.pos, nme.getterToLocal(nme.OUTER)) - setFlag (SYNTHETIC | PROTECTED | PARAMACCESSOR) + setFlag (SYNTHETIC | PARAMACCESSOR | access) setInfo clazz.outerClass.thisType) } } @@ -168,9 +169,25 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter /** Select and apply outer accessor from 'base' * The result is typed but not positioned. + * If the outer access is from current class and current class is final + * take outer field instead of accessor */ private def outerSelect(base: Tree): Tree = { - val path = Apply(Select(base, outerAccessor(base.tpe.typeSymbol.toInterface)), List()) + val outerAcc = outerAccessor(base.tpe.typeSymbol.toInterface) + val currentClass = this.currentClass //todo: !!! if this line is removed, we get a build failure that protected$currentClass need an override modifier + // outerFld is the $outer field of the current class, if the reference can + // use it (i.e. reference is allowed to be of the form this.$outer), + // otherwise it is NoSymbol + val outerFld = + if (outerAcc.owner == currentClass && + base.tpe =:= currentClass.thisType && + outerAcc.owner.isFinal) + outerField(currentClass).suchThat(_.owner == currentClass) + else + NoSymbol + val path = + if (outerFld != NoSymbol) Select(base, outerFld) + else Apply(Select(base, outerAcc), List()) localTyper.typed(path) } @@ -278,8 +295,8 @@ abstract class ExplicitOuter extends InfoTransform with TransMatcher with Patter /** The definition tree of the outer accessor of current class */ def outerFieldDef: Tree = { - val outerF = outerField(currentClass) - ValDef(outerF, EmptyTree) + val outerFld = outerField(currentClass) + ValDef(outerFld, EmptyTree) } /** The definition tree of the outer accessor of current class -- cgit v1.2.3