summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-18 15:11:06 -0700
committerPaul Phillips <paulp@improving.org>2012-10-19 09:04:19 -0700
commit3fea5453b6a6c9451ecd6d0a93b92432b575e6cb (patch)
tree6e010951cdd253747afe18912547ca6d3fce2e6e
parent32d470d61195cbf092614711b27db396d0d54a40 (diff)
parent87c5895d4bae62f1b5bacbd145f2e0fddcccf423 (diff)
downloadscala-3fea5453b6a6c9451ecd6d0a93b92432b575e6cb.tar.gz
scala-3fea5453b6a6c9451ecd6d0a93b92432b575e6cb.tar.bz2
scala-3fea5453b6a6c9451ecd6d0a93b92432b575e6cb.zip
Merge remote-tracking branch 'origin/2.10.x' into merge-210
* origin/2.10.x: (52 commits) JavaUniverse Moved @contentDiagram in Symbols Adds lots of new documentation for TypeTags, Mirrors, Universes and more runtime.JavaUniverse - put ungrouped members at the top Forgotten annotation in Annotations Diagram tweaking Grouping for reflection and macros fixes a typo scala.reflect.api.Symbols documentation Symbols docs cleanup, mostly moved to guide scala.reflect.api.Position documentation scala.reflect.api.StandardNames documentation scala.reflect.api.Constants documentation removed docs for internal TypeCreator and TreeCreator simplified reflection docs for trees Rearranged some reflection docs, moving things to the guide reflection docs improvements and moves to doc page docs for reflection and macros SI-6509 Correct @template owners SI-6155 Scaladoc @template diagrms ... Conflicts: src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala src/reflect/scala/reflect/api/Trees.scala test/scaladoc/run/links.scala
-rw-r--r--build.xml2
-rw-r--r--src/compiler/scala/reflect/macros/runtime/Parsers.scala2
-rw-r--r--src/compiler/scala/reflect/macros/runtime/Typers.scala13
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala24
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala10
-rw-r--r--src/compiler/scala/reflect/reify/Taggers.scala10
-rw-r--r--src/compiler/scala/reflect/reify/package.scala4
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala3
-rw-r--r--src/compiler/scala/reflect/reify/utils/SymbolTables.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala20
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala46
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala13
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala1
-rw-r--r--src/compiler/scala/tools/nsc/scratchpad/Mixer.scala1
-rw-r--r--src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala8
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
-rw-r--r--src/compiler/scala/tools/nsc/util/InterruptReq.scala5
-rw-r--r--src/compiler/scala/tools/reflect/MacroImplementations.scala2
-rw-r--r--src/compiler/scala/tools/util/PathResolver.scala2
-rw-r--r--src/library/scala/annotation/switch.scala3
-rw-r--r--src/library/scala/collection/TraversableLike.scala7
-rw-r--r--src/library/scala/concurrent/Awaitable.scala55
-rw-r--r--src/library/scala/concurrent/package.scala70
-rw-r--r--src/library/scala/package.scala3
-rw-r--r--src/library/scala/reflect/ClassTag.scala35
-rw-r--r--src/library/scala/runtime/WorksheetSupport.scala1
-rw-r--r--src/reflect/scala/reflect/api/Annotations.scala123
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala3
-rw-r--r--src/reflect/scala/reflect/api/Constants.scala202
-rw-r--r--src/reflect/scala/reflect/api/Exprs.scala47
-rw-r--r--src/reflect/scala/reflect/api/FlagSets.scala75
-rw-r--r--src/reflect/scala/reflect/api/Importers.scala76
-rw-r--r--src/reflect/scala/reflect/api/JavaMirrors.scala52
-rw-r--r--src/reflect/scala/reflect/api/JavaUniverse.scala25
-rw-r--r--src/reflect/scala/reflect/api/Mirror.scala40
-rw-r--r--src/reflect/scala/reflect/api/Mirrors.scala282
-rw-r--r--src/reflect/scala/reflect/api/Names.scala78
-rw-r--r--src/reflect/scala/reflect/api/Position.scala113
-rw-r--r--src/reflect/scala/reflect/api/Positions.scala20
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala156
-rw-r--r--src/reflect/scala/reflect/api/Scopes.scala51
-rw-r--r--src/reflect/scala/reflect/api/StandardDefinitions.scala256
-rw-r--r--src/reflect/scala/reflect/api/StandardNames.scala68
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala412
-rw-r--r--src/reflect/scala/reflect/api/TagInterop.scala23
-rw-r--r--src/reflect/scala/reflect/api/TreeCreator.scala20
-rw-r--r--src/reflect/scala/reflect/api/Trees.scala1383
-rw-r--r--src/reflect/scala/reflect/api/TypeCreator.scala18
-rw-r--r--src/reflect/scala/reflect/api/TypeTags.scala277
-rw-r--r--src/reflect/scala/reflect/api/Types.scala350
-rw-r--r--src/reflect/scala/reflect/api/Universe.scala105
-rw-r--r--src/reflect/scala/reflect/api/package.scala95
-rw-r--r--src/reflect/scala/reflect/internal/FlagSets.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala47
-rw-r--r--src/reflect/scala/reflect/internal/StdAttachments.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Types.scala36
-rw-r--r--src/reflect/scala/reflect/internal/util/Position.scala46
-rw-r--r--src/reflect/scala/reflect/macros/Aliases.scala76
-rw-r--r--src/reflect/scala/reflect/macros/Attachments.scala (renamed from src/reflect/scala/reflect/api/Attachments.scala)19
-rw-r--r--src/reflect/scala/reflect/macros/Context.scala65
-rw-r--r--src/reflect/scala/reflect/macros/Enclosures.scala5
-rw-r--r--src/reflect/scala/reflect/macros/Evals.scala47
-rw-r--r--src/reflect/scala/reflect/macros/ExprUtils.scala16
-rw-r--r--src/reflect/scala/reflect/macros/FrontEnds.scala28
-rw-r--r--src/reflect/scala/reflect/macros/Infrastructure.scala3
-rw-r--r--src/reflect/scala/reflect/macros/Names.scala11
-rw-r--r--src/reflect/scala/reflect/macros/Parsers.scala15
-rw-r--r--src/reflect/scala/reflect/macros/Reifiers.scala15
-rw-r--r--src/reflect/scala/reflect/macros/TreeBuilder.scala17
-rw-r--r--src/reflect/scala/reflect/macros/Typers.scala29
-rw-r--r--src/reflect/scala/reflect/macros/Universe.scala108
-rw-r--r--src/reflect/scala/reflect/macros/package.scala12
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala17
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverse.scala7
-rw-r--r--src/reflect/scala/reflect/runtime/ReflectionUtils.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/Settings.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolLoaders.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SymbolTable.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedOps.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/SynchronizedTypes.scala2
-rw-r--r--src/reflect/scala/reflect/runtime/package.scala17
-rw-r--r--test/files/neg/t6483.check9
-rw-r--r--test/files/neg/t6483.scala24
-rw-r--r--test/files/pos/t6215.scala1
-rw-r--r--test/files/pos/t6485a/Macros_1.scala5
-rw-r--r--test/files/pos/t6485a/Test_2.scala5
-rw-r--r--test/files/pos/t6485b/Test.scala10
-rw-r--r--test/files/pos/t6499.scala3
-rw-r--r--test/files/presentation/forgotten-ask.scala33
-rw-r--r--test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala2
-rw-r--r--test/files/run/macro-typecheck-implicitsdisabled.check2
-rw-r--r--test/files/run/reflection-magicsymbols-invoke.scala8
-rw-r--r--test/files/run/reflection-valueclasses-magic.scala8
-rw-r--r--test/files/run/t6344.check16
-rw-r--r--test/files/run/t6440.check1
-rw-r--r--test/files/run/t6440.scala7
-rw-r--r--test/scaladoc/resources/SI-6509.scala24
-rw-r--r--test/scaladoc/resources/SI-6511.scala24
-rw-r--r--test/scaladoc/resources/links.scala14
-rw-r--r--test/scaladoc/run/SI-6509.check1
-rw-r--r--test/scaladoc/run/SI-6509.scala30
-rw-r--r--test/scaladoc/run/SI-6511.check1
-rw-r--r--test/scaladoc/run/SI-6511.scala22
-rw-r--r--test/scaladoc/run/groups.scala94
-rw-r--r--test/scaladoc/run/links.scala7
112 files changed, 4566 insertions, 1147 deletions
diff --git a/build.xml b/build.xml
index 67d715bfe9..c9027e0985 100644
--- a/build.xml
+++ b/build.xml
@@ -2337,7 +2337,7 @@ DOCUMENTATION
docfooter="epfl"
docsourceurl="${scaladoc.url}€{FILE_PATH}.scala#L1"
docUncompilable="${src.dir}/library-aux"
- skipPackages="scala.reflect.macros.internal:scala.reflect.internal:scala.reflect.runtime:scala.reflect.io"
+ skipPackages="scala.reflect.macros.internal:scala.reflect.internal:scala.reflect.io:scala.concurrent.impl"
sourcepath="${src.dir}"
classpathref="pack.classpath"
addparams="${scalac.args.all}"
diff --git a/src/compiler/scala/reflect/macros/runtime/Parsers.scala b/src/compiler/scala/reflect/macros/runtime/Parsers.scala
index ab9b94ec9f..566bcde73d 100644
--- a/src/compiler/scala/reflect/macros/runtime/Parsers.scala
+++ b/src/compiler/scala/reflect/macros/runtime/Parsers.scala
@@ -19,6 +19,6 @@ trait Parsers {
} catch {
case ToolBoxError(msg, cause) =>
// todo. provide a position
- throw new ParseError(universe.NoPosition, msg)
+ throw new ParseException(universe.NoPosition, msg)
}
}
diff --git a/src/compiler/scala/reflect/macros/runtime/Typers.scala b/src/compiler/scala/reflect/macros/runtime/Typers.scala
index 9fa8567ada..f9add91b9a 100644
--- a/src/compiler/scala/reflect/macros/runtime/Typers.scala
+++ b/src/compiler/scala/reflect/macros/runtime/Typers.scala
@@ -8,6 +8,9 @@ trait Typers {
def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits
+ /**
+ * @see [[scala.tools.reflect.Toolbox.typeCheck]]
+ */
def typeCheck(tree: Tree, pt: Type = universe.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled))
val context = callsiteTyper.context
@@ -25,7 +28,7 @@ trait Typers {
result
case error @ universe.analyzer.SilentTypeError(_) =>
macroLogVerbose(error.err.errMsg)
- if (!silent) throw new universe.TypeError(error.err.errPos, error.err.errMsg)
+ if (!silent) throw new TypecheckException(error.err.errPos, error.err.errMsg)
universe.EmptyTree
})
}
@@ -49,19 +52,13 @@ trait Typers {
wrapper(universe.analyzer.inferImplicit(tree, pt, reportAmbiguous = true, isView = isView, context = context, saveAmbiguousDivergent = !silent, pos = pos)) match {
case failure if failure.tree.isEmpty =>
macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
- if (context.hasErrors) throw new universe.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg)
+ if (context.hasErrors) throw new TypecheckException(context.errBuffer.head.errPos, context.errBuffer.head.errMsg)
universe.EmptyTree
case success =>
success.tree
}
}
- type TypeError = universe.TypeError
-
- object TypeError extends TypeErrorExtractor {
- def unapply(error: TypeError): Option[(Position, String)] = Some((error.pos, error.msg))
- }
-
def resetAllAttrs(tree: Tree): Tree = universe.resetAllAttrs(tree)
def resetLocalAttrs(tree: Tree): Tree = universe.resetLocalAttrs(tree)
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
index fb6765d9ed..b8b5f8033b 100644
--- a/src/compiler/scala/reflect/reify/Errors.scala
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -1,7 +1,7 @@
package scala.reflect.reify
-import scala.reflect.macros.ReificationError
-import scala.reflect.macros.UnexpectedReificationError
+import scala.reflect.macros.ReificationException
+import scala.reflect.macros.UnexpectedReificationException
trait Errors {
self: Reifier =>
@@ -19,17 +19,17 @@ trait Errors {
def CannotReifyType(tpe: Type) = {
val msg = "implementation restriction: cannot reify type %s (%s)".format(tpe, tpe.kind)
- throw new ReificationError(defaultErrorPosition, msg)
+ throw new ReificationException(defaultErrorPosition, msg)
}
def CannotReifySymbol(sym: Symbol) = {
val msg = "implementation restriction: cannot reify symbol %s (%s)".format(sym, sym.accurateKindString)
- throw new ReificationError(defaultErrorPosition, msg)
+ throw new ReificationException(defaultErrorPosition, msg)
}
def CannotReifyWeakType(details: Any) = {
val msg = "cannot create a TypeTag" + details
- throw new ReificationError(defaultErrorPosition, msg)
+ throw new ReificationException(defaultErrorPosition, msg)
}
def CannotConvertManifestToTagWithoutScalaReflect(tpe: Type, manifestInScope: Tree) = {
@@ -37,7 +37,7 @@ trait Errors {
|to create a type tag here, it is necessary to interoperate with the manifest `$manifestInScope` in scope.
|however manifest -> typetag conversion requires Scala reflection, which is not present on the classpath.
|to proceed put scala-reflect.jar on your compilation classpath and recompile.""".trim.stripMargin
- throw new ReificationError(defaultErrorPosition, msg)
+ throw new ReificationException(defaultErrorPosition, msg)
}
def CannotReifyRuntimeSplice(tree: Tree) = {
@@ -46,7 +46,7 @@ trait Errors {
|cross-stage evaluations need to be invoked explicitly, so we're showing you this error.
|if you're sure this is not an oversight, add scala-compiler.jar to the classpath,
|import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin
- throw new ReificationError(tree.pos, msg)
+ throw new ReificationException(tree.pos, msg)
}
// unexpected errors: these can never happen under normal conditions unless there's a bug in the compiler (or in a compiler plugin or in a macro)
@@ -54,26 +54,26 @@ trait Errors {
def CannotReifyUntypedPrefix(prefix: Tree) = {
val msg = "internal error: untyped prefixes are not supported, consider typechecking the prefix before passing it to the reifier"
- throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ throw new UnexpectedReificationException(defaultErrorPosition, msg)
}
def CannotReifyUntypedReifee(reifee: Any) = {
val msg = "internal error: untyped trees are not supported, consider typechecking the reifee before passing it to the reifier"
- throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ throw new UnexpectedReificationException(defaultErrorPosition, msg)
}
def CannotReifyErroneousPrefix(prefix: Tree) = {
val msg = "internal error: erroneous prefixes are not supported, make sure that your prefix has typechecked successfully before passing it to the reifier"
- throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ throw new UnexpectedReificationException(defaultErrorPosition, msg)
}
def CannotReifyErroneousReifee(reifee: Any) = {
val msg = "internal error: erroneous reifees are not supported, make sure that your reifee has typechecked successfully before passing it to the reifier"
- throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ throw new UnexpectedReificationException(defaultErrorPosition, msg)
}
def CannotReifyInvalidLazyVal(tree: ValDef) = {
val msg = "internal error: could not reconstruct original lazy val due to missing accessor"
- throw new UnexpectedReificationError(tree.pos, msg)
+ throw new UnexpectedReificationException(tree.pos, msg)
}
}
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
index 5d3ac8cde0..b3224b1aa6 100644
--- a/src/compiler/scala/reflect/reify/Reifier.scala
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -1,8 +1,8 @@
package scala.reflect.reify
import scala.tools.nsc.Global
-import scala.reflect.macros.ReificationError
-import scala.reflect.macros.UnexpectedReificationError
+import scala.reflect.macros.ReificationException
+import scala.reflect.macros.UnexpectedReificationException
import scala.reflect.reify.utils.Utils
/** Given a tree or a type, generate a tree that when executed at runtime produces the original tree or type.
@@ -132,12 +132,12 @@ abstract class Reifier extends States
untyped
} catch {
- case ex: ReificationError =>
+ case ex: ReificationException =>
throw ex
- case ex: UnexpectedReificationError =>
+ case ex: UnexpectedReificationException =>
throw ex
case ex: Throwable =>
- throw new UnexpectedReificationError(defaultErrorPosition, "reification crashed", ex)
+ throw new UnexpectedReificationException(defaultErrorPosition, "reification crashed", ex)
}
}
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Taggers.scala b/src/compiler/scala/reflect/reify/Taggers.scala
index 7db6394734..cbaee41890 100644
--- a/src/compiler/scala/reflect/reify/Taggers.scala
+++ b/src/compiler/scala/reflect/reify/Taggers.scala
@@ -1,6 +1,6 @@
package scala.reflect.reify
-import scala.reflect.macros.{ReificationError, UnexpectedReificationError}
+import scala.reflect.macros.{ReificationException, UnexpectedReificationException, TypecheckException}
import scala.reflect.macros.runtime.Context
abstract class Taggers {
@@ -65,22 +65,22 @@ abstract class Taggers {
translatingReificationErrors(materializer)
}
try c.typeCheck(result)
- catch { case terr @ c.TypeError(pos, msg) => failTag(result, terr) }
+ catch { case terr @ TypecheckException(pos, msg) => failTag(result, terr) }
}
def materializeExpr(universe: Tree, mirror: Tree, expr: Tree): Tree = {
val result = translatingReificationErrors(c.reifyTree(universe, mirror, expr))
try c.typeCheck(result)
- catch { case terr @ c.TypeError(pos, msg) => failExpr(result, terr) }
+ catch { case terr @ TypecheckException(pos, msg) => failExpr(result, terr) }
}
private def translatingReificationErrors(materializer: => Tree): Tree = {
try materializer
catch {
- case ReificationError(pos, msg) =>
+ case ReificationException(pos, msg) =>
c.error(pos.asInstanceOf[c.Position], msg) // this cast is a very small price for the sanity of exception handling
EmptyTree
- case UnexpectedReificationError(pos, err, cause) if cause != null =>
+ case UnexpectedReificationException(pos, err, cause) if cause != null =>
throw cause
}
}
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
index 5a23ab7214..55f8684df2 100644
--- a/src/compiler/scala/reflect/reify/package.scala
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -1,7 +1,7 @@
package scala.reflect
import scala.language.implicitConversions
-import scala.reflect.macros.{Context, ReificationError, UnexpectedReificationError}
+import scala.reflect.macros.{Context, ReificationException, UnexpectedReificationException}
import scala.tools.nsc.Global
package object reify {
@@ -53,7 +53,7 @@ package object reify {
if (tpe.isSpliceable) {
val classTagInScope = typer0.resolveClassTag(enclosingMacroPosition, tpe, allowMaterialization = false)
if (!classTagInScope.isEmpty) return Select(classTagInScope, nme.runtimeClass)
- if (concrete) throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
+ if (concrete) throw new ReificationException(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
}
tpe.normalize match {
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
index 1b7509fdbe..9a1732a872 100644
--- a/src/compiler/scala/reflect/reify/phases/Reshape.scala
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -326,7 +326,8 @@ trait Reshape {
case Some(ddef) =>
toPreTyperLazyVal(ddef)
case None =>
- CannotReifyInvalidLazyVal(vdef)
+ if (reifyDebug) println("couldn't find corresponding lazy val accessor")
+ vdef
}
if (reifyDebug) println(s"reconstructed lazy val is $vdef1")
vdef1::Nil
diff --git a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
index 3ec43c863d..dbb0836e0a 100644
--- a/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
+++ b/src/compiler/scala/reflect/reify/utils/SymbolTables.scala
@@ -28,7 +28,7 @@ trait SymbolTables {
symtab.get(sym) match {
case Some(FreeDef(_, name, _, _, _)) => name
case Some(SymDef(_, name, _, _)) => name
- case None => EmptyTermName
+ case None => nme.EMPTY
}
def symAliases(sym: Symbol): List[TermName] =
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index cd0c242f22..02b69034ef 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -86,7 +86,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
with model.comment.CommentFactory
with model.TreeFactory
with model.MemberLookup {
- override def templateShouldDocument(sym: compiler.Symbol, inTpl: TemplateImpl) =
+ override def templateShouldDocument(sym: compiler.Symbol, inTpl: DocTemplateImpl) =
extraTemplatesToDocument(sym) || super.templateShouldDocument(sym, inTpl)
}
)
diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
index 7f260bb90a..1248de625d 100644
--- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
@@ -120,19 +120,17 @@ trait MemberLookup {
private object OnlyTerm extends SearchStrategy
private def lookupInRootPackage(pos: Position, members: List[String]) =
- if (members.length == 1)
- lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
- else
- lookupInTemplate(pos, members, RootPackage)
+ lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
private def createLinks(syms: List[(Symbol, Symbol)]): List[LinkTo] =
syms.flatMap { case (sym, owner) =>
- if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
- findTemplateMaybe(sym) map (LinkToTpl(_))
- else
- findTemplateMaybe(owner) flatMap { inTpl =>
- inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl))
- }
+ 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)] = {
@@ -153,7 +151,7 @@ trait MemberLookup {
case tplName::rest =>
def completeSearch(syms: List[Symbol]) =
- syms filter {sym => sym.isPackage || sym.isClass || sym.isModule} flatMap (lookupInTemplate(pos, rest, _))
+ syms flatMap (lookupInTemplate(pos, rest, _))
completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match {
case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType))
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 906c17faa0..a4ca881230 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -31,6 +31,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
import rootMirror.{ RootPackage, RootClass, EmptyPackage }
+ // Defaults for member grouping, that may be overridden by the template
+ val defaultGroup = "Ungrouped"
+ val defaultGroupName = "Ungrouped"
+ val defaultGroupDesc = None
+ val defaultGroupPriority = 1000
+
def templatesCount = docTemplatesCache.count(_._2.isDocTemplate) - droppedPackages.size
private var _modelFinished = false
@@ -121,7 +127,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
if (inTpl != null) thisFactory.comment(sym, thisTpl, inTpl) else None
}
- def group = comment flatMap (_.group) getOrElse "No Group"
+ def group = comment flatMap (_.group) getOrElse defaultGroup
override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
def inDefinitionTemplates =
@@ -284,7 +290,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
val tps = (this match {
case a: AliasType => sym.tpe.dealias.parents
case a: AbstractType => sym.info.bounds match {
- case TypeBounds(lo, hi) => List(hi)
+ case TypeBounds(lo, RefinedType(parents, decls)) => parents
+ case TypeBounds(lo, hi) => hi :: Nil
case _ => Nil
}
case _ => sym.tpe.parents
@@ -484,14 +491,28 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def inheritanceDiagram = makeInheritanceDiagram(this)
def contentDiagram = makeContentDiagram(this)
- def groupSearch[T](extractor: Comment => Option[T]): Option[T] = {
- val comments = comment +: linearizationTemplates.collect { case dtpl: DocTemplateImpl => dtpl.comment }
- comments.flatten.map(extractor).flatten.headOption
+ def groupSearch[T](extractor: Comment => T, default: T): T = {
+ // query this template
+ if (comment.isDefined) {
+ val entity = extractor(comment.get)
+ if (entity != default) return entity
+ }
+ // query linearization
+ if (!sym.isPackage)
+ for (tpl <- linearizationTemplates.collect{ case dtpl: DocTemplateImpl if dtpl!=this => dtpl}) {
+ val entity = tpl.groupSearch(extractor, default)
+ if (entity != default) return entity
+ }
+ // query inTpl, going up the ownerChain
+ if (inTpl != null)
+ inTpl.groupSearch(extractor, default)
+ else
+ default
}
- def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group))
- def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group)) getOrElse 0
- def groupName(group: String): String = groupSearch(_.groupNames.get(group)) getOrElse group
+ def groupDescription(group: String): Option[Body] = groupSearch(_.groupDesc.get(group), if (group == defaultGroup) defaultGroupDesc else None)
+ def groupPriority(group: String): Int = groupSearch(_.groupPrio.get(group) match { case Some(prio) => prio; case _ => 0 }, if (group == defaultGroup) defaultGroupPriority else 0)
+ def groupName(group: String): String = groupSearch(_.groupNames.get(group) match { case Some(name) => name; case _ => group }, if (group == defaultGroup) defaultGroupName else group)
}
abstract class PackageImpl(sym: Symbol, inTpl: PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
@@ -721,7 +742,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
else {
// no class inheritance at this point
- assert(inOriginalOwner(bSym, inTpl) || bSym.isAbstractType || bSym.isAliasType, bSym + " in " + inTpl)
+ assert(inOriginalOwner(bSym, inTpl), bSym + " in " + inTpl)
Some(createDocTemplate(bSym, inTpl))
}
}
@@ -817,7 +838,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
Some(new MemberTemplateImpl(bSym, inTpl) with AliasImpl with AliasType {
override def isAliasType = true
})
- else if (!modelFinished && (bSym.isPackage || bSym.isAliasType || bSym.isAbstractType || templateShouldDocument(bSym, inTpl)))
+ else if (!modelFinished && (bSym.isPackage || templateShouldDocument(bSym, inTpl)))
modelCreation.createTemplate(bSym, inTpl)
else
None
@@ -1016,8 +1037,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def inOriginalOwner(aSym: Symbol, inTpl: TemplateImpl): Boolean =
normalizeTemplate(aSym.owner) == normalizeTemplate(inTpl.sym)
- def templateShouldDocument(aSym: Symbol, inTpl: TemplateImpl): Boolean =
- (aSym.isTrait || aSym.isClass || aSym.isModule) &&
+ def templateShouldDocument(aSym: Symbol, inTpl: DocTemplateImpl): Boolean =
+ (aSym.isTrait || aSym.isClass || aSym.isModule || typeShouldDocument(aSym, inTpl)) &&
localShouldDocument(aSym) &&
!isEmptyJavaObject(aSym) &&
// either it's inside the original owner or we can document it later:
@@ -1057,6 +1078,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// whether or not to create a page for an {abstract,alias} type
def typeShouldDocument(bSym: Symbol, inTpl: DocTemplateImpl) =
(settings.docExpandAllTypes.value && (bSym.sourceFile != null)) ||
+ (bSym.isAliasType || bSym.isAbstractType) &&
{ val rawComment = global.expandedDocComment(bSym, inTpl.sym)
rawComment.contains("@template") || rawComment.contains("@documentable") }
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index ae38a082ca..b528948716 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -13,6 +13,7 @@ import scala.tools.nsc.util.FailedInterrupt
import scala.tools.nsc.util.EmptyAction
import scala.tools.nsc.util.WorkScheduler
import scala.reflect.internal.util.{SourceFile, Position}
+import scala.tools.nsc.util.InterruptReq
/** Interface of interactive compiler to a client such as an IDE
* The model the presentation compiler consists of the following parts:
@@ -221,6 +222,7 @@ trait CompilerControl { self: Global =>
* everything is brought up to date in a regular type checker run.
* @param response The response.
*/
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
def askInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) =
postWorkItem(new AskInstrumentedItem(source, line, response))
@@ -388,6 +390,7 @@ trait CompilerControl { self: Global =>
response raise new MissingResponse
}
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
case class AskInstrumentedItem(val source: SourceFile, line: Int, response: Response[(String, Array[Char])]) extends WorkItem {
def apply() = self.getInstrumented(source, line, response)
override def toString = "getInstrumented "+source
@@ -413,6 +416,16 @@ trait CompilerControl { self: Global =>
override def doQuickly[A](op: () => A): A = {
throw new FailedInterrupt(new Exception("Posted a work item to a compiler that's shutting down"))
}
+
+ override def askDoQuickly[A](op: () => A): InterruptReq { type R = A } = {
+ val ir = new InterruptReq {
+ type R = A
+ val todo = () => throw new MissingResponse
+ }
+ ir.execute()
+ ir
+ }
+
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index ec3ed110fd..2e2c772a38 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -205,7 +205,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
protected[interactive] var minRunId = 1
- private var interruptsEnabled = true
+ private[interactive] var interruptsEnabled = true
private val NoResponse: Response[_] = new Response[Any]
@@ -1041,6 +1041,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
}
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
def getInstrumented(source: SourceFile, line: Int, response: Response[(String, Array[Char])]) {
try {
interruptsEnabled = false
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index afac5828e5..be837b32f3 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -92,6 +92,7 @@ object REPL {
val completeResult = new Response[List[comp.Member]]
val typedResult = new Response[comp.Tree]
val structureResult = new Response[comp.Tree]
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
val instrumentedResult = new Response[(String, Array[Char])]
def makePos(file: String, off1: String, off2: String) = {
@@ -124,6 +125,7 @@ object REPL {
* @param iContents An Array[Char] containing the instrumented source
* @return The name of the instrumented source file
*/
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
def writeInstrumented(iFullName: String, suffix: String, iContents: Array[Char]): String = {
val iSimpleName = iFullName drop ((iFullName lastIndexOf '.') + 1)
val iSourceName = iSimpleName + suffix
@@ -142,6 +144,7 @@ object REPL {
* and outputs in the right column, or None if the presentation compiler
* does not respond to askInstrumented.
*/
+ @deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
def instrument(arguments: List[String], line: Int): Option[(String, String)] = {
val source = toSourceFile(arguments.head)
// strip right hand side comment column and any trailing spaces from all lines
diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
index 7d332d9f7f..7f0265bf4f 100644
--- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
@@ -6,6 +6,7 @@ import scala.collection.mutable.ArrayBuffer
import scala.reflect.internal.Chars.{isLineBreakChar, isWhitespace}
import ast.parser.Tokens._
+@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
trait ScratchPadMaker { self: Global =>
import definitions._
diff --git a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
index f7ad39bd95..10e9982594 100644
--- a/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
+++ b/src/compiler/scala/tools/nsc/scratchpad/Mixer.scala
@@ -7,6 +7,7 @@ import java.lang.reflect.InvocationTargetException
import scala.reflect.runtime.ReflectionUtils._
import scala.collection.mutable.ArrayBuffer
+@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
class Mixer {
protected val stdSeparator = "//> "
diff --git a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala
index 5eeab53fca..01dccd7521 100644
--- a/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala
+++ b/src/compiler/scala/tools/nsc/scratchpad/SourceInserter.scala
@@ -5,6 +5,7 @@ import java.io.Writer
import scala.reflect.internal.util.SourceFile
import scala.reflect.internal.Chars._
+@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
object SourceInserter {
def stripRight(cs: Array[Char]): Array[Char] = {
val lines =
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 90d5a7ac75..14e5e352f7 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -56,11 +56,11 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
case OverloadedType(_, alts) =>
val index = alts indexOf imeth
assert(index >= 0, alts+" does not contain "+imeth)
- def altName(index: Int) = newTermName("extension"+index+"$"+imeth.name)
+ def altName(index: Int) = newTermName(imeth.name+"$extension"+index)
altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
case tpe =>
assert(tpe != NoType, imeth.name+" not found in "+imeth.owner+"'s decls: "+imeth.owner.info.decls)
- Stream(newTermName("extension$"+imeth.name))
+ Stream(newTermName(imeth.name+"$extension"))
}
}
@@ -68,10 +68,10 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
*/
def extensionMethod(imeth: Symbol): Symbol = enteringPhase(currentRun.refchecksPhase) {
val companionInfo = imeth.owner.companionModule.info
- val candidates = extensionNames(imeth) map (companionInfo.decl(_))
+ val candidates = extensionNames(imeth) map (companionInfo.decl(_)) filter (_.exists)
val matching = candidates filter (alt => normalize(alt.tpe, imeth.owner) matches imeth.tpe)
assert(matching.nonEmpty,
- s"no extension method found for $imeth:${imeth.tpe}+among ${candidates map (c => c.name+":"+c.tpe)} / ${extensionNames(imeth)}")
+ s"no extension method found for $imeth:${imeth.tpe} among ${candidates map (c => c.name+":"+c.tpe)} / ${extensionNames(imeth)}")
matching.head
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 2aeadb67d5..2c4034db84 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -391,6 +391,8 @@ trait Namers extends MethodSynthesis {
&& (clazz.sourceFile ne null)
&& (module.sourceFile ne null)
&& !(module isCoDefinedWith clazz)
+ && module.exists
+ && clazz.exists
)
if (fails) {
context.unit.error(tree.pos, (
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index a83787a43c..2c3ff0bfa4 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -1430,6 +1430,9 @@ trait Typers extends Modes with Adaptations with Tags {
//see https://issues.scala-lang.org/browse/SI-6463
case _: ClassDef =>
implRestriction(tree, "nested class")
+ case Select(sup @ Super(qual, mix), selector) if selector != nme.CONSTRUCTOR && qual.symbol == clazz && mix != tpnme.EMPTY =>
+ //see https://issues.scala-lang.org/browse/SI-6483
+ implRestriction(sup, "qualified super reference")
case _ =>
}
super.traverse(tree)
diff --git a/src/compiler/scala/tools/nsc/util/InterruptReq.scala b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
index 816d16f767..b1b81d0952 100644
--- a/src/compiler/scala/tools/nsc/util/InterruptReq.scala
+++ b/src/compiler/scala/tools/nsc/util/InterruptReq.scala
@@ -47,7 +47,10 @@ abstract class InterruptReq {
}
def onComplete(k: Continuation) = synchronized {
- waiting = k :: waiting
+ if (result.isDefined)
+ k(result.get)
+ else
+ waiting = k :: waiting
}
}
diff --git a/src/compiler/scala/tools/reflect/MacroImplementations.scala b/src/compiler/scala/tools/reflect/MacroImplementations.scala
index 48a4811744..86cd845c54 100644
--- a/src/compiler/scala/tools/reflect/MacroImplementations.scala
+++ b/src/compiler/scala/tools/reflect/MacroImplementations.scala
@@ -1,6 +1,6 @@
package scala.tools.reflect
-import scala.reflect.macros.{ReificationError, UnexpectedReificationError}
+import scala.reflect.macros.{ReificationException, UnexpectedReificationException}
import scala.reflect.macros.runtime.Context
import scala.collection.mutable.ListBuffer
import scala.collection.mutable.Stack
diff --git a/src/compiler/scala/tools/util/PathResolver.scala b/src/compiler/scala/tools/util/PathResolver.scala
index f6dc92f96e..7cf3586d3d 100644
--- a/src/compiler/scala/tools/util/PathResolver.scala
+++ b/src/compiler/scala/tools/util/PathResolver.scala
@@ -195,7 +195,7 @@ class PathResolver(settings: Settings, context: JavaContext) {
def scalaExtDirs = cmdLineOrElse("extdirs", Defaults.scalaExtDirs)
/** Scaladoc doesn't need any bootstrapping, otherwise will create errors such as:
* [scaladoc] ../scala-trunk/src/reflect/scala/reflect/macros/Reifiers.scala:89: error: object api is not a member of package reflect
- * [scaladoc] case class ReificationError(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg)
+ * [scaladoc] case class ReificationException(val pos: reflect.api.PositionApi, val msg: String) extends Throwable(msg)
* [scaladoc] ^
* because the bootstrapping will look at the sourcepath and create package "reflect" in "<root>"
* and then when typing relative names, instead of picking <root>.scala.relect, typedIdentifier will pick up the
diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala
index a867783455..20056bc03c 100644
--- a/src/library/scala/annotation/switch.scala
+++ b/src/library/scala/annotation/switch.scala
@@ -9,8 +9,7 @@ package scala.annotation
/** An annotation to be applied to a match expression. If present,
* the compiler will verify that the match has been compiled to a
- * [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc14.html tableswitch]]
- * or [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc8.html#lookupswitch lookupswitch]]
+ * [[http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-3.html#jvms-3.10 tableswitch or lookupswitch]]
* and issue an error if it instead compiles into a series of conditional expressions.
* Example usage:
{{{
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index ce0b130b86..7849f1c544 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -271,12 +271,7 @@ trait TraversableLike[+A, +Repr] extends Any
* @return a new $coll consisting of all elements of this $coll that do not satisfy the given
* predicate `p`. The order of the elements is preserved.
*/
- def filterNot(p: A => Boolean): Repr = {
- val b = newBuilder
- for (x <- this)
- if (!p(x)) b += x
- b.result
- }
+ def filterNot(p: A => Boolean): Repr = filter(!p(_))
def collect[B, That](pf: PartialFunction[A, B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala
index 3bd7617bce..c0c688bf42 100644
--- a/src/library/scala/concurrent/Awaitable.scala
+++ b/src/library/scala/concurrent/Awaitable.scala
@@ -14,36 +14,47 @@ import scala.concurrent.duration.Duration
+/**
+ * An object that may eventually be completed with a result value of type `T` which may be
+ * awaited using blocking methods.
+ *
+ * The [[Await]] object provides methods that allow accessing the result of an `Awaitable`
+ * by blocking the current thread until the `Awaitable` has been completed or a timeout has
+ * occurred.
+ */
trait Awaitable[+T] {
+
/**
- * Await the "resolved" state of this Awaitable.
- * This method should not be called directly.
- *
- * @param atMost
- * maximum wait time, which may be negative (no waiting is done),
- * [[Duration.Inf]] for unbounded waiting, or a finite positive
- * duration
- * @return the Awaitable itself
- * @throws InterruptedException if the wait call was interrupted
- * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
- * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
+ * Await the "completed" state of this `Awaitable`.
+ *
+ * '''''This method should not be called directly; use [[Await.ready]] instead.'''''
+ *
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return this `Awaitable`
+ * @throws InterruptedException if the current thread is interrupted while waiting
+ * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type
/**
- * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable).
- * This method should not be called directly.
- *
- * @param atMost
- * maximum wait time, which may be negative (no waiting is done),
- * [[Duration.Inf]] for unbounded waiting, or a finite positive
- * duration
- * @return the value if the Awaitable was successful within the specific maximum wait time
- * @throws InterruptedException if the wait call was interrupted
- * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
- * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
+ * Await and return the result (of type `T`) of this `Awaitable`.
+ *
+ * '''''This method should not be called directly; use [[Await.result]] instead.'''''
+ *
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the result value if the `Awaitable` is completed within the specific maximum wait time
+ * @throws InterruptedException if the current thread is interrupted while waiting
+ * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index e683732e41..c0d46df883 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -23,7 +23,7 @@ package object concurrent {
* The result becomes available once the asynchronous computation is completed.
*
* @tparam T the type of the result
- * @param body the asychronous computation
+ * @param body the asynchronous computation
* @param execctx the execution context on which the future is run
* @return the `Future` holding the result of the computation
*/
@@ -37,17 +37,15 @@ package object concurrent {
*/
def promise[T]()(implicit execctx: ExecutionContext): Promise[T] = Promise[T]()
- /** Used to designate a piece of code which potentially blocks, allowing the BlockContext to adjust the runtime's behavior.
+ /** Used to designate a piece of code which potentially blocks, allowing the current [[BlockContext]] to adjust
+ * the runtime's behavior.
* Properly marking blocking code may improve performance or avoid deadlocks.
*
- * If you have an `Awaitable` then you should use Await.result instead of `blocking`.
+ * Blocking on an [[Awaitable]] should be done using [[Await.result]] instead of `blocking`.
*
* @param body A piece of code which contains potentially blocking or long running calls.
- *
- * Calling this method may throw the following exceptions:
- * - CancellationException - if the computation was cancelled
- * - InterruptedException - in the case that a wait within the blockable object was interrupted
- * - TimeoutException - in the case that the blockable object timed out
+ * @throws `CancellationException` if the computation was cancelled
+ * @throws `InterruptedException` in the case that a wait within the blocking `body` was interrupted
*/
@throws(classOf[Exception])
def blocking[T](body: =>T): T = BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)
@@ -67,19 +65,21 @@ package concurrent {
*/
object Await {
/**
- * Await the "resolved" state of this Awaitable.
- * Invokes ready() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
- *
- * @param awaitable
- * the `Awaitable` on which `ready` is to be called
- * @param atMost
- * maximum wait time, which may be negative (no waiting is done),
- * [[Duration.Inf]] for unbounded waiting, or a finite positive
- * duration
- * @return the awaitable itself
- * @throws InterruptedException if the wait call was interrupted
- * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
- * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
+ * Await the "completed" state of an `Awaitable`.
+ *
+ * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that
+ * the underlying [[ExecutionContext]] is prepared to properly manage the blocking.
+ *
+ * @param awaitable
+ * the `Awaitable` to be awaited
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the `awaitable`
+ * @throws InterruptedException if the current thread is interrupted while waiting
+ * @throws TimeoutException if after waiting for the specified time this `Awaitable` is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
@@ -87,19 +87,21 @@ package concurrent {
blocking(awaitable.ready(atMost)(AwaitPermission))
/**
- * Await and return the result of this Awaitable, which is either of type T or a thrown exception (any Throwable).
- * Invokes result() on the awaitable, properly wrapped by a call to `scala.concurrent.blocking`.
- *
- * @param awaitable
- * the `Awaitable` on which `result` is to be called
- * @param atMost
- * maximum wait time, which may be negative (no waiting is done),
- * [[Duration.Inf]] for unbounded waiting, or a finite positive
- * duration
- * @return the value if the Awaitable was successful within the specific maximum wait time
- * @throws InterruptedException if the wait call was interrupted
- * @throws TimeoutException if after waiting for the specified time this Awaitable is still not ready
- * @throws IllegalArgumentException if `atMost` is [[Duration.Undefined]]
+ * Await and return the result (of type `T`) of an `Awaitable`.
+ *
+ * Although this method is blocking, the internal use of [[scala.concurrent.blocking blocking]] ensures that
+ * the underlying [[ExecutionContext]] to properly detect blocking and ensure that there are no deadlocks.
+ *
+ * @param awaitable
+ * the `Awaitable` to be awaited
+ * @param atMost
+ * maximum wait time, which may be negative (no waiting is done),
+ * [[scala.concurrent.duration.Duration.Inf Duration.Inf]] for unbounded waiting, or a finite positive
+ * duration
+ * @return the result value if `awaitable` is completed within the specific maximum wait time
+ * @throws InterruptedException if the current thread is interrupted while waiting
+ * @throws TimeoutException if after waiting for the specified time `awaitable` is still not ready
+ * @throws IllegalArgumentException if `atMost` is [[scala.concurrent.duration.Duration.Undefined Duration.Undefined]]
*/
@throws(classOf[Exception])
def result[T](awaitable: Awaitable[T], atMost: Duration): T =
diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala
index a41cdedfa9..fbb98d0582 100644
--- a/src/library/scala/package.scala
+++ b/src/library/scala/package.scala
@@ -95,7 +95,10 @@ package object scala {
val Equiv = scala.math.Equiv
type Fractional[T] = scala.math.Fractional[T]
+ val Fractional = scala.math.Fractional
+
type Integral[T] = scala.math.Integral[T]
+ val Integral = scala.math.Integral
type Numeric[T] = scala.math.Numeric[T]
val Numeric = scala.math.Numeric
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 5c2067a548..d699e34ffc 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -5,19 +5,34 @@ import java.lang.{ Class => jClass }
import scala.language.{implicitConversions, existentials}
import scala.runtime.ScalaRunTime.{ arrayClass, arrayElementClass }
-/** A `ClassTag[T]` wraps a runtime class (the erasure) and can create array instances.
+/**
+ *
+ * A `ClassTag[T]` stores the erased class of a given type `T`, accessible via the `runtimeClass`
+ * field. This is particularly useful for instantiating `Array`s whose element types are unknown
+ * at compile time.
+ *
+ * `ClassTag`s are a weaker special case of [[scala.reflect.api.TypeTags#TypeTag]]s, in that they
+ * wrap only the runtime class of a given type, whereas a `TypeTag` contains all static type
+ * information. That is, `ClassTag`s are constructed from knowing only the top-level class of a
+ * type, without necessarily knowing all of its argument types. This runtime information is enough
+ * for runtime `Array` creation.
*
- * If an implicit value of type ClassTag[T] is requested, the compiler will create one.
- * The runtime class (i.e. the erasure, a java.lang.Class on the JVM) of T can be accessed
- * via the `runtimeClass` field. References to type parameters or abstract type members are
- * replaced by the concrete types if ClassTags are available for them.
+ * For example:
+ * {{{
+ * scala> def mkArray[T : ClassTag](elems: T*) = Array[T](elems: _*)
+ * mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
*
- * Besides accessing the erasure, a ClassTag knows how to instantiate single- and multi-
- * dimensional `Arrays` where the element type is unknown at compile time.
+ * scala> mkArray(42, 13)
+ * res0: Array[Int] = Array(42, 13)
*
- * [[scala.reflect.ClassTag]] corresponds to a previous concept of [[scala.reflect.ClassManifest]].
+ * scala> mkArray("Japan","Brazil","Germany")
+ * res1: Array[String] = Array(Japan, Brazil, Germany)
+ * }}}
+ *
+ * See [[scala.reflect.api.TypeTags]] for more examples, or the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
+ * for more details.
*
- * @see [[scala.reflect.api.TypeTags]]
*/
@scala.annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serializable {
@@ -29,7 +44,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
*/
def runtimeClass: jClass[_]
- /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
+ /** Produces a `ClassTag` that knows how to instantiate an `Array[Array[T]]` */
def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(runtimeClass))
/** Produces a new array with element type `T` and length `len` */
diff --git a/src/library/scala/runtime/WorksheetSupport.scala b/src/library/scala/runtime/WorksheetSupport.scala
index a003bba034..016a0d04e0 100644
--- a/src/library/scala/runtime/WorksheetSupport.scala
+++ b/src/library/scala/runtime/WorksheetSupport.scala
@@ -4,6 +4,7 @@ import scala.runtime.ScalaRunTime.stringOf
/** A utility object that's needed by the code that executes a worksheet.
*/
+@deprecated("SI-6458: Instrumentation logic will be moved out of the compiler.","2.10.0")
object WorksheetSupport {
/** The offset in the source which should be printed */
diff --git a/src/reflect/scala/reflect/api/Annotations.scala b/src/reflect/scala/reflect/api/Annotations.scala
index 37882a9f3c..fb353a5520 100644
--- a/src/reflect/scala/reflect/api/Annotations.scala
+++ b/src/reflect/scala/reflect/api/Annotations.scala
@@ -3,122 +3,195 @@ package api
import scala.collection.immutable.ListMap
-/**
- * Defines the type hierarchy for annotations.
+/** This trait provides annotation support for the reflection API.
+ *
+ * The API distinguishes between two kinds of annotations:
+ *
+ * <ul>
+ * <li>''Java annotations'': annotations on definitions produced by the Java compiler, i.e., subtypes of [[java.lang.annotation.Annotation]]
+ * attached to program definitions. When read by Scala reflection, the [[scala.annotation.ClassfileAnnotation]] trait
+ * is automatically added as a subclass to every Java annotation.</li>
+ * <li>''Scala annotations'': annotations on definitions or types produced by the Scala compiler.</li>
+ * </ul>
+ *
+ * When a Scala annotation that inherits from [[scala.annotation.StaticAnnotation]] or [[scala.annotation.ClassfileAnnotation]] is compiled,
+ * it is stored as special attributes in the corresponding classfile, and not as a Java annotation. Note that subclassing
+ * just [[scala.annotation.Annotation]] is not enough to have the corresponding metadata persisted for runtime reflection.
+ *
+ * The distinction between Java and Scala annotations is manifested in the contract of [[scala.reflect.api.Annotations#Annotation]], which exposes
+ * both `scalaArgs` and `javaArgs`. For Scala or Java annotations extending [[scala.annotation.ClassfileAnnotation]] `scalaArgs` is empty
+ * and arguments are stored in `javaArgs`. For all other Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty.
+ *
+ * Arguments in `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases
+ * following the type-checker. Arguments in `javaArgs` are repesented as a map from [[scala.reflect.api.Names#Name]] to
+ * [[scala.reflect.api.Annotations#JavaArgument]]. Instances of `JavaArgument` represent different kinds of Java annotation arguments:
+ * - literals (primitive and string constants),
+ * - arrays and
+ * - nested annotations.
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Annotations { self: Universe =>
- /** Typed information about an annotation. It can be attached to either a symbol or an annotated type.
- *
- * Annotations are either ''Scala annotations'', which conform to [[scala.annotation.StaticAnnotation]]
- * or ''Java annotations'', which conform to [[scala.annotation.ClassfileAnnotation]].
- * Trait `ClassfileAnnotation` is automatically added to every Java annotation by the scalac classfile parser.
+ /** Information about an annotation.
+ * @template
+ * @group Annotations
*/
type Annotation >: Null <: AnyRef with AnnotationApi
/** A tag that preserves the identity of the `Annotation` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotationTag: ClassTag[Annotation]
- /** The constructor/deconstructor for `Annotation` instances. */
+ /** The constructor/deconstructor for `Annotation` instances.
+ * @group Extractors
+ */
val Annotation: AnnotationExtractor
- /** An extractor class to create and pattern match with syntax `Annotation(atp, scalaArgs, javaArgs)`.
- * Here, `atp` is the annotation type, `scalaArgs` the arguments, and `javaArgs` the annotation's key-value
- * pairs.
- *
- * Annotations are pickled, i.e. written to scala symtab attribute in the classfile.
- * Annotations are written to the classfile as Java annotations if `atp` conforms to `ClassfileAnnotation`.
- *
- * For Scala annotations, arguments are stored in `scalaArgs` and `javaArgs` is empty. Arguments in
- * `scalaArgs` are represented as typed trees. Note that these trees are not transformed by any phases
- * following the type-checker. For Java annotations, `scalaArgs` is empty and arguments are stored in
- * `javaArgs`.
- */
+ /** An extractor class to create and pattern match with syntax `Annotation(tpe, scalaArgs, javaArgs)`.
+ * Here, `tpe` is the annotation type, `scalaArgs` the payload of Scala annotations, and `javaArgs` the payload of Java annotations.
+ * @group Extractors
+ */
abstract class AnnotationExtractor {
def apply(tpe: Type, scalaArgs: List[Tree], javaArgs: ListMap[Name, JavaArgument]): Annotation
def unapply(ann: Annotation): Option[(Type, List[Tree], ListMap[Name, JavaArgument])]
}
+ /** The API of `Annotation` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait AnnotationApi {
+ /** The type of the annotation. */
def tpe: Type
+
+ /** Payload of the Scala annotation: a list of abstract syntax trees that represent the argument.
+ * Empty for Java annotations.
+ */
def scalaArgs: List[Tree]
+
+ /** Payload of the Java annotation: a list of name-value pairs.
+ * Empty for Scala annotations.
+ */
def javaArgs: ListMap[Name, JavaArgument]
}
- /** A Java annotation argument */
+ /** A Java annotation argument
+ * @template
+ * @group Annotations
+ */
type JavaArgument >: Null <: AnyRef
+
+ /** A tag that preserves the identity of the `JavaArgument` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val JavaArgumentTag: ClassTag[JavaArgument]
- /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`*/
+ /** A literal argument to a Java annotation as `"Use X instead"` in `@Deprecated("Use X instead")`
+ * @template
+ * @group Annotations
+ */
type LiteralArgument >: Null <: AnyRef with JavaArgument with LiteralArgumentApi
/** A tag that preserves the identity of the `LiteralArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LiteralArgumentTag: ClassTag[LiteralArgument]
- /** The constructor/deconstructor for `LiteralArgument` instances. */
+ /** The constructor/deconstructor for `LiteralArgument` instances.
+ * @group Extractors
+ */
val LiteralArgument: LiteralArgumentExtractor
/** An extractor class to create and pattern match with syntax `LiteralArgument(value)`
* where `value` is the constant argument.
+ * @group Extractors
*/
abstract class LiteralArgumentExtractor {
def apply(value: Constant): LiteralArgument
def unapply(arg: LiteralArgument): Option[Constant]
}
+ /** The API of `LiteralArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait LiteralArgumentApi {
+ /** The underlying compile-time constant value. */
def value: Constant
}
/** An array argument to a Java annotation as in `@Target(value={TYPE,FIELD,METHOD,PARAMETER})`
+ * @template
+ * @group Annotations
*/
type ArrayArgument >: Null <: AnyRef with JavaArgument with ArrayArgumentApi
/** A tag that preserves the identity of the `ArrayArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ArrayArgumentTag: ClassTag[ArrayArgument]
- /** The constructor/deconstructor for `ArrayArgument` instances. */
+ /** The constructor/deconstructor for `ArrayArgument` instances.
+ * @group Extractors
+ */
val ArrayArgument: ArrayArgumentExtractor
/** An extractor class to create and pattern match with syntax `ArrayArgument(args)`
* where `args` is the argument array.
+ * @group Extractors
*/
abstract class ArrayArgumentExtractor {
def apply(args: Array[JavaArgument]): ArrayArgument
def unapply(arg: ArrayArgument): Option[Array[JavaArgument]]
}
+ /** API of `ArrayArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait ArrayArgumentApi {
+ /** The underlying array of Java annotation arguments. */
def args: Array[JavaArgument]
}
/** A nested annotation argument to a Java annotation as `@Nested` in `@Outer(@Nested)`.
+ * @template
+ * @group Annotations
*/
type NestedArgument >: Null <: AnyRef with JavaArgument with NestedArgumentApi
/** A tag that preserves the identity of the `NestedArgument` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NestedArgumentTag: ClassTag[NestedArgument]
- /** The constructor/deconstructor for `NestedArgument` instances. */
+ /** The constructor/deconstructor for `NestedArgument` instances.
+ * @group Extractors
+ */
val NestedArgument: NestedArgumentExtractor
/** An extractor class to create and pattern match with syntax `NestedArgument(annotation)`
* where `annotation` is the nested annotation.
+ * @group Extractors
*/
abstract class NestedArgumentExtractor {
def apply(annotation: Annotation): NestedArgument
def unapply(arg: NestedArgument): Option[Annotation]
}
+ /** API of `NestedArgument` instances.
+ * The main source of information about annotations is the [[scala.reflect.api.Annotations]] page.
+ * @group API
+ */
trait NestedArgumentApi {
+ /** The underlying nested annotation. */
def annotation: Annotation
}
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index b0de7f8d5a..0c8e81a220 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -3,15 +3,18 @@ package api
/**
* This is an internal implementation class.
+ * @groupname TreeBuilders Tree Building
*/
private[reflect] trait BuildUtils { self: Universe =>
+ /** @group TreeBuilders */
val build: BuildApi
// this API abstracts away the functionality necessary for reification
// it's too gimmicky and unstructured to be exposed directly in the universe
// but we need it in a publicly available place for reification to work
+ /** @group TreeBuilders */
abstract class BuildApi {
/** Selects type symbol with given simple name `name` from the defined members of `owner`.
*/
diff --git a/src/reflect/scala/reflect/api/Constants.scala b/src/reflect/scala/reflect/api/Constants.scala
index f2d8ef2eb9..a92fc5cbb3 100644
--- a/src/reflect/scala/reflect/api/Constants.scala
+++ b/src/reflect/scala/reflect/api/Constants.scala
@@ -7,50 +7,214 @@ package scala.reflect
package api
/**
- * Defines the type hierachy for compile-time constants.
+ * According to the section 6.24 "Constant Expressions" of the Scala language specification,
+ * certain expressions (dubbed ''constant expressions'') can be evaluated by the Scala compiler at compile-time.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * [[scala.reflect.api.Constants#Constant]] instances represent certain kinds of these expressions
+ * (with values stored in the `value` field and its strongly-typed views named `booleanValue`, `intValue` etc.), namely:
+ * 1. Literals of primitive value classes (bytes, shorts, ints, longs, floats, doubles, chars, booleans and voids).
+ * 1. String literals.
+ * 1. References to classes (typically constructed with [[scala.Predef#classOf]]).
+ * 1. References to enumeration values.
+ *
+ * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node)
+ * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class).
+ *
+ * === Example ===
+ *
+ * The `value` field deserves some explanation. Primitive and string values are represented as themselves, whereas
+ * references to classes and enums are a bit roundabout.
+ *
+ * Class references are represented as instances of [[scala.reflect.api.Types#Type]]
+ * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have been compiled).
+ * To convert such a reference to a runtime class, one should use the `runtimeClass` method of a mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror]]
+ * (the simplest way to get such a mirror is using [[scala.reflect.runtime.package#currentMirror]]).
+ *
+ * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods
+ * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum,
+ * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]).
+
+ * {{{
+ * enum JavaSimpleEnumeration { FOO, BAR }
+ *
+ * import java.lang.annotation.*;
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @Target({ElementType.TYPE})
+ * public @interface JavaSimpleAnnotation {
+ * Class<?> classRef();
+ * JavaSimpleEnumeration enumRef();
+ * }
+ *
+ * @JavaSimpleAnnotation(
+ * classRef = JavaAnnottee.class,
+ * enumRef = JavaSimpleEnumeration.BAR
+ * )
+ * public class JavaAnnottee {}
+ * }}}
+ * {{{
+ * import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.{currentMirror => cm}
+ *
+ * object Test extends App {
+ * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs
+ * def jarg(name: String) = jann(newTermName(name)).asInstanceOf[LiteralArgument].value
+ *
+ * val classRef = jarg("classRef").typeValue
+ * println(showRaw(classRef)) // TypeRef(ThisType(<empty>), JavaAnnottee, List())
+ * println(cm.runtimeClass(classRef)) // class JavaAnnottee
+ *
+ * val enumRef = jarg("enumRef").symbolValue
+ * println(enumRef) // value BAR
+ *
+ * val siblings = enumRef.owner.typeSignature.declarations
+ * val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic)
+ * println(enumValues) // Scope{
+ * // final val FOO: JavaSimpleEnumeration;
+ * // final val BAR: JavaSimpleEnumeration
+ * // }
+ *
+ * // doesn't work because of https://issues.scala-lang.org/browse/SI-6459
+ * // val enumValue = mirror.reflectField(enumRef.asTerm).get
+ * val enumClass = cm.runtimeClass(enumRef.owner.asClass)
+ * val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null)
+ * println(enumValue) // BAR
+ * }
+ * }}}
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Constants {
self: Universe =>
- /** The type of compile-time constants.
+ /**
+ * This "virtual" case class represents the reflection interface for literal expressions which can not be further
+ * broken down or evaluated, such as "true", "0", "classOf[List]". Such values become parts of the Scala abstract
+ * syntax tree representing the program. The constants
+ * correspond to section 6.24 "Constant Expressions" of the
+ * [[http://www.scala-lang.org/docu/files/ScalaReference.pdf Scala language specification]].
+ *
+ * Such constants are used to represent literals in abstract syntax trees (the [[scala.reflect.api.Trees#Literal]] node)
+ * and literal arguments for Java class file annotations (the [[scala.reflect.api.Annotations#LiteralArgument]] class).
+ *
+ * Constants can be matched against and can be constructed directly, as if they were case classes:
+ * {{{
+ * assert(Constant(true).value == true)
+ * Constant(true) match {
+ * case Constant(s: String) => println("A string: " + s)
+ * case Constant(b: Boolean) => println("A boolean value: " + b)
+ * case Constant(x) => println("Something else: " + x)
+ * }
+ * }}}
+ *
+ * `Constant` instances can wrap certain kinds of these expressions:
+ * 1. Literals of primitive value classes ([[scala.Byte `Byte`]], [[scala.Short `Short`]], [[scala.Int `Int`]], [[scala.Long `Long`]], [[scala.Float `Float`]], [[scala.Double `Double`]], [[scala.Char `Char`]], [[scala.Boolean `Boolean`]] and [[scala.Unit `Unit`]]) - represented directly as the corresponding type
+ * 1. String literals - represented as instances of the `String`.
+ * 1. References to classes, typically constructed with [[scala.Predef#classOf]] - represented as [[scala.reflect.api.Types#Type types]].
+ * 1. References to enumeration values - represented as [[scala.reflect.api.Symbols#Symbol symbols]].
+ *
+ * Class references are represented as instances of [[scala.reflect.api.Types#Type]]
+ * (because when the Scala compiler processes a class reference, the underlying runtime class might not yet have
+ * been compiled). To convert such a reference to a runtime class, one should use the [[scala.reflect.api.Mirrors#RuntimeMirror#runtimeClass `runtimeClass`]] method of a
+ * mirror such as [[scala.reflect.api.Mirrors#RuntimeMirror `RuntimeMirror`]] (the simplest way to get such a mirror is using
+ * [[scala.reflect.runtime#currentMirror `scala.reflect.runtime.currentMirror`]]).
+ *
+ * Enumeration value references are represented as instances of [[scala.reflect.api.Symbols#Symbol]], which on JVM point to methods
+ * that return underlying enum values. To inspect an underlying enumeration or to get runtime value of a reference to an enum,
+ * one should use a [[scala.reflect.api.Mirrors#RuntimeMirror]] (the simplest way to get such a mirror is again [[scala.reflect.runtime.package#currentMirror]]).
+ *
+ * Usage example:
+ * {{{
+ * enum JavaSimpleEnumeration { FOO, BAR }
+ *
+ * import java.lang.annotation.*;
+ * @Retention(RetentionPolicy.RUNTIME)
+ * @Target({ElementType.TYPE})
+ * public @interface JavaSimpleAnnotation {
+ * Class<?> classRef();
+ * JavaSimpleEnumeration enumRef();
+ * }
+ *
+ * @JavaSimpleAnnotation(
+ * classRef = JavaAnnottee.class,
+ * enumRef = JavaSimpleEnumeration.BAR
+ * )
+ * public class JavaAnnottee {}
+ * }}}
+ * {{{
+ * import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.{currentMirror => cm}
+ *
+ * object Test extends App {
+ * val jann = typeOf[JavaAnnottee].typeSymbol.annotations(0).javaArgs
+ * def jarg(name: String) = jann(newTermName(name)) match {
+ * // Constant is always wrapped into a Literal or LiteralArgument tree node
+ * case LiteralArgument(ct: Constant) => value
+ * case _ => sys.error("Not a constant")
+ * }
+ *
+ * val classRef = jarg("classRef").value.asInstanceOf[Type]
+ * // ideally one should match instead of casting
+ * println(showRaw(classRef)) // TypeRef(ThisType(<empty>), JavaAnnottee, List())
+ * println(cm.runtimeClass(classRef)) // class JavaAnnottee
+ *
+ * val enumRef = jarg("enumRef").value.asInstanceOf[Symbol]
+ * // ideally one should match instead of casting
+ * println(enumRef) // value BAR
+ *
+ * val siblings = enumRef.owner.typeSignature.declarations
+ * val enumValues = siblings.filter(sym => sym.isVal && sym.isPublic)
+ * println(enumValues) // Scope{
+ * // final val FOO: JavaSimpleEnumeration;
+ * // final val BAR: JavaSimpleEnumeration
+ * // }
+ *
+ * // doesn't work because of https://issues.scala-lang.org/browse/SI-6459
+ * // val enumValue = mirror.reflectField(enumRef.asTerm).get
+ * val enumClass = cm.runtimeClass(enumRef.owner.asClass)
+ * val enumValue = enumClass.getDeclaredField(enumRef.name.toString).get(null)
+ * println(enumValue) // BAR
+ * }
+ * }}}
+ * @template
+ * @group Constants
*/
type Constant >: Null <: AnyRef with ConstantApi
/** A tag that preserves the identity of the `Constant` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ConstantTag: ClassTag[Constant]
- /** The constructor/deconstructor for `Constant` instances. */
+ /** The constructor/deconstructor for `Constant` instances.
+ * @group Extractors
+ */
val Constant: ConstantExtractor
/** An extractor class to create and pattern match with syntax `Constant(value)`
* where `value` is the Scala value of the constant.
+ * @group Extractors
*/
abstract class ConstantExtractor {
+ /** A factory method that produces [[Constant `Constant`]] instances.
+ *
+ * Notice that not any value can be passed to a constant: it must be either a primitive, a `String`, a
+ * [[scala.reflect.api.Types#Type type]] or a [[scala.reflect.api.Symbols#Symbol symbol]].
+ * See [[Constant the `Constant` class]] for more information.
+ */
def apply(value: Any): Constant
+ /** An extractor that enables writing pattern matches against the [[Constant `Constant`]] class. */
def unapply(arg: Constant): Option[Any]
}
+ /** The API of [[Constant]] instances.
+ * @group API
+ */
abstract class ConstantApi {
+ /** Payload of the constant, that can be accessed directly or pattern matched against. */
val value: Any
+
+ /** Scala type that describes the constant. It is generated automatically based on the type of the value. */
def tpe: Type
- def isNaN: Boolean
-
- def booleanValue: Boolean
- def byteValue: Byte
- def shortValue: Short
- def charValue: Char
- def intValue: Int
- def longValue: Long
- def floatValue: Float
- def doubleValue: Double
- def stringValue: String
- def typeValue: Type
- def symbolValue: Symbol
-
- def convertTo(pt: Type): Constant
}
}
diff --git a/src/reflect/scala/reflect/api/Exprs.scala b/src/reflect/scala/reflect/api/Exprs.scala
index b86f36420d..45bfddb55d 100644
--- a/src/reflect/scala/reflect/api/Exprs.scala
+++ b/src/reflect/scala/reflect/api/Exprs.scala
@@ -8,9 +8,29 @@ package api
import scala.reflect.runtime.{universe => ru}
+/** A trait that defines strongly-typed tree wrappers and operations on them for use in Scala Reflection.
+ *
+ * `Expr` wraps an abstract syntax tree ([[scala.reflect.api.Trees#Tree]]) and tags it with its type ([[scala.reflect.api.Types#Type]]).
+ *
+ * Usually `Expr`s are created via [[scala.reflect.api.Universe#reify]], in which case a compiler
+ * produces a [[scala.reflect.api.TreeCreator]] for the provided expression and also
+ * creates a complementary [[scala.reflect.api.TypeTags#WeakTypeTag]] that corresponds to the type of that expression.
+ *
+ * `Expr`s can also be created manually via the `Expr` companion object, but then the burden of providing a `TreeCreator` lies on the programmer.
+ * Compile-time reflection via macros, as described in [[scala.reflect.macros.Aliases]], provides an easier way to instantiate exprs manually.
+ * Manual creation, however, is very rarely needed when working with runtime reflection.
+ *
+ * `Expr` can be migrated from one mirror to another by using the `in` method. Migration means that all symbolic references
+ * to classes/objects/packages in the expression are re-resolved within the new mirror
+ * (typically using that mirror's classloader). The default universe of an `Expr` is typically
+ * [[scala.reflect.runtime#universe]], the default mirror is typically [[scala.reflect.runtime#currentMirror]].
+ */
trait Exprs { self: Universe =>
- /** Expr wraps an expression tree and tags it with its type. */
+ /** Expr wraps an abstract syntax tree and tags it with its type.
+ * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page.
+ * @group Expressions
+ */
trait Expr[+T] extends Equals with Serializable {
/**
* Underlying mirror of this expr.
@@ -19,23 +39,24 @@ trait Exprs { self: Universe =>
/**
* Migrates the expression into another mirror, jumping into a different universe if necessary.
- *
- * This means that all symbolic references to classes/objects/packages in the expression
- * will be re-resolved within the new mirror (typically using that mirror's classloader).
*/
def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # Expr[T]
/**
- * The Scala syntax tree representing the wrapped expression.
+ * The Scala abstract syntax tree representing the wrapped expression.
*/
def tree: Tree
/**
- * Representation of the type of the wrapped expression tree as found via type tags.
+ * Type of the wrapped expression tree as provided during creation.
+ *
+ * When exprs are created by the compiler, `staticType` represents
+ * a statically known type of the tree as calculated at that point by the compiler.
*/
def staticType: Type
+
/**
- * Representation of the type of the wrapped expression tree as found in the tree.
+ * Type of the wrapped expression tree as found in the underlying tree.
*/
def actualType: Type
@@ -65,6 +86,7 @@ trait Exprs { self: Universe =>
* because expr of type Expr[T] itself does not have a method foo.
*/
def splice: T
+
/**
* A dummy value to denote cross-stage path-dependent type dependencies.
*
@@ -81,10 +103,16 @@ trait Exprs { self: Universe =>
*/
val value: T
- /** case class accessories */
+ /** TODO how do I doc this? */
override def canEqual(x: Any) = x.isInstanceOf[Expr[_]]
+
+ /** TODO how do I doc this? */
override def equals(x: Any) = x.isInstanceOf[Expr[_]] && this.mirror == x.asInstanceOf[Expr[_]].mirror && this.tree == x.asInstanceOf[Expr[_]].tree
+
+ /** TODO how do I doc this? */
override def hashCode = mirror.hashCode * 31 + tree.hashCode
+
+ /** TODO how do I doc this? */
override def toString = "Expr["+staticType+"]("+tree+")"
}
@@ -93,6 +121,9 @@ trait Exprs { self: Universe =>
*
* Can be useful, when having a tree and wanting to splice it in reify call,
* in which case the tree first needs to be wrapped in an expr.
+
+ * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page.
+ * @group Expressions
*/
object Expr {
def apply[T: WeakTypeTag](mirror: scala.reflect.api.Mirror[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec)
diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala
index 599c4ca426..a7d1ca05a6 100644
--- a/src/reflect/scala/reflect/api/FlagSets.scala
+++ b/src/reflect/scala/reflect/api/FlagSets.scala
@@ -3,32 +3,95 @@ package api
import scala.language.implicitConversions
+/**
+ * The trait that defines flag sets and operations on them.
+ *
+ * `Flag`s are used to provide modifiers for abstract syntax trees that represent definitions
+ * via the `flags` field of [[scala.reflect.api.Trees#Modifiers]]. Trees that accept modifiers are:
+ *
+ * - '''[[scala.reflect.api.Trees#ClassDef]]'''. Classes and traits.
+ * - '''[[scala.reflect.api.Trees#ModuleDef]]'''. Objects.
+ * - '''[[scala.reflect.api.Trees#ValDef]]'''. Vals, vars, parameters and self-type annotations.
+ * - '''[[scala.reflect.api.Trees#DefDef]]'''. Methods and constructors.
+ * - '''[[scala.reflect.api.Trees#TypeDef]]'''. Type aliases, abstract type members and type parameters.
+ *
+ * For example, to create a class named `C` one would write something like:
+ * {{{
+ * ClassDef(Modifiers(NoFlags), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * Here, the flag set is empty.
+ *
+ * To make `C` private, one would write something like:
+ * {{{
+ * ClassDef(Modifiers(PRIVATE), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * Flags can also be combined with the vertical bar operator (`|`).
+ * For example, a private final class is written something like:
+ * {{{
+ * ClassDef(Modifiers(PRIVATE | FINAL), newTypeName("C"), Nil, ...)
+ * }}}
+ *
+ * The list of all available flags is defined in [[scala.reflect.api.FlagSets#FlagValues]], available via
+ * [[scala.reflect.api.FlagSets#Flag]]. (Typically one writes a blanket import for this, e.g.
+ * `import scala.reflect.runtime.universe.Flag._`).
+ *
+ * Definition trees are compiled down to symbols, so flags on modifiers of these trees are transformed into flags
+ * on the resulting symbols. Unlike trees, symbols don't expose flags, but rather provide `isXXX` test methods
+ * (e.g. `isFinal` can be used to test finality). These test methods might require an upcast with `asTerm`,
+ * `asType` or `asClass` as some flags only make sense for certain kinds of symbols.
+ *
+ * ''Of Note:'' This part of the Reflection API is being considered as a candidate for redesign. It is
+ * quite possible that in future releases of the reflection API, flag sets could be replaced with something else.
+ *
+ * For more details about `FlagSet`s and other aspects of Scala reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ */
trait FlagSets { self: Universe =>
- /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols */
+ /** An abstract type representing sets of flags (like private, final, etc.) that apply to definition trees and symbols
+ * @template
+ * @group Flags
+ */
type FlagSet
/** A tag that preserves the identity of the `FlagSet` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FlagSetTag: ClassTag[FlagSet]
+ /** The API of `FlagSet` instances.
+ * The main source of information about flag sets is the [[scala.reflect.api.FlagSets]] page.
+ * @group Flags
+ */
trait FlagOps extends Any {
+ /** Produces a flag set that's a union of this flag set and the provided flag set. */
def | (right: FlagSet): FlagSet
}
+ /** The API of `FlagSet` instances.
+ * @group Flags
+ */
implicit def addFlagOps(left: FlagSet): FlagOps
+ /** A module that contains all possible values that can constitute flag sets.
+ * @group Flags
+ */
val Flag: FlagValues
- type FlagValues >: Null <: FlagValuesApi
-
// Q: I have a pretty flag. Can I put it here?
// A: Only if there's a tree that cannot be built without it.
// If you want to put a flag here so that it can be tested against,
// introduce an `isXXX` method in one of the `api.Symbols` classes instead.
- trait FlagValuesApi {
+ /** All possible values that can constitute flag sets.
+ * The main source of information about flag sets is the [[scala.reflect.api.FlagSets]] page.
+ * @group Flags
+ */
+ trait FlagValues {
/** Flag indicating that tree represents a trait */
val TRAIT: FlagSet
@@ -106,6 +169,8 @@ trait FlagSets { self: Universe =>
val DEFAULTINIT: FlagSet
}
- /** The empty set of flags */
+ /** The empty set of flags
+ * @group Flags
+ */
val NoFlags: FlagSet
}
diff --git a/src/reflect/scala/reflect/api/Importers.scala b/src/reflect/scala/reflect/api/Importers.scala
index fbc29a514e..4286b2b45c 100644
--- a/src/reflect/scala/reflect/api/Importers.scala
+++ b/src/reflect/scala/reflect/api/Importers.scala
@@ -1,21 +1,97 @@
package scala.reflect
package api
+/** This trait provides support for importers, a facility to migrate reflection artifacts between universes.
+ *
+ * Reflection artifacts, such as [[scala.reflect.api.Symbols Symbols]] and [[scala.reflect.api.Types Types]],
+ * are contained in [[scala.reflect.api.Universes Universe]]s. Typically all processing happens
+ * within a single `Universe` (e.g. a compile-time macro `Universe` or a runtime reflection `Universe`), but sometimes
+ * there is a need to migrate artifacts from one `Universe` to another. For example, runtime compilation works by
+ * importing runtime reflection trees into a runtime compiler universe, compiling the importees and exporting the
+ * result back.
+ *
+ * Reflection artifacts are firmly grounded in their `Universe`s, which is reflected by the fact that types of artifacts
+ * from different universes are not compatible. By using `Importer`s, however, they be imported from one universe
+ * into another. For example, to import `foo.bar.Baz` from the source `Universe` to the target `Universe`,
+ * an importer will first check whether the entire owner chain exists in the target `Universe`.
+ * If it does, then nothing else will be done. Otherwise, the importer will recreate the entire owner chain
+ * and will import the corresponding type signatures into the target `Universe`.
+ *
+ * Since importers match `Symbol` tables of the source and the target `Universe`s using plain string names,
+ * it is programmer's responsibility to make sure that imports don't distort semantics, e.g., that
+ * `foo.bar.Baz` in the source `Universe` means the same that `foo.bar.Baz` does in the target `Universe`.
+ *
+ * === Example ===
+ *
+ * Here's how one might implement a macro that performs compile-time evaluation of its argument
+ * by using a runtime compiler to compile and evaluate a tree that belongs to a compile-time compiler:
+ *
+ * {{{
+ * def staticEval[T](x: T) = macro staticEval[T]
+ *
+ * def staticEval[T](c: scala.reflect.macros.Context)(x: c.Expr[T]) = {
+ * // creates a runtime reflection universe to host runtime compilation
+ * import scala.reflect.runtime.{universe => ru}
+ * val mirror = ru.runtimeMirror(c.libraryClassLoader)
+ * import scala.tools.reflect.ToolBox
+ * val toolBox = mirror.mkToolBox()
+ *
+ * // runtime reflection universe and compile-time macro universe are different
+ * // therefore an importer is needed to bridge them
+ * // currently mkImporter requires a cast to correctly assign the path-dependent types
+ * val importer0 = ru.mkImporter(c.universe)
+ * val importer = importer0.asInstanceOf[ru.Importer { val from: c.universe.type }]
+ *
+ * // the created importer is used to turn a compiler tree into a runtime compiler tree
+ * // both compilers use the same classpath, so semantics remains intact
+ * val imported = importer.importTree(tree)
+ *
+ * // after the tree is imported, it can be evaluated as usual
+ * val tree = toolBox.resetAllAttrs(imported.duplicate)
+ * val valueOfX = toolBox.eval(imported).asInstanceOf[T]
+ * ...
+ * }
+ * }}}
+ */
trait Importers { self: Universe =>
+ /** Creates an importer that moves reflection artifacts between universes.
+ * @group Importers
+ */
def mkImporter(from0: Universe): Importer { val from: from0.type }
+ /** The API of importers.
+ * The main source of information about importers is the [[scala.reflect.api.Importers]] page.
+ * @group Importers
+ */
trait Importer {
+ /** The source universe of reflection artifacts that will be processed.
+ * The target universe is universe that created this importer with `mkImporter`.
+ */
val from: Universe
+ /** An importer that works in reverse direction, namely:
+ * imports reflection artifacts from the current universe to the universe specified in `from`.
+ */
val reverse: from.Importer { val from: self.type }
+ /** In the current universe, locates or creates a symbol that corresponds to the provided symbol in the source universe.
+ * If necessary imports the owner chain, companions, type signature, annotations and attachments.
+ */
def importSymbol(sym: from.Symbol): Symbol
+ /** In the current universe, locates or creates a type that corresponds to the provided type in the source universe.
+ * If necessary imports the underlying symbols, annotations, scopes and trees.
+ */
def importType(tpe: from.Type): Type
+ /** In the current universe, creates a tree that corresponds to the provided tree in the source universe.
+ * If necessary imports the underlying symbols, types and attachments.
+ */
def importTree(tree: from.Tree): Tree
+ /** In the current universe, creates a position that corresponds to the provided position in the source universe.
+ */
def importPosition(pos: from.Position): Position
}
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/JavaMirrors.scala b/src/reflect/scala/reflect/api/JavaMirrors.scala
new file mode 100644
index 0000000000..df099006b5
--- /dev/null
+++ b/src/reflect/scala/reflect/api/JavaMirrors.scala
@@ -0,0 +1,52 @@
+package scala.reflect
+package api
+
+/** A refinement of [[scala.reflect.api.Mirror]] for runtime reflection using JVM classloaders.
+ *
+ * This refinement equips mirrors with reflection capabilities for the JVM. `JavaMirror` can
+ * convert Scala reflection artifacts (symbols and types) into Java reflection artifacts (classes)
+ * and vice versa. It can also perform reflective invocations (getting/setting field values,
+ * calling methods, etc).
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @groupname JavaMirrors Java Mirrors
+ */
+trait JavaMirrors { self: JavaUniverse =>
+
+ /** In runtime reflection universes, runtime representation of a class is `java.lang.Class`.
+ * @group JavaMirrors
+ */
+ type RuntimeClass = java.lang.Class[_]
+
+ /** In runtime reflection universes, mirrors are `JavaMirrors`.
+ * @group JavaMirrors
+ */
+ override type Mirror >: Null <: JavaMirror
+
+ /** A refinement of [[scala.reflect.api.Mirror]] for runtime reflection using JVM classloaders.
+ *
+ * With this upgrade, mirrors become capable of converting Scala reflection artifacts (symbols and types)
+ * into Java reflection artifacts (classes) and vice versa. Consequently, refined mirrors
+ * become capable of performing reflective invocations (getting/setting field values, calling methods, etc).
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @group JavaMirrors
+ */
+ trait JavaMirror extends scala.reflect.api.Mirror[self.type] with RuntimeMirror {
+ val classLoader: ClassLoader
+ override def toString = s"JavaMirror with ${runtime.ReflectionUtils.show(classLoader)}"
+ }
+
+ /** Creates a runtime reflection mirror from a JVM classloader.
+ *
+ * For more information about `Mirrors`s, see [[scala.reflect.api.Mirrors]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @group JavaMirrors
+ */
+ def runtimeMirror(cl: ClassLoader): Mirror
+}
diff --git a/src/reflect/scala/reflect/api/JavaUniverse.scala b/src/reflect/scala/reflect/api/JavaUniverse.scala
index cc703e833d..f83692034f 100644
--- a/src/reflect/scala/reflect/api/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/api/JavaUniverse.scala
@@ -1,19 +1,19 @@
package scala.reflect
package api
-trait JavaUniverse extends Universe with Mirrors { self =>
-
- type RuntimeClass = java.lang.Class[_]
-
- override type Mirror >: Null <: JavaMirror
-
- trait JavaMirror extends scala.reflect.api.Mirror[self.type] with RuntimeMirror {
- val classLoader: ClassLoader
- override def toString = s"JavaMirror with ${runtime.ReflectionUtils.show(classLoader)}"
- }
-
- def runtimeMirror(cl: ClassLoader): Mirror
+/** A refinement of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders.
+ *
+ * The refinement consists of an upgrade to the mirror API, which gets extended from [[scala.reflect.api.Mirror]]
+ * to [[scala.reflect.api.JavaMirrors#JavaMirror]].
+ *
+ * See the [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for details on how to use runtime reflection.
+ * @groupname JavaUniverse Java Mirrors
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
+trait JavaUniverse extends Universe with JavaMirrors { self =>
+ /* @group JavaUniverse */
override def typeTagToManifest[T: ClassTag](mirror0: Any, tag: Universe # TypeTag[T]): Manifest[T] = {
// SI-6239: make this conversion more precise
val mirror = mirror0.asInstanceOf[Mirror]
@@ -21,6 +21,7 @@ trait JavaUniverse extends Universe with Mirrors { self =>
Manifest.classType(runtimeClass).asInstanceOf[Manifest[T]]
}
+ /* @group JavaUniverse */
override def manifestToTypeTag[T](mirror0: Any, manifest: Manifest[T]): Universe # TypeTag[T] =
TypeTag(mirror0.asInstanceOf[Mirror], new TypeCreator {
def apply[U <: Universe with Singleton](mirror: scala.reflect.api.Mirror[U]): U # Type = {
diff --git a/src/reflect/scala/reflect/api/Mirror.scala b/src/reflect/scala/reflect/api/Mirror.scala
index 2de0d7120e..b1290cc02e 100644
--- a/src/reflect/scala/reflect/api/Mirror.scala
+++ b/src/reflect/scala/reflect/api/Mirror.scala
@@ -2,32 +2,41 @@ package scala.reflect
package api
/**
- * The base interface for all mirrors.
+ * The base class for all mirrors.
*
- * @tparam U the type of the universe this mirror belongs to.
- *
- * This is defined outside the reflection universe cake pattern implementation
- * so that it can be referenced from outside. For example TypeCreator and TreeCreator
- * reference Mirror and also need to be defined outside the cake as they are
- * used by type tags, which can be migrated between different universes and consequently
- * cannot be bound to a fixed one.
+ * See [[scala.reflect.api.Mirrors]] or [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ * for a complete overview of `Mirror`s.
*
- * @see [[Mirrors]]
+ * @tparam U the type of the universe this mirror belongs to.
*/
+// Note: Unlike most Scala reflection artifact classes, `Mirror` is not defined as an inner class,
+// so that it can be referenced from outside. For example, [[scala.reflect.api.TypeCreator]] and [[scala.reflect.api.TreeCreator]]
+// reference `Mirror` and also need to be defined outside the cake as they are used by type tags, which can be migrated between
+// different universes and consequently cannot be bound to a fixed one.
abstract class Mirror[U <: Universe with Singleton] {
- /** The universe this mirror belongs to. */
+ /** The universe this mirror belongs to.
+ * @group Mirror
+ */
val universe: U
- /** The class symbol of the `_root_` package */
+ /** The class symbol of the `_root_` package
+ * @group Mirror
+ */
def RootClass: U#ClassSymbol
- /** The module symbol of the `_root_` package */
+ /** The module symbol of the `_root_` package
+ * @group Mirror
+ */
def RootPackage: U#ModuleSymbol
- /** The module class symbol of the default (unnamed) package */
+ /** The module class symbol of the default (unnamed) package
+ * @group Mirror
+ */
def EmptyPackageClass: U#ClassSymbol
- /** The module symbol of the default (unnamed) package */
+ /** The module symbol of the default (unnamed) package
+ * @group Mirror
+ */
def EmptyPackage: U#ModuleSymbol
/** The symbol corresponding to the globally accessible class with the
@@ -71,6 +80,7 @@ abstract class Mirror[U <: Universe with Singleton] {
*
* In the example above, to load a symbol that corresponds to the class B declared in the object foo,
* use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
+ * @group Mirror
*/
def staticClass(fullName: String): U#ClassSymbol
@@ -97,11 +107,13 @@ abstract class Mirror[U <: Universe with Singleton] {
*
* In the example above, to load a symbol that corresponds to the object B declared in the object foo,
* use staticModule("foo") to load the module symbol and then navigate typeSignature.members of its moduleClass.
+ * @group Mirror
*/
def staticModule(fullName: String): U#ModuleSymbol
/** The symbol corresponding to a package with the
* given fully qualified name `fullName`.
+ * @group Mirror
*/
def staticPackage(fullName: String): U#ModuleSymbol
}
diff --git a/src/reflect/scala/reflect/api/Mirrors.scala b/src/reflect/scala/reflect/api/Mirrors.scala
index bff899daa4..cc1b9762cb 100644
--- a/src/reflect/scala/reflect/api/Mirrors.scala
+++ b/src/reflect/scala/reflect/api/Mirrors.scala
@@ -1,13 +1,207 @@
package scala.reflect
package api
-/**
- * Defines a type hierarchy for mirrors.
+/** This trait provides support for Mirrors in the Scala Reflection API.
*
- * Every universe has one or more mirrors. A mirror defines a hierarchy of symbols starting with the root package `_root_`
- * and provides methods to locate and define classes and singleton objects in that hierarchy.
+ * `Mirror`s are a central part of Scala Reflection. All information provided by
+ * reflection is made accessible through `Mirror`s. Depending on the type of information
+ * to be obtained, or the reflective action to be taken, different flavors of mirrors
+ * must be used. "Classloader" mirrors can be used to obtain representations of types
+ * and members. From a classloader `Mirror`, it's possible to obtain more specialized
+ * "invoker" `Mirror`s (the most commonly-used mirrors), which implement reflective
+ * invocations, such as method/constructor calls and field accesses.
*
- * On the JVM, there is a one to one correspondance between class loaders and mirrors.
+ * The two flavors of mirrors:
+ *
+ * <ul>
+ * <li>```“Classloader” mirrors```. These mirrors translate names to symbols
+ * (via methods `staticClass`/`staticModule`/`staticPackage`).</li>
+ * <li>```"Invoker” mirrors```. These mirrors implement reflective invocations
+ * (via methods `MethodMirror.apply`, `FieldMirror.get`, etc). These "invoker"
+ * mirrors are the types of mirrors that are most commonly used.</li>
+ * </ul>
+ *
+ * === Compile-time Mirrors ===
+ * Compile-time `Mirror`s make use of only classloader `Mirror`s to load `Symbol`s
+ * by name.
+ *
+ * The entry point to classloader `Mirror`s is via [[scala.reflect.macros.Context#mirror]].
+ * Typical methods which use classloader `Mirror`s include [[scala.reflect.api.Mirror#staticClass]],
+ * [[scala.reflect.api.Mirror#staticModule]], and [[scala.reflect.api.Mirror#staticPackage]]. For
+ * example:
+ * {{{
+ * import scala.reflect.macros.Context
+ *
+ * case class Location(filename: String, line: Int, column: Int)
+ *
+ * object Macros {
+ * def currentLocation: Location = macro impl
+ *
+ * def impl(c: Context): c.Expr[Location] = {
+ * import c.universe._
+ * val pos = c.macroApplication.pos
+ * val clsLocation = c.mirror.staticModule("Location") // get symbol of "Location" object
+ * c.Expr(Apply(Ident(clsLocation), List(Literal(Constant(pos.source.path)), Literal(Constant(pos.line)), Literal(Constant(pos.column)))))
+ * }
+ * }
+ * }}}
+ *
+ * ''Of Note:'' There are several high-level alternatives that one can use to avoid having to manually
+ * lookup symbols. For example, `typeOf[Location.type].termSymbol` (or `typeOf[Location].typeSymbol`
+ * if we needed a `ClassSymbol`), which are type safe since we don’t have to use `String`s to lookup
+ * the `Symbol`.
+ *
+ * === Runtime Mirrors ===
+ *
+ * Runtime `Mirror`s make use of both classloader and invoker `Mirror`s.
+ *
+ * The entry point to `Mirror`s for use at runtime is via `ru.runtimeMirror(<classloader>)`, where
+ * `ru` is [[scala.reflect.runtime.universe]].
+ *
+ * The result of a [[scala.reflect.api.JavaMirrors#runtimeMirror]] call is a classloader mirror,
+ * of type [[scala.reflect.api.Mirrors#ReflectiveMirror]], which can load symbols by names as
+ * discussed above (in the “Compile-time” section).
+ *
+ * A classloader mirror can create invoker mirrors, which include: [[scala.reflect.api.Mirrors#InstanceMirror]],
+ * [[scala.reflect.api.Mirrors#MethodMirror]], [[scala.reflect.api.Mirrors#FieldMirror]],
+ * [[scala.reflect.api.Mirrors#ClassMirror]] and [[scala.reflect.api.Mirrors#ModuleMirror]].
+ *
+ * Examples of how these two types of `Mirror`s interact are available below.
+ *
+ * === Types of Mirrors, Their Use Cases & Examples ===
+ *
+ * '''[[scala.reflect.api.Mirrors#ReflectiveMirror]]'''. Used for loading `Symbol`s by name, and
+ * as an entry point into invoker mirrors. Entry point: `val m = ru.runtimeMirror(<classloader>)`.
+ * Example:
+ * {{{
+ * scala> val ru = scala.reflect.runtime.universe
+ * ru: scala.reflect.api.JavaUniverse = ...
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#InstanceMirror]]'''. Used for creating invoker `Mirror`s for methods
+ * and fields and for inner classes and inner objects (modules). Entry point: `val im = m.reflect(<value>)`.
+ * Example:
+ * {{{
+ * scala> class C { def x = 2 }
+ * defined class C
+ *
+ * scala> val im = m.reflect(new C)
+ * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@3442299e
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#MethodMirror]]'''. Used for invoking instance methods (Scala only has
+ * instance methods-- methods of objects are instance methods of object instances, obtainable
+ * via `ModuleMirror.instance`). Entry point: `val mm = im.reflectMethod(<method symbol>)`.
+ * Example:
+ * {{{
+ * scala> val methodX = typeOf[C].declaration(newTermName("x")).asMethod
+ * methodX: reflect.runtime.universe.MethodSymbol = method x
+ *
+ * scala> val mm = im.reflectMethod(methodX)
+ * mm: reflect.runtime.universe.MethodMirror = method mirror for C.x: scala.Int (bound to C@3442299e)
+ *
+ * scala> mm()
+ * res0: Any = 2
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#FieldMirror]]'''. Used for getting/setting instance fields
+ * (Scala only has instance fields-- fields of objects are instance methods of object instances
+ * obtainable via ModuleMirror.instance). Entry point:
+ * `val fm = im.reflectMethod(<field or accessor symbol>)`.
+ * Example:
+ * {{{
+ * scala> class C { val x = 2; val y = 3 }
+ * defined class C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val im = m.reflect(new C)
+ * im: reflect.runtime.universe.InstanceMirror = instance mirror for C@5f0c8ac1
+ *
+ * scala> val fieldX = typeOf[C].declaration(newTermName("x")).asTerm.accessed.asTerm
+ * fieldX: reflect.runtime.universe.TermSymbol = value x
+ * scala> val fmX = im.reflectField(fieldX)
+ * fmX: reflect.runtime.universe.FieldMirror = field mirror for C.x (bound to C@5f0c8ac1)
+ *
+ * scala> fmX.get
+ * res0: Any = 2
+ *
+ * scala> fmX.set(3)
+ * scala.ScalaReflectionException: cannot set an immutable field x
+ * ...
+ *
+ * scala> val fieldY = typeOf[C].declaration(newTermName("y")).asTerm.accessed.asTerm
+ * fieldY: reflect.runtime.universe.TermSymbol = variable y
+ *
+ * scala> val fmY = im.reflectField(fieldY)
+ * fmY: reflect.runtime.universe.FieldMirror = field mirror for C.y (bound to C@5f0c8ac1)
+ *
+ * scala> fmY.get
+ * res1: Any = 3
+ *
+ * scala> fmY.set(4)
+ *
+ * scala> fmY.get
+ * res2: Any = 4
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#ClassMirror]]'''. Used for creating invoker mirrors for constructors.
+ * Entry points: for ''static classes'' `val cm1 = m.reflectClass(<class symbol>)`,
+ * for ''inner classes'' `val mm2 = im.reflectClass(<module symbol>)`.
+ * Example:
+ * {{{
+ * scala> case class C(x: Int)
+ * defined class C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val classC = typeOf[C].typeSymbol.asClass
+ *
+ * classC: reflect.runtime.universe.Symbol = class C
+ *
+ * scala> val cm = m.reflectClass(classC)
+ * cm: reflect.runtime.universe.ClassMirror = class mirror for C (bound to null)
+ *
+ * scala> val ctorC = typeOf[C].declaration(ru.nme.CONSTRUCTOR).asMethod
+ * ctorC: reflect.runtime.universe.MethodSymbol = constructor C
+ *
+ * scala> val ctorm = cm.reflectConstructor(ctorC)
+ * ctorm: reflect.runtime.universe.MethodMirror = constructor mirror for C.<init>(x: scala.Int): C (bound to null)
+ *
+ * scala> ctorm(2)
+ * res0: Any = C(2)
+ * }}}
+ *
+ * '''[[scala.reflect.api.Mirrors#ModuleMirror]]'''. Used for getting singleton instances of objects.
+ * Entry points: for ''static objects (modules)'' `val mm1 = m.reflectModule(<module symbol>)`,
+ * for ''inner objects (modules)'' `val mm2 = im.reflectModule(<module symbol>)`.
+ * Example:
+ * {{{
+ * scala> object C { def x = 2 }
+ * defined module C
+ *
+ * scala> val m = ru.runtimeMirror(getClass.getClassLoader)
+ * m: reflect.runtime.universe.Mirror = JavaMirror ...
+ *
+ * scala> val objectC = typeOf[C.type].termSymbol.asModule
+ * objectC: reflect.runtime.universe.ModuleSymbol = object C
+ *
+ * scala> val mm = m.reflectModule(objectC)
+ * mm: reflect.runtime.universe.ModuleMirror = module mirror for C (bound to null)
+ *
+ * scala> val obj = mm.instance
+ * obj: Any = C$@1005ec04
+ * }}}
+ *
+ * For more information about `Mirrors`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Mirrors]]
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Mirrors { self: Universe =>
@@ -15,27 +209,35 @@ trait Mirrors { self: Universe =>
*
* This abstract type conforms the base interface for all mirrors defined in [[scala.reflect.api.Mirror]]
* and is gradually refined in specific universes (e.g. `Mirror` of a [[scala.reflect.api.JavaUniverse]] is capable of reflection).
+ * @group Mirrors
*/
type Mirror >: Null <: scala.reflect.api.Mirror[self.type]
/** The root mirror of this universe. This mirror contains standard Scala classes and types such as `Any`, `AnyRef`, `AnyVal`,
* `Nothing`, `Null`, and all classes loaded from scala-library, which are shared across all mirrors within the enclosing universe.
+ * @group Mirrors
*/
val rootMirror: Mirror
+ /** Abstracts the runtime representation of a class on the underlying platform.
+ * @group Mirrors
+ */
type RuntimeClass >: Null
// todo. an improvement might be having mirrors reproduce the structure of the reflection domain
// e.g. a ClassMirror could also have a list of fields, methods, constructors and so on
// read up more on the proposed design in "Reflecting Scala" by Y. Coppel
- /** A mirror that reflects a runtime value */
+ /** A mirror that reflects a runtime value.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait InstanceMirror {
/** The instance value reflected by this mirror */
def instance: Any
- /** The symbol corresponding to the run-time class of the reflected instance */
+ /** The symbol corresponding to the runtime class of the reflected instance */
def symbol: ClassSymbol
/** Reflects against a field symbol and returns a mirror
@@ -103,7 +305,10 @@ trait Mirrors { self: Universe =>
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
- /** A mirror that reflects a field */
+ /** A mirror that reflects a field.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait FieldMirror {
/** The object containing the field */
@@ -145,7 +350,10 @@ trait Mirrors { self: Universe =>
def set(value: Any): Unit
}
- /** A mirror that reflects a method handle */
+ /** A mirror that reflects a method.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait MethodMirror {
/** The receiver object of the method */
@@ -163,12 +371,12 @@ trait Mirrors { self: Universe =>
def apply(args: Any*): Any
}
- /** A mirror that reflects the instance or static parts of a runtime class */
+ /** A mirror that reflects the instance or static parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait TemplateMirror {
- /** The runtime class reflected by this mirror */
- def runtimeClass: RuntimeClass
-
/** True if the mirror represents the static part
* of a runtime class or the companion object of a Scala class.
* One has:
@@ -180,21 +388,12 @@ trait Mirrors { self: Universe =>
/** The Scala symbol corresponding to the reflected runtime class or object */
def symbol: Symbol
-
- /** Optionally, the mirror of the companion reflected by this mirror.
- * If this mirror reflects a Scala object, the mirror for the companion class, or None
- * if the mirror represents a Scala object that comes without a class.
- * Otherwise, if the mirror represents the static part of a runtime class, the
- * mirror representing the instance part of the same class.
- * Otherwise, if the mirror represents a Scala instance class, the mirror for the companion
- * object of that class, or None if no such object exists.
- * Otherwise, if the mirror represents a runtime instance class, a mirror representing the static
- * part of the same class.
- */
- def companion: Option[TemplateMirror]
}
- /** A mirror that reflects a Scala object definition or the static parts of a runtime class */
+ /** A mirror that reflects a Scala object definition or the static parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ModuleMirror extends TemplateMirror {
/** The Scala module symbol corresponding to the reflected object */
@@ -205,17 +404,12 @@ trait Mirrors { self: Universe =>
* If this mirror reflects the static part of a runtime class, returns `null`.
*/
def instance: Any
-
- /** Optionally, the mirror of the companion class if the object reflected by this mirror.
- * If this mirror reflects a Scala object, the mirror for the companion class, or None
- * if the mirror represents a Scala object that comes without a class.
- * Otherwise, if the mirror represents the static part of a runtime class, the
- * mirror representing the instance part of the same class.
- */
- override def companion: Option[ClassMirror]
}
- /** A mirror that reflects the instance parts of a runtime class */
+ /** A mirror that reflects the instance parts of a runtime class.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ClassMirror extends TemplateMirror {
/** The Scala class symbol corresponding to the reflected class */
@@ -232,17 +426,12 @@ trait Mirrors { self: Universe =>
* It must be a member (declared or inherited) of the class underlying this mirror.
*/
def reflectConstructor(constructor: MethodSymbol): MethodMirror
-
- /** Optionally, the mirror of the companion object of the class reflected by this mirror.
- * If this mirror represents a Scala instance class, the mirror for the companion
- * object of that class, or None if no such object exists.
- * Otherwise, if the mirror represents a runtime instance class, a mirror representing the static
- * part of the same class.
- */
- override def companion: Option[ModuleMirror]
}
- /** A mirror that reflects instances and static classes */
+ /** A mirror that reflects instances and static classes.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait ReflectiveMirror extends scala.reflect.api.Mirror[Mirrors.this.type] {
/** A reflective mirror for the given object.
@@ -277,7 +466,10 @@ trait Mirrors { self: Universe =>
def reflectModule(mod: ModuleSymbol): ModuleMirror
}
- /** The API of a mirror for a reflective universe */
+ /** The API of a mirror for a reflective universe.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use runtime reflection.
+ * @group Mirrors
+ */
trait RuntimeMirror extends ReflectiveMirror { self =>
/** Maps a Scala type to the corresponding Java class object */
diff --git a/src/reflect/scala/reflect/api/Names.scala b/src/reflect/scala/reflect/api/Names.scala
index e8665ca736..02eb79f8ed 100644
--- a/src/reflect/scala/reflect/api/Names.scala
+++ b/src/reflect/scala/reflect/api/Names.scala
@@ -1,40 +1,70 @@
package scala.reflect
package api
-/** A trait that manages names.
+/** This trait defines Names (a Scala reflection concept) and operations on them.
*
- * @see TermName
- * @see TypeName
+ * Names are simple wrappers for strings. [[scala.reflect.api.Names#Name Name]] has two subtypes [[scala.reflect.api.Names#TermName TermName]] and [[scala.reflect.api.Names#TypeName TypeName]] which
+ * distinguish names of terms (like objects or members) and types. A term and a type of the
+ * same name can co-exist in an object.
+ *
+ * === Examples ===
+ *
+ * To search for the `map` method (which is a term) declared in the `List` class,
+ * use `typeOf[List[_]].member(newTermName("map"))`. To search for a type member, use
+ * newTypeName instead.
+ *
+ * See the [[docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]] for more about Scala Reflection.
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Names {
- // Intentionally no implicit from String => Name.
+ /** An implicit conversion from String to TermName.
+ * Enables an alternative notation `"map": TermName` as opposed to `newTermName("map")`.
+ * @group Names
+ */
implicit def stringToTermName(s: String): TermName = newTermName(s)
+
+ /** An implicit conversion from String to TypeName.
+ * Enables an alternative notation `"List": TypeName` as opposed to `newTypeName("List")`.
+ * @group Names
+ */
implicit def stringToTypeName(s: String): TypeName = newTypeName(s)
- /**
- * The abstract type of names
- *
- * A Name wraps a string as the name for either a type ([[TypeName]]) of a term ([[TermName]]).
- * Two names are equal, if the wrapped string are equal and they are either both `TypeName` or both `TermName`.
- * The same string can co-exist as a `TypeName` and a `TermName`, but they would not be equal.
- * Names are interned. That is, for two names `name11 and `name2`,
- * `name1 == name2` implies `name1 eq name2`.
- *
- * One of the reasons for the existence of names rather than plain strings is being more explicit about what is a name and if it represents a type or a term.
+ /** The abstract type of names.
+ * @group Names
*/
type Name >: Null <: NameApi
+
+ /** A tag that preserves the identity of the `Name` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val NameTag: ClassTag[Name]
- /** The abstract type of names representing terms */
+ /** The abstract type of names representing terms.
+ * @group Names
+ */
type TypeName >: Null <: Name
- implicit val TypeNameTag: ClassTag[TypeName]
- /** The abstract type of names representing types */
+ /** A tag that preserves the identity of the `TypeName` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
+implicit val TypeNameTag: ClassTag[TypeName]
+
+ /** The abstract type of names representing types.
+ * @group Names
+ */
type TermName >: Null <: Name
+
+ /** A tag that preserves the identity of the `TermName` abstract type from erasure.
+ * Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
+ */
implicit val TermNameTag: ClassTag[TermName]
- /** The API of names that's supported on reflect mirror via an
- * implicit conversion in reflect.ops
+ /** The API of Name instances.
+ * @group API
*/
abstract class NameApi {
/** Checks wether the name is a a term name */
@@ -69,18 +99,12 @@ trait Names {
}
/** Create a new term name.
+ * @group Names
*/
def newTermName(s: String): TermName
/** Creates a new type name.
+ * @group Names
*/
def newTypeName(s: String): TypeName
-
- /** Wraps the empty string. Can be used as the null object for term name.
- */
- def EmptyTermName: TermName = newTermName("")
-
- /** Wraps the empty string. Can be used as the null object for type name.
- */
- def EmptyTypeName: TypeName = EmptyTermName.toTypeName
}
diff --git a/src/reflect/scala/reflect/api/Position.scala b/src/reflect/scala/reflect/api/Position.scala
index 9c63e4becf..61d643b449 100644
--- a/src/reflect/scala/reflect/api/Position.scala
+++ b/src/reflect/scala/reflect/api/Position.scala
@@ -1,64 +1,65 @@
package scala.reflect
package api
-/** The Position class and its subclasses represent positions of ASTs and symbols.
- * Except for NoPosition and FakePos, every position refers to a SourceFile
- * and to an offset in the sourcefile (its `point`). For batch compilation,
- * that's all. For interactive IDE's there are also RangePositions
- * and TransparentPositions. A RangePosition indicates a start and an end
- * in addition to its point. TransparentPositions are a subclass of RangePositions.
- * Range positions that are not transparent are called opaque.
- * Trees with RangePositions need to satisfy the following invariants.
+import scala.reflect.macros.Attachments
+
+/** Position tracks the origin of [[Symbols#Symbol symbols]] and [[Trees#Tree tree nodes]]. They are commonly used when
+ * displaying warnings and errors, to indicate the incorrect point in the program.
+ *
+ * A position indicates the [[source source file]] and an [[point offset]]. A position may be
+ * undefined, which means it's pointing to the [[Positions#NoPosition]] element.
+ *
+ * <b>Please note that this trait may be refactored in future versions of the Scala reflection API.</b>
*
- * INV1: A tree with an offset position never contains a child
+ * @see [[http://docs.scala-lang.org/overviews/reflection/names-exprs-scopes-more.html]]
+ *
+ * The compiler adds more information to positions, such a ranges in the source file and defines different types of
+ * positions depending on how a symbol or tree node was generated. The guide fully describes compiler-generated positions.
+ *
+ * - INV1: A tree with an offset position never contains a child
* with a range position
- * INV2: If the child of a tree with a range position also has a range position,
+ * - INV2: If the child of a tree with a range position also has a range position,
* then the child's range is contained in the parent's range.
- * INV3: Opaque range positions of children of the same node are non-overlapping
+ * - INV3: Opaque range positions of children of the same node are non-overlapping
* (this means their overlap is at most a single point).
*
* The following tests are useful on positions:
- *
- * pos.isDefined true if position is not a NoPosition nor a FakePosition
- * pos.isRange true if position is a range
- * pos.isOpaqueRange true if position is an opaque range
- *
- * The following accessor methods are provided:
- *
- * pos.source The source file of the position, which must be defined
- * pos.point The offset of the position's point, which must be defined
- * pos.start The start of the position, which must be a range
- * pos.end The end of the position, which must be a range
+ * `pos.isDefined` true if position is not a NoPosition,
+ * `pos.isRange` true if position is a range,
+ * `pos.isOpaqueRange` true if position is an opaque range,
*
* There are also convenience methods, such as
- *
- * pos.startOrPoint
- * pos.endOrPoint
- * pos.pointOrElse(default)
- *
+ * `pos.startOrPoint`,
+ * `pos.endOrPoint`,
+ * `pos.pointOrElse(default)`.
* These are less strict about the kind of position on which they can be applied.
*
* The following conversion methods are often used:
+ * `pos.focus` converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged,
+ * `pos.makeTransparent` converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
*
- * pos.focus converts a range position to an offset position, keeping its point;
- * returns all other positions unchanged.
- * pos.makeTransparent converts an opaque range position into a transparent one.
- * returns all other positions unchanged.
+ * @groupname Common Commonly used methods
*/
trait Position extends Attachments {
+ /** @inheritdoc */
type Pos >: Null <: Position
/** Java file corresponding to the source file of this position.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
+ *
+ * @group Common
*/
def source: scala.reflect.internal.util.SourceFile
/** Is this position neither a NoPosition nor a FakePosition?
* If isDefined is true, offset and source are both defined.
+ * @group Common
*/
def isDefined: Boolean
@@ -69,36 +70,46 @@ trait Position extends Attachments {
def isTransparent: Boolean
/** Is this position a non-transparent range position? */
- def isOpaqueRange: Boolean
+ def isOpaqueRange: Boolean
- /** if opaque range, make this position transparent */
+ /** If opaque range, make this position transparent. */
def makeTransparent: Pos
- /** The start of the position's range, error if not a range position */
+ /** The start of the position's range, error if not a range position. */
def start: Int
- /** The start of the position's range, or point if not a range position */
+ /** The start of the position's range, or point if not a range position. */
def startOrPoint: Int
- /** The point (where the ^ is) of the position */
+ /** The point (where the ^ is) of the position, which is easiest to access using the [[line]] and [[column]] values.
+ * The [[lineContent line content]] is also available.
+ * @group Common
+ */
def point: Int
- /** The point (where the ^ is) of the position, or else `default` if undefined */
+ /** The point (where the ^ is) of the position, or else `default` if undefined.
+ * @group Common
+ */
def pointOrElse(default: Int): Int
- /** The end of the position's range, error if not a range position */
+ /** The end of the position's range, error if not a range position.
+ */
def end: Int
- /** The end of the position's range, or point if not a range position */
+ /** The end of the position's range, or point if not a range position.
+ */
def endOrPoint: Int
- /** The same position with a different start value (if a range) */
+ /** The same position with a different start value (if a range).
+ */
def withStart(off: Int): Pos
- /** The same position with a different end value (if a range) */
+ /** The same position with a different end value (if a range).
+ */
def withEnd(off: Int): Pos
- /** The same position with a different point value (if a range or offset) */
+ /** The same position with a different point value (if a range or offset).
+ */
def withPoint(off: Int): Pos
/** If this is a range, the union with the other range, with the point of this position.
@@ -121,7 +132,7 @@ trait Position extends Attachments {
*/
def focusEnd: Pos
- /** Does this position include the given position `pos`.
+ /** Does this position include the given position `pos`?
* This holds if `this` is a range position and its range [start..end]
* is the same or covers the range of the given position, which may or may not be a range position.
*/
@@ -154,14 +165,26 @@ trait Position extends Attachments {
*/
def sameRange(pos: Pos): Boolean
+ /** The position indicates a [[column `column`]] and the `line` in the source file.
+ * @group Common
+ */
def line: Int
+ /** The position indicates a `column` and the [[line `line`]] in the source file.
+ * @group Common
+ */
def column: Int
- /** Convert this to a position around `point` that spans a single source line */
+ /** Convert this to a position around `point` that spans a single source line
+ */
def toSingleLine: Pos
+ /** The content of the line this Position refers to.
+ * @group Common
+ */
def lineContent: String
+ /** Show a textual representation of the position.
+ */
def show: String
}
diff --git a/src/reflect/scala/reflect/api/Positions.scala b/src/reflect/scala/reflect/api/Positions.scala
index 5c530e7e70..8d8a0081cc 100644
--- a/src/reflect/scala/reflect/api/Positions.scala
+++ b/src/reflect/scala/reflect/api/Positions.scala
@@ -1,26 +1,34 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for positions.
+/** This trait defines the concept of positions and operations on them.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * @see [[scala.reflect.api.Position]]
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Positions {
self: Universe =>
- /** .. */
+ /** Defines a universe-specific notion of positions.
+ * The main documentation entry about positions is located at [[scala.reflect.api.Position]].
+ * @group Positions
+ */
type Position >: Null <: scala.reflect.api.Position { type Pos = Position }
/** A tag that preserves the identity of the `Position` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PositionTag: ClassTag[Position]
- /** A special "missing" position. */
+ /** A special "missing" position.
+ * @group Positions
+ */
val NoPosition: Position
/** Assigns a given position to all position-less nodes of a given AST.
+ * @group Positions
*/
def atPos[T <: Tree](pos: Position)(tree: T): T
@@ -28,6 +36,7 @@ trait Positions {
* The point of the wrapping position is the point of the default position.
* If some of the trees are ranges, returns a range position enclosing all ranges
* Otherwise returns default position.
+ * @group Positions
*/
def wrappingPos(default: Position, trees: List[Tree]): Position
@@ -35,6 +44,7 @@ trait Positions {
* The point of the wrapping position is the point of the first trees' position.
* If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
* Otherwise returns a synthetic offset position to point.
+ * @group Positions
*/
def wrappingPos(trees: List[Tree]): Position
}
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala
index 65ff2ed9fa..1e8161aeef 100644
--- a/src/reflect/scala/reflect/api/Printers.scala
+++ b/src/reflect/scala/reflect/api/Printers.scala
@@ -3,9 +3,135 @@ package api
import java.io.{ PrintWriter, StringWriter }
+/** Utilities for nicely printing [[scala.reflect.api.Trees]] and [[scala.reflect.api.Types]].
+ *
+ * === Printing Trees ===
+ * The method `show` displays the "prettified" representation of reflection artifacts.
+ * This representation provides one with the desugared Java representation of Scala code.
+ * For example:
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> def tree = reify{ final class C { def x = 2 } }.tree
+ * tree: reflect.runtime.universe.Tree
+ *
+ * scala> show(tree)
+ * res0: String =
+ * {
+ * final class C extends AnyRef {
+ * def <init>() = {
+ * super.<init>();
+ * ()
+ * };
+ * def x = 2
+ * };
+ * ()
+ * }
+ * }}}
+ *
+ * The method `showRaw` displays internal structure of a given reflection object
+ * as a Scala abstract syntax tree (AST), the representation that the Scala typechecker
+ * operates on.
+ *
+ * Note, that while this representation appears to generate correct trees that one
+ * might think would be possible to use in a macro implementation, this is not usually
+ * the case. Symbols aren't fully represented (only their names are). Thus, this method
+ * is best-suited for use simply inspecting ASTs given some valid Scala code.
+ * {{{
+ * scala> showRaw(tree)
+ * res1: String = Block(List(
+ * ClassDef(Modifiers(FINAL), newTypeName("C"), List(), Template(
+ * List(Ident(newTypeName("AnyRef"))),
+ * emptyValDef,
+ * List(
+ * DefDef(Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree(),
+ * Block(List(
+ * Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())),
+ * Literal(Constant(())))),
+ * DefDef(Modifiers(), newTermName("x"), List(), List(), TypeTree(),
+ * Literal(Constant(2))))))),
+ * Literal(Constant(())))
+ * }}}
+ *
+ * The method `showRaw` can also print [[scala.reflect.api.Types]] next to the artifacts
+ * being inspected
+ * {{{
+ * scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar
+ * import scala.tools.reflect.ToolBox
+ *
+ * scala> import scala.reflect.runtime.{currentMirror => cm}
+ * import scala.reflect.runtime.{currentMirror=>cm}
+ *
+ * scala> showRaw(cm.mkToolBox().typeCheck(tree), printTypes = true)
+ * res2: String = Block[1](List(
+ * ClassDef[2](Modifiers(FINAL), newTypeName("C"), List(), Template[3](
+ * List(Ident[4](newTypeName("AnyRef"))),
+ * emptyValDef,
+ * List(
+ * DefDef[2](Modifiers(), nme.CONSTRUCTOR, List(), List(List()), TypeTree[3](),
+ * Block[1](List(
+ * Apply[4](Select[5](Super[6](This[3](newTypeName("C")), tpnme.EMPTY), ...))),
+ * Literal[1](Constant(())))),
+ * DefDef[2](Modifiers(), newTermName("x"), List(), List(), TypeTree[7](),
+ * Literal[8](Constant(2))))))),
+ * Literal[1](Constant(())))
+ * [1] TypeRef(ThisType(scala), scala.Unit, List())
+ * [2] NoType
+ * [3] TypeRef(NoPrefix, newTypeName("C"), List())
+ * [4] TypeRef(ThisType(java.lang), java.lang.Object, List())
+ * [5] MethodType(List(), TypeRef(ThisType(java.lang), java.lang.Object, List()))
+ * [6] SuperType(ThisType(newTypeName("C")), TypeRef(... java.lang.Object ...))
+ * [7] TypeRef(ThisType(scala), scala.Int, List())
+ * [8] ConstantType(Constant(2))
+ * }}}
+ *
+ * === Printing Types ===
+ *
+ * The method `show`
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> def tpe = typeOf[{ def x: Int; val y: List[Int] }]
+ * tpe: reflect.runtime.universe.Type
+ *
+ * scala> show(tpe)
+ * res0: String = scala.AnyRef{def x: Int; val y: scala.List[Int]}
+ * }}}
+ *
+ * Like the method `showRaw` for [[scala.reflect.api.Trees]], `showRaw`
+ * for [[scala.reflect.api.Types]] provides a visualization of the Scala
+ * AST operated on by the Scala typechecker.
+ * {{{
+ * // showRaw has already been discussed above
+ * scala> showRaw(tpe)
+ * res1: String = RefinedType(
+ * List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())),
+ * Scope(
+ * newTermName("x"),
+ * newTermName("y")))
+ * }}}
+ *
+ * `printIds` and/or `printKinds` can additionally be supplied as arguments in a call to
+ * `showRaw` which additionally shows the unique identifiers of symbols.
+ * scala> showRaw(tpe, printIds = true, printKinds = true)
+ * res2: String = RefinedType(
+ * List(TypeRef(ThisType(scala#2043#PK), newTypeName("AnyRef")#691#TPE, List())),
+ * Scope(
+ * newTermName("x")#2540#METH,
+ * newTermName("y")#2541#GET))
+ * }}}
+ *
+ * For more details about `Printer`s and other aspects of Scala reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ */
trait Printers { self: Universe =>
- trait TreePrinter {
+ /** @group Printers */
+ protected trait TreePrinter {
def print(args: Any*)
protected var printTypes = false
protected var printIds = false
@@ -21,13 +147,16 @@ trait Printers { self: Universe =>
def withoutMirrors: this.type = { printMirrors = false; this }
}
+ /** @group Printers */
case class BooleanFlag(val value: Option[Boolean])
+ /** @group Printers */
object BooleanFlag {
import scala.language.implicitConversions
implicit def booleanToBooleanFlag(value: Boolean): BooleanFlag = BooleanFlag(Some(value))
implicit def optionToBooleanFlag(value: Option[Boolean]): BooleanFlag = BooleanFlag(value)
}
+ /** @group Printers */
protected def render(what: Any, mkPrinter: PrintWriter => TreePrinter, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String = {
val buffer = new StringWriter()
val writer = new PrintWriter(buffer)
@@ -41,41 +170,54 @@ trait Printers { self: Universe =>
buffer.toString
}
- /** By default trees are printed with `show` */
+ /** By default trees are printed with `show`
+ * @group Printers
+ */
override protected def treeToString(tree: Tree) = show(tree)
- /** Renders a prettified representation of a reflection artifact.
- * Typically it looks very close to the Scala code it represents.
+ /** Renders a representation of a reflection artifact
+ * as desugared Java code.
+ *
+ * @group Printers
*/
def show(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String =
render(any, newTreePrinter(_), printTypes, printIds, printKinds, printMirrors)
/** Hook to define what `show(...)` means.
+ * @group Printers
*/
- def newTreePrinter(out: PrintWriter): TreePrinter
+ protected def newTreePrinter(out: PrintWriter): TreePrinter
- /** Renders internal structure of a reflection artifact.
+ /** Renders internal structure of a reflection artifact as the
+ * visualization of a Scala syntax tree.
+ *
+ * @group Printers
*/
def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None): String =
render(any, newRawTreePrinter(_), printTypes, printIds, printKinds, printMirrors)
/** Hook to define what `showRaw(...)` means.
+ * @group Printers
*/
- def newRawTreePrinter(out: PrintWriter): TreePrinter
+ protected def newRawTreePrinter(out: PrintWriter): TreePrinter
/** Renders a prettified representation of a name.
+ * @group Printers
*/
def show(name: Name): String
/** Renders internal structure of a name.
+ * @group Printers
*/
def showRaw(name: Name): String = name.toString
/** Renders a prettified representation of a flag set.
+ * @group Printers
*/
def show(flags: FlagSet): String
/** Renders internal structure of a flag set.
+ * @group Printers
*/
def showRaw(flags: FlagSet): String = flags.toString
}
diff --git a/src/reflect/scala/reflect/api/Scopes.scala b/src/reflect/scala/reflect/api/Scopes.scala
index d30da07ad5..80683c8e76 100644
--- a/src/reflect/scala/reflect/api/Scopes.scala
+++ b/src/reflect/scala/reflect/api/Scopes.scala
@@ -1,34 +1,57 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for scopes.
+/** This trait provides support for scopes in the reflection API.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * A scope object generally maps names to symbols available in a corresponding lexical scope.
+ * Scopes can be nested. The base type exposed to the reflection API, however,
+ * only exposes a minimal interface, representing a scope as an iterable of symbols.
+ *
+ * For rare occasions when it is necessary to create a scope manually,
+ * e.g., to populate members of [[scala.reflect.api.Types#RefinedType]],
+ * there is the `newScopeWith` function.
+ *
+ * Additional functionality is exposed in member scopes that are returned by
+ * `members` and `declarations` defined in [[scala.reflect.api.Types#TypeApi]].
+ * Such scopes support the `sorted` method, which sorts members in declaration order.
*/
trait Scopes { self: Universe =>
- /** The base type of all scopes. A scope object generally maps names to symbols available in the current lexical scope.
- * Scopes can be nested. This base type, however, only exposes a minimal interface, representing a scope as an iterable of symbols.
+ /** The base type of all scopes.
+ * @template
+ * @group Scopes
*/
type Scope >: Null <: ScopeApi
- /** The API that all scopes support */
+ /** The API that all scopes support
+ * @group API
+ */
trait ScopeApi extends Iterable[Symbol]
/** A tag that preserves the identity of the `Scope` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ScopeTag: ClassTag[Scope]
- /** The type of member scopes, as in class definitions, for example. */
+ /** Create a new scope with the given initial elements.
+ * @group Scopes
+ */
+ def newScopeWith(elems: Symbol*): Scope
+
+ /** The type of member scopes, as in class definitions, for example.
+ * @template
+ * @group Scopes
+ */
type MemberScope >: Null <: Scope with MemberScopeApi
- /** The API that all member scopes support */
+ /** The API that all member scopes support
+ * @group API
+ */
trait MemberScopeApi extends ScopeApi {
/** Sorts the symbols included in this scope so that:
* 1) Symbols appear in the linearization order of their owners.
- * 2) Symbols with the same owner appear in reverse order of their declarations.
+ * 2) Symbols with the same owner appear in same order of their declarations.
* 3) Synthetic members (e.g. getters/setters for vals/vars) might appear in arbitrary order.
*/
def sorted: List[Symbol]
@@ -36,15 +59,7 @@ trait Scopes { self: Universe =>
/** A tag that preserves the identity of the `MemberScope` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MemberScopeTag: ClassTag[MemberScope]
-
- /** Create a new scope. */
- def newScope: Scope
-
- /** Create a new scope nested in another one with which it shares its elements. */
- def newNestedScope(outer: Scope): Scope
-
- /** Create a new scope with the given initial elements. */
- def newScopeWith(elems: Symbol*): Scope
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala
index 03f2a6b0aa..a31a501357 100644
--- a/src/reflect/scala/reflect/api/StandardDefinitions.scala
+++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala
@@ -5,139 +5,305 @@
package scala.reflect
package api
-/**
- * Defines standard symbols and types.
+/** All Scala standard symbols and types.
+ *
+ * These standard definitions can accessed to using `definitions`.
+ * They're typically imported with a blanket import `import definitions`, and are
+ * listed in [[scala.reflect.api.StandardDefinitions#DefinitionsApi]].
*/
trait StandardDefinitions {
self: Universe =>
- /** A value containing all standard defnitions. */
+ /** A value containing all standard definitions in [[DefinitionsApi]]
+ * @group Definitions
+ */
val definitions: DefinitionsApi
- /** Defines standard symbols (and types via its base trait). */
+ /** Defines standard symbols (and types via its base trait).
+ * @group API
+ */
trait DefinitionsApi extends StandardTypes {
- /** The class symbol of package `scala`. */
+ /** The module class symbol of package `scala`. */
def ScalaPackageClass: ClassSymbol
- /** The module class symbol of package `scala`. */
+ /** The module symbol of package `scala`. */
def ScalaPackage: ModuleSymbol
- // top types
+ /** The class symbol of core class `scala.Any`. */
def AnyClass : ClassSymbol
+
+ /** The class symbol of core class `scala.AnyVal`. */
def AnyValClass: ClassSymbol
+
+ /** The class symbol of core class `java.lang.Object`. */
def ObjectClass: ClassSymbol
+
+ /** The type symbol of core class `scala.AnyRef`. */
def AnyRefClass: TypeSymbol
- // bottom types
+ /** The class symbol of core class `scala.Null`. */
def NullClass : ClassSymbol
+
+ /** The class symbol of core class `scala.Nothing`. */
def NothingClass: ClassSymbol
- // the scala value classes
+ /** The class symbol of primitive class `scala.Unit`. */
def UnitClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Byte`. */
def ByteClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Short`. */
def ShortClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Char`. */
def CharClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Int`. */
def IntClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Long`. */
def LongClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Float`. */
def FloatClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Double`. */
def DoubleClass : ClassSymbol
+
+ /** The class symbol of primitive class `scala.Boolean`. */
def BooleanClass: ClassSymbol
- /** The class symbol of class `String`. */
+ /** The class symbol of class `scala.String`. */
def StringClass : ClassSymbol
- /** The class symbol of class `Class`. */
+ /** The class symbol of class `java.lang.Class`. */
def ClassClass : ClassSymbol
- /** The class symbol of class `Array`. */
+ /** The class symbol of class `scala.Array`. */
def ArrayClass : ClassSymbol
- /** The class symbol of class `List`. */
+ /** The class symbol of class `scala.List`. */
def ListClass : ClassSymbol
- /** The module symbol of `scala.Predef`. */
+ /** The module symbol of module `scala.Predef`. */
def PredefModule: ModuleSymbol
+ /** The module class symbol of package `java.lang`. */
def JavaLangPackageClass: ClassSymbol
+
+ /** The module symbol of package `java.lang`. */
def JavaLangPackage: ModuleSymbol
+
+ /** The module symbol of module `scala.Array`. */
def ArrayModule: ModuleSymbol
+
+ /** The method symbol of method `apply` in module `scala.Array`. */
def ArrayModule_overloadedApply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `apply` in class `scala.Array`. */
def Array_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `clone` in class `scala.Array`. */
def Array_clone: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `length` in class `scala.Array`. */
def Array_length: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The method symbol of method `update` in class `scala.Array`. */
def Array_update: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** A dummy class symbol that is used to indicate by-name parameters.
+ *
+ * {{{
+ * scala> class C { def m(x: => Int) = ??? }
+ * defined class C
+ *
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = => scala.Int
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<byname>, // <-- ByNameParamClass
+ * List(TypeRef(ThisType(scala), scala.Int, List())))
+ * }}}
+ */
def ByNameParamClass: ClassSymbol
- def ConsClass: ClassSymbol
- def FunctionClass : Array[ClassSymbol]
- def IterableClass: ClassSymbol
- def IteratorClass: ClassSymbol
- def IteratorModule: ModuleSymbol
- def Iterator_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** A dummy class symbol that is used to indicate repeated parameters
+ * compiled by the Java compiler.
+ *
+ * {{{
+ * class C {
+ * public void m(Object... x) {}
+ * }
+ * }}}
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = <repeated...>[Object]
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<repeated...>, // <-- JavaRepeatedParamClass
+ * List(TypeRef(ThisType(java.lang), Object, List())))
+ * }}}
+ */
def JavaRepeatedParamClass: ClassSymbol
+
+ /** A dummy class symbol that is used to indicate repeated parameters
+ * compiled by the Scala compiler.
+ *
+ * {{{
+ * scala> class C { def m(x: Int*) = ??? }
+ * defined class C
+ *
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> val m = typeOf[C].member(newTermName("m")).asMethod
+ * m: reflect.runtime.universe.MethodSymbol = method m
+ *
+ * scala> m.params(0)(0).typeSignature
+ * res1: reflect.runtime.universe.Type = scala.Int*
+ *
+ * scala> showRaw(m.params(0)(0).typeSignature)
+ * res2: String = TypeRef(
+ * ThisType(scala),
+ * scala.<repeated>, // <-- RepeatedParamClass
+ * List(TypeRef(ThisType(scala), scala.Int, List())))
+ * }}}
+ */
+ def RepeatedParamClass: ClassSymbol
+
+ /** The module symbol of module `scala.List`. */
def ListModule: ModuleSymbol
+
+ /** The method symbol of method `apply` in class `scala.List`. */
def List_apply: TermSymbol // todo. fix the bug in Definitions.getMemberMethod
+
+ /** The module symbol of module `scala.collection.immutable.Nil`. */
def NilModule: ModuleSymbol
- def NoneModule: ModuleSymbol
+
+ /** The class symbol of class `scala.Option`. */
def OptionClass: ClassSymbol
- def ProductClass : Array[ClassSymbol]
- def RepeatedParamClass: ClassSymbol
- def SeqClass: ClassSymbol
- def SeqModule: ModuleSymbol
- def SomeClass: ClassSymbol
+
+ /** The module symbol of module `scala.None`. */
+ def NoneModule: ModuleSymbol
+
+ /** The module symbol of module `scala.Some`. */
def SomeModule: ModuleSymbol
- def StringBuilderClass: ClassSymbol
- def SymbolClass : ClassSymbol
- def TraversableClass: ClassSymbol
+
+ /** The array of class symbols for classes `scala.ProductX`.
+ * - 0th element is `Unit`
+ * - 1st element is `Product1`
+ * - ...
+ * - 22nd element is `Product22`
+ */
+ def ProductClass : Array[ClassSymbol]
+
+ /** The array of class symbols for classes `scala.FunctionX`.
+ * - 0th element is `Function0`
+ * - 1st element is `Function1`
+ * - ...
+ * - 22nd element is `Function22`
+ */
+ def FunctionClass : Array[ClassSymbol]
+
+ /** The array of class symbols for classes `scala.TupleX`.
+ * - 0th element is `NoSymbol`
+ * - 1st element is `Product1`
+ * - ...
+ * - 22nd element is `Product22`
+ */
def TupleClass: Array[Symbol] // cannot make it Array[ClassSymbol], because TupleClass(0) is supposed to be NoSymbol. weird
+
+ /** Contains Scala primitive value classes:
+ * - Byte
+ * - Short
+ * - Int
+ * - Long
+ * - Float
+ * - Double
+ * - Char
+ * - Boolean
+ * - Unit
+ */
def ScalaPrimitiveValueClasses: List[ClassSymbol]
+
+ /** Contains Scala numeric value classes:
+ * - Byte
+ * - Short
+ * - Int
+ * - Long
+ * - Float
+ * - Double
+ * - Char
+ */
def ScalaNumericValueClasses: List[ClassSymbol]
}
- /** Defines standard types. */
+ /** Defines standard types.
+ * @group Definitions
+ */
trait StandardTypes {
- /** The `Type` of type `Unit`. */
+ /** The type of primitive type `Unit`. */
val UnitTpe: Type
- /** The `Type` of primitive type `Byte`. */
+ /** The type of primitive type `Byte`. */
val ByteTpe: Type
- /** The `Type` of primitive type `Short`. */
+ /** The type of primitive type `Short`. */
val ShortTpe: Type
- /** The `Type` of primitive type `Char`. */
+ /** The type of primitive type `Char`. */
val CharTpe: Type
- /** The `Type` of primitive type `Int`. */
+ /** The type of primitive type `Int`. */
val IntTpe: Type
- /** The `Type` of primitive type `Long`. */
+ /** The type of primitive type `Long`. */
val LongTpe: Type
- /** The `Type` of primitive type `Float`. */
+ /** The type of primitive type `Float`. */
val FloatTpe: Type
- /** The `Type` of primitive type `Double`. */
+ /** The type of primitive type `Double`. */
val DoubleTpe: Type
- /** The `Type` of primitive type `Boolean`. */
+ /** The type of primitive type `Boolean`. */
val BooleanTpe: Type
- /** The `Type` of type `Any`. */
+ /** The type of core type `Any`. */
val AnyTpe: Type
- /** The `Type` of type `AnyVal`. */
+ /** The type of core type `AnyVal`. */
val AnyValTpe: Type
- /** The `Type` of type `AnyRef`. */
+ /** The type of core type `AnyRef`. */
val AnyRefTpe: Type
- /** The `Type` of type `Object`. */
+ /** The type of core type `Object`. */
val ObjectTpe: Type
- /** The `Type` of type `Nothing`. */
+ /** The type of core type `Nothing`. */
val NothingTpe: Type
- /** The `Type` of type `Null`. */
+ /** The type of core type `Null`. */
val NullTpe: Type
}
}
diff --git a/src/reflect/scala/reflect/api/StandardNames.scala b/src/reflect/scala/reflect/api/StandardNames.scala
index 354a9f9328..fc18c02706 100644
--- a/src/reflect/scala/reflect/api/StandardNames.scala
+++ b/src/reflect/scala/reflect/api/StandardNames.scala
@@ -10,35 +10,95 @@ package api
// Is it necessary to perform reflection (like ERROR or LOCAL_SUFFIX_STRING)? If yes, then sure.
// Otherwise you'd better not - reflection API should stay minimalistic.
-// TODO: document better
/**
- * Names necessary to create Scala trees.
+ * Standard names are names that are essential to creating trees or to reflecting Scala artifacts.
+ * For example, `CONSTRUCTOR` (aka `<init>` on JVM) is necessary to create and invoke constructors.
+ *
+ * These standard names can be referred to using [[nme `nme`]] for term names and [[tpnme `tpnme`]] for type names
+ *
+ * @see [[Names]]
+ *
+ * The API for names in Scala reflection.
+ * @groupname StandardNames Standard Names
*/
trait StandardNames {
self: Universe =>
+ /** A value containing all [[TermNamesApi standard term names]].
+ * @group StandardNames
+ */
val nme: TermNamesApi
+
+ /** A value containing all [[TypeNamesApi standard type names]].
+ * @group StandardNames
+ */
val tpnme: TypeNamesApi
+ /** Defines standard names, common for term and type names: These can be accessed via the [[nme]] and [[tpnme]] members.
+ * @group API
+ */
trait NamesApi {
+ /** An abstract type that represents the exact flavor of the name. */
type NameType >: Null <: Name
+
+ /** The term or type name `_`.
+ * Used to construct trees that correspond to underscores in Scala.
+ */
val WILDCARD: NameType
- val ROOT: NameType
+
+ /** The term or type name corresponding to an empty string.
+ * Represents an empty name, used to denote the fact that no name was specified
+ * for `privateWithin` in [[Trees#Modifiers]], for [[Trees#This]],
+ * for [[Trees#Super]], etc.
+ */
val EMPTY: NameType
+
+ /** The term or type name `<error>`.
+ * Indicates that the enclosing tree or symbol contains a compilation error.
+ */
val ERROR: NameType
+
+ /** The term or type name `package`.
+ * Used to get modules representing package objects.
+ */
val PACKAGE: NameType
}
+ /** Defines standard term names that can be accessed via the [[nme]] member.
+ * @group API
+ */
trait TermNamesApi extends NamesApi {
+ /** @inheritdoc */
type NameType = TermName
+
+ /** The term name `<init>`.
+ * Represents the constructor name on the JVM.
+ */
val CONSTRUCTOR: NameType
+
+ /** The term name `_root_`.
+ * Represents the root package.
+ */
val ROOTPKG: NameType
+
+ /** The string " " (a single whitespace).
+ * `LOCAL_SUFFIX_STRING` is appended to the names of local identifiers,
+ * when it's necessary to prevent a naming conflict. For example, underlying fields
+ * of non-private vals and vars are renamed using `LOCAL_SUFFIX_STRING`.
+ */
val LOCAL_SUFFIX_STRING: String
}
+ /** Defines standard type names that can be accessed via the [[tpnme]] member.
+ * @group API
+ */
trait TypeNamesApi extends NamesApi {
+ /** @inheritdoc */
type NameType = TypeName
- val EMPTY: NameType
+
+ /** The type name `_*`.
+ * Used to construct types that specify sequence arguments to repeated parameters.
+ */
val WILDCARD_STAR: NameType
}
}
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index e456428338..993cbd97a5 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -1,85 +1,164 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for symbols
+/** This trait defines symbols and operations on them.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * Symbols are used to establish bindings between a name and the entity it refers to, such as a class or a method.
+ * Anything you define and can give a name to in Scala has an associated symbol.
+ *
+ * Certain types of tree nodes, such as [[Trees#Ident Ident]] (references to identifiers) and
+ * [[Trees#Select Select]] (references to members) expose method [[Trees.SymTreeApi.symbol `symbol`]]
+ * to obtain the symbol that represents their declaration. During the typechecking phase, the compiler looks up the
+ * symbol based on the name and scope and sets the [[Trees.SymTreeApi.symbol `symbol` field]] of tree nodes.
+ *
+ * @contentDiagram hideNodes "*Api"
+ *
+ * @see [[http://docs.scala-lang.org/overviews/reflection/overview.html]]
+ *
+ * The Reflection Guide provides more details on symbol usage and attached intricacies.
+ *
+ * @define SYMACCESSORS Class [[Symbol]] defines `isXXX` test methods such as `isPublic` or `isFinal`, `params` and
+ * `returnType` methods for method symbols, `baseClasses` for class symbols and so on. Some of these methods don't
+ * make sense for certain subclasses of `Symbol` and return `NoSymbol`, `Nil` or other empty values.
*/
trait Symbols { self: Universe =>
- /** The type of symbols representing declarations */
+ /** The type of symbols representing declarations.
+ * @group Symbols
+ * @template
+ */
type Symbol >: Null <: SymbolApi
/** A tag that preserves the identity of the `Symbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SymbolTag: ClassTag[Symbol]
/** The type of type symbols representing type, class, and trait declarations,
- * as well as type parameters
+ * as well as type parameters.
+ * @group Symbols
+ * @template
*/
type TypeSymbol >: Null <: Symbol with TypeSymbolApi
/** A tag that preserves the identity of the `TypeSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeSymbolTag: ClassTag[TypeSymbol]
/** The type of term symbols representing val, var, def, and object declarations as
* well as packages and value parameters.
+ * @group Symbols
+ * @template
*/
type TermSymbol >: Null <: Symbol with TermSymbolApi
/** A tag that preserves the identity of the `TermSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TermSymbolTag: ClassTag[TermSymbol]
- /** The type of method symbols representing def declarations */
+ /** The type of method symbols representing def declarations.
+ * @group Symbols
+ * @template
+ */
type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi
/** A tag that preserves the identity of the `MethodSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MethodSymbolTag: ClassTag[MethodSymbol]
- /** The type of module symbols representing object declarations */
+ /** The type of module symbols representing object declarations.
+ * @group Symbols
+ * @template
+ */
type ModuleSymbol >: Null <: TermSymbol with ModuleSymbolApi
/** A tag that preserves the identity of the `ModuleSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ModuleSymbolTag: ClassTag[ModuleSymbol]
- /** The type of class symbols representing class and trait definitions */
+ /** The type of class symbols representing class and trait definitions.
+ * @group Symbols
+ * @template
+ */
type ClassSymbol >: Null <: TypeSymbol with ClassSymbolApi
/** A tag that preserves the identity of the `ClassSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassSymbolTag: ClassTag[ClassSymbol]
- /** The type of free terms introduced by reification */
+ /** The type of free terms introduced by reification.
+ * @group Symbols
+ * @template
+ */
type FreeTermSymbol >: Null <: TermSymbol with FreeTermSymbolApi
/** A tag that preserves the identity of the `FreeTermSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FreeTermSymbolTag: ClassTag[FreeTermSymbol]
- /** The type of free types introduced by reification */
+ /** The type of free types introduced by reification.
+ * @group Symbols
+ * @template
+ */
type FreeTypeSymbol >: Null <: TypeSymbol with FreeTypeSymbolApi
/** A tag that preserves the identity of the `FreeTypeSymbol` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FreeTypeSymbolTag: ClassTag[FreeTypeSymbol]
- /** A special "missing" symbol */
+ /** A special "missing" symbol. Commonly used in the API to denote a default or empty value.
+ * @group Symbols
+ * @template
+ */
val NoSymbol: Symbol
- /** The API of symbols */
+ /** The API of symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ * @groupname Basics Symbol Basic Information
+ * @groupprio Basics 0
+ * @groupname Tests Symbol Type Tests
+ * @groupprio Tests 1
+ * @groupname Conversions Symbol Conversions
+ * @groupprio Conversions 2
+ * @groupname Constructors New Symbol Constructors
+ * @groupprio Constructors 3
+ * @groupdesc Constructors These methods construct new symbols owned by the current symbol.
+ * @groupname Helpers Iteration Helpers
+ * @groupprio Helpers 4
+ * @groupdesc Helpers These methods enable collections-like operations on symbols.
+ * @groupname Type TypeSymbol Members
+ * @groupprio Type -1
+ * @groupname FreeType FreeType Symbol Members
+ * @groupprio FreeType -2
+ * @groupname Term TermSymbol Members
+ * @groupprio Term -1
+ * @groupname FreeTerm FreeTerm Symbol Members
+ * @groupprio FreeTerm -2
+ * @groupname Class Class Symbol Members
+ * @groupprio Class -2
+ * @groupname Method Method Symbol Members
+ * @groupprio Method -2
+ * @groupname Module Module Symbol Members
+ * @groupprio Module -2
+ */
trait SymbolApi { this: Symbol =>
/** The owner of this symbol. This is the symbol
@@ -90,6 +169,8 @@ trait Symbols { self: Universe =>
* and the Scala root object [[scala.reflect.api.Mirror.RootPackage]] is `NoSymbol`.
* Every other symbol has a chain of owners that ends in
* [[scala.reflect.api.Mirror.RootClass]].
+ *
+ * @group Basics
*/
def owner: Symbol
@@ -98,15 +179,18 @@ trait Symbols { self: Universe =>
*
* Type name namespaces do not intersect with term name namespaces.
* This fact is reflected in different types for names of `TermSymbol` and `TypeSymbol`.
+ * @group Basics
*/
type NameType >: Null <: Name
/** The name of the symbol as a member of the `Name` type.
+ * @group Basics
*/
def name: Name
/** The encoded full path name of this symbol, where outer names and inner names
* are separated by periods.
+ * @group Basics
*/
def fullName: String
@@ -114,11 +198,15 @@ trait Symbols { self: Universe =>
* Note that every symbol is either a term or a type.
* So for every symbol `sym` (except for `NoSymbol`),
* either `sym.isTerm` is true or `sym.isType` is true.
+ *
+ * @group Tests
*/
def isType: Boolean = false
/** This symbol cast to a TypeSymbol.
* @throws ScalaReflectionException if `isType` is false.
+ *
+ * @group Conversions
*/
def asType: TypeSymbol = throw new ScalaReflectionException(s"$this is not a type")
@@ -126,21 +214,29 @@ trait Symbols { self: Universe =>
* Note that every symbol is either a term or a type.
* So for every symbol `sym` (except for `NoSymbol`),
* either `sym.isTerm` is true or `sym.isTerm` is true.
+ *
+ * @group Tests
*/
def isTerm: Boolean = false
/** This symbol cast to a TermSymbol.
* @throws ScalaReflectionException if `isTerm` is false.
+ *
+ * @group Conversions
*/
def asTerm: TermSymbol = throw new ScalaReflectionException(s"$this is not a term")
/** Does this symbol represent the definition of a method?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isMethod: Boolean = false
/** This symbol cast to a MethodSymbol.
* @throws ScalaReflectionException if `isMethod` is false.
+ *
+ * @group Conversions
*/
def asMethod: MethodSymbol = {
def overloadedMsg =
@@ -151,92 +247,135 @@ trait Symbols { self: Universe =>
throw new ScalaReflectionException(s"$this $msg")
}
- /** Used to provide a better error message for `asMethod` */
+ /** Used to provide a better error message for `asMethod`
+ *
+ * @group Tests
+ */
protected def isOverloadedMethod = false
/** Does this symbol represent the definition of a module (i.e. it
* results from an object definition?).
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isModule: Boolean = false
/** This symbol cast to a ModuleSymbol defined by an object definition.
* @throws ScalaReflectionException if `isModule` is false.
+ *
+ * @group Conversions
*/
def asModule: ModuleSymbol = throw new ScalaReflectionException(s"$this is not a module")
/** Does this symbol represent the definition of a class or trait?
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isClass: Boolean = false
/** Does this symbol represent the definition of a class implicitly associated
* with an object definition (module class in scala compiler parlance).
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isModuleClass: Boolean = false
/** This symbol cast to a ClassSymbol representing a class or trait.
* @throws ScalaReflectionException if `isClass` is false.
+ *
+ * @group Conversions
*/
def asClass: ClassSymbol = throw new ScalaReflectionException(s"$this is not a class")
/** Does this symbol represent a free term captured by reification?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isFreeTerm: Boolean = false
/** This symbol cast to a free term symbol.
* @throws ScalaReflectionException if `isFreeTerm` is false.
+ *
+ * @group Conversions
*/
def asFreeTerm: FreeTermSymbol = throw new ScalaReflectionException(s"$this is not a free term")
/** Does this symbol represent a free type captured by reification?
* If yes, `isType` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isFreeType: Boolean = false
/** This symbol cast to a free type symbol.
* @throws ScalaReflectionException if `isFreeType` is false.
+ *
+ * @group Conversions
*/
def asFreeType: FreeTypeSymbol = throw new ScalaReflectionException(s"$this is not a free type")
+ /** @group Constructors */
def newTermSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TermSymbol
+ /** @group Constructors */
def newModuleAndClassSymbol(name: Name, pos: Position = NoPosition, flags: FlagSet = NoFlags): (ModuleSymbol, ClassSymbol)
+ /** @group Constructors */
def newMethodSymbol(name: TermName, pos: Position = NoPosition, flags: FlagSet = NoFlags): MethodSymbol
+ /** @group Constructors */
def newTypeSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): TypeSymbol
+ /** @group Constructors */
def newClassSymbol(name: TypeName, pos: Position = NoPosition, flags: FlagSet = NoFlags): ClassSymbol
/** Source file if this symbol is created during this compilation run,
* or a class file if this symbol is loaded from a *.class or *.jar.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
+ *
+ * @group Basics
*/
def associatedFile: scala.reflect.io.AbstractFile
/** A list of annotations attached to this Symbol.
+ *
+ * @group Basics
*/
def annotations: List[Annotation]
/** For a class: the module or case class factory with the same name in the same package.
* For a module: the class with the same name in the same package.
* For all others: NoSymbol
+ *
+ * @group Basics
*/
def companionSymbol: Symbol
/** The type signature of this symbol seen as a member of given type `site`.
+ *
+ * @group Basics
*/
def typeSignatureIn(site: Type): Type
/** The type signature of this symbol.
- * Note if the symbol is a member of a class, one almost always is interested
- * in `typeSignatureIn` with a site type instead.
+ *
+ * This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
+ * instantiation of a generic type. For example, signature
+ * of the method `def map[B](f: (A) ⇒ B): List[B]`, which refers to the type parameter `A` of the declaring class `List[A]`,
+ * will always feature `A`, regardless of whether `map` is loaded from the `List[_]` or from `List[Int]`. To get a signature
+ * with type parameters appropriately instantiated, one should use `typeSignatureIn`.
+ *
+ * @group Basics
*/
def typeSignature: Type
- /** Returns all symbols overriden by this symbol. */
+ /** Returns all symbols overriden by this symbol.
+ *
+ * @group Basics
+ */
def allOverriddenSymbols: List[Symbol]
/******************* tests *******************/
@@ -244,11 +383,15 @@ trait Symbols { self: Universe =>
/** Does this symbol represent a synthetic (i.e. a compiler-generated) entity?
* Examples of synthetic entities are accessors for vals and vars
* or mixin constructors in trait implementation classes.
+ *
+ * @group Tests
*/
def isSynthetic: Boolean
/** Does this symbol represent an implementation artifact that isn't meant for public use?
- * Examples of such artifacts are erasure bridges and $outer fields.
+ * Examples of such artifacts are erasure bridges and outer fields.
+ *
+ * @group Tests
*/
def isImplementationArtifact: Boolean
@@ -258,20 +401,28 @@ trait Symbols { self: Universe =>
* Local symbols can only be accessed from the same object instance.
*
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isLocal: Boolean
/** Does this symbol represent a private declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isPrivate: Boolean
/** Does this symbol represent a protected declaration or definition?
* If yes, `privateWithin` might tell more about this symbol's visibility scope.
+ *
+ * @group Tests
*/
def isProtected: Boolean
/** Does this symbol represent a public declaration or definition?
+ *
+ * @group Tests
*/
def isPublic: Boolean
@@ -299,20 +450,28 @@ trait Symbols { self: Universe =>
* java package: !isPrivate && !isProtected && (privateWithin == enclosingPackage)
* java protected: isProtected && (privateWithin == enclosingPackage)
* java public: !isPrivate && !isProtected && (privateWithin == NoSymbol)
+ *
+ * @group Tests
*/
def privateWithin: Symbol
/** Does this symbol represent the definition of a package?
* If yes, `isTerm` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isPackage: Boolean
/** Does this symbol represent a package class?
* If yes, `isClass` is also guaranteed to be true.
+ *
+ * @group Tests
*/
def isPackageClass: Boolean
/** Does this symbol or its underlying type represent a typechecking error?
+ *
+ * @group Tests
*/
def isErroneous : Boolean
@@ -320,62 +479,96 @@ trait Symbols { self: Universe =>
* Q: When exactly is a sym marked as STATIC?
* A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
* http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
+ *
+ * @group Tests
*/
def isStatic: Boolean
/** Is this symbol final?
+ *
+ * @group Tests
*/
def isFinal: Boolean
/** Is this symbol overriding something?
+ *
+ * @group Tests
*/
def isOverride: Boolean
/** Is this symbol labelled as "abstract override"?
+ *
+ * @group Tests
*/
def isAbstractOverride: Boolean
/** Is this symbol a macro?
+ *
+ * @group Tests
*/
def isMacro: Boolean
/** Is this symbol a parameter (either a method parameter or a type parameter)?
+ *
+ * @group Tests
*/
def isParameter: Boolean
/** Is this symbol a specialized type parameter or a generated specialized member?
+ *
+ * @group Tests
*/
def isSpecialized: Boolean
/** Is this symbol defined by Java?
+ *
+ * @group Tests
*/
def isJava: Boolean
/** Does this symbol represent an implicit value, definition, class or parameter?
+ *
+ * @group Tests
*/
def isImplicit: Boolean
/******************* helpers *******************/
- /** ...
+ /** Provides an alternate if symbol is a NoSymbol.
+ *
+ * @group Helpers
*/
def orElse(alt: => Symbol): Symbol
- /** ...
+ /** Filters the underlying alternatives (or a single-element list
+ * composed of the symbol itself if the symbol is not overloaded).
+ * Returns an overloaded symbol is there are multiple matches.
+ * Returns a NoSymbol if there are no matches.
+ *
+ * @group Helpers
*/
def filter(cond: Symbol => Boolean): Symbol
/** If this is a NoSymbol, returns NoSymbol, otherwise
* returns the result of applying `f` to this symbol.
+ *
+ * @group Helpers
*/
def map(f: Symbol => Symbol): Symbol
- /** ...
+ /** Does the same as `filter`, but crashes if there are multiple matches.
+ *
+ * @group Helpers
*/
def suchThat(cond: Symbol => Boolean): Symbol
}
- /** The API of term symbols */
+ /** The API of term symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait TermSymbolApi extends SymbolApi { this: TermSymbol =>
/** Term symbols have their names of type `TermName`.
*/
@@ -385,78 +578,117 @@ trait Symbols { self: Universe =>
final override def asTerm = this
/** Is this symbol introduced as `val`?
+ *
+ * @group Term
*/
def isVal: Boolean
- /** Does this symbol denote a stable value? */
+ /** Does this symbol denote a stable value?
+ *
+ * @group Term
+ */
def isStable: Boolean
/** Is this symbol introduced as `var`?
+ *
+ * @group Term
*/
def isVar: Boolean
/** Does this symbol represent a getter or a setter?
+ *
+ * @group Term
*/
def isAccessor: Boolean
/** Does this symbol represent a getter of a field?
* If yes, `isMethod` is also guaranteed to be true.
+ *
+ * @group Term
*/
def isGetter: Boolean
/** Does this symbol represent a setter of a field?
* If yes, `isMethod` is also guaranteed to be true.
+ *
+ * @group Term
*/
def isSetter: Boolean
/** Does this symbol represent an overloaded method?
* If yes, `isMethod` is false, and the list of the enclosed alternatives can be found out via `alternatives`.
+ *
+ * @group Term
*/
def isOverloaded : Boolean
/** Does this symbol represent a lazy value?
+ *
+ * @group Term
*/
def isLazy: Boolean
- /** The overloaded alternatives of this symbol */
+ /** The overloaded alternatives of this symbol
+ *
+ * @group Term
+ */
def alternatives: List[Symbol]
/** Used to provide a better error message for `asMethod` */
override protected def isOverloadedMethod = alternatives exists (_.isMethod)
/** Backing field for an accessor method, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def accessed: Symbol
/** Getter method for a backing field of a val or a val, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def getter: Symbol
/** Setter method for a backing field of a val or a val, NoSymbol for all other term symbols.
+ *
+ * @group Term
*/
def setter: Symbol
/** Does this symbol represent a field of a class
* that was generated from a parameter of that class?
+ *
+ * @group Term
*/
def isParamAccessor: Boolean
/** Does this symbol represent a field of a case class
* that corresponds to a parameter in the first parameter list of the
* primary constructor of that class?
+ *
+ * @group Term
*/
def isCaseAccessor: Boolean
/** Does this symbol represent a parameter with a default value?
+ *
+ * @group Term
*/
def isParamWithDefault: Boolean
/** Does this symbol represent a by-name parameter?
+ *
+ * @group Term
*/
def isByNameParam: Boolean
}
- /** The API of type symbols */
+ /** The API of type symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait TypeSymbolApi extends SymbolApi { this: TypeSymbol =>
/** Type symbols have their names of type `TypeName`.
*/
@@ -468,11 +700,15 @@ trait Symbols { self: Universe =>
*
* Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
* `C`. Then `C.toType` is the type `C[T]`, but `C.toTypeConstructor` is `C`.
+ *
+ * @group Type
*/
def toTypeConstructor: Type
/** A type reference that refers to this type symbol seen
* as a member of given type `site`.
+ *
+ * @group Type
*/
def toTypeIn(site: Type): Type
@@ -486,42 +722,64 @@ trait Symbols { self: Universe =>
* By contrast, `C.typeSignature` would be a type signature of form
* `PolyType(ClassInfoType(...))` that describes type parameters, value
* parameters, parent types, and members of `C`.
- */
+ *
+ * @group Type
+ */
def toType: Type
final override def isType = true
final override def asType = this
/** Is the type parameter represented by this symbol contravariant?
+ *
+ * @group Type
*/
def isContravariant : Boolean
/** Is the type parameter represented by this symbol contravariant?
+ *
+ * @group Type
*/
def isCovariant : Boolean
/** Does this symbol represent the definition of a skolem?
* Skolems are used during typechecking to represent type parameters viewed from inside their scopes.
+ *
+ * @group Type
*/
def isSkolem : Boolean
/** Does this symbol represent the definition of a type alias?
+ *
+ * @group Type
*/
def isAliasType : Boolean
/** Does this symbol represent the definition of an abstract type?
+ *
+ * @group Type
*/
def isAbstractType : Boolean
/** Does this symbol represent an existentially bound type?
+ *
+ * @group Type
*/
def isExistential : Boolean
- /** For a polymorphic type, its type parameters, the empty list for all other types */
+ /** For a polymorphic type, its type parameters, the empty list for all other types
+ *
+ * @group Type
+ */
def typeParams: List[Symbol]
}
- /** The API of method symbols */
+ /** The API of method symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol =>
final override def isMethod = true
final override def asMethod = this
@@ -530,13 +788,21 @@ trait Symbols { self: Universe =>
*
* If `owner` is a class, then this is a vanilla JVM constructor.
* If `owner` is a trait, then this is a mixin constructor.
+ *
+ * @group Method
*/
def isConstructor: Boolean
- /** Does this symbol denote the primary constructor of its enclosing class? */
+ /** Does this symbol denote the primary constructor of its enclosing class?
+ *
+ * @group Method
+ */
def isPrimaryConstructor: Boolean
- /** For a polymorphic method, its type parameters, the empty list for all other methods */
+ /** For a polymorphic method, its type parameters, the empty list for all other methods
+ *
+ * @group Method
+ */
def typeParams: List[Symbol]
/** All parameter lists of the method.
@@ -545,22 +811,36 @@ trait Symbols { self: Universe =>
* Can be used to distinguish nullary methods and methods with empty parameter lists.
* For a nullary method, returns the empty list (i.e. `List()`).
* For a method with an empty parameter list, returns a list that contains the empty list (i.e. `List(List())`).
+ *
+ * @group Method
*/
def paramss: List[List[Symbol]]
/** Does this method support variable length argument lists?
+ *
+ * @group Method
*/
def isVarargs: Boolean
- /** The return type of the method */
+ /** The return type of the method
+ *
+ * @group Method
+ */
def returnType: Type
}
- /** The API of module symbols */
+ /** The API of module symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait ModuleSymbolApi extends TermSymbolApi { this: ModuleSymbol =>
/** The class implicitly associated with the object definition.
* One can go back from a module class to the associated module symbol
* by inspecting its `selfType.termSymbol`.
+ *
+ * @group Module
*/
def moduleClass: Symbol // needed for tree traversals
// when this becomes `moduleClass: ClassSymbol`, it will be the happiest day in my life
@@ -569,7 +849,12 @@ trait Symbols { self: Universe =>
final override def asModule = this
}
- /** The API of class symbols */
+ /** The API of class symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait ClassSymbolApi extends TypeSymbolApi { this: ClassSymbol =>
final override def isClass = true
final override def asClass = this
@@ -577,82 +862,129 @@ trait Symbols { self: Universe =>
/** Does this symbol represent the definition of a primitive class?
* Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
* [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ *
+ * @group Class
*/
def isPrimitive: Boolean
/** Does this symbol represent the definition of a numeric value class?
* Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
* [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ *
+ * @group Class
*/
def isNumeric: Boolean
/** Does this symbol represent the definition of a custom value class?
* Namely, is AnyVal among its parent classes?
+ *
+ * @group Class
*/
def isDerivedValueClass: Boolean
/** Does this symbol represent a trait?
+ *
+ * @group Class
*/
def isTrait: Boolean
/** Does this symbol represent an abstract class?
+ *
+ * @group Class
*/
def isAbstractClass: Boolean
/** Does this symbol represent a case class?
+ *
+ * @group Class
*/
def isCaseClass: Boolean
/** Does this symbol represent a sealed class?
+ *
+ * @group Class
*/
def isSealed: Boolean
/** If this is a sealed class, its known direct subclasses.
* Otherwise, the empty set.
+ *
+ * @group Class
*/
def knownDirectSubclasses: Set[Symbol]
/** The list of all base classes of this type (including its own typeSymbol)
* in reverse linearization order, starting with the class itself and ending
* in class Any.
+ *
+ * @group Class
*/
def baseClasses: List[Symbol]
/** The module corresponding to this module class,
* or NoSymbol if this symbol is not a module class.
+ *
+ * @group Class
*/
def module: Symbol
/** If this symbol is a class or trait, its self type, otherwise the type
* of the symbol itself.
+ *
+ * @group Class
*/
def selfType: Type
- /** The type `C.this`, where `C` is the current class */
+ /** The type `C.this`, where `C` is the current class
+ *
+ * @group Class
+ */
def thisPrefix: Type
- /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait */
+ /** For a polymorphic class/trait, its type parameters, the empty list for all other classes/trait
+ *
+ * @group Class
+ */
def typeParams: List[Symbol]
}
- /** The API of free term symbols */
+ /** The API of free term symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait FreeTermSymbolApi extends TermSymbolApi { this: FreeTermSymbol =>
final override def isFreeTerm = true
final override def asFreeTerm = this
- /** The place where this symbol has been spawned */
+ /** The place where this symbol has been spawned
+ *
+ * @group FreeTerm
+ */
def origin: String
- /** The valus this symbol refers to */
+ /** The valus this symbol refers to
+ *
+ * @group FreeTerm
+ */
def value: Any
}
- /** The API of free term symbols */
+ /** The API of free type symbols.
+ * The main source of information about symbols is the [[Symbols]] page.
+ *
+ * $SYMACCESSORS
+ * @group API
+ */
trait FreeTypeSymbolApi extends TypeSymbolApi { this: FreeTypeSymbol =>
final override def isFreeType = true
final override def asFreeType = this
- /** The place where this symbol has been spawned */
+ /** The place where this symbol has been spawned
+ *
+ * @group FreeType
+ */
def origin: String
}
}
diff --git a/src/reflect/scala/reflect/api/TagInterop.scala b/src/reflect/scala/reflect/api/TagInterop.scala
index fc0558d717..4e43f59706 100644
--- a/src/reflect/scala/reflect/api/TagInterop.scala
+++ b/src/reflect/scala/reflect/api/TagInterop.scala
@@ -1,26 +1,37 @@
package scala.reflect
package api
+/** This trait provides type tag <-> manifest interoperability.
+ * @groupname TagInterop TypeTag and Manifest Interoperability
+ */
trait TagInterop { self: Universe =>
// TODO `mirror` parameters are now of type `Any`, because I can't make these path-dependent types work
// if you're brave enough, replace `Any` with `Mirror`, recompile and run interop_typetags_are_manifests.scala
/**
- * Convert a typetag to a pre `Scala-2.10` manifest.
- * For example
+ * Convert a [[scala.reflect.api.TypeTags#TypeTag]] to a [[scala.reflect.Manifest]].
+ *
+ * Compiler usually generates these conversions automatically, when a type tag for a type `T` is in scope,
+ * and an implicit of type `Manifest[T]` is requested, but this method can also be called manually.
+ * For example:
* {{{
- * typeTagToManifest( scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]] )
+ * typeTagToManifest(scala.reflect.runtime.currentMirror, implicitly[TypeTag[String]])
* }}}
+ * @group TagInterop
*/
def typeTagToManifest[T: ClassTag](mirror: Any, tag: Universe#TypeTag[T]): Manifest[T] =
throw new UnsupportedOperationException("This universe does not support tag -> manifest conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.")
/**
- * Convert a pre `Scala-2.10` manifest to a typetag.
- * For example
+ * Convert a [[scala.reflect.Manifest]] to a [[scala.reflect.api.TypeTags#TypeTag]].
+ *
+ * Compiler usually generates these conversions automatically, when a manifest for a type `T` is in scope,
+ * and an implicit of type `TypeTag[T]` is requested, but this method can also be called manually.
+ * For example:
* {{{
- * manifestToTypeTag( scala.reflect.runtime.currentMirror, implicitly[Manifest[String]] )
+ * manifestToTypeTag(scala.reflect.runtime.currentMirror, implicitly[Manifest[String]])
* }}}
+ * @group TagInterop
*/
def manifestToTypeTag[T](mirror: Any, manifest: Manifest[T]): Universe#TypeTag[T] =
throw new UnsupportedOperationException("This universe does not support manifest -> tag conversions. Use a JavaUniverse, e.g. the scala.reflect.runtime.universe.")
diff --git a/src/reflect/scala/reflect/api/TreeCreator.scala b/src/reflect/scala/reflect/api/TreeCreator.scala
index a8e8ae1b58..cba90b72e6 100644
--- a/src/reflect/scala/reflect/api/TreeCreator.scala
+++ b/src/reflect/scala/reflect/api/TreeCreator.scala
@@ -1,25 +1,9 @@
package scala.reflect
package api
-/** A mirror-aware factory for trees.
+/** This is an internal implementation class.
*
- * In the reflection API, artifacts are specific to universes and
- * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors.
- *
- * Therefore to build a tree one needs to know a universe that the tree is going to be bound to
- * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int`
- * points to a core class `Int` from scala-library.jar).
- *
- * `TreeCreator` implements this notion by providing a standalone tree factory.
- *
- * This is immediately useful for reification. When the compiler reifies an expression,
- * the end result needs to make sense in any mirror. That's because the compiler knows
- * the universe it's reifying an expression into (specified by the target of the `reify` call),
- * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM
- * it doesn't know what classloader use to resolve symbolic names in the reifee).
- *
- * Due to a typechecker restriction (no eta-expansion for dependent method types),
- * `TreeCreator` can't have a functional type, so it's implemented as class with an apply method.
+ * This class is used internally by Scala Reflection, and is not recommended for use in client code.
*/
abstract class TreeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Tree
diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala
index bbd5d00be3..9ff3efc799 100644
--- a/src/reflect/scala/reflect/api/Trees.scala
+++ b/src/reflect/scala/reflect/api/Trees.scala
@@ -5,67 +5,62 @@
package scala.reflect
package api
-// Syncnote: Trees are currently not thread-safe.
+/** This trait defines the node types used in Scala abstract syntax trees (AST) and operations on them.
+ *
+* All tree node types are sub types of [[scala.reflect.api.Trees#Tree Tree]].
+ *
+ * Trees are immutable, except for three fields
+ * [[Trees#TreeApi.pos pos]], [[Trees#TreeApi.symbol symbol]], and [[Trees#TreeApi.tpe tpe]], which are assigned when a tree is typechecked
+ * to attribute it with the information gathered by the typechecker.
+ *
+ * [[scala.reflect.api.Universe#reify reify]] can be used to get the tree for a given Scala expression.
+ *
+ * [[scala.reflect.api.Universe#showRaw showRaw]] can be used to get a readable representation of a tree.
+ *
+ * === Examples ===
+ * `Literal(Constant(5))` creates an AST representing a literal 5 in Scala source code.
+ *
+ * `Apply(Select(Select(This(newTypeName("scala")), newTermName("Predef")), newTermName("print")), List(Literal(Constant("Hello World"))))`
+ * creates an AST representing `print("Hello World")`.
+ *
+ * `import scala.reflect.runtime.universe.{reify,showRaw}`
+ * `print( showRaw( reify{5}.tree ) )` // prints Literal(Constant(5))
+ *
+ * @see [[http://docs.scala-lang.org/overviews/reflection/symbols-trees-types.html#trees]].
+ * @groupname Traversal Tree Traversal and Transformation
+ * @groupprio Traversal 1
+ * @groupprio Factories 1
+ * @groupname Copying Tree Copying
+ * @groupprio Copying 1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
trait Trees { self: Universe =>
- /** Tree is the basis for scala's abstract syntax. The nodes are
- * implemented as case classes, and the parameters which initialize
- * a given tree are immutable: however Trees have several mutable
- * fields which are manipulated in the course of typechecking,
- * including pos, symbol, and tpe.
- *
- * Newly instantiated trees have tpe set to null (though it
- * may be set immediately thereafter depending on how it is
- * constructed.) When a tree is passed to the typer, typically via
- * `typer.typed(tree)`, under normal circumstances the tpe must be
- * null or the typer will ignore it. Furthermore, the typer is not
- * required to return the same tree it was passed.
- *
- * Trees can be easily traversed with e.g. foreach on the root node;
- * for a more nuanced traversal, subclass Traverser. Transformations
- * can be considerably trickier: see the numerous subclasses of
- * Transformer found around the compiler.
- *
- * Copying Trees should be done with care depending on whether
- * it needs be done lazily or strictly (see LazyTreeCopier and
- * StrictTreeCopier) and on whether the contents of the mutable
- * fields should be copied. The tree copiers will copy the mutable
- * attributes to the new tree; calling Tree#duplicate will copy
- * symbol and tpe, but all the positions will be focused.
- *
- * Trees can be coarsely divided into four mutually exclusive categories:
- *
- * - TermTrees, representing terms
- * - TypTrees, representing types. Note that is `TypTree`, not `TypeTree`.
- * - SymTrees, which may represent types or terms.
- * - Other Trees, which have none of those as parents.
- *
- * SymTrees include important nodes Ident and Select, which are
- * used as both terms and types; they are distinguishable based on
- * whether the Name is a TermName or TypeName. The correct way
- * to test any Tree for a type or a term are the `isTerm`/`isType`
- * methods on Tree.
- *
- * "Others" are mostly syntactic or short-lived constructs. Examples
- * include CaseDef, which wraps individual match cases: they are
- * neither terms nor types, nor do they carry a symbol. Another
- * example is Parens, which is eliminated during parsing.
+ /** The type of Scala abstract syntax trees.
+ * @group Trees
+ * @template
*/
type Tree >: Null <: TreeApi
/** A tag that preserves the identity of the `Tree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TreeTag: ClassTag[Tree]
- /** The API that all trees support */
+ /** The API that all trees support.
+ * The main source of information about trees is the [[scala.reflect.api.Trees]] page.
+ * @group API
+ */
trait TreeApi extends Product { this: Tree =>
- // TODO
- /** ... */
+ /** Does this tree represent a definition? (of a method, of a class, etc) */
def isDef: Boolean
- // TODO
- /** ... */
+ /** Is this tree one of the empty trees?
+ * Empty trees are: the `EmptyTree` null object, `TypeTree` instances that don't carry a type
+ * and the special `emptyValDef` singleton.
+ */
def isEmpty: Boolean
/** The canonical way to test if a Tree represents a term.
@@ -76,32 +71,37 @@ trait Trees { self: Universe =>
*/
def isType: Boolean
- /** ... */
+ /** Position of the tree. */
def pos: Position
- /** ... */
+ /** Type of the tree.
+ *
+ * Upon creation most trees have their `tpe` set to `null`.
+ * Types are typically assigned to trees during typechecking.
+ * Some node factory methods set `tpe` immediately after creation.
+ *
+ * When the typechecker encounters a tree with a non-null tpe,
+ * it will assume it to be correct and not check it again. This means one has
+ * to be careful not to erase the `tpe` field of subtrees.
+ */
def tpe: Type
- /** Note that symbol is fixed as null at this level. In SymTrees,
- * it is overridden and implemented with a var, initialized to NoSymbol.
+ /** Symbol of the tree.
*
- * Trees which are not SymTrees but which carry symbols do so by
- * overriding `def symbol` to forward it elsewhere. Examples:
+ * For most trees symbol is `null`. In `SymTree`s,
+ * it is overridden and implemented with a var, initialized to `NoSymbol`.
*
- * Super(qual, _) // has qual's symbol
- * Apply(fun, args) // has fun's symbol
- * TypeApply(fun, args) // has fun's symbol
- * AppliedTypeTree(tpt, args) // has tpt's symbol
- * TypeTree(tpe) // has tpe's typeSymbol, if tpe != null
+ * Trees which are not `SymTree`s but which carry symbols do so by
+ * overriding `def symbol` to forward it elsewhere. Examples:
*
- * Attempting to set the symbol of a Tree which does not support
- * it will induce an exception.
+ * - `Super(qual, _)` has `qual`'s symbol,
+ * - `Apply(fun, args)` has `fun`'s symbol,
+ * - `TypeApply(fun, args)` has `fun`'s symbol,
+ * - `AppliedTypeTree(tpt, args)` has `tpt`'s symbol,
+ * - `TypeTree(tpe)` has `tpe`'s `typeSymbol`, if `tpe != null`.
*/
def symbol: Symbol
- /** ... */
- def hasSymbolField: Boolean
-
/** Provides an alternate if tree is empty
* @param alt The alternate tree
* @return If this tree is non empty, this tree, otherwise `alt`.
@@ -175,166 +175,239 @@ trait Trees { self: Universe =>
override def toString: String = treeToString(this)
}
- /** Obtains string representation of a tree */
+ /** Obtains string representation of a tree
+ * @group Trees
+ */
protected def treeToString(tree: Tree): String
- /** The empty tree */
+ /** The empty tree
+ * @group Trees
+ */
val EmptyTree: Tree
/** A tree for a term. Not all trees representing terms are TermTrees; use isTerm
* to reliably identify terms.
+ * @group Trees
+ * @template
*/
type TermTree >: Null <: AnyRef with Tree with TermTreeApi
/** A tag that preserves the identity of the `TermTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TermTreeTag: ClassTag[TermTree]
- /** The API that all term trees support */
+ /** The API that all term trees support
+ * @group API
+ */
trait TermTreeApi extends TreeApi { this: TermTree =>
}
/** A tree for a type. Not all trees representing types are TypTrees; use isType
* to reliably identify types.
+ * @group Trees
+ * @template
*/
type TypTree >: Null <: AnyRef with Tree with TypTreeApi
/** A tag that preserves the identity of the `TypTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypTreeTag: ClassTag[TypTree]
- /** The API that all typ trees support */
+ /** The API that all typ trees support
+ * @group API
+ */
trait TypTreeApi extends TreeApi { this: TypTree =>
}
/** A tree with a mutable symbol field, initialized to NoSymbol.
+ * @group Trees
+ * @template
*/
type SymTree >: Null <: AnyRef with Tree with SymTreeApi
/** A tag that preserves the identity of the `SymTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SymTreeTag: ClassTag[SymTree]
- /** The API that all sym trees support */
+ /** The API that all sym trees support
+ * @group API
+ */
trait SymTreeApi extends TreeApi { this: SymTree =>
+ /** @inheritdoc */
def symbol: Symbol
}
/** A tree with a name - effectively, a DefTree or RefTree.
+ * @group Trees
+ * @template
*/
type NameTree >: Null <: AnyRef with Tree with NameTreeApi
/** A tag that preserves the identity of the `NameTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NameTreeTag: ClassTag[NameTree]
- /** The API that all name trees support */
+ /** The API that all name trees support
+ * @group API
+ */
trait NameTreeApi extends TreeApi { this: NameTree =>
+ /** The underlying name.
+ * For example, the `<List>` part of `Ident("List": TermName)`.
+ */
def name: Name
}
/** A tree which references a symbol-carrying entity.
* References one, as opposed to defining one; definitions
* are in DefTrees.
+ * @group Trees
+ * @template
*/
type RefTree >: Null <: SymTree with NameTree with RefTreeApi
/** A tag that preserves the identity of the `RefTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val RefTreeTag: ClassTag[RefTree]
- /** The API that all ref trees support */
+ /** The API that all ref trees support
+ * @group API
+ */
trait RefTreeApi extends SymTreeApi with NameTreeApi { this: RefTree =>
- def qualifier: Tree // empty for Idents
+ /** The qualifier of the reference.
+ * For example, the `<scala>` part of `Select("scala": TermName, "List": TermName)`.
+ * `EmptyTree` for `Ident` instances.
+ */
+ def qualifier: Tree
+
+ /** @inheritdoc */
def name: Name
}
/** A tree which defines a symbol-carrying entity.
+ * @group Trees
+ * @template
*/
type DefTree >: Null <: SymTree with NameTree with DefTreeApi
/** A tag that preserves the identity of the `DefTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val DefTreeTag: ClassTag[DefTree]
- /** The API that all def trees support */
+ /** The API that all def trees support
+ * @group API
+ */
trait DefTreeApi extends SymTreeApi with NameTreeApi { this: DefTree =>
+ /** @inheritdoc */
def name: Name
}
/** Common base class for all member definitions: types, classes,
* objects, packages, vals and vars, defs.
+ * @group Trees
+ * @template
*/
type MemberDef >: Null <: DefTree with MemberDefApi
/** A tag that preserves the identity of the `MemberDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MemberDefTag: ClassTag[MemberDef]
- /** The API that all member defs support */
+ /** The API that all member defs support
+ * @group API
+ */
trait MemberDefApi extends DefTreeApi { this: MemberDef =>
+ /** Modifiers of the declared member. */
def mods: Modifiers
}
/** A packaging, such as `package pid { stats }`
+ * @group Trees
+ * @template
*/
type PackageDef >: Null <: MemberDef with PackageDefApi
/** A tag that preserves the identity of the `PackageDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PackageDefTag: ClassTag[PackageDef]
- /** The constructor/deconstructor for `PackageDef` instances. */
+ /** The constructor/deconstructor for `PackageDef` instances.
+ * @group Extractors
+ */
val PackageDef: PackageDefExtractor
/** An extractor class to create and pattern match with syntax `PackageDef(pid, stats)`.
* This AST node corresponds to the following Scala code:
*
* `package` pid { stats }
+ * @group Extractors
*/
abstract class PackageDefExtractor {
def apply(pid: RefTree, stats: List[Tree]): PackageDef
def unapply(packageDef: PackageDef): Option[(RefTree, List[Tree])]
}
- /** The API that all package defs support */
+ /** The API that all package defs support
+ * @group API
+ */
trait PackageDefApi extends MemberDefApi { this: PackageDef =>
+ /** The (possibly, fully-qualified) name of the package. */
val pid: RefTree
+
+ /** Body of the package definition. */
val stats: List[Tree]
}
/** A common base class for class and object definitions.
+ * @group Trees
+ * @template
*/
type ImplDef >: Null <: MemberDef with ImplDefApi
/** A tag that preserves the identity of the `ImplDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImplDefTag: ClassTag[ImplDef]
- /** The API that all impl defs support */
+ /** The API that all impl defs support
+ * @group API
+ */
trait ImplDefApi extends MemberDefApi { this: ImplDef =>
+ /** The body of the definition. */
val impl: Template
}
/** A class definition.
+ * @group Trees
+ * @template
*/
type ClassDef >: Null <: ImplDef with ClassDefApi
/** A tag that preserves the identity of the `ClassDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassDefTag: ClassTag[ClassDef]
- /** The constructor/deconstructor for `ClassDef` instances. */
+ /** The constructor/deconstructor for `ClassDef` instances.
+ * @group Extractors
+ */
val ClassDef: ClassDefExtractor
/** An extractor class to create and pattern match with syntax `ClassDef(mods, name, tparams, impl)`.
@@ -345,32 +418,47 @@ trait Trees { self: Universe =>
* Where impl stands for:
*
* `extends` parents { defs }
+ * @group Extractors
*/
abstract class ClassDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template): ClassDef
def unapply(classDef: ClassDef): Option[(Modifiers, TypeName, List[TypeDef], Template)]
}
- /** The API that all class defs support */
+ /** The API that all class defs support
+ * @group API
+ */
trait ClassDefApi extends ImplDefApi { this: ClassDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** The name of the class. */
val name: TypeName
+
+ /** The type parameters of the class. */
val tparams: List[TypeDef]
+
+ /** @inheritdoc */
val impl: Template
}
/** An object definition, e.g. `object Foo`. Internally, objects are
* quite frequently called modules to reduce ambiguity.
* Eliminated by compiler phase refcheck.
+ * @group Trees
+ * @template
*/
type ModuleDef >: Null <: ImplDef with ModuleDefApi
/** A tag that preserves the identity of the `ModuleDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ModuleDefTag: ClassTag[ModuleDef]
- /** The constructor/deconstructor for `ModuleDef` instances. */
+ /** The constructor/deconstructor for `ModuleDef` instances.
+ * @group Extractors
+ */
val ModuleDef: ModuleDefExtractor
/** An extractor class to create and pattern match with syntax `ModuleDef(mods, name, impl)`.
@@ -381,32 +469,55 @@ trait Trees { self: Universe =>
* Where impl stands for:
*
* `extends` parents { defs }
+ * @group Extractors
*/
abstract class ModuleDefExtractor {
def apply(mods: Modifiers, name: TermName, impl: Template): ModuleDef
def unapply(moduleDef: ModuleDef): Option[(Modifiers, TermName, Template)]
}
- /** The API that all module defs support */
+ /** The API that all module defs support
+ * @group API
+ */
trait ModuleDefApi extends ImplDefApi { this: ModuleDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** The name of the module. */
val name: TermName
+
+ /** @inheritdoc */
val impl: Template
}
/** A common base class for ValDefs and DefDefs.
+ * @group Trees
+ * @template
*/
type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi
/** A tag that preserves the identity of the `ValOrDefDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ValOrDefDefTag: ClassTag[ValOrDefDef]
- /** The API that all val defs and def defs support */
+ /** The API that all val defs and def defs support
+ * @group API
+ */
trait ValOrDefDefApi extends MemberDefApi { this: ValOrDefDef =>
+ /** @inheritdoc */
def name: Name // can't be a TermName because macros can be type names.
+
+ /** The type ascribed to the definition.
+ * An empty `TypeTree` if the type hasn't been specified explicitly
+ * and is supposed to be inferred.
+ */
def tpt: Tree
+
+ /** The body of the definition.
+ * The `EmptyTree` is the body is empty (e.g. for abstract members).
+ */
def rhs: Tree
}
@@ -417,15 +528,20 @@ trait Trees { self: Universe =>
* - lazy values, e.g. "lazy val x" - the LAZY flag set in mods
* - method parameters, see vparamss in [[scala.reflect.api.Trees#DefDef]] - the PARAM flag is set in mods
* - explicit self-types, e.g. class A { self: Bar => }
+ * @group Trees
+ * @template
*/
type ValDef >: Null <: ValOrDefDef with ValDefApi
/** A tag that preserves the identity of the `ValDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ValDefTag: ClassTag[ValDef]
- /** The constructor/deconstructor for `ValDef` instances. */
+ /** The constructor/deconstructor for `ValDef` instances.
+ * @group Extractors
+ */
val ValDef: ValDefExtractor
/** An extractor class to create and pattern match with syntax `ValDef(mods, name, tpt, rhs)`.
@@ -441,31 +557,46 @@ trait Trees { self: Universe =>
*
* If the type of a value is not specified explicitly (i.e. is meant to be inferred),
* this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!).
+ * @group Extractors
*/
abstract class ValDefExtractor {
def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef
def unapply(valDef: ValDef): Option[(Modifiers, TermName, Tree, Tree)]
}
- /** The API that all val defs support */
+ /** The API that all val defs support
+ * @group API
+ */
trait ValDefApi extends ValOrDefDefApi { this: ValDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: TermName
+
+ /** @inheritdoc */
val tpt: Tree
+
+ /** @inheritdoc */
val rhs: Tree
}
/** A method or macro definition.
* @param name The name of the method or macro. Can be a type name in case this is a type macro
+ * @group Trees
+ * @template
*/
type DefDef >: Null <: ValOrDefDef with DefDefApi
/** A tag that preserves the identity of the `DefDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val DefDefTag: ClassTag[DefDef]
- /** The constructor/deconstructor for `DefDef` instances. */
+ /** The constructor/deconstructor for `DefDef` instances.
+ * @group Extractors
+ */
val DefDef: DefDefExtractor
/** An extractor class to create and pattern match with syntax `DefDef(mods, name, tparams, vparamss, tpt, rhs)`.
@@ -475,33 +606,52 @@ trait Trees { self: Universe =>
*
* If the return type is not specified explicitly (i.e. is meant to be inferred),
* this is expressed by having `tpt` set to `TypeTree()` (but not to an `EmptyTree`!).
+ * @group Extractors
*/
abstract class DefDefExtractor {
def apply(mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
def unapply(defDef: DefDef): Option[(Modifiers, Name, List[TypeDef], List[List[ValDef]], Tree, Tree)]
}
- /** The API that all def defs support */
+ /** The API that all def defs support
+ * @group API
+ */
trait DefDefApi extends ValOrDefDefApi { this: DefDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: Name
+
+ /** The type parameters of the method. */
val tparams: List[TypeDef]
+
+ /** The parameter lists of the method. */
val vparamss: List[List[ValDef]]
+
+ /** @inheritdoc */
val tpt: Tree
+
+ /** @inheritdoc */
val rhs: Tree
}
/** An abstract type, a type parameter, or a type alias.
* Eliminated by erasure.
+ * @group Trees
+ * @template
*/
type TypeDef >: Null <: MemberDef with TypeDefApi
/** A tag that preserves the identity of the `TypeDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeDefTag: ClassTag[TypeDef]
- /** The constructor/deconstructor for `TypeDef` instances. */
+ /** The constructor/deconstructor for `TypeDef` instances.
+ * @group Extractors
+ */
val TypeDef: TypeDefExtractor
/** An extractor class to create and pattern match with syntax `TypeDef(mods, name, tparams, rhs)`.
@@ -514,17 +664,29 @@ trait Trees { self: Universe =>
* First usage illustrates `TypeDefs` representing type aliases and type parameters.
* Second usage illustrates `TypeDefs` representing abstract types,
* where lo and hi are both `TypeBoundsTrees` and `Modifier.deferred` is set in mods.
+ * @group Extractors
*/
abstract class TypeDefExtractor {
def apply(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef
def unapply(typeDef: TypeDef): Option[(Modifiers, TypeName, List[TypeDef], Tree)]
}
- /** The API that all type defs support */
+ /** The API that all type defs support
+ * @group API
+ */
trait TypeDefApi extends MemberDefApi { this: TypeDef =>
+ /** @inheritdoc */
val mods: Modifiers
+
+ /** @inheritdoc */
val name: TypeName
+
+ /** The type parameters of this type definition. */
val tparams: List[TypeDef]
+
+ /** The body of the definition.
+ * The `EmptyTree` is the body is empty (e.g. for abstract type members).
+ */
val rhs: Tree
}
@@ -541,15 +703,20 @@ trait Trees { self: Universe =>
* assigned to the Idents.
*
* Forward jumps within a block are allowed.
+ * @group Trees
+ * @template
*/
type LabelDef >: Null <: DefTree with TermTree with LabelDefApi
/** A tag that preserves the identity of the `LabelDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LabelDefTag: ClassTag[LabelDef]
- /** The constructor/deconstructor for `LabelDef` instances. */
+ /** The constructor/deconstructor for `LabelDef` instances.
+ * @group Extractors
+ */
val LabelDef: LabelDefExtractor
/** An extractor class to create and pattern match with syntax `LabelDef(name, params, rhs)`.
@@ -558,21 +725,33 @@ trait Trees { self: Universe =>
* It is used for tailcalls and like.
* For example, while/do are desugared to label defs as follows:
* {{{
- * while (cond) body ==> LabelDef($L, List(), if (cond) { body; L$() } else ())
+ * while (cond) body ==> LabelDef(\$L, List(), if (cond) { body; L\$() } else ())
* }}}
* {{{
- * do body while (cond) ==> LabelDef($L, List(), body; if (cond) L$() else ())
+ * do body while (cond) ==> LabelDef(\$L, List(), body; if (cond) L\$() else ())
* }}}
+ * @group Extractors
*/
abstract class LabelDefExtractor {
def apply(name: TermName, params: List[Ident], rhs: Tree): LabelDef
def unapply(labelDef: LabelDef): Option[(TermName, List[Ident], Tree)]
}
- /** The API that all label defs support */
+ /** The API that all label defs support
+ * @group API
+ */
trait LabelDefApi extends DefTreeApi with TermTreeApi { this: LabelDef =>
+ /** @inheritdoc */
val name: TermName
+
+ /** Label's parameters - names that can be used in the body of the label.
+ * See the example for [[scala.reflect.api.Trees#LabelDefExtractor]].
+ */
val params: List[Ident]
+
+ /** The body of the label.
+ * See the example for [[scala.reflect.api.Trees#LabelDefExtractor]].
+ */
val rhs: Tree
}
@@ -586,30 +765,51 @@ trait Trees { self: Universe =>
* @param namePos its position or -1 if undefined
* @param rename the name the import is renamed to (== name if no renaming)
* @param renamePos the position of the rename or -1 if undefined
+ * @group Trees
+ * @template
*/
type ImportSelector >: Null <: AnyRef with ImportSelectorApi
/** A tag that preserves the identity of the `ImportSelector` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImportSelectorTag: ClassTag[ImportSelector]
- /** The constructor/deconstructor for `ImportSelector` instances. */
+ /** The constructor/deconstructor for `ImportSelector` instances.
+ * @group Extractors
+ */
val ImportSelector: ImportSelectorExtractor
/** An extractor class to create and pattern match with syntax `ImportSelector(name:, namePos, rename, renamePos)`.
* This is not an AST node, it is used as a part of the `Import` node.
+ * @group Extractors
*/
abstract class ImportSelectorExtractor {
def apply(name: Name, namePos: Int, rename: Name, renamePos: Int): ImportSelector
def unapply(importSelector: ImportSelector): Option[(Name, Int, Name, Int)]
}
- /** The API that all import selectors support */
+ /** The API that all import selectors support
+ * @group API
+ */
trait ImportSelectorApi { this: ImportSelector =>
+ /** The imported name. */
val name: Name
+
+ /** Offset of the position of the importing part of the selector in the source file.
+ * Is equal to -1 is the position is unknown.
+ */
val namePos: Int
+
+ /** The name the import is renamed to.
+ * Is equal to `name` if it's not a renaming import.
+ */
val rename: Name
+
+ /** Offset of the position of the renaming part of the selector in the source file.
+ * Is equal to -1 is the position is unknown.
+ */
val renamePos: Int
}
@@ -617,15 +817,20 @@ trait Trees { self: Universe =>
*
* @param expr
* @param selectors
+ * @group Trees
+ * @template
*/
type Import >: Null <: SymTree with ImportApi
/** A tag that preserves the identity of the `Import` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ImportTag: ClassTag[Import]
- /** The constructor/deconstructor for `Import` instances. */
+ /** The constructor/deconstructor for `Import` instances.
+ * @group Extractors
+ */
val Import: ImportExtractor
/** An extractor class to create and pattern match with syntax `Import(expr, selectors)`.
@@ -644,15 +849,25 @@ trait Trees { self: Universe =>
*
* The symbol of an `Import` is an import symbol @see Symbol.newImport.
* It's used primarily as a marker to check that the import has been typechecked.
+ * @group Extractors
*/
abstract class ImportExtractor {
def apply(expr: Tree, selectors: List[ImportSelector]): Import
def unapply(import_ : Import): Option[(Tree, List[ImportSelector])]
}
- /** The API that all imports support */
+ /** The API that all imports support
+ * @group API
+ */
trait ImportApi extends SymTreeApi { this: Import =>
+ /** The qualifier of the import.
+ * See the example for [[scala.reflect.api.Trees#ImportExtractor]].
+ */
val expr: Tree
+
+ /** The selectors of the import.
+ * See the example for [[scala.reflect.api.Trees#ImportExtractor]].
+ */
val selectors: List[ImportSelector]
}
@@ -660,15 +875,20 @@ trait Trees { self: Universe =>
*
* @param parents
* @param body
+ * @group Trees
+ * @template
*/
type Template >: Null <: SymTree with TemplateApi
/** A tag that preserves the identity of the `Template` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TemplateTag: ClassTag[Template]
- /** The constructor/deconstructor for `Template` instances. */
+ /** The constructor/deconstructor for `Template` instances.
+ * @group Extractors
+ */
val Template: TemplateExtractor
/** An extractor class to create and pattern match with syntax `Template(parents, self, body)`.
@@ -688,28 +908,45 @@ trait Trees { self: Universe =>
* def bar // owner is local dummy
* }
* }
+ * @group Extractors
*/
abstract class TemplateExtractor {
def apply(parents: List[Tree], self: ValDef, body: List[Tree]): Template
def unapply(template: Template): Option[(List[Tree], ValDef, List[Tree])]
}
- /** The API that all templates support */
+ /** The API that all templates support
+ * @group API
+ */
trait TemplateApi extends SymTreeApi { this: Template =>
+ /** Superclasses of the template. */
val parents: List[Tree]
+
+ /** Self type of the template.
+ * Is equal to `emptyValDef` if the self type is not specified.
+ */
val self: ValDef
+
+ /** Body of the template.
+ */
val body: List[Tree]
}
- /** Block of expressions (semicolon separated expressions) */
+ /** Block of expressions (semicolon separated expressions)
+ * @group Trees
+ * @template
+ */
type Block >: Null <: TermTree with BlockApi
/** A tag that preserves the identity of the `Block` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BlockTag: ClassTag[Block]
- /** The constructor/deconstructor for `Block` instances. */
+ /** The constructor/deconstructor for `Block` instances.
+ * @group Extractors
+ */
val Block: BlockExtractor
/** An extractor class to create and pattern match with syntax `Block(stats, expr)`.
@@ -718,30 +955,43 @@ trait Trees { self: Universe =>
* { stats; expr }
*
* If the block is empty, the `expr` is set to `Literal(Constant(()))`.
+ * @group Extractors
*/
abstract class BlockExtractor {
def apply(stats: List[Tree], expr: Tree): Block
def unapply(block: Block): Option[(List[Tree], Tree)]
}
- /** The API that all blocks support */
+ /** The API that all blocks support
+ * @group API
+ */
trait BlockApi extends TermTreeApi { this: Block =>
+ /** All, but the last, expressions in the block.
+ * Can very well be an empty list.
+ */
val stats: List[Tree]
+
+ /** The last expression in the block. */
val expr: Tree
}
/** Case clause in a pattern match.
* (except for occurrences in switch statements).
* Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher)
+ * @group Trees
+ * @template
*/
type CaseDef >: Null <: AnyRef with Tree with CaseDefApi
/** A tag that preserves the identity of the `CaseDef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CaseDefTag: ClassTag[CaseDef]
- /** The constructor/deconstructor for `CaseDef` instances. */
+ /** The constructor/deconstructor for `CaseDef` instances.
+ * @group Extractors
+ */
val CaseDef: CaseDefExtractor
/** An extractor class to create and pattern match with syntax `CaseDef(pat, guard, body)`.
@@ -751,16 +1001,28 @@ trait Trees { self: Universe =>
*
* If the guard is not present, the `guard` is set to `EmptyTree`.
* If the body is not specified, the `body` is set to `Literal(Constant())`
+ * @group Extractors
*/
abstract class CaseDefExtractor {
def apply(pat: Tree, guard: Tree, body: Tree): CaseDef
def unapply(caseDef: CaseDef): Option[(Tree, Tree, Tree)]
}
- /** The API that all case defs support */
+ /** The API that all case defs support
+ * @group API
+ */
trait CaseDefApi extends TreeApi { this: CaseDef =>
+ /** The pattern of the pattern matching clause. */
val pat: Tree
+
+ /** The guard of the pattern matching clause.
+ * Is equal to `EmptyTree` if the guard is not specified.
+ */
val guard: Tree
+
+ /** The body of the pattern matching clause.
+ * Is equal to `Literal(Constant())` if the body is not specified.
+ */
val body: Tree
}
@@ -769,58 +1031,76 @@ trait Trees { self: Universe =>
* Eliminated by compiler phases Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher),
* except for
* occurrences in encoded Switch stmt (i.e. remaining Match(CaseDef(...)))
+ * @group Trees
+ * @template
*/
type Alternative >: Null <: TermTree with AlternativeApi
/** A tag that preserves the identity of the `Alternative` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AlternativeTag: ClassTag[Alternative]
- /** The constructor/deconstructor for `Alternative` instances. */
+ /** The constructor/deconstructor for `Alternative` instances.
+ * @group Extractors
+ */
val Alternative: AlternativeExtractor
/** An extractor class to create and pattern match with syntax `Alternative(trees)`.
* This AST node corresponds to the following Scala code:
*
* pat1 | ... | patn
+ * @group Extractors
*/
abstract class AlternativeExtractor {
def apply(trees: List[Tree]): Alternative
def unapply(alternative: Alternative): Option[List[Tree]]
}
- /** The API that all alternatives support */
+ /** The API that all alternatives support
+ * @group API
+ */
trait AlternativeApi extends TermTreeApi { this: Alternative =>
+ /** Alternatives of the pattern matching clause. */
val trees: List[Tree]
}
/** Repetition of pattern.
*
* Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher).
+ * @group Trees
+ * @template
*/
type Star >: Null <: TermTree with StarApi
/** A tag that preserves the identity of the `Star` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val StarTag: ClassTag[Star]
- /** The constructor/deconstructor for `Star` instances. */
+ /** The constructor/deconstructor for `Star` instances.
+ * @group Extractors
+ */
val Star: StarExtractor
/** An extractor class to create and pattern match with syntax `Star(elem)`.
* This AST node corresponds to the following Scala code:
*
* pat*
+ * @group Extractors
*/
abstract class StarExtractor {
def apply(elem: Tree): Star
def unapply(star: Star): Option[Tree]
}
- /** The API that all stars support */
+ /** The API that all stars support
+ * @group API
+ */
trait StarApi extends TermTreeApi { this: Star =>
+ /** The quantified pattern. */
val elem: Tree
}
@@ -830,30 +1110,46 @@ trait Trees { self: Universe =>
*
* @param name
* @param body
+ * @group Trees
+ * @template
*/
type Bind >: Null <: DefTree with BindApi
/** A tag that preserves the identity of the `Bind` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BindTag: ClassTag[Bind]
- /** The constructor/deconstructor for `Bind` instances. */
+ /** The constructor/deconstructor for `Bind` instances.
+ * @group Extractors
+ */
val Bind: BindExtractor
/** An extractor class to create and pattern match with syntax `Bind(name, body)`.
* This AST node corresponds to the following Scala code:
*
* pat*
+ * @group Extractors
*/
abstract class BindExtractor {
def apply(name: Name, body: Tree): Bind
def unapply(bind: Bind): Option[(Name, Tree)]
}
- /** The API that all binds support */
+ /** The API that all binds support
+ * @group API
+ */
trait BindApi extends DefTreeApi { this: Bind =>
+ /** The name that can be used to refer to this fragment of the matched expression.
+ * The `list` part of the `list @ List(x, y)`.
+ */
val name: Name
+
+ /** The pattern that represents this fragment of the matched expression.
+ * The `List(x, y)` part of the `list @ List(x, y)`.
+ * Is equal to `EmptyTree` if the pattern is not specified as in `case x => x`.
+ */
val body: Tree
}
@@ -883,41 +1179,62 @@ trait Trees { self: Universe =>
* }}}
*
* Introduced by typer. Eliminated by compiler phases patmat (in the new pattern matcher of 2.10) or explicitouter (in the old pre-2.10 pattern matcher).
+ * @group Trees
+ * @template
*/
type UnApply >: Null <: TermTree with UnApplyApi
/** A tag that preserves the identity of the `UnApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val UnApplyTag: ClassTag[UnApply]
- /** The constructor/deconstructor for `UnApply` instances. */
+ /** The constructor/deconstructor for `UnApply` instances.
+ * @group Extractors
+ */
val UnApply: UnApplyExtractor
/** An extractor class to create and pattern match with syntax `UnApply(fun, args)`.
* This AST node does not have direct correspondence to Scala code,
* and is introduced when typechecking pattern matches and `try` blocks.
+ * @group Extractors
*/
abstract class UnApplyExtractor {
def apply(fun: Tree, args: List[Tree]): UnApply
def unapply(unApply: UnApply): Option[(Tree, List[Tree])]
}
- /** The API that all unapplies support */
+ /** The API that all unapplies support
+ * @group API
+ */
trait UnApplyApi extends TermTreeApi { this: UnApply =>
+ /** A dummy node that carries the type of unapplication.
+ * See the example for [[scala.reflect.api.Trees#UnApplyExtractor]].
+ */
val fun: Tree
+
+ /** The arguments of the unapplication.
+ * See the example for [[scala.reflect.api.Trees#UnApplyExtractor]].
+ */
val args: List[Tree]
}
- /** Anonymous function, eliminated by compiler phase lambdalift */
+ /** Anonymous function, eliminated by compiler phase lambdalift
+ * @group Trees
+ * @template
+ */
type Function >: Null <: TermTree with SymTree with FunctionApi
/** A tag that preserves the identity of the `Function` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val FunctionTag: ClassTag[Function]
- /** The constructor/deconstructor for `Function` instances. */
+ /** The constructor/deconstructor for `Function` instances.
+ * @group Extractors
+ */
val Function: FunctionExtractor
/** An extractor class to create and pattern match with syntax `Function(vparams, body)`.
@@ -927,56 +1244,83 @@ trait Trees { self: Universe =>
*
* The symbol of a Function is a synthetic TermSymbol.
* It is the owner of the function's parameters.
+ * @group Extractors
*/
abstract class FunctionExtractor {
def apply(vparams: List[ValDef], body: Tree): Function
def unapply(function: Function): Option[(List[ValDef], Tree)]
}
- /** The API that all functions support */
+ /** The API that all functions support
+ * @group API
+ */
trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function =>
+ /** The list of parameters of the function.
+ */
val vparams: List[ValDef]
+
+ /** The body of the function.
+ */
val body: Tree
}
- /** Assignment */
+ /** Assignment
+ * @group Trees
+ * @template
+ */
type Assign >: Null <: TermTree with AssignApi
/** A tag that preserves the identity of the `Assign` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AssignTag: ClassTag[Assign]
- /** The constructor/deconstructor for `Assign` instances. */
+ /** The constructor/deconstructor for `Assign` instances.
+ * @group Extractors
+ */
val Assign: AssignExtractor
/** An extractor class to create and pattern match with syntax `Assign(lhs, rhs)`.
* This AST node corresponds to the following Scala code:
*
* lhs = rhs
+ * @group Extractors
*/
abstract class AssignExtractor {
def apply(lhs: Tree, rhs: Tree): Assign
def unapply(assign: Assign): Option[(Tree, Tree)]
}
- /** The API that all assigns support */
+ /** The API that all assigns support
+ * @group API
+ */
trait AssignApi extends TermTreeApi { this: Assign =>
+ /** The left-hand side of the assignment.
+ */
val lhs: Tree
+
+ /** The right-hand side of the assignment.
+ */
val rhs: Tree
}
/** Either an assignment or a named argument. Only appears in argument lists,
* eliminated by compiler phase typecheck (doTypedApply), resurrected by reifier.
+ * @group Trees
+ * @template
*/
type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi
/** A tag that preserves the identity of the `AssignOrNamedArg` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AssignOrNamedArgTag: ClassTag[AssignOrNamedArg]
- /** The constructor/deconstructor for `AssignOrNamedArg` instances. */
+ /** The constructor/deconstructor for `AssignOrNamedArg` instances.
+ * @group Extractors
+ */
val AssignOrNamedArg: AssignOrNamedArgExtractor
/** An extractor class to create and pattern match with syntax `AssignOrNamedArg(lhs, rhs)`.
@@ -989,27 +1333,41 @@ trait Trees { self: Universe =>
* @annotation(lhs = rhs)
* }}}
*
+ * @group Extractors
*/
abstract class AssignOrNamedArgExtractor {
def apply(lhs: Tree, rhs: Tree): AssignOrNamedArg
def unapply(assignOrNamedArg: AssignOrNamedArg): Option[(Tree, Tree)]
}
- /** The API that all assigns support */
+ /** The API that all assigns support
+ * @group API
+ */
trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg =>
+ /** The left-hand side of the expression.
+ */
val lhs: Tree
+
+ /** The right-hand side of the expression.
+ */
val rhs: Tree
}
- /** Conditional expression */
+ /** Conditional expression
+ * @group Trees
+ * @template
+ */
type If >: Null <: TermTree with IfApi
/** A tag that preserves the identity of the `If` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val IfTag: ClassTag[If]
- /** The constructor/deconstructor for `If` instances. */
+ /** The constructor/deconstructor for `If` instances.
+ * @group Extractors
+ */
val If: IfExtractor
/** An extractor class to create and pattern match with syntax `If(cond, thenp, elsep)`.
@@ -1018,16 +1376,28 @@ trait Trees { self: Universe =>
* `if` (cond) thenp `else` elsep
*
* If the alternative is not present, the `elsep` is set to `Literal(Constant(()))`.
+ * @group Extractors
*/
abstract class IfExtractor {
def apply(cond: Tree, thenp: Tree, elsep: Tree): If
def unapply(if_ : If): Option[(Tree, Tree, Tree)]
}
- /** The API that all ifs support */
+ /** The API that all ifs support
+ * @group API
+ */
trait IfApi extends TermTreeApi { this: If =>
+ /** The condition of the if.
+ */
val cond: Tree
+
+ /** The main branch of the if.
+ */
val thenp: Tree
+
+ /** The alternative of the if.
+ * Is equal to `Literal(Constant(()))` if not specified.
+ */
val elsep: Tree
}
@@ -1041,15 +1411,20 @@ trait Trees { self: Universe =>
* or `Alternative(lit|...|lit)`
* - except for an "otherwise" branch, which has pattern
* `Ident(nme.WILDCARD)`
+ * @group Trees
+ * @template
*/
type Match >: Null <: TermTree with MatchApi
/** A tag that preserves the identity of the `Match` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MatchTag: ClassTag[Match]
- /** The constructor/deconstructor for `Match` instances. */
+ /** The constructor/deconstructor for `Match` instances.
+ * @group Extractors
+ */
val Match: MatchExtractor
/** An extractor class to create and pattern match with syntax `Match(selector, cases)`.
@@ -1058,27 +1433,39 @@ trait Trees { self: Universe =>
* selector `match` { cases }
*
* `Match` is also used in pattern matching assignments like `val (foo, bar) = baz`.
+ * @group Extractors
*/
abstract class MatchExtractor {
def apply(selector: Tree, cases: List[CaseDef]): Match
def unapply(match_ : Match): Option[(Tree, List[CaseDef])]
}
- /** The API that all matches support */
+ /** The API that all matches support
+ * @group API
+ */
trait MatchApi extends TermTreeApi { this: Match =>
+ /** The scrutinee of the pattern match. */
val selector: Tree
+
+ /** The arms of the pattern match. */
val cases: List[CaseDef]
}
- /** Return expression */
+ /** Return expression
+ * @group Trees
+ * @template
+ */
type Return >: Null <: TermTree with SymTree with ReturnApi
/** A tag that preserves the identity of the `Return` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ReturnTag: ClassTag[Return]
- /** The constructor/deconstructor for `Return` instances. */
+ /** The constructor/deconstructor for `Return` instances.
+ * @group Extractors
+ */
val Return: ReturnExtractor
/** An extractor class to create and pattern match with syntax `Return(expr)`.
@@ -1087,26 +1474,36 @@ trait Trees { self: Universe =>
* `return` expr
*
* The symbol of a Return node is the enclosing method.
+ * @group Extractors
*/
abstract class ReturnExtractor {
def apply(expr: Tree): Return
def unapply(return_ : Return): Option[Tree]
}
- /** The API that all returns support */
+ /** The API that all returns support
+ * @group API
+ */
trait ReturnApi extends TermTreeApi { this: Return =>
+ /** The returned expression. */
val expr: Tree
}
- /** [Eugene++] comment me! */
+ /** Try catch node
+ * @group Trees
+ * @template
+ */
type Try >: Null <: TermTree with TryApi
/** A tag that preserves the identity of the `Try` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TryTag: ClassTag[Try]
- /** The constructor/deconstructor for `Try` instances. */
+ /** The constructor/deconstructor for `Try` instances.
+ * @group Extractors
+ */
val Try: TryExtractor
/** An extractor class to create and pattern match with syntax `Try(block, catches, finalizer)`.
@@ -1115,55 +1512,77 @@ trait Trees { self: Universe =>
* `try` block `catch` { catches } `finally` finalizer
*
* If the finalizer is not present, the `finalizer` is set to `EmptyTree`.
+ * @group Extractors
*/
abstract class TryExtractor {
def apply(block: Tree, catches: List[CaseDef], finalizer: Tree): Try
def unapply(try_ : Try): Option[(Tree, List[CaseDef], Tree)]
}
- /** The API that all tries support */
+ /** The API that all tries support
+ * @group API
+ */
trait TryApi extends TermTreeApi { this: Try =>
+ /** The protected block. */
val block: Tree
+
+ /** The `catch` pattern-matching clauses of the try. */
val catches: List[CaseDef]
+
+ /** The `finally` part of the try. */
val finalizer: Tree
}
- /** Throw expression */
+ /** Throw expression
+ * @group Trees
+ * @template
+ */
type Throw >: Null <: TermTree with ThrowApi
/** A tag that preserves the identity of the `Throw` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThrowTag: ClassTag[Throw]
- /** The constructor/deconstructor for `Throw` instances. */
+ /** The constructor/deconstructor for `Throw` instances.
+ * @group Extractors
+ */
val Throw: ThrowExtractor
/** An extractor class to create and pattern match with syntax `Throw(expr)`.
* This AST node corresponds to the following Scala code:
*
* `throw` expr
+ * @group Extractors
*/
abstract class ThrowExtractor {
def apply(expr: Tree): Throw
def unapply(throw_ : Throw): Option[Tree]
}
- /** The API that all tries support */
+ /** The API that all tries support
+ * @group API
+ */
trait ThrowApi extends TermTreeApi { this: Throw =>
+ /** The thrown expression. */
val expr: Tree
}
/** Object instantiation
+ * @group Trees
+ * @template
*/
type New >: Null <: TermTree with NewApi
/** A tag that preserves the identity of the `New` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NewTag: ClassTag[New]
/** The constructor/deconstructor for `New` instances.
+ * @group Extractors
*/
val New: NewExtractor
@@ -1175,6 +1594,7 @@ trait Trees { self: Universe =>
* This node always occurs in the following context:
*
* (`new` tpt).<init>[targs](args)
+ * @group Extractors
*/
abstract class NewExtractor {
/** A user level `new`.
@@ -1186,50 +1606,75 @@ trait Trees { self: Universe =>
def unapply(new_ : New): Option[Tree]
}
- /** The API that all news support */
+ /** The API that all news support
+ * @group API
+ */
trait NewApi extends TermTreeApi { this: New =>
+ /** The tree that represents the type being instantiated.
+ * See the example for [[scala.reflect.api.Trees#NewExtractor]].
+ */
val tpt: Tree
}
- /** Type annotation, eliminated by compiler phase cleanup */
+ /** Type annotation, eliminated by compiler phase cleanup
+ * @group Trees
+ * @template
+ */
type Typed >: Null <: TermTree with TypedApi
/** A tag that preserves the identity of the `Typed` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypedTag: ClassTag[Typed]
- /** The constructor/deconstructor for `Typed` instances. */
+ /** The constructor/deconstructor for `Typed` instances.
+ * @group Extractors
+ */
val Typed: TypedExtractor
/** An extractor class to create and pattern match with syntax `Typed(expr, tpt)`.
* This AST node corresponds to the following Scala code:
*
* expr: tpt
+ * @group Extractors
*/
abstract class TypedExtractor {
def apply(expr: Tree, tpt: Tree): Typed
def unapply(typed: Typed): Option[(Tree, Tree)]
}
- /** The API that all typeds support */
+ /** The API that all typeds support
+ * @group API
+ */
trait TypedApi extends TermTreeApi { this: Typed =>
+ /** The expression being ascribed with the type. */
val expr: Tree
+
+ /** The type being ascribed to the expression. */
val tpt: Tree
}
/** Common base class for Apply and TypeApply.
+ * @group Trees
+ * @template
*/
type GenericApply >: Null <: TermTree with GenericApplyApi
/** A tag that preserves the identity of the `GenericApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val GenericApplyTag: ClassTag[GenericApply]
- /** The API that all applies support */
+ /** The API that all applies support
+ * @group API
+ */
trait GenericApplyApi extends TermTreeApi { this: GenericApply =>
+ /** The target of the application. */
val fun: Tree
+
+ /** The arguments of the application. */
val args: List[Tree]
}
@@ -1237,40 +1682,55 @@ trait Trees { self: Universe =>
* but I can't find that explicitly stated anywhere. Unless your last name
* is odersky, you should probably treat it as true.
*/
- /** Explicit type application. */
+ /** Explicit type application.
+ * @group Trees
+ * @template
+ */
type TypeApply >: Null <: GenericApply with TypeApplyApi
/** A tag that preserves the identity of the `TypeApply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeApplyTag: ClassTag[TypeApply]
- /** The constructor/deconstructor for `TypeApply` instances. */
+ /** The constructor/deconstructor for `TypeApply` instances.
+ * @group Extractors
+ */
val TypeApply: TypeApplyExtractor
/** An extractor class to create and pattern match with syntax `TypeApply(fun, args)`.
* This AST node corresponds to the following Scala code:
*
* fun[args]
+ * @group Extractors
*/
abstract class TypeApplyExtractor {
def apply(fun: Tree, args: List[Tree]): TypeApply
def unapply(typeApply: TypeApply): Option[(Tree, List[Tree])]
}
- /** The API that all type applies support */
+ /** The API that all type applies support
+ * @group API
+ */
trait TypeApplyApi extends GenericApplyApi { this: TypeApply =>
}
- /** Value application */
+ /** Value application
+ * @group Trees
+ * @template
+ */
type Apply >: Null <: GenericApply with ApplyApi
/** A tag that preserves the identity of the `Apply` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ApplyTag: ClassTag[Apply]
- /** The constructor/deconstructor for `Apply` instances. */
+ /** The constructor/deconstructor for `Apply` instances.
+ * @group Extractors
+ */
val Apply: ApplyExtractor
/** An extractor class to create and pattern match with syntax `Apply(fun, args)`.
@@ -1285,27 +1745,35 @@ trait Trees { self: Universe =>
* Is expressed as:
*
* Apply(TypeApply(fun, targs), args)
+ * @group Extractors
*/
abstract class ApplyExtractor {
def apply(fun: Tree, args: List[Tree]): Apply
def unapply(apply: Apply): Option[(Tree, List[Tree])]
}
- /** The API that all applies support */
+ /** The API that all applies support
+ * @group API
+ */
trait ApplyApi extends GenericApplyApi { this: Apply =>
}
/** Super reference, where `qual` is the corresponding `this` reference.
* A super reference `C.super[M]` is represented as `Super(This(C), M)`.
+ * @group Trees
+ * @template
*/
type Super >: Null <: TermTree with SuperApi
/** A tag that preserves the identity of the `Super` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SuperTag: ClassTag[Super]
- /** The constructor/deconstructor for `Super` instances. */
+ /** The constructor/deconstructor for `Super` instances.
+ * @group Extractors
+ */
val Super: SuperExtractor
/** An extractor class to create and pattern match with syntax `Super(qual, mix)`.
@@ -1321,27 +1789,43 @@ trait Trees { self: Universe =>
*
* The symbol of a Super is the class _from_ which the super reference is made.
* For instance in C.super(...), it would be C.
+ * @group Extractors
*/
abstract class SuperExtractor {
def apply(qual: Tree, mix: TypeName): Super
def unapply(super_ : Super): Option[(Tree, TypeName)]
}
- /** The API that all supers support */
+ /** The API that all supers support
+ * @group API
+ */
trait SuperApi extends TermTreeApi { this: Super =>
+ /** The qualifier of the `super` expression.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val qual: Tree
+
+ /** The selector of the `super` expression.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val mix: TypeName
}
- /** Self reference */
+ /** Self reference
+ * @group Trees
+ * @template
+ */
type This >: Null <: TermTree with SymTree with ThisApi
/** A tag that preserves the identity of the `This` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThisTag: ClassTag[This]
- /** The constructor/deconstructor for `This` instances. */
+ /** The constructor/deconstructor for `This` instances.
+ * @group Extractors
+ */
val This: ThisExtractor
/** An extractor class to create and pattern match with syntax `This(qual)`.
@@ -1351,55 +1835,77 @@ trait Trees { self: Universe =>
*
* The symbol of a This is the class to which the this refers.
* For instance in C.this, it would be C.
- *
- * If `mix` is empty, then ???
+ * @group Extractors
*/
abstract class ThisExtractor {
def apply(qual: TypeName): This
def unapply(this_ : This): Option[TypeName]
}
- /** The API that all thises support */
+ /** The API that all thises support
+ * @group API
+ */
trait ThisApi extends TermTreeApi with SymTreeApi { this: This =>
+ /** The qualifier of the `this` expression.
+ * For an unqualified `this` refers to the enclosing class.
+ */
val qual: TypeName
}
- /** Designator <qualifier> . <name> */
+ /** A member selection <qualifier> . <name>
+ * @group Trees
+ * @template
+ */
type Select >: Null <: RefTree with SelectApi
/** A tag that preserves the identity of the `Select` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SelectTag: ClassTag[Select]
- /** The constructor/deconstructor for `Select` instances. */
+ /** The constructor/deconstructor for `Select` instances.
+ * @group Extractors
+ */
val Select: SelectExtractor
/** An extractor class to create and pattern match with syntax `Select(qual, name)`.
* This AST node corresponds to the following Scala code:
*
* qualifier.selector
+ * @group Extractors
*/
abstract class SelectExtractor {
def apply(qualifier: Tree, name: Name): Select
def unapply(select: Select): Option[(Tree, Name)]
}
- /** The API that all selects support */
+ /** The API that all selects support
+ * @group API
+ */
trait SelectApi extends RefTreeApi { this: Select =>
+ /** @inheritdoc */
val qualifier: Tree
+
+ /** @inheritdoc */
val name: Name
}
- /** Identifier <name> */
+ /** A reference to identifier `name`.
+ * @group Trees
+ * @template
+ */
type Ident >: Null <: RefTree with IdentApi
/** A tag that preserves the identity of the `Ident` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val IdentTag: ClassTag[Ident]
- /** The constructor/deconstructor for `Ident` instances. */
+ /** The constructor/deconstructor for `Ident` instances.
+ * @group Extractors
+ */
val Ident: IdentExtractor
/** An extractor class to create and pattern match with syntax `Ident(qual, name)`.
@@ -1409,32 +1915,42 @@ trait Trees { self: Universe =>
*
* Type checker converts idents that refer to enclosing fields or methods to selects.
* For example, name ==> this.name
+ * @group Extractors
*/
abstract class IdentExtractor {
def apply(name: Name): Ident
def unapply(ident: Ident): Option[Name]
}
- /** The API that all idents support */
+ /** The API that all idents support
+ * @group API
+ */
trait IdentApi extends RefTreeApi { this: Ident =>
+ /** @inheritdoc */
val name: Name
}
/** Marks underlying reference to id as boxed.
- * @pre id must refer to a captured variable
+ *
+ * <b>Precondition:<\b> id must refer to a captured variable
* A reference such marked will refer to the boxed entity, no dereferencing
* with `.elem` is done on it.
* This tree node can be emitted by macros such as reify that call referenceCapturedVariable.
* It is eliminated in LambdaLift, where the boxing conversion takes place.
+ * @group Trees
+ * @template
*/
type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi
/** A tag that preserves the identity of the `ReferenceToBoxed` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ReferenceToBoxedTag: ClassTag[ReferenceToBoxed]
- /** The constructor/deconstructor for `ReferenceToBoxed` instances. */
+ /** The constructor/deconstructor for `ReferenceToBoxed` instances.
+ * @group Extractors
+ */
val ReferenceToBoxed: ReferenceToBoxedExtractor
/** An extractor class to create and pattern match with syntax `ReferenceToBoxed(ident)`.
@@ -1455,40 +1971,54 @@ trait Trees { self: Universe =>
* Select(Ident(x), "elem")
*
* If `ReferenceToBoxed` were used instead of Ident, no transformation would be performed.
+ * @group Extractors
*/
abstract class ReferenceToBoxedExtractor {
def apply(ident: Ident): ReferenceToBoxed
def unapply(referenceToBoxed: ReferenceToBoxed): Option[Ident]
}
- /** The API that all references support */
+ /** The API that all references support
+ * @group API
+ */
trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed =>
+ /** The underlying reference. */
val ident: Tree
}
- /** Literal */
+ /** Literal
+ * @group Trees
+ * @template
+ */
type Literal >: Null <: TermTree with LiteralApi
/** A tag that preserves the identity of the `Literal` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val LiteralTag: ClassTag[Literal]
- /** The constructor/deconstructor for `Literal` instances. */
+ /** The constructor/deconstructor for `Literal` instances.
+ * @group Extractors
+ */
val Literal: LiteralExtractor
/** An extractor class to create and pattern match with syntax `Literal(value)`.
* This AST node corresponds to the following Scala code:
*
* value
+ * @group Extractors
*/
abstract class LiteralExtractor {
def apply(value: Constant): Literal
def unapply(literal: Literal): Option[Constant]
}
- /** The API that all literals support */
+ /** The API that all literals support
+ * @group API
+ */
trait LiteralApi extends TermTreeApi { this: Literal =>
+ /** The compile-time constant underlying the literal. */
val value: Constant
}
@@ -1496,15 +2026,20 @@ trait Trees { self: Universe =>
* annotation ascriptions, annotations on definitions are stored in the Modifiers.
* Eliminated by typechecker (typedAnnotated), the annotations are then stored in
* an AnnotatedType.
+ * @group Trees
+ * @template
*/
type Annotated >: Null <: AnyRef with Tree with AnnotatedApi
/** A tag that preserves the identity of the `Annotated` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotatedTag: ClassTag[Annotated]
- /** The constructor/deconstructor for `Annotated` instances. */
+ /** The constructor/deconstructor for `Annotated` instances.
+ * @group Extractors
+ */
val Annotated: AnnotatedExtractor
/** An extractor class to create and pattern match with syntax `Annotated(annot, arg)`.
@@ -1512,54 +2047,76 @@ trait Trees { self: Universe =>
*
* arg @annot // for types
* arg: @annot // for exprs
+ * @group Extractors
*/
abstract class AnnotatedExtractor {
def apply(annot: Tree, arg: Tree): Annotated
def unapply(annotated: Annotated): Option[(Tree, Tree)]
}
- /** The API that all annotateds support */
+ /** The API that all annotateds support
+ * @group API
+ */
trait AnnotatedApi extends TreeApi { this: Annotated =>
+ /** The annotation. */
val annot: Tree
+
+ /** The annotee. */
val arg: Tree
}
- /** Singleton type, eliminated by RefCheck */
+ /** Singleton type, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi
/** A tag that preserves the identity of the `SingletonTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingletonTypeTreeTag: ClassTag[SingletonTypeTree]
- /** The constructor/deconstructor for `SingletonTypeTree` instances. */
+ /** The constructor/deconstructor for `SingletonTypeTree` instances.
+ * @group Extractors
+ */
val SingletonTypeTree: SingletonTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `SingletonTypeTree(ref)`.
* This AST node corresponds to the following Scala code:
*
* ref.type
+ * @group Extractors
*/
abstract class SingletonTypeTreeExtractor {
def apply(ref: Tree): SingletonTypeTree
def unapply(singletonTypeTree: SingletonTypeTree): Option[Tree]
}
- /** The API that all singleton type trees support */
+ /** The API that all singleton type trees support
+ * @group API
+ */
trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree =>
+ /** The underlying reference. */
val ref: Tree
}
- /** Type selection <qualifier> # <name>, eliminated by RefCheck */
+ /** Type selection <qualifier> # <name>, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
// [Eugene++] don't see why we need it, when we have Select
type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi
/** A tag that preserves the identity of the `SelectFromTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SelectFromTypeTreeTag: ClassTag[SelectFromTypeTree]
- /** The constructor/deconstructor for `SelectFromTypeTree` instances. */
+ /** The constructor/deconstructor for `SelectFromTypeTree` instances.
+ * @group Extractors
+ */
val SelectFromTypeTree: SelectFromTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `SelectFromTypeTree(qualifier, name)`.
@@ -1568,151 +2125,219 @@ trait Trees { self: Universe =>
* qualifier # selector
*
* Note: a path-dependent type p.T is expressed as p.type # T
+ * @group Extractors
*/
abstract class SelectFromTypeTreeExtractor {
def apply(qualifier: Tree, name: TypeName): SelectFromTypeTree
def unapply(selectFromTypeTree: SelectFromTypeTree): Option[(Tree, TypeName)]
}
- /** The API that all selects from type trees support */
+ /** The API that all selects from type trees support
+ * @group API
+ */
trait SelectFromTypeTreeApi extends TypTreeApi with RefTreeApi { this: SelectFromTypeTree =>
+ /** @inheritdoc */
val qualifier: Tree
+
+ /** @inheritdoc */
val name: TypeName
}
- /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck */
+ /** Intersection type <parent1> with ... with <parentN> { <decls> }, eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi
/** A tag that preserves the identity of the `CompoundTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CompoundTypeTreeTag: ClassTag[CompoundTypeTree]
- /** The constructor/deconstructor for `CompoundTypeTree` instances. */
+ /** The constructor/deconstructor for `CompoundTypeTree` instances.
+ * @group Extractors
+ */
val CompoundTypeTree: CompoundTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `CompoundTypeTree(templ)`.
* This AST node corresponds to the following Scala code:
*
* parent1 with ... with parentN { refinement }
+ * @group Extractors
*/
abstract class CompoundTypeTreeExtractor {
def apply(templ: Template): CompoundTypeTree
def unapply(compoundTypeTree: CompoundTypeTree): Option[Template]
}
- /** The API that all compound type trees support */
+ /** The API that all compound type trees support
+ * @group API
+ */
trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree =>
+ /** The template of the compound type - represents the parents, the optional self-type and the optional definitions. */
val templ: Template
}
- /** Applied type <tpt> [ <args> ], eliminated by RefCheck */
+ /** Applied type <tpt> [ <args> ], eliminated by RefCheck
+ * @group Trees
+ * @template
+ */
type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi
/** A tag that preserves the identity of the `AppliedTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AppliedTypeTreeTag: ClassTag[AppliedTypeTree]
- /** The constructor/deconstructor for `AppliedTypeTree` instances. */
+ /** The constructor/deconstructor for `AppliedTypeTree` instances.
+ * @group Extractors
+ */
val AppliedTypeTree: AppliedTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `AppliedTypeTree(tpt, args)`.
* This AST node corresponds to the following Scala code:
*
* tpt[args]
+ * @group Extractors
*/
abstract class AppliedTypeTreeExtractor {
def apply(tpt: Tree, args: List[Tree]): AppliedTypeTree
def unapply(appliedTypeTree: AppliedTypeTree): Option[(Tree, List[Tree])]
}
- /** The API that all applied type trees support */
+ /** The API that all applied type trees support
+ * @group API
+ */
trait AppliedTypeTreeApi extends TypTreeApi { this: AppliedTypeTree =>
+ /** The target of the application. */
val tpt: Tree
+
+ /** The arguments of the application. */
val args: List[Tree]
}
- /** Document me! */
+ /** Type bounds tree node
+ * @group Trees
+ * @template
+ */
type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi
/** A tag that preserves the identity of the `TypeBoundsTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeBoundsTreeTag: ClassTag[TypeBoundsTree]
- /** The constructor/deconstructor for `TypeBoundsTree` instances. */
+ /** The constructor/deconstructor for `TypeBoundsTree` instances.
+ * @group Extractors
+ */
val TypeBoundsTree: TypeBoundsTreeExtractor
/** An extractor class to create and pattern match with syntax `TypeBoundsTree(lo, hi)`.
* This AST node corresponds to the following Scala code:
*
* >: lo <: hi
+ * @group Extractors
*/
abstract class TypeBoundsTreeExtractor {
def apply(lo: Tree, hi: Tree): TypeBoundsTree
def unapply(typeBoundsTree: TypeBoundsTree): Option[(Tree, Tree)]
}
- /** The API that all type bound trees support */
+ /** The API that all type bound trees support
+ * @group API
+ */
trait TypeBoundsTreeApi extends TypTreeApi { this: TypeBoundsTree =>
+ /** The lower bound.
+ * Is equal to `Ident(<scala.Nothing>)` if not specified explicitly.
+ */
val lo: Tree
+
+ /** The upper bound.
+ * Is equal to `Ident(<scala.Any>)` if not specified explicitly.
+ */
val hi: Tree
}
- /** Document me! */
+ /** Existential type tree node
+ * @group Trees
+ * @template
+ */
type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi
/** A tag that preserves the identity of the `ExistentialTypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ExistentialTypeTreeTag: ClassTag[ExistentialTypeTree]
- /** The constructor/deconstructor for `ExistentialTypeTree` instances. */
+ /** The constructor/deconstructor for `ExistentialTypeTree` instances.
+ * @group Extractors
+ */
val ExistentialTypeTree: ExistentialTypeTreeExtractor
/** An extractor class to create and pattern match with syntax `ExistentialTypeTree(tpt, whereClauses)`.
* This AST node corresponds to the following Scala code:
*
* tpt forSome { whereClauses }
+ * @group Extractors
*/
abstract class ExistentialTypeTreeExtractor {
def apply(tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
def unapply(existentialTypeTree: ExistentialTypeTree): Option[(Tree, List[Tree])]
}
- /** The API that all existential type trees support */
+ /** The API that all existential type trees support
+ * @group API
+ */
trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree =>
+ /** The underlying type of the existential type. */
val tpt: Tree
+
+ /** The clauses of the definition of the existential type. */
val whereClauses: List[Tree]
}
/** A synthetic tree holding an arbitrary type. Not to be confused with
- * with TypTree, the trait for trees that are only used for type trees.
- * TypeTree's are inserted in several places, but most notably in
- * `RefCheck`, where the arbitrary type trees are all replaced by
- * TypeTree's. */
+ * with TypTree, the trait for trees that are only used for type trees.
+ * TypeTree's are inserted in several places, but most notably in
+ * `RefCheck`, where the arbitrary type trees are all replaced by
+ * TypeTree's.
+ * @group Trees
+ * @template
+ */
type TypeTree >: Null <: TypTree with TypeTreeApi
/** A tag that preserves the identity of the `TypeTree` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeTreeTag: ClassTag[TypeTree]
- /** The constructor/deconstructor for `TypeTree` instances. */
+ /** The constructor/deconstructor for `TypeTree` instances.
+ * @group Extractors
+ */
val TypeTree: TypeTreeExtractor
/** An extractor class to create and pattern match with syntax `TypeTree()`.
* This AST node does not have direct correspondence to Scala code,
* and is emitted by everywhere when we want to wrap a `Type` in a `Tree`.
+ * @group Extractors
*/
abstract class TypeTreeExtractor {
def apply(): TypeTree
def unapply(typeTree: TypeTree): Boolean
}
- /** The API that all type trees support */
+ /** The API that all type trees support
+ * @group API
+ */
trait TypeTreeApi extends TypTreeApi { this: TypeTree =>
+ /** The precursor of this tree.
+ * Is equal to `EmptyTree` if this type tree doesn't have precursors.
+ */
def original: Tree
}
@@ -1720,156 +2345,415 @@ trait Trees { self: Universe =>
* val _: _
* This is used as a placeholder in the `self` parameter Template if there is
* no definition of a self value of self type.
+ * @group Trees
*/
val emptyValDef: ValDef
// ---------------------- factories ----------------------------------------------
- /** @param sym the class symbol
- * @param impl the implementation template
+ /** A factory method for `ClassDef` nodes.
+ * @group Factories
*/
def ClassDef(sym: Symbol, impl: Template): ClassDef
- /**
- * @param sym the class symbol
- * @param impl the implementation template
+ /** A factory method for `ModuleDef` nodes.
+ * @group Factories
*/
def ModuleDef(sym: Symbol, impl: Template): ModuleDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def ValDef(sym: Symbol, rhs: Tree): ValDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def ValDef(sym: Symbol): ValDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, rhs: Tree): DefDef
+ /** A factory method for `ValDef` nodes.
+ * @group Factories
+ */
def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef
- /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */
+ /** A factory method for `TypeDef` nodes.
+ * @group Factories
+ */
def TypeDef(sym: Symbol, rhs: Tree): TypeDef
- /** A TypeDef node which defines abstract type or type parameter for given `sym` */
+ /** A factory method for `TypeDef` nodes.
+ * @group Factories
+ */
def TypeDef(sym: Symbol): TypeDef
+ /** A factory method for `LabelDef` nodes.
+ * @group Factories
+ */
def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef
- /** Block factory that flattens directly nested blocks.
+ /** A factory method for `Block` nodes.
+ * Flattens directly nested blocks.
+ * @group Factories
*/
def Block(stats: Tree*): Block
- /** casedef shorthand */
+ /** A factory method for `CaseDef` nodes.
+ * @group Factories
+ */
def CaseDef(pat: Tree, body: Tree): CaseDef
+ /** A factory method for `Bind` nodes.
+ * @group Factories
+ */
def Bind(sym: Symbol, body: Tree): Bind
+ /** A factory method for `Try` nodes.
+ * @group Factories
+ */
def Try(body: Tree, cases: (Tree, Tree)*): Try
+ /** A factory method for `Throw` nodes.
+ * @group Factories
+ */
def Throw(tpe: Type, args: Tree*): Throw
/** Factory method for object creation `new tpt(args_1)...(args_n)`
* A `New(t, as)` is expanded to: `(new t).<init>(as)`
+ * @group Factories
*/
def New(tpt: Tree, argss: List[List[Tree]]): Tree
/** 0-1 argument list new, based on a type.
+ * @group Factories
*/
def New(tpe: Type, args: Tree*): Tree
+ /** 0-1 argument list new, based on a symbol.
+ * @group Factories
+ */
def New(sym: Symbol, args: Tree*): Tree
+ /** A factory method for `Apply` nodes.
+ * @group Factories
+ */
def Apply(sym: Symbol, args: Tree*): Tree
+ /** 0-1 argument list new, based on a type tree.
+ * @group Factories
+ */
def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree
+ /** A factory method for `Super` nodes.
+ * @group Factories
+ */
def Super(sym: Symbol, mix: TypeName): Tree
+ /** A factory method for `This` nodes.
+ * @group Factories
+ */
def This(sym: Symbol): Tree
+ /** A factory method for `Select` nodes.
+ * The string `name` argument is assumed to represent a [[scala.reflect.api.Names#TermName `TermName`]].
+ * @group Factories
+ */
def Select(qualifier: Tree, name: String): Select
+ /** A factory method for `Select` nodes.
+ * @group Factories
+ */
def Select(qualifier: Tree, sym: Symbol): Select
+ /** A factory method for `Ident` nodes.
+ * @group Factories
+ */
def Ident(name: String): Ident
+ /** A factory method for `Ident` nodes.
+ * @group Factories
+ */
def Ident(sym: Symbol): Ident
+ /** A factory method for `TypeTree` nodes.
+ * @group Factories
+ */
def TypeTree(tp: Type): TypeTree
// ---------------------- copying ------------------------------------------------
- /** The standard (lazy) tree copier
+ /** The type of standard (lazy) tree copiers.
+ * @template
+ * @group Copying
*/
type TreeCopier <: TreeCopierOps
+
+ /** The standard (lazy) tree copier.
+ * @group Copying
+ */
val treeCopy: TreeCopier = newLazyTreeCopier
+ /** Creates a strict tree copier.
+ * @group Copying
+ */
def newStrictTreeCopier: TreeCopier
+
+ /** Creates a lazy tree copier.
+ * @group Copying
+ */
def newLazyTreeCopier: TreeCopier
/** The API of a tree copier
- * tree copiers are made available by an implicit conversion in reflect.ops
+ * @group API
*/
abstract class TreeCopierOps {
+ /** Creates a `ClassDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef
+
+ /** Creates a `PackageDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef
+
+ /** Creates a `ModuleDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef
+
+ /** Creates a `ValDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef
+
+ /** Creates a `DefDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
+
+ /** Creates a `TypeDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
+
+ /** Creates a `LabelDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
+
+ /** Creates a `Import` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
+
+ /** Creates a `Template` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
+
+ /** Creates a `Block` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
+
+ /** Creates a `CaseDef` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
+
+ /** Creates a `Alternative` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Alternative(tree: Tree, trees: List[Tree]): Alternative
+
+ /** Creates a `Star` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Star(tree: Tree, elem: Tree): Star
+
+ /** Creates a `Bind` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Bind(tree: Tree, name: Name, body: Tree): Bind
+
+ /** Creates a `UnApply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply
+
+ /** Creates a `Function` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function
+
+ /** Creates a `Assign` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign
+
+ /** Creates a `AssignOrNamedArg` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg
+
+ /** Creates a `If` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
+
+ /** Creates a `Match` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
+
+ /** Creates a `Return` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Return(tree: Tree, expr: Tree): Return
+
+ /** Creates a `Try` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
+
+ /** Creates a `Throw` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Throw(tree: Tree, expr: Tree): Throw
+
+ /** Creates a `New` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def New(tree: Tree, tpt: Tree): New
+
+ /** Creates a `Typed` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
+
+ /** Creates a `TypeApply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
+
+ /** Creates a `Apply` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
+
+ /** Creates a `Super` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Super(tree: Tree, qual: Tree, mix: TypeName): Super
+
+ /** Creates a `This` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def This(tree: Tree, qual: Name): This
+
+ /** Creates a `Select` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Select(tree: Tree, qualifier: Tree, selector: Name): Select
+
+ /** Creates a `Ident` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Ident(tree: Tree, name: Name): Ident
+
+ /** Creates a `ReferenceToBoxed` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
+
+ /** Creates a `Literal` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Literal(tree: Tree, value: Constant): Literal
+
+ /** Creates a `TypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeTree(tree: Tree): TypeTree
+
+ /** Creates a `Annotated` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
+
+ /** Creates a `SingletonTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
+
+ /** Creates a `SelectFromTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
+
+ /** Creates a `CompoundTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree
+
+ /** Creates a `AppliedTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
+
+ /** Creates a `TypeBoundsTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
+
+ /** Creates a `ExistentialTypeTree` node from the given components, having a given `tree` as a prototype.
+ * Having a tree as a prototype means that the tree's attachments, type and symbol will be copied into the result.
+ */
def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
}
// ---------------------- traversing and transforming ------------------------------
+ /** A class that implement a default tree traversal strategy: breadth-first component-wise.
+ * @group Traversal
+ */
class Traverser {
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
+ /** Traverses a single tree. */
def traverse(tree: Tree): Unit = itraverse(this, tree)
+ /** Traverses a list of trees. */
def traverseTrees(trees: List[Tree]) {
trees foreach traverse
}
+
+ /** Traverses a list of lists of trees. */
def traverseTreess(treess: List[List[Tree]]) {
treess foreach traverseTrees
}
+
+ /** Traverses a list of trees with a given owner symbol. */
def traverseStats(stats: List[Tree], exprOwner: Symbol) {
stats foreach (stat =>
if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat))
@@ -1877,6 +2761,7 @@ trait Trees { self: Universe =>
)
}
+ /** Performs a traversal with a given owner symbol. */
def atOwner(owner: Symbol)(traverse: => Unit) {
val prevOwner = currentOwner
currentOwner = owner
@@ -1889,49 +2774,81 @@ trait Trees { self: Universe =>
def apply[T <: Tree](tree: T): T = { traverse(tree); tree }
}
+ /** Delegates the traversal strategy to `scala.reflect.internal.Trees`,
+ * because pattern matching on abstract types we have here degrades performance.
+ * @group Traversal
+ */
protected def itraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)
+ /** Provides an extension hook for the traversal strategy.
+ * Future-proofs against new node types.
+ * @group Traversal
+ */
protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)
+ /** A class that implement a default tree transformation strategy: breadth-first component-wise cloning.
+ * @group Traversal
+ */
abstract class Transformer {
+ /** The underlying tree copier. */
val treeCopy: TreeCopier = newLazyTreeCopier
+
+ /** The current owner symbol. */
protected[scala] var currentOwner: Symbol = rootMirror.RootClass
+
+ /** The enclosing method of the currently transformed tree. */
protected def currentMethod = {
def enclosingMethod(sym: Symbol): Symbol =
if (sym.isMethod || sym == NoSymbol) sym else enclosingMethod(sym.owner)
enclosingMethod(currentOwner)
}
+
+ /** The enclosing class of the currently transformed tree. */
protected def currentClass = {
def enclosingClass(sym: Symbol): Symbol =
if (sym.isClass || sym == NoSymbol) sym else enclosingClass(sym.owner)
enclosingClass(currentOwner)
}
+
// protected def currentPackage = currentOwner.enclosingTopLevelClass.owner
+
+ /** Transforms a single tree. */
def transform(tree: Tree): Tree = itransform(this, tree)
- def transformTrees(trees: List[Tree]): List[Tree] =
- trees mapConserve (transform(_))
+ /** Transforms a list of trees. */
+ def transformTrees(trees: List[Tree]): List[Tree] = trees mapConserve (transform(_))
+
+ /** Transforms a `Template`. */
def transformTemplate(tree: Template): Template =
transform(tree: Tree).asInstanceOf[Template]
+ /** Transforms a list of `TypeDef` trees. */
def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] =
trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef])
+ /** Transforms a `ValDef`. */
def transformValDef(tree: ValDef): ValDef =
if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef]
+ /** Transforms a list of `ValDef` nodes. */
def transformValDefs(trees: List[ValDef]): List[ValDef] =
trees mapConserve (transformValDef(_))
+ /** Transforms a list of lists of `ValDef` nodes. */
def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
treess mapConserve (transformValDefs(_))
+ /** Transforms a list of `CaseDef` nodes. */
def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef])
+ /** Transforms a list of `Ident` nodes. */
def transformIdents(trees: List[Ident]): List[Ident] =
trees mapConserve (tree => transform(tree).asInstanceOf[Ident])
+ /** Traverses a list of trees with a given owner symbol. */
def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
stats mapConserve (stat =>
if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
else transform(stat)) filter (EmptyTree != _)
+ /** Transforms `Modifiers`. */
def transformModifiers(mods: Modifiers): Modifiers =
mods.mapAnnotations(transformTrees)
+ /** Transforms a tree with a given owner symbol. */
def atOwner[A](owner: Symbol)(trans: => A): A = {
val prevOwner = currentOwner
currentOwner = owner
@@ -1941,39 +2858,83 @@ trait Trees { self: Universe =>
}
}
+ /** Delegates the transformation strategy to `scala.reflect.internal.Trees`,
+ * because pattern matching on abstract types we have here degrades performance.
+ * @group Traversal
+ */
protected def itransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)
+ /** Provides an extension hook for the transformation strategy.
+ * Future-proofs against new node types.
+ * @group Traversal
+ */
protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)
-
- /** ... */
+ /** The type of tree modifiers.
+ * @group Traversal
+ */
type Modifiers >: Null <: AnyRef with ModifiersApi
/** A tag that preserves the identity of the `Modifiers` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Traversal
*/
implicit val ModifiersTag: ClassTag[Modifiers]
- /** ... */
+ /** The API that all Modifiers support
+ * @group API
+ */
abstract class ModifiersApi {
- def flags: FlagSet // default: NoFlags
+ /** The underlying flags of the enclosing definition.
+ * Is equal to `NoFlags` if none are specified explicitly.
+ */
+ def flags: FlagSet
+
def hasFlag(flag: FlagSet): Boolean
- def privateWithin: Name // default: EmptyTypeName
- def annotations: List[Tree] // default: List()
+
+ /** The visibility scope of the enclosing definition.
+ * Is equal to `tpnme.EMPTY` if none is specified explicitly.
+ */
+ def privateWithin: Name
+
+ /** The annotations of the enclosing definition.
+ * Empty list if none are specified explicitly.
+ */
+ def annotations: List[Tree]
+
+ /** Creates a new instance of `Modifiers` with
+ * the annotations transformed according to the given function.
+ */
def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers =
Modifiers(flags, privateWithin, f(annotations))
}
+ /** The constructor/deconstructor for `Modifiers` instances.
+ * @group Traversal
+ */
val Modifiers: ModifiersCreator
+ /** An extractor class to create and pattern match with syntax `Modifiers(flags, privateWithin, annotations)`.
+ * Modifiers encapsulate flags, visibility annotations and Scala annotations for member definitions.
+ * @group Traversal
+ */
abstract class ModifiersCreator {
- def apply(): Modifiers = Modifiers(NoFlags, EmptyTypeName, List())
+ def apply(): Modifiers = Modifiers(NoFlags, tpnme.EMPTY, List())
def apply(flags: FlagSet, privateWithin: Name, annotations: List[Tree]): Modifiers
}
+ /** The factory for `Modifiers` instances.
+ * @group Traversal
+ */
def Modifiers(flags: FlagSet, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List())
- def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, EmptyTypeName)
- /** ... */
+ /** The factory for `Modifiers` instances.
+ * @group Traversal
+ */
+ def Modifiers(flags: FlagSet): Modifiers = Modifiers(flags, tpnme.EMPTY)
+
+ /** An empty `Modifiers` object: no flags, empty visibility annotation and no Scala annotations.
+ * @group Traversal
+ */
lazy val NoMods = Modifiers()
}
diff --git a/src/reflect/scala/reflect/api/TypeCreator.scala b/src/reflect/scala/reflect/api/TypeCreator.scala
index 2b3ef4320b..9c386f2939 100644
--- a/src/reflect/scala/reflect/api/TypeCreator.scala
+++ b/src/reflect/scala/reflect/api/TypeCreator.scala
@@ -3,23 +3,7 @@ package api
/** A mirror-aware factory for types.
*
- * In the reflection API, artifacts are specific to universes and
- * symbolic references used in artifacts (e.g. `scala.Int`) are resolved by mirrors.
- *
- * Therefore to build a type one needs to know a universe that the type is going to be bound to
- * and a mirror that is going to resolve symbolic references (e.g. to determine that `scala.Int`
- * points to a core class `Int` from scala-library.jar).
- *
- * `TypeCreator` implements this notion by providing a standalone type factory.
- *
- * This is immediately useful for type tags. When the compiler creates a type tag,
- * the end result needs to make sense in any mirror. That's because the compiler knows
- * the universe it's creating a type tag for (since `TypeTag` is path-dependent on a universe),
- * but it cannot know in advance the mirror to instantiate the result in (e.g. on JVM
- * it doesn't know what classloader use to resolve symbolic names in the type tag).
- *
- * Due to a typechecker restriction (no eta-expansion for dependent method types),
- * `TypeCreator` can't have a functional type, so it's implemented as class with an apply method.
+ * This class is used internally by Scala Reflection, and is not recommended for use in client code.
*/
abstract class TypeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Type
diff --git a/src/reflect/scala/reflect/api/TypeTags.scala b/src/reflect/scala/reflect/api/TypeTags.scala
index fc3f067a96..812d5199fc 100644
--- a/src/reflect/scala/reflect/api/TypeTags.scala
+++ b/src/reflect/scala/reflect/api/TypeTags.scala
@@ -18,143 +18,168 @@ import scala.language.implicitConversions
* Backwards compat item1: [Eugene++] it might be useful, though, to guard against abstractness of the incoming type.
*/
/**
- * A type tag encapsulates a representation of type T.
- *
- * Type tags replace the pre-2.10 concept of a [[scala.reflect.Manifest]] and are integrated with reflection.
- *
- * === Overview and examples ===
- *
- * Type tags are organized in a hierarchy of three classes:
- * [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]].
- *
- * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.Universe#TypeTag]], [[scala.reflect.api.Universe#WeakTypeTag]]
- *
- * Examples:
- * {{{
- * scala> class Person
- * scala> class Container[T]
- * scala> import scala.reflect.ClassTag
- * scala> import scala.reflect.runtime.universe.TypeTag
- * scala> import scala.reflect.runtime.universe.WeakTypeTag
- * scala> def firstTypeArg( tag: WeakTypeTag[_] ) = (tag.tpe match {case TypeRef(_,_,typeArgs) => typeArgs})(0)
- * }}}
- * TypeTag contains concrete type arguments:
- * {{{
- * scala> firstTypeArg( implicitly[TypeTag[Container[Person]]] )
- * res0: reflect.runtime.universe.Type = Person
- * }}}
- * TypeTag guarantees concrete type arguments (fails for references to unbound type arguments):
- * {{{
- * scala> def foo1[T] = implicitly[TypeTag[Container[T]]]
- * <console>:11: error: No TypeTag available for Container[T]
- * def foo1[T] = implicitly[TypeTag[Container[T]]]
- * }}}
- * WeakTypeTag allows references to unbound type arguments:
- * {{{
- * scala> def foo2[T] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
- * foo2: [T]=> reflect.runtime.universe.Type
- * scala> foo2[Person]
- * res1: reflect.runtime.universe.Type = T
- * }}}
- * TypeTag allows unbound type arguments for which type tags are available:
- * {{{
- * scala> def foo3[T:TypeTag] = firstTypeArg( implicitly[TypeTag[Container[T]]] )
- * foo3: [T](implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type
- * scala> foo3[Person]
- * res1: reflect.runtime.universe.Type = Person
- * }}}
- * WeakTypeTag contains concrete type arguments if available via existing tags:
- * {{{
- * scala> def foo4[T:WeakTypeTag] = firstTypeArg( implicitly[WeakTypeTag[Container[T]]] )
- * foo4: [T](implicit evidence$1: reflect.runtime.universe.WeakTypeTag[T])reflect.runtime.universe.Type
- * scala> foo4[Person]
- * res1: reflect.runtime.universe.Type = Person
- * }}}
- *
- *
- * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#WeakTypeTag]] are path dependent on their universe.
- *
- * The default universe is [[scala.reflect.runtime.universe]]
- *
- * Type tags can be migrated to another universe given the corresponding mirror using
- *
- * {{{
- * tag.in( other_mirror )
- * }}}
- *
- * See [[scala.reflect.api.TypeTags#WeakTypeTag.in]]
- *
- * === WeakTypeTag vs TypeTag ===
- *
- * Be careful with WeakTypeTag, because it will reify types even if these types are abstract.
- * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime
- * by getting cryptic errors far away from their source. For example, consider the following snippet:
+ * A `TypeTag[T]` encapsulates the runtime type representation of some type `T`.
+ * Like [[scala.reflect.Manifest]], the prime use case of `TypeTag`s is to give access
+ * to erased types. However, `TypeTag`s should be considered to be a richer
+ * replacement of the pre-2.10 notion of a [[scala.reflect.Manifest Manifest]], that
+ * are, in addition, fully integrated with Scala reflection.
+ *
+ * There exist three different types of `TypeTags`:
+ *
+ * <ul>
+ * <li>[[scala.reflect.api.TypeTags#TypeTag]]. <br/>A full type descriptor of a Scala type.
+ * For example, a `TypeTag[List[String]]` contains all type information,
+ * in this case, of type `scala.List[String]`.</li>
+ *
+ * <li>[[scala.reflect.ClassTag]]. <br/>A partial type descriptor of a Scala type. For
+ * example, a `ClassTag[List[String]]` contains only the erased class
+ * type information, in this case, of type `scala.collection.immutable.List`.
+ * `ClassTag`s provide access only to the runtime class of a type.
+ * Analogous to [[scala.reflect.ClassManifest]]</li>
+ *
+ * <li>[[scala.reflect.api.TypeTags#WeakTypeTag]]. <br/>A type descriptor for abstract
+ * types (see description below).</li>
+ * </ul>
+ *
+ * Like [[scala.reflect.Manifest Manifest]]s, `TypeTag`s are always generated by the
+ * compiler, and can be obtained in three ways:
+ *
+ * === #1 Via the methods [[scala.reflect.api.TypeTags#typeTag typeTag]],
+ * [[scala.reflect#classTag classTag]], or [[scala.reflect.api.TypeTags#weakTypeTag weakTypeTag]] ===
+ *
+ * For example:
+ * {{{
+ * import scala.reflect.runtime.universe._
+ * val tt = typeTag[Int]
+ *
+ * import scala.reflect._
+ * val ct = classTag[String]
+ * }}}
+ *
+ * Each of these methods constructs a `TypeTag[T]` or `ClassTag[T]` for the given
+ * type argument `T`.
+ *
+ * === #2 Using an implicit parameter of type `TypeTag[T]`, `ClassTag[T]`, or `WeakTypeTag[T]
+ *
+ * For example:
+ * {{{
+ * import scala.reflect.runtime.universe._
+ *
+ * def paramInfo[T](x: T)(implicit tag: TypeTag[T]): Unit = {
+ * val targs = tag.tpe match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
+ * }
+ *
+ * scala> paramInfo(42)
+ * type of 42 has type arguments List()
+ *
+ * scala> paramInfo(List(1, 2))
+ * type of List(1, 2) has type arguments List(Int)
+ * }}}
+ *
+ * === #3 Context bound of a type parameter ===
+ *
+ * ...on methods or classes. The above example can be implemented as follows:
*
* {{{
- * def bind[T: WeakTypeTag](name: String, value: T): IR.Result = bind((name, value))
- * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
- * object NamedParam {
- * implicit def namedValue[T: WeakTypeTag](name: String, x: T): NamedParam = apply(name, x)
- * def apply[T: WeakTypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
+ * import scala.reflect.runtime.universe._
+ *
+ * def paramInfo[T: TypeTag](x: T): Unit = {
+ * val targs = typeOf[T] match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
* }
+ *
+ * scala> paramInfo(42)
+ * type of 42 has type arguments List()
+ *
+ * scala> paramInfo(List(1, 2))
+ * type of List(1, 2) has type arguments List(Int)
* }}}
+ *
+ * === `WeakTypeTag`s ===
*
- * This fragment of the Scala REPL implementation defines a `bind` function that carries a named value along with its type
- * into the heart of the REPL. Using a [[scala.reflect.api.Universe#WeakTypeTag]] here is reasonable, because it is desirable
- * to work with all types, even if they are type parameters or abstract type members.
+ *`WeakTypeTag[T]` generalizes `TypeTag[T]`. Unlike a regular `TypeTag`, components of
+ * its type representation can be references to type parameters or abstract types.
+ * However, `WeakTypeTag[T]` tries to be as concrete as possible, i.e. if type tags
+ * are available for the referenced type arguments or abstract types, they are used to
+ * embed the concrete types into the `WeakTypeTag[T]`.
*
- * However if any of the three `WeakTypeTag` context bounds is omitted, the resulting code will be incorrect,
- * because the missing `WeakTypeTag` will be transparently generated by the compiler, carrying meaningless information.
- * Most likely, this problem will manifest itself elsewhere, making debugging complicated.
- * If `WeakTypeTag` context bounds were replaced with `TypeTag`, then such errors would be reported statically.
- * But in that case we wouldn't be able to use `bind` in arbitrary contexts.
+ * Continuing the example above:
+ * {{{
+ * def weakParamInfo[T](x: T)(implicit tag: WeakTypeTag[T]): Unit = {
+ * val targs = tag.tpe match { case TypeRef(_, _, args) => args }
+ * println(s"type of $x has type arguments $targs")
+ * }
+ *
+ * scala> def foo[T] = weakParamInfo(List[T]())
+ * foo: [T]=> Unit
*
- * === Backward compatibility with Manifests ===
+ * scala> foo[Int]
+ * type of List() has type arguments List(T)
+ * }}}
*
- * Type tags correspond loosely to manifests.
+ * === TypeTags and Manifests ===
*
- * More precisely:
- * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
- * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.runtime.universe.TypeTag,
+ * `TypeTag`s correspond loosely to the pre-2.10 notion of
+ * [[scala.reflect.Manifest]]s. While [[scala.reflect.ClassTag]] corresponds to
+ * [[scala.reflect.ClassManifest]] and [[scala.reflect.api.TypeTags#TypeTag]] mostly
+ * corresponds to [[scala.reflect.Manifest]], other pre-2.10 `Manifest` types do not
+ * have a direct correspondence with a 2.10 "`Tag`" type.
*
- * In Scala 2.10, manifests are deprecated, so it's advisable to migrate them to tags,
- * because manifests will probably be removed in the next major release.
+ * <ul>
+ * <li>'''[[scala.reflect.OptManifest]] is not supported.''' <br/>This is because `Tag`s
+ * can reify arbitrary types, so they are always available.<li>
*
- * In most cases it will be enough to replace ClassManifest with ClassTag and Manifest with TypeTag.
- * There are however a few caveats:
+ * <li>'''There is no equivalent for [[scala.reflect.AnyValManifest]].''' <br/>Instead, one
+ * can compare their `Tag` with one of the base `Tag`s (defined in the corresponding
+ * companion objects) in order to find out whether or not it represents a primitive
+ * value class. Additionally, it's possible to simply use
+ * `<tag>.tpe.typeSymbol.isPrimitiveValueClass`.</li>
*
- * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available.
+ * <li>'''There are no replacement for factory methods defined in the `Manifest`
+ * companion objects'''. <br/>Instead, one could generate corresponding types using the
+ * reflection APIs provided by Java (for classes) and Scala (for types).</li>
*
- * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the base tags
- * (defined in the corresponding companion objects) to find out whether it represents a primitive value class.
- * You can also use `<tag>.tpe.typeSymbol.isPrimitiveValueClass` for that purpose (requires scala-reflect.jar).
+ * <li>'''Certain manifest operations(i.e., <:<, >:> and typeArguments) are not
+ * supported.''' <br/>Instead, one culd use the reflection APIs provided by Java (for
+ * classes) and Scala (for types).</li>
+ *</ul>
*
- * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects.
- * Consider assembling corresponding types using the reflection APIs provided by Java (for classes) and Scala (for types).
+ * In Scala 2.10, [[scala.reflect.ClassManifest]]s are deprecated, and it is planned
+ * to deprecate [[scala.reflect.Manifest]] in favor of `TypeTag`s and `ClassTag`s in
+ * an upcoming point release. Thus, it is advisable to migrate any `Manifest`-based
+ * APIs to use `Tag`s.
*
- * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API.
- * Consider using the reflection APIs provided by Java (for classes) and Scala (for types) instead.
+ * For more information about `TypeTag`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
+ *
+ * @see [[scala.reflect.ClassTag]], [[scala.reflect.api.TypeTags#TypeTag]], [[scala.reflect.api.TypeTags#WeakTypeTag]]
+ * @group TypeTags Type Tags
*/
trait TypeTags { self: Universe =>
import definitions._
/**
- * If an implicit value of type WeakTypeTag[T] is required, the compiler will create one.
- * A reflective representation of T can be accessed via the tpe field.
- * Components of T can be references to type parameters or abstract types. WeakTypeTag makes an effort to
- * be as concrete as possible, i.e. if type tags are available for the referenced type arguments or abstract types,
- * they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will contain a reference
- * to an abstract type. This behavior can be useful, when one expects T to be possibly partially abstract, but
- * requires special care to handle this case. If however T is expected to be fully known, use
- * [[scala.reflect.api.Universe#TypeTag]] instead, which statically guarantees this property.
+ * If an implicit value of type `WeakTypeTag[T]` is required, the compiler will create one,
+ * and the reflective representation of `T` can be accessed via the `tpe` field.
+ * Components of `T` can be references to type parameters or abstract types. Note that `WeakTypeTag`
+ * makes an effort to be as concrete as possible, i.e. if `TypeTag`s are available for the referenced type arguments
+ * or abstract types, they are used to embed the concrete types into the WeakTypeTag. Otherwise the WeakTypeTag will
+ * contain a reference to an abstract type. This behavior can be useful, when one expects `T` to be perhaps be partially
+ * abstract, but requires special care to handle this case. However, if `T` is expected to be fully known, use
+ * [[scala.reflect.api.TypeTags#TypeTag]] instead, which statically guarantees this property.
+ *
+ * For more information about `TypeTag`s, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html Reflection Guide: TypeTags]]
*
* @see [[scala.reflect.api.TypeTags]]
+ * @group TypeTags
*/
@annotation.implicitNotFound(msg = "No WeakTypeTag available for ${T}")
trait WeakTypeTag[T] extends Equals with Serializable {
/**
- * Underlying mirror of this type tag.
+ * The underlying `Mirror` of this type tag.
*/
val mirror: Mirror
@@ -171,15 +196,22 @@ trait TypeTags { self: Universe =>
*/
def tpe: Type
- // case class accessories
+ // TODO how do I doc this?
override def canEqual(x: Any) = x.isInstanceOf[WeakTypeTag[_]]
+
+ // TODO how do I doc this?
override def equals(x: Any) = x.isInstanceOf[WeakTypeTag[_]] && this.mirror == x.asInstanceOf[WeakTypeTag[_]].mirror && this.tpe == x.asInstanceOf[WeakTypeTag[_]].tpe
+
+ // TODO how do I doc this?
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
+
+ // TODO how do I doc this?
override def toString = "WeakTypeTag[" + tpe + "]"
}
/**
* Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags.
+ * @group TypeTags
*/
object WeakTypeTag {
val Byte : WeakTypeTag[scala.Byte] = TypeTag.Byte
@@ -222,6 +254,7 @@ trait TypeTags { self: Universe =>
def unapply[T](ttag: WeakTypeTag[T]): Option[Type] = Some(ttag.tpe)
}
+ /* @group TypeTags */
private class WeakTypeTagImpl[T](val mirror: Mirror, val tpec: TypeCreator) extends WeakTypeTag[T] {
lazy val tpe: Type = tpec(mirror)
def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # WeakTypeTag[T] = {
@@ -232,11 +265,12 @@ trait TypeTags { self: Universe =>
}
/**
- * A `TypeTag` is a [[scala.reflect.api.Universe#WeakTypeTag]] with the additional
+ * A `TypeTag` is a [[scala.reflect.api.TypeTags#WeakTypeTag]] with the additional
* static guarantee that all type references are concrete, i.e. it does <b>not</b> contain any references to
* unresolved type parameters or abstract types.
*
* @see [[scala.reflect.api.TypeTags]]
+ * @group TypeTags
*/
@annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
trait TypeTag[T] extends WeakTypeTag[T] with Equals with Serializable {
@@ -245,13 +279,23 @@ trait TypeTags { self: Universe =>
*/
override def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # TypeTag[T]
- // case class accessories
+ /** TODO how do I doc this? */
override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]]
+
+ /** TODO how do I doc this? */
override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.mirror == x.asInstanceOf[TypeTag[_]].mirror && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+
+ /** TODO how do I doc this? */
override def hashCode = mirror.hashCode * 31 + tpe.hashCode
+
+ /** TODO how do I doc this? */
override def toString = "TypeTag[" + tpe + "]"
}
+ /**
+ * Type tags corresponding to primitive types and constructor/extractor for WeakTypeTags.
+ * @group TypeTags
+ */
object TypeTag {
val Byte: TypeTag[scala.Byte] = new PredefTypeTag[scala.Byte] (ByteTpe, _.TypeTag.Byte)
val Short: TypeTag[scala.Short] = new PredefTypeTag[scala.Short] (ShortTpe, _.TypeTag.Short)
@@ -292,6 +336,7 @@ trait TypeTags { self: Universe =>
def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe)
}
+ /* @group TypeTags */
private class TypeTagImpl[T](mirror: Mirror, tpec: TypeCreator) extends WeakTypeTagImpl[T](mirror, tpec) with TypeTag[T] {
override def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # TypeTag[T] = {
val otherMirror1 = otherMirror.asInstanceOf[scala.reflect.api.Mirror[otherMirror.universe.type]]
@@ -300,12 +345,14 @@ trait TypeTags { self: Universe =>
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
}
+ /* @group TypeTags */
private class PredefTypeCreator[T](copyIn: Universe => Universe#TypeTag[T]) extends TypeCreator {
def apply[U <: Universe with Singleton](m: scala.reflect.api.Mirror[U]): U # Type = {
copyIn(m.universe).asInstanceOf[U # TypeTag[T]].tpe
}
}
+ /* @group TypeTags */
private class PredefTypeTag[T](_tpe: Type, copyIn: Universe => Universe#TypeTag[T]) extends TypeTagImpl[T](rootMirror, new PredefTypeCreator(copyIn)) {
override lazy val tpe: Type = _tpe
private def writeReplace(): AnyRef = new SerializedTypeTag(tpec, concrete = true)
@@ -313,22 +360,26 @@ trait TypeTags { self: Universe =>
/**
* Shortcut for `implicitly[WeakTypeTag[T]]`
+ * @group TypeTags
*/
def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag
/**
* Shortcut for `implicitly[TypeTag[T]]`
+ * @group TypeTags
*/
def typeTag[T](implicit ttag: TypeTag[T]) = ttag
// big thanks to Viktor Klang for this brilliant idea!
/**
* Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ * @group TypeTags
*/
def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe
/**
* Shortcut for `implicitly[TypeTag[T]].tpe`
+ * @group TypeTags
*/
def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe
}
diff --git a/src/reflect/scala/reflect/api/Types.scala b/src/reflect/scala/reflect/api/Types.scala
index af70c9e761..2267f21609 100644
--- a/src/reflect/scala/reflect/api/Types.scala
+++ b/src/reflect/scala/reflect/api/Types.scala
@@ -1,37 +1,102 @@
package scala.reflect
package api
-/**
- * Defines the type hierachy for types.
+/** A trait that defines types and operations on them.
*
- * Note: Because of implementation details, some type factories have return type `Type`
- * instead of a more precise type.
+ * Type instances represent information about the type of a corresponding symbol. This includes its members
+ * (methods, fields, type parameters, nested classes, traits, etc) either declared directly or inherited, its base types,
+ * its erasure and so on. Types also provide operation to test for type conformance or euqivalence or for widening.
*
- * @see [[scala.reflect]] for a description on how the class hierarchy is encoded here.
+ * === Instantiating types ===
+ *
+ * There are three ways to instantiate types. The simplest one involves the [[scala.reflect.api.TypeTags#typeOf]] method,
+ * which takes a type argument and produces a `Type` instance that represents that argument. For example, `typeOf[List[Int]]`
+ * produces a [[scala.reflect.api.Types#TypeRef]], which corresponds to a type `List` applied to a type argument `Int`.
+ * Method `typeOf` does not work for types with type parameters, such as `typeOf[List[A]]` where `A` is a type variable.
+ * In this case, use [[scala.reflect.api.TypeTags#weakTypeOf]] instead. Refer to [[scala.reflect.api.TypeTags the type tags page]] to find out
+ * more about this distinction.
+ *
+ * `typeOf` requires spelling out a type explicitly, but there's also a way to capture types implicitly with the [[scala.reflect.api.TypeTags#TypeTag]]
+ * context bound. See [[scala.reflect.api.TypeTags the type tags page]] for details.
+ *
+ * Finally, types can be instantiated manually using factory methods such as `typeRef` or `polyType`.
+ * This is necessary only in cases when `typeOf` or `typeTag` cannot be applied because the type cannot be spelt out
+ * in a Scala snippet, usually when writing macros. Manual construction requires deep knowledge of Scala compiler internals
+ * and should be avoided if possible.
+ *
+ * === Using types ===
+ *
+ * Common operations on types are querying them for inner declarations or type conformance tests.
+ *
+ * Every type has `members` and `declarations` methods (along with their singular counterparts `member` and `declaration`),
+ * which provide the list of definitions associated with that type. For example, to look up the `map` method of `List`, one can
+ * write `typeOf[List[_]].member("map": TermName)`, getting a `MethodSymbol`
+ *
+ * Types expose `<:<` and `weak_<:<` methods to test for subtype relationships. The latter is an extension of the former - it also works
+ * with numeric types (for example, `Int <:< Long` is false, but `Int weak_<:< Long` is true). Unlike the subtype tests implemented by
+ * type tags, tests provided by `Type`s are aware of all the intricacies of the Scala type system and work correctly even for involved types.
+ *
+ * The vanilla `==` method should not be used to compare types for equality. Instead, one should always use the `=:=` method.
+ * Operator `=:=` knows about type aliases, e.g., `typeOf[scala.List[_]] =:= typeOf[scala.collection.immutable.List[_]]`.
+ *
+ * === Exploring types ===
+ *
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> typeOf[List[_]].members.sorted take 5 foreach println
+ * constructor List
+ * method companion
+ * method ::
+ * method :::
+ * method reverse_:::
+ *
+ * scala> def test[T: TypeTag](x: T) = s"I've been called for an x typed as \${typeOf[T]}"
+ * test: [T](x: T)(implicit evidence\$1: reflect.runtime.universe.TypeTag[T])String
+ *
+ * scala> test(2)
+ * res0 @ 3fc80fae: String = I've been called for an x typed as Int
+ *
+ * scala> test(List(2, "x"))
+ * res1 @ 10139edf: String = I've been called for an x typed as List[Any]
+ * }}}
+ *
+ * @groupname TypeCreators Types - Creation
+ * @groupname TypeOps Types - Operations
+ *
+ * @contentDiagram hideNodes "*Api"
*/
trait Types { self: Universe =>
/** The type of Scala types, and also Scala type signatures.
* (No difference is internally made between the two).
+ * @template
+ * @group Types
*/
type Type >: Null <: TypeApi
/** A tag that preserves the identity of the `Type` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeTagg: ClassTag[Type]
/** This constant is used as a special value that indicates that no meaningful type exists.
+ * @group Types
*/
val NoType: Type
/** This constant is used as a special value denoting the empty prefix in a path dependent type.
* For instance `x.type` is represented as `SingleType(NoPrefix, <x>)`, where `<x>` stands for
* the symbol for `x`.
+ * @group Types
*/
val NoPrefix: Type
- /** The API of types
+ /** The API of types.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
*/
abstract class TypeApi {
/** The term symbol associated with the type, or `NoSymbol` for types
@@ -92,7 +157,8 @@ trait Types { self: Universe =>
/** Does this type conform to given type argument `that`? */
def <:< (that: Type): Boolean
- /** Is this type a weak subtype of that type? True also for numeric types, i.e. Int weak_<:< Long.
+ /** Does this type weakly conform to given type argument `that`, i.e., either conforms in terms of `<:<` or both are primitive number types
+ * that conform according to Section "Weak Conformance" in the spec. For example, Int weak_<:< Long.
*/
def weak_<:<(that: Type): Boolean
@@ -186,11 +252,14 @@ trait Types { self: Universe =>
* x.type
* }}}
* as well as [[ConstantType constant types]].
+ * @template
+ * @group Types
*/
type SingletonType >: Null <: Type
/** A tag that preserves the identity of the `SingletonType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingletonTypeTag: ClassTag[SingletonType]
@@ -199,19 +268,25 @@ trait Types { self: Universe =>
* {{{
* C.this.type ThisType(C)
* }}}
+ * @template
+ * @group Types
*/
type ThisType >: Null <: AnyRef with SingletonType with ThisTypeApi
/** A tag that preserves the identity of the `ThisType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ThisTypeTag: ClassTag[ThisType]
- /** The constructor/deconstructor for `ThisType` instances. */
+ /** The constructor/deconstructor for `ThisType` instances.
+ * @group Extractors
+ */
val ThisType: ThisTypeExtractor
/** An extractor class to create and pattern match with syntax `ThisType(sym)`
* where `sym` is the class prefix of the this type.
+ * @group Extractors
*/
abstract class ThisTypeExtractor {
/**
@@ -221,8 +296,12 @@ trait Types { self: Universe =>
def unapply(tpe: ThisType): Option[Symbol]
}
- /** The API that all this types support */
+ /** The API that all this types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ThisTypeApi extends TypeApi { this: ThisType =>
+ /** The underlying class symbol. */
val sym: Symbol
}
@@ -233,29 +312,41 @@ trait Types { self: Universe =>
* p.x.type SingleType(p.type, x)
* x.type SingleType(NoPrefix, x)
* }}}
+ * @template
+ * @group Types
*/
type SingleType >: Null <: AnyRef with SingletonType with SingleTypeApi
/** A tag that preserves the identity of the `SingleType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SingleTypeTag: ClassTag[SingleType]
- /** The constructor/deconstructor for `SingleType` instances. */
+ /** The constructor/deconstructor for `SingleType` instances.
+ * @group Extractors
+ */
val SingleType: SingleTypeExtractor
/** An extractor class to create and pattern match with syntax `SingleType(pre, sym)`
* Here, `pre` is the prefix of the single-type, and `sym` is the stable value symbol
* referred to by the single-type.
+ * @group Extractors
*/
abstract class SingleTypeExtractor {
def apply(pre: Type, sym: Symbol): Type // not SingleTypebecause of implementation details
def unapply(tpe: SingleType): Option[(Type, Symbol)]
}
- /** The API that all single types support */
+ /** The API that all single types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait SingleTypeApi extends TypeApi { this: SingleType =>
+ /** The type of the qualifier. */
val pre: Type
+
+ /** The underlying symbol. */
val sym: Symbol
}
/** The `SuperType` type is not directly written, but arises when `C.super` is used
@@ -266,27 +357,43 @@ trait Types { self: Universe =>
* Here, `thistpe` is the type of the corresponding this-type. For instance,
* in the type arising from C.super, the `thistpe` part would be `ThisType(C)`.
* `supertpe` is the type of the super class referred to by the `super`.
+ * @template
+ * @group Types
*/
type SuperType >: Null <: AnyRef with SingletonType with SuperTypeApi
/** A tag that preserves the identity of the `SuperType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val SuperTypeTag: ClassTag[SuperType]
- /** The constructor/deconstructor for `SuperType` instances. */
+ /** The constructor/deconstructor for `SuperType` instances.
+ * @group Extractors
+ */
val SuperType: SuperTypeExtractor
/** An extractor class to create and pattern match with syntax `SingleType(thistpe, supertpe)`
+ * @group Extractors
*/
abstract class SuperTypeExtractor {
def apply(thistpe: Type, supertpe: Type): Type // not SuperTypebecause of implementation details
def unapply(tpe: SuperType): Option[(Type, Type)]
}
- /** The API that all super types support */
+ /** The API that all super types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait SuperTypeApi extends TypeApi { this: SuperType =>
+ /** The type of the qualifier.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val thistpe: Type
+
+ /** The type of the selector.
+ * See the example for [[scala.reflect.api.Trees#SuperExtractor]].
+ */
val supertpe: Type
}
/** The `ConstantType` type is not directly written in user programs, but arises as the type of a constant.
@@ -295,27 +402,37 @@ trait Types { self: Universe =>
* 1 ConstantType(Constant(1))
* "abc" ConstantType(Constant("abc"))
* }}}
+ * @template
+ * @group Types
*/
type ConstantType >: Null <: AnyRef with SingletonType with ConstantTypeApi
/** A tag that preserves the identity of the `ConstantType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ConstantTypeTag: ClassTag[ConstantType]
- /** The constructor/deconstructor for `ConstantType` instances. */
+ /** The constructor/deconstructor for `ConstantType` instances.
+ * @group Extractors
+ */
val ConstantType: ConstantTypeExtractor
/** An extractor class to create and pattern match with syntax `ConstantType(constant)`
* Here, `constant` is the constant value represented by the type.
+ * @group Extractors
*/
abstract class ConstantTypeExtractor {
def apply(value: Constant): ConstantType
def unapply(tpe: ConstantType): Option[Constant]
}
- /** The API that all constant types support */
+ /** The API that all constant types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ConstantTypeApi extends TypeApi { this: ConstantType =>
+ /** The compile-time constant underlying this type. */
val value: Constant
}
@@ -329,40 +446,61 @@ trait Types { self: Universe =>
* p.C TypeRef(p.type, C, Nil)
* C TypeRef(NoPrefix, C, Nil)
* }}}
+ * @template
+ * @group Types
*/
type TypeRef >: Null <: AnyRef with Type with TypeRefApi
/** A tag that preserves the identity of the `TypeRef` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeRefTag: ClassTag[TypeRef]
- /** The constructor/deconstructor for `TypeRef` instances. */
+ /** The constructor/deconstructor for `TypeRef` instances.
+ * @group Extractors
+ */
val TypeRef: TypeRefExtractor
/** An extractor class to create and pattern match with syntax `TypeRef(pre, sym, args)`
* Here, `pre` is the prefix of the type reference, `sym` is the symbol
* referred to by the type reference, and `args` is a possible empty list of
* type argumenrts.
+ * @group Extractors
*/
abstract class TypeRefExtractor {
def apply(pre: Type, sym: Symbol, args: List[Type]): Type // not TypeRefbecause of implementation details
def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])]
}
- /** The API that all type refs support */
+ /** The API that all type refs support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait TypeRefApi extends TypeApi { this: TypeRef =>
+ /** The prefix of the type reference.
+ * Is equal to `NoPrefix` if the prefix is not applicable.
+ */
val pre: Type
+
+ /** The underlying symbol of the type reference. */
val sym: Symbol
+
+ /** The arguments of the type reference.
+ * Is equal to `Nil` if the arguments are not provided.
+ */
val args: List[Type]
}
/** A subtype of Type representing refined types as well as `ClassInfo` signatures.
+ * @template
+ * @group Types
*/
type CompoundType >: Null <: AnyRef with Type
/** A tag that preserves the identity of the `CompoundType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val CompoundTypeTag: ClassTag[CompoundType]
@@ -373,20 +511,26 @@ trait Types { self: Universe =>
* P_1 with ... with P_m RefinedType(List(P_1, ..., P_m), Scope())
* { D_1; ...; D_n} RefinedType(List(AnyRef), Scope(D_1, ..., D_n))
* }}}
+ * @template
+ * @group Types
*/
type RefinedType >: Null <: AnyRef with CompoundType with RefinedTypeApi
/** A tag that preserves the identity of the `RefinedType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val RefinedTypeTag: ClassTag[RefinedType]
- /** The constructor/deconstructor for `RefinedType` instances. */
+ /** The constructor/deconstructor for `RefinedType` instances.
+ * @group Extractors
+ */
val RefinedType: RefinedTypeExtractor
/** An extractor class to create and pattern match with syntax `RefinedType(parents, decls)`
* Here, `parents` is the list of parent types of the class, and `decls` is the scope
* containing all declarations in the class.
+ * @group Extractors
*/
abstract class RefinedTypeExtractor {
def apply(parents: List[Type], decls: Scope): RefinedType
@@ -398,9 +542,15 @@ trait Types { self: Universe =>
def unapply(tpe: RefinedType): Option[(List[Type], Scope)]
}
- /** The API that all refined types support */
+ /** The API that all refined types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait RefinedTypeApi extends TypeApi { this: RefinedType =>
+ /** The superclasses of the type. */
val parents: List[Type]
+
+ /** The scope that holds the definitions comprising the type. */
val decls: Scope
}
@@ -413,44 +563,63 @@ trait Types { self: Universe =>
* {{{
* ClassInfo(List(P_1, ..., P_m), Scope(D_1, ..., D_n), C)
* }}}
+ * @template
+ * @group Types
*/
type ClassInfoType >: Null <: AnyRef with CompoundType with ClassInfoTypeApi
/** A tag that preserves the identity of the `ClassInfoType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ClassInfoTypeTag: ClassTag[ClassInfoType]
- /** The constructor/deconstructor for `ClassInfoType` instances. */
+ /** The constructor/deconstructor for `ClassInfoType` instances.
+ * @group Extractors
+ */
val ClassInfoType: ClassInfoTypeExtractor
/** An extractor class to create and pattern match with syntax `ClassInfo(parents, decls, clazz)`
* Here, `parents` is the list of parent types of the class, `decls` is the scope
* containing all declarations in the class, and `clazz` is the symbol of the class
* itself.
+ * @group Extractors
*/
abstract class ClassInfoTypeExtractor {
def apply(parents: List[Type], decls: Scope, typeSymbol: Symbol): ClassInfoType
def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)]
}
- /** The API that all class info types support */
+ /** The API that all class info types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ClassInfoTypeApi extends TypeApi { this: ClassInfoType =>
+ /** The superclasses of the class type. */
val parents: List[Type]
+
+ /** The scope that holds the definitions comprising the class type. */
val decls: Scope
+
+ /** The symbol underlying the class type. */
val typeSymbol: Symbol
}
/** The `MethodType` type signature is used to indicate parameters and result type of a method
+ * @template
+ * @group Types
*/
type MethodType >: Null <: AnyRef with Type with MethodTypeApi
/** A tag that preserves the identity of the `MethodType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val MethodTypeTag: ClassTag[MethodType]
- /** The constructor/deconstructor for `MethodType` instances. */
+ /** The constructor/deconstructor for `MethodType` instances.
+ * @group Extractors
+ */
val MethodType: MethodTypeExtractor
/** An extractor class to create and pattern match with syntax `MethodType(params, respte)`
@@ -466,128 +635,183 @@ trait Types { self: Universe =>
* def f: Int
* }}}
* its type is a `NullaryMethodType`.
+ * @group Extractors
*/
abstract class MethodTypeExtractor {
def apply(params: List[Symbol], resultType: Type): MethodType
def unapply(tpe: MethodType): Option[(List[Symbol], Type)]
}
- /** The API that all method types support */
+ /** The API that all method types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait MethodTypeApi extends TypeApi { this: MethodType =>
+ /** The symbols that correspond to the parameters of the method. */
val params: List[Symbol]
+
+ /** The result type of the method. */
val resultType: Type
}
/** The `NullaryMethodType` type signature is used for parameterless methods
* with declarations of the form `def foo: T`
+ * @template
+ * @group Types
*/
type NullaryMethodType >: Null <: AnyRef with Type with NullaryMethodTypeApi
/** A tag that preserves the identity of the `NullaryMethodType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val NullaryMethodTypeTag: ClassTag[NullaryMethodType]
- /** The constructor/deconstructor for `NullaryMethodType` instances. */
+ /** The constructor/deconstructor for `NullaryMethodType` instances.
+ * @group Extractors
+ */
val NullaryMethodType: NullaryMethodTypeExtractor
/** An extractor class to create and pattern match with syntax `NullaryMethodType(resultType)`.
* Here, `resultType` is the result type of the parameterless method.
+ * @group Extractors
*/
abstract class NullaryMethodTypeExtractor {
def apply(resultType: Type): NullaryMethodType
def unapply(tpe: NullaryMethodType): Option[(Type)]
}
- /** The API that all nullary method types support */
+ /** The API that all nullary method types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait NullaryMethodTypeApi extends TypeApi { this: NullaryMethodType =>
+ /** The result type of the method. */
val resultType: Type
}
/** The `PolyType` type signature is used for polymorphic methods
* that have at least one type parameter.
+ * @template
+ * @group Types
*/
type PolyType >: Null <: AnyRef with Type with PolyTypeApi
/** A tag that preserves the identity of the `PolyType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val PolyTypeTag: ClassTag[PolyType]
- /** The constructor/deconstructor for `PolyType` instances. */
+ /** The constructor/deconstructor for `PolyType` instances.
+ * @group Extractors
+ */
val PolyType: PolyTypeExtractor
/** An extractor class to create and pattern match with syntax `PolyType(typeParams, resultType)`.
* Here, `typeParams` are the type parameters of the method and `resultType`
* is the type signature following the type parameters.
+ * @group Extractors
*/
abstract class PolyTypeExtractor {
def apply(typeParams: List[Symbol], resultType: Type): PolyType
def unapply(tpe: PolyType): Option[(List[Symbol], Type)]
}
- /** The API that all polymorphic types support */
+ /** The API that all polymorphic types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait PolyTypeApi extends TypeApi { this: PolyType =>
+ /** The symbols corresponding to the type parameters. */
val typeParams: List[Symbol]
+
+ /** The underlying type. */
val resultType: Type
}
/** The `ExistentialType` type signature is used for existential types and
* wildcard types.
+ * @template
+ * @group Types
*/
type ExistentialType >: Null <: AnyRef with Type with ExistentialTypeApi
/** A tag that preserves the identity of the `ExistentialType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val ExistentialTypeTag: ClassTag[ExistentialType]
- /** The constructor/deconstructor for `ExistentialType` instances. */
+ /** The constructor/deconstructor for `ExistentialType` instances.
+ * @group Extractors
+ */
val ExistentialType: ExistentialTypeExtractor
/** An extractor class to create and pattern match with syntax
* `ExistentialType(quantified, underlying)`.
* Here, `quantified` are the type variables bound by the existential type and `underlying`
* is the type that's existentially quantified.
+ * @group Extractors
*/
abstract class ExistentialTypeExtractor {
def apply(quantified: List[Symbol], underlying: Type): ExistentialType
def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)]
}
- /** The API that all existential types support */
+ /** The API that all existential types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait ExistentialTypeApi extends TypeApi { this: ExistentialType =>
+ /** The symbols corresponding to the `forSome` clauses of the existential type. */
val quantified: List[Symbol]
+
+ /** The underlying type of the existential type. */
val underlying: Type
}
/** The `AnnotatedType` type signature is used for annotated types of the
* for `<type> @<annotation>`.
+ * @template
+ * @group Types
*/
type AnnotatedType >: Null <: AnyRef with Type with AnnotatedTypeApi
/** A tag that preserves the identity of the `AnnotatedType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val AnnotatedTypeTag: ClassTag[AnnotatedType]
- /** The constructor/deconstructor for `AnnotatedType` instances. */
+ /** The constructor/deconstructor for `AnnotatedType` instances.
+ * @group Extractors
+ */
val AnnotatedType: AnnotatedTypeExtractor
/** An extractor class to create and pattern match with syntax
* `AnnotatedType(annotations, underlying, selfsym)`.
* Here, `annotations` are the annotations decorating the underlying type `underlying`.
* `selfSym` is a symbol representing the annotated type itself.
+ * @group Extractors
*/
abstract class AnnotatedTypeExtractor {
def apply(annotations: List[Annotation], underlying: Type, selfsym: Symbol): AnnotatedType
def unapply(tpe: AnnotatedType): Option[(List[Annotation], Type, Symbol)]
}
- /** The API that all annotated types support */
+ /** The API that all annotated types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait AnnotatedTypeApi extends TypeApi { this: AnnotatedType =>
+ /** The annotations. */
val annotations: List[Annotation]
+
+ /** The annotee. */
val underlying: Type
+
+ /** A symbol that represents the annotated type itself. */
val selfsym: Symbol
}
@@ -600,34 +824,51 @@ trait Types { self: Universe =>
* T >: L TypeBounds(L, Any)
* T <: U TypeBounds(Nothing, U)
* }}}
+ * @template
+ * @group Types
*/
type TypeBounds >: Null <: AnyRef with Type with TypeBoundsApi
/** A tag that preserves the identity of the `TypeBounds` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val TypeBoundsTag: ClassTag[TypeBounds]
- /** The constructor/deconstructor for `TypeBounds` instances. */
+ /** The constructor/deconstructor for `TypeBounds` instances.
+ * @group Extractors
+ */
val TypeBounds: TypeBoundsExtractor
/** An extractor class to create and pattern match with syntax `TypeBound(lower, upper)`
* Here, `lower` is the lower bound of the `TypeBounds` pair, and `upper` is
* the upper bound.
+ * @group Extractors
*/
abstract class TypeBoundsExtractor {
def apply(lo: Type, hi: Type): TypeBounds
def unapply(tpe: TypeBounds): Option[(Type, Type)]
}
- /** The API that all type bounds support */
+ /** The API that all type bounds support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait TypeBoundsApi extends TypeApi { this: TypeBounds =>
+ /** The lower bound.
+ * Is equal to `definitions.NothingTpe` if not specified explicitly.
+ */
val lo: Type
+
+ /** The upper bound.
+ * Is equal to `definitions.AnyTpe` if not specified explicitly.
+ */
val hi: Type
}
/** An object representing an unknown type, used during type inference.
* If you see WildcardType outside of inference it is almost certainly a bug.
+ * @group Types
*/
val WildcardType: Type
@@ -640,55 +881,77 @@ trait Types { self: Universe =>
* the name of a method in the converted type, a HasMethodMatching
* type is created: a MethodType with parameters typed as
* BoundedWildcardTypes.
+ * @template
+ * @group Types
*/
type BoundedWildcardType >: Null <: AnyRef with Type with BoundedWildcardTypeApi
/** A tag that preserves the identity of the `BoundedWildcardType` abstract type from erasure.
* Can be used for pattern matching, instance tests, serialization and likes.
+ * @group Tags
*/
implicit val BoundedWildcardTypeTag: ClassTag[BoundedWildcardType]
- /** The constructor/deconstructor for `BoundedWildcardType` instances. */
+ /** The constructor/deconstructor for `BoundedWildcardType` instances.
+ * @group Extractors
+ */
val BoundedWildcardType: BoundedWildcardTypeExtractor
/** An extractor class to create and pattern match with syntax `BoundedWildcardTypeExtractor(bounds)`
* with `bounds` denoting the type bounds.
+ * @group Extractors
*/
abstract class BoundedWildcardTypeExtractor {
def apply(bounds: TypeBounds): BoundedWildcardType
def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
}
- /** The API that all this types support */
+ /** The API that all this types support.
+ * The main source of information about types is the [[scala.reflect.api.Types]] page.
+ * @group API
+ */
trait BoundedWildcardTypeApi extends TypeApi { this: BoundedWildcardType =>
+ /** Type bounds for the wildcard type. */
val bounds: TypeBounds
}
- /** The least upper bound of a list of types, as determined by `<:<`. */
+ /** The least upper bound of a list of types, as determined by `<:<`.
+ * @group TypeOps
+ */
def lub(xs: List[Type]): Type
- /** The greatest lower bound of a list of types, as determined by `<:<`. */
+ /** The greatest lower bound of a list of types, as determined by `<:<`.
+ * @group TypeOps
+ */
def glb(ts: List[Type]): Type
// Creators ---------------------------------------------------------------
// too useful and too non-trivial to be left out of public API
- /** The canonical creator for single-types */
+ /** The canonical creator for single-types
+ * @group TypeCreators
+ */
def singleType(pre: Type, sym: Symbol): Type
- /** the canonical creator for a refined type with a given scope */
+ /** the canonical creator for a refined type with a given scope
+ * @group TypeCreators
+ */
def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type
/** The canonical creator for a refined type with an initially empty scope.
+ * @group TypeCreators
*/
def refinedType(parents: List[Type], owner: Symbol): Type
/** The canonical creator for typerefs
+ * @group TypeCreators
*/
def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type
/** A creator for intersection type where intersections of a single type are
- * replaced by the type itself. */
+ * replaced by the type itself.
+ * @group TypeCreators
+ */
def intersectionType(tps: List[Type]): Type
/** A creator for intersection type where intersections of a single type are
@@ -696,15 +959,19 @@ trait Types { self: Universe =>
*
* !!! Repeated parent classes are not merged - is this a bug in the
* comment or in the code?
+ * @group TypeCreators
*/
def intersectionType(tps: List[Type], owner: Symbol): Type
- /** A creator for type applications */
+ /** A creator for type applications
+ * @group Types
+ */
def appliedType(tycon: Type, args: List[Type]): Type
/** A creator for type parameterizations that strips empty type parameter lists.
* Use this factory method to indicate the type has kind * (it's a polymorphic value)
* until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty).
+ * @group Types
*/
def polyType(tparams: List[Symbol], tpe: Type): Type
@@ -725,6 +992,7 @@ trait Types { self: Universe =>
* The abstraction drops all type parameters that are not directly or
* indirectly referenced by type `tpe1`. If there are no remaining type
* parameters, simply returns result type `tpe`.
+ * @group TypeCreators
*/
def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type
}
diff --git a/src/reflect/scala/reflect/api/Universe.scala b/src/reflect/scala/reflect/api/Universe.scala
index 7d0f6cf0d6..7d1f5c9df1 100644
--- a/src/reflect/scala/reflect/api/Universe.scala
+++ b/src/reflect/scala/reflect/api/Universe.scala
@@ -1,6 +1,58 @@
package scala.reflect
package api
+/**
+ * `Universe` provides a complete set of reflection operations which make it possible for one
+ * to reflectively inspect Scala type relations, such as membership or subtyping.
+ *
+ * [[scala.reflect.api.Universe]] has two specialized sub-universes for different scenarios.
+ * [[scala.reflect.api.JavaUniverse]] adds operations that link symbols and types to the underlying
+ * classes and runtime values of a JVM instance-- this can be thought of as the `Universe` that
+ * should be used for all typical use-cases of Scala reflection. [[scala.reflect.macros.Universe]]
+ * adds operations which allow macros to access selected compiler data structures and operations--
+ * this type of `Universe` should only ever exist within the implementation of a Scala macro.
+ *
+ * `Universe` can be thought of as the entry point to Scala reflection. It mixes-in, and thus provides
+ * an interface to the following main types:
+ *
+ * - [[scala.reflect.api.Types#Type Types]] represent types
+ * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions
+ * - [[scala.reflect.api.Trees#Tree Trees]] represent abstract syntax trees
+ * - [[scala.reflect.api.Names#Name Names]] represent term and type names
+ * - [[scala.reflect.api.Annotations#Annotation Annotations]] represent annotations
+ * - [[scala.reflect.api.Positions#Position Positions]] represent source positions of tree nodes
+ * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
+ * definition trees
+ * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants.
+ *
+ * To obtain a `Universe` to use with Scala runtime reflection, simply make sure to use or import
+ * `scala.reflect.runtime.universe._`
+ * {{{
+ * scala> import scala.reflect.runtime.universe._
+ * import scala.reflect.runtime.universe._
+ *
+ * scala> typeOf[List[Int]]
+ * res0: reflect.runtime.universe.Type = scala.List[Int]
+ *
+ * scala> typeOf[Either[String, Int]]
+ * res1: reflect.runtime.universe.Type = scala.Either[String,Int]
+ * }}}
+ *
+ * To obtain a `Universe` for use within a Scala macro, use [[scala.reflect.macros.Context#universe]]. For example:
+ * {{{
+ * def printf(format: String, params: Any*): Unit = macro impl
+ * def impl(c: Context)(format: c.Expr[String], params: c.Expr[Any]*): c.Expr[Unit] = {
+ * import c.universe._
+ * ...
+ * }
+ * }}}
+ *
+ * For more information about `Universe`s, see the [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]]
+ *
+ * @groupprio Universe -1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
abstract class Universe extends Symbols
with Types
with FlagSets
@@ -20,61 +72,20 @@ abstract class Universe extends Symbols
with Printers
with Importers
{
- /** Produce the abstract syntax tree representing the given Scala expression.
+ /** Use `refiy` to produce the abstract syntax tree representing a given Scala expression.
*
- * For example
+ * For example:
*
* {{{
* val five = reify{ 5 } // Literal(Constant(5))
- * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("$plus")), List( Literal(Constant(4)) ) )
- * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("$plus")), List( Literal(Constant(4)) ) )
+ * reify{ 2 + 4 } // Apply( Select( Literal(Constant(2)), newTermName("\$plus")), List( Literal(Constant(4)) ) )
+ * reify{ five.splice + 4 } // Apply( Select( Literal(Constant(5)), newTermName("\$plus")), List( Literal(Constant(4)) ) )
* }}}
*
* The produced tree is path dependent on the Universe `reify` was called from.
*
- * Use [[scala.reflect.api.Exprs#Expr.splice]] to embed an existing expression into a reify call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced.
- *
- * == Further info and implementation details ==
- *
- * `reify` is implemented as a macro, which given an expression, generates a tree that when compiled and executed produces the original tree.
- *
- * For instance in `reify{ x + 1 }` the macro `reify` receives the abstract syntax tree of `x + 1` as its argument, which is
- *
- * {{{
- * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
- * }}}
- *
- * and returns a tree, which produces the tree above, when compiled and executed. So in other terms, the refiy call expands to something like
- *
- * {{{
- * val $u: u.type = u // where u is a reference to the Universe that calls the reify
- * $u.Expr[Int]($u.Apply($u.Select($u.Ident($u.newFreeVar("x", <Int>, x), "+"), List($u.Literal($u.Constant(1))))))
- * }}}
- *
- * ------
- *
- * Reification performs expression splicing (when processing Expr.splice)
- * and type splicing (for every type T that has a TypeTag[T] implicit in scope):
- *
- * {{{
- * val two = mirror.reify(2) // Literal(Constant(2))
- * val four = mirror.reify(two.splice + two.splice) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree))
- *
- * def macroImpl[T](c: Context) = {
- * ...
- * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion
- * // however, if T were annotated with c.WeakTypeTag (which would declare an implicit parameter for macroImpl)
- * // then reification would substitute T with the TypeTree that was used in a TypeApply of this particular macro invocation
- * val factory = c.reify{ new Queryable[T] }
- * ...
- * }
- * }}}
- *
- * The transformation looks mostly straightforward, but it has its tricky parts:
- * - Reifier retains symbols and types defined outside the reified tree, however
- * locally defined entities get erased and replaced with their original trees
- * - Free variables are detected and wrapped in symbols of the type `FreeTermSymbol` or `FreeTypeSymbol`
- * - Mutable variables that are accessed from a local function are wrapped in refs
+ * Use [[scala.reflect.api.Exprs#Expr.splice]] to embed an existing expression into a `reify` call. Use [[Expr]] to turn a [[Tree]] into an expression that can be spliced.
+ * @group Universe
*/
// implementation is hardwired to `scala.reflect.reify.Taggers`
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
diff --git a/src/reflect/scala/reflect/api/package.scala b/src/reflect/scala/reflect/api/package.scala
index 0b2a43936e..bd9c72a839 100644
--- a/src/reflect/scala/reflect/api/package.scala
+++ b/src/reflect/scala/reflect/api/package.scala
@@ -2,72 +2,35 @@ package scala.reflect
import scala.reflect.api.{Universe => ApiUniverse}
-/**
- * The main package of Scala's reflection library.
- *
- * The reflection library is structured according to the 'cake pattern'. The main layer
- * resides in package [[scala.reflect.api]] and defines an interface to the following main types:
- *
- * - [[scala.reflect.api.Types#Type Types]] represent types
- * - [[scala.reflect.api.Symbols#Symbol Symbols]] represent definitions
- * - [[scala.reflect.api.Trees#Tree Trees]] represent abstract syntax trees
- * - [[scala.reflect.api.Names#Name Names]] represent term and type names
- * - [[scala.reflect.api.Annotations#Annotation Annotations]] represent annotations
- * - [[scala.reflect.api.Positions#Position Positions]] represent source positions of tree nodes
- * - [[scala.reflect.api.FlagSets#FlagSet FlagSet]] represent sets of flags that apply to symbols and
- * definition trees
- * - [[scala.reflect.api.Constants#Constant Constants]] represent compile-time constants.
- *
- * Each of these types are defined in their own enclosing traits, which are ultimately all inherited by class
- * [[scala.reflect.api.Universe Universe]]. The main universe defines a minimal interface to the above types.
- * Universes that provide additional functionality such as deeper introspection or runtime code generation,
- * are defined in packages [[scala.reflect.api]] and `scala.tools.reflect`.
- *
- * The cake pattern employed here requires to write certain Scala idioms with more indirections that usual.
- * What follows is a description of these indirections, which will help to navigate the Scaladocs easily.
- *
- * For instance, consider the base type of all abstract syntax trees: [[scala.reflect.api.Trees#Tree]].
- * This type is not a class but is abstract and has an upper bound of [[scala.reflect.api.Trees#TreeApi]],
- * which is a class defining the minimal base interface for all trees.
- *
- * For a more interesting tree type, consider [[scala.reflect.api.Trees#If]] representing if-expressions.
- * It is defined next to a value `If` of type [[scala.reflect.api.Trees#IfExtractor]].
- * This value serves as the companion object defining a factory method `apply` and a corresponding `unapply`
- * for pattern matching.
- *
- * {{{
- * import scala.reflect.runtime.universe._
- * val cond = reify{ condition }.tree // <- just some tree representing a condition
- * val body = Literal(Constant(1))
- * val other = Literal(Constant(2))
- * val iftree = If(cond,body,other)
- * }}}
- *
- * is equivalent to
- *
- * {{{
- * import scala.reflect.runtime.universe._
- * val iftree = reify{ if( condition ) 1 else 2 }.tree
- * }}}
- *
- * and can be pattern matched as
- *
- * {{{
- * iftree match { case If(cond,body,other) => ... }
- * }}}
- *
- * Moreover, there is an implicit value [[scala.reflect.api.Trees#IfTag]] of type
- * `ClassTag[If]` that is used by the Scala compiler so that we can indeed pattern match on `If`:
- * {{{
- * iftree match { case _:If => ... }
- * }}}
- * Without the given implicit value, this pattern match would raise an "unchecked" warning at compile time
- * since `If` is an abstract type that gets erased at runtime. See [[scala.reflect.ClassTag]] for details.
- *
- * To summarize: each tree type `X` (and similarly for other types such as `Type` or `Symbol`) is represented
- * by an abstract type `X`, optionally together with a class `XApi` that defines `X`'s' interface.
- * `X`'s companion object, if it exists, is represented by a value `X` that is of type `XExtractor`.
- * Moreover, for each type `X`, there is a value `XTag` of type `ClassTag[X]` that allows to pattern match on `X`.
+/** The Scala Reflection API (located in scala-reflect.jar).
+ *
+ * In Scala 2.10.0, the Scala Reflection API and its implementation have an "experimental" status.
+ * This means that the API and the docs are not complete and can be changed in binary- and source-incompatible
+ * manner in 2.10.1. This also means that the implementation has some known issues.
+ *
+ * The following types are the backbone of the Scala Reflection API, and serve as a good starting point
+ * for information about Scala Reflection:
+ *
+ * - [[scala.reflect.api.Symbols]]
+ * - [[scala.reflect.api.Types]]
+ * - [[scala.reflect.api.Mirrors]]
+ * - [[scala.reflect.api.Universe]]
+ *
+ * For more information about Scala Reflection, see the
+ * [[http://docs.scala-lang.org/overviews/reflection/overview.html Reflection Guide]]
+ *
+ * @groupprio API 9
+ * @groupprio Extractors 10
+ * @groupprio Tags 11
+ * @groupdesc API The methods available for each reflection entity, without the implementation. Since the
+ * reflection entities are later overridden by runtime reflection and macros, their API
+ * counterparts guarantee a minimum set of methods that are implemented.
+ * @groupdesc Extractors Extractors provide the machinery necessary to allow pattern matching and construction of
+ * reflection entities that is similar to case classes, although the entities are only abstract
+ * types that are later overridden.
+ * @groupdesc Tags Implicit values that provide [[scala.reflect.ClassTag `ClassTags`]] for the reflection
+ * classes. These are abstract in the interface but are later filled in to provide ClassTags
+ * for the either the runtime reflection or macros entities, depending on the use.
*/
package object api {
diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala
index 6270416d4f..6a3b6870a0 100644
--- a/src/reflect/scala/reflect/internal/FlagSets.scala
+++ b/src/reflect/scala/reflect/internal/FlagSets.scala
@@ -17,8 +17,6 @@ trait FlagSets extends api.FlagSets { self: SymbolTable =>
val NoFlags: FlagSet = 0L
- trait FlagValues extends FlagValuesApi
-
object Flag extends FlagValues {
val TRAIT : FlagSet = Flags.TRAIT
val INTERFACE : FlagSet = Flags.INTERFACE
diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala
index b4f03cfdd1..eaa05bc89d 100644
--- a/src/reflect/scala/reflect/internal/Printers.scala
+++ b/src/reflect/scala/reflect/internal/Printers.scala
@@ -534,17 +534,16 @@ trait Printers extends api.Printers { self: SymbolTable =>
depth += 1
args foreach {
+ case expr: Expr[_] =>
+ print("Expr")
+ if (printTypes) print(expr.staticType)
+ print("(")
+ print(expr.tree)
+ print(")")
case EmptyTree =>
print("EmptyTree")
case emptyValDef: AnyRef if emptyValDef eq self.emptyValDef =>
print("emptyValDef")
- case Literal(Constant(value)) =>
- def print(s: String) = this.print("Literal(Constant(" + s + "))")
- value match {
- case s: String => print("\"" + s + "\"")
- case null => print(null)
- case _ => print(value.toString)
- }
case tree: Tree =>
val hasSymbolField = tree.hasSymbolField && tree.symbol != NoSymbol
val isError = hasSymbolField && tree.symbol.name.toString == nme.ERROR.toString
@@ -568,6 +567,12 @@ trait Printers extends api.Printers { self: SymbolTable =>
} else {
print(name)
}
+ case Constant(s: String) =>
+ print("Constant(\"" + s + "\")")
+ case Constant(null) =>
+ print("Constant(null)")
+ case Constant(value) =>
+ print("Constant(" + value + ")")
case arg =>
print(arg)
},
@@ -582,14 +587,18 @@ trait Printers extends api.Printers { self: SymbolTable =>
if (printIds) print("#", sym.id)
if (printKinds) print("#", sym.abbreviatedKindString)
if (printMirrors) print("%M", footnotes.put[scala.reflect.api.Mirror[_]](mirrorThatLoaded(sym)))
- case NoType =>
- print("NoType")
- case NoPrefix =>
- print("NoPrefix")
+ case tag: TypeTag[_] =>
+ print("TypeTag(", tag.tpe, ")")
+ case tag: WeakTypeTag[_] =>
+ print("WeakTypeTag(", tag.tpe, ")")
case tpe: Type =>
val defer = printTypesInFootnotes && !printingFootnotes
if (defer) print("[", footnotes.put(tpe), "]")
- else printProduct(tpe.asInstanceOf[Product])
+ else tpe match {
+ case NoType => print("NoType")
+ case NoPrefix => print("NoPrefix")
+ case _ => printProduct(tpe.asInstanceOf[Product])
+ }
case mods: Modifiers =>
print("Modifiers(")
if (mods.flags != NoFlags || mods.privateWithin != tpnme.EMPTY || mods.annotations.nonEmpty) print(show(mods.flags))
@@ -598,6 +607,9 @@ trait Printers extends api.Printers { self: SymbolTable =>
print(")")
case name: Name =>
print(show(name))
+ case scope: Scope =>
+ print("Scope")
+ printIterable(scope.toList)
case list: List[_] =>
print("List")
printIterable(list)
@@ -645,16 +657,15 @@ trait Printers extends api.Printers { self: SymbolTable =>
}
def show(name: Name): String = name match {
+ case tpnme.WILDCARD => "tpnme.WILDCARD"
case tpnme.EMPTY => "tpnme.EMPTY"
- case tpnme.ROOT => "tpnme.ROOT"
+ case tpnme.ERROR => "tpnme.ERROR"
case tpnme.PACKAGE => "tpnme.PACKAGE"
- case tpnme.EMPTY_PACKAGE_NAME => "tpnme.EMPTY_PACKAGE_NAME"
- case tpnme.WILDCARD => "tpnme.WILDCARD"
+ case tpnme.WILDCARD_STAR => "tpnme.WILDCARD_STAR"
+ case nme.WILDCARD => "nme.WILDCARD"
case nme.EMPTY => "nme.EMPTY"
- case nme.ROOT => "nme.ROOT"
+ case nme.ERROR => "tpnme.ERROR"
case nme.PACKAGE => "nme.PACKAGE"
- case nme.EMPTY_PACKAGE_NAME => "nme.EMPTY_PACKAGE_NAME"
- case nme.WILDCARD => "nme.WILDCARD"
case nme.CONSTRUCTOR => "nme.CONSTRUCTOR"
case nme.ROOTPKG => "nme.ROOTPKG"
case _ =>
diff --git a/src/reflect/scala/reflect/internal/StdAttachments.scala b/src/reflect/scala/reflect/internal/StdAttachments.scala
index 5c4d1f7e28..9fe443bf50 100644
--- a/src/reflect/scala/reflect/internal/StdAttachments.scala
+++ b/src/reflect/scala/reflect/internal/StdAttachments.scala
@@ -8,7 +8,7 @@ trait StdAttachments {
* Common code between reflect-internal Symbol and Tree related to Attachments.
*/
trait Attachable {
- protected var rawatt: scala.reflect.api.Attachments { type Pos = Position } = NoPosition
+ protected var rawatt: scala.reflect.macros.Attachments { type Pos = Position } = NoPosition
def attachments = rawatt
def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this }
def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this }
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 7d0c05bc81..ee97b3fe2a 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -654,7 +654,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass
final def isMethodWithExtension =
- isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR)
+ isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR) && !isTermMacro
final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
final def isDefinedInPackage = effectiveOwner.isPackageClass
diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala
index e15340543e..92db92d5f3 100644
--- a/src/reflect/scala/reflect/internal/Types.scala
+++ b/src/reflect/scala/reflect/internal/Types.scala
@@ -3923,7 +3923,17 @@ trait Types extends api.Types { self: SymbolTable =>
def avoidWiden: Boolean = avoidWidening
def addLoBound(tp: Type, isNumericBound: Boolean = false) {
- if (!lobounds.contains(tp)) {
+ // For some reason which is still a bit fuzzy, we must let Nothing through as
+ // a lower bound despite the fact that Nothing is always a lower bound. My current
+ // supposition is that the side-effecting type constraint accumulation mechanism
+ // depends on these subtype tests being performed to make forward progress when
+ // there are mutally recursive type vars.
+ // See pos/t6367 and pos/t6499 for the competing test cases.
+ val mustConsider = tp.typeSymbol match {
+ case NothingClass => true
+ case _ => !(lobounds contains tp)
+ }
+ if (mustConsider) {
if (isNumericBound && isNumericValueType(tp)) {
if (numlo == NoType || isNumericSubType(numlo, tp))
numlo = tp
@@ -3943,7 +3953,13 @@ trait Types extends api.Types { self: SymbolTable =>
}
def addHiBound(tp: Type, isNumericBound: Boolean = false) {
- if (!hibounds.contains(tp)) {
+ // My current test case only demonstrates the need to let Nothing through as
+ // a lower bound, but I suspect the situation is symmetrical.
+ val mustConsider = tp.typeSymbol match {
+ case AnyClass => true
+ case _ => !(hibounds contains tp)
+ }
+ if (mustConsider) {
checkWidening(tp)
if (isNumericBound && isNumericValueType(tp)) {
if (numhi == NoType || isNumericSubType(tp, numhi))
@@ -6330,21 +6346,26 @@ trait Types extends api.Types { self: SymbolTable =>
})
if (!cyclic) {
if (up) {
- if (bound.typeSymbol != AnyClass)
+ if (bound.typeSymbol != AnyClass) {
+ log(s"$tvar addHiBound $bound.instantiateTypeParams($tparams, $tvars)")
tvar addHiBound bound.instantiateTypeParams(tparams, tvars)
+ }
for (tparam2 <- tparams)
tparam2.info.bounds.lo.dealias match {
case TypeRef(_, `tparam`, _) =>
+ log(s"$tvar addHiBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
tvar addHiBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
} else {
if (bound.typeSymbol != NothingClass && bound.typeSymbol != tparam) {
+ log(s"$tvar addLoBound $bound.instantiateTypeParams($tparams, $tvars)")
tvar addLoBound bound.instantiateTypeParams(tparams, tvars)
}
for (tparam2 <- tparams)
tparam2.info.bounds.hi.dealias match {
case TypeRef(_, `tparam`, _) =>
+ log(s"$tvar addLoBound $tparam2.tpeHK.instantiateTypeParams($tparams, $tvars)")
tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
@@ -6353,14 +6374,15 @@ trait Types extends api.Types { self: SymbolTable =>
tvar.constr.inst = NoType // necessary because hibounds/lobounds may contain tvar
//println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen)))
-
- tvar setInst (
+ val newInst = (
if (up) {
if (depth != AnyDepth) glb(tvar.constr.hiBounds, depth) else glb(tvar.constr.hiBounds)
} else {
if (depth != AnyDepth) lub(tvar.constr.loBounds, depth) else lub(tvar.constr.loBounds)
- })
-
+ }
+ )
+ log(s"$tvar setInst $newInst")
+ tvar setInst newInst
//Console.println("solving "+tvar+" "+up+" "+(if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds)+((if (up) (tvar.constr.hiBounds) else tvar.constr.loBounds) map (_.widen))+" = "+tvar.constr.inst)//@MDEBUG
}
}
diff --git a/src/reflect/scala/reflect/internal/util/Position.scala b/src/reflect/scala/reflect/internal/util/Position.scala
index 151a64daff..5456d66584 100644
--- a/src/reflect/scala/reflect/internal/util/Position.scala
+++ b/src/reflect/scala/reflect/internal/util/Position.scala
@@ -7,7 +7,7 @@
package scala.reflect.internal.util
import scala.reflect.ClassTag
-import scala.reflect.api.Attachments
+import scala.reflect.macros.Attachments
object Position {
val tabInc = 8
@@ -35,6 +35,50 @@ object Position {
}
}
+/** The Position class and its subclasses represent positions of ASTs and symbols.
+ * Except for NoPosition and FakePos, every position refers to a SourceFile
+ * and to an offset in the sourcefile (its `point`). For batch compilation,
+ * that's all. For interactive IDE's there are also RangePositions
+ * and TransparentPositions. A RangePosition indicates a start and an end
+ * in addition to its point. TransparentPositions are a subclass of RangePositions.
+ * Range positions that are not transparent are called opaque.
+ * Trees with RangePositions need to satisfy the following invariants.
+ *
+ * INV1: A tree with an offset position never contains a child
+ * with a range position
+ * INV2: If the child of a tree with a range position also has a range position,
+ * then the child's range is contained in the parent's range.
+ * INV3: Opaque range positions of children of the same node are non-overlapping
+ * (this means their overlap is at most a single point).
+ *
+ * The following tests are useful on positions:
+ *
+ * pos.isDefined true if position is not a NoPosition nor a FakePosition
+ * pos.isRange true if position is a range
+ * pos.isOpaqueRange true if position is an opaque range
+ *
+ * The following accessor methods are provided:
+ *
+ * pos.source The source file of the position, which must be defined
+ * pos.point The offset of the position's point, which must be defined
+ * pos.start The start of the position, which must be a range
+ * pos.end The end of the position, which must be a range
+ *
+ * There are also convenience methods, such as
+ *
+ * pos.startOrPoint
+ * pos.endOrPoint
+ * pos.pointOrElse(default)
+ *
+ * These are less strict about the kind of position on which they can be applied.
+ *
+ * The following conversion methods are often used:
+ *
+ * pos.focus converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged.
+ * pos.makeTransparent converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
+ */
abstract class Position extends scala.reflect.api.Position { self =>
type Pos = Position
diff --git a/src/reflect/scala/reflect/macros/Aliases.scala b/src/reflect/scala/reflect/macros/Aliases.scala
index 754335d50d..7f7ab66848 100644
--- a/src/reflect/scala/reflect/macros/Aliases.scala
+++ b/src/reflect/scala/reflect/macros/Aliases.scala
@@ -1,33 +1,109 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that defines shorthands for the
+ * most frequently used types and functions of the underlying compiler universe.
+ */
trait Aliases {
self: Context =>
+ /** The type of symbols representing declarations. */
type Symbol = universe.Symbol
+
+ /** The type of Scala types, and also Scala type signatures.
+ * (No difference is internally made between the two).
+ */
type Type = universe.Type
+
+ /** The abstract type of names. */
type Name = universe.Name
+
+ /** The abstract type of names representing terms. */
type TermName = universe.TermName
+
+ /** The abstract type of names representing types. */
type TypeName = universe.TypeName
+
+ /** The type of Scala abstract syntax trees. */
type Tree = universe.Tree
+
+ /** Defines a universe-specific notion of positions. */
type Position = universe.Position
+
+ /** The base type of all scopes. */
type Scope = universe.Scope
+
+ /** The type of tree modifiers. */
type Modifiers = universe.Modifiers
+
+ /** The type of compilation runs. */
type Run = universe.Run
+
+ /** The type of compilation units. */
type CompilationUnit = universe.CompilationUnit
+ /** Expr wraps an abstract syntax tree and tags it with its type. */
type Expr[+T] = universe.Expr[T]
+
+ /** Constructor/Extractor for `Expr`. */
val Expr = universe.Expr
+
+ /** A shorthand to create an expr.
+ *
+ * Unlike the conventional expr factory, which requires a [[scala.reflect.api.TreeCreator]],
+ * this one accepts a regular tree, but the resulting exprs are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def Expr[T: WeakTypeTag](tree: Tree): Expr[T]
+ /** The type of weak type tags. */
type WeakTypeTag[T] = universe.WeakTypeTag[T]
+
+ /** The type of type tags. */
type TypeTag[T] = universe.TypeTag[T]
+
+ /** Constructor/Extractor for `WeakTypeTag`. */
val WeakTypeTag = universe.WeakTypeTag
+
+ /** Constructor/Extractor for `TypeTag`. */
val TypeTag = universe.TypeTag
+
+ /** A shorthand to create a weak type tag.
+ *
+ * Unlike the conventional type tag factory, which requires a [[scala.reflect.api.TypeCreator]],
+ * this one accepts a regular type, but the resulting type tags are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def WeakTypeTag[T](tpe: Type): WeakTypeTag[T]
+
+ /** A shorthand to create a type tag.
+ *
+ * Unlike the conventional type tag factory, which requires a [[scala.reflect.api.TypeCreator]],
+ * this one accepts a regular type, but the resulting type tags are unable of being migrated
+ * to other universes/mirrors (the functionality normally not needed for macros, since there is
+ * only one compile-time universe and only one compile-time mirror).
+ */
def TypeTag[T](tpe: Type): TypeTag[T]
+
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]]`
+ */
def weakTypeTag[T](implicit attag: WeakTypeTag[T]) = attag
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]]`
+ */
def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+
+ /**
+ * Shortcut for `implicitly[WeakTypeTag[T]].tpe`
+ */
def weakTypeOf[T](implicit attag: WeakTypeTag[T]): Type = attag.tpe
+
+ /**
+ * Shortcut for `implicitly[TypeTag[T]].tpe`
+ */
def typeOf[T](implicit ttag: TypeTag[T]): Type = ttag.tpe
}
diff --git a/src/reflect/scala/reflect/api/Attachments.scala b/src/reflect/scala/reflect/macros/Attachments.scala
index edbb0131ca..ba5ccf88f1 100644
--- a/src/reflect/scala/reflect/api/Attachments.scala
+++ b/src/reflect/scala/reflect/macros/Attachments.scala
@@ -1,12 +1,20 @@
package scala.reflect
-package api
+package macros
-/** Attachments is a generalization of Position. Typically it stores a Position of a tree, but this can be extended to
+/** Attachments provide a way to associate custom metadata with symbols and trees.
+ *
+ * Along with `symbol` and `tpe`, which represent core metadata of trees, each tree
+ * carries the `attachments` field that can store other metadata: compiler-defined (e.g. positions) or user-defined.
+ * Same story is true for symbols, which also have extensible metadata by the virtue
+ * of the same `attachments` field.
+ *
+ * Typically attachments just store a [[scala.reflect.api.Position]], but they can be extended to
* encompass arbitrary payloads. Payloads are stored in type-indexed slots, which can be read with `get[T]` and written
* with `update[T]` and `remove[T]`.
*
- * Attachments always carry positions because we don't want to introduce an additional field for attachments in `Tree`
- * imposing an unnecessary memory tax because of something that will not be used in most cases.
+ * This API doesn't have much use in the runtime reflection API (the [[scala.reflect.api]] package), but it might be of help
+ * for macro writers, providing a way to coordinate multiple macros operating on the same code. Therefore the `attachments`
+ * field is only declared in trees and symbols belonging to [[scala.reflect.macros.Universe]].
*/
abstract class Attachments { self =>
@@ -30,8 +38,7 @@ abstract class Attachments { self =>
(all filter matchesTag[T]).headOption.asInstanceOf[Option[T]]
/** Creates a copy of this attachment with the payload slot of T added/updated with the provided value.
- *
- * Replaces an existing payload of the same type, if exists.
+ * Replaces an existing payload of the same type, if exists.
*/
def update[T: ClassTag](attachment: T): Attachments { type Pos = self.Pos } =
new NonemptyAttachments(this.pos, remove[T].all + attachment)
diff --git a/src/reflect/scala/reflect/macros/Context.scala b/src/reflect/scala/reflect/macros/Context.scala
index 7a365ed37b..1f6e97adbc 100644
--- a/src/reflect/scala/reflect/macros/Context.scala
+++ b/src/reflect/scala/reflect/macros/Context.scala
@@ -5,6 +5,25 @@ package macros
// the most lightweight context should just expose the stuff from the SIP
// the full context should include all traits from scala.reflect.macros (and probably reside in scala-compiler.jar)
+/** The Scala macros context.
+ *
+ * See [[scala.reflect.macros.package the overview page]] for a description of how macros work. This documentation
+ * entry provides information on the API available to macro writers.
+ *
+ * A macro context wraps a compiler universe exposed in `universe` and having type [[scala.reflect.macros.Universe]].
+ * This type is a refinement over the generic reflection API provided in [[scala.reflect.api.Universe]]. The
+ * extended Universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees,
+ * add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality
+ * such as `Symbol.deSkolemize` or `Tree.attachments`.
+ *
+ * Another fundamental part of a macro context is `macroApplication`, which provides access to the tree undergoing
+ * macro expansion. Parts of this tree can be found in arguments of the corresponding macro implementations and
+ * in `prefix`, but `macroApplication` gives the full picture.
+ *
+ * Other than that, macro contexts provide facilities for typechecking, exploring the compiler's symbol table and
+ * enclosing trees and compilation units, evaluating trees, logging warnings/errors and much more.
+ * Refer to the documentation of top-level traits in this package to learn the details.
+ */
trait Context extends Aliases
with Enclosures
with Names
@@ -16,15 +35,53 @@ trait Context extends Aliases
with Evals
with ExprUtils {
- /** The compile-time universe */
+ /** The compile-time universe. */
val universe: Universe
- /** The mirror of the compile-time universe */
+ /** The mirror of the compile-time universe. */
val mirror: universe.Mirror
- /** The type of the prefix tree from which the macro is selected */
+ /** The type of the prefix tree from which the macro is selected.
+ * See the documentation entry for `prefix` for an example.
+ */
type PrefixType
- /** The prefix tree from which the macro is selected */
+ /** The prefix tree from which the macro is selected.
+ *
+ * For a example, for a macro `filter` defined as an instance method on a collection `Coll`,
+ * `prefix` represents an equivalent of `this` for normal instance methods:
+ *
+ * {{{
+ * scala> class Coll[T] {
+ * | def filter(p: T => Boolean): Coll[T] = macro M.filter[T]
+ * | }; object M {
+ * | def filter[T](c: Context { type PrefixType = Coll[T] })
+ * | (p: c.Expr[T => Boolean]): c.Expr[Coll[T]] =
+ * | {
+ * | println(c.prefix.tree)
+ * | c.prefix
+ * | }
+ * | }
+ * defined class Coll
+ * defined module Macros
+ *
+ * scala> new Coll[Int]().filter(_ % 2 == 0)
+ * new Coll[Int]()
+ * res0: Coll[Int] = ...
+ *
+ * scala> val x = new Coll[String]()
+ * x: Coll[String] = ...
+ *
+ * scala> x.filter(_ != "")
+ * \$line11.\$read.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.\$iw.x
+ * res1 @ 35563b4b: x.type = ...
+ * }}}
+ *
+ * Note how the value of `prefix` changes depending on the qualifier of the macro call
+ * (i.e. the expression that is at the left-hand side of the dot).
+ *
+ * Another noteworthy thing about the snippet above is the `Context { type PrefixType = Coll[T] }`
+ * type that is used to stress that the macro implementation works with prefixes of type `Coll[T]`.
+ */
val prefix: Expr[PrefixType]
}
diff --git a/src/reflect/scala/reflect/macros/Enclosures.scala b/src/reflect/scala/reflect/macros/Enclosures.scala
index 218cf6ebb3..41d6af94e3 100644
--- a/src/reflect/scala/reflect/macros/Enclosures.scala
+++ b/src/reflect/scala/reflect/macros/Enclosures.scala
@@ -1,6 +1,11 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that exposes
+ * enclosing trees (method, class, compilation unit and currently compiled application),
+ * the enclosing position of the macro expansion, as well as macros and implicits
+ * that are currently in-flight.
+ */
trait Enclosures {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/Evals.scala b/src/reflect/scala/reflect/macros/Evals.scala
index 3837d749da..6aab3d5b02 100644
--- a/src/reflect/scala/reflect/macros/Evals.scala
+++ b/src/reflect/scala/reflect/macros/Evals.scala
@@ -1,9 +1,54 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that provides
+ * a facility to evaluate trees.
+ */
trait Evals {
self: Context =>
- /** .. */
+ /** Takes a typed wrapper for a tree of type `T` and evaluates it to a value of type `T`.
+ *
+ * Can be used to perform compile-time computations on macro arguments to the extent
+ * permitted by the shape of the arguments.
+ *
+ * Known issues: because of [[https://issues.scala-lang.org/browse/SI-5748 https://issues.scala-lang.org/browse/SI-5748]]
+ * trees being evaluated first need to undergo `resetAllAttrs`. Resetting symbols and types
+ * mutates the tree in place, therefore the conventional approach is to `duplicate` the tree first.
+ *
+ * {{{
+ * scala> def impl(c: Context)(x: c.Expr[String]) = {
+ * | val x1 = c.Expr[String](c.resetAllAttrs(x.tree.duplicate))
+ * | println(s"compile-time value is: \${c.eval(x1)}")
+ * | x
+ * | }
+ * impl: (c: Context)(x: c.Expr[String])c.Expr[String]
+ *
+ * scala> def test(x: String) = macro impl
+ * test: (x: String)String
+ *
+ * scala> test("x")
+ * compile-time value is: x
+ * res0: String = x
+ *
+ * scala> test("x" + "y")
+ * compile-time value is: xy
+ * res1: String = xy
+ *
+ * scala> val x = "x"
+ * x: String = x
+ *
+ * scala> test(x + "y")
+ * compile-time value is: xy
+ * res2: String = xy
+ *
+ * scala> { val x = "x"; test(x + "y") }
+ * error: exception during macro expansion:
+ * scala.tools.reflect.ToolBoxError: reflective compilation failed
+ * }}}
+ *
+ * Note that in the last case evaluation has failed, because the argument of a macro
+ * refers to a runtime value `x`, which is unknown at compile time.
+ */
def eval[T](expr: Expr[T]): T
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/macros/ExprUtils.scala b/src/reflect/scala/reflect/macros/ExprUtils.scala
index adcdc78c78..a9acc61735 100644
--- a/src/reflect/scala/reflect/macros/ExprUtils.scala
+++ b/src/reflect/scala/reflect/macros/ExprUtils.scala
@@ -1,32 +1,48 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that defines shorthands for the
+ * most common `Expr`-creating functions.
+ */
trait ExprUtils {
self: Context =>
+ /** Shorthand for `Literal(Constant(null))` in the underlying `universe`. */
def literalNull: Expr[Null]
+ /** Shorthand for `Literal(Constant(()))` in the underlying `universe`. */
def literalUnit: Expr[Unit]
+ /** Shorthand for `Literal(Constant(true))` in the underlying `universe`. */
def literalTrue: Expr[Boolean]
+ /** Shorthand for `Literal(Constant(false))` in the underlying `universe`. */
def literalFalse: Expr[Boolean]
+ /** Shorthand for `Literal(Constant(x: Boolean))` in the underlying `universe`. */
def literal(x: Boolean): Expr[Boolean]
+ /** Shorthand for `Literal(Constant(x: Byte))` in the underlying `universe`. */
def literal(x: Byte): Expr[Byte]
+ /** Shorthand for `Literal(Constant(x: Short))` in the underlying `universe`. */
def literal(x: Short): Expr[Short]
+ /** Shorthand for `Literal(Constant(x: Int))` in the underlying `universe`. */
def literal(x: Int): Expr[Int]
+ /** Shorthand for `Literal(Constant(x: Long))` in the underlying `universe`. */
def literal(x: Long): Expr[Long]
+ /** Shorthand for `Literal(Constant(x: Float))` in the underlying `universe`. */
def literal(x: Float): Expr[Float]
+ /** Shorthand for `Literal(Constant(x: Double))` in the underlying `universe`. */
def literal(x: Double): Expr[Double]
+ /** Shorthand for `Literal(Constant(x: String))` in the underlying `universe`. */
def literal(x: String): Expr[String]
+ /** Shorthand for `Literal(Constant(x: Char))` in the underlying `universe`. */
def literal(x: Char): Expr[Char]
}
diff --git a/src/reflect/scala/reflect/macros/FrontEnds.scala b/src/reflect/scala/reflect/macros/FrontEnds.scala
index e6b67cfc87..8c47202342 100644
--- a/src/reflect/scala/reflect/macros/FrontEnds.scala
+++ b/src/reflect/scala/reflect/macros/FrontEnds.scala
@@ -1,30 +1,44 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides facilities to communicate with the compiler's front end
+ * (emit warnings, errors and other sorts of messages).
+ */
trait FrontEnds {
self: Context =>
/** For sending a message which should not be labeled as a warning/error,
* but also shouldn't require -verbose to be visible.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def echo(pos: Position, msg: String): Unit
- /** Informational messages, suppressed unless -verbose or force=true.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ /** Emits an informational message, suppressed unless `-verbose` or `force=true`.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def info(pos: Position, msg: String, force: Boolean): Unit
- /** Warnings and errors.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ /** Does the compilation session have any warnings?
*/
def hasWarnings: Boolean
- def hasErrors: Boolean
+
+ /** Emits a warning.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
+ */
def warning(pos: Position, msg: String): Unit
+
+ /** Does the compilation session have any errors?
+ */
+ def hasErrors: Boolean
+
+ /** Emits a compilation error.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
+ */
def error(pos: Position, msg: String): Unit
/** Abruptly terminates current macro expansion leaving a note about what happened.
- * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ * Use `enclosingPosition` if you're in doubt what position to pass to `pos`.
*/
def abort(pos: Position, msg: String): Nothing
} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/macros/Infrastructure.scala b/src/reflect/scala/reflect/macros/Infrastructure.scala
index a1ef1c87a3..2f3b8e8d19 100644
--- a/src/reflect/scala/reflect/macros/Infrastructure.scala
+++ b/src/reflect/scala/reflect/macros/Infrastructure.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides facilities to communicate with the compiler's infrastructure.
+ */
trait Infrastructure {
self: Context =>
diff --git a/src/reflect/scala/reflect/macros/Names.scala b/src/reflect/scala/reflect/macros/Names.scala
index fab9bbbca5..20e750b225 100644
--- a/src/reflect/scala/reflect/macros/Names.scala
+++ b/src/reflect/scala/reflect/macros/Names.scala
@@ -1,15 +1,20 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * provides functions that generate unique names.
+ */
trait Names {
self: Context =>
- /** Creates a fresh string */
+ /** Creates a unique string. */
def fresh(): String
- /** Creates a fresh string from the provided string */
+ /** Creates a unique string having a given prefix. */
def fresh(name: String): String
- /** Creates a fresh name from the provided name */
+ /** Creates a unique name having a given name as a prefix and
+ * having the same flavor (term name or type name) as the given name.
+ */
def fresh[NameType <: Name](name: NameType): NameType
}
diff --git a/src/reflect/scala/reflect/macros/Parsers.scala b/src/reflect/scala/reflect/macros/Parsers.scala
index c2d4d8a3ab..bf73c36b1b 100644
--- a/src/reflect/scala/reflect/macros/Parsers.scala
+++ b/src/reflect/scala/reflect/macros/Parsers.scala
@@ -1,14 +1,19 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * exposes functions to parse strings with Scala code into trees.
+ */
trait Parsers {
self: Context =>
- /** .. */
- // todo. distinguish between parsing an expression and parsing arbitrary code
- // for example, parsing in expression mode will fail on packages
+ /** Parses a string with a Scala expression into an abstract syntax tree.
+ * Only works for expressions, i.e. parsing a package declaration will fail.
+ * @throws [[scala.reflect.macros.ParseException]]
+ */
def parse(code: String): Tree
}
-// should be path-dependent, otherwise exception handling becomes a mess
-case class ParseError(val pos: scala.reflect.api.Position, val msg: String) extends Throwable(msg)
+/** Indicates an error during [[scala.reflect.macros.Parsers#parse]].
+ */
+case class ParseException(val pos: scala.reflect.api.Position, val msg: String) extends Exception(msg)
diff --git a/src/reflect/scala/reflect/macros/Reifiers.scala b/src/reflect/scala/reflect/macros/Reifiers.scala
index ed31663c68..d7ee30c7d9 100644
--- a/src/reflect/scala/reflect/macros/Reifiers.scala
+++ b/src/reflect/scala/reflect/macros/Reifiers.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * exposes functions to save reflection artifacts for runtime.
+ */
trait Reifiers {
self: Context =>
@@ -76,6 +79,14 @@ trait Reifiers {
// made these guys non path-dependent, otherwise exception handling quickly becomes a mess
-case class ReificationError(val pos: scala.reflect.api.Position, val msg: String) extends Throwable(msg)
+/** Indicates an expected error during one of the `reifyXXX` methods in [[scala.reflect.macros.Reifiers]].
+ * Such errors represent one of the standard ways for reification to go wrong, e.g.
+ * an attempt to create a `TypeTag` from a weak type.
+ */
+case class ReificationException(val pos: scala.reflect.api.Position, val msg: String) extends Exception(msg)
-case class UnexpectedReificationError(val pos: scala.reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause)
+/** Indicates an unexpected expected error during one of the `reifyXXX` methods in [[scala.reflect.macros.Reifiers]].
+ * Such errors wrap random crashes in reification logic and are distinguished from expected [[scala.reflect.macros.ReificationException]]s
+ * so that the latter can be reported as compilation errors, while the former manifest themselves as compiler crashes.
+ */
+case class UnexpectedReificationException(val pos: scala.reflect.api.Position, val msg: String, val cause: Throwable = null) extends Exception(msg, cause)
diff --git a/src/reflect/scala/reflect/macros/TreeBuilder.scala b/src/reflect/scala/reflect/macros/TreeBuilder.scala
index 5f18ab9ee8..727387c5af 100644
--- a/src/reflect/scala/reflect/macros/TreeBuilder.scala
+++ b/src/reflect/scala/reflect/macros/TreeBuilder.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A helper available in [[scala.reflect.macros.Universe]] that defines shorthands for the
+ * most common tree-creating functions.
+ */
abstract class TreeBuilder {
val global: Universe
@@ -46,12 +49,26 @@ abstract class TreeBuilder {
* @return the newly created trees.
*/
def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(method: Symbol, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(target: Tree, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
+
+ /** TODO how to refer to the main `mkMethodCall`? */
def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
/** A tree that refers to the runtime reflexive universe, ``scala.reflect.runtime.universe''. */
diff --git a/src/reflect/scala/reflect/macros/Typers.scala b/src/reflect/scala/reflect/macros/Typers.scala
index eef6507418..016a08bd01 100644
--- a/src/reflect/scala/reflect/macros/Typers.scala
+++ b/src/reflect/scala/reflect/macros/Typers.scala
@@ -1,6 +1,9 @@
package scala.reflect
package macros
+/** A slice of [[scala.reflect.macros.Context the Scala macros context]] that
+ * partially exposes the type checker to macro writers.
+ */
trait Typers {
self: Context =>
@@ -24,11 +27,11 @@ trait Typers {
* Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation,
* so it might change depending on what is going on during macro expansion.
*/
- def openImplicits: List[(Type, Tree)]
+ def openImplicits: List[(Type, Tree)]
/** Typechecks the provided tree against the expected type `pt` in the macro callsite context.
*
- * If `silent` is false, `TypeError` will be thrown in case of a typecheck error.
+ * If `silent` is false, `TypecheckException` will be thrown in case of a typecheck error.
* If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs.
* Such errors don't vanish and can be inspected by turning on -Ymacro-debug-verbose.
* Unlike in `inferImplicitValue` and `inferImplicitView`, `silent` is false by default.
@@ -36,26 +39,32 @@ trait Typers {
* Typechecking can be steered with the following optional parameters:
* `withImplicitViewsDisabled` recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false
* `withMacrosDisabled` recursively prohibits macro expansions and macro-based implicits, default value is false
+ *
+ * @throws [[scala.reflect.macros.TypecheckException]]
*/
def typeCheck(tree: Tree, pt: Type = WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree
/** Infers an implicit value of the expected type `pt` in the macro callsite context.
* Optional `pos` parameter provides a position that will be associated with the implicit search.
*
- * If `silent` is false, `TypeError` will be thrown in case of an inference error.
+ * If `silent` is false, `TypecheckException` will be thrown in case of an inference error.
* If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs.
* Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
* Unlike in `typeCheck`, `silent` is true by default.
+ *
+ * @throws [[scala.reflect.macros.TypecheckException]]
*/
def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree
/** Infers an implicit view from the provided tree `tree` of the type `from` to the type `to` in the macro callsite context.
* Optional `pos` parameter provides a position that will be associated with the implicit search.
*
- * If `silent` is false, `TypeError` will be thrown in case of an inference error.
+ * If `silent` is false, `TypecheckException` will be thrown in case of an inference error.
* If `silent` is true, the typecheck is silent and will return `EmptyTree` if an error occurs.
* Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
* Unlike in `typeCheck`, `silent` is true by default.
+ *
+ * @throws [[scala.reflect.macros.TypecheckException]]
*/
def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree
@@ -72,12 +81,8 @@ trait Typers {
* For more info, read up https://issues.scala-lang.org/browse/SI-5464.
*/
def resetLocalAttrs(tree: Tree): Tree
+}
- /** Represents an error during typechecking
- */
- type TypeError <: Throwable
- val TypeError: TypeErrorExtractor
- abstract class TypeErrorExtractor {
- def unapply(error: TypeError): Option[(Position, String)]
- }
-} \ No newline at end of file
+/** Indicates an error during one of the methods in [[scala.reflect.macros.Typers]].
+ */
+case class TypecheckException(val pos: scala.reflect.api.Position, val msg: String) extends Exception(msg)
diff --git a/src/reflect/scala/reflect/macros/Universe.scala b/src/reflect/scala/reflect/macros/Universe.scala
index 97d0a8d98a..86bc37b4c9 100644
--- a/src/reflect/scala/reflect/macros/Universe.scala
+++ b/src/reflect/scala/reflect/macros/Universe.scala
@@ -1,69 +1,125 @@
package scala.reflect
package macros
+/** The refinement of [[scala.reflect.api.Universe]] for the use by macro writers.
+ *
+ * This universe provides mutability for reflection artifacts (e.g. macros can change types of compiler trees,
+ * add annotation to symbols representing definitions, etc) and exposes some internal compiler functionality
+ * such as `Symbol.deSkolemize` or `Tree.attachments`.
+ * @groupname Macros Macro Specific Additions
+ * @groupprio Macros -1
+ *
+ * @contentDiagram hideNodes "*Api"
+ */
abstract class Universe extends scala.reflect.api.Universe {
+ /** A factory that encapsulates common tree-building functions.
+ * @group Macros
+ */
val treeBuild: TreeBuilder { val global: Universe.this.type }
+ /** The API of reflection artifacts that support [[scala.reflect.macros.Attachments]].
+ * These artifacts are trees and symbols.
+ * @group Macros
+ */
trait AttachableApi {
- /** ... */
- def attachments: scala.reflect.api.Attachments { type Pos = Position }
+ /** The attachment of the reflection artifact. */
+ def attachments: Attachments { type Pos = Position }
- /** ... */
+ /** Updates the attachment with the payload slot of T added/updated with the provided value.
+ * Replaces an existing payload of the same type, if exists.
+ * Returns the reflection artifact itself.
+ */
def updateAttachment[T: ClassTag](attachment: T): AttachableApi.this.type
- /** ... */
+ /** Update the attachment with the payload of the given class type `T` removed.
+ * Returns the reflection artifact itself.
+ */
def removeAttachment[T: ClassTag]: AttachableApi.this.type
}
// Symbol extensions ---------------------------------------------------------------
+ /** The `Symbol` API is extended for macros: See [[SymbolContextApi]] for details.
+ *
+ * @group Macros
+ */
override type Symbol >: Null <: SymbolContextApi
/** The extended API of symbols that's supported in macro context universes
+ * @group API
*/
trait SymbolContextApi extends SymbolApi with AttachableApi { self: Symbol =>
+ /** If this symbol is a skolem, its corresponding type parameter, otherwise the symbol itself.
+ *
+ * [[https://groups.google.com/forum/#!msg/scala-internals/0j8laVNTQsI/kRXMF_c8bGsJ To quote Martin Odersky]],
+ * skolems are synthetic type "constants" that are copies of existentially bound or universally
+ * bound type variables. E.g. if one is inside the right-hand side of a method:
+ *
+ * {{{
+ * def foo[T](x: T) = ... foo[List[T]]....
+ * }}}
+ *
+ * the skolem named `T` refers to the unknown type instance of `T` when `foo` is called. It needs to be different
+ * from the type parameter because in a recursive call as in the `foo[List[T]]` above the type parameter gets
+ * substituted with `List[T]`, but the ''type skolem'' stays what it is.
+ *
+ * The other form of skolem is an ''existential skolem''. Say one has a function
+ *
+ * {{{
+ * def bar(xs: List[T] forSome { type T }) = xs.head
+ * }}}
+ *
+ * then each occurrence of `xs` on the right will have type `List[T']` where `T'` is a fresh copy of `T`.
+ */
def deSkolemize: Symbol
- /** The position of this symbol
- */
+ /** The position of this symbol. */
def pos: Position
+ /** Sets the `typeSignature` of the symbol. */
def setTypeSignature(tpe: Type): Symbol
+ /** Sets the `annotations` of the symbol. */
def setAnnotations(annots: Annotation*): Symbol
+ /** Sets the `name` of the symbol. */
def setName(name: Name): Symbol
+ /** Sets the `privateWithin` of the symbol. */
def setPrivateWithin(sym: Symbol): Symbol
}
// Tree extensions ---------------------------------------------------------------
+ /** The `Tree` API is extended for macros: See [[TreeContextApi]] for details.
+ *
+ * @group Macros
+ */
override type Tree >: Null <: TreeContextApi
/** The extended API of trees that's supported in macro context universes
+ * @group API
*/
trait TreeContextApi extends TreeApi with AttachableApi { self: Tree =>
- /** ... */
+ /** Sets the `pos` of the tree. Returns `Unit`. */
def pos_=(pos: Position): Unit
- /** ... */
+ /** Sets the `pos` of the tree. Returns the tree itself. */
def setPos(newpos: Position): Tree
- /** ... */
+ /** Sets the `tpe` of the tree. Returns `Unit`. */
def tpe_=(t: Type): Unit
- /** Set tpe to give `tp` and return this.
- */
+ /** Sets the `tpe` of the tree. Returns the tree itself. */
def setType(tp: Type): Tree
/** Like `setType`, but if this is a previously empty TypeTree that
* fact is remembered so that resetAllAttrs will snap back.
*
- * @PP: Attempting to elaborate on the above, I find: If defineType
+ * \@PP: Attempting to elaborate on the above, I find: If defineType
* is called on a TypeTree whose type field is null or NoType,
* this is recorded as "wasEmpty = true". That value is used in
* ResetAttrsTraverser, which nulls out the type field of TypeTrees
@@ -79,55 +135,72 @@ abstract class Universe extends scala.reflect.api.Universe {
*/
def defineType(tp: Type): Tree
- /** ... */
+ /** Sets the `symbol` of the tree. Returns `Unit`. */
def symbol_=(sym: Symbol): Unit
- /** ... */
+ /** Sets the `symbol` of the tree. Returns the tree itself. */
def setSymbol(sym: Symbol): Tree
}
+ /** @inheritdoc */
override type SymTree >: Null <: Tree with SymTreeContextApi
/** The extended API of sym trees that's supported in macro context universes
+ * @group API
*/
trait SymTreeContextApi extends SymTreeApi { this: SymTree =>
+ /** Sets the `symbol` field of the sym tree. */
var symbol: Symbol
}
+ /** @inheritdoc */
override type TypeTree >: Null <: TypTree with TypeTreeContextApi
/** The extended API of sym trees that's supported in macro context universes
+ * @group API
*/
trait TypeTreeContextApi extends TypeTreeApi { this: TypeTree =>
+ /** Sets the `original` field of the type tree. */
def setOriginal(tree: Tree): this.type
}
+ /** @inheritdoc */
override type Ident >: Null <: RefTree with IdentContextApi
/** The extended API of idents that's supported in macro context universes
+ * @group API
*/
trait IdentContextApi extends IdentApi { this: Ident =>
+ /** Was this ident created from a backquoted identifier? */
def isBackquoted: Boolean
}
/** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ * @group Macros
*/
def captureVariable(vble: Symbol): Unit
/** Mark given identifier as a reference to a captured variable itself
* suppressing dereferencing with the `elem` field.
+ * @group Macros
*/
def referenceCapturedVariable(vble: Symbol): Tree
/** Convert type of a captured variable to *Ref type.
+ * @group Macros
*/
def capturedVariableType(vble: Symbol): Type
+ /** The type of compilation runs.
+ * @template
+ * @group Macros
+ */
type Run <: RunContextApi
/** Compilation run uniquely identifies current invocation of the compiler
* (e.g. can be used to implement per-run caches for macros) and provides access to units of work
* of the invocation (currently processed unit of work and the list of all units).
+ * @group API
*/
trait RunContextApi {
/** Currently processed unit of work (a real or a virtual file). */
@@ -137,10 +210,15 @@ abstract class Universe extends scala.reflect.api.Universe {
def units: Iterator[CompilationUnit]
}
+ /** The type of compilation units.
+ * @template
+ * @group Macros
+ */
type CompilationUnit <: CompilationUnitContextApi
/** Compilation unit describes a unit of work of the compilation run.
* It provides such information as file name, textual representation of the unit and the underlying AST.
+ * @group API
*/
trait CompilationUnitContextApi {
/** Source file corresponding to this compilation unit.
@@ -148,7 +226,7 @@ abstract class Universe extends scala.reflect.api.Universe {
* Exposes information about the file as a part of a real or virtual file system
* along with the contents of that file.
*
- * The return type is [[scala.reflect.io.AbstractFile]], which belongs to an experimental part of Scala reflection.
+ * The return type is `scala.reflect.io.AbstractFile`, which belongs to an experimental part of Scala reflection.
* It should not be used unless you know what you are doing. In subsequent releases, this API will be refined
* and exposed as a part of scala.reflect.api.
*/
diff --git a/src/reflect/scala/reflect/macros/package.scala b/src/reflect/scala/reflect/macros/package.scala
new file mode 100644
index 0000000000..3a2f04bcf2
--- /dev/null
+++ b/src/reflect/scala/reflect/macros/package.scala
@@ -0,0 +1,12 @@
+package scala.reflect
+
+/** The base package for Scala macros.
+ *
+ * Macros are functions that are called by the compiler during compilation.
+ * Within these functions the programmer has access to compiler APIs exposed in [[scala.reflect.macros.Context]].
+ * For example, it is possible to generate, analyze and typecheck code.
+ *
+ * See the [[http://docs.scala-lang.org/overviews/macros.html Macros Guide]] on how to get started with Scala macros.
+ */
+package object macros {
+} \ No newline at end of file
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index f7664a46cc..f517c30fe6 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -24,7 +24,7 @@ import scala.language.existentials
import scala.runtime.{ScalaRunTime, BoxesRunTime}
import scala.reflect.internal.util.Collections._
-trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable =>
+private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUniverse: SymbolTable =>
private lazy val mirrors = new WeakHashMap[ClassLoader, WeakReference[JavaMirror]]()
@@ -446,8 +446,7 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUnive
extends TemplateMirror {
def outer: AnyRef
def erasure: ClassSymbol
- lazy val runtimeClass = classToJava(erasure)
- lazy val signature = typeToScala(runtimeClass)
+ lazy val signature = typeToScala(classToJava(erasure))
}
private class JavaClassMirror(val outer: AnyRef, val symbol: ClassSymbol)
@@ -458,10 +457,6 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUnive
checkConstructorOf(constructor, symbol)
new JavaConstructorMirror(outer, constructor)
}
- def companion: Option[ModuleMirror] = symbol.companionModule match {
- case module: ModuleSymbol => Some(new JavaModuleMirror(outer, module))
- case _ => None
- }
override def toString = s"class mirror for ${symbol.fullName} (bound to $outer)"
}
@@ -476,10 +471,6 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUnive
if (outer == null) staticSingletonInstance(classToJava(symbol.moduleClass.asClass))
else innerSingletonInstance(outer, symbol.name)
}
- def companion: Option[ClassMirror] = symbol.companionClass match {
- case cls: ClassSymbol => Some(new JavaClassMirror(outer, cls))
- case _ => None
- }
override def toString = s"module mirror for ${symbol.fullName} (bound to $outer)"
}
@@ -1279,6 +1270,6 @@ trait JavaMirrors extends internal.SymbolTable with api.JavaUniverse { thisUnive
}
}
-class ReflectError(msg: String) extends java.lang.Error(msg)
+private[reflect] class ReflectError(msg: String) extends java.lang.Error(msg)
-class HasJavaClass[J](val getClazz: J => java.lang.Class[_])
+private[reflect] class HasJavaClass[J](val getClazz: J => java.lang.Class[_])
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
index 1d875b10f1..e18435d5b0 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala
@@ -3,8 +3,11 @@ package runtime
import internal.{SomePhase, NoPhase, Phase, TreeGen}
-/** The universe for standard runtime reflection from Java.
- * This type implements all abstract term members in internal.SymbolTable.
+/** An implementation of [[scala.reflect.api.Universe]] for runtime reflection using JVM classloaders.
+ *
+ * Should not be instantiated directly, use [[scala.reflect.runtime.universe]] instead.
+ *
+ * @contentDiagram hideNodes "*Api" "*Extractor"
*/
class JavaUniverse extends internal.SymbolTable with ReflectSetup with runtime.SymbolTable { self =>
diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
index 44d9d94a46..73425bae55 100644
--- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
+++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
@@ -10,7 +10,7 @@ import java.lang.reflect.{ Method, InvocationTargetException, UndeclaredThrowabl
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
*/
-object ReflectionUtils {
+private[scala] object ReflectionUtils {
// Unwraps some chained exceptions which arise during reflective calls.
def unwrapThrowable(x: Throwable): Throwable = x match {
case _: InvocationTargetException | // thrown by reflectively invoked method or constructor
diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala
index 08d58aaadc..7d04202455 100644
--- a/src/reflect/scala/reflect/runtime/Settings.scala
+++ b/src/reflect/scala/reflect/runtime/Settings.scala
@@ -7,7 +7,7 @@ import scala.reflect.internal.settings.MutableSettings
* This should be refined, so that settings are settable via command
* line options or properties.
*/
-class Settings extends MutableSettings {
+private[reflect] class Settings extends MutableSettings {
trait Setting extends SettingValue { }
diff --git a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
index 27107856f3..2b192ce570 100644
--- a/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolLoaders.scala
@@ -5,7 +5,7 @@ import internal.Flags
import java.lang.{Class => jClass, Package => jPackage}
import scala.collection.mutable
-trait SymbolLoaders { self: SymbolTable =>
+private[reflect] trait SymbolLoaders { self: SymbolTable =>
/** The standard completer for top-level classes
* @param clazz The top-level class
diff --git a/src/reflect/scala/reflect/runtime/SymbolTable.scala b/src/reflect/scala/reflect/runtime/SymbolTable.scala
index 73632be965..5c08e9a508 100644
--- a/src/reflect/scala/reflect/runtime/SymbolTable.scala
+++ b/src/reflect/scala/reflect/runtime/SymbolTable.scala
@@ -8,7 +8,7 @@ import scala.reflect.internal.Flags._
* It can be used either from a reflexive universe (class scala.reflect.runtime.JavaUniverse), or else from
* a runtime compiler that uses reflection to get a class information (class scala.tools.reflect.ReflectGlobal)
*/
-trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps {
+private[scala] trait SymbolTable extends internal.SymbolTable with JavaMirrors with SymbolLoaders with SynchronizedOps {
def info(msg: => String) =
if (settings.verbose.value) println("[reflect-compiler] "+msg)
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
index 1a17dd12d2..7b280e59b9 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedOps.scala
@@ -2,7 +2,7 @@ package scala.reflect
package runtime
// SI-6240: test thread-safety, make trees synchronized as well
-trait SynchronizedOps extends internal.SymbolTable
+private[reflect] trait SynchronizedOps extends internal.SymbolTable
with SynchronizedSymbols
with SynchronizedTypes { self: SymbolTable =>
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
index 775583649f..366b4319c3 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -3,7 +3,7 @@ package runtime
import scala.reflect.io.AbstractFile
-trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
+private[reflect] trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
override protected def nextId() = synchronized { super.nextId() }
diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
index 9b4d8d1d48..a3e7c28ca4 100644
--- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
+++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala
@@ -7,7 +7,7 @@ import java.lang.ref.WeakReference
/** This trait overrides methods in reflect.internal, bracketing
* them in synchronized { ... } to make them thread-safe
*/
-trait SynchronizedTypes extends internal.Types { self: SymbolTable =>
+private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTable =>
// No sharing of map objects:
override protected def commonOwnerMap = new CommonOwnerMap
diff --git a/src/reflect/scala/reflect/runtime/package.scala b/src/reflect/scala/reflect/runtime/package.scala
index 7b9f69e657..b97913daf0 100644
--- a/src/reflect/scala/reflect/runtime/package.scala
+++ b/src/reflect/scala/reflect/runtime/package.scala
@@ -1,17 +1,30 @@
package scala.reflect
+/** Entry points into runtime reflection.
+ * See [[scala.reflect.api.package the overview page]] for details on how to use them.
+ */
package object runtime {
- // type is api.JavaUniverse because we only want to expose the `scala.reflect.api.*` subset of reflection
+ /** The entry point into Scala runtime reflection.
+ *
+ * To use Scala runtime reflection, simply use or import `scala.reflect.runtime.universe._`
+ *
+ * See [[scala.reflect.api.Universe]] or the
+ * [[http://docs.scala-lang.org/overviews/reflection/environment-universes-mirrors.html Reflection Guide: Universes]]
+ * for more details.
+ */
lazy val universe: api.JavaUniverse = new runtime.JavaUniverse
+ /** The runtime reflection mirror that corresponds to the current lexical context.
+ * It's typically equivalent to `universe.runtimeMirror(getClass.getClassLoader)` invoked at the call site.
+ */
// implementation hardwired to the `currentMirror` method below
// using the mechanism implemented in `scala.tools.reflect.FastTrack`
def currentMirror: universe.Mirror = ??? // macro
}
package runtime {
- object Macros {
+ private[scala] object Macros {
def currentMirror(c: scala.reflect.macros.Context): c.Expr[universe.Mirror] = {
import c.universe._
val runtimeClass = c.reifyEnclosingRuntimeClass
diff --git a/test/files/neg/t6483.check b/test/files/neg/t6483.check
new file mode 100644
index 0000000000..66e3507107
--- /dev/null
+++ b/test/files/neg/t6483.check
@@ -0,0 +1,9 @@
+t6483.scala:7: error: implementation restriction: qualified super reference is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ override def foo = super[T].foo // error
+ ^
+t6483.scala:20: error: implementation restriction: nested class is not allowed in value class
+This restriction is planned to be removed in subsequent releases.
+ class Inner extends T {
+ ^
+two errors found
diff --git a/test/files/neg/t6483.scala b/test/files/neg/t6483.scala
new file mode 100644
index 0000000000..bd99f68fa4
--- /dev/null
+++ b/test/files/neg/t6483.scala
@@ -0,0 +1,24 @@
+trait T extends Any {
+ def foo = 1
+ type X
+}
+
+class C1(val a: Any) extends AnyVal with T {
+ override def foo = super[T].foo // error
+}
+
+class C2(val a: Int) extends AnyVal with T {
+ override def foo = super.foo + a // okay
+}
+
+class C3(val a: Int) extends AnyVal with T {
+ override def foo = C3.super.foo + a // okay
+}
+
+class C4(val a: Int) extends AnyVal with T {
+ def foo {
+ class Inner extends T {
+ override def foo = super[T].foo + a // no (direct) error, other than that a nested class is currently illegal.
+ }
+ }
+}
diff --git a/test/files/pos/t6215.scala b/test/files/pos/t6215.scala
new file mode 100644
index 0000000000..2f66892b69
--- /dev/null
+++ b/test/files/pos/t6215.scala
@@ -0,0 +1 @@
+class Foo(val v: String) extends AnyVal { private def len = v.length ; def f = len }
diff --git a/test/files/pos/t6485a/Macros_1.scala b/test/files/pos/t6485a/Macros_1.scala
new file mode 100644
index 0000000000..85c2d5dbdb
--- /dev/null
+++ b/test/files/pos/t6485a/Macros_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.macros.Context
+
+object Macros {
+ def crash(c: Context): c.Expr[Unit] = c.universe.reify(())
+} \ No newline at end of file
diff --git a/test/files/pos/t6485a/Test_2.scala b/test/files/pos/t6485a/Test_2.scala
new file mode 100644
index 0000000000..54e260ac74
--- /dev/null
+++ b/test/files/pos/t6485a/Test_2.scala
@@ -0,0 +1,5 @@
+import scala.language.experimental.macros
+
+final class Ops[T](val x: T) extends AnyVal {
+ def f = macro Macros.crash
+}
diff --git a/test/files/pos/t6485b/Test.scala b/test/files/pos/t6485b/Test.scala
new file mode 100644
index 0000000000..382df1c453
--- /dev/null
+++ b/test/files/pos/t6485b/Test.scala
@@ -0,0 +1,10 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+final class Ops[T](val x: T) extends AnyVal {
+ def f = macro Macros.crash
+}
+
+object Macros {
+ def crash(c: Context): c.Expr[Unit] = c.universe.reify(())
+} \ No newline at end of file
diff --git a/test/files/pos/t6499.scala b/test/files/pos/t6499.scala
new file mode 100644
index 0000000000..db376572ee
--- /dev/null
+++ b/test/files/pos/t6499.scala
@@ -0,0 +1,3 @@
+object Test {
+ Map(): Map[_, Int] with Map[_, Int]
+}
diff --git a/test/files/presentation/forgotten-ask.scala b/test/files/presentation/forgotten-ask.scala
new file mode 100644
index 0000000000..358dd75e98
--- /dev/null
+++ b/test/files/presentation/forgotten-ask.scala
@@ -0,0 +1,33 @@
+import scala.tools.nsc.interactive._
+import tests._
+
+/** Test that no ask calls are left unanswered after a compiler has shut down. */
+object Test extends InteractiveTest {
+ import compiler._
+
+ def askItem(): Response[Unit] = {
+ compiler.askForResponse { () =>
+ Thread.sleep(100)
+ }
+ }
+
+ final val Timeout = 5000 //ms
+
+ override def main(args: Array[String]) {
+ val item1 = askItem()
+
+ compiler.askShutdown()
+
+ Thread.sleep(1000) // wait a bit, the compiler is shutting down
+ val item2 = askItem()
+
+ item1.get(Timeout) match {
+ case None => println("TIMEOUT")
+ case _ =>
+ }
+ item2.get(Timeout) match {
+ case None => println("TIMEOUT")
+ case _ =>
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala
index 089f30f389..adecfcff17 100644
--- a/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala
+++ b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala
@@ -11,7 +11,7 @@ object Test extends App {
val macrobody = Select(Ident(newTermName("Impls")), newTermName("foo"))
val macroparam = ValDef(NoMods, newTermName("x"), TypeTree(definitions.IntClass.toType), EmptyTree)
val macrodef = DefDef(Modifiers(MACRO), newTermName("foo"), Nil, List(List(macroparam)), TypeTree(), macrobody)
- val modulector = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(List()), TypeTree(), Block(Apply(Select(Super(This(EmptyTypeName), EmptyTypeName), nme.CONSTRUCTOR), List())))
+ val modulector = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(List()), TypeTree(), Block(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())))
val module = ModuleDef(NoMods, newTermName("Macros"), Template(Nil, emptyValDef, List(modulector, macrodef)))
val macroapp = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
val tree = Block(macrodef, module, macroapp)
diff --git a/test/files/run/macro-typecheck-implicitsdisabled.check b/test/files/run/macro-typecheck-implicitsdisabled.check
index 6cf25076a7..c4fa2c5c28 100644
--- a/test/files/run/macro-typecheck-implicitsdisabled.check
+++ b/test/files/run/macro-typecheck-implicitsdisabled.check
@@ -1,2 +1,2 @@
scala.this.Predef.any2ArrowAssoc[Int](1).->[Int](2)
-scala.reflect.internal.Types$TypeError: value -> is not a member of Int
+scala.reflect.macros.TypecheckException: value -> is not a member of Int
diff --git a/test/files/run/reflection-magicsymbols-invoke.scala b/test/files/run/reflection-magicsymbols-invoke.scala
index b38d1be7b2..5f39370708 100644
--- a/test/files/run/reflection-magicsymbols-invoke.scala
+++ b/test/files/run/reflection-magicsymbols-invoke.scala
@@ -2,6 +2,12 @@ import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe.definitions._
import scala.reflect.runtime.{currentMirror => cm}
+package scala {
+ object ExceptionUtils {
+ def unwrapThrowable(ex: Throwable): Throwable = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ }
+}
+
object Test extends App {
def key(sym: Symbol) = sym + ": " + sym.typeSignature
def test(tpe: Type, receiver: Any, method: String, args: Any*) {
@@ -13,7 +19,7 @@ object Test extends App {
println(result)
} catch {
case ex: Throwable =>
- val realex = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ val realex = scala.ExceptionUtils.unwrapThrowable(ex)
println(realex.getClass + ": " + realex.getMessage)
}
print(s"testing ${tpe.typeSymbol.name}.$method: ")
diff --git a/test/files/run/reflection-valueclasses-magic.scala b/test/files/run/reflection-valueclasses-magic.scala
index a40b570774..c4a26e460a 100644
--- a/test/files/run/reflection-valueclasses-magic.scala
+++ b/test/files/run/reflection-valueclasses-magic.scala
@@ -3,6 +3,12 @@ import scala.reflect.runtime.universe.definitions._
import scala.reflect.runtime.{currentMirror => cm}
import scala.reflect.ClassTag
+package scala {
+ object ExceptionUtils {
+ def unwrapThrowable(ex: Throwable): Throwable = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ }
+}
+
object Test extends App {
def key(sym: Symbol) = {
sym match {
@@ -35,7 +41,7 @@ object Test extends App {
println(s"[${result.getClass}] =======> $result")
} catch {
case ex: Throwable =>
- val realex = scala.reflect.runtime.ReflectionUtils.unwrapThrowable(ex)
+ val realex = scala.ExceptionUtils.unwrapThrowable(ex)
println(realex.getClass + ": " + realex.getMessage)
}
val meth = tpe.declaration(newTermName(method).encodedName.toTermName)
diff --git a/test/files/run/t6344.check b/test/files/run/t6344.check
index 5ac04d0320..8d9adac849 100644
--- a/test/files/run/t6344.check
+++ b/test/files/run/t6344.check
@@ -101,14 +101,14 @@ public int ValueInt.x()
public int ValueInt.x()
public java.lang.Object ValueInt.x()
public java.lang.Object ValueInt.x()
-public static Gen ValueInt.extension$plus(int,Gen,Gen)
-public static Gen<java.lang.Object> ValueInt.extension$plus(int,Gen<java.lang.Object>,Gen<java.lang.Object>)
-public static boolean ValueInt.extension$equals(int,java.lang.Object)
-public static boolean ValueInt.extension$equals(int,java.lang.Object)
-public static int ValueInt.extension$hashCode(int)
-public static int ValueInt.extension$hashCode(int)
-public static int ValueInt.extension$iplus(int,int,int)
-public static int ValueInt.extension$iplus(int,int,int)
+public static Gen ValueInt.plus$extension(int,Gen,Gen)
+public static Gen<java.lang.Object> ValueInt.plus$extension(int,Gen<java.lang.Object>,Gen<java.lang.Object>)
+public static boolean ValueInt.equals$extension(int,java.lang.Object)
+public static boolean ValueInt.equals$extension(int,java.lang.Object)
+public static int ValueInt.hashCode$extension(int)
+public static int ValueInt.hashCode$extension(int)
+public static int ValueInt.iplus$extension(int,int,int)
+public static int ValueInt.iplus$extension(int,int,int)
RefInt
public Gen RefInt.plus(Gen,Gen)
diff --git a/test/files/run/t6440.check b/test/files/run/t6440.check
new file mode 100644
index 0000000000..b5684daee4
--- /dev/null
+++ b/test/files/run/t6440.check
@@ -0,0 +1 @@
+Stream((), ?)
diff --git a/test/files/run/t6440.scala b/test/files/run/t6440.scala
new file mode 100644
index 0000000000..2b690f31e1
--- /dev/null
+++ b/test/files/run/t6440.scala
@@ -0,0 +1,7 @@
+object Test {
+
+ def main(args: Array[String]): Unit = {
+ println(Stream.continually(()).filterNot(_ => false).take(2))
+ }
+
+}
diff --git a/test/scaladoc/resources/SI-6509.scala b/test/scaladoc/resources/SI-6509.scala
new file mode 100644
index 0000000000..540ba243bd
--- /dev/null
+++ b/test/scaladoc/resources/SI-6509.scala
@@ -0,0 +1,24 @@
+package test.scaladoc.template.owners
+
+trait X {
+ /** @template */
+ type Symbol >: Null <: SymbolApi
+
+ /** @template */
+ type TypeSymbol >: Null <: Symbol with TypeSymbolApi
+
+ /** @template */
+ type TermSymbol >: Null <: Symbol with TermSymbolApi
+
+ /** @template */
+ type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi
+
+ trait SymbolApi { this: Symbol => def x: Int}
+ trait TermSymbolApi extends SymbolApi { this: TermSymbol => def y: Int}
+ trait TypeSymbolApi extends SymbolApi { this: TypeSymbol => def z: Int}
+ trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol => def t: Int }
+}
+
+trait Y extends X
+trait Z extends Y
+trait T extends Z
diff --git a/test/scaladoc/resources/SI-6511.scala b/test/scaladoc/resources/SI-6511.scala
new file mode 100644
index 0000000000..1f153caeb0
--- /dev/null
+++ b/test/scaladoc/resources/SI-6511.scala
@@ -0,0 +1,24 @@
+package test.scaladoc.template.diagrams
+
+/** @contentDiagram hideNodes "*Api" */
+trait X {
+ /** @template */
+ type Symbol >: Null <: SymbolApi
+
+ /** @template */
+ type TypeSymbol >: Null <: Symbol with TypeSymbolApi
+
+ /** @template */
+ type TermSymbol >: Null <: Symbol with TermSymbolApi
+
+ /** @template */
+ type MethodSymbol >: Null <: TermSymbol with MethodSymbolApi
+
+ trait SymbolApi { this: Symbol => def x: Int}
+ trait TermSymbolApi extends SymbolApi { this: TermSymbol => def y: Int}
+ trait TypeSymbolApi extends SymbolApi { this: TypeSymbol => def z: Int}
+ trait MethodSymbolApi extends TermSymbolApi { this: MethodSymbol => def t: Int }
+}
+
+/** @contentDiagram hideNodes "*Api" */
+trait Y extends X
diff --git a/test/scaladoc/resources/links.scala b/test/scaladoc/resources/links.scala
index 12f03a10d8..ecac9c63cf 100644
--- a/test/scaladoc/resources/links.scala
+++ b/test/scaladoc/resources/links.scala
@@ -3,6 +3,9 @@
// SI-4497 "Links in ScalaDoc - Spec and implementation unsufficient"
// SI-4224 "Wiki-links should support method targets"
// SI-3695 "support non-fully-qualified type links in scaladoc comments"
+// SI-6487 "Scaladoc can't link to inner classes"
+// SI-6495 "Scaladoc won't pick up group name, priority and description from owner chain"
+// SI-6501 "Scaladoc won't link to a @template type T as a template but as a member"
package scala.test.scaladoc.links {
import language.higherKinds
class C
@@ -56,9 +59,18 @@ package scala.test.scaladoc.links {
* - [[localMethod object TEST -> localMethod]] (should use the current template to resolve link instead of inTpl, that's the package)
* - [[#localMethod object TEST -> localMethod]] (should exercise Java-style links to empty members)
* - [[ImOutside class ImOutside (check correct lookup in EmptyPackage)]]
+ * - [[ImOutside.Inner#foo class ImOutside#class Inner#method foo (check correct lookup in EmptyPackage)]]
+ * - [[ImOutside.T class ImOutside#type T (check correct linking to templates)]]
+ * - [[ImOutside.T#foo class ImOutside#type T#method foo (check correct interaction between @template and links)]]
*/
object TEST {
def localMethod = 3
}
}
-class ImOutside
+trait ImOutside {
+ /** @template */
+ type T <: Inner
+ class Inner {
+ def foo: Any
+ }
+}
diff --git a/test/scaladoc/run/SI-6509.check b/test/scaladoc/run/SI-6509.check
new file mode 100644
index 0000000000..3925a0d464
--- /dev/null
+++ b/test/scaladoc/run/SI-6509.check
@@ -0,0 +1 @@
+Done. \ No newline at end of file
diff --git a/test/scaladoc/run/SI-6509.scala b/test/scaladoc/run/SI-6509.scala
new file mode 100644
index 0000000000..3857949d14
--- /dev/null
+++ b/test/scaladoc/run/SI-6509.scala
@@ -0,0 +1,30 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile: String = "SI-6509.scala"
+
+ // 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 main = rootPackage._package("test")._package("scaladoc")._package("template")._package("owners")
+ val X = main._trait("X")
+ val Y = main._trait("Y")
+ val Z = main._trait("Z")
+ val T = main._trait("T")
+
+ def checkTemplateOwner(d: DocTemplateEntity) =
+ for (mbr <- List("Symbol", "TypeSymbol", "TermSymbol", "MethodSymbol")) {
+ val tpl = d._absTypeTpl(mbr).inTemplate
+ assert(tpl == X, tpl + " == X")
+ }
+
+ for (tpl <- List(X, Y, Z, T))
+ checkTemplateOwner(tpl)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/SI-6511.check b/test/scaladoc/run/SI-6511.check
new file mode 100644
index 0000000000..3925a0d464
--- /dev/null
+++ b/test/scaladoc/run/SI-6511.check
@@ -0,0 +1 @@
+Done. \ No newline at end of file
diff --git a/test/scaladoc/run/SI-6511.scala b/test/scaladoc/run/SI-6511.scala
new file mode 100644
index 0000000000..cc950a98d6
--- /dev/null
+++ b/test/scaladoc/run/SI-6511.scala
@@ -0,0 +1,22 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ override def resourceFile: String = "SI-6511.scala"
+
+ // no need for special settings
+ def scaladocSettings = "-diagrams"
+
+ 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 main = rootPackage._package("test")._package("scaladoc")._package("template")._package("diagrams")
+ val X = main._trait("X")
+ val Y = main._trait("Y")
+
+ testDiagram(X, X.contentDiagram, nodes = 4, edges = 3)
+ testDiagram(Y, Y.contentDiagram, nodes = 4, edges = 3)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/groups.scala b/test/scaladoc/run/groups.scala
index 05324c2ec9..c9e4a8679b 100644
--- a/test/scaladoc/run/groups.scala
+++ b/test/scaladoc/run/groups.scala
@@ -4,49 +4,54 @@ import scala.tools.partest.ScaladocModelTest
object Test extends ScaladocModelTest {
override def code = """
- package test.scaladoc.groups {
-
- /**
- * The trait A
- * @groupdesc A Group A is the group that contains functions starting with f
- * For example:
- * {{{
- * this is an example
- * }}}
- * @groupdesc B Group B is the group that contains functions starting with b
- * @groupname B Group B has a nice new name and a high priority
- * @groupprio B -10
- * @group Traits
- * @note This is a note
- */
- trait A {
- /** foo description
- * @group A */
- def foo = 1
-
- /** bar description
- * @group B */
- def bar = 2
- }
-
- /** The trait B
- * @group Traits
- * @groupdesc C Group C is introduced by B
- */
- trait B {
- /** baz descriptopn
- * @group C */
- def baz = 3
- }
-
- /** The class C which inherits from both A and B
- * @group Classes
- * @groupdesc B Look ma, I'm overriding group descriptions!!!
- * @groupname B And names
- */
- class C extends A with B {
- /** Oh noes, I lost my group -- or did I?!? */
- override def baz = 4
+ package test.scaladoc {
+
+ /** @groupname Z From owner chain */
+ package object `groups`
+
+ package groups {
+ /**
+ * The trait A
+ * @groupdesc A Group A is the group that contains functions starting with f
+ * For example:
+ * {{{
+ * this is an example
+ * }}}
+ * @groupdesc B Group B is the group that contains functions starting with b
+ * @groupname B Group B has a nice new name and a high priority
+ * @groupprio B -10
+ * @group Traits
+ * @note This is a note
+ */
+ trait A {
+ /** foo description
+ * @group A */
+ def foo = 1
+
+ /** bar description
+ * @group B */
+ def bar = 2
+ }
+
+ /** The trait B
+ * @group Traits
+ * @groupdesc C Group C is introduced by B
+ */
+ trait B {
+ /** baz descriptopn
+ * @group C */
+ def baz = 3
+ }
+
+ /** The class C which inherits from both A and B
+ * @group Classes
+ * @groupdesc B Look ma, I'm overriding group descriptions!!!
+ * @groupname B And names
+ */
+ class C extends A with B {
+ /** Oh noes, I lost my group -- or did I?!? */
+ override def baz = 4
+ }
}
}
"""
@@ -101,10 +106,12 @@ object Test extends ScaladocModelTest {
checkGroupDesc(A, "B", "Group B is the group that contains functions starting with b")
checkGroupName(A, "B", "Group B has a nice new name and a high priority")
checkGroupPrio(A, "B", -10)
+ checkGroupName(A, "Z", "From owner chain")
checkGroupDesc(B, "C", "Group C is introduced by B")
checkGroupName(B, "C", "C")
checkGroupPrio(B, "C", 0)
+ checkGroupName(B, "Z", "From owner chain")
checkGroupDesc(C, "A", "Group A is the group that contains functions starting with f")
checkGroupName(C, "A", "A")
@@ -115,5 +122,6 @@ object Test extends ScaladocModelTest {
checkGroupDesc(C, "C", "Group C is introduced by B")
checkGroupName(C, "C", "C")
checkGroupPrio(C, "C", 0)
+ checkGroupName(C, "Z", "From owner chain")
}
} \ No newline at end of file
diff --git a/test/scaladoc/run/links.scala b/test/scaladoc/run/links.scala
index ca8f3e2723..9fbf618558 100644
--- a/test/scaladoc/run/links.scala
+++ b/test/scaladoc/run/links.scala
@@ -5,6 +5,9 @@ import scala.tools.partest.ScaladocModelTest
// SI-4497 "Links in ScalaDoc - Spec and implementation unsufficient"
// SI-4224 "Wiki-links should support method targets"
// SI-3695 "support non-fully-qualified type links in scaladoc comments"
+// SI-6487 "Scaladoc can't link to inner classes"
+// SI-6495 "Scaladoc won't pick up group name, priority and description from owner chain"
+// SI-6501 "Scaladoc won't link to a @template type T as a template but as a member"
object Test extends ScaladocModelTest {
override def resourceFile = "links.scala"
@@ -22,7 +25,7 @@ object Test extends ScaladocModelTest {
val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember])
val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl])
- assert(memberLinks == 16, memberLinks + " == 16 (the member links in object TEST)")
- assert(templateLinks == 5, templateLinks + " == 5 (the template links in object TEST)")
+ assert(memberLinks == 18, memberLinks + " == 18 (the member links in object TEST)")
+ assert(templateLinks == 6, templateLinks + " == 6 (the template links in object TEST)")
}
}