diff options
Diffstat (limited to 'src/compiler')
4 files changed, 62 insertions, 34 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 8dd7e7801e..3ae1210ebf 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -493,28 +493,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def inheritanceDiagram = makeInheritanceDiagram(this) def contentDiagram = makeContentDiagram(this) - def groupSearch[T](extractor: Comment => T, default: T): T = { - // query this template - if (comment.isDefined) { - val entity = extractor(comment.get) - if (entity != default) return entity + def groupSearch[T](extractor: Comment => Option[T]): Option[T] = { + val comments = comment +: linearizationTemplates.collect { case dtpl: DocTemplateImpl => dtpl.comment } + comments.flatten.map(extractor).flatten.headOption orElse { + Option(inTpl) flatMap (_.groupSearch(extractor)) } - // query linearization - if (!sym.isPackage) - for (tpl <- linearizationTemplates.collect{ case dtpl: DocTemplateImpl if dtpl!=this => dtpl}) { - val entity = tpl.groupSearch(extractor, default) - if (entity != default) return entity - } - // query inTpl, going up the ownerChain - if (inTpl != null) - inTpl.groupSearch(extractor, default) - else - default } - def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group), if (group == defaultGroup) defaultGroupDesc else None) - def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group) match { case Some(prio) => prio; case _ => 0 }, if (group == defaultGroup) defaultGroupPriority else 0) - def groupName(group: String): String = groupSearch(_.groupNames.get(group) match { case Some(name) => name; case _ => group }, if (group == defaultGroup) defaultGroupName else group) + def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group)) orElse { if (group == defaultGroup) defaultGroupDesc else None } + def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group)) getOrElse { if (group == defaultGroup) defaultGroupPriority else 0 } + def groupName(group: String): String = groupSearch(_.groupNames.get(group)) getOrElse { if (group == defaultGroup) defaultGroupName else group } } abstract class PackageImpl(sym: Symbol, inTpl: PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package { diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 56617d0026..2ab389445f 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -20,18 +20,23 @@ import scala.tools.nsc.io.Pickler._ import scala.tools.nsc.typechecker.DivergentImplicit import scala.annotation.tailrec import symtab.Flags.{ACCESSOR, PARAMACCESSOR} +import scala.annotation.elidable import scala.language.implicitConversions /** The main class of the presentation compiler in an interactive environment such as an IDE */ -class Global(settings: Settings, _reporter: Reporter, projectName: String = "") - extends scala.tools.nsc.Global(settings, _reporter) - with CompilerControl - with RangePositions - with ContextTrees - with RichCompilationUnits - with ScratchPadMaker - with Picklers { +class Global(settings: Settings, _reporter: Reporter, projectName: String = "") extends { + /* Is the compiler initializing? Early def, so that the field is true during the + * execution of the super constructor. + */ + private var initializing = true +} with scala.tools.nsc.Global(settings, _reporter) + with CompilerControl + with RangePositions + with ContextTrees + with RichCompilationUnits + with ScratchPadMaker + with Picklers { import definitions._ @@ -51,6 +56,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") import log.logreplay debugLog("logger: " + log.getClass + " writing to " + (new java.io.File(logName)).getAbsolutePath) debugLog("classpath: "+classPath) + Console.err.println("\n ======= CHECK THREAD ACCESS compiler build ========\n") private var curTime = System.nanoTime private def timeStep = { @@ -433,7 +439,18 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") private var threadId = 0 /** The current presentation compiler runner */ - @volatile private[interactive] var compileRunner = newRunnerThread() + @volatile private[interactive] var compileRunner: Thread = newRunnerThread() + + /** Check that the currenyly executing thread is the presentation compiler thread. + * + * Compiler initialization may happen on a different thread (signalled by globalPhase being NoPhase) + */ + @elidable(elidable.WARNING) + override def assertCorrectThread() { + assert(initializing || (Thread.currentThread() eq compileRunner), + "Race condition detected: You are running a presentation compiler method outside the PC thread.[phase: %s]".format(globalPhase) + + " Please file a ticket with the current stack trace at https://www.assembla.com/spaces/scala-ide/support/tickets") + } /** Create a new presentation compiler runner. */ @@ -1110,6 +1127,12 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") alt } } + + /** The compiler has been initialized. Constructors are evaluated in textual order, + * so this is set to true only after all super constructors and the primary constructor + * have been executed. + */ + initializing = false } object CancelException extends Exception diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index c1dc91dbfc..ee7805cb3d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1376,6 +1376,16 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans ) } + private def checkCompileTimeOnly(sym: Symbol, pos: Position) = { + if (sym.isCompileTimeOnly) { + def defaultMsg = + s"""|Reference to ${sym.fullLocationString} should not have survived past type checking, + |it should have been processed and eliminated during expansion of an enclosing macro.""".stripMargin + // The getOrElse part should never happen, it's just here as a backstop. + unit.error(pos, sym.compileTimeOnlyMessage getOrElse defaultMsg) + } + } + private def lessAccessible(otherSym: Symbol, memberSym: Symbol): Boolean = ( (otherSym != NoSymbol) && !otherSym.isProtected @@ -1562,6 +1572,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkDeprecated(sym, tree.pos) if (settings.Xmigration28.value) checkMigration(sym, tree.pos) + checkCompileTimeOnly(sym, tree.pos) if (sym eq NoSymbol) { unit.warning(tree.pos, "Select node has NoSymbol! " + tree + " / " + tree.tpe) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 789211fa98..222c9ff8c3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1100,6 +1100,10 @@ trait Typers extends Modes with Adaptations with Tags { instantiateToMethodType(mt) case _ => + def shouldInsertApply(tree: Tree) = inAllModes(mode, EXPRmode | FUNmode) && (tree.tpe match { + case _: MethodType | _: OverloadedType | _: PolyType => false + case _ => applyPossible + }) def applyPossible = { def applyMeth = member(adaptToName(tree, nme.apply), nme.apply) dyna.acceptsApplyDynamic(tree.tpe) || ( @@ -1118,10 +1122,7 @@ trait Typers extends Modes with Adaptations with Tags { macroExpand(this, tree, mode, pt) else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode)) adaptConstrPattern() - else if (inAllModes(mode, EXPRmode | FUNmode) && - !tree.tpe.isInstanceOf[MethodType] && - !tree.tpe.isInstanceOf[OverloadedType] && - applyPossible) + else if (shouldInsertApply(tree)) insertApply() else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9) assert(!inHKMode(mode), modeString(mode)) //@M @@ -3079,7 +3080,7 @@ trait Typers extends Modes with Adaptations with Tags { def checkNotMacro() = { if (fun.symbol != null && fun.symbol.filter(sym => sym != null && sym.isTermMacro && !sym.isErroneous) != NoSymbol) - duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) + tryTupleApply getOrElse duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun)) } if (mt.isErroneous) duplErrTree @@ -3936,9 +3937,14 @@ trait Typers extends Modes with Adaptations with Tags { case t: ValOrDefDef => t.rhs case t => t } - val (outer, explicitTargs) = cxTree1 match { + val cxTree2 = cxTree1 match { + case Typed(t, tpe) => t // ignore outer type annotation + case t => t + } + val (outer, explicitTargs) = cxTree2 match { case TypeApply(fun, targs) => (fun, targs) case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs) + case Select(TypeApply(fun, targs), nme) => (Select(fun, nme), targs) case t => (t, Nil) } def hasNamedArg(as: List[Tree]) = as.collectFirst{case AssignOrNamedArg(lhs, rhs) =>}.nonEmpty |