summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml36
-rw-r--r--src/compiler/scala/reflect/reify/codegen/GenTrees.scala124
-rw-r--r--src/compiler/scala/reflect/reify/utils/Extractors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala20
-rw-r--r--src/compiler/scala/tools/nsc/Driver.scala6
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala73
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala39
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala87
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala79
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala97
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala2
-rwxr-xr-x[-rw-r--r--]src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala (renamed from src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala)232
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/base/LinkTo.scala15
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala230
-rwxr-xr-x[-rw-r--r--]src/compiler/scala/tools/nsc/doc/base/comment/Body.scala (renamed from src/compiler/scala/tools/nsc/doc/model/comment/Body.scala)2
-rw-r--r--src/compiler/scala/tools/nsc/doc/base/comment/Comment.scala (renamed from src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala)3
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala9
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Source.scala1
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/CommentFactory.scala114
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/LinkTo.scala24
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala225
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala44
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala3
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/Doc.scala50
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala3
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/TailCalls.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala30
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala32
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala16
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala12
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala33
-rw-r--r--src/library/scala/collection/convert/WrapAsJava.scala3
-rw-r--r--src/library/scala/collection/convert/WrapAsScala.scala5
-rw-r--r--src/library/scala/collection/immutable/Range.scala1
-rw-r--r--src/library/scala/collection/mutable/MutableList.scala10
-rw-r--r--src/library/scala/collection/mutable/Queue.scala28
-rw-r--r--src/library/scala/util/Random.scala2
-rw-r--r--src/partest/scala/tools/partest/ScaladocModelTest.scala2
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala5
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala4
-rw-r--r--test/files/jvm/serialization.scala15
-rw-r--r--test/files/neg/case-collision.check10
-rw-r--r--test/files/neg/case-collision.flags1
-rw-r--r--test/files/neg/case-collision.scala11
-rw-r--r--test/files/neg/t1672b.check16
-rw-r--r--test/files/neg/t1672b.scala52
-rw-r--r--test/files/neg/t3222.check14
-rw-r--r--test/files/neg/t4044.check7
-rw-r--r--test/files/neg/t6260.check4
-rw-r--r--test/files/neg/t6535.check6
-rw-r--r--test/files/neg/t6535.scala15
-rw-r--r--test/files/neg/t6558.check10
-rw-r--r--test/files/neg/t6558.scala12
-rw-r--r--test/files/neg/t6558b.check7
-rw-r--r--test/files/neg/t6558b.scala15
-rw-r--r--test/files/neg/t6667.check13
-rw-r--r--test/files/neg/t6667.scala10
-rw-r--r--test/files/neg/t6667b.check13
-rw-r--r--test/files/neg/t6667b.scala25
-rw-r--r--test/files/neg/t6758.check28
-rw-r--r--test/files/neg/t6758.scala43
-rw-r--r--test/files/pos/strip-tvars-for-lubbasetypes.scala25
-rw-r--r--test/files/pos/t1672.scala10
-rw-r--r--test/files/pos/t5877.scala14
-rw-r--r--test/files/pos/t5877b.scala13
-rw-r--r--test/files/pos/t6547.flags1
-rw-r--r--test/files/pos/t6547.scala6
-rw-r--r--test/files/pos/t6712.scala5
-rwxr-xr-xtest/files/presentation/doc.check48
-rwxr-xr-xtest/files/presentation/doc.scala71
-rwxr-xr-xtest/files/presentation/doc/src/Test.scala1
-rw-r--r--test/files/presentation/memory-leaks/MemoryLeaksTest.scala5
-rw-r--r--test/files/run/reify_renamed_term_basic.check1
-rw-r--r--test/files/run/reify_renamed_term_basic.scala20
-rw-r--r--test/files/run/reify_renamed_term_local_to_reifee.check1
-rw-r--r--test/files/run/reify_renamed_term_local_to_reifee.scala20
-rw-r--r--test/files/run/reify_renamed_term_overloaded_method.check1
-rw-r--r--test/files/run/reify_renamed_term_overloaded_method.scala17
-rw-r--r--test/files/run/reify_renamed_term_si5841.check1
-rw-r--r--test/files/run/reify_renamed_term_si5841.scala7
-rw-r--r--test/files/run/reify_renamed_type_basic.check1
-rw-r--r--test/files/run/reify_renamed_type_basic.scala16
-rw-r--r--test/files/run/reify_renamed_type_local_to_reifee.check1
-rw-r--r--test/files/run/reify_renamed_type_local_to_reifee.scala24
-rw-r--r--test/files/run/reify_renamed_type_spliceable.check1
-rw-r--r--test/files/run/reify_renamed_type_spliceable.scala21
-rw-r--r--test/files/run/t1672.scala28
-rw-r--r--test/files/run/t5789.check14
-rw-r--r--test/files/run/t5789.scala14
-rw-r--r--test/files/run/t5894.scala17
-rw-r--r--test/files/run/t6549.check32
-rw-r--r--test/files/run/t6549.scala22
-rw-r--r--test/files/run/t6555.check22
-rw-r--r--test/files/run/t6555.scala15
-rw-r--r--test/files/run/t6614.check11
-rw-r--r--test/files/run/t6614.scala8
-rw-r--r--test/files/run/t6690.scala62
-rwxr-xr-xtest/scaladoc/run/SI-191-deprecated.scala3
-rwxr-xr-xtest/scaladoc/run/SI-191.scala3
-rw-r--r--test/scaladoc/run/SI-3314.scala3
-rw-r--r--test/scaladoc/run/SI-5235.scala3
-rw-r--r--test/scaladoc/run/links.scala7
-rw-r--r--test/scaladoc/run/t4922.check1
-rw-r--r--test/scaladoc/run/t4922.scala32
-rw-r--r--test/scaladoc/scalacheck/CommentFactoryTest.scala3
119 files changed, 1879 insertions, 845 deletions
diff --git a/build.xml b/build.xml
index 3cfbd454e2..95e324250a 100644
--- a/build.xml
+++ b/build.xml
@@ -22,7 +22,7 @@ END-USER TARGETS
<target name="clean" depends="quick.clean"
description="Removes binaries of compiler and library. Distributions are untouched."/>
- <target name="test" depends="test.done, osgi.test"
+ <target name="test" depends="test.done, osgi.test, bc.run"
description="Runs test suite and bootstrapping test on Scala compiler and library."/>
<target name="test-opt"
@@ -2644,6 +2644,40 @@ BOOTRAPING TEST AND TEST SUITE
<target name="test.done" depends="test.suite, test.continuations.suite, test.scaladoc, test.stability, test.sbt"/>
+
+<!-- ===========================================================================
+Binary compatibility testing
+============================================================================ -->
+
+ <target name="bc.init" depends="init">
+ <property name="bc-build.dir" value="${build.dir}/bc"/>
+ <!-- Obtain mima -->
+ <mkdir dir="${bc-build.dir}"/>
+ <!-- Pull down MIMA -->
+ <artifact:dependencies pathId="mima.classpath">
+ <dependency groupId="com.typesafe" artifactId="mima-reporter_2.9.2" version="0.1.4"/>
+ </artifact:dependencies>
+ <artifact:dependencies pathId="old.bc.classpath">
+ <dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/>
+ </artifact:dependencies>
+ </target>
+
+ <target name="bc.run" depends="bc.init, pack.lib">
+ <java
+ fork="true"
+ failonerror="true"
+ classname="com.typesafe.tools.mima.cli.Main">
+ <arg value="--prev"/>
+ <arg value="${org.scala-lang:scala-library:jar}"/>
+ <arg value="--curr"/>
+ <arg value="${build-pack.dir}/lib/scala-library.jar"/>
+ <classpath>
+ <path refid="mima.classpath"/>
+ </classpath>
+ </java>
+ </target>
+
+
<!-- ===========================================================================
DISTRIBUTION
============================================================================ -->
diff --git a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
index 918aedce51..31974b5b76 100644
--- a/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
+++ b/src/compiler/scala/reflect/reify/codegen/GenTrees.scala
@@ -120,88 +120,102 @@ trait GenTrees {
// unlike in `reifyBoundType` we can skip checking for `tpe` being local or not local w.r.t the reifee
// a single check for a symbol of the bound term should be enough
// that's because only Idents and Thises can be bound terms, and they cannot host complex types
- private def reifyBoundTerm(tree: Tree): Tree = tree match {
- case tree @ This(_) if tree.symbol == NoSymbol =>
- throw new Error("unexpected: bound term that doesn't have a symbol: " + showRaw(tree))
- case tree @ This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass && !tree.symbol.isLocalToReifee =>
- val sym = tree.symbol
- if (reifyDebug) println("This for %s, reified as freeVar".format(sym))
- if (reifyDebug) println("Free: " + sym)
- mirrorBuildCall(nme.Ident, reifyFreeTerm(This(sym)))
- case tree @ This(_) if !tree.symbol.isLocalToReifee =>
- if (reifyDebug) println("This for %s, reified as This".format(tree.symbol))
- mirrorBuildCall(nme.This, reify(tree.symbol))
- case tree @ This(_) if tree.symbol.isLocalToReifee =>
- mirrorCall(nme.This, reify(tree.qual))
- case tree @ Ident(_) if tree.symbol == NoSymbol =>
- // this sometimes happens, e.g. for binds that don't have a body
- // or for untyped code generated during previous phases
- // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?")
- mirrorCall(nme.Ident, reify(tree.name))
- case tree @ Ident(_) if !tree.symbol.isLocalToReifee =>
- if (tree.symbol.isVariable && tree.symbol.owner.isTerm) {
- captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reification here.
- mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(tree.symbol)), reify(nme.elem))
- } else {
- mirrorBuildCall(nme.Ident, reify(tree.symbol))
- }
- case tree @ Ident(_) if tree.symbol.isLocalToReifee =>
- mirrorCall(nme.Ident, reify(tree.name))
- case _ =>
- throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ private def reifyBoundTerm(tree: Tree): Tree = {
+ val sym = tree.symbol
+
+ tree match {
+ case This(qual) =>
+ assert(sym != NoSymbol, "unexpected: bound term that doesn't have a symbol: " + showRaw(tree))
+ if (sym.isLocalToReifee)
+ mirrorCall(nme.This, reify(qual))
+ else if (sym.isClass && !sym.isModuleClass) {
+ if (reifyDebug) println("This for %s, reified as freeVar".format(sym))
+ if (reifyDebug) println("Free: " + sym)
+ mirrorBuildCall(nme.Ident, reifyFreeTerm(This(sym)))
+ }
+ else {
+ if (reifyDebug) println("This for %s, reified as This".format(sym))
+ mirrorBuildCall(nme.This, reify(sym))
+ }
+
+ case Ident(name) =>
+ if (sym == NoSymbol) {
+ // this sometimes happens, e.g. for binds that don't have a body
+ // or for untyped code generated during previous phases
+ // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?")
+ mirrorCall(nme.Ident, reify(name))
+ }
+ else if (!sym.isLocalToReifee) {
+ if (sym.isVariable && sym.owner.isTerm) {
+ captureVariable(sym) // Note order dependency: captureVariable needs to come before reification here.
+ mirrorCall(nme.Select, mirrorBuildCall(nme.Ident, reify(sym)), reify(nme.elem))
+ }
+ else mirrorBuildCall(nme.Ident, reify(sym))
+ }
+ else mirrorCall(nme.Ident, reify(name))
+
+ case Select(qual, name) =>
+ if (sym == NoSymbol || sym.name == name)
+ reifyProduct(tree)
+ else
+ reifyProduct(Select(qual, sym.name))
+
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
}
private def reifyBoundType(tree: Tree): Tree = {
+ val sym = tree.symbol
+ val tpe = tree.tpe
+
def reifyBoundType(tree: Tree): Tree = {
- if (tree.tpe == null)
- throw new Error("unexpected: bound type that doesn't have a tpe: " + showRaw(tree))
+ assert(tpe != null, "unexpected: bound type that doesn't have a tpe: " + showRaw(tree))
// if a symbol or a type of the scrutinee are local to reifee
// (e.g. point to a locally declared class or to a path-dependent thingie that depends on a local variable)
// then we can reify the scrutinee as a symless AST and that will definitely be hygienic
// why? because then typechecking of a scrutinee doesn't depend on the environment external to the quasiquote
// otherwise we need to reify the corresponding type
- if (tree.symbol.isLocalToReifee || tree.tpe.isLocalToReifee)
+ if (sym.isLocalToReifee || tpe.isLocalToReifee)
reifyProduct(tree)
else {
- val sym = tree.symbol
- val tpe = tree.tpe
if (reifyDebug) println("reifying bound type %s (underlying type is %s)".format(sym, tpe))
if (tpe.isSpliceable) {
val spliced = spliceType(tpe)
+
if (spliced == EmptyTree) {
if (reifyDebug) println("splicing failed: reify as is")
mirrorBuildCall(nme.TypeTree, reify(tpe))
- } else {
- spliced match {
- case TypeRefToFreeType(freeType) =>
- if (reifyDebug) println("splicing returned a free type: " + freeType)
- Ident(freeType)
- case _ =>
- if (reifyDebug) println("splicing succeeded: " + spliced)
- mirrorBuildCall(nme.TypeTree, spliced)
- }
}
- } else {
- if (sym.isLocatable) {
- if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym))
- mirrorBuildCall(nme.Ident, reify(sym))
- } else {
- if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe))
- mirrorBuildCall(nme.TypeTree, reify(tpe))
+ else spliced match {
+ case TypeRefToFreeType(freeType) =>
+ if (reifyDebug) println("splicing returned a free type: " + freeType)
+ Ident(freeType)
+ case _ =>
+ if (reifyDebug) println("splicing succeeded: " + spliced)
+ mirrorBuildCall(nme.TypeTree, spliced)
}
}
+ else if (sym.isLocatable) {
+ if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym))
+ mirrorBuildCall(nme.Ident, reify(sym))
+ }
+ else {
+ if (reifyDebug) println("tpe is not locatable: reify as TypeTree(%s)".format(tpe))
+ mirrorBuildCall(nme.TypeTree, reify(tpe))
+ }
}
}
tree match {
- case Select(_, _) =>
- reifyBoundType(tree)
- case SelectFromTypeTree(_, _) =>
- reifyBoundType(tree)
- case Ident(_) =>
+ case Select(qual, name) if name != sym.name =>
+ reifyBoundType(Select(qual, sym.name))
+
+ case Select(_, _) | SelectFromTypeTree(_, _) | Ident(_) =>
reifyBoundType(tree)
+
case _ =>
throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
}
diff --git a/src/compiler/scala/reflect/reify/utils/Extractors.scala b/src/compiler/scala/reflect/reify/utils/Extractors.scala
index b60d15c1d4..ebbcb95481 100644
--- a/src/compiler/scala/reflect/reify/utils/Extractors.scala
+++ b/src/compiler/scala/reflect/reify/utils/Extractors.scala
@@ -251,6 +251,8 @@ trait Extractors {
object BoundTerm {
def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(_, name) if name.isTermName =>
+ Some(tree)
case Ident(name) if name.isTermName =>
Some(tree)
case This(_) =>
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index 4e7ba60d5e..355a1fd262 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -23,7 +23,7 @@ trait CompilationUnits { self: Global =>
/** 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. */
- class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi {
+ class CompilationUnit(val source: SourceFile) extends CompilationUnitContextApi { self =>
/** the fresh name creator */
var fresh: FreshNameCreator = new FreshNameCreator.Default
@@ -57,7 +57,23 @@ trait CompilationUnits { self: Global =>
/** Synthetic definitions generated by namer, eliminated by typer.
*/
- val synthetics = mutable.HashMap[Symbol, Tree]()
+ object synthetics {
+ private val map = mutable.HashMap[Symbol, Tree]()
+ def update(sym: Symbol, tree: Tree) {
+ debuglog(s"adding synthetic ($sym, $tree) to $self")
+ map.update(sym, tree)
+ }
+ def -=(sym: Symbol) {
+ debuglog(s"removing synthetic $sym from $self")
+ map -= sym
+ }
+ def get(sym: Symbol): Option[Tree] = logResultIf[Option[Tree]](s"found synthetic for $sym in $self", _.isDefined) {
+ map get sym
+ }
+ def keys: Iterable[Symbol] = map.keys
+ def clear(): Unit = map.clear()
+ override def toString = map.toString
+ }
/** things to check at end of compilation unit */
val toCheck = new ListBuffer[() => Unit]
diff --git a/src/compiler/scala/tools/nsc/Driver.scala b/src/compiler/scala/tools/nsc/Driver.scala
index 1775602122..814bd58a66 100644
--- a/src/compiler/scala/tools/nsc/Driver.scala
+++ b/src/compiler/scala/tools/nsc/Driver.scala
@@ -54,10 +54,10 @@ abstract class Driver {
doCompile(compiler)
} catch {
case ex: Throwable =>
- compiler.logThrowable(ex)
+ compiler.reportThrowable(ex)
ex match {
- case FatalError(msg) => reporter.error(null, "fatal error: " + msg)
- case _ => throw ex
+ case FatalError(msg) => // signals that we should fail compilation.
+ case _ => throw ex // unexpected error, tell the outside world.
}
}
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index b0288c0149..8883920325 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -292,7 +292,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
log(msg)
}
- def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
+ @deprecated("Renamed to reportThrowable", "2.10.1")
+ def logThrowable(t: Throwable): Unit = reportThrowable(t)
+ def reportThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
override def throwableAsString(t: Throwable) = util.stackTraceString(t)
// ------------ File interface -----------------------------------------
@@ -1144,37 +1146,41 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Don't want to introduce new errors trying to report errors,
* so swallow exceptions.
*/
- override def supplementErrorMessage(errorMessage: String): String = try {
- val tree = analyzer.lastTreeToTyper
- val sym = tree.symbol
- val tpe = tree.tpe
- val enclosing = lastSeenContext.enclClassOrMethod.tree
-
- val info1 = formatExplain(
- "while compiling" -> currentSource.path,
- "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ),
- "library version" -> scala.util.Properties.versionString,
- "compiler version" -> Properties.versionString,
- "reconstructed args" -> settings.recreateArgs.mkString(" ")
- )
- val info2 = formatExplain(
- "last tree to typer" -> tree.summaryString,
- "symbol" -> Option(sym).fold("null")(_.debugLocationString),
- "symbol definition" -> Option(sym).fold("null")(_.defString),
- "tpe" -> tpe,
- "symbol owners" -> ownerChainString(sym),
- "context owners" -> ownerChainString(lastSeenContext.owner)
- )
- val info3: List[String] = (
- ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
- ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
- ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
- ++ ( List(errorMessage) )
- )
-
- ("\n" + info1) :: info2 :: info3 mkString "\n\n"
- }
- catch { case x: Exception => errorMessage }
+ override def supplementErrorMessage(errorMessage: String): String =
+ if (currentRun.supplementedError) errorMessage
+ else try {
+ val tree = analyzer.lastTreeToTyper
+ val sym = tree.symbol
+ val tpe = tree.tpe
+ val enclosing = lastSeenContext.enclClassOrMethod.tree
+
+ val info1 = formatExplain(
+ "while compiling" -> currentSource.path,
+ "during phase" -> ( if (globalPhase eq phase) phase else "global=%s, atPhase=%s".format(globalPhase, phase) ),
+ "library version" -> scala.util.Properties.versionString,
+ "compiler version" -> Properties.versionString,
+ "reconstructed args" -> settings.recreateArgs.mkString(" ")
+ )
+ val info2 = formatExplain(
+ "last tree to typer" -> tree.summaryString,
+ "symbol" -> Option(sym).fold("null")(_.debugLocationString),
+ "symbol definition" -> Option(sym).fold("null")(_.defString),
+ "tpe" -> tpe,
+ "symbol owners" -> ownerChainString(sym),
+ "context owners" -> ownerChainString(lastSeenContext.owner)
+ )
+ val info3: List[String] = (
+ ( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
+ ++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
+ ++ ( if (!opt.debug) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
+ ++ ( List(errorMessage) )
+ )
+
+ currentRun.supplementedError = true
+
+ ("\n" + info1) :: info2 :: info3 mkString "\n\n"
+ }
+ catch { case x: Exception => errorMessage }
/** The id of the currently active run
*/
@@ -1230,6 +1236,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
/** Has any macro expansion used a fallback during this run? */
var seenMacroExpansionsFallingBack = false
+ /** Have we already supplemented the error message of a compiler crash? */
+ private[nsc] final var supplementedError = false
+
/** To be initialized from firstPhase. */
private var terminalPhase: Phase = NoPhase
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index 5a4be5125d..e635c5e87d 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -19,11 +19,17 @@ import scala.collection.mutable
*/
trait DocComments { self: Global =>
- var cookedDocComments = Map[Symbol, String]()
+ val cookedDocComments = mutable.HashMap[Symbol, String]()
/** The raw doc comment map */
val docComments = mutable.HashMap[Symbol, DocComment]()
+ def clearDocComments() {
+ cookedDocComments.clear()
+ docComments.clear()
+ defs.clear()
+ }
+
/** Associate comment with symbol `sym` at position `pos`. */
def docComment(sym: Symbol, docStr: String, pos: Position = NoPosition) =
if ((sym ne null) && (sym ne NoSymbol))
@@ -55,25 +61,20 @@ trait DocComments { self: Global =>
* If a symbol does not have a doc comment but some overridden version of it does,
* the doc comment of the overridden version is copied instead.
*/
- def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.get(sym) match {
- case Some(comment) =>
- comment
- case None =>
- val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
+ def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.getOrElseUpdate(sym, {
+ val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
else DocComment(docStr).template
- val comment = superComment(sym) match {
- case None =>
- if (ownComment.indexOf("@inheritdoc") != -1)
- reporter.warning(sym.pos, "The comment for " + sym +
- " contains @inheritdoc, but no parent comment is available to inherit from.")
- ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
- case Some(sc) =>
- if (ownComment == "") sc
- else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
- }
- cookedDocComments += (sym -> comment)
- comment
- }
+ superComment(sym) match {
+ case None =>
+ if (ownComment.indexOf("@inheritdoc") != -1)
+ reporter.warning(sym.pos, "The comment for " + sym +
+ " contains @inheritdoc, but no parent comment is available to inherit from.")
+ ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
+ case Some(sc) =>
+ if (ownComment == "") sc
+ else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
+ }
+ })
/** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
*
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
index 6eb05c4402..d185ed0c34 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -21,7 +21,7 @@ import asm.Label
*
* Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2012Q2/GenASM.pdf
*/
-abstract class GenASM extends SubComponent with BytecodeWriters {
+abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM {
import global._
import icodes._
import icodes.opcodes._
@@ -32,20 +32,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
/** Create a new phase */
override def newPhase(p: Phase): Phase = new AsmPhase(p)
- private def outputDirectory(sym: Symbol): AbstractFile =
- settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
-
- private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
- var dir = base
- val pathParts = clsName.split("[./]").toList
- for (part <- pathParts.init) {
- dir = dir.subdirectoryNamed(part)
- }
- dir.fileNamed(pathParts.last + suffix)
- }
- private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
- getFile(outputDirectory(sym), clsName, suffix)
-
/** JVM code generation phase
*/
class AsmPhase(prev: Phase) extends ICodePhase(prev) {
@@ -55,62 +41,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
val BeanInfoAttr = rootMirror.getRequiredClass("scala.beans.BeanInfo")
- def isJavaEntryPoint(icls: IClass) = {
- val sym = icls.symbol
- def fail(msg: String, pos: Position = sym.pos) = {
- icls.cunit.warning(sym.pos,
- sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" +
- " Reason: " + msg
- // TODO: make this next claim true, if possible
- // by generating valid main methods as static in module classes
- // not sure what the jvm allows here
- // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead."
- )
- false
- }
- def failNoForwarder(msg: String) = {
- fail(msg + ", which means no static forwarder can be generated.\n")
- }
- val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil
- val hasApproximate = possibles exists { m =>
- m.info match {
- case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass
- case _ => false
- }
- }
- // At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
- hasApproximate && {
- // Before erasure so we can identify generic mains.
- beforeErasure {
- val companion = sym.linkedClassOfClass
- val companionMain = companion.tpe.member(nme.main)
-
- if (hasJavaMainMethod(companion))
- failNoForwarder("companion contains its own main method")
- else if (companion.tpe.member(nme.main) != NoSymbol)
- // this is only because forwarders aren't smart enough yet
- failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)")
- else if (companion.isTrait)
- failNoForwarder("companion is a trait")
- // Now either succeeed, or issue some additional warnings for things which look like
- // attempts to be java main methods.
- else possibles exists { m =>
- m.info match {
- case PolyType(_, _) =>
- fail("main methods cannot be generic.")
- case MethodType(params, res) =>
- if (res.typeSymbol :: params exists (_.isAbstractType))
- fail("main methods cannot refer to type parameters or abstract types.", m.pos)
- else
- isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos)
- case tp =>
- fail("don't know what this is: " + tp, m.pos)
- }
- }
- }
- }
- }
-
private def initBytecodeWriter(entryPoints: List[IClass]): BytecodeWriter = {
settings.outputDirs.getSingleOutput match {
case Some(f) if f hasExtension "jar" =>
@@ -160,7 +90,14 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
}
// For predictably ordered error messages.
- var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName)
+ var sortedClasses = classes.values.toList sortBy (_.symbol.fullName)
+
+ // Warn when classes will overwrite one another on case-insensitive systems.
+ for ((_, v1 :: v2 :: _) <- sortedClasses groupBy (_.symbol.javaClassName.toString.toLowerCase)) {
+ v1.cunit.warning(v1.symbol.pos,
+ s"Class ${v1.symbol.javaClassName} differs only in case from ${v2.symbol.javaClassName}. " +
+ "Such classes will overwrite one another on case-insensitive filesystems.")
+ }
debuglog("Created new bytecode generator for " + classes.size + " classes.")
val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint)
@@ -1090,12 +1027,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters {
// a plain class lacking companion module, for details see `isCandidateForForwarders`).
// -----------------------------------------------------------------------------------------
- val ExcludedForwarderFlags = {
- import Flags._
- // Should include DEFERRED but this breaks findMember.
- ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags )
- }
-
/** Add a forwarder for method m. Used only from addForwarders(). */
private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, module: Symbol, m: Symbol) {
val moduleName = javaName(module)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 3d29b2590e..fe0020e074 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -26,7 +26,7 @@ import scala.language.postfixOps
* @version 1.0
*
*/
-abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with BytecodeWriters {
+abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with BytecodeWriters with GenJVMASM {
import global._
import icodes._
import icodes.opcodes._
@@ -37,20 +37,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
/** Create a new phase */
override def newPhase(p: Phase): Phase = new JvmPhase(p)
- private def outputDirectory(sym: Symbol): AbstractFile =
- settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
-
- private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
- var dir = base
- val pathParts = clsName.split("[./]").toList
- for (part <- pathParts.init) {
- dir = dir.subdirectoryNamed(part)
- }
- dir.fileNamed(pathParts.last + suffix)
- }
- private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
- getFile(outputDirectory(sym), clsName, suffix)
-
/** JVM code generation phase
*/
class JvmPhase(prev: Phase) extends ICodePhase(prev) {
@@ -58,63 +44,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
override def erasedTypes = true
def apply(cls: IClass) = sys.error("no implementation")
- def isJavaEntryPoint(clasz: IClass) = {
- val sym = clasz.symbol
- def fail(msg: String, pos: Position = sym.pos) = {
- clasz.cunit.warning(sym.pos,
- sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" +
- " Reason: " + msg
- // TODO: make this next claim true, if possible
- // by generating valid main methods as static in module classes
- // not sure what the jvm allows here
- // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead."
- )
- false
- }
- def failNoForwarder(msg: String) = {
- fail(msg + ", which means no static forwarder can be generated.\n")
- }
- val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil
- val hasApproximate = possibles exists { m =>
- m.info match {
- case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass
- case _ => false
- }
- }
- // At this point it's a module with a main-looking method, so either
- // succeed or warn that it isn't.
- hasApproximate && {
- // Before erasure so we can identify generic mains.
- beforeErasure {
- val companion = sym.linkedClassOfClass
- val companionMain = companion.tpe.member(nme.main)
-
- if (hasJavaMainMethod(companion))
- failNoForwarder("companion contains its own main method")
- else if (companion.tpe.member(nme.main) != NoSymbol)
- // this is only because forwarders aren't smart enough yet
- failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)")
- else if (companion.isTrait)
- failNoForwarder("companion is a trait")
- // Now either succeeed, or issue some additional warnings for things which look like
- // attempts to be java main methods.
- else possibles exists { m =>
- m.info match {
- case PolyType(_, _) =>
- fail("main methods cannot be generic.")
- case MethodType(params, res) =>
- if (res.typeSymbol :: params exists (_.isAbstractType))
- fail("main methods cannot refer to type parameters or abstract types.", m.pos)
- else
- isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos)
- case tp =>
- fail("don't know what this is: " + tp, m.pos)
- }
- }
- }
- }
- }
-
override def run() {
// we reinstantiate the bytecode generator at each run, to allow the GC
// to collect everything
@@ -210,12 +139,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val BeanDisplayNameAttr = rootMirror.getRequiredClass("scala.beans.BeanDisplayName")
val BeanDescriptionAttr = rootMirror.getRequiredClass("scala.beans.BeanDescription")
- final val ExcludedForwarderFlags = {
- import Flags._
- // Should include DEFERRED but this breaks findMember.
- ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags )
- }
-
// Additional interface parents based on annotations and other cues
def newParentForAttr(attr: Symbol): Option[Symbol] = attr match {
case SerializableAttr => Some(SerializableClass)
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala
new file mode 100644
index 0000000000..49c0fa2757
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala
@@ -0,0 +1,97 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2013 LAMP/EPFL
+ * @author Jason Zaugg
+ */
+
+package scala.tools.nsc
+package backend.jvm
+import scala.tools.nsc.io.AbstractFile
+import scala.tools.nsc.symtab._
+
+/** Code shared between the legagy backend [[scala.tools.nsc.backend.jvm.GenJVM]]
+ * and the new backend [[scala.tools.nsc.backend.jvm.GenASM]]. There should be
+ * more here, but for now I'm starting with the refactorings that are either
+ * straightforward to review or necessary for maintenance.
+ */
+trait GenJVMASM {
+ val global: Global
+ import global._
+ import icodes._
+ import definitions._
+
+ protected def outputDirectory(sym: Symbol): AbstractFile =
+ settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
+
+ protected def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
+ var dir = base
+ val pathParts = clsName.split("[./]").toList
+ for (part <- pathParts.init) {
+ dir = dir.subdirectoryNamed(part)
+ }
+ dir.fileNamed(pathParts.last + suffix)
+ }
+ protected def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
+ getFile(outputDirectory(sym), clsName, suffix)
+
+ protected val ExcludedForwarderFlags = {
+ import Flags._
+ // Should include DEFERRED but this breaks findMember.
+ ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags | MACRO )
+ }
+
+ protected def isJavaEntryPoint(icls: IClass) = {
+ val sym = icls.symbol
+ def fail(msg: String, pos: Position = sym.pos) = {
+ icls.cunit.warning(sym.pos,
+ sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" +
+ " Reason: " + msg
+ // TODO: make this next claim true, if possible
+ // by generating valid main methods as static in module classes
+ // not sure what the jvm allows here
+ // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead."
+ )
+ false
+ }
+ def failNoForwarder(msg: String) = {
+ fail(msg + ", which means no static forwarder can be generated.\n")
+ }
+ val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil
+ val hasApproximate = possibles exists { m =>
+ m.info match {
+ case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass
+ case _ => false
+ }
+ }
+ // At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
+ hasApproximate && {
+ // Before erasure so we can identify generic mains.
+ beforeErasure {
+ val companion = sym.linkedClassOfClass
+ val companionMain = companion.tpe.member(nme.main)
+
+ if (hasJavaMainMethod(companion))
+ failNoForwarder("companion contains its own main method")
+ else if (companion.tpe.member(nme.main) != NoSymbol)
+ // this is only because forwarders aren't smart enough yet
+ failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)")
+ else if (companion.isTrait)
+ failNoForwarder("companion is a trait")
+ // Now either succeeed, or issue some additional warnings for things which look like
+ // attempts to be java main methods.
+ else possibles exists { m =>
+ m.info match {
+ case PolyType(_, _) =>
+ fail("main methods cannot be generic.")
+ case MethodType(params, res) =>
+ if (res.typeSymbol :: params exists (_.isAbstractType))
+ fail("main methods cannot refer to type parameters or abstract types.", m.pos)
+ else
+ isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos)
+ case tp =>
+ fail("don't know what this is: " + tp, m.pos)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
index bb14c3dce0..23f932b5b4 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/ClosureElimination.scala
@@ -147,18 +147,18 @@ abstract class ClosureElimination extends SubComponent {
case _ =>
}
- case UNBOX(_) =>
+ case UNBOX(boxType) =>
info.stack match {
case Deref(LocalVar(loc1)) :: _ if info.bindings isDefinedAt LocalVar(loc1) =>
val value = info.getBinding(loc1)
value match {
- case Boxed(LocalVar(loc2)) =>
+ case Boxed(LocalVar(loc2)) if loc2.kind == boxType =>
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(info.getBinding(loc2)) :: Nil)
debuglog("replaced " + i + " with " + info.getBinding(loc2))
case _ =>
()
}
- case Boxed(LocalVar(loc1)) :: _ =>
+ case Boxed(LocalVar(loc1)) :: _ if loc1.kind == boxType =>
val loc2 = info.getAlias(loc1)
bb.replaceInstruction(i, DROP(icodes.ObjectReference) :: valueToInstruction(Deref(LocalVar(loc2))) :: Nil)
debuglog("replaced " + i + " with " + LocalVar(loc2))
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index 642e330a57..a091b04993 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -80,7 +80,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
with model.ModelFactoryImplicitSupport
with model.ModelFactoryTypeSupport
with model.diagram.DiagramFactory
- with model.comment.CommentFactory
+ with model.CommentFactory
with model.TreeFactory
with model.MemberLookup {
override def templateShouldDocument(sym: compiler.Symbol, inTpl: DocTemplateImpl) =
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala
index 40057bbb52..f60d56d9bb 100644..100755
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala
@@ -1,13 +1,13 @@
/* NSC -- new Scala compiler
- * Copyright 2007-2013 LAMP/EPFL
+ * Copyright 2007-2012 LAMP/EPFL
* @author Manohar Jonnalagedda
*/
package scala.tools.nsc
package doc
-package model
-package comment
+package base
+import base.comment._
import reporters.Reporter
import scala.collection._
import scala.util.matching.Regex
@@ -23,78 +23,10 @@ import scala.language.postfixOps
*
* @author Manohar Jonnalagedda
* @author Gilles Dubochet */
-trait CommentFactory { thisFactory: ModelFactory with CommentFactory with MemberLookup=>
+trait CommentFactoryBase { this: MemberLookupBase =>
val global: Global
- import global.{ reporter, definitions }
-
- protected val commentCache = mutable.HashMap.empty[(global.Symbol, TemplateImpl), Comment]
-
- def addCommentBody(sym: global.Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): global.Symbol = {
- commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None)
- sym
- }
-
- def comment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = {
- val key = (sym, inTpl)
- if (commentCache isDefinedAt key)
- Some(commentCache(key))
- else {
- val c = defineComment(sym, currentTpl, inTpl)
- if (c isDefined) commentCache += (sym, inTpl) -> c.get
- c
- }
- }
-
- /** A comment is usualy created by the parser, however for some special
- * cases we have to give some `inTpl` comments (parent class for example)
- * to the comment of the symbol.
- * This function manages some of those cases : Param accessor and Primary constructor */
- def defineComment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = {
-
- //param accessor case
- // We just need the @param argument, we put it into the body
- if( sym.isParamAccessor &&
- inTpl.comment.isDefined &&
- inTpl.comment.get.valueParams.isDefinedAt(sym.encodedName)) {
- val comContent = Some(inTpl.comment.get.valueParams(sym.encodedName))
- Some(createComment(body0 = comContent))
- }
-
- // Primary constructor case
- // We need some content of the class definition : @constructor for the body,
- // @param and @deprecated, we can add some more if necessary
- else if (sym.isPrimaryConstructor && inTpl.comment.isDefined ) {
- val tplComment = inTpl.comment.get
- // If there is nothing to put into the comment there is no need to create it
- if(tplComment.constructor.isDefined ||
- tplComment.throws != Map.empty ||
- tplComment.valueParams != Map.empty ||
- tplComment.typeParams != Map.empty ||
- tplComment.deprecated.isDefined
- )
- Some(createComment( body0 = tplComment.constructor,
- throws0 = tplComment.throws,
- valueParams0 = tplComment.valueParams,
- typeParams0 = tplComment.typeParams,
- deprecated0 = tplComment.deprecated
- ))
- else None
- }
-
- //other comment cases
- // parse function will make the comment
- else {
- val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
- if (rawComment != "") {
- val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl)
- val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt)
- Some(c)
- }
- else None
- }
-
- }
+ import global.{ reporter, definitions, Symbol }
/* Creates comments with necessary arguments */
def createComment (
@@ -259,9 +191,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
* @param comment The expanded comment string (including start and end markers) to be parsed.
* @param src The raw comment source string.
* @param pos The position of the comment in source. */
- protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = {
- assert(!inTplOpt.isDefined || inTplOpt.get != null)
-
+ protected def parseAtSymbol(comment: String, src: String, pos: Position, siteOpt: Option[Symbol] = None): Comment = {
/** The cleaned raw comment as a list of lines. Cleaning removes comment
* start and end markers, line start markers and unnecessary whitespace. */
def clean(comment: String): List[String] = {
@@ -387,7 +317,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
val tagsWithoutDiagram = tags.filterNot(pair => stripTags.contains(pair._1))
val bodyTags: mutable.Map[TagKey, List[Body]] =
- mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWiki(_, pos, inTplOpt))} toSeq: _*)
+ mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, siteOpt))} toSeq: _*)
def oneTag(key: SimpleTagKey): Option[Body] =
((bodyTags remove key): @unchecked) match {
@@ -420,7 +350,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
}
val com = createComment (
- body0 = Some(parseWiki(docBody.toString, pos, inTplOpt)),
+ body0 = Some(parseWikiAtSymbol(docBody.toString, pos, siteOpt)),
authors0 = allTags(SimpleTagKey("author")),
see0 = allTags(SimpleTagKey("see")),
result0 = oneTag(SimpleTagKey("return")),
@@ -460,24 +390,17 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
* - Removed start-of-line star and one whitespace afterwards (if present).
* - Removed all end-of-line whitespace.
* - Only `endOfLine` is used to mark line endings. */
- def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = {
- assert(!inTplOpt.isDefined || inTplOpt.get != null)
-
- new WikiParser(string, pos, inTplOpt).document()
- }
+ def parseWikiAtSymbol(string: String, pos: Position, siteOpt: Option[Symbol]): Body = new WikiParser(string, pos, siteOpt).document()
/** TODO
*
* @author Ingo Maier
* @author Manohar Jonnalagedda
* @author Gilles Dubochet */
- protected final class WikiParser(val buffer: String, pos: Position, inTplOpt: Option[DocTemplateImpl]) extends CharReader(buffer) { wiki =>
- assert(!inTplOpt.isDefined || inTplOpt.get != null)
-
+ protected final class WikiParser(val buffer: String, pos: Position, siteOpt: Option[Symbol]) extends CharReader(buffer) { wiki =>
var summaryParsed = false
def document(): Body = {
- nextChar()
val blocks = new mutable.ListBuffer[Block]
while (char != endOfText)
blocks += block()
@@ -559,21 +482,21 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def code(): Block = {
jumpWhitespace()
jump("{{{")
- readUntil("}}}")
+ val str = readUntil("}}}")
if (char == endOfText)
reportError(pos, "unclosed code block")
else
jump("}}}")
blockEnded("code block")
- Code(normalizeIndentation(getRead))
+ Code(normalizeIndentation(str))
}
/** {{{ title ::= ('=' inline '=' | "==" inline "==" | ...) '\n' }}} */
def title(): Block = {
jumpWhitespace()
- val inLevel = repeatJump("=")
+ val inLevel = repeatJump('=')
val text = inline(check("=" * inLevel))
- val outLevel = repeatJump("=", inLevel)
+ val outLevel = repeatJump('=', inLevel)
if (inLevel != outLevel)
reportError(pos, "unbalanced or unclosed heading")
blockEnded("heading")
@@ -583,7 +506,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
/** {{{ hrule ::= "----" { '-' } '\n' }}} */
def hrule(): Block = {
jumpWhitespace()
- repeatJump("-")
+ repeatJump('-')
blockEnded("horizontal rule")
HorizontalRule()
}
@@ -621,8 +544,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
}
do {
- readUntil { char == safeTagMarker || char == endOfText }
- val str = getRead()
+ val str = readUntil { char == safeTagMarker || char == endOfText }
nextChar()
list += str
@@ -660,8 +582,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
else if (check(",,")) subscript()
else if (check("[[")) link()
else {
- readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
- Text(getRead())
+ val str = readUntil { char == safeTagMarker || check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
+ Text(str)
}
}
@@ -698,9 +620,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def htmlTag(): HtmlTag = {
jump(safeTagMarker)
- readUntil(safeTagMarker)
+ val read = readUntil(safeTagMarker)
if (char != endOfText) jump(safeTagMarker)
- var read = getRead
HtmlTag(read)
}
@@ -762,14 +683,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
def link(): Inline = {
val SchemeUri = """([a-z]+:.*)""".r
jump("[[")
- var parens = 1
- readUntil { parens += 1; !check("[") }
- getRead // clear the buffer
+ var parens = 2 + repeatJump('[')
val start = "[" * parens
val stop = "]" * parens
//println("link with " + parens + " matching parens")
- readUntil { check(stop) || check(" ") }
- val target = getRead()
+ val target = readUntil { check(stop) || check(" ") }
val title =
if (!check(stop)) Some({
jump(" ")
@@ -782,7 +700,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
case (SchemeUri(uri), optTitle) =>
Link(uri, optTitle getOrElse Text(uri))
case (qualName, optTitle) =>
- makeEntityLink(optTitle getOrElse Text(target), pos, target, inTplOpt)
+ makeEntityLink(optTitle getOrElse Text(target), pos, target, siteOpt)
}
}
@@ -860,7 +778,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
(char == endOfText) ||
((char == endOfLine) && {
val poff = offset
- val pc = char
nextChar() // read EOL
val ok = {
checkSkipInitWhitespace(endOfLine) ||
@@ -870,7 +787,6 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
checkSkipInitWhitespace('\u003D')
}
offset = poff
- char = pc
ok
})
}
@@ -882,40 +798,31 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
protected sealed class CharReader(buffer: String) { reader =>
- var char: Char = _
var offset: Int = 0
+ def char: Char =
+ if (offset >= buffer.length) endOfText else buffer charAt offset
final def nextChar() {
- if (offset >= buffer.length)
- char = endOfText
- else {
- char = buffer charAt offset
- offset += 1
- }
+ offset += 1
}
final def check(chars: String): Boolean = {
val poff = offset
- val pc = char
val ok = jump(chars)
offset = poff
- char = pc
ok
}
def checkSkipInitWhitespace(c: Char): Boolean = {
val poff = offset
- val pc = char
jumpWhitespace()
val ok = jump(c)
offset = poff
- char = pc
ok
}
def checkSkipInitWhitespace(chars: String): Boolean = {
val poff = offset
- val pc = char
jumpWhitespace()
val (ok0, chars0) =
if (chars.charAt(0) == ' ')
@@ -924,20 +831,17 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
(true, chars)
val ok = ok0 && jump(chars0)
offset = poff
- char = pc
ok
}
def countWhitespace: Int = {
var count = 0
val poff = offset
- val pc = char
while (isWhitespace(char) && char != endOfText) {
nextChar()
count += 1
}
offset = poff
- char = pc
count
}
@@ -964,38 +868,10 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
index == chars.length
}
- final def checkedJump(chars: String): Boolean = {
- val poff = offset
- val pc = char
- val ok = jump(chars)
- if (!ok) {
- offset = poff
- char = pc
- }
- ok
- }
-
- final def repeatJump(chars: String, max: Int): Int = {
- var count = 0
- var more = true
- while (more && count < max) {
- if (!checkedJump(chars))
- more = false
- else
- count += 1
- }
- count
- }
-
- final def repeatJump(chars: String): Int = {
+ final def repeatJump(c: Char, max: Int = Int.MaxValue): Int = {
var count = 0
- var more = true
- while (more) {
- if (!checkedJump(chars))
- more = false
- else
- count += 1
- }
+ while (jump(c) && count < max)
+ count += 1
count
}
@@ -1035,47 +911,41 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
/* READERS */
- private val readBuilder = new mutable.StringBuilder
-
- final def getRead(): String = {
- val bld = readBuilder.toString
- readBuilder.clear()
- if (bld.length < 6) bld.intern else bld
- }
-
- final def readUntil(ch: Char): Int = {
- var count = 0
- while (char != ch && char != endOfText) {
- readBuilder += char
- nextChar()
+ final def readUntil(c: Char): String = {
+ withRead {
+ while (char != c && char != endOfText) {
+ nextChar()
+ }
}
- count
}
- final def readUntil(chars: String): Int = {
+ final def readUntil(chars: String): String = {
assert(chars.length > 0)
- var count = 0
- val c = chars.charAt(0)
- while (!check(chars) && char != endOfText) {
- readBuilder += char
- nextChar()
- while (char != c && char != endOfText) {
- readBuilder += char
+ withRead {
+ val c = chars.charAt(0)
+ while (!check(chars) && char != endOfText) {
nextChar()
+ while (char != c && char != endOfText)
+ nextChar()
}
}
- count
}
- final def readUntil(pred: => Boolean): Int = {
- var count = 0
- while (!pred && char != endOfText) {
- readBuilder += char
- nextChar()
+ final def readUntil(pred: => Boolean): String = {
+ withRead {
+ while (char != endOfText && !pred) {
+ nextChar()
+ }
}
- count
}
+ private def withRead(read: => Unit): String = {
+ val start = offset
+ read
+ buffer.substring(start, offset)
+ }
+
+
/* CHARS CLASSES */
def isWhitespace(c: Char) = c == ' ' || c == '\t'
diff --git a/src/compiler/scala/tools/nsc/doc/base/LinkTo.scala b/src/compiler/scala/tools/nsc/doc/base/LinkTo.scala
new file mode 100755
index 0000000000..c11179800c
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/base/LinkTo.scala
@@ -0,0 +1,15 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2013 LAMP/EPFL
+ */
+
+package scala.tools.nsc
+package doc
+package base
+
+import scala.collection._
+
+sealed trait LinkTo
+final case class LinkToMember[Mbr, Tpl](mbr: Mbr, tpl: Tpl) extends LinkTo
+final case class LinkToTpl[Tpl](tpl: Tpl) extends LinkTo
+final case class LinkToExternal(name: String, url: String) extends LinkTo
+final case class Tooltip(name: String) extends LinkTo
diff --git a/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
new file mode 100755
index 0000000000..f3a5660dc4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
@@ -0,0 +1,230 @@
+package scala.tools.nsc
+package doc
+package base
+
+import comment._
+
+/** This trait extracts all required information for documentation from compilation units.
+ * The base trait has been extracted to allow getting light-weight documentation
+ * for a particular symbol in the IDE.*/
+trait MemberLookupBase {
+
+ val global: Global
+ val settings: doc.Settings
+
+ import global._
+ def internalLink(sym: Symbol, site: Symbol): Option[LinkTo]
+ def chooseLink(links: List[LinkTo]): LinkTo
+
+ import global._
+ import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
+ import rootMirror.{RootPackage, EmptyPackage}
+
+ private def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
+
+ def makeEntityLink(title: Inline, pos: Position, query: String, siteOpt: Option[Symbol]) =
+ new EntityLink(title) { lazy val link = memberLookup(pos, query, siteOpt) }
+
+ def memberLookup(pos: Position, query: String, siteOpt: Option[Symbol]): LinkTo = {
+ var members = breakMembers(query)
+
+ // (1) First look in the root package, as most of the links are qualified
+ val fromRoot = lookupInRootPackage(pos, members)
+
+ // (2) Or recursively go into each containing template.
+ val fromParents = siteOpt.fold(Stream.empty[Symbol]) { s =>
+ Stream.iterate(s)(_.owner)
+ }.takeWhile (!isRoot(_)).map {
+ lookupInTemplate(pos, members, _)
+ }
+
+ val syms = (fromRoot +: fromParents) find (!_.isEmpty) getOrElse Nil
+
+ val links = syms flatMap { case (sym, site) => internalLink(sym, site) } match {
+ case Nil =>
+ // (3) Look at external links
+ syms.flatMap { case (sym, owner) =>
+ // reconstruct the original link
+ def linkName(sym: Symbol) = {
+ def nameString(s: Symbol) = s.nameString + (if ((s.isModule || s.isModuleClass) && !s.isPackage) "$" else "")
+ val packageSuffix = if (sym.isPackage) ".package" else ""
+
+ sym.ownerChain.reverse.filterNot(isRoot(_)).map(nameString(_)).mkString(".") + packageSuffix
+ }
+
+ if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
+ findExternalLink(sym, linkName(sym))
+ else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage)
+ findExternalLink(sym, linkName(owner) + "@" + externalSignature(sym))
+ else
+ None
+ }
+ case links => links
+ }
+ links match {
+ case Nil =>
+ if (!settings.docNoLinkWarnings.value)
+ reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
+ // (4) if we still haven't found anything, create a tooltip
+ Tooltip(query)
+ case List(l) => l
+ case links =>
+ val chosen = chooseLink(links)
+ def linkToString(link: LinkTo) = {
+ val chosenInfo =
+ if (link == chosen) " [chosen]" else ""
+ link.toString + chosenInfo + "\n"
+ }
+ if (!settings.docNoLinkWarnings.value)
+ reporter.warning(pos,
+ "The link target \"" + query + "\" is ambiguous. Several (possibly overloaded) members fit the target:\n" +
+ links.map(linkToString).mkString +
+ (if (MemberLookup.showExplanation)
+ "\n\n" +
+ "Quick crash course on using Scaladoc links\n" +
+ "==========================================\n" +
+ "Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:\n" +
+ " - [[scala.collection.immutable.List!.apply class List's apply method]] and\n" +
+ " - [[scala.collection.immutable.List$.apply object List's apply method]]\n" +
+ "Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:\n" +
+ " - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]\n" +
+ " - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]\n" +
+ "Notes: \n" +
+ " - you can use any number of matching square brackets to avoid interference with the signature\n" +
+ " - you can use \\. to escape dots in prefixes (don't forget to use * at the end to match the signature!)\n" +
+ " - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.\n"
+ else "")
+ )
+ chosen
+ }
+ }
+
+ private abstract class SearchStrategy
+ private object BothTypeAndTerm extends SearchStrategy
+ private object OnlyType extends SearchStrategy
+ private object OnlyTerm extends SearchStrategy
+
+ private def lookupInRootPackage(pos: Position, members: List[String]) =
+ lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
+
+ private def lookupInTemplate(pos: Position, members: List[String], container: Symbol): List[(Symbol, Symbol)] = {
+ // Maintaining compatibility with previous links is a bit tricky here:
+ // we have a preference for term names for all terms except for the last, where we prefer a class:
+ // How to do this:
+ // - at each step we do a DFS search with the prefered strategy
+ // - if the search doesn't return any members, we backtrack on the last decision
+ // * we look for terms with the last member's name
+ // * we look for types with the same name, all the way up
+ val result = members match {
+ case Nil => Nil
+ case mbrName::Nil =>
+ var syms = lookupInTemplate(pos, mbrName, container, OnlyType) map ((_, container))
+ if (syms.isEmpty)
+ syms = lookupInTemplate(pos, mbrName, container, OnlyTerm) map ((_, container))
+ syms
+
+ case tplName::rest =>
+ def completeSearch(syms: List[Symbol]) =
+ syms flatMap (lookupInTemplate(pos, rest, _))
+
+ completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match {
+ case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType))
+ case syms => syms
+ }
+ }
+ //println("lookupInTemplate(" + members + ", " + container + ") => " + result)
+ result
+ }
+
+ private def lookupInTemplate(pos: Position, member: String, container: Symbol, strategy: SearchStrategy): List[Symbol] = {
+ val name = member.stripSuffix("$").stripSuffix("!").stripSuffix("*")
+ def signatureMatch(sym: Symbol): Boolean = externalSignature(sym).startsWith(name)
+
+ // We need to cleanup the bogus classes created by the .class file parser. For example, [[scala.Predef]] resolves
+ // to (bogus) class scala.Predef loaded by the class loader -- which we need to eliminate by looking at the info
+ // and removing NoType classes
+ def cleanupBogusClasses(syms: List[Symbol]) = { syms.filter(_.info != NoType) }
+
+ def syms(name: Name) = container.info.nonPrivateMember(name.encodedName).alternatives
+ def termSyms = cleanupBogusClasses(syms(newTermName(name)))
+ def typeSyms = cleanupBogusClasses(syms(newTypeName(name)))
+
+ val result = if (member.endsWith("$"))
+ termSyms
+ else if (member.endsWith("!"))
+ typeSyms
+ else if (member.endsWith("*"))
+ cleanupBogusClasses(container.info.nonPrivateDecls) filter signatureMatch
+ else
+ if (strategy == BothTypeAndTerm)
+ termSyms ::: typeSyms
+ else if (strategy == OnlyType)
+ typeSyms
+ else if (strategy == OnlyTerm)
+ termSyms
+ else
+ Nil
+
+ //println("lookupInTemplate(" + member + ", " + container + ") => " + result)
+ result
+ }
+
+ private def breakMembers(query: String): List[String] = {
+ // Okay, how does this work? Well: you split on . but you don't want to split on \. => thus the ugly regex
+ // query.split((?<=[^\\\\])\\.).map(_.replaceAll("\\."))
+ // The same code, just faster:
+ var members = List[String]()
+ var index = 0
+ var last_index = 0
+ val length = query.length
+ while (index < length) {
+ if ((query.charAt(index) == '.' || query.charAt(index) == '#') &&
+ ((index == 0) || (query.charAt(index-1) != '\\'))) {
+
+ val member = query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$1")
+ // we want to allow javadoc-style links [[#member]] -- which requires us to remove empty members from the first
+ // elemnt in the list
+ if ((member != "") || (!members.isEmpty))
+ members ::= member
+ last_index = index + 1
+ }
+ index += 1
+ }
+ if (last_index < length)
+ members ::= query.substring(last_index, length).replaceAll("\\\\\\.", ".")
+ members.reverse
+ }
+
+
+ def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
+ val sym1 =
+ if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
+ else if (sym.isPackage)
+ /* Get package object which has associatedFile ne null */
+ sym.info.member(newTermName("package"))
+ else sym
+ Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
+ val path = src.path
+ settings.extUrlMapping get path map { url =>
+ LinkToExternal(name, url + "#" + name)
+ }
+ } orElse {
+ // Deprecated option.
+ settings.extUrlPackageMapping find {
+ case (pkg, _) => name startsWith pkg
+ } map {
+ case (_, url) => LinkToExternal(name, url + "#" + name)
+ }
+ }
+ }
+
+ def externalSignature(sym: Symbol) = {
+ sym.info // force it, otherwise we see lazy types
+ (sym.nameString + sym.signatureString).replaceAll("\\s", "")
+ }
+}
+
+object MemberLookup {
+ private[this] var _showExplanation = true
+ def showExplanation: Boolean = if (_showExplanation) { _showExplanation = false; true } else false
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala b/src/compiler/scala/tools/nsc/doc/base/comment/Body.scala
index 3e5e634e18..02e662da85 100644..100755
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
+++ b/src/compiler/scala/tools/nsc/doc/base/comment/Body.scala
@@ -5,7 +5,7 @@
package scala.tools.nsc
package doc
-package model
+package base
package comment
import scala.collection._
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala b/src/compiler/scala/tools/nsc/doc/base/comment/Comment.scala
index 3e172544dd..2b28164ca4 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
+++ b/src/compiler/scala/tools/nsc/doc/base/comment/Comment.scala
@@ -5,7 +5,7 @@
package scala.tools.nsc
package doc
-package model
+package base
package comment
import scala.collection._
@@ -131,5 +131,4 @@ abstract class Comment {
(authors map ("@author " + _.toString)).mkString("\n") +
(result map ("@return " + _.toString)).mkString("\n") +
(version map ("@version " + _.toString)).mkString
-
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index e8131e242b..69da322418 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -7,8 +7,9 @@ package scala.tools.nsc
package doc
package html
+import base._
+import base.comment._
import model._
-import comment._
import scala.xml.{XML, NodeSeq}
import scala.xml.dtd.{DocType, PublicID}
@@ -126,12 +127,12 @@ abstract class HtmlPage extends Page { thisPage =>
}
def linkToHtml(text: Inline, link: LinkTo, hasLinks: Boolean) = link match {
- case LinkToTpl(dtpl) =>
+ case LinkToTpl(dtpl: TemplateEntity) =>
if (hasLinks)
<a href={ relativeLinkTo(dtpl) } class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</a>
else
<span class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</span>
- case LinkToMember(mbr, inTpl) =>
+ case LinkToMember(mbr: MemberEntity, inTpl: TemplateEntity) =>
if (hasLinks)
<a href={ relativeLinkTo(inTpl) + "#" + mbr.signature } class="extmbr" name={ mbr.qualifiedName }>{ inlineToHtml(text) }</a>
else
@@ -140,7 +141,7 @@ abstract class HtmlPage extends Page { thisPage =>
<span class="extype" name={ tooltip }>{ inlineToHtml(text) }</span>
case LinkToExternal(name, url) =>
<a href={ url } class="extype" target="_top">{ inlineToHtml(text) }</a>
- case NoLink =>
+ case _ =>
inlineToHtml(text)
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Source.scala b/src/compiler/scala/tools/nsc/doc/html/page/Source.scala
index 807a1bc11a..68289b7474 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Source.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Source.scala
@@ -9,7 +9,6 @@ package html
package page
import model._
-import comment._
import scala.xml.{NodeSeq, Unparsed}
import java.io.File
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index 008999e09f..e885e9c56e 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -8,6 +8,9 @@ package doc
package html
package page
+import base._
+import base.comment._
+
import model._
import model.diagram._
import diagram._
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
index 304c534bdc..847367838c 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/diagram/DotDiagramGenerator.scala
@@ -74,7 +74,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
def textTypeEntity(text: String) =
new TypeEntity {
val name = text
- def refEntity: SortedMap[Int, (LinkTo, Int)] = SortedMap()
+ def refEntity: SortedMap[Int, (base.LinkTo, Int)] = SortedMap()
}
// it seems dot chokes on node names over 8000 chars, so let's limit the size of the string
diff --git a/src/compiler/scala/tools/nsc/doc/model/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/CommentFactory.scala
new file mode 100644
index 0000000000..9ba89146c0
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/CommentFactory.scala
@@ -0,0 +1,114 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2013 LAMP/EPFL
+ * @author Manohar Jonnalagedda
+ */
+
+package scala.tools.nsc
+package doc
+package model
+
+import base.comment._
+
+import reporters.Reporter
+import scala.collection._
+import scala.reflect.internal.util.{NoPosition, Position}
+import scala.language.postfixOps
+
+/** The comment parser transforms raw comment strings into `Comment` objects.
+ * Call `parse` to run the parser. Note that the parser is stateless and
+ * should only be built once for a given Scaladoc run.
+ *
+ * @param reporter The reporter on which user messages (error, warnings) should be printed.
+ *
+ * @author Manohar Jonnalagedda
+ * @author Gilles Dubochet */
+trait CommentFactory extends base.CommentFactoryBase {
+ thisFactory: ModelFactory with CommentFactory with MemberLookup =>
+
+ val global: Global
+ import global.{ reporter, definitions, Symbol }
+
+ protected val commentCache = mutable.HashMap.empty[(Symbol, TemplateImpl), Comment]
+
+ def addCommentBody(sym: Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): Symbol = {
+ commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None)
+ sym
+ }
+
+ def comment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = {
+ val key = (sym, inTpl)
+ if (commentCache isDefinedAt key)
+ Some(commentCache(key))
+ else {
+ val c = defineComment(sym, currentTpl, inTpl)
+ if (c isDefined) commentCache += (sym, inTpl) -> c.get
+ c
+ }
+ }
+
+ /** A comment is usualy created by the parser, however for some special
+ * cases we have to give some `inTpl` comments (parent class for example)
+ * to the comment of the symbol.
+ * This function manages some of those cases : Param accessor and Primary constructor */
+ def defineComment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = {
+
+ //param accessor case
+ // We just need the @param argument, we put it into the body
+ if( sym.isParamAccessor &&
+ inTpl.comment.isDefined &&
+ inTpl.comment.get.valueParams.isDefinedAt(sym.encodedName)) {
+ val comContent = Some(inTpl.comment.get.valueParams(sym.encodedName))
+ Some(createComment(body0 = comContent))
+ }
+
+ // Primary constructor case
+ // We need some content of the class definition : @constructor for the body,
+ // @param and @deprecated, we can add some more if necessary
+ else if (sym.isPrimaryConstructor && inTpl.comment.isDefined ) {
+ val tplComment = inTpl.comment.get
+ // If there is nothing to put into the comment there is no need to create it
+ if(tplComment.constructor.isDefined ||
+ tplComment.throws != Map.empty ||
+ tplComment.valueParams != Map.empty ||
+ tplComment.typeParams != Map.empty ||
+ tplComment.deprecated.isDefined
+ )
+ Some(createComment( body0 = tplComment.constructor,
+ throws0 = tplComment.throws,
+ valueParams0 = tplComment.valueParams,
+ typeParams0 = tplComment.typeParams,
+ deprecated0 = tplComment.deprecated
+ ))
+ else None
+ }
+
+ //other comment cases
+ // parse function will make the comment
+ else {
+ val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
+ if (rawComment != "") {
+ val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl)
+ val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt)
+ Some(c)
+ }
+ else None
+ }
+
+ }
+
+ protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = {
+ assert(!inTplOpt.isDefined || inTplOpt.get != null)
+ parseAtSymbol(comment, src, pos, inTplOpt map (_.sym))
+ }
+
+ /** Parses a string containing wiki syntax into a `Comment` object.
+ * Note that the string is assumed to be clean:
+ * - Removed Scaladoc start and end markers.
+ * - Removed start-of-line star and one whitespace afterwards (if present).
+ * - Removed all end-of-line whitespace.
+ * - Only `endOfLine` is used to mark line endings. */
+ def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = {
+ assert(!inTplOpt.isDefined || inTplOpt.get != null)
+ parseWikiAtSymbol(string,pos, inTplOpt map (_.sym))
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index c3f9101f17..cbc1a23d44 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -9,7 +9,7 @@ package doc
package model
import scala.collection._
-import comment._
+import base.comment._
import diagram._
/** An entity in a Scaladoc universe. Entities are declarations in the program and correspond to symbols in the
diff --git a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala
deleted file mode 100644
index 6c13d5a6d3..0000000000
--- a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2007-2013 LAMP/EPFL
- */
-
-package scala.tools.nsc
-package doc
-package model
-
-import scala.collection._
-
-abstract sealed class LinkTo
-final case class LinkToTpl(tpl: DocTemplateEntity) extends LinkTo
-final case class LinkToMember(mbr: MemberEntity, inTpl: DocTemplateEntity) extends LinkTo
-final case class Tooltip(name: String) extends LinkTo { def this(tpl: TemplateEntity) = this(tpl.qualifiedName) }
-final case class LinkToExternal(name: String, url: String) extends LinkTo
-case object NoLink extends LinkTo // you should use Tooltip if you have a name from the user, this is only in case all fails
-
-object LinkToTpl {
- // this makes it easier to create links
- def apply(tpl: TemplateEntity) = tpl match {
- case dtpl: DocTemplateEntity => new LinkToTpl(dtpl)
- case ntpl: TemplateEntity => new Tooltip(ntpl.qualifiedName)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
index 5257db1610..b1105196b7 100644
--- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
@@ -2,227 +2,30 @@ package scala.tools.nsc
package doc
package model
-import comment._
-
-import scala.reflect.internal.util.FakePos //Position
+import base._
/** This trait extracts all required information for documentation from compilation units */
-trait MemberLookup {
+trait MemberLookup extends base.MemberLookupBase {
thisFactory: ModelFactory =>
import global._
- import rootMirror.RootPackage, rootMirror.EmptyPackage
-
- def makeEntityLink(title: Inline, pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]) =
- new EntityLink(title) { lazy val link = memberLookup(pos, query, inTplOpt) }
-
- def memberLookup(pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]): LinkTo = {
- assert(modelFinished)
-
- var members = breakMembers(query)
- //println(query + " => " + members)
-
- // (1) First look in the root package, as most of the links are qualified
- val fromRoot = lookupInRootPackage(pos, members)
-
- // (2) Or recursively go into each containing template.
- val fromParents = inTplOpt.fold(Stream.empty[DocTemplateImpl]) { tpl =>
- Stream.iterate(tpl)(_.inTemplate)
- }.takeWhile (tpl => tpl != null && !tpl.isRootPackage).map { tpl =>
- lookupInTemplate(pos, members, tpl.asInstanceOf[EntityImpl].sym)
- }
-
- val syms = (fromRoot +: fromParents) find (!_.isEmpty) getOrElse Nil
- val linkTo = createLinks(syms) match {
- case Nil if !syms.isEmpty =>
- // (3) Look at external links
- syms.flatMap { case (sym, owner) =>
-
- // reconstruct the original link
- def linkName(sym: Symbol) = {
- def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
- def nameString(s: Symbol) = s.nameString + (if ((s.isModule || s.isModuleClass) && !s.isPackage) "$" else "")
- val packageSuffix = if (sym.isPackage) ".package" else ""
- sym.ownerChain.reverse.filterNot(isRoot(_)).map(nameString(_)).mkString(".") + packageSuffix
- }
-
- if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
- findExternalLink(sym, linkName(sym))
- else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage)
- findExternalLink(sym, linkName(owner) + "@" + externalSignature(sym))
- else
- None
+ override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
+ findTemplateMaybe(sym) match {
+ case Some(tpl) => Some(LinkToTpl(tpl))
+ case None =>
+ findTemplateMaybe(site) flatMap { inTpl =>
+ inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl))
}
- case links => links
}
- //println(createLinks(syms))
- //println(linkTo)
-
- // (4) if we still haven't found anything, create a tooltip, if we found too many, report
- if (linkTo.isEmpty){
- if (!settings.docNoLinkWarnings.value)
- reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
- Tooltip(query)
- } else {
- if (linkTo.length > 1) {
-
- val chosen =
- if (linkTo.exists(_.isInstanceOf[LinkToMember]))
- linkTo.collect({case lm: LinkToMember => lm}).min(Ordering[MemberEntity].on[LinkToMember](_.mbr))
- else
- linkTo.head
-
- def linkToString(link: LinkTo) = {
- val description =
- link match {
- case lm@LinkToMember(mbr, inTpl) => " * " + mbr.kind + " \"" + mbr.signature + "\" in " + inTpl.kind + " " + inTpl.qualifiedName
- case lt@LinkToTpl(tpl) => " * " + tpl.kind + " \"" + tpl.qualifiedName + "\""
- case other => " * " + other.toString
- }
- val chosenInfo =
- if (link == chosen)
- " [chosen]"
- else
- ""
- description + chosenInfo + "\n"
- }
- if (!settings.docNoLinkWarnings.value)
- reporter.warning(pos,
- "The link target \"" + query + "\" is ambiguous. Several (possibly overloaded) members fit the target:\n" +
- linkTo.map(link => linkToString(link)).mkString +
- (if (MemberLookup.showExplanation)
- "\n\n" +
- "Quick crash course on using Scaladoc links\n" +
- "==========================================\n" +
- "Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:\n" +
- " - [[scala.collection.immutable.List!.apply class List's apply method]] and\n" +
- " - [[scala.collection.immutable.List$.apply object List's apply method]]\n" +
- "Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:\n" +
- " - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]\n" +
- " - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]\n" +
- "Notes: \n" +
- " - you can use any number of matching square brackets to avoid interference with the signature\n" +
- " - you can use \\. to escape dots in prefixes (don't forget to use * at the end to match the signature!)\n" +
- " - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.\n"
- else "")
- )
- chosen
- } else
- linkTo.head
+ override def chooseLink(links: List[LinkTo]): LinkTo = {
+ val mbrs = links.collect {
+ case lm@LinkToMember(mbr: MemberEntity, _) => (mbr, lm)
}
- }
-
- private abstract class SearchStrategy
- private object BothTypeAndTerm extends SearchStrategy
- private object OnlyType extends SearchStrategy
- private object OnlyTerm extends SearchStrategy
-
- private def lookupInRootPackage(pos: Position, members: List[String]) =
- lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
-
- private def createLinks(syms: List[(Symbol, Symbol)]): List[LinkTo] =
- syms.flatMap { case (sym, owner) =>
- findTemplateMaybe(sym) match {
- case Some(tpl) => LinkToTpl(tpl) :: Nil
- case None =>
- findTemplateMaybe(owner) flatMap { inTpl =>
- inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl))
- }
- }
- }
-
- private def lookupInTemplate(pos: Position, members: List[String], container: Symbol): List[(Symbol, Symbol)] = {
- // Maintaining compatibility with previous links is a bit tricky here:
- // we have a preference for term names for all terms except for the last, where we prefer a class:
- // How to do this:
- // - at each step we do a DFS search with the prefered strategy
- // - if the search doesn't return any members, we backtrack on the last decision
- // * we look for terms with the last member's name
- // * we look for types with the same name, all the way up
- val result = members match {
- case Nil => Nil
- case mbrName::Nil =>
- var syms = lookupInTemplate(pos, mbrName, container, OnlyType) map ((_, container))
- if (syms.isEmpty)
- syms = lookupInTemplate(pos, mbrName, container, OnlyTerm) map ((_, container))
- syms
-
- case tplName::rest =>
- def completeSearch(syms: List[Symbol]) =
- syms flatMap (lookupInTemplate(pos, rest, _))
-
- completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match {
- case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType))
- case syms => syms
- }
- }
- //println("lookupInTemplate(" + members + ", " + container + ") => " + result)
- result
- }
-
- private def lookupInTemplate(pos: Position, member: String, container: Symbol, strategy: SearchStrategy): List[Symbol] = {
- val name = member.stripSuffix("$").stripSuffix("!").stripSuffix("*")
- def signatureMatch(sym: Symbol): Boolean = externalSignature(sym).startsWith(name)
-
- // We need to cleanup the bogus classes created by the .class file parser. For example, [[scala.Predef]] resolves
- // to (bogus) class scala.Predef loaded by the class loader -- which we need to eliminate by looking at the info
- // and removing NoType classes
- def cleanupBogusClasses(syms: List[Symbol]) = { syms.filter(_.info != NoType) }
-
- def syms(name: Name) = container.info.nonPrivateMember(name.encodedName).alternatives
- def termSyms = cleanupBogusClasses(syms(newTermName(name)))
- def typeSyms = cleanupBogusClasses(syms(newTypeName(name)))
-
- val result = if (member.endsWith("$"))
- termSyms
- else if (member.endsWith("!"))
- typeSyms
- else if (member.endsWith("*"))
- cleanupBogusClasses(container.info.nonPrivateDecls) filter signatureMatch
+ if (mbrs.isEmpty)
+ links.head
else
- if (strategy == BothTypeAndTerm)
- termSyms ::: typeSyms
- else if (strategy == OnlyType)
- typeSyms
- else if (strategy == OnlyTerm)
- termSyms
- else
- Nil
-
- //println("lookupInTemplate(" + member + ", " + container + ") => " + result)
- result
- }
-
- private def breakMembers(query: String): List[String] = {
- // Okay, how does this work? Well: you split on . but you don't want to split on \. => thus the ugly regex
- // query.split((?<=[^\\\\])\\.).map(_.replaceAll("\\."))
- // The same code, just faster:
- var members = List[String]()
- var index = 0
- var last_index = 0
- val length = query.length
- while (index < length) {
- if ((query.charAt(index) == '.' || query.charAt(index) == '#') &&
- ((index == 0) || (query.charAt(index-1) != '\\'))) {
-
- val member = query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$1")
- // we want to allow javadoc-style links [[#member]] -- which requires us to remove empty members from the first
- // elemnt in the list
- if ((member != "") || (!members.isEmpty))
- members ::= member
- last_index = index + 1
- }
- index += 1
- }
- if (last_index < length)
- members ::= query.substring(last_index, length).replaceAll("\\\\\\.", ".")
- members.reverse
+ mbrs.min(Ordering[MemberEntity].on[(MemberEntity, LinkTo)](_._1))._2
}
}
-
-object MemberLookup {
- private[this] var _showExplanation = true
- def showExplanation: Boolean = if (_showExplanation) { _showExplanation = false; true } else false
-}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 3ae1210ebf..ea074873e8 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -4,8 +4,8 @@ package scala.tools.nsc
package doc
package model
-import comment._
-
+import base._
+import base.comment._
import diagram._
import scala.collection._
@@ -950,7 +950,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// units.filter should return only one element
(currentRun.units filter (_.source.file == aSym.sourceFile)).toList match {
case List(unit) =>
- (unit.body find (_.symbol == aSym)) match {
+ // SI-4922 `sym == aSym` is insufficent if `aSym` is a clone of symbol
+ // of the parameter in the tree, as can happen with type parametric methods.
+ def isCorrespondingParam(sym: Symbol) = (
+ sym != null &&
+ sym != NoSymbol &&
+ sym.owner == aSym.owner &&
+ sym.name == aSym.name &&
+ sym.isParamWithDefault
+ )
+ (unit.body find (t => isCorrespondingParam(t.symbol))) match {
case Some(ValDef(_,_,_,rhs)) => makeTree(rhs)
case _ => None
}
@@ -1085,31 +1094,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
{ val rawComment = global.expandedDocComment(bSym, inTpl.sym)
rawComment.contains("@template") || rawComment.contains("@documentable") }
- def findExternalLink(sym: Symbol, name: String): Option[LinkTo] = {
- val sym1 =
- if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
- else if (sym.isPackage)
- /* Get package object which has associatedFile ne null */
- sym.info.member(newTermName("package"))
- else sym
- Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
- val path = src.path
- settings.extUrlMapping get path map { url =>
- LinkToExternal(name, url + "#" + name)
- }
- } orElse {
- // Deprecated option.
- settings.extUrlPackageMapping find {
- case (pkg, _) => name startsWith pkg
- } map {
- case (_, url) => LinkToExternal(name, url + "#" + name)
- }
+ object LinkToTpl {
+ // this makes it easier to create links
+ def apply(tpl: TemplateEntity): LinkTo = tpl match {
+ case dtpl: DocTemplateEntity => new LinkToTpl(dtpl)
+ case _ => new Tooltip(tpl.qualifiedName)
}
}
-
- def externalSignature(sym: Symbol) = {
- sym.info // force it, otherwise we see lazy types
- (sym.nameString + sym.signatureString).replaceAll("\\s", "")
- }
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index 5334de3797..f88251b22e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -10,8 +10,6 @@ package scala.tools.nsc
package doc
package model
-import comment._
-
import scala.collection._
import scala.util.matching.Regex
@@ -608,4 +606,4 @@ trait ModelFactoryImplicitSupport {
false
} else true // the member structure is different foo(3, 5) vs foo(3)(5)
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
index 942ccaf1ba..87dc615c8e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala
@@ -4,8 +4,7 @@ package scala.tools.nsc
package doc
package model
-import comment._
-
+import base._
import diagram._
import scala.collection._
@@ -24,7 +23,8 @@ trait ModelFactoryTypeSupport {
with ModelFactoryTypeSupport
with DiagramFactory
with CommentFactory
- with TreeFactory =>
+ with TreeFactory
+ with MemberLookup =>
import global._
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
diff --git a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
index e4a053e115..cf5c1fb3fb 100644
--- a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala
@@ -20,7 +20,7 @@ abstract class TypeEntity {
/** Maps which parts of this type's name reference entities. The map is indexed by the position of the first
* character that reference some entity, and contains the entity and the position of the last referenced
* character. The referenced character ranges do not to overlap or nest. The map is sorted by position. */
- def refEntity: SortedMap[Int, (LinkTo, Int)]
+ def refEntity: SortedMap[Int, (base.LinkTo, Int)]
/** The human-readable representation of this type. */
override def toString = name
diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
index 49cfaffc2e..cd60865ce7 100644
--- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramDirectiveParser.scala
@@ -3,7 +3,6 @@ package model
package diagram
import model._
-import comment.CommentFactory
import java.util.regex.{Pattern, Matcher}
import scala.util.matching.Regex
@@ -259,4 +258,4 @@ trait DiagramDirectiveParser {
result
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
index db2d0c0175..175b4a6472 100644
--- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala
@@ -3,7 +3,6 @@ package model
package diagram
import model._
-import comment.CommentFactory
import scala.collection.mutable
// statistics
@@ -25,7 +24,7 @@ trait DiagramFactory extends DiagramDirectiveParser {
// the following can used for hardcoding different relations into the diagram, for bootstrapping purposes
def aggregationNode(text: String) =
- NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (LinkTo, Int)]() }, None)()
+ NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (base.LinkTo, Int)]() }, None)()
/** Create the inheritance diagram for this template */
def makeInheritanceDiagram(tpl: DocTemplateImpl): Option[Diagram] = {
diff --git a/src/compiler/scala/tools/nsc/interactive/Doc.scala b/src/compiler/scala/tools/nsc/interactive/Doc.scala
new file mode 100755
index 0000000000..4d02de6198
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interactive/Doc.scala
@@ -0,0 +1,50 @@
+/* NSC -- new Scala compiler
+ * Copyright 2007-2012 LAMP/EPFL
+ * @author Eugene Vigdorchik
+ */
+
+package scala.tools.nsc
+package interactive
+
+import doc.base._
+import comment._
+import scala.xml.NodeSeq
+
+sealed trait DocResult
+final case class UrlResult(url: String) extends DocResult
+final case class HtmlResult(comment: Comment) extends DocResult
+
+abstract class Doc(val settings: doc.Settings) extends MemberLookupBase with CommentFactoryBase {
+
+ override val global: interactive.Global
+ import global._
+
+ def chooseLink(links: List[LinkTo]): LinkTo
+
+ override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
+ ask { () =>
+ if (sym.isClass || sym.isModule)
+ Some(LinkToTpl(sym))
+ else
+ if ((site.isClass || site.isModule) && site.info.members.toList.contains(sym))
+ Some(LinkToMember(sym, site))
+ else
+ None
+ }
+
+ def retrieve(sym: Symbol, site: Symbol): Option[DocResult] = {
+ val sig = ask { () => externalSignature(sym) }
+ findExternalLink(sym, sig) map { link => UrlResult(link.url) } orElse {
+ val resp = new Response[Tree]
+ // Ensure docComment tree is type-checked.
+ val pos = ask { () => docCommentPos(sym) }
+ askTypeAt(pos, resp)
+ resp.get.left.toOption flatMap { _ =>
+ ask { () =>
+ val comment = parseAtSymbol(expandedDocComment(sym), rawDocComment(sym), pos, Some(site))
+ Some(HtmlResult(comment))
+ }
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 2ab389445f..0fc4fcaaf7 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -74,6 +74,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
if (verboseIDE) println("[%s][%s]".format(projectName, msg))
override def forInteractive = true
+ override def forScaladoc = settings.isScaladoc
/** A map of all loaded files to the rich compilation units that correspond to them.
*/
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
index 5c1837b3bf..ea2333a65b 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
@@ -8,6 +8,7 @@ import scala.reflect.internal.util.Position
/** Trait encapsulating the creation of a presentation compiler's instance.*/
private[tests] trait PresentationCompilerInstance extends TestSettings {
protected val settings = new Settings
+ protected def docSettings: doc.Settings = new doc.Settings(_ => ())
protected val compilerReporter: CompilerReporter = new InteractiveReporter {
override def compiler = PresentationCompilerInstance.this.compiler
}
@@ -28,4 +29,4 @@ private[tests] trait PresentationCompilerInstance extends TestSettings {
reporter.println("\tbootClassPath: %s".format(settings.bootclasspath.value))
reporter.println("\tverbose: %b".format(settings.verbose.value))
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
index 12fb8f1507..67519cf90c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -120,7 +120,7 @@ trait MemberHandlers {
if (replProps.vids) """" + " @ " + "%%8x".format(System.identityHashCode(%s)) + " """.trim.format(req fullPath name)
else ""
- """ + "%s%s: %s = " + %s""".format(prettyName, vidString, string2code(req typeOf name), resultString)
+ """ + "%s%s: %s = " + %s""".format(string2code(prettyName), vidString, string2code(req typeOf name), resultString)
}
}
}
@@ -147,8 +147,7 @@ trait MemberHandlers {
override def resultExtractionCode(req: Request) = {
val lhsType = string2code(req lookupTypeOf name)
val res = string2code(req fullPath name)
-
- """ + "%s: %s = " + %s + "\n" """.format(lhs, lhsType, res) + "\n"
+ """ + "%s: %s = " + %s + "\n" """.format(string2code(lhs.toString), lhsType, res) + "\n"
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index ebbb1d7798..57bdaea17a 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -269,7 +269,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** Mix in members of implementation class mixinClass into class clazz */
def mixinImplClassMembers(mixinClass: Symbol, mixinInterface: Symbol) {
- assert(mixinClass.isImplClass, "Not an impl class:" +
+ if (!mixinClass.isImplClass) debugwarn ("Impl class flag is not set " +
((mixinClass.debugLocationString, mixinInterface.debugLocationString)))
for (member <- mixinClass.info.decls ; if isForwarded(member)) {
@@ -360,7 +360,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// first complete the superclass with mixed in members
addMixedinMembers(clazz.superClass, unit)
- //Console.println("adding members of " + clazz.info.baseClasses.tail.takeWhile(superclazz !=) + " to " + clazz);//DEBUG
for (mc <- clazz.mixinClasses ; if mc hasFlag lateINTERFACE) {
// @SEAN: adding trait tracking so we don't have to recompile transitive closures
unit.depends += mc
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 2f79472cfb..bbab545d9e 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -965,6 +965,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (NoSymbol, _) => None
case (overridden, env) =>
val om = specializedOverload(clazz, overridden, env)
+ foreachWithIndex(om.paramss) { (params, i) =>
+ foreachWithIndex(params) { (param, j) =>
+ param.name = overriding.paramss(i)(j).name // SI-6555 Retain the parameter names from the subclass.
+ }
+ }
debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info))
typeEnv(om) = env
addConcreteSpecMethod(overriding)
diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
index 95cb052fda..a767850cba 100644
--- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala
+++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala
@@ -327,8 +327,16 @@ abstract class TailCalls extends Transform {
transformTrees(cases).asInstanceOf[List[CaseDef]]
)
+ case Try(block, catches, finalizer @ EmptyTree) =>
+ // SI-1672 Catches are in tail position when there is no finalizer
+ treeCopy.Try(tree,
+ noTailTransform(block),
+ transformTrees(catches).asInstanceOf[List[CaseDef]],
+ EmptyTree
+ )
+
case Try(block, catches, finalizer) =>
- // no calls inside a try are in tail position, but keep recursing for nested functions
+ // no calls inside a try are in tail position if there is a finalizer, but keep recursing for nested functions
treeCopy.Try(tree,
noTailTransform(block),
noTailTransforms(catches).asInstanceOf[List[CaseDef]],
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 9829fd0e57..838ea7d5a0 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -251,7 +251,10 @@ abstract class UnCurry extends InfoTransform
val applyMethodDef = {
val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
- methSym setInfoAndEnter MethodType(methSym newSyntheticValueParams formals, restpe)
+ val paramSyms = map2(formals, fun.vparams) {
+ (tp, param) => methSym.newSyntheticValueParam(tp, param.name)
+ }
+ methSym setInfoAndEnter MethodType(paramSyms, restpe)
fun.vparams foreach (_.symbol.owner = methSym)
fun.body changeOwner (fun.symbol -> methSym)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index fc10f68454..ad01de9447 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -149,9 +149,20 @@ trait Implicits {
class SearchResult(val tree: Tree, val subst: TreeTypeSubstituter) {
override def toString = "SearchResult(%s, %s)".format(tree,
if (subst.isEmpty) "" else subst)
+
+ def isFailure = false
+ def isAmbiguousFailure = false
+ final def isSuccess = !isFailure
}
- lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter)
+ lazy val SearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) {
+ override def isFailure = true
+ }
+
+ lazy val AmbiguousSearchFailure = new SearchResult(EmptyTree, EmptyTreeTypeSubstituter) {
+ override def isFailure = true
+ override def isAmbiguousFailure = true
+ }
/** A class that records an available implicit
* @param name The name of the implicit
@@ -831,7 +842,7 @@ trait Implicits {
catch divergenceHandler
tryImplicitInfo(i) match {
- case SearchFailure =>
+ case sr if sr.isFailure =>
// We don't want errors that occur during checking implicit info
// to influence the check of further infos.
context.condBufferFlush(_.kind != ErrorKinds.Divergent)
@@ -871,14 +882,14 @@ trait Implicits {
rest find (alt => !improves(chosen, alt)) match {
case Some(competing) =>
AmbiguousImplicitError(chosen, competing, "both", "and", "")(isView, pt, tree)(context)
- return SearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala
+ return AmbiguousSearchFailure // Stop the search once ambiguity is encountered, see t4457_2.scala
case _ =>
if (isView) chosen.useCountView += 1
else chosen.useCountArg += 1
}
}
- if (best == SearchFailure) {
+ if (best.isFailure) {
/** If there is no winner, and we witnessed and caught divergence,
* now we can throw it for the error message.
*/
@@ -1377,24 +1388,25 @@ trait Implicits {
var result = searchImplicit(context.implicitss, true)
- if (result == SearchFailure) {
+ if (result.isFailure) {
if (Statistics.canEnable) Statistics.stopTimer(inscopeFailNanos, failstart)
} else {
if (Statistics.canEnable) Statistics.stopTimer(inscopeSucceedNanos, succstart)
if (Statistics.canEnable) Statistics.incCounter(inscopeImplicitHits)
}
- if (result == SearchFailure) {
+ if (result.isFailure) {
val previousErrs = context.flushAndReturnBuffer()
val failstart = if (Statistics.canEnable) Statistics.startTimer(oftypeFailNanos) else null
val succstart = if (Statistics.canEnable) Statistics.startTimer(oftypeSucceedNanos) else null
+ val wasAmbigious = result.isAmbiguousFailure // SI-6667, never search companions after an ambiguous error in in-scope implicits
result = materializeImplicit(pt)
// `materializeImplicit` does some preprocessing for `pt`
// is it only meant for manifests/tags or we need to do the same for `implicitsOfExpectedType`?
- if (result == SearchFailure) result = searchImplicit(implicitsOfExpectedType, false)
+ if (result.isFailure && !wasAmbigious) result = searchImplicit(implicitsOfExpectedType, false)
- if (result == SearchFailure) {
+ if (result.isFailure) {
context.updateBuffer(previousErrs)
if (Statistics.canEnable) Statistics.stopTimer(oftypeFailNanos, failstart)
} else {
@@ -1403,7 +1415,7 @@ trait Implicits {
}
}
- if (result == SearchFailure && settings.debug.value)
+ if (result.isFailure && settings.debug.value)
log("no implicits found for "+pt+" "+pt.typeSymbol.info.baseClasses+" "+implicitsOfExpectedType)
result
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 22daf13e33..7ae8923e43 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -1003,22 +1003,22 @@ trait Infer extends Checkable {
*/
/** error if arguments not within bounds. */
def checkBounds(tree: Tree, pre: Type, owner: Symbol,
- tparams: List[Symbol], targs: List[Type], prefix: String): Boolean = {
- //@M validate variances & bounds of targs wrt variances & bounds of tparams
- //@M TODO: better place to check this?
- //@M TODO: errors for getters & setters are reported separately
- val kindErrors = checkKindBounds(tparams, targs, pre, owner)
-
- if(!kindErrors.isEmpty) {
- if (targs contains WildcardType) true
- else { KindBoundErrors(tree, prefix, targs, tparams, kindErrors); false }
- } else if (!isWithinBounds(pre, owner, tparams, targs)) {
- if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
- NotWithinBounds(tree, prefix, targs, tparams, kindErrors)
- false
- } else true
- } else true
- }
+ tparams: List[Symbol], targs: List[Type], prefix: String): Boolean =
+ if ((targs exists (_.isErroneous)) || (tparams exists (_.isErroneous))) true
+ else {
+ //@M validate variances & bounds of targs wrt variances & bounds of tparams
+ //@M TODO: better place to check this?
+ //@M TODO: errors for getters & setters are reported separately
+ val kindErrors = checkKindBounds(tparams, targs, pre, owner)
+ kindErrors match {
+ case Nil =>
+ def notWithinBounds() = NotWithinBounds(tree, prefix, targs, tparams, Nil)
+ isWithinBounds(pre, owner, tparams, targs) || {notWithinBounds(); false}
+ case errors =>
+ def kindBoundErrors() = KindBoundErrors(tree, prefix, targs, tparams, errors)
+ (targs contains WildcardType) || {kindBoundErrors(); false}
+ }
+ }
def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = {
checkKindBounds0(tparams, targs, pre, owner, true) map {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index fa9a4ba9ea..3f546c9a51 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1255,7 +1255,11 @@ trait Namers extends MethodSynthesis {
case defn: MemberDef =>
val ainfos = defn.mods.annotations filterNot (_ eq null) map { ann =>
// need to be lazy, #1782. beforeTyper to allow inferView in annotation args, SI-5892.
- AnnotationInfo lazily beforeTyper(typer typedAnnotation ann)
+ AnnotationInfo lazily {
+ val context1 = typer.context.make(ann)
+ context1.setReportErrors()
+ beforeTyper(newTyper(context1) typedAnnotation ann)
+ }
}
if (ainfos.nonEmpty) {
annotated setAnnotations ainfos
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index fbeb401c7d..3e1d3fdcc4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -1264,13 +1264,15 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
val cdef = ClassDef(mods | MODULE, name.toTypeName, Nil, impl) setSymbol classSym setType NoType
def findOrCreateModuleVar() = localTyper.typedPos(tree.pos) {
- lazy val createModuleVar = gen.mkModuleVarDef(sym)
- sym.enclClass.info.decl(nme.moduleVarName(sym.name.toTermName)) match {
- // In case we are dealing with local symbol then we already have
- // to correct error with forward reference
- case NoSymbol => createModuleVar
- case vsym => ValDef(vsym)
- }
+ // See SI-5012, SI-6712.
+ val vsym = (
+ if (sym.owner.isTerm) NoSymbol
+ else sym.enclClass.info.decl(nme.moduleVarName(sym.name.toTermName))
+ )
+ // In case we are dealing with local symbol then we already have
+ // to correct error with forward reference
+ if (vsym == NoSymbol) gen.mkModuleVarDef(sym)
+ else ValDef(vsym)
}
def createStaticModuleAccessor() = afterRefchecks {
val method = (
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
index 0a1d3bfa7a..20db479463 100644
--- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -19,16 +19,16 @@ trait StdAttachments {
* by `parentTypes`. This attachment coordinates `parentTypes` and `typedTemplate` and
* allows them to complete the synthesis.
*/
- case class SuperCallArgsAttachment(argss: List[List[Tree]])
+ case class SuperArgsAttachment(argss: List[List[Tree]])
- /** Convenience method for `SuperCallArgsAttachment`.
+ /** Convenience method for `SuperArgsAttachment`.
* Compared with `MacroRuntimeAttachment` this attachment has different a usage pattern,
* so it really benefits from a dedicated extractor.
*/
- def superCallArgs(tree: Tree): Option[List[List[Tree]]] =
- tree.attachments.get[SuperCallArgsAttachment] collect { case SuperCallArgsAttachment(argss) => argss }
+ def superArgs(tree: Tree): Option[List[List[Tree]]] =
+ tree.attachments.get[SuperArgsAttachment] collect { case SuperArgsAttachment(argss) => argss }
- /** Determines whether the given tree has an associated SuperCallArgsAttachment.
+ /** Determines whether the given tree has an associated SuperArgsAttachment.
*/
- def hasSuperArgs(tree: Tree): Boolean = superCallArgs(tree).nonEmpty
+ def hasSuperArgs(tree: Tree): Boolean = superArgs(tree).nonEmpty
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 9e07b51b77..454b03c9b3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -48,6 +48,7 @@ trait Typers extends Modes with Adaptations with Tags {
resetContexts()
resetImplicits()
transformed.clear()
+ clearDocComments()
}
object UnTyper extends Traverser {
@@ -134,7 +135,7 @@ trait Typers extends Modes with Adaptations with Tags {
val res = if (paramFailed || (paramTp.isError && {paramFailed = true; true})) SearchFailure else inferImplicit(fun, paramTp, context.reportErrors, false, context)
argResultsBuff += res
- if (res != SearchFailure) {
+ if (res.isSuccess) {
argBuff += mkArg(res.tree, param.name)
} else {
mkArg = mkNamedArg // don't pass the default argument (if any) here, but start emitting named arguments for the following args
@@ -763,7 +764,7 @@ trait Typers extends Modes with Adaptations with Tags {
featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse
val featureName = (nestedOwners map (_.name + ".")).mkString + featureTrait.name
def action(): Boolean = {
- def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure
+ def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context).isSuccess
def hasOption = settings.language.value exists (s => s == featureName || s == "_")
val OK = hasImport || hasOption
if (!OK) {
@@ -1511,7 +1512,7 @@ trait Typers extends Modes with Adaptations with Tags {
*
* Returns a `TypeTree` representing a resolved parent type.
* If the typechecked parent reference implies non-nullary and non-empty argument list,
- * this argument list is attached to the returned value in SuperCallArgsAttachment.
+ * this argument list is attached to the returned value in SuperArgsAttachment.
* The attachment is necessary for the subsequent typecheck to fixup a super constructor call
* in the body of the primary constructor (see `typedTemplate` for details).
*
@@ -1577,7 +1578,7 @@ trait Typers extends Modes with Adaptations with Tags {
// this is the place where we tell the typer what argss should be used for the super call
// if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`)
// the super call dummy is already good enough, so we don't need to do anything
- if (argssAreTrivial) supertpt else supertpt updateAttachment SuperCallArgsAttachment(argss)
+ if (argssAreTrivial) supertpt else supertpt updateAttachment SuperArgsAttachment(argss)
}
}
@@ -1929,8 +1930,7 @@ trait Typers extends Modes with Adaptations with Tags {
*/
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
val clazz = context.owner
- // complete lazy annotations
- val annots = clazz.annotations
+ clazz.annotations.map(_.completeInfo)
if (templ.symbol == NoSymbol)
templ setSymbol clazz.newLocalDummy(templ.pos)
val self1 = templ.self match {
@@ -1977,7 +1977,7 @@ trait Typers extends Modes with Adaptations with Tags {
val primaryCtor = treeInfo.firstConstructor(body)
val primaryCtor1 = primaryCtor match {
case DefDef(_, _, _, _, _, Block(earlyVals :+ global.pendingSuperCall, unit)) =>
- val argss = superCallArgs(parents1.head) getOrElse Nil
+ val argss = superArgs(parents1.head) getOrElse Nil
val pos = wrappingPos(parents1.head.pos, argss.flatten)
val superCall = atPos(pos)(PrimarySuperCall(argss))
deriveDefDef(primaryCtor)(block => Block(earlyVals :+ superCall, unit) setPos pos) setPos pos
@@ -2025,8 +2025,7 @@ trait Typers extends Modes with Adaptations with Tags {
val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor)
val typedMods = typedModifiers(vdef.mods)
- // complete lazy annotations
- val annots = sym.annotations
+ sym.annotations.map(_.completeInfo)
var tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
checkNonCyclic(vdef, tpt1)
@@ -2269,8 +2268,7 @@ trait Typers extends Modes with Adaptations with Tags {
val tparams1 = ddef.tparams mapConserve typedTypeDef
val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef)
- // complete lazy annotations
- val annots = meth.annotations
+ meth.annotations.map(_.completeInfo)
for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
if (isRepeatedParamType(vparam1.symbol.tpe))
@@ -2345,8 +2343,7 @@ trait Typers extends Modes with Adaptations with Tags {
reenterTypeParams(tdef.tparams)
val tparams1 = tdef.tparams mapConserve typedTypeDef
val typedMods = typedModifiers(tdef.mods)
- // complete lazy annotations
- val annots = tdef.symbol.annotations
+ tdef.symbol.annotations.map(_.completeInfo)
// @specialized should not be pickled when compiling with -no-specialize
if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) {
@@ -2956,7 +2953,11 @@ trait Typers extends Modes with Adaptations with Tags {
var moreToAdd = true
while (moreToAdd) {
val initElems = scope.elems
- for (sym <- scope)
+ // SI-5877 The decls of a package include decls of the package object. But we don't want to add
+ // the corresponding synthetics to the package class, only to the package object class.
+ def shouldAdd(sym: Symbol) =
+ inBlock || !isInPackageObject(sym, context.owner)
+ for (sym <- scope if shouldAdd(sym))
for (tree <- context.unit.synthetics get sym) {
newStats += typedStat(tree) // might add even more synthetics to the scope
context.unit.synthetics -= sym
@@ -5249,16 +5250,14 @@ trait Typers extends Modes with Adaptations with Tags {
def typedPackageDef(pdef: PackageDef) = {
val pid1 = typedQualifier(pdef.pid).asInstanceOf[RefTree]
assert(sym.moduleClass ne NoSymbol, sym)
- // complete lazy annotations
- val annots = sym.annotations
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
.typedStats(pdef.stats, NoSymbol)
treeCopy.PackageDef(tree, pid1, stats1) setType NoType
}
def typedDocDef(docdef: DocDef) = {
- val comment = docdef.comment
if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) {
+ val comment = docdef.comment
docComments(sym) = comment
comment.defineVariables(sym)
val typer1 = newTyper(context.makeNewScope(tree, context.owner))
diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala
index 9115b9e5fb..5e6126a7cf 100644
--- a/src/library/scala/collection/convert/WrapAsJava.scala
+++ b/src/library/scala/collection/convert/WrapAsJava.scala
@@ -10,10 +10,11 @@ package scala.collection
package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
-import Wrappers._
import scala.language.implicitConversions
trait WrapAsJava {
+ import Wrappers._
+
/**
* Implicitly converts a Scala Iterator to a Java Iterator.
* The returned Java Iterator is backed by the provided Scala
diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala
index 5a5d204ece..ffcca62291 100644
--- a/src/library/scala/collection/convert/WrapAsScala.scala
+++ b/src/library/scala/collection/convert/WrapAsScala.scala
@@ -10,11 +10,13 @@ package scala.collection
package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
-import Wrappers._
import scala.language.implicitConversions
trait LowPriorityWrapAsScala {
this: WrapAsScala =>
+
+ import Wrappers._
+
/**
* Implicitly converts a Java ConcurrentMap to a Scala mutable ConcurrentMap.
* The returned Scala ConcurrentMap is backed by the provided Java
@@ -34,6 +36,7 @@ trait LowPriorityWrapAsScala {
}
trait WrapAsScala extends LowPriorityWrapAsScala {
+ import Wrappers._
/**
* Implicitly converts a Java `Iterator` to a Scala `Iterator`.
*
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index 3b6ab81146..802e16605d 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -33,7 +33,6 @@ import scala.collection.parallel.immutable.ParRange
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#ranges "Scala's Collection Library overview"]]
* section on `Ranges` for more information.
*
- * @define Coll Range
* @define coll range
* @define mayNotTerminateInf
* @define willNotTerminateInf
diff --git a/src/library/scala/collection/mutable/MutableList.scala b/src/library/scala/collection/mutable/MutableList.scala
index 183de5b727..fd92d2e555 100644
--- a/src/library/scala/collection/mutable/MutableList.scala
+++ b/src/library/scala/collection/mutable/MutableList.scala
@@ -56,12 +56,16 @@ extends AbstractSeq[A]
/** Returns the rest of this list
*/
override def tail: MutableList[A] = {
- require(nonEmpty, "tail of empty list")
val tl = new MutableList[A]
+ tailImpl(tl)
+ tl
+ }
+
+ protected final def tailImpl(tl: MutableList[A]) {
+ require(nonEmpty, "tail of empty list")
tl.first0 = first0.tail
- tl.last0 = last0
tl.len = len - 1
- tl
+ tl.last0 = if (tl.len == 0) tl.first0 else last0
}
/** Prepends a single element to this list. This operation takes constant
diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala
index 5ea012eb9f..b947fa3cca 100644
--- a/src/library/scala/collection/mutable/Queue.scala
+++ b/src/library/scala/collection/mutable/Queue.scala
@@ -66,7 +66,7 @@ extends MutableList[A]
else {
val res = first0.elem
first0 = first0.next
- len -= 1
+ decrementLength()
res
}
@@ -82,11 +82,11 @@ extends MutableList[A]
else if (p(first0.elem)) {
val res: Option[A] = Some(first0.elem)
first0 = first0.next
- len -= 1
+ decrementLength()
res
} else {
val optElem = removeFromList(p)
- if (optElem != None) len -= 1
+ if (optElem != None) decrementLength()
optElem
}
@@ -119,7 +119,7 @@ extends MutableList[A]
while ((first0.nonEmpty) && p(first0.elem)) {
res += first0.elem
first0 = first0.next
- len -= 1
+ decrementLength()
}
if (first0.isEmpty) res
else removeAllFromList(p, res)
@@ -130,10 +130,10 @@ extends MutableList[A]
var leftlst = first0
while (leftlst.next.nonEmpty) {
if (p(leftlst.next.elem)) {
- res += leftlst.next.elem
- if (leftlst.next eq last0) last0 = leftlst
- leftlst.next = leftlst.next.next
- len -= 1
+ res += leftlst.next.elem
+ if (leftlst.next eq last0) last0 = leftlst
+ leftlst.next = leftlst.next.next
+ decrementLength()
} else leftlst = leftlst.next
}
res
@@ -154,7 +154,7 @@ extends MutableList[A]
else {
val res: Option[LinkedList[A]] = Some(cell.next)
cell.next = cell.next.next
- len -= 1
+ decrementLength()
res
}
}
@@ -170,11 +170,8 @@ extends MutableList[A]
// TODO - Don't override this just for new to create appropriate type....
override def tail: Queue[A] = {
- require(nonEmpty, "tail of empty list")
val tl = new Queue[A]
- tl.first0 = first0.tail
- tl.last0 = last0
- tl.len = len - 1
+ tailImpl(tl)
tl
}
@@ -183,6 +180,11 @@ extends MutableList[A]
bf ++= seq
bf.result
}
+
+ private[this] def decrementLength() {
+ len -= 1
+ if (len == 0) last0 = first0
+ }
}
diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala
index 24c4cd7a32..2b11594f66 100644
--- a/src/library/scala/util/Random.scala
+++ b/src/library/scala/util/Random.scala
@@ -17,7 +17,7 @@ import scala.language.{implicitConversions, higherKinds}
* @author Stephane Micheloud
*
*/
-class Random(val self: java.util.Random) {
+class Random(val self: java.util.Random) extends AnyRef with Serializable {
/** Creates a new random number generator using a single long seed. */
def this(seed: Long) = this(new java.util.Random(seed))
diff --git a/src/partest/scala/tools/partest/ScaladocModelTest.scala b/src/partest/scala/tools/partest/ScaladocModelTest.scala
index e7134d0271..b9abff69d8 100644
--- a/src/partest/scala/tools/partest/ScaladocModelTest.scala
+++ b/src/partest/scala/tools/partest/ScaladocModelTest.scala
@@ -12,7 +12,7 @@ import scala.tools.nsc.util.CommandLineParser
import scala.tools.nsc.doc.{Settings, DocFactory, Universe}
import scala.tools.nsc.doc.model._
import scala.tools.nsc.doc.model.diagram._
-import scala.tools.nsc.doc.model.comment._
+import scala.tools.nsc.doc.base.comment._
import scala.tools.nsc.reporters.ConsoleReporter
/** A class for testing scaladoc model generation
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 7c12b5979d..6a5a742cc7 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -201,6 +201,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
override def toString = if (forced) forcedInfo.toString else "@<?>"
override def pos: Position = if (forced) forcedInfo.pos else NoPosition
+
+ override def completeInfo(): Unit = forcedInfo
}
/** Typed information about an annotation. It can be attached to either
@@ -242,6 +244,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
this
}
+ // Forces LazyAnnotationInfo, no op otherwise
+ def completeInfo(): Unit = ()
+
/** Annotations annotating annotations are confusing so I drew
* an example. Given the following code:
*
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index d82692000d..119a57d268 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -6605,11 +6605,11 @@ trait Types extends api.Types { self: SymbolTable =>
case ExistentialType(qs, _) => qs
case t => List()
}
- def stripType(tp: Type) = tp match {
+ def stripType(tp: Type): Type = tp match {
case ExistentialType(_, res) =>
res
case tv@TypeVar(_, constr) =>
- if (tv.instValid) constr.inst
+ if (tv.instValid) stripType(constr.inst)
else if (tv.untouchable) tv
else abort("trying to do lub/glb of typevar "+tp)
case t => t
diff --git a/test/files/jvm/serialization.scala b/test/files/jvm/serialization.scala
index 34b64938b4..f2c47aad77 100644
--- a/test/files/jvm/serialization.scala
+++ b/test/files/jvm/serialization.scala
@@ -604,6 +604,7 @@ object Test {
Test7
Test8
Test9_parallel
+ Test10_util
}
}
@@ -669,3 +670,17 @@ object Test9_parallel {
throw e
}
}
+
+//############################################################################
+// Test classes in package scala.util
+
+object Test10_util {
+ import scala.util.Random
+ def rep[A](n: Int)(f: => A) { if (n > 0) { f; rep(n-1)(f) } }
+
+ try {
+ val random = new Random(345)
+ val random2: Random = read(write(random))
+ rep(5) { assert(random.nextInt == random2.nextInt) }
+ }
+}
diff --git a/test/files/neg/case-collision.check b/test/files/neg/case-collision.check
new file mode 100644
index 0000000000..4edc6f1205
--- /dev/null
+++ b/test/files/neg/case-collision.check
@@ -0,0 +1,10 @@
+case-collision.scala:5: error: Class foo.BIPPY differs only in case from foo.Bippy. Such classes will overwrite one another on case-insensitive filesystems.
+class BIPPY
+ ^
+case-collision.scala:11: error: Class foo.HyRaX$ differs only in case from foo.Hyrax$. Such classes will overwrite one another on case-insensitive filesystems.
+object HyRaX
+ ^
+case-collision.scala:8: error: Class foo.DINGO$ differs only in case from foo.Dingo$. Such classes will overwrite one another on case-insensitive filesystems.
+object DINGO
+ ^
+three errors found
diff --git a/test/files/neg/case-collision.flags b/test/files/neg/case-collision.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/case-collision.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/case-collision.scala b/test/files/neg/case-collision.scala
new file mode 100644
index 0000000000..241169a77a
--- /dev/null
+++ b/test/files/neg/case-collision.scala
@@ -0,0 +1,11 @@
+package foo
+
+class Bippy
+
+class BIPPY
+
+object Dingo
+object DINGO
+
+case class Hyrax()
+object HyRaX
diff --git a/test/files/neg/t1672b.check b/test/files/neg/t1672b.check
new file mode 100644
index 0000000000..60ccf77174
--- /dev/null
+++ b/test/files/neg/t1672b.check
@@ -0,0 +1,16 @@
+t1672b.scala:3: error: could not optimize @tailrec annotated method bar: it contains a recursive call not in tail position
+ def bar : Nothing = {
+ ^
+t1672b.scala:14: error: could not optimize @tailrec annotated method baz: it contains a recursive call not in tail position
+ def baz : Nothing = {
+ ^
+t1672b.scala:29: error: could not optimize @tailrec annotated method boz: it contains a recursive call not in tail position
+ case _: Throwable => boz; ???
+ ^
+t1672b.scala:34: error: could not optimize @tailrec annotated method bez: it contains a recursive call not in tail position
+ def bez : Nothing = {
+ ^
+t1672b.scala:46: error: could not optimize @tailrec annotated method bar: it contains a recursive call not in tail position
+ else 1 + (try {
+ ^
+5 errors found
diff --git a/test/files/neg/t1672b.scala b/test/files/neg/t1672b.scala
new file mode 100644
index 0000000000..0ccdd03633
--- /dev/null
+++ b/test/files/neg/t1672b.scala
@@ -0,0 +1,52 @@
+object Test {
+ @annotation.tailrec
+ def bar : Nothing = {
+ try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => bar
+ } finally {
+ bar
+ }
+ }
+
+ @annotation.tailrec
+ def baz : Nothing = {
+ try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => baz
+ } finally {
+ ???
+ }
+ }
+
+ @annotation.tailrec
+ def boz : Nothing = {
+ try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => boz; ???
+ }
+ }
+
+ @annotation.tailrec
+ def bez : Nothing = {
+ try {
+ bez
+ } finally {
+ ???
+ }
+ }
+
+ // the `liftedTree` local method will prevent a tail call here.
+ @annotation.tailrec
+ def bar(i : Int) : Int = {
+ if (i == 0) 0
+ else 1 + (try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => bar(i - 1)
+ })
+ }
+}
diff --git a/test/files/neg/t3222.check b/test/files/neg/t3222.check
index e724024f45..6170827cc9 100644
--- a/test/files/neg/t3222.check
+++ b/test/files/neg/t3222.check
@@ -1,7 +1,13 @@
-t3222.scala:4: error: not found: type D
- def foo(@throws(classOf[D]) x: Int) {}
- ^
t3222.scala:1: error: not found: type B
@throws(classOf[B])
^
-two errors found
+t3222.scala:4: error: not found: type D
+ def foo(@throws(classOf[D]) x: Int) {}
+ ^
+t3222.scala:3: error: not found: type C
+ @throws(classOf[C])
+ ^
+t3222.scala:6: error: not found: type E
+ @throws(classOf[E])
+ ^
+four errors found
diff --git a/test/files/neg/t4044.check b/test/files/neg/t4044.check
index 41a04f69b9..0e1ea4f51d 100644
--- a/test/files/neg/t4044.check
+++ b/test/files/neg/t4044.check
@@ -1,11 +1,6 @@
t4044.scala:9: error: AnyRef takes no type parameters, expected: one
M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *)
^
-t4044.scala:9: error: kinds of the type arguments (<error>) do not conform to the expected kinds of the type parameters (type N).
-<error>'s type parameters do not match type N's expected parameters:
-<none> has no type parameters, but type N has one
- M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *)
- ^
t4044.scala:11: error: kinds of the type arguments (Test.A) do not conform to the expected kinds of the type parameters (type N).
Test.A's type parameters do not match type N's expected parameters:
type _ has no type parameters, but type O has one
@@ -16,4 +11,4 @@ Test.C's type parameters do not match type N's expected parameters:
type _ has one type parameter, but type _ has none
M[C] // error, (C :: (* -> * -> * -> *) not kind-conformant to (N :: * -> * -> *)
^
-four errors found
+three errors found
diff --git a/test/files/neg/t6260.check b/test/files/neg/t6260.check
index 2b7f1a8bfb..46e9bd1dfc 100644
--- a/test/files/neg/t6260.check
+++ b/test/files/neg/t6260.check
@@ -1,10 +1,10 @@
-t6260.scala:3: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
+t6260.scala:3: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun
which overrides method apply: (v1: T1)R in trait Function1
clashes with definition of the member itself;
both have erased type (v1: Object)Object
((bx: Box[X]) => new Box(f(bx.x)))(this)
^
-t6260.scala:8: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
+t6260.scala:8: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun
which overrides method apply: (v1: T1)R in trait Function1
clashes with definition of the member itself;
both have erased type (v1: Object)Object
diff --git a/test/files/neg/t6535.check b/test/files/neg/t6535.check
new file mode 100644
index 0000000000..1225ea70db
--- /dev/null
+++ b/test/files/neg/t6535.check
@@ -0,0 +1,6 @@
+t6535.scala:2: error: encountered unrecoverable cycle resolving import.
+Note: this is often due in part to a class depending on a definition nested within its companion.
+If applicable, you may wish to try moving some members into another object.
+ import Bs.B._
+ ^
+one error found
diff --git a/test/files/neg/t6535.scala b/test/files/neg/t6535.scala
new file mode 100644
index 0000000000..30a750311c
--- /dev/null
+++ b/test/files/neg/t6535.scala
@@ -0,0 +1,15 @@
+object As {
+ import Bs.B._
+
+ object A
+ extends scala.AnyRef // needed for the cycle;
+ // replacing with a locally defined closs doesn't
+ // hit the locked import and hence doesn't cycle.
+}
+
+object Bs {
+ import As.A._
+
+ object B
+ extends scala.AnyRef // scala.Immutable, ...
+}
diff --git a/test/files/neg/t6558.check b/test/files/neg/t6558.check
new file mode 100644
index 0000000000..6ad3cecd50
--- /dev/null
+++ b/test/files/neg/t6558.check
@@ -0,0 +1,10 @@
+t6558.scala:4: error: not found: type classs
+ @classs
+ ^
+t6558.scala:7: error: not found: type typeparam
+ class D[@typeparam T]
+ ^
+t6558.scala:10: error: not found: type valueparam
+ @valueparam x: Any
+ ^
+three errors found
diff --git a/test/files/neg/t6558.scala b/test/files/neg/t6558.scala
new file mode 100644
index 0000000000..b4304ff686
--- /dev/null
+++ b/test/files/neg/t6558.scala
@@ -0,0 +1,12 @@
+class AnnotNotFound {
+ def foo(a: Any) = ()
+
+ @classs
+ class C
+
+ class D[@typeparam T]
+
+ class E(
+ @valueparam x: Any
+ )
+}
diff --git a/test/files/neg/t6558b.check b/test/files/neg/t6558b.check
new file mode 100644
index 0000000000..cfa384fc08
--- /dev/null
+++ b/test/files/neg/t6558b.check
@@ -0,0 +1,7 @@
+t6558b.scala:5: error: not found: type inargument
+ @inargument
+ ^
+t6558b.scala:11: error: not found: type infunction
+ @infunction
+ ^
+two errors found
diff --git a/test/files/neg/t6558b.scala b/test/files/neg/t6558b.scala
new file mode 100644
index 0000000000..2aa06f69cf
--- /dev/null
+++ b/test/files/neg/t6558b.scala
@@ -0,0 +1,15 @@
+class AnnotNotFound {
+ def foo(a: Any) = ()
+
+ foo {
+ @inargument
+ def foo = 0
+ foo
+ }
+
+ () => {
+ @infunction
+ def foo = 0
+ ()
+ }
+}
diff --git a/test/files/neg/t6667.check b/test/files/neg/t6667.check
new file mode 100644
index 0000000000..43313fa4fe
--- /dev/null
+++ b/test/files/neg/t6667.check
@@ -0,0 +1,13 @@
+t6667.scala:8: error: ambiguous implicit values:
+ both value inScope1 in object Test of type => C
+ and value inScope2 in object Test of type => C
+ match expected type C
+ implicitly[C]: Unit // C.companion was used; whereas the ambiguity should abort the implicit search.
+ ^
+t6667.scala:9: error: ambiguous implicit values:
+ both value inScope1 in object Test of type => C
+ and value inScope2 in object Test of type => C
+ match expected type C
+ implicitly[C] // ambiguity reported, rather than falling back to C.companion
+ ^
+two errors found
diff --git a/test/files/neg/t6667.scala b/test/files/neg/t6667.scala
new file mode 100644
index 0000000000..fb857ebd33
--- /dev/null
+++ b/test/files/neg/t6667.scala
@@ -0,0 +1,10 @@
+class C
+object C {
+ implicit def companion = new C
+}
+
+object Test {
+ implicit val inScope1, inScope2 = new C
+ implicitly[C]: Unit // C.companion was used; whereas the ambiguity should abort the implicit search.
+ implicitly[C] // ambiguity reported, rather than falling back to C.companion
+}
diff --git a/test/files/neg/t6667b.check b/test/files/neg/t6667b.check
new file mode 100644
index 0000000000..99cea9a47c
--- /dev/null
+++ b/test/files/neg/t6667b.check
@@ -0,0 +1,13 @@
+t6667b.scala:16: error: ambiguous implicit values:
+ both value a in object Test of type => Test.Box
+ and value b of type Test.Box
+ match expected type Test.Box
+ new Test()
+ ^
+t6667b.scala:19: error: ambiguous implicit values:
+ both value a in object Test of type => Test.Box
+ and value b of type Test.Box
+ match expected type Test.Box
+ new Test()
+ ^
+two errors found
diff --git a/test/files/neg/t6667b.scala b/test/files/neg/t6667b.scala
new file mode 100644
index 0000000000..4e64e1af17
--- /dev/null
+++ b/test/files/neg/t6667b.scala
@@ -0,0 +1,25 @@
+object Test {
+ abstract class Box {
+ val value: Int
+ }
+
+ implicit val a: Box = new Box {
+ val value= 1
+ }
+
+ def main(args: Array[String]) {
+ implicit val b: Box= new Box {
+ val value= 2
+ }
+
+ new Object {
+ new Test()
+ }
+ // compare with:
+ new Test()
+ }
+}
+
+class Test()(implicit x: Test.Box) {
+ println(x.value)
+}
diff --git a/test/files/neg/t6758.check b/test/files/neg/t6758.check
new file mode 100644
index 0000000000..2cdd6b8ae5
--- /dev/null
+++ b/test/files/neg/t6758.check
@@ -0,0 +1,28 @@
+t6758.scala:5: error: not found: type inargument
+ @inargument
+ ^
+t6758.scala:11: error: not found: type infunction
+ @infunction
+ ^
+t6758.scala:18: error: not found: type nested
+ @nested
+ ^
+t6758.scala:25: error: not found: type param
+ def func(@param x: Int): Int = 0
+ ^
+t6758.scala:28: error: not found: type typealias
+ @typealias
+ ^
+t6758.scala:32: error: not found: type classs
+ @classs
+ ^
+t6758.scala:35: error: not found: type module
+ @module
+ ^
+t6758.scala:38: error: not found: type typeparam
+ class D[@typeparam T]
+ ^
+t6758.scala:41: error: not found: type valueparam
+ @valueparam x: Any
+ ^
+9 errors found
diff --git a/test/files/neg/t6758.scala b/test/files/neg/t6758.scala
new file mode 100644
index 0000000000..acf333bf90
--- /dev/null
+++ b/test/files/neg/t6758.scala
@@ -0,0 +1,43 @@
+class AnnotNotFound {
+ def foo(a: Any) = ()
+
+ foo {
+ @inargument
+ def foo = 0
+ foo
+ }
+
+ () => {
+ @infunction
+ def foo = 0
+ ()
+ }
+
+ () => {
+ val bar: Int = {
+ @nested
+ val bar2: Int = 2
+ 2
+ }
+ ()
+ }
+
+ def func(@param x: Int): Int = 0
+
+ abstract class A {
+ @typealias
+ type B = Int
+ }
+
+ @classs
+ class C
+
+ @module
+ object D
+
+ class D[@typeparam T]
+
+ class E(
+ @valueparam x: Any
+ )
+}
diff --git a/test/files/pos/strip-tvars-for-lubbasetypes.scala b/test/files/pos/strip-tvars-for-lubbasetypes.scala
new file mode 100644
index 0000000000..2be8625bae
--- /dev/null
+++ b/test/files/pos/strip-tvars-for-lubbasetypes.scala
@@ -0,0 +1,25 @@
+object Test {
+
+ implicit final class EqualOps[T](val x: T) extends AnyVal {
+ def ===[T1, Ph >: T <: T1, Ph2 >: Ph <: T1](other: T1): Boolean = x == other
+ def !!![T1, Ph2 >: Ph <: T1, Ph >: T <: T1](other: T1): Boolean = x == other
+ }
+
+ class A
+ class B extends A
+ class C extends A
+
+ val a = new A
+ val b = new B
+ val c = new C
+
+ val x1 = a === b
+ val x2 = b === a
+ val x3 = b === c // error, infers Object{} for T1
+ val x4 = b.===[A, B, B](c)
+
+ val x5 = b !!! c // always compiled due to the order of Ph2 and Ph
+
+
+
+}
diff --git a/test/files/pos/t1672.scala b/test/files/pos/t1672.scala
new file mode 100644
index 0000000000..5ee6bb1759
--- /dev/null
+++ b/test/files/pos/t1672.scala
@@ -0,0 +1,10 @@
+object Test {
+ @annotation.tailrec
+ def bar : Nothing = {
+ try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => bar
+ }
+ }
+}
diff --git a/test/files/pos/t5877.scala b/test/files/pos/t5877.scala
new file mode 100644
index 0000000000..c7827df99f
--- /dev/null
+++ b/test/files/pos/t5877.scala
@@ -0,0 +1,14 @@
+package foo {
+ class Foo
+
+ object Test {
+ new Foo().huzzah
+ }
+}
+
+package object foo {
+ // Crasher: No synthetics for method PimpedFoo2: synthetics contains
+ implicit class PimpedFoo2(value: Foo) {
+ def huzzah = ""
+ }
+}
diff --git a/test/files/pos/t5877b.scala b/test/files/pos/t5877b.scala
new file mode 100644
index 0000000000..6b8cbd473e
--- /dev/null
+++ b/test/files/pos/t5877b.scala
@@ -0,0 +1,13 @@
+package foo
+
+class Foo
+
+object Test {
+ new Foo().huzzah
+}
+
+object `package` {
+ implicit class PimpedFoo2(value: Foo) {
+ def huzzah = ""
+ }
+}
diff --git a/test/files/pos/t6547.flags b/test/files/pos/t6547.flags
new file mode 100644
index 0000000000..c9b68d70dc
--- /dev/null
+++ b/test/files/pos/t6547.flags
@@ -0,0 +1 @@
+-optimise
diff --git a/test/files/pos/t6547.scala b/test/files/pos/t6547.scala
new file mode 100644
index 0000000000..53bd798219
--- /dev/null
+++ b/test/files/pos/t6547.scala
@@ -0,0 +1,6 @@
+trait ConfigurableDefault[@specialized V] {
+ def fillArray(arr: Array[V], v: V) = (arr: Any) match {
+ case x: Array[Int] => null
+ case x: Array[Long] => v.asInstanceOf[Long]
+ }
+}
diff --git a/test/files/pos/t6712.scala b/test/files/pos/t6712.scala
new file mode 100644
index 0000000000..3c96eb14fb
--- /dev/null
+++ b/test/files/pos/t6712.scala
@@ -0,0 +1,5 @@
+class H {
+ object O
+
+ def foo() { object O }
+}
diff --git a/test/files/presentation/doc.check b/test/files/presentation/doc.check
new file mode 100755
index 0000000000..62b3bfc2e3
--- /dev/null
+++ b/test/files/presentation/doc.check
@@ -0,0 +1,48 @@
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:
+@since:
+@todo:
+@note:
+@see:
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
+@since:
+@todo:
+@note:
+@see:
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
+@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
+@todo:
+@note:
+@see:
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
+@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
+@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
+@note:
+@see:
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
+@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
+@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
+@note:Body(List(Paragraph(Chain(List(Summary(Text(Don't inherit!)))))))
+@see:
+body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
+))))))
+@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
+@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
+@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
+@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
+@note:Body(List(Paragraph(Chain(List(Summary(Text(Don't inherit!)))))))
+@see:Body(List(Paragraph(Chain(List(Summary(Text(some other method)))))))
diff --git a/test/files/presentation/doc.scala b/test/files/presentation/doc.scala
new file mode 100755
index 0000000000..4b0d6baa1f
--- /dev/null
+++ b/test/files/presentation/doc.scala
@@ -0,0 +1,71 @@
+import scala.tools.nsc.doc
+import scala.tools.nsc.doc.base.LinkTo
+import scala.tools.nsc.doc.base.comment._
+import scala.tools.nsc.interactive._
+import scala.tools.nsc.interactive.tests._
+import scala.tools.nsc.util._
+import scala.tools.nsc.io._
+
+object Test extends InteractiveTest {
+ override val settings: doc.Settings = docSettings
+
+ val tags = Seq(
+ "@example `\"abb\".permutations = Iterator(abb, bab, bba)`",
+ "@version 1.0, 09/07/2012",
+ "@since 2.10",
+ "@todo this method is unsafe",
+ "@note Don't inherit!",
+ "@see some other method"
+ )
+
+ val comment = "This is a test comment."
+ val caret = "<caret>"
+
+ def text(nTags: Int) =
+ """|/** %s
+ |
+ | * %s */
+ |trait Commented {}
+ |class User(c: %sCommented)""".stripMargin.format(comment, tags take nTags mkString "\n", caret)
+
+ override def main(args: Array[String]) {
+ val documenter = new Doc(settings) {
+ val global: compiler.type = compiler
+
+ def chooseLink(links: List[LinkTo]): LinkTo = links.head
+ }
+ for (i <- 1 to tags.length) {
+ val markedText = text(i)
+ val idx = markedText.indexOf(caret)
+ val fileText = markedText.substring(0, idx) + markedText.substring(idx + caret.length)
+ val source = sourceFiles(0)
+ val batch = new BatchSourceFile(source.file, fileText.toCharArray)
+ val reloadResponse = new Response[Unit]
+ compiler.askReload(List(batch), reloadResponse)
+ reloadResponse.get.left.toOption match {
+ case None =>
+ reporter.println("Couldn't reload")
+ case Some(_) =>
+ val treeResponse = new compiler.Response[compiler.Tree]
+ val pos = compiler.rangePos(batch, idx, idx, idx)
+ compiler.askTypeAt(pos, treeResponse)
+ treeResponse.get.left.toOption match {
+ case Some(tree) =>
+ val sym = tree.tpe.typeSymbol
+ documenter.retrieve(sym, sym.owner) match {
+ case Some(HtmlResult(comment)) =>
+ import comment._
+ val tags: List[(String, Iterable[Body])] =
+ List(("@example", example), ("@version", version), ("@since", since.toList), ("@todo", todo), ("@note", note), ("@see", see))
+ val str = ("body:" + body + "\n") +
+ tags.map{ case (name, bodies) => name + ":" + bodies.mkString("\n") }.mkString("\n")
+ reporter.println(str)
+ case Some(_) => reporter.println("Got unexpected result")
+ case None => reporter.println("Got no result")
+ }
+ case None => reporter.println("Couldn't find a typedTree")
+ }
+ }
+ }
+ }
+}
diff --git a/test/files/presentation/doc/src/Test.scala b/test/files/presentation/doc/src/Test.scala
new file mode 100755
index 0000000000..fcc1554994
--- /dev/null
+++ b/test/files/presentation/doc/src/Test.scala
@@ -0,0 +1 @@
+object Test \ No newline at end of file
diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
index a5533a623a..159097cc10 100644
--- a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
+++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
@@ -5,6 +5,7 @@ import java.util.Calendar
import scala.tools.nsc.interactive.tests._
import scala.tools.nsc.util._
import scala.tools.nsc.io._
+import scala.tools.nsc.doc
/** This test runs the presentation compiler on the Scala compiler project itself and records memory consumption.
*
@@ -24,6 +25,8 @@ import scala.tools.nsc.io._
object Test extends InteractiveTest {
final val mega = 1024 * 1024
+ override val settings: doc.Settings = docSettings
+
override def execute(): Unit = memoryConsumptionTest()
def batchSource(name: String) =
@@ -120,4 +123,4 @@ object Test extends InteractiveTest {
r.totalMemory() - r.freeMemory()
}
-} \ No newline at end of file
+}
diff --git a/test/files/run/reify_renamed_term_basic.check b/test/files/run/reify_renamed_term_basic.check
new file mode 100644
index 0000000000..e78f94fffd
--- /dev/null
+++ b/test/files/run/reify_renamed_term_basic.check
@@ -0,0 +1 @@
+((),(),())
diff --git a/test/files/run/reify_renamed_term_basic.scala b/test/files/run/reify_renamed_term_basic.scala
new file mode 100644
index 0000000000..cd76def395
--- /dev/null
+++ b/test/files/run/reify_renamed_term_basic.scala
@@ -0,0 +1,20 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object A {
+ object B {
+ val c = ()
+ }
+}
+
+object Test extends App {
+ import A.{B => X}
+ import A.B.{c => y}
+ import X.{c => z}
+
+ val expr = reify (
+ X.c, y, z
+ )
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_term_local_to_reifee.check b/test/files/run/reify_renamed_term_local_to_reifee.check
new file mode 100644
index 0000000000..e78f94fffd
--- /dev/null
+++ b/test/files/run/reify_renamed_term_local_to_reifee.check
@@ -0,0 +1 @@
+((),(),())
diff --git a/test/files/run/reify_renamed_term_local_to_reifee.scala b/test/files/run/reify_renamed_term_local_to_reifee.scala
new file mode 100644
index 0000000000..1860316a5b
--- /dev/null
+++ b/test/files/run/reify_renamed_term_local_to_reifee.scala
@@ -0,0 +1,20 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object A {
+ object B {
+ val c = ()
+ }
+}
+
+object Test extends App {
+ val expr = reify {
+ import A.{B => X}
+ import A.B.{c => y}
+ import X.{c => z}
+
+ (X.c, y, z)
+ }
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_term_overloaded_method.check b/test/files/run/reify_renamed_term_overloaded_method.check
new file mode 100644
index 0000000000..48082f72f0
--- /dev/null
+++ b/test/files/run/reify_renamed_term_overloaded_method.check
@@ -0,0 +1 @@
+12
diff --git a/test/files/run/reify_renamed_term_overloaded_method.scala b/test/files/run/reify_renamed_term_overloaded_method.scala
new file mode 100644
index 0000000000..3ef442d203
--- /dev/null
+++ b/test/files/run/reify_renamed_term_overloaded_method.scala
@@ -0,0 +1,17 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object O {
+ def show(i: Int) = i.toString
+ def show(s: String) = s
+}
+
+object Test extends App {
+ import O.{show => s}
+
+ val expr = reify {
+ s("1") + s(2)
+ }
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_term_si5841.check b/test/files/run/reify_renamed_term_si5841.check
new file mode 100644
index 0000000000..6031277b76
--- /dev/null
+++ b/test/files/run/reify_renamed_term_si5841.check
@@ -0,0 +1 @@
+class scala.reflect.runtime.JavaUniverse
diff --git a/test/files/run/reify_renamed_term_si5841.scala b/test/files/run/reify_renamed_term_si5841.scala
new file mode 100644
index 0000000000..ef18d650bf
--- /dev/null
+++ b/test/files/run/reify_renamed_term_si5841.scala
@@ -0,0 +1,7 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{universe => ru}
+import scala.tools.reflect.Eval
+
+object Test extends App {
+ println(reify{ru}.eval.getClass)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_type_basic.check b/test/files/run/reify_renamed_type_basic.check
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/files/run/reify_renamed_type_basic.check
@@ -0,0 +1 @@
+()
diff --git a/test/files/run/reify_renamed_type_basic.scala b/test/files/run/reify_renamed_type_basic.scala
new file mode 100644
index 0000000000..23729e5c54
--- /dev/null
+++ b/test/files/run/reify_renamed_type_basic.scala
@@ -0,0 +1,16 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object O {
+ type A = Unit
+}
+
+object Test extends App {
+ import O.{A => X}
+
+ def expr = reify {
+ val a: X = ()
+ }
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_type_local_to_reifee.check b/test/files/run/reify_renamed_type_local_to_reifee.check
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/files/run/reify_renamed_type_local_to_reifee.check
@@ -0,0 +1 @@
+()
diff --git a/test/files/run/reify_renamed_type_local_to_reifee.scala b/test/files/run/reify_renamed_type_local_to_reifee.scala
new file mode 100644
index 0000000000..ed1bad239e
--- /dev/null
+++ b/test/files/run/reify_renamed_type_local_to_reifee.scala
@@ -0,0 +1,24 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+object O {
+ type A = Unit
+}
+
+object Test extends App {
+ val expr = reify {
+ import O.{A => X}
+
+ val a: X = ()
+
+ object P {
+ type B = Unit
+ }
+
+ import P.{B => Y}
+
+ val b: Y = ()
+ }
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_renamed_type_spliceable.check b/test/files/run/reify_renamed_type_spliceable.check
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/files/run/reify_renamed_type_spliceable.check
@@ -0,0 +1 @@
+()
diff --git a/test/files/run/reify_renamed_type_spliceable.scala b/test/files/run/reify_renamed_type_spliceable.scala
new file mode 100644
index 0000000000..9c2cff5199
--- /dev/null
+++ b/test/files/run/reify_renamed_type_spliceable.scala
@@ -0,0 +1,21 @@
+import scala.reflect.runtime.universe._
+import scala.tools.reflect.Eval
+
+abstract class C {
+ type T >: Null
+}
+
+object Test extends App {
+ def foo(c: C) = {
+ import c.{T => U}
+ reify {
+ val x: U = null
+ }
+ }
+
+ val expr = foo(new C {
+ type T = AnyRef
+ })
+
+ println(expr.eval)
+} \ No newline at end of file
diff --git a/test/files/run/t1672.scala b/test/files/run/t1672.scala
new file mode 100644
index 0000000000..ee025b9031
--- /dev/null
+++ b/test/files/run/t1672.scala
@@ -0,0 +1,28 @@
+object Test {
+ @annotation.tailrec
+ def bar(i : Int) : Int = {
+ if (i == 0) 0
+ else try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable => bar(i - 1)
+ }
+ }
+
+ @annotation.tailrec
+ def nestedTry1(i : Int) : Int = {
+ if (i == 0) 0
+ else try {
+ throw new RuntimeException
+ } catch {
+ case _: Throwable =>
+ try { ??? } catch { case _: Throwable => nestedTry1(i - 1) }
+ }
+ }
+
+ def main(args: Array[String]) {
+ assert(bar(2) == 0)
+
+ assert(nestedTry1(2) == 0)
+ }
+}
diff --git a/test/files/run/t5789.check b/test/files/run/t5789.check
new file mode 100644
index 0000000000..ea8d4966b1
--- /dev/null
+++ b/test/files/run/t5789.check
@@ -0,0 +1,14 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> val n = 2
+n: Int = 2
+
+scala> () => n
+res0: () => Int = <function0>
+
+scala>
+
+scala>
diff --git a/test/files/run/t5789.scala b/test/files/run/t5789.scala
new file mode 100644
index 0000000000..461f6a4aae
--- /dev/null
+++ b/test/files/run/t5789.scala
@@ -0,0 +1,14 @@
+
+import scala.tools.nsc._
+import interpreter.ILoop
+import scala.tools.partest.ReplTest
+
+
+object Test extends ReplTest {
+ override def extraSettings = "-Yinline"
+ def code = """
+ val n = 2
+ () => n
+ """
+}
+
diff --git a/test/files/run/t5894.scala b/test/files/run/t5894.scala
new file mode 100644
index 0000000000..abeec32365
--- /dev/null
+++ b/test/files/run/t5894.scala
@@ -0,0 +1,17 @@
+import language.experimental.macros
+
+class Test
+
+object Test {
+ def foo = macro fooImpl
+ def fooImpl(c: reflect.macros.Context) = c.literalUnit
+
+ def main(args: Array[String]) {
+ try {
+ val method = classOf[Test].getMethod("foo")
+ sys.error("Static forwarder generated for macro: " + method)
+ } catch {
+ case _: NoSuchMethodException => // okay
+ }
+ }
+}
diff --git a/test/files/run/t6549.check b/test/files/run/t6549.check
new file mode 100644
index 0000000000..bc78aac741
--- /dev/null
+++ b/test/files/run/t6549.check
@@ -0,0 +1,32 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> case class `X"`(var xxx: Any)
+defined class X$u0022
+
+scala> val m = Map(("": Any) -> `X"`("\""), ('s: Any) -> `X"`("\""))
+m: scala.collection.immutable.Map[Any,X"] = Map("" -> X"("), 's -> X"("))
+
+scala> m("")
+res0: X" = X"(")
+
+scala> m("").xxx
+res1: Any = "
+
+scala> m("").xxx = 0
+m("").xxx: Any = 0
+
+scala> m("").xxx = "\""
+m("").xxx: Any = "
+
+scala> m('s).xxx = 's
+m(scala.Symbol("s")).xxx: Any = 's
+
+scala> val `"` = 0
+": Int = 0
+
+scala>
+
+scala>
diff --git a/test/files/run/t6549.scala b/test/files/run/t6549.scala
new file mode 100644
index 0000000000..7335661dc7
--- /dev/null
+++ b/test/files/run/t6549.scala
@@ -0,0 +1,22 @@
+import scala.tools.partest.ReplTest
+
+// Check that the fragments of code generated in
+// in the REPL correctly escape values added to
+// literal strings.
+//
+// Before, we saw:
+// scala> m("").x = 77
+// <console>:10: error: ')' expected but string literal found.
+// + "m("").x: Int = " + `$ires8` + "\n"
+object Test extends ReplTest {
+ def code = """
+ |case class `X"`(var xxx: Any)
+ |val m = Map(("": Any) -> `X"`("\""), ('s: Any) -> `X"`("\""))
+ |m("")
+ |m("").xxx
+ |m("").xxx = 0
+ |m("").xxx = "\""
+ |m('s).xxx = 's
+ |val `"` = 0
+ """.stripMargin
+}
diff --git a/test/files/run/t6555.check b/test/files/run/t6555.check
new file mode 100644
index 0000000000..04117b7c2f
--- /dev/null
+++ b/test/files/run/t6555.check
@@ -0,0 +1,22 @@
+[[syntax trees at end of specialize]] // newSource1
+package <empty> {
+ class Foo extends Object {
+ def <init>(): Foo = {
+ Foo.super.<init>();
+ ()
+ };
+ private[this] val f: Int => Int = {
+ @SerialVersionUID(0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
+ def <init>(): anonymous class $anonfun = {
+ $anonfun.super.<init>();
+ ()
+ };
+ final def apply(param: Int): Int = $anonfun.this.apply$mcII$sp(param);
+ <specialized> def apply$mcII$sp(param: Int): Int = param
+ };
+ (new anonymous class $anonfun(): Int => Int)
+ };
+ <stable> <accessor> def f(): Int => Int = Foo.this.f
+ }
+}
+
diff --git a/test/files/run/t6555.scala b/test/files/run/t6555.scala
new file mode 100644
index 0000000000..b1a6137786
--- /dev/null
+++ b/test/files/run/t6555.scala
@@ -0,0 +1,15 @@
+import scala.tools.partest._
+import java.io.{Console => _, _}
+
+object Test extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp -Xprint:specialize -d " + testOutput.path
+
+ override def code = "class Foo { val f = (param: Int) => param } "
+
+ override def show(): Unit = {
+ Console.withErr(System.out) {
+ compile()
+ }
+ }
+}
diff --git a/test/files/run/t6614.check b/test/files/run/t6614.check
new file mode 100644
index 0000000000..2e80ebda8b
--- /dev/null
+++ b/test/files/run/t6614.check
@@ -0,0 +1,11 @@
+(ArrayStack(),true)
+(ArrayStack(0),true)
+(ArrayStack(0, 1),true)
+(ArrayStack(0, 1, 2),true)
+(ArrayStack(0, 1, 2, 3),true)
+(ArrayStack(0, 1, 2, 3, 4),true)
+(ArrayStack(0, 1, 2, 3, 4, 5),true)
+(ArrayStack(0, 1, 2, 3, 4, 5, 6),true)
+(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7),true)
+(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7, 8),true)
+(ArrayStack(0, 1, 2, 3, 4, 5, 6, 7, 8, 9),true)
diff --git a/test/files/run/t6614.scala b/test/files/run/t6614.scala
new file mode 100644
index 0000000000..3ad9f36fc4
--- /dev/null
+++ b/test/files/run/t6614.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ import scala.collection.mutable.ArrayStack
+
+ println((for (i <- 0 to 10) yield {
+ val in = ArrayStack.tabulate(i)(_.toString)
+ (in, (in filter (_ => true)) == in)
+ }).mkString("\n"))
+}
diff --git a/test/files/run/t6690.scala b/test/files/run/t6690.scala
new file mode 100644
index 0000000000..43ede967a0
--- /dev/null
+++ b/test/files/run/t6690.scala
@@ -0,0 +1,62 @@
+import scala.collection.mutable
+
+object Test extends App {
+ def last0(ml: mutable.MutableList[Int]) =
+ ml.asInstanceOf[{def last0: mutable.LinkedList[Int]}].last0
+
+ def first0(ml: mutable.MutableList[Int]) =
+ ml.asInstanceOf[{def first0: mutable.LinkedList[Int]}].first0
+
+ val f = mutable.Queue[Int]()
+ def check(desc: String) {
+ assert(f.length == 0, s"$desc: non empty: $f")
+ assert(last0(f).isEmpty, s"$desc: last0 leak: ${last0(f)}")
+ assert(first0(f).isEmpty, s"$desc: first0 leak: ${last0(f)}")
+ }
+
+ f.enqueue(1)
+ f.dequeue()
+ check("dequeue 1")
+
+ f.enqueue(1)
+ f.enqueue(2)
+ f.dequeue()
+ assert(last0(f).toList == List(2), last0(f))
+ f.dequeue()
+ check("dequeue 2")
+
+ f.enqueue(1)
+ f.dequeueAll(_ => false)
+ f.dequeueAll(_ => true)
+ check("dequeueAll")
+
+ f.enqueue(1)
+ f.dequeueFirst(_ => true)
+ check("dequeueFirst")
+
+ {
+ f.enqueue(1)
+ val tail = f.tail
+ assert(last0(tail).isEmpty, last0(tail))
+ assert(first0(tail).isEmpty, first0(tail))
+ }
+
+ {
+ val ml = mutable.MutableList[Int]()
+ 1 +=: ml
+ val tail = ml.tail
+ assert(last0(tail).isEmpty, last0(tail))
+ assert(first0(tail).isEmpty, first0(tail))
+ }
+
+ {
+ val ml = mutable.MutableList[Int]()
+ 1 +=: ml
+ ml += 2
+ val tail = ml.tail
+ assert(last0(tail).toList == List(2), last0(tail))
+ assert(first0(tail) == last0(tail).toList, first0(tail))
+ assert(last0(tail.tail).toList == Nil, last0(tail.tail).toList)
+ assert(first0(tail.tail) == Nil, first0(tail.tail))
+ }
+}
diff --git a/test/scaladoc/run/SI-191-deprecated.scala b/test/scaladoc/run/SI-191-deprecated.scala
index 746aa9c598..4ed24ff8d1 100755
--- a/test/scaladoc/run/SI-191-deprecated.scala
+++ b/test/scaladoc/run/SI-191-deprecated.scala
@@ -1,5 +1,6 @@
import scala.tools.nsc.doc.model._
-import scala.tools.nsc.doc.model.comment._
+import scala.tools.nsc.doc.base._
+import scala.tools.nsc.doc.base.comment._
import scala.tools.partest.ScaladocModelTest
import java.net.{URI, URL}
import java.io.File
diff --git a/test/scaladoc/run/SI-191.scala b/test/scaladoc/run/SI-191.scala
index 0fb28145c3..6fb5339d66 100755
--- a/test/scaladoc/run/SI-191.scala
+++ b/test/scaladoc/run/SI-191.scala
@@ -1,5 +1,6 @@
import scala.tools.nsc.doc.model._
-import scala.tools.nsc.doc.model.comment._
+import scala.tools.nsc.doc.base._
+import scala.tools.nsc.doc.base.comment._
import scala.tools.partest.ScaladocModelTest
import java.net.{URI, URL}
import java.io.File
diff --git a/test/scaladoc/run/SI-3314.scala b/test/scaladoc/run/SI-3314.scala
index fe220b08af..c856fe46a8 100644
--- a/test/scaladoc/run/SI-3314.scala
+++ b/test/scaladoc/run/SI-3314.scala
@@ -1,3 +1,4 @@
+import scala.tools.nsc.doc.base._
import scala.tools.nsc.doc.model._
import scala.tools.partest.ScaladocModelTest
@@ -88,4 +89,4 @@ object Test extends ScaladocModelTest {
assert(bar.valueParams(0)(0).resultType.name == "(AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]",
bar.valueParams(0)(0).resultType.name + " == (AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]")
}
-} \ No newline at end of file
+}
diff --git a/test/scaladoc/run/SI-5235.scala b/test/scaladoc/run/SI-5235.scala
index 6295fc7786..c6b7922bb8 100644
--- a/test/scaladoc/run/SI-5235.scala
+++ b/test/scaladoc/run/SI-5235.scala
@@ -1,3 +1,4 @@
+import scala.tools.nsc.doc.base._
import scala.tools.nsc.doc.model._
import scala.tools.nsc.doc.model.diagram._
import scala.tools.partest.ScaladocModelTest
@@ -84,4 +85,4 @@ object Test extends ScaladocModelTest {
assert(mcReverseType.refEntity(0)._1 == LinkToTpl(MyCollection),
mcReverse.qualifiedName + "'s return type has a link to " + MyCollection.qualifiedName)
}
-} \ No newline at end of file
+}
diff --git a/test/scaladoc/run/links.scala b/test/scaladoc/run/links.scala
index 0c67857e1c..fde24edb2a 100644
--- a/test/scaladoc/run/links.scala
+++ b/test/scaladoc/run/links.scala
@@ -1,3 +1,4 @@
+import scala.tools.nsc.doc.base._
import scala.tools.nsc.doc.model._
import scala.tools.partest.ScaladocModelTest
@@ -23,9 +24,9 @@ object Test extends ScaladocModelTest {
val base = rootPackage._package("scala")._package("test")._package("scaladoc")._package("links")
val TEST = base._object("TEST")
- val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember])
- val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl])
+ val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember[_, _]])
+ val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl[_]])
assert(memberLinks == 17, memberLinks + " == 17 (the member links in object TEST)")
assert(templateLinks == 6, templateLinks + " == 6 (the template links in object TEST)")
}
-} \ No newline at end of file
+}
diff --git a/test/scaladoc/run/t4922.check b/test/scaladoc/run/t4922.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/t4922.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/t4922.scala b/test/scaladoc/run/t4922.scala
new file mode 100644
index 0000000000..bce87ac980
--- /dev/null
+++ b/test/scaladoc/run/t4922.scala
@@ -0,0 +1,32 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ // Test code
+ override def code = """
+ // This the default values should be displayed
+
+ object Test {
+ def f (a: Any = "".isEmpty) = ()
+ def g[A](b: A = null) = ()
+ }
+ """
+
+ // no need for special settings
+ def scaladocSettings = ""
+
+ def testModel(rootPackage: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ val Test = rootPackage._object("Test")
+ val f = Test._method("f")
+ val g = Test._method("g")
+
+ def assertEqual(s1: String, s2: String) = assert(s1 == s2, s1 + " == " + s2)
+
+ assertEqual(f.valueParams(0)(0).defaultValue.get.expression, "\"\".isEmpty")
+ assertEqual(g.valueParams(0)(0).defaultValue.get.expression, "null")
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala
index 5e3141bdc0..96174d29d1 100644
--- a/test/scaladoc/scalacheck/CommentFactoryTest.scala
+++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala
@@ -3,8 +3,7 @@ import org.scalacheck.Prop._
import scala.tools.nsc.Global
import scala.tools.nsc.doc
-import scala.tools.nsc.doc.model._
-import scala.tools.nsc.doc.model.comment._
+import scala.tools.nsc.doc.base.comment._
import scala.tools.nsc.doc.model._
import scala.tools.nsc.doc.model.diagram._