Merge remote-tracking branch 'origin/2.10.x' into merge-2.10.x
* origin/2.10.x: (31 commits) Implicit vars should have non-implicit setters. Deprecate `scala.tools.nsc.Phases` because it's dead-code. scaladoc Template: remove duplicate code and several usages of Option.get. adds scala-reflect.jar to MIMA in ant Test showing the absence of a forward reference update mailmap Remove dead code from `Global`. Cleanup MemberLookup. Better explain ambiguous link targets. typedIdent no longer destroys attachments fixes incorrect handling of Annotated in lazy copier simplifies checkBounds Recurse into instantiations when stripping type vars. Extract base scaladoc functionality for the IDE. Expand pattern match position tests. SI-6288 Remedy ill-positioned extractor binding. SI-6288 Fix positioning of label jumps SI-6288 Position argument of unapply Fixes SI-6758: force LazyAnnnotationInfo for DefDef and TypeDef SI-6795 Simplify errors related to "abstract override" on type members SI-6795 Adds negative check for "abstract override" on types in traits ... Conflicts: .mailmap src/compiler/scala/tools/nsc/Global.scala src/compiler/scala/tools/nsc/ast/DocComments.scala src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala src/compiler/scala/tools/nsc/doc/html/page/Source.scala src/compiler/scala/tools/nsc/doc/html/page/Template.scala src/compiler/scala/tools/nsc/doc/model/LinkTo.scala src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala src/compiler/scala/tools/nsc/typechecker/Typers.scala src/reflect/scala/reflect/runtime/JavaMirrors.scala test/scaladoc/run/links.scala
This commit is contained in:
commit
106ca1b676
28
.mailmap
28
.mailmap
|
@ -1,7 +1,27 @@
|
|||
Aleksandar Prokopec <aleksandar@aleksandar-Latitude-E6500.(none)>
|
||||
Aleksandar Prokopec <aleksandar@htpc.(none)>
|
||||
Aleksandar Prokopec <aleksandar@htpc-axel22.(none)>
|
||||
Aleksandar Prokopec <aleksandar@lampmac14.epfl.ch>
|
||||
Aleksandar Prokopec <aleksandar.prokopec@epfl.ch>
|
||||
Aleksandar Prokopec <aleksandar@aleksandar-Latitude-E6500.(none)>
|
||||
Aleksandar Prokopec <aleksandar@htpc-axel22.(none)>
|
||||
Aleksandar Prokopec <aleksandar@htpc.(none)>
|
||||
Aleksandar Prokopec <aleksandar@lampmac14.epfl.ch>
|
||||
Antonio Cunei <antonio.cunei@typesafe.com>
|
||||
Caoyuan Deng <dcaoyuan@epfl.ch>
|
||||
Chris Hodapp <clhodapp1@gmail.com>
|
||||
Chris James <chrisJames@epfl.ch>
|
||||
Christopher Vogt <vogt@epfl.ch>
|
||||
Damien Obristi <damien.obrist@gmail.com>
|
||||
Daniel C. Sobral <dcs@dcs-132-CK-NF79.(none)>
|
||||
Daniel C. Sobral <dcs@dcs-132-CK-NF79.(none)>
|
||||
Ilya Sergei <ilyas@epfl.ch>
|
||||
Ingo Maier <ingoem@gmail.com>
|
||||
Kenji Yoshida <6b656e6a69@gmail.com>
|
||||
Luc Bourlier <skyluc@epfl.ch>
|
||||
Martin Odersky <odersky@gamil.com>
|
||||
Nada Amin <amin@epfl.ch>
|
||||
Nada Amin <nada.amin@epfl.ch>
|
||||
Natallie Baikevich <lu-a-jalla@ya.ru>
|
||||
Pavel Pavlov <pavel.e.pavlov@gmail.com>
|
||||
Pavel Pavlov <pavel.e.pavlov@gmail.com>
|
||||
Philipp Haller <philipp.haller@typesafe.com>
|
||||
Roland Kuhn <rk@rkuhn.info>
|
||||
Rüdiger Klaehn <rklaehn@gmail.com>
|
||||
Stéphane Micheloud <michelou@epfl.ch>
|
||||
|
|
15
build.xml
15
build.xml
|
@ -2503,6 +2503,7 @@ Binary compatibility testing
|
|||
</artifact:dependencies>
|
||||
<artifact:dependencies pathId="old.bc.classpath">
|
||||
<dependency groupId="org.scala-lang" artifactId="scala-library" version="2.10.0-RC2"/>
|
||||
<dependency groupId="org.scala-lang" artifactId="scala-reflect" version="2.10.0-RC2"/>
|
||||
</artifact:dependencies>
|
||||
</target>
|
||||
|
||||
|
@ -2518,7 +2519,19 @@ Binary compatibility testing
|
|||
<classpath>
|
||||
<path refid="mima.classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</java>
|
||||
<java
|
||||
fork="true"
|
||||
failonerror="true"
|
||||
classname="com.typesafe.tools.mima.cli.Main">
|
||||
<arg value="--prev"/>
|
||||
<arg value="${org.scala-lang:scala-reflect:jar}"/>
|
||||
<arg value="--curr"/>
|
||||
<arg value="${build-pack.dir}/lib/scala-reflect.jar"/>
|
||||
<classpath>
|
||||
<path refid="mima.classpath"/>
|
||||
</classpath>
|
||||
</java>
|
||||
</target>
|
||||
|
||||
|
||||
|
|
|
@ -54,10 +54,10 @@ abstract class Driver {
|
|||
doCompile(compiler)
|
||||
} catch {
|
||||
case ex: Throwable =>
|
||||
compiler.logThrowable(ex)
|
||||
compiler.reportThrowable(ex)
|
||||
ex match {
|
||||
case FatalError(msg) => reporter.error(null, "fatal error: " + msg)
|
||||
case _ => throw ex
|
||||
case FatalError(msg) => // signals that we should fail compilation.
|
||||
case _ => throw ex // unexpected error, tell the outside world.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -284,7 +284,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
|
|||
log(msg)
|
||||
}
|
||||
|
||||
def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
|
||||
@deprecated("Renamed to reportThrowable", "2.10.1")
|
||||
def logThrowable(t: Throwable): Unit = reportThrowable(t)
|
||||
def reportThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
|
||||
override def throwableAsString(t: Throwable) = util.stackTraceString(t)
|
||||
|
||||
// ------------ File interface -----------------------------------------
|
||||
|
@ -709,7 +711,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
|
|||
/* The set of phase objects that is the basis for the compiler phase chain */
|
||||
protected lazy val phasesSet = new mutable.HashSet[SubComponent]
|
||||
protected lazy val phasesDescMap = new mutable.HashMap[SubComponent, String] withDefaultValue ""
|
||||
private lazy val phaseTimings = new Phases.TimingModel // tracking phase stats
|
||||
|
||||
protected def addToPhasesSet(sub: SubComponent, descr: String) {
|
||||
phasesSet += sub
|
||||
|
@ -1038,37 +1039,41 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
|
|||
/** Don't want to introduce new errors trying to report errors,
|
||||
* so swallow exceptions.
|
||||
*/
|
||||
override def supplementErrorMessage(errorMessage: String): String = try {
|
||||
val tree = analyzer.lastTreeToTyper
|
||||
val sym = tree.symbol
|
||||
val tpe = tree.tpe
|
||||
val enclosing = lastSeenContext.enclClassOrMethod.tree
|
||||
override def supplementErrorMessage(errorMessage: String): String =
|
||||
if (currentRun.supplementedError) errorMessage
|
||||
else try {
|
||||
val tree = analyzer.lastTreeToTyper
|
||||
val sym = tree.symbol
|
||||
val tpe = tree.tpe
|
||||
val enclosing = lastSeenContext.enclClassOrMethod.tree
|
||||
|
||||
val info1 = formatExplain(
|
||||
"while compiling" -> currentSource.path,
|
||||
"during phase" -> ( if (globalPhase eq phase) phase else "global=%s, enteringPhase=%s".format(globalPhase, phase) ),
|
||||
"library version" -> scala.util.Properties.versionString,
|
||||
"compiler version" -> Properties.versionString,
|
||||
"reconstructed args" -> settings.recreateArgs.mkString(" ")
|
||||
)
|
||||
val info2 = formatExplain(
|
||||
"last tree to typer" -> tree.summaryString,
|
||||
"symbol" -> Option(sym).fold("null")(_.debugLocationString),
|
||||
"symbol definition" -> Option(sym).fold("null")(_.defString),
|
||||
"tpe" -> tpe,
|
||||
"symbol owners" -> ownerChainString(sym),
|
||||
"context owners" -> ownerChainString(lastSeenContext.owner)
|
||||
)
|
||||
val info3: List[String] = (
|
||||
( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
|
||||
++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
|
||||
++ ( if (!settings.debug.value) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
|
||||
++ ( List(errorMessage) )
|
||||
)
|
||||
val info1 = formatExplain(
|
||||
"while compiling" -> currentSource.path,
|
||||
"during phase" -> ( if (globalPhase eq phase) phase else "global=%s, enteringPhase=%s".format(globalPhase, phase) ),
|
||||
"library version" -> scala.util.Properties.versionString,
|
||||
"compiler version" -> Properties.versionString,
|
||||
"reconstructed args" -> settings.recreateArgs.mkString(" ")
|
||||
)
|
||||
val info2 = formatExplain(
|
||||
"last tree to typer" -> tree.summaryString,
|
||||
"symbol" -> Option(sym).fold("null")(_.debugLocationString),
|
||||
"symbol definition" -> Option(sym).fold("null")(_.defString),
|
||||
"tpe" -> tpe,
|
||||
"symbol owners" -> ownerChainString(sym),
|
||||
"context owners" -> ownerChainString(lastSeenContext.owner)
|
||||
)
|
||||
val info3: List[String] = (
|
||||
( List("== Enclosing template or block ==", nodePrinters.nodeToString(enclosing).trim) )
|
||||
++ ( if (tpe eq null) Nil else List("== Expanded type of tree ==", typeDeconstruct.show(tpe)) )
|
||||
++ ( if (!settings.debug.value) Nil else List("== Current unit body ==", nodePrinters.nodeToString(currentUnit.body)) )
|
||||
++ ( List(errorMessage) )
|
||||
)
|
||||
|
||||
("\n" + info1) :: info2 :: info3 mkString "\n\n"
|
||||
}
|
||||
catch { case x: Exception => errorMessage }
|
||||
currentRun.supplementedError = true
|
||||
|
||||
("\n" + info1) :: info2 :: info3 mkString "\n\n"
|
||||
}
|
||||
catch { case x: Exception => errorMessage }
|
||||
|
||||
/** The id of the currently active run
|
||||
*/
|
||||
|
@ -1122,6 +1127,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
|
|||
/** Has any macro expansion used a fallback during this run? */
|
||||
var seenMacroExpansionsFallingBack = false
|
||||
|
||||
/** Have we already supplemented the error message of a compiler crash? */
|
||||
private[nsc] final var supplementedError = false
|
||||
|
||||
private val unitbuf = new mutable.ListBuffer[CompilationUnit]
|
||||
val compiledFiles = new mutable.HashSet[String]
|
||||
|
||||
|
@ -1478,7 +1486,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
|
|||
|
||||
// progress update
|
||||
informTime(globalPhase.description, startTime)
|
||||
phaseTimings(globalPhase) = currentTime - startTime
|
||||
val shouldWriteIcode = (
|
||||
(settings.writeICode.isSetByUser && (settings.writeICode containsPhase globalPhase))
|
||||
|| (!settings.Xprint.doAllPhases && (settings.Xprint containsPhase globalPhase) && runIsAtOptimiz)
|
||||
|
|
|
@ -8,6 +8,7 @@ package scala.tools.nsc
|
|||
import scala.reflect.internal.util.TableDef
|
||||
import scala.language.postfixOps
|
||||
|
||||
@deprecated("Scheduled for removal as being a dead-code in the compiler.", "2.10.1")
|
||||
object Phases {
|
||||
val MaxPhases = 64
|
||||
|
||||
|
|
|
@ -16,11 +16,22 @@ import scala.collection.mutable
|
|||
*/
|
||||
trait DocComments { self: Global =>
|
||||
|
||||
var cookedDocComments = Map[Symbol, String]()
|
||||
val cookedDocComments = mutable.HashMap[Symbol, String]()
|
||||
|
||||
/** The raw doc comment map */
|
||||
val docComments = mutable.HashMap[Symbol, DocComment]()
|
||||
|
||||
def clearDocComments() {
|
||||
cookedDocComments.clear()
|
||||
docComments.clear()
|
||||
defs.clear()
|
||||
}
|
||||
|
||||
/** Associate comment with symbol `sym` at position `pos`. */
|
||||
def docComment(sym: Symbol, docStr: String, pos: Position = NoPosition) =
|
||||
if ((sym ne null) && (sym ne NoSymbol))
|
||||
docComments += (sym -> DocComment(docStr, pos))
|
||||
|
||||
/** The raw doc comment of symbol `sym`, as it appears in the source text, "" if missing.
|
||||
*/
|
||||
def rawDocComment(sym: Symbol): String =
|
||||
|
@ -47,25 +58,20 @@ trait DocComments { self: Global =>
|
|||
* If a symbol does not have a doc comment but some overridden version of it does,
|
||||
* the doc comment of the overridden version is copied instead.
|
||||
*/
|
||||
def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.get(sym) match {
|
||||
case Some(comment) =>
|
||||
comment
|
||||
case None =>
|
||||
val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
|
||||
def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.getOrElseUpdate(sym, {
|
||||
val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
|
||||
else DocComment(docStr).template
|
||||
val comment = superComment(sym) match {
|
||||
case None =>
|
||||
if (ownComment.indexOf("@inheritdoc") != -1)
|
||||
reporter.warning(sym.pos, "The comment for " + sym +
|
||||
" contains @inheritdoc, but no parent comment is available to inherit from.")
|
||||
ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
|
||||
case Some(sc) =>
|
||||
if (ownComment == "") sc
|
||||
else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
|
||||
}
|
||||
cookedDocComments += (sym -> comment)
|
||||
comment
|
||||
}
|
||||
superComment(sym) match {
|
||||
case None =>
|
||||
if (ownComment.indexOf("@inheritdoc") != -1)
|
||||
reporter.warning(sym.pos, "The comment for " + sym +
|
||||
" contains @inheritdoc, but no parent comment is available to inherit from.")
|
||||
ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
|
||||
case Some(sc) =>
|
||||
if (ownComment == "") sc
|
||||
else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
|
||||
}
|
||||
})
|
||||
|
||||
/** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
|
||||
*
|
||||
|
|
|
@ -308,7 +308,12 @@ trait BasicBlocks {
|
|||
else
|
||||
instrs.zipWithIndex collect {
|
||||
case (oldInstr, i) if map contains oldInstr =>
|
||||
code.touched |= replaceInstruction(i, map(oldInstr))
|
||||
// SI-6288 clone important here because `replaceInstruction` assigns
|
||||
// a position to `newInstr`. Without this, a single instruction can
|
||||
// be added twice, and the position last position assigned clobbers
|
||||
// all previous positions in other usages.
|
||||
val newInstr = map(oldInstr).clone()
|
||||
code.touched |= replaceInstruction(i, newInstr)
|
||||
}
|
||||
|
||||
////////////////////// Emit //////////////////////
|
||||
|
|
|
@ -78,7 +78,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
|
|||
with model.ModelFactoryImplicitSupport
|
||||
with model.ModelFactoryTypeSupport
|
||||
with model.diagram.DiagramFactory
|
||||
with model.comment.CommentFactory
|
||||
with model.CommentFactory
|
||||
with model.TreeFactory
|
||||
with model.MemberLookup {
|
||||
override def templateShouldDocument(sym: compiler.Symbol, inTpl: DocTemplateImpl) =
|
||||
|
|
94
src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala → src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala
Normal file → Executable file
94
src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala → src/compiler/scala/tools/nsc/doc/base/CommentFactoryBase.scala
Normal file → Executable file
|
@ -1,13 +1,13 @@
|
|||
/* NSC -- new Scala compiler
|
||||
* Copyright 2007-2013 LAMP/EPFL
|
||||
* Copyright 2007-2012 LAMP/EPFL
|
||||
* @author Manohar Jonnalagedda
|
||||
*/
|
||||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package model
|
||||
package comment
|
||||
package base
|
||||
|
||||
import base.comment._
|
||||
import scala.collection._
|
||||
import scala.util.matching.Regex
|
||||
import scala.reflect.internal.util.Position
|
||||
|
@ -21,73 +21,10 @@ import scala.language.postfixOps
|
|||
*
|
||||
* @author Manohar Jonnalagedda
|
||||
* @author Gilles Dubochet */
|
||||
trait CommentFactory { thisFactory: ModelFactory with CommentFactory with MemberLookup=>
|
||||
trait CommentFactoryBase { this: MemberLookupBase =>
|
||||
|
||||
val global: Global
|
||||
import global.{ reporter, definitions }
|
||||
|
||||
protected val commentCache = mutable.HashMap.empty[(global.Symbol, TemplateImpl), Comment]
|
||||
|
||||
def comment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = {
|
||||
val key = (sym, inTpl)
|
||||
if (commentCache isDefinedAt key)
|
||||
Some(commentCache(key))
|
||||
else {
|
||||
val c = defineComment(sym, currentTpl, inTpl)
|
||||
if (c isDefined) commentCache += (sym, inTpl) -> c.get
|
||||
c
|
||||
}
|
||||
}
|
||||
|
||||
/** A comment is usualy created by the parser, however for some special
|
||||
* cases we have to give some `inTpl` comments (parent class for example)
|
||||
* to the comment of the symbol.
|
||||
* This function manages some of those cases : Param accessor and Primary constructor */
|
||||
def defineComment(sym: global.Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = {
|
||||
|
||||
//param accessor case
|
||||
// We just need the @param argument, we put it into the body
|
||||
if( sym.isParamAccessor &&
|
||||
inTpl.comment.isDefined &&
|
||||
inTpl.comment.get.valueParams.isDefinedAt(sym.encodedName)) {
|
||||
val comContent = Some(inTpl.comment.get.valueParams(sym.encodedName))
|
||||
Some(createComment(body0 = comContent))
|
||||
}
|
||||
|
||||
// Primary constructor case
|
||||
// We need some content of the class definition : @constructor for the body,
|
||||
// @param and @deprecated, we can add some more if necessary
|
||||
else if (sym.isPrimaryConstructor && inTpl.comment.isDefined ) {
|
||||
val tplComment = inTpl.comment.get
|
||||
// If there is nothing to put into the comment there is no need to create it
|
||||
if(tplComment.constructor.isDefined ||
|
||||
tplComment.throws != Map.empty ||
|
||||
tplComment.valueParams != Map.empty ||
|
||||
tplComment.typeParams != Map.empty ||
|
||||
tplComment.deprecated.isDefined
|
||||
)
|
||||
Some(createComment( body0 = tplComment.constructor,
|
||||
throws0 = tplComment.throws,
|
||||
valueParams0 = tplComment.valueParams,
|
||||
typeParams0 = tplComment.typeParams,
|
||||
deprecated0 = tplComment.deprecated
|
||||
))
|
||||
else None
|
||||
}
|
||||
|
||||
//other comment cases
|
||||
// parse function will make the comment
|
||||
else {
|
||||
val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
|
||||
if (rawComment != "") {
|
||||
val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl)
|
||||
val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt)
|
||||
Some(c)
|
||||
}
|
||||
else None
|
||||
}
|
||||
|
||||
}
|
||||
import global.{ reporter, Symbol }
|
||||
|
||||
/* Creates comments with necessary arguments */
|
||||
def createComment (
|
||||
|
@ -251,9 +188,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
* @param comment The expanded comment string (including start and end markers) to be parsed.
|
||||
* @param src The raw comment source string.
|
||||
* @param pos The position of the comment in source. */
|
||||
protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = {
|
||||
assert(!inTplOpt.isDefined || inTplOpt.get != null)
|
||||
|
||||
protected def parseAtSymbol(comment: String, src: String, pos: Position, siteOpt: Option[Symbol] = None): Comment = {
|
||||
/** The cleaned raw comment as a list of lines. Cleaning removes comment
|
||||
* start and end markers, line start markers and unnecessary whitespace. */
|
||||
def clean(comment: String): List[String] = {
|
||||
|
@ -379,7 +314,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
val tagsWithoutDiagram = tags.filterNot(pair => stripTags.contains(pair._1))
|
||||
|
||||
val bodyTags: mutable.Map[TagKey, List[Body]] =
|
||||
mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWiki(_, pos, inTplOpt))} toSeq: _*)
|
||||
mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, siteOpt))} toSeq: _*)
|
||||
|
||||
def oneTag(key: SimpleTagKey): Option[Body] =
|
||||
((bodyTags remove key): @unchecked) match {
|
||||
|
@ -412,7 +347,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
}
|
||||
|
||||
val com = createComment (
|
||||
body0 = Some(parseWiki(docBody.toString, pos, inTplOpt)),
|
||||
body0 = Some(parseWikiAtSymbol(docBody.toString, pos, siteOpt)),
|
||||
authors0 = allTags(SimpleTagKey("author")),
|
||||
see0 = allTags(SimpleTagKey("see")),
|
||||
result0 = oneTag(SimpleTagKey("return")),
|
||||
|
@ -452,20 +387,14 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
* - Removed start-of-line star and one whitespace afterwards (if present).
|
||||
* - Removed all end-of-line whitespace.
|
||||
* - Only `endOfLine` is used to mark line endings. */
|
||||
def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = {
|
||||
assert(!inTplOpt.isDefined || inTplOpt.get != null)
|
||||
|
||||
new WikiParser(string, pos, inTplOpt).document()
|
||||
}
|
||||
def parseWikiAtSymbol(string: String, pos: Position, siteOpt: Option[Symbol]): Body = new WikiParser(string, pos, siteOpt).document()
|
||||
|
||||
/** TODO
|
||||
*
|
||||
* @author Ingo Maier
|
||||
* @author Manohar Jonnalagedda
|
||||
* @author Gilles Dubochet */
|
||||
protected final class WikiParser(val buffer: String, pos: Position, inTplOpt: Option[DocTemplateImpl]) extends CharReader(buffer) { wiki =>
|
||||
assert(!inTplOpt.isDefined || inTplOpt.get != null)
|
||||
|
||||
protected final class WikiParser(val buffer: String, pos: Position, siteOpt: Option[Symbol]) extends CharReader(buffer) { wiki =>
|
||||
var summaryParsed = false
|
||||
|
||||
def document(): Body = {
|
||||
|
@ -752,6 +681,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
val SchemeUri = """([a-z]+:.*)""".r
|
||||
jump("[[")
|
||||
val parens = 2 + repeatJump('[')
|
||||
val start = "[" * parens
|
||||
val stop = "]" * parens
|
||||
//println("link with " + parens + " matching parens")
|
||||
val target = readUntil { check(stop) || check(" ") }
|
||||
|
@ -767,7 +697,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member
|
|||
case (SchemeUri(uri), optTitle) =>
|
||||
Link(uri, optTitle getOrElse Text(uri))
|
||||
case (qualName, optTitle) =>
|
||||
makeEntityLink(optTitle getOrElse Text(target), pos, target, inTplOpt)
|
||||
makeEntityLink(optTitle getOrElse Text(target), pos, target, siteOpt)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/* NSC -- new Scala compiler
|
||||
* Copyright 2007-2013 LAMP/EPFL
|
||||
*/
|
||||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package base
|
||||
|
||||
import scala.collection._
|
||||
|
||||
sealed trait LinkTo
|
||||
final case class LinkToMember[Mbr, Tpl](mbr: Mbr, tpl: Tpl) extends LinkTo
|
||||
final case class LinkToTpl[Tpl](tpl: Tpl) extends LinkTo
|
||||
final case class LinkToExternal(name: String, url: String) extends LinkTo
|
||||
final case class Tooltip(name: String) extends LinkTo
|
|
@ -0,0 +1,229 @@
|
|||
package scala.tools.nsc
|
||||
package doc
|
||||
package base
|
||||
|
||||
import comment._
|
||||
|
||||
/** This trait extracts all required information for documentation from compilation units.
|
||||
* The base trait has been extracted to allow getting light-weight documentation
|
||||
* for a particular symbol in the IDE.*/
|
||||
trait MemberLookupBase {
|
||||
|
||||
val global: Global
|
||||
val settings: doc.Settings
|
||||
|
||||
import global._
|
||||
def internalLink(sym: Symbol, site: Symbol): Option[LinkTo]
|
||||
def chooseLink(links: List[LinkTo]): LinkTo
|
||||
def toString(link: LinkTo): String
|
||||
|
||||
import global._
|
||||
import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
|
||||
import rootMirror.{RootPackage, EmptyPackage}
|
||||
|
||||
private def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
|
||||
|
||||
def makeEntityLink(title: Inline, pos: Position, query: String, siteOpt: Option[Symbol]) =
|
||||
new EntityLink(title) { lazy val link = memberLookup(pos, query, siteOpt) }
|
||||
|
||||
private var showExplanation = true
|
||||
private def explanation: String =
|
||||
if (showExplanation) {
|
||||
showExplanation = false
|
||||
"""
|
||||
|Quick crash course on using Scaladoc links
|
||||
|==========================================
|
||||
|Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:
|
||||
| - [[scala.collection.immutable.List!.apply class List's apply method]] and
|
||||
| - [[scala.collection.immutable.List$.apply object List's apply method]]
|
||||
|Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:
|
||||
| - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]
|
||||
| - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]
|
||||
|Notes:
|
||||
| - you can use any number of matching square brackets to avoid interference with the signature
|
||||
| - you can use \\. to escape dots in prefixes (don't forget to use * at the end to match the signature!)
|
||||
| - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.""".stripMargin
|
||||
} else ""
|
||||
|
||||
def memberLookup(pos: Position, query: String, siteOpt: Option[Symbol]): LinkTo = {
|
||||
var members = breakMembers(query)
|
||||
|
||||
// (1) First look in the root package, as most of the links are qualified
|
||||
val fromRoot = lookupInRootPackage(pos, members)
|
||||
|
||||
// (2) Or recursively go into each containing template.
|
||||
val fromParents = siteOpt.fold(Stream.empty[Symbol]) { s =>
|
||||
Stream.iterate(s)(_.owner)
|
||||
}.takeWhile (!isRoot(_)).map {
|
||||
lookupInTemplate(pos, members, _)
|
||||
}
|
||||
|
||||
val syms = (fromRoot +: fromParents) find (!_.isEmpty) getOrElse Nil
|
||||
|
||||
val links = syms flatMap { case (sym, site) => internalLink(sym, site) } match {
|
||||
case Nil =>
|
||||
// (3) Look at external links
|
||||
syms.flatMap { case (sym, owner) =>
|
||||
// reconstruct the original link
|
||||
def linkName(sym: Symbol) = {
|
||||
def nameString(s: Symbol) = s.nameString + (if ((s.isModule || s.isModuleClass) && !s.isPackage) "$" else "")
|
||||
val packageSuffix = if (sym.isPackage) ".package" else ""
|
||||
|
||||
sym.ownerChain.reverse.filterNot(isRoot(_)).map(nameString(_)).mkString(".") + packageSuffix
|
||||
}
|
||||
|
||||
if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
|
||||
findExternalLink(sym, linkName(sym))
|
||||
else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage)
|
||||
findExternalLink(sym, linkName(owner) + "@" + externalSignature(sym))
|
||||
else
|
||||
None
|
||||
}
|
||||
case links => links
|
||||
}
|
||||
links match {
|
||||
case Nil =>
|
||||
if (!settings.docNoLinkWarnings.value)
|
||||
reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
|
||||
// (4) if we still haven't found anything, create a tooltip
|
||||
Tooltip(query)
|
||||
case List(l) => l
|
||||
case links =>
|
||||
val chosen = chooseLink(links)
|
||||
def linkToString(link: LinkTo) = {
|
||||
val chosenInfo =
|
||||
if (link == chosen) " [chosen]" else ""
|
||||
toString(link) + chosenInfo + "\n"
|
||||
}
|
||||
if (!settings.docNoLinkWarnings.value) {
|
||||
val allLinks = links.map(linkToString).mkString
|
||||
reporter.warning(pos,
|
||||
s"""The link target \"$query\" is ambiguous. Several members fit the target:
|
||||
|$allLinks
|
||||
|$explanation""".stripMargin)
|
||||
}
|
||||
chosen
|
||||
}
|
||||
}
|
||||
|
||||
private sealed trait SearchStrategy
|
||||
private case object BothTypeAndTerm extends SearchStrategy
|
||||
private case object OnlyType extends SearchStrategy
|
||||
private case object OnlyTerm extends SearchStrategy
|
||||
|
||||
private def lookupInRootPackage(pos: Position, members: List[String]) =
|
||||
lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
|
||||
|
||||
private def lookupInTemplate(pos: Position, members: List[String], container: Symbol): List[(Symbol, Symbol)] = {
|
||||
// Maintaining compatibility with previous links is a bit tricky here:
|
||||
// we have a preference for term names for all terms except for the last, where we prefer a class:
|
||||
// How to do this:
|
||||
// - at each step we do a DFS search with the prefered strategy
|
||||
// - if the search doesn't return any members, we backtrack on the last decision
|
||||
// * we look for terms with the last member's name
|
||||
// * we look for types with the same name, all the way up
|
||||
val result = members match {
|
||||
case Nil => Nil
|
||||
case mbrName::Nil =>
|
||||
var syms = lookupInTemplate(pos, mbrName, container, OnlyType) map ((_, container))
|
||||
if (syms.isEmpty)
|
||||
syms = lookupInTemplate(pos, mbrName, container, OnlyTerm) map ((_, container))
|
||||
syms
|
||||
|
||||
case tplName::rest =>
|
||||
def completeSearch(syms: List[Symbol]) =
|
||||
syms flatMap (lookupInTemplate(pos, rest, _))
|
||||
|
||||
completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match {
|
||||
case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType))
|
||||
case syms => syms
|
||||
}
|
||||
}
|
||||
//println("lookupInTemplate(" + members + ", " + container + ") => " + result)
|
||||
result
|
||||
}
|
||||
|
||||
private def lookupInTemplate(pos: Position, member: String, container: Symbol, strategy: SearchStrategy): List[Symbol] = {
|
||||
val name = member.stripSuffix("$").stripSuffix("!").stripSuffix("*")
|
||||
def signatureMatch(sym: Symbol): Boolean = externalSignature(sym).startsWith(name)
|
||||
|
||||
// We need to cleanup the bogus classes created by the .class file parser. For example, [[scala.Predef]] resolves
|
||||
// to (bogus) class scala.Predef loaded by the class loader -- which we need to eliminate by looking at the info
|
||||
// and removing NoType classes
|
||||
def cleanupBogusClasses(syms: List[Symbol]) = { syms.filter(_.info != NoType) }
|
||||
|
||||
def syms(name: Name) = container.info.nonPrivateMember(name.encodedName).alternatives
|
||||
def termSyms = cleanupBogusClasses(syms(newTermName(name)))
|
||||
def typeSyms = cleanupBogusClasses(syms(newTypeName(name)))
|
||||
|
||||
val result = if (member.endsWith("$"))
|
||||
termSyms
|
||||
else if (member.endsWith("!"))
|
||||
typeSyms
|
||||
else if (member.endsWith("*"))
|
||||
cleanupBogusClasses(container.info.nonPrivateDecls) filter signatureMatch
|
||||
else
|
||||
strategy match {
|
||||
case BothTypeAndTerm => termSyms ::: typeSyms
|
||||
case OnlyType => typeSyms
|
||||
case OnlyTerm => termSyms
|
||||
}
|
||||
|
||||
//println("lookupInTemplate(" + member + ", " + container + ") => " + result)
|
||||
result
|
||||
}
|
||||
|
||||
private def breakMembers(query: String): List[String] = {
|
||||
// Okay, how does this work? Well: you split on . but you don't want to split on \. => thus the ugly regex
|
||||
// query.split((?<=[^\\\\])\\.).map(_.replaceAll("\\."))
|
||||
// The same code, just faster:
|
||||
var members = List[String]()
|
||||
var index = 0
|
||||
var last_index = 0
|
||||
val length = query.length
|
||||
while (index < length) {
|
||||
if ((query.charAt(index) == '.' || query.charAt(index) == '#') &&
|
||||
((index == 0) || (query.charAt(index-1) != '\\'))) {
|
||||
|
||||
val member = query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$1")
|
||||
// we want to allow javadoc-style links [[#member]] -- which requires us to remove empty members from the first
|
||||
// elemnt in the list
|
||||
if ((member != "") || (!members.isEmpty))
|
||||
members ::= member
|
||||
last_index = index + 1
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
if (last_index < length)
|
||||
members ::= query.substring(last_index, length).replaceAll("\\\\\\.", ".")
|
||||
members.reverse
|
||||
}
|
||||
|
||||
|
||||
def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
|
||||
val sym1 =
|
||||
if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
|
||||
else if (sym.isPackage)
|
||||
/* Get package object which has associatedFile ne null */
|
||||
sym.info.member(newTermName("package"))
|
||||
else sym
|
||||
Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
|
||||
val path = src.path
|
||||
settings.extUrlMapping get path map { url =>
|
||||
LinkToExternal(name, url + "#" + name)
|
||||
}
|
||||
} orElse {
|
||||
// Deprecated option.
|
||||
settings.extUrlPackageMapping find {
|
||||
case (pkg, _) => name startsWith pkg
|
||||
} map {
|
||||
case (_, url) => LinkToExternal(name, url + "#" + name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def externalSignature(sym: Symbol) = {
|
||||
sym.info // force it, otherwise we see lazy types
|
||||
(sym.nameString + sym.signatureString).replaceAll("\\s", "")
|
||||
}
|
||||
}
|
2
src/compiler/scala/tools/nsc/doc/model/comment/Body.scala → src/compiler/scala/tools/nsc/doc/base/comment/Body.scala
Normal file → Executable file
2
src/compiler/scala/tools/nsc/doc/model/comment/Body.scala → src/compiler/scala/tools/nsc/doc/base/comment/Body.scala
Normal file → Executable file
|
@ -5,7 +5,7 @@
|
|||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package model
|
||||
package base
|
||||
package comment
|
||||
|
||||
import scala.collection._
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package model
|
||||
package base
|
||||
package comment
|
||||
|
||||
import scala.collection._
|
||||
|
@ -128,5 +128,4 @@ abstract class Comment {
|
|||
(authors map ("@author " + _.toString)).mkString("\n") +
|
||||
(result map ("@return " + _.toString)).mkString("\n") +
|
||||
(version map ("@version " + _.toString)).mkString
|
||||
|
||||
}
|
|
@ -7,8 +7,9 @@ package scala.tools.nsc
|
|||
package doc
|
||||
package html
|
||||
|
||||
import base._
|
||||
import base.comment._
|
||||
import model._
|
||||
import comment._
|
||||
|
||||
import scala.xml.NodeSeq
|
||||
import scala.xml.dtd.{DocType, PublicID}
|
||||
|
@ -126,12 +127,12 @@ abstract class HtmlPage extends Page { thisPage =>
|
|||
}
|
||||
|
||||
def linkToHtml(text: Inline, link: LinkTo, hasLinks: Boolean) = link match {
|
||||
case LinkToTpl(dtpl) =>
|
||||
case LinkToTpl(dtpl: TemplateEntity) =>
|
||||
if (hasLinks)
|
||||
<a href={ relativeLinkTo(dtpl) } class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</a>
|
||||
else
|
||||
<span class="extype" name={ dtpl.qualifiedName }>{ inlineToHtml(text) }</span>
|
||||
case LinkToMember(mbr, inTpl) =>
|
||||
case LinkToMember(mbr: MemberEntity, inTpl: TemplateEntity) =>
|
||||
if (hasLinks)
|
||||
<a href={ relativeLinkTo(inTpl) + "#" + mbr.signature } class="extmbr" name={ mbr.qualifiedName }>{ inlineToHtml(text) }</a>
|
||||
else
|
||||
|
@ -140,7 +141,7 @@ abstract class HtmlPage extends Page { thisPage =>
|
|||
<span class="extype" name={ tooltip }>{ inlineToHtml(text) }</span>
|
||||
case LinkToExternal(name, url) =>
|
||||
<a href={ url } class="extype" target="_top">{ inlineToHtml(text) }</a>
|
||||
case NoLink =>
|
||||
case _ =>
|
||||
inlineToHtml(text)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,11 @@ package doc
|
|||
package html
|
||||
package page
|
||||
|
||||
import base._
|
||||
import base.comment._
|
||||
|
||||
import model._
|
||||
import model.diagram._
|
||||
import scala.xml.{ NodeSeq, Text, UnprefixedAttribute }
|
||||
import scala.language.postfixOps
|
||||
|
||||
|
@ -328,12 +333,10 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
}
|
||||
}
|
||||
|
||||
def memberToShortCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = {
|
||||
if (mbr.comment.isEmpty)
|
||||
NodeSeq.Empty
|
||||
else
|
||||
<p class="shortcomment cmt">{ memberToUseCaseCommentHtml(mbr, isSelf) }{ inlineToHtml(mbr.comment.get.short) }</p>
|
||||
}
|
||||
def memberToShortCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
|
||||
mbr.comment.fold(NodeSeq.Empty) { comment =>
|
||||
<p class="shortcomment cmt">{ memberToUseCaseCommentHtml(mbr, isSelf) }{ inlineToHtml(comment.short) }</p>
|
||||
}
|
||||
|
||||
def memberToInlineCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
|
||||
<p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
|
||||
|
@ -354,37 +357,34 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
case _ => Nil
|
||||
}
|
||||
|
||||
def mbrCmt = mbr.comment.get
|
||||
|
||||
def paramCommentToHtml(prs: List[ParameterEntity]): NodeSeq = prs match {
|
||||
def paramCommentToHtml(prs: List[ParameterEntity], comment: Comment): NodeSeq = prs match {
|
||||
|
||||
case (tp: TypeParam) :: rest =>
|
||||
val paramEntry: NodeSeq = {
|
||||
<dt class="tparam">{ tp.name }</dt><dd class="cmt">{ bodyToHtml(mbrCmt.typeParams(tp.name)) }</dd>
|
||||
<dt class="tparam">{ tp.name }</dt><dd class="cmt">{ bodyToHtml(comment.typeParams(tp.name)) }</dd>
|
||||
}
|
||||
paramEntry ++ paramCommentToHtml(rest)
|
||||
paramEntry ++ paramCommentToHtml(rest, comment)
|
||||
|
||||
case (vp: ValueParam) :: rest =>
|
||||
val paramEntry: NodeSeq = {
|
||||
<dt class="param">{ vp.name }</dt><dd class="cmt">{ bodyToHtml(mbrCmt.valueParams(vp.name)) }</dd>
|
||||
<dt class="param">{ vp.name }</dt><dd class="cmt">{ bodyToHtml(comment.valueParams(vp.name)) }</dd>
|
||||
}
|
||||
paramEntry ++ paramCommentToHtml(rest)
|
||||
paramEntry ++ paramCommentToHtml(rest, comment)
|
||||
|
||||
case _ =>
|
||||
NodeSeq.Empty
|
||||
}
|
||||
|
||||
if (mbr.comment.isEmpty) NodeSeq.Empty
|
||||
else {
|
||||
mbr.comment.fold(NodeSeq.Empty) { comment =>
|
||||
val cmtedPrs = prs filter {
|
||||
case tp: TypeParam => mbrCmt.typeParams isDefinedAt tp.name
|
||||
case vp: ValueParam => mbrCmt.valueParams isDefinedAt vp.name
|
||||
case tp: TypeParam => comment.typeParams isDefinedAt tp.name
|
||||
case vp: ValueParam => comment.valueParams isDefinedAt vp.name
|
||||
}
|
||||
if (cmtedPrs.isEmpty && mbrCmt.result.isEmpty) NodeSeq.Empty
|
||||
if (cmtedPrs.isEmpty && comment.result.isEmpty) NodeSeq.Empty
|
||||
else {
|
||||
<dl class="paramcmts block">{
|
||||
paramCommentToHtml(cmtedPrs) ++ (
|
||||
mbrCmt.result match {
|
||||
paramCommentToHtml(cmtedPrs, comment) ++ (
|
||||
comment.result match {
|
||||
case None => NodeSeq.Empty
|
||||
case Some(cmt) =>
|
||||
<dt>returns</dt><dd class="cmt">{ bodyToHtml(cmt) }</dd>
|
||||
|
@ -463,7 +463,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
}
|
||||
|
||||
// --- start attributes block vals
|
||||
val attributes: Seq[scala.xml.Node] = {
|
||||
val attributes: NodeSeq = {
|
||||
val fvs: List[comment.Paragraph] = visibility(mbr).toList
|
||||
if (fvs.isEmpty || isReduced) NodeSeq.Empty
|
||||
else {
|
||||
|
@ -472,7 +472,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
}
|
||||
}
|
||||
|
||||
val definitionClasses: Seq[scala.xml.Node] = {
|
||||
val definitionClasses: NodeSeq = {
|
||||
val inDefTpls = mbr.inDefinitionTemplates
|
||||
if ((inDefTpls.tail.isEmpty && (inDefTpls.head == inTpl)) || isReduced) NodeSeq.Empty
|
||||
else {
|
||||
|
@ -481,7 +481,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
}
|
||||
}
|
||||
|
||||
val fullSignature: Seq[scala.xml.Node] = {
|
||||
val fullSignature: NodeSeq = {
|
||||
mbr match {
|
||||
case nte: NonTemplateMemberEntity if nte.isUseCase =>
|
||||
<div class="full-signature-block toggleContainer">
|
||||
|
@ -492,14 +492,14 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
}
|
||||
}
|
||||
|
||||
val selfType: Seq[scala.xml.Node] = mbr match {
|
||||
val selfType: NodeSeq = mbr match {
|
||||
case dtpl: DocTemplateEntity if (isSelf && !dtpl.selfType.isEmpty && !isReduced) =>
|
||||
<dt>Self Type</dt>
|
||||
<dd>{ typeToHtml(dtpl.selfType.get, hasLinks = true) }</dd>
|
||||
case _ => NodeSeq.Empty
|
||||
}
|
||||
|
||||
val annotations: Seq[scala.xml.Node] = {
|
||||
val annotations: NodeSeq = {
|
||||
// A list of annotations which don't show their arguments, e. g. because they are shown separately.
|
||||
val annotationsWithHiddenArguments = List("deprecated", "Deprecated", "migration")
|
||||
|
||||
|
@ -521,7 +521,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
val sourceLink: Seq[scala.xml.Node] = mbr match {
|
||||
val sourceLink: NodeSeq = mbr match {
|
||||
case dtpl: DocTemplateEntity if (isSelf && dtpl.sourceUrl.isDefined && dtpl.inSource.isDefined && !isReduced) =>
|
||||
val (absFile, _) = dtpl.inSource.get
|
||||
<dt>Source</dt>
|
||||
|
@ -529,83 +529,87 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp
|
|||
case _ => NodeSeq.Empty
|
||||
}
|
||||
|
||||
val deprecation: Seq[scala.xml.Node] =
|
||||
if (mbr.deprecation.isEmpty || isReduced) NodeSeq.Empty
|
||||
else {
|
||||
<dt>Deprecated</dt>
|
||||
<dd class="cmt">{ bodyToHtml(mbr.deprecation.get) }</dd>
|
||||
val deprecation: NodeSeq =
|
||||
mbr.deprecation match {
|
||||
case Some(deprecation) if !isReduced =>
|
||||
<dt>Deprecated</dt>
|
||||
<dd class="cmt">{ bodyToHtml(deprecation) }</dd>
|
||||
case _ => NodeSeq.Empty
|
||||
}
|
||||
|
||||
val migration: Seq[scala.xml.Node] =
|
||||
if(mbr.migration.isEmpty || isReduced) NodeSeq.Empty
|
||||
else {
|
||||
val migration: NodeSeq =
|
||||
mbr.migration match {
|
||||
case Some(migration) if !isReduced =>
|
||||
<dt>Migration</dt>
|
||||
<dd class="cmt">{ bodyToHtml(mbr.migration.get) }</dd>
|
||||
<dd class="cmt">{ bodyToHtml(migration) }</dd>
|
||||
case _ => NodeSeq.Empty
|
||||
}
|
||||
|
||||
val mainComment: Seq[scala.xml.Node] = mbr.comment match {
|
||||
val mainComment: NodeSeq = mbr.comment match {
|
||||
case Some(comment) if (! isReduced) =>
|
||||
def orEmpty[T](it: Iterable[T])(gen: =>NodeSeq): NodeSeq =
|
||||
if (it.isEmpty) NodeSeq.Empty else gen
|
||||
|
||||
val example =
|
||||
if(!comment.example.isEmpty)
|
||||
orEmpty(comment.example) {
|
||||
<div class="block">Example{ if (comment.example.length > 1) "s" else ""}:
|
||||
<ol>{
|
||||
val exampleXml: List[scala.xml.NodeSeq] =
|
||||
for(example <- comment.example ) yield
|
||||
<li class="cmt">{ bodyToHtml(example) }</li>
|
||||
exampleXml.reduceLeft(_ ++ Text(", ") ++ _)
|
||||
<ol>{
|
||||
val exampleXml: List[NodeSeq] = for (ex <- comment.example) yield
|
||||
<li class="cmt">{ bodyToHtml(ex) }</li>
|
||||
exampleXml.reduceLeft(_ ++ Text(", ") ++ _)
|
||||
}</ol>
|
||||
</div>
|
||||
else NodeSeq.Empty
|
||||
</div>
|
||||
}
|
||||
|
||||
val version: Seq[scala.xml.Node] =
|
||||
if(!comment.version.isEmpty) {
|
||||
val version: NodeSeq =
|
||||
orEmpty(comment.version) {
|
||||
<dt>Version</dt>
|
||||
<dd>{ for(body <- comment.version.toList) yield {bodyToHtml(body)} }</dd>
|
||||
} else NodeSeq.Empty
|
||||
<dd>{ for(body <- comment.version.toList) yield bodyToHtml(body) }</dd>
|
||||
}
|
||||
|
||||
val sinceVersion: Seq[scala.xml.Node] =
|
||||
if(!comment.since.isEmpty) {
|
||||
val sinceVersion: NodeSeq =
|
||||
orEmpty(comment.since) {
|
||||
<dt>Since</dt>
|
||||
<dd>{ for(body <- comment.since.toList) yield {bodyToHtml(body)} }</dd>
|
||||
} else NodeSeq.Empty
|
||||
<dd>{ for(body <- comment.since.toList) yield bodyToHtml(body) }</dd>
|
||||
}
|
||||
|
||||
val note: Seq[scala.xml.Node] =
|
||||
if(!comment.note.isEmpty) {
|
||||
val note: NodeSeq =
|
||||
orEmpty(comment.note) {
|
||||
<dt>Note</dt>
|
||||
<dd>{
|
||||
val noteXml: List[scala.xml.NodeSeq] = (for(note <- comment.note ) yield <span class="cmt">{bodyToHtml(note)}</span> )
|
||||
val noteXml: List[NodeSeq] = for(note <- comment.note ) yield <span class="cmt">{bodyToHtml(note)}</span>
|
||||
noteXml.reduceLeft(_ ++ Text(", ") ++ _)
|
||||
}</dd>
|
||||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
val seeAlso: Seq[scala.xml.Node] =
|
||||
if(!comment.see.isEmpty) {
|
||||
val seeAlso: NodeSeq =
|
||||
orEmpty(comment.see) {
|
||||
<dt>See also</dt>
|
||||
<dd>{
|
||||
val seeXml:List[scala.xml.NodeSeq]=(for(see <- comment.see ) yield <span class="cmt">{bodyToHtml(see)}</span> )
|
||||
val seeXml: List[NodeSeq] = for(see <- comment.see ) yield <span class="cmt">{bodyToHtml(see)}</span>
|
||||
seeXml.reduceLeft(_ ++ _)
|
||||
}</dd>
|
||||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
val exceptions: Seq[scala.xml.Node] =
|
||||
if(!comment.throws.isEmpty) {
|
||||
val exceptions: NodeSeq =
|
||||
orEmpty(comment.throws) {
|
||||
<dt>Exceptions thrown</dt>
|
||||
<dd>{
|
||||
val exceptionsXml: Iterable[scala.xml.NodeSeq] =
|
||||
for(exception <- comment.throws.toList.sortBy(_._1) ) yield
|
||||
<span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span>
|
||||
val exceptionsXml: List[NodeSeq] =
|
||||
for((name, body) <- comment.throws.toList.sortBy(_._1) ) yield
|
||||
<span class="cmt">{Text(name) ++ bodyToHtml(body)}</span>
|
||||
exceptionsXml.reduceLeft(_ ++ Text("") ++ _)
|
||||
}</dd>
|
||||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
val todo: Seq[scala.xml.Node] =
|
||||
if(!comment.todo.isEmpty) {
|
||||
val todo: NodeSeq =
|
||||
orEmpty(comment.todo) {
|
||||
<dt>To do</dt>
|
||||
<dd>{
|
||||
val todoXml: List[scala.xml.NodeSeq] = (for(todo <- comment.todo ) yield <span class="cmt">{bodyToHtml(todo)}</span> )
|
||||
val todoXml: List[NodeSeq] = (for(todo <- comment.todo ) yield <span class="cmt">{bodyToHtml(todo)}</span> )
|
||||
todoXml.reduceLeft(_ ++ Text(", ") ++ _)
|
||||
}</dd>
|
||||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
example ++ version ++ sinceVersion ++ exceptions ++ todo ++ note ++ seeAlso
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class DotDiagramGenerator(settings: doc.Settings) extends DiagramGenerator {
|
|||
def textTypeEntity(text: String) =
|
||||
new TypeEntity {
|
||||
val name = text
|
||||
def refEntity: SortedMap[Int, (LinkTo, Int)] = SortedMap()
|
||||
def refEntity: SortedMap[Int, (base.LinkTo, Int)] = SortedMap()
|
||||
}
|
||||
|
||||
// it seems dot chokes on node names over 8000 chars, so let's limit the size of the string
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/* NSC -- new Scala compiler
|
||||
* Copyright 2007-2013 LAMP/EPFL
|
||||
* @author Manohar Jonnalagedda
|
||||
*/
|
||||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package model
|
||||
|
||||
import base.comment._
|
||||
|
||||
import reporters.Reporter
|
||||
import scala.collection._
|
||||
import scala.reflect.internal.util.{NoPosition, Position}
|
||||
import scala.language.postfixOps
|
||||
|
||||
/** The comment parser transforms raw comment strings into `Comment` objects.
|
||||
* Call `parse` to run the parser. Note that the parser is stateless and
|
||||
* should only be built once for a given Scaladoc run.
|
||||
*
|
||||
* @param reporter The reporter on which user messages (error, warnings) should be printed.
|
||||
*
|
||||
* @author Manohar Jonnalagedda
|
||||
* @author Gilles Dubochet */
|
||||
trait CommentFactory extends base.CommentFactoryBase {
|
||||
thisFactory: ModelFactory with CommentFactory with MemberLookup =>
|
||||
|
||||
val global: Global
|
||||
import global.{ reporter, definitions, Symbol }
|
||||
|
||||
protected val commentCache = mutable.HashMap.empty[(Symbol, TemplateImpl), Comment]
|
||||
|
||||
def addCommentBody(sym: Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): Symbol = {
|
||||
commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None)
|
||||
sym
|
||||
}
|
||||
|
||||
def comment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = {
|
||||
val key = (sym, inTpl)
|
||||
if (commentCache isDefinedAt key)
|
||||
Some(commentCache(key))
|
||||
else {
|
||||
val c = defineComment(sym, currentTpl, inTpl)
|
||||
if (c isDefined) commentCache += (sym, inTpl) -> c.get
|
||||
c
|
||||
}
|
||||
}
|
||||
|
||||
/** A comment is usualy created by the parser, however for some special
|
||||
* cases we have to give some `inTpl` comments (parent class for example)
|
||||
* to the comment of the symbol.
|
||||
* This function manages some of those cases : Param accessor and Primary constructor */
|
||||
def defineComment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = {
|
||||
|
||||
//param accessor case
|
||||
// We just need the @param argument, we put it into the body
|
||||
if( sym.isParamAccessor &&
|
||||
inTpl.comment.isDefined &&
|
||||
inTpl.comment.get.valueParams.isDefinedAt(sym.encodedName)) {
|
||||
val comContent = Some(inTpl.comment.get.valueParams(sym.encodedName))
|
||||
Some(createComment(body0 = comContent))
|
||||
}
|
||||
|
||||
// Primary constructor case
|
||||
// We need some content of the class definition : @constructor for the body,
|
||||
// @param and @deprecated, we can add some more if necessary
|
||||
else if (sym.isPrimaryConstructor && inTpl.comment.isDefined ) {
|
||||
val tplComment = inTpl.comment.get
|
||||
// If there is nothing to put into the comment there is no need to create it
|
||||
if(tplComment.constructor.isDefined ||
|
||||
tplComment.throws != Map.empty ||
|
||||
tplComment.valueParams != Map.empty ||
|
||||
tplComment.typeParams != Map.empty ||
|
||||
tplComment.deprecated.isDefined
|
||||
)
|
||||
Some(createComment( body0 = tplComment.constructor,
|
||||
throws0 = tplComment.throws,
|
||||
valueParams0 = tplComment.valueParams,
|
||||
typeParams0 = tplComment.typeParams,
|
||||
deprecated0 = tplComment.deprecated
|
||||
))
|
||||
else None
|
||||
}
|
||||
|
||||
//other comment cases
|
||||
// parse function will make the comment
|
||||
else {
|
||||
val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
|
||||
if (rawComment != "") {
|
||||
val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl)
|
||||
val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt)
|
||||
Some(c)
|
||||
}
|
||||
else None
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = {
|
||||
assert(!inTplOpt.isDefined || inTplOpt.get != null)
|
||||
parseAtSymbol(comment, src, pos, inTplOpt map (_.sym))
|
||||
}
|
||||
|
||||
/** Parses a string containing wiki syntax into a `Comment` object.
|
||||
* Note that the string is assumed to be clean:
|
||||
* - Removed Scaladoc start and end markers.
|
||||
* - Removed start-of-line star and one whitespace afterwards (if present).
|
||||
* - Removed all end-of-line whitespace.
|
||||
* - Only `endOfLine` is used to mark line endings. */
|
||||
def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = {
|
||||
assert(!inTplOpt.isDefined || inTplOpt.get != null)
|
||||
parseWikiAtSymbol(string,pos, inTplOpt map (_.sym))
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ package doc
|
|||
package model
|
||||
|
||||
import scala.collection._
|
||||
import comment._
|
||||
import base.comment._
|
||||
import diagram._
|
||||
|
||||
/** An entity in a Scaladoc universe. Entities are declarations in the program and correspond to symbols in the
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/* NSC -- new Scala compiler
|
||||
* Copyright 2007-2013 LAMP/EPFL
|
||||
*/
|
||||
|
||||
package scala.tools.nsc
|
||||
package doc
|
||||
package model
|
||||
|
||||
abstract sealed class LinkTo
|
||||
final case class LinkToTpl(tpl: DocTemplateEntity) extends LinkTo
|
||||
final case class LinkToMember(mbr: MemberEntity, inTpl: DocTemplateEntity) extends LinkTo
|
||||
final case class Tooltip(name: String) extends LinkTo { def this(tpl: TemplateEntity) = this(tpl.qualifiedName) }
|
||||
final case class LinkToExternal(name: String, url: String) extends LinkTo
|
||||
case object NoLink extends LinkTo // you should use Tooltip if you have a name from the user, this is only in case all fails
|
||||
|
||||
object LinkToTpl {
|
||||
// this makes it easier to create links
|
||||
def apply(tpl: TemplateEntity) = tpl match {
|
||||
case dtpl: DocTemplateEntity => new LinkToTpl(dtpl)
|
||||
case ntpl: TemplateEntity => new Tooltip(ntpl.qualifiedName)
|
||||
}
|
||||
}
|
|
@ -2,225 +2,37 @@ package scala.tools.nsc
|
|||
package doc
|
||||
package model
|
||||
|
||||
import comment._
|
||||
import base._
|
||||
|
||||
/** This trait extracts all required information for documentation from compilation units */
|
||||
trait MemberLookup {
|
||||
trait MemberLookup extends base.MemberLookupBase {
|
||||
thisFactory: ModelFactory =>
|
||||
|
||||
import global._
|
||||
import rootMirror.RootPackage, rootMirror.EmptyPackage
|
||||
|
||||
def makeEntityLink(title: Inline, pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]) =
|
||||
new EntityLink(title) { lazy val link = memberLookup(pos, query, inTplOpt) }
|
||||
|
||||
def memberLookup(pos: Position, query: String, inTplOpt: Option[DocTemplateImpl]): LinkTo = {
|
||||
assert(modelFinished)
|
||||
|
||||
val members = breakMembers(query)
|
||||
//println(query + " => " + members)
|
||||
|
||||
// (1) First look in the root package, as most of the links are qualified
|
||||
val fromRoot = lookupInRootPackage(pos, members)
|
||||
|
||||
// (2) Or recursively go into each containing template.
|
||||
val fromParents = inTplOpt.fold(Stream.empty[DocTemplateImpl]) { tpl =>
|
||||
Stream.iterate(tpl)(_.inTemplate)
|
||||
}.takeWhile (tpl => tpl != null && !tpl.isRootPackage).map { tpl =>
|
||||
lookupInTemplate(pos, members, tpl.asInstanceOf[EntityImpl].sym)
|
||||
}
|
||||
|
||||
val syms = (fromRoot +: fromParents) find (!_.isEmpty) getOrElse Nil
|
||||
val linkTo = createLinks(syms) match {
|
||||
case Nil if !syms.isEmpty =>
|
||||
// (3) Look at external links
|
||||
syms.flatMap { case (sym, owner) =>
|
||||
|
||||
// reconstruct the original link
|
||||
def linkName(sym: Symbol) = {
|
||||
def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
|
||||
def nameString(s: Symbol) = s.nameString + (if ((s.isModule || s.isModuleClass) && !s.isPackage) "$" else "")
|
||||
val packageSuffix = if (sym.isPackage) ".package" else ""
|
||||
|
||||
sym.ownerChain.reverse.filterNot(isRoot(_)).map(nameString(_)).mkString(".") + packageSuffix
|
||||
}
|
||||
|
||||
if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
|
||||
findExternalLink(sym, linkName(sym))
|
||||
else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage)
|
||||
findExternalLink(sym, linkName(owner) + "@" + externalSignature(sym))
|
||||
else
|
||||
None
|
||||
override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
|
||||
findTemplateMaybe(sym) match {
|
||||
case Some(tpl) => Some(LinkToTpl(tpl))
|
||||
case None =>
|
||||
findTemplateMaybe(site) flatMap { inTpl =>
|
||||
inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl))
|
||||
}
|
||||
case links => links
|
||||
}
|
||||
|
||||
//println(createLinks(syms))
|
||||
//println(linkTo)
|
||||
|
||||
// (4) if we still haven't found anything, create a tooltip, if we found too many, report
|
||||
if (linkTo.isEmpty){
|
||||
if (!settings.docNoLinkWarnings.value)
|
||||
reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
|
||||
Tooltip(query)
|
||||
} else {
|
||||
if (linkTo.length > 1) {
|
||||
|
||||
val chosen =
|
||||
if (linkTo.exists(_.isInstanceOf[LinkToMember]))
|
||||
linkTo.collect({case lm: LinkToMember => lm}).min(Ordering[MemberEntity].on[LinkToMember](_.mbr))
|
||||
else
|
||||
linkTo.head
|
||||
|
||||
def linkToString(link: LinkTo) = {
|
||||
val description =
|
||||
link match {
|
||||
case lm@LinkToMember(mbr, inTpl) => " * " + mbr.kind + " \"" + mbr.signature + "\" in " + inTpl.kind + " " + inTpl.qualifiedName
|
||||
case lt@LinkToTpl(tpl) => " * " + tpl.kind + " \"" + tpl.qualifiedName + "\""
|
||||
case other => " * " + other.toString
|
||||
}
|
||||
val chosenInfo =
|
||||
if (link == chosen)
|
||||
" [chosen]"
|
||||
else
|
||||
""
|
||||
description + chosenInfo + "\n"
|
||||
}
|
||||
if (!settings.docNoLinkWarnings.value)
|
||||
reporter.warning(pos,
|
||||
"The link target \"" + query + "\" is ambiguous. Several (possibly overloaded) members fit the target:\n" +
|
||||
linkTo.map(link => linkToString(link)).mkString +
|
||||
(if (MemberLookup.showExplanation)
|
||||
"\n\n" +
|
||||
"Quick crash course on using Scaladoc links\n" +
|
||||
"==========================================\n" +
|
||||
"Disambiguating terms and types: Prefix terms with '$' and types with '!' in case both names are in use:\n" +
|
||||
" - [[scala.collection.immutable.List!.apply class List's apply method]] and\n" +
|
||||
" - [[scala.collection.immutable.List$.apply object List's apply method]]\n" +
|
||||
"Disambiguating overloaded members: If a term is overloaded, you can indicate the first part of its signature followed by *:\n" +
|
||||
" - [[[scala.collection.immutable.List$.fill[A](Int)(⇒A):List[A]* Fill with a single parameter]]]\n" +
|
||||
" - [[[scala.collection.immutable.List$.fill[A](Int,Int)(⇒A):List[List[A]]* Fill with a two parameters]]]\n" +
|
||||
"Notes: \n" +
|
||||
" - you can use any number of matching square brackets to avoid interference with the signature\n" +
|
||||
" - you can use \\. to escape dots in prefixes (don't forget to use * at the end to match the signature!)\n" +
|
||||
" - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.\n"
|
||||
else "")
|
||||
)
|
||||
chosen
|
||||
} else
|
||||
linkTo.head
|
||||
override def chooseLink(links: List[LinkTo]): LinkTo = {
|
||||
val mbrs = links.collect {
|
||||
case lm@LinkToMember(mbr: MemberEntity, _) => (mbr, lm)
|
||||
}
|
||||
}
|
||||
|
||||
private abstract class SearchStrategy
|
||||
private object BothTypeAndTerm extends SearchStrategy
|
||||
private object OnlyType extends SearchStrategy
|
||||
private object OnlyTerm extends SearchStrategy
|
||||
|
||||
private def lookupInRootPackage(pos: Position, members: List[String]) =
|
||||
lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage)
|
||||
|
||||
private def createLinks(syms: List[(Symbol, Symbol)]): List[LinkTo] =
|
||||
syms.flatMap { case (sym, owner) =>
|
||||
findTemplateMaybe(sym) match {
|
||||
case Some(tpl) => LinkToTpl(tpl) :: Nil
|
||||
case None =>
|
||||
findTemplateMaybe(owner) flatMap { inTpl =>
|
||||
inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def lookupInTemplate(pos: Position, members: List[String], container: Symbol): List[(Symbol, Symbol)] = {
|
||||
// Maintaining compatibility with previous links is a bit tricky here:
|
||||
// we have a preference for term names for all terms except for the last, where we prefer a class:
|
||||
// How to do this:
|
||||
// - at each step we do a DFS search with the prefered strategy
|
||||
// - if the search doesn't return any members, we backtrack on the last decision
|
||||
// * we look for terms with the last member's name
|
||||
// * we look for types with the same name, all the way up
|
||||
val result = members match {
|
||||
case Nil => Nil
|
||||
case mbrName::Nil =>
|
||||
var syms = lookupInTemplate(pos, mbrName, container, OnlyType) map ((_, container))
|
||||
if (syms.isEmpty)
|
||||
syms = lookupInTemplate(pos, mbrName, container, OnlyTerm) map ((_, container))
|
||||
syms
|
||||
|
||||
case tplName::rest =>
|
||||
def completeSearch(syms: List[Symbol]) =
|
||||
syms flatMap (lookupInTemplate(pos, rest, _))
|
||||
|
||||
completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match {
|
||||
case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType))
|
||||
case syms => syms
|
||||
}
|
||||
}
|
||||
//println("lookupInTemplate(" + members + ", " + container + ") => " + result)
|
||||
result
|
||||
}
|
||||
|
||||
private def lookupInTemplate(pos: Position, member: String, container: Symbol, strategy: SearchStrategy): List[Symbol] = {
|
||||
val name = member.stripSuffix("$").stripSuffix("!").stripSuffix("*")
|
||||
def signatureMatch(sym: Symbol): Boolean = externalSignature(sym).startsWith(name)
|
||||
|
||||
// We need to cleanup the bogus classes created by the .class file parser. For example, [[scala.Predef]] resolves
|
||||
// to (bogus) class scala.Predef loaded by the class loader -- which we need to eliminate by looking at the info
|
||||
// and removing NoType classes
|
||||
def cleanupBogusClasses(syms: List[Symbol]) = { syms.filter(_.info != NoType) }
|
||||
|
||||
def syms(name: Name) = container.info.nonPrivateMember(name.encodedName).alternatives
|
||||
def termSyms = cleanupBogusClasses(syms(newTermName(name)))
|
||||
def typeSyms = cleanupBogusClasses(syms(newTypeName(name)))
|
||||
|
||||
val result = if (member.endsWith("$"))
|
||||
termSyms
|
||||
else if (member.endsWith("!"))
|
||||
typeSyms
|
||||
else if (member.endsWith("*"))
|
||||
cleanupBogusClasses(container.info.nonPrivateDecls) filter signatureMatch
|
||||
if (mbrs.isEmpty)
|
||||
links.head
|
||||
else
|
||||
if (strategy == BothTypeAndTerm)
|
||||
termSyms ::: typeSyms
|
||||
else if (strategy == OnlyType)
|
||||
typeSyms
|
||||
else if (strategy == OnlyTerm)
|
||||
termSyms
|
||||
else
|
||||
Nil
|
||||
|
||||
//println("lookupInTemplate(" + member + ", " + container + ") => " + result)
|
||||
result
|
||||
mbrs.min(Ordering[MemberEntity].on[(MemberEntity, LinkTo)](_._1))._2
|
||||
}
|
||||
|
||||
private def breakMembers(query: String): List[String] = {
|
||||
// Okay, how does this work? Well: you split on . but you don't want to split on \. => thus the ugly regex
|
||||
// query.split((?<=[^\\\\])\\.).map(_.replaceAll("\\."))
|
||||
// The same code, just faster:
|
||||
var members = List[String]()
|
||||
var index = 0
|
||||
var last_index = 0
|
||||
val length = query.length
|
||||
while (index < length) {
|
||||
if ((query.charAt(index) == '.' || query.charAt(index) == '#') &&
|
||||
((index == 0) || (query.charAt(index-1) != '\\'))) {
|
||||
|
||||
val member = query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$1")
|
||||
// we want to allow javadoc-style links [[#member]] -- which requires us to remove empty members from the first
|
||||
// elemnt in the list
|
||||
if ((member != "") || (!members.isEmpty))
|
||||
members ::= member
|
||||
last_index = index + 1
|
||||
}
|
||||
index += 1
|
||||
}
|
||||
if (last_index < length)
|
||||
members ::= query.substring(last_index, length).replaceAll("\\\\\\.", ".")
|
||||
members.reverse
|
||||
override def toString(link: LinkTo) = link match {
|
||||
case LinkToTpl(tpl: EntityImpl) => tpl.sym.toString
|
||||
case LinkToMember(mbr: EntityImpl, inTpl: EntityImpl) =>
|
||||
mbr.sym.signatureString + " in " + inTpl.sym.toString
|
||||
case _ => link.toString
|
||||
}
|
||||
}
|
||||
|
||||
object MemberLookup {
|
||||
private[this] var _showExplanation = true
|
||||
def showExplanation: Boolean = if (_showExplanation) { _showExplanation = false; true } else false
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ package scala.tools.nsc
|
|||
package doc
|
||||
package model
|
||||
|
||||
import comment._
|
||||
|
||||
import base._
|
||||
import base.comment._
|
||||
import diagram._
|
||||
|
||||
import scala.collection._
|
||||
|
@ -1038,32 +1038,5 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
|
|||
(bSym.isAliasType || bSym.isAbstractType) &&
|
||||
{ val rawComment = global.expandedDocComment(bSym, inTpl.sym)
|
||||
rawComment.contains("@template") || rawComment.contains("@documentable") }
|
||||
|
||||
def findExternalLink(sym: Symbol, name: String): Option[LinkTo] = {
|
||||
val sym1 =
|
||||
if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
|
||||
else if (sym.isPackage)
|
||||
/* Get package object which has associatedFile ne null */
|
||||
sym.info.member(newTermName("package"))
|
||||
else sym
|
||||
Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
|
||||
val path = src.path
|
||||
settings.extUrlMapping get path map { url =>
|
||||
LinkToExternal(name, url + "#" + name)
|
||||
}
|
||||
} orElse {
|
||||
// Deprecated option.
|
||||
settings.extUrlPackageMapping find {
|
||||
case (pkg, _) => name startsWith pkg
|
||||
} map {
|
||||
case (_, url) => LinkToExternal(name, url + "#" + name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def externalSignature(sym: Symbol) = {
|
||||
sym.info // force it, otherwise we see lazy types
|
||||
(sym.nameString + sym.signatureString).replaceAll("\\s", "")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,6 @@ package scala.tools.nsc
|
|||
package doc
|
||||
package model
|
||||
|
||||
import comment._
|
||||
|
||||
import scala.collection._
|
||||
import symtab.Flags
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ package scala.tools.nsc
|
|||
package doc
|
||||
package model
|
||||
|
||||
import comment._
|
||||
|
||||
import base._
|
||||
import diagram._
|
||||
|
||||
import scala.collection._
|
||||
|
@ -17,7 +16,8 @@ trait ModelFactoryTypeSupport {
|
|||
with ModelFactoryTypeSupport
|
||||
with DiagramFactory
|
||||
with CommentFactory
|
||||
with TreeFactory =>
|
||||
with TreeFactory
|
||||
with MemberLookup =>
|
||||
|
||||
import global._
|
||||
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
|
||||
|
@ -82,7 +82,10 @@ trait ModelFactoryTypeSupport {
|
|||
findTemplateMaybe(bSym) match {
|
||||
case Some(bTpl) if owner == bSym.owner =>
|
||||
// (0) the owner's class is linked AND has a template - lovely
|
||||
LinkToTpl(bTpl)
|
||||
bTpl match {
|
||||
case dtpl: DocTemplateEntity => new LinkToTpl(dtpl)
|
||||
case _ => new Tooltip(bTpl.qualifiedName)
|
||||
}
|
||||
case _ =>
|
||||
val oTpl = findTemplateMaybe(owner)
|
||||
(oTpl, oTpl flatMap (findMember(bSym, _))) match {
|
||||
|
|
|
@ -20,7 +20,7 @@ abstract class TypeEntity {
|
|||
/** Maps which parts of this type's name reference entities. The map is indexed by the position of the first
|
||||
* character that reference some entity, and contains the entity and the position of the last referenced
|
||||
* character. The referenced character ranges do not to overlap or nest. The map is sorted by position. */
|
||||
def refEntity: SortedMap[Int, (LinkTo, Int)]
|
||||
def refEntity: SortedMap[Int, (base.LinkTo, Int)]
|
||||
|
||||
/** The human-readable representation of this type. */
|
||||
override def toString = name
|
||||
|
|
|
@ -3,7 +3,6 @@ package model
|
|||
package diagram
|
||||
|
||||
import model._
|
||||
import comment.CommentFactory
|
||||
import java.util.regex.{Pattern, Matcher}
|
||||
import scala.util.matching.Regex
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package model
|
|||
package diagram
|
||||
|
||||
import model._
|
||||
import comment.CommentFactory
|
||||
|
||||
// statistics
|
||||
import html.page.diagram.DiagramStats
|
||||
|
@ -24,7 +23,7 @@ trait DiagramFactory extends DiagramDirectiveParser {
|
|||
|
||||
// the following can used for hardcoding different relations into the diagram, for bootstrapping purposes
|
||||
def aggregationNode(text: String) =
|
||||
NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (LinkTo, Int)]() }, None)()
|
||||
NormalNode(new TypeEntity { val name = text; val refEntity = SortedMap[Int, (base.LinkTo, Int)]() }, None)()
|
||||
|
||||
/** Create the inheritance diagram for this template */
|
||||
def makeInheritanceDiagram(tpl: DocTemplateImpl): Option[Diagram] = {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* NSC -- new Scala compiler
|
||||
* Copyright 2007-2012 LAMP/EPFL
|
||||
* @author Eugene Vigdorchik
|
||||
*/
|
||||
|
||||
package scala.tools.nsc
|
||||
package interactive
|
||||
|
||||
import doc.base._
|
||||
import comment._
|
||||
import scala.xml.NodeSeq
|
||||
|
||||
sealed trait DocResult
|
||||
final case class UrlResult(url: String) extends DocResult
|
||||
final case class HtmlResult(comment: Comment) extends DocResult
|
||||
|
||||
abstract class Doc(val settings: doc.Settings) extends MemberLookupBase with CommentFactoryBase {
|
||||
|
||||
override val global: interactive.Global
|
||||
import global._
|
||||
|
||||
def chooseLink(links: List[LinkTo]): LinkTo
|
||||
|
||||
override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
|
||||
ask { () =>
|
||||
if (sym.isClass || sym.isModule)
|
||||
Some(LinkToTpl(sym))
|
||||
else
|
||||
if ((site.isClass || site.isModule) && site.info.members.toList.contains(sym))
|
||||
Some(LinkToMember(sym, site))
|
||||
else
|
||||
None
|
||||
}
|
||||
|
||||
override def toString(link: LinkTo) = ask { () =>
|
||||
link match {
|
||||
case LinkToMember(mbr: Symbol, site: Symbol) =>
|
||||
mbr.signatureString + " in " + site.toString
|
||||
case LinkToTpl(sym: Symbol) => sym.toString
|
||||
case _ => link.toString
|
||||
}
|
||||
}
|
||||
|
||||
def retrieve(sym: Symbol, site: Symbol): Option[DocResult] = {
|
||||
val sig = ask { () => externalSignature(sym) }
|
||||
findExternalLink(sym, sig) map { link => UrlResult(link.url) } orElse {
|
||||
val resp = new Response[Tree]
|
||||
// Ensure docComment tree is type-checked.
|
||||
val pos = ask { () => docCommentPos(sym) }
|
||||
askTypeAt(pos, resp)
|
||||
resp.get.left.toOption flatMap { _ =>
|
||||
ask { () =>
|
||||
val comment = parseAtSymbol(expandedDocComment(sym), rawDocComment(sym), pos, Some(site))
|
||||
Some(HtmlResult(comment))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,6 +70,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
|
|||
if (verboseIDE) println("[%s][%s]".format(projectName, msg))
|
||||
|
||||
override def forInteractive = true
|
||||
override def forScaladoc = settings.isScaladoc
|
||||
|
||||
/** A map of all loaded files to the rich compilation units that correspond to them.
|
||||
*/
|
||||
|
|
|
@ -7,6 +7,7 @@ import reporters.{Reporter => CompilerReporter}
|
|||
/** Trait encapsulating the creation of a presentation compiler's instance.*/
|
||||
private[tests] trait PresentationCompilerInstance extends TestSettings {
|
||||
protected val settings = new Settings
|
||||
protected def docSettings: doc.Settings = new doc.Settings(_ => ())
|
||||
protected val compilerReporter: CompilerReporter = new InteractiveReporter {
|
||||
override def compiler = PresentationCompilerInstance.this.compiler
|
||||
}
|
||||
|
|
|
@ -993,6 +993,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|
|||
case (overridden, env) =>
|
||||
val om = specializedOverload(clazz, overridden, env)
|
||||
clazz.info.decls.enter(om)
|
||||
foreachWithIndex(om.paramss) { (params, i) =>
|
||||
foreachWithIndex(params) { (param, j) =>
|
||||
param.name = overriding.paramss(i)(j).name // SI-6555 Retain the parameter names from the subclass.
|
||||
}
|
||||
}
|
||||
debuglog("specialized overload %s for %s in %s: %s".format(om, overriding.name.decode, pp(env), om.info))
|
||||
if (overriding.isAbstractOverride) om.setFlag(ABSOVERRIDE)
|
||||
typeEnv(om) = env
|
||||
|
|
|
@ -234,7 +234,10 @@ abstract class UnCurry extends InfoTransform
|
|||
|
||||
val applyMethodDef = {
|
||||
val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
|
||||
methSym setInfoAndEnter MethodType(methSym newSyntheticValueParams formals, restpe)
|
||||
val paramSyms = map2(formals, fun.vparams) {
|
||||
(tp, param) => methSym.newSyntheticValueParam(tp, param.name)
|
||||
}
|
||||
methSym setInfoAndEnter MethodType(paramSyms, restpe)
|
||||
|
||||
fun.vparams foreach (_.symbol.owner = methSym)
|
||||
fun.body changeOwner (fun.symbol -> methSym)
|
||||
|
|
|
@ -977,7 +977,7 @@ trait ContextErrors {
|
|||
object SymValidateErrors extends Enumeration {
|
||||
val ImplicitConstr, ImplicitNotTermOrClass, ImplicitAtToplevel,
|
||||
OverrideClass, SealedNonClass, AbstractNonClass,
|
||||
OverrideConstr, AbstractOverride, LazyAndEarlyInit,
|
||||
OverrideConstr, AbstractOverride, AbstractOverrideOnTypeMember, LazyAndEarlyInit,
|
||||
ByNameParameter, AbstractVar = Value
|
||||
}
|
||||
|
||||
|
@ -1076,6 +1076,9 @@ trait ContextErrors {
|
|||
case AbstractOverride =>
|
||||
"`abstract override' modifier only allowed for members of traits"
|
||||
|
||||
case AbstractOverrideOnTypeMember =>
|
||||
"`abstract override' modifier not allowed for type members"
|
||||
|
||||
case LazyAndEarlyInit =>
|
||||
"`lazy' definitions may not be initialized early"
|
||||
|
||||
|
|
|
@ -938,8 +938,8 @@ trait Implicits {
|
|||
* - for alias types and abstract types, we take instead the parts
|
||||
* - of their upper bounds.
|
||||
* @return For those parts that refer to classes with companion objects that
|
||||
* can be accessed with unambiguous stable prefixes, the implicits infos
|
||||
* which are members of these companion objects.
|
||||
* can be accessed with unambiguous stable prefixes that are not existentially
|
||||
* bound, the implicits infos which are members of these companion objects.
|
||||
*/
|
||||
private def companionImplicitMap(tp: Type): InfoMap = {
|
||||
|
||||
|
@ -955,7 +955,7 @@ trait Implicits {
|
|||
infoMap(sym) = List() // ambiguous prefix - ignore implicit members
|
||||
}
|
||||
case None =>
|
||||
if (pre.isStable) {
|
||||
if (pre.isStable && !pre.typeSymbol.isExistentiallyBound) {
|
||||
val companion = companionSymbolOf(sym, context)
|
||||
companion.moduleClass match {
|
||||
case mc: ModuleClassSymbol =>
|
||||
|
|
|
@ -1066,22 +1066,22 @@ trait Infer extends Checkable {
|
|||
*/
|
||||
/** error if arguments not within bounds. */
|
||||
def checkBounds(tree: Tree, pre: Type, owner: Symbol,
|
||||
tparams: List[Symbol], targs: List[Type], prefix: String): Boolean = {
|
||||
//@M validate variances & bounds of targs wrt variances & bounds of tparams
|
||||
//@M TODO: better place to check this?
|
||||
//@M TODO: errors for getters & setters are reported separately
|
||||
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
|
||||
|
||||
if(!kindErrors.isEmpty) {
|
||||
if (targs contains WildcardType) true
|
||||
else { KindBoundErrors(tree, prefix, targs, tparams, kindErrors); false }
|
||||
} else if (!isWithinBounds(pre, owner, tparams, targs)) {
|
||||
if (!(targs exists (_.isErroneous)) && !(tparams exists (_.isErroneous))) {
|
||||
NotWithinBounds(tree, prefix, targs, tparams, kindErrors)
|
||||
false
|
||||
} else true
|
||||
} else true
|
||||
}
|
||||
tparams: List[Symbol], targs: List[Type], prefix: String): Boolean =
|
||||
if ((targs exists (_.isErroneous)) || (tparams exists (_.isErroneous))) true
|
||||
else {
|
||||
//@M validate variances & bounds of targs wrt variances & bounds of tparams
|
||||
//@M TODO: better place to check this?
|
||||
//@M TODO: errors for getters & setters are reported separately
|
||||
val kindErrors = checkKindBounds(tparams, targs, pre, owner)
|
||||
kindErrors match {
|
||||
case Nil =>
|
||||
def notWithinBounds() = NotWithinBounds(tree, prefix, targs, tparams, Nil)
|
||||
isWithinBounds(pre, owner, tparams, targs) || {notWithinBounds(); false}
|
||||
case errors =>
|
||||
def kindBoundErrors() = KindBoundErrors(tree, prefix, targs, tparams, errors)
|
||||
(targs contains WildcardType) || {kindBoundErrors(); false}
|
||||
}
|
||||
}
|
||||
|
||||
def checkKindBounds(tparams: List[Symbol], targs: List[Type], pre: Type, owner: Symbol): List[String] = {
|
||||
checkKindBounds0(tparams, targs, pre, owner, true) map {
|
||||
|
|
|
@ -1462,8 +1462,12 @@ trait Namers extends MethodSynthesis {
|
|||
|
||||
if (sym.isConstructor && sym.isAnyOverride)
|
||||
fail(OverrideConstr)
|
||||
if (sym.isAbstractOverride && !sym.owner.isTrait)
|
||||
fail(AbstractOverride)
|
||||
if (sym.isAbstractOverride) {
|
||||
if (!sym.owner.isTrait)
|
||||
fail(AbstractOverride)
|
||||
if(sym.isType)
|
||||
fail(AbstractOverrideOnTypeMember)
|
||||
}
|
||||
if (sym.isLazy && sym.hasFlag(PRESUPER))
|
||||
fail(LazyAndEarlyInit)
|
||||
if (sym.info.typeSymbol == FunctionClass(0) && sym.isValueParameter && sym.owner.isCaseClass)
|
||||
|
|
|
@ -799,8 +799,8 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
|
|||
protected def spliceApply(binder: Symbol): Tree = {
|
||||
object splice extends Transformer {
|
||||
override def transform(t: Tree) = t match {
|
||||
case Apply(x, List(Ident(nme.SELECTOR_DUMMY))) =>
|
||||
treeCopy.Apply(t, x, List(CODE.REF(binder)))
|
||||
case Apply(x, List(i @ Ident(nme.SELECTOR_DUMMY))) =>
|
||||
treeCopy.Apply(t, x, List(CODE.REF(binder).setPos(i.pos)))
|
||||
case _ => super.transform(t)
|
||||
}
|
||||
}
|
||||
|
@ -877,7 +877,7 @@ trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL
|
|||
override def transform(tree: Tree): Tree = {
|
||||
def subst(from: List[Symbol], to: List[Tree]): Tree =
|
||||
if (from.isEmpty) tree
|
||||
else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate, tree.tpe)
|
||||
else if (tree.symbol == from.head) typedIfOrigTyped(to.head.shallowDuplicate.setPos(tree.pos), tree.tpe)
|
||||
else subst(from.tail, to.tail)
|
||||
|
||||
tree match {
|
||||
|
|
|
@ -1545,8 +1545,14 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans
|
|||
sym.name == nme.apply &&
|
||||
isClassTypeAccessible(tree)
|
||||
|
||||
if (doTransform)
|
||||
if (doTransform) {
|
||||
tree foreach {
|
||||
case i@Ident(_) =>
|
||||
enterReference(i.pos, i.symbol) // SI-5390 need to `enterReference` for `a` in `a.B()`
|
||||
case _ =>
|
||||
}
|
||||
toConstructor(tree.pos, tree.tpe)
|
||||
}
|
||||
else {
|
||||
ifNot
|
||||
tree
|
||||
|
|
|
@ -19,16 +19,16 @@ trait StdAttachments {
|
|||
* by `parentTypes`. This attachment coordinates `parentTypes` and `typedTemplate` and
|
||||
* allows them to complete the synthesis.
|
||||
*/
|
||||
case class SuperCallArgsAttachment(argss: List[List[Tree]])
|
||||
case class SuperArgsAttachment(argss: List[List[Tree]])
|
||||
|
||||
/** Convenience method for `SuperCallArgsAttachment`.
|
||||
/** Convenience method for `SuperArgsAttachment`.
|
||||
* Compared with `MacroRuntimeAttachment` this attachment has different a usage pattern,
|
||||
* so it really benefits from a dedicated extractor.
|
||||
*/
|
||||
def superCallArgs(tree: Tree): Option[List[List[Tree]]] =
|
||||
tree.attachments.get[SuperCallArgsAttachment] collect { case SuperCallArgsAttachment(argss) => argss }
|
||||
def superArgs(tree: Tree): Option[List[List[Tree]]] =
|
||||
tree.attachments.get[SuperArgsAttachment] collect { case SuperArgsAttachment(argss) => argss }
|
||||
|
||||
/** Determines whether the given tree has an associated SuperCallArgsAttachment.
|
||||
/** Determines whether the given tree has an associated SuperArgsAttachment.
|
||||
*/
|
||||
def hasSuperArgs(tree: Tree): Boolean = superCallArgs(tree).nonEmpty
|
||||
def hasSuperArgs(tree: Tree): Boolean = superArgs(tree).nonEmpty
|
||||
}
|
|
@ -48,6 +48,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
resetContexts()
|
||||
resetImplicits()
|
||||
transformed.clear()
|
||||
clearDocComments()
|
||||
}
|
||||
|
||||
object UnTyper extends Traverser {
|
||||
|
@ -1453,7 +1454,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
*
|
||||
* Returns a `TypeTree` representing a resolved parent type.
|
||||
* If the typechecked parent reference implies non-nullary and non-empty argument list,
|
||||
* this argument list is attached to the returned value in SuperCallArgsAttachment.
|
||||
* this argument list is attached to the returned value in SuperArgsAttachment.
|
||||
* The attachment is necessary for the subsequent typecheck to fixup a super constructor call
|
||||
* in the body of the primary constructor (see `typedTemplate` for details).
|
||||
*
|
||||
|
@ -1519,7 +1520,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
// this is the place where we tell the typer what argss should be used for the super call
|
||||
// if argss are nullary or empty, then (see the docs for `typedPrimaryConstrBody`)
|
||||
// the super call dummy is already good enough, so we don't need to do anything
|
||||
if (argssAreTrivial) supertpt else supertpt updateAttachment SuperCallArgsAttachment(argss)
|
||||
if (argssAreTrivial) supertpt else supertpt updateAttachment SuperArgsAttachment(argss)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1845,8 +1846,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
*/
|
||||
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
|
||||
val clazz = context.owner
|
||||
// complete lazy annotations
|
||||
clazz.annotations
|
||||
clazz.annotations.map(_.completeInfo)
|
||||
if (templ.symbol == NoSymbol)
|
||||
templ setSymbol clazz.newLocalDummy(templ.pos)
|
||||
val self1 = templ.self match {
|
||||
|
@ -1893,7 +1893,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
val primaryCtor = treeInfo.firstConstructor(body)
|
||||
val primaryCtor1 = primaryCtor match {
|
||||
case DefDef(_, _, _, _, _, Block(earlyVals :+ global.pendingSuperCall, unit)) =>
|
||||
val argss = superCallArgs(parents1.head) getOrElse Nil
|
||||
val argss = superArgs(parents1.head) getOrElse Nil
|
||||
val pos = wrappingPos(parents1.head.pos, argss.flatten)
|
||||
val superCall = atPos(pos)(PrimarySuperCall(argss))
|
||||
deriveDefDef(primaryCtor)(block => Block(earlyVals :+ superCall, unit) setPos pos) setPos pos
|
||||
|
@ -1936,8 +1936,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
val typer1 = constrTyperIf(sym.isParameter && sym.owner.isConstructor)
|
||||
val typedMods = typedModifiers(vdef.mods)
|
||||
|
||||
// complete lazy annotations
|
||||
sym.annotations
|
||||
sym.annotations.map(_.completeInfo)
|
||||
val tpt1 = checkNoEscaping.privates(sym, typer1.typedType(vdef.tpt))
|
||||
checkNonCyclic(vdef, tpt1)
|
||||
|
||||
|
@ -2165,8 +2164,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
val tparams1 = ddef.tparams mapConserve typedTypeDef
|
||||
val vparamss1 = ddef.vparamss mapConserve (_ mapConserve typedValDef)
|
||||
|
||||
// complete lazy annotations
|
||||
meth.annotations
|
||||
meth.annotations.map(_.completeInfo)
|
||||
|
||||
for (vparams1 <- vparamss1; vparam1 <- vparams1 dropRight 1)
|
||||
if (isRepeatedParamType(vparam1.symbol.tpe))
|
||||
|
@ -2241,8 +2239,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
reenterTypeParams(tdef.tparams)
|
||||
val tparams1 = tdef.tparams mapConserve typedTypeDef
|
||||
val typedMods = typedModifiers(tdef.mods)
|
||||
// complete lazy annotations
|
||||
tdef.symbol.annotations
|
||||
tdef.symbol.annotations.map(_.completeInfo)
|
||||
|
||||
// @specialized should not be pickled when compiling with -no-specialize
|
||||
if (settings.nospecialization.value && currentRun.compiles(tdef.symbol)) {
|
||||
|
@ -2707,6 +2704,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
def typedRefinement(templ: Template) {
|
||||
val stats = templ.body
|
||||
namer.enterSyms(stats)
|
||||
|
||||
// need to delay rest of typedRefinement to avoid cyclic reference errors
|
||||
unit.toCheck += { () =>
|
||||
val stats1 = typedStats(stats, NoSymbol)
|
||||
|
@ -4769,7 +4767,7 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
typedClassOf(tree, TypeTree(pt.typeArgs.head))
|
||||
else {
|
||||
val pre1 = if (sym.owner.isPackageClass) sym.owner.thisType else if (qual == EmptyTree) NoPrefix else qual.tpe
|
||||
val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name))
|
||||
val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(atPos(tree.pos.focusStart)(qual), name) setAttachments tree.attachments)
|
||||
val (tree2, pre2) = makeAccessible(tree1, sym, pre1, qual)
|
||||
// SI-5967 Important to replace param type A* with Seq[A] when seen from from a reference, to avoid
|
||||
// inference errors in pattern matching.
|
||||
|
@ -4791,14 +4789,20 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
def typedCompoundTypeTree(tree: CompoundTypeTree) = {
|
||||
val templ = tree.templ
|
||||
val parents1 = templ.parents mapConserve (typedType(_, mode))
|
||||
if (parents1 exists (_.isErrorTyped)) tree setType ErrorType
|
||||
|
||||
// This is also checked later in typedStats, but that is too late for SI-5361, so
|
||||
// we eagerly check this here.
|
||||
for (stat <- templ.body if !treeInfo.isDeclarationOrTypeDef(stat))
|
||||
OnlyDeclarationsError(stat)
|
||||
|
||||
if ((parents1 ++ templ.body) exists (_.isErrorTyped)) tree setType ErrorType
|
||||
else {
|
||||
val decls = newScope
|
||||
//Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
|
||||
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
|
||||
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ)
|
||||
templ updateAttachment CompoundTypeTreeOriginalAttachment(parents1, Nil) // stats are set elsewhere
|
||||
tree setType self
|
||||
tree setType (if (templ.exists(_.isErroneous)) ErrorType else self) // Being conservative to avoid SI-5361
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4861,16 +4865,14 @@ trait Typers extends Modes with Adaptations with Tags {
|
|||
def typedPackageDef(pdef: PackageDef) = {
|
||||
val pid1 = typedQualifier(pdef.pid).asInstanceOf[RefTree]
|
||||
assert(sym.moduleClass ne NoSymbol, sym)
|
||||
// complete lazy annotations
|
||||
sym.annotations
|
||||
val stats1 = newTyper(context.make(tree, sym.moduleClass, sym.info.decls))
|
||||
.typedStats(pdef.stats, NoSymbol)
|
||||
treeCopy.PackageDef(tree, pid1, stats1) setType NoType
|
||||
}
|
||||
|
||||
def typedDocDef(docdef: DocDef) = {
|
||||
val comment = docdef.comment
|
||||
if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) {
|
||||
val comment = docdef.comment
|
||||
docComments(sym) = comment
|
||||
comment.defineVariables(sym)
|
||||
val typer1 = newTyper(context.makeNewScope(tree, context.owner))
|
||||
|
|
|
@ -39,6 +39,10 @@ abstract class DirectTest extends App {
|
|||
// new compiler
|
||||
def newCompiler(args: String*): Global = {
|
||||
val settings = newSettings((CommandLineParser tokenize ("-d \"" + testOutput.path + "\" " + extraSettings)) ++ args.toList)
|
||||
newCompiler(settings)
|
||||
}
|
||||
|
||||
def newCompiler(settings: Settings): Global = {
|
||||
if (settings.Yrangepos.value) new Global(settings, reporter(settings)) with interactive.RangePositions
|
||||
else new Global(settings, reporter(settings))
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import scala.tools.nsc.util.CommandLineParser
|
|||
import scala.tools.nsc.doc.{Settings, DocFactory, Universe}
|
||||
import scala.tools.nsc.doc.model._
|
||||
import scala.tools.nsc.doc.model.diagram._
|
||||
import scala.tools.nsc.doc.model.comment._
|
||||
import scala.tools.nsc.doc.base.comment._
|
||||
import scala.tools.nsc.reporters.ConsoleReporter
|
||||
|
||||
/** A class for testing scaladoc model generation
|
||||
|
|
|
@ -200,6 +200,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
|
|||
override def toString = if (forced) forcedInfo.toString else "@<?>"
|
||||
|
||||
override def pos: Position = if (forced) forcedInfo.pos else NoPosition
|
||||
|
||||
override def completeInfo(): Unit = forcedInfo
|
||||
}
|
||||
|
||||
/** Typed information about an annotation. It can be attached to either
|
||||
|
@ -241,6 +243,9 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
|
|||
this
|
||||
}
|
||||
|
||||
// Forces LazyAnnotationInfo, no op otherwise
|
||||
def completeInfo(): Unit = ()
|
||||
|
||||
/** Annotations annotating annotations are confusing so I drew
|
||||
* an example. Given the following code:
|
||||
*
|
||||
|
|
|
@ -275,7 +275,7 @@ class Flags extends ModifierFlags {
|
|||
* Getters of immutable values also get STABLE.
|
||||
*/
|
||||
final val GetterFlags = ~(PRESUPER | MUTABLE)
|
||||
final val SetterFlags = ~(PRESUPER | MUTABLE | STABLE | CASEACCESSOR)
|
||||
final val SetterFlags = ~(PRESUPER | MUTABLE | STABLE | CASEACCESSOR | IMPLICIT)
|
||||
|
||||
/** When a symbol for a default getter is created, it inherits these
|
||||
* flags from the method with the default. Other flags applied at creation
|
||||
|
|
|
@ -10,6 +10,7 @@ trait StdAttachments {
|
|||
trait Attachable {
|
||||
protected var rawatt: scala.reflect.macros.Attachments { type Pos = Position } = NoPosition
|
||||
def attachments = rawatt
|
||||
def setAttachments(attachments: scala.reflect.macros.Attachments { type Pos = Position }): this.type = { rawatt = attachments; this }
|
||||
def updateAttachment[T: ClassTag](attachment: T): this.type = { rawatt = rawatt.update(attachment); this }
|
||||
def removeAttachment[T: ClassTag]: this.type = { rawatt = rawatt.remove[T]; this }
|
||||
|
||||
|
|
|
@ -824,7 +824,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
|
|||
}
|
||||
def Annotated(tree: Tree, annot: Tree, arg: Tree) = tree match {
|
||||
case t @ Annotated(annot0, arg0)
|
||||
if (annot0==annot) => t
|
||||
if (annot0==annot && arg0==arg) => t
|
||||
case _ => treeCopy.Annotated(tree, annot, arg)
|
||||
}
|
||||
def SingletonTypeTree(tree: Tree, ref: Tree) = tree match {
|
||||
|
|
|
@ -6321,11 +6321,11 @@ trait Types extends api.Types { self: SymbolTable =>
|
|||
case ExistentialType(qs, _) => qs
|
||||
case t => List()
|
||||
}
|
||||
def stripType(tp: Type) = tp match {
|
||||
def stripType(tp: Type): Type = tp match {
|
||||
case ExistentialType(_, res) =>
|
||||
res
|
||||
case tv@TypeVar(_, constr) =>
|
||||
if (tv.instValid) constr.inst
|
||||
if (tv.instValid) stripType(constr.inst)
|
||||
else if (tv.untouchable) tv
|
||||
else abort("trying to do lub/glb of typevar "+tp)
|
||||
case t => t
|
||||
|
|
|
@ -568,7 +568,7 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
|
|||
case None =>
|
||||
// class does not have a Scala signature; it's a Java class
|
||||
info("translating reflection info for Java " + jclazz) //debug
|
||||
initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz))
|
||||
initClassAndModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz))
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
|
@ -670,9 +670,9 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
|
|||
def enter(sym: Symbol, mods: Int) =
|
||||
(if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
|
||||
|
||||
for (jinner <- jclazz.getDeclaredClasses) {
|
||||
enter(jclassAsScala(jinner, clazz), jinner.getModifiers)
|
||||
}
|
||||
for (jinner <- jclazz.getDeclaredClasses)
|
||||
jclassAsScala(jinner) // inner class is entered as a side-effect
|
||||
// no need to call enter explicitly
|
||||
|
||||
pendingLoadActions = { () =>
|
||||
|
||||
|
@ -1016,14 +1016,15 @@ private[reflect] trait JavaMirrors extends internal.SymbolTable with api.JavaUni
|
|||
* @param jclazz The Java class
|
||||
* @return A Scala class symbol that wraps all reflection info of `jclazz`
|
||||
*/
|
||||
private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz))
|
||||
private def jclassAsScala(jclazz: jClass[_]): ClassSymbol =
|
||||
toScala(classCache, jclazz)(_ jclassAsScala1 _)
|
||||
|
||||
private def jclassAsScala(jclazz: jClass[_], owner: Symbol): ClassSymbol = {
|
||||
private def jclassAsScala1(jclazz: jClass[_]): ClassSymbol = {
|
||||
val owner = sOwner(jclazz)
|
||||
val name = scalaSimpleName(jclazz)
|
||||
val completer = (clazz: Symbol, module: Symbol) => new FromJavaClassCompleter(clazz, module, jclazz)
|
||||
val (clazz, _) = createClassModule(owner, name, completer)
|
||||
classCache enter (jclazz, clazz)
|
||||
clazz
|
||||
|
||||
initAndEnterClassAndModule(owner, name, completer)._1
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
|
|||
* @param name The simple name of the newly created class
|
||||
* @param completer The completer to be used to set the info of the class and the module
|
||||
*/
|
||||
protected def createClassModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = {
|
||||
protected def initAndEnterClassAndModule(owner: Symbol, name: TypeName, completer: (Symbol, Symbol) => LazyType) = {
|
||||
assert(!(name.toString endsWith "[]"), name)
|
||||
val clazz = owner.newClass(name)
|
||||
val module = owner.newModule(name.toTermName)
|
||||
|
@ -67,7 +67,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
|
|||
owner.info.decls enter clazz
|
||||
owner.info.decls enter module
|
||||
}
|
||||
initClassModule(clazz, module, completer(clazz, module))
|
||||
initClassAndModule(clazz, module, completer(clazz, module))
|
||||
(clazz, module)
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
|
|||
List(clazz, module, module.moduleClass) foreach (_ setInfo info)
|
||||
}
|
||||
|
||||
protected def initClassModule(clazz: Symbol, module: Symbol, completer: LazyType) =
|
||||
protected def initClassAndModule(clazz: Symbol, module: Symbol, completer: LazyType) =
|
||||
setAllInfos(clazz, module, completer)
|
||||
|
||||
/** The type completer for packages.
|
||||
|
@ -118,7 +118,7 @@ private[reflect] trait SymbolLoaders { self: SymbolTable =>
|
|||
val loadingMirror = currentMirror.mirrorDefining(cls)
|
||||
val (_, module) =
|
||||
if (loadingMirror eq currentMirror) {
|
||||
createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _))
|
||||
initAndEnterClassAndModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _))
|
||||
} else {
|
||||
val origOwner = loadingMirror.packageNameToScala(pkgClass.fullName)
|
||||
val clazz = origOwner.info decl name.toTypeName
|
||||
|
|
|
@ -1 +1 @@
|
|||
c5788c5e518eb267445c5a995fd98b2210f90a58 ?javac-artifacts.jar
|
||||
61931a51bb1a2d308d214b96d06e9a8808515dcf ?javac-artifacts.jar
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
t3222.scala:4: error: not found: type D
|
||||
def foo(@throws(classOf[D]) x: Int) {}
|
||||
^
|
||||
t3222.scala:1: error: not found: type B
|
||||
@throws(classOf[B])
|
||||
^
|
||||
two errors found
|
||||
t3222.scala:4: error: not found: type D
|
||||
def foo(@throws(classOf[D]) x: Int) {}
|
||||
^
|
||||
t3222.scala:3: error: not found: type C
|
||||
@throws(classOf[C])
|
||||
^
|
||||
t3222.scala:6: error: not found: type E
|
||||
@throws(classOf[E])
|
||||
^
|
||||
four errors found
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
t3614.scala:2: error: class type required but AnyRef{def a: Int} found
|
||||
t3614.scala:2: error: only declarations allowed here
|
||||
def v = new ({ def a=0 })
|
||||
^
|
||||
^
|
||||
one error found
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
t3995.scala:31: error: type mismatch;
|
||||
found : String("")
|
||||
required: _1.F0 where val _1: Lift
|
||||
(new Lift).apply("")
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,32 @@
|
|||
class Lift {
|
||||
def apply(f: F0) {}
|
||||
|
||||
class F0
|
||||
object F0 {
|
||||
implicit def f2f0(fn: String): F0 = ???
|
||||
}
|
||||
}
|
||||
|
||||
object Test {
|
||||
val l = new Lift
|
||||
val f = ""
|
||||
|
||||
"": l.F0 // okay
|
||||
|
||||
l.apply("") // okay
|
||||
|
||||
{
|
||||
val l = new Lift
|
||||
l.apply("") // okay
|
||||
}
|
||||
|
||||
// fails trying to mkAttributedQualifier for pre = Skolem(_1 <: Lift with Singletom).F0
|
||||
// should this even have shown up in `companionImplicitMap`? It says that:
|
||||
//
|
||||
// "@return For those parts that refer to classes with companion objects that
|
||||
// can be accessed with unambiguous stable prefixes, the implicits infos
|
||||
// which are members of these companion objects."
|
||||
//
|
||||
// The skolem is stable, but it doen't seem much good to us
|
||||
(new Lift).apply("")
|
||||
}
|
|
@ -1,11 +1,6 @@
|
|||
t4044.scala:9: error: AnyRef takes no type parameters, expected: one
|
||||
M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *)
|
||||
^
|
||||
t4044.scala:9: error: kinds of the type arguments (<error>) do not conform to the expected kinds of the type parameters (type N).
|
||||
<error>'s type parameters do not match type N's expected parameters:
|
||||
<none> has no type parameters, but type N has one
|
||||
M[AnyRef] // error, (AnyRef :: *) not kind-conformant to (N :: * -> * -> *)
|
||||
^
|
||||
t4044.scala:11: error: kinds of the type arguments (Test.A) do not conform to the expected kinds of the type parameters (type N).
|
||||
Test.A's type parameters do not match type N's expected parameters:
|
||||
type _ has no type parameters, but type O has one
|
||||
|
@ -16,4 +11,4 @@ Test.C's type parameters do not match type N's expected parameters:
|
|||
type _ has one type parameter, but type _ has none
|
||||
M[C] // error, (C :: (* -> * -> * -> *) not kind-conformant to (N :: * -> * -> *)
|
||||
^
|
||||
four errors found
|
||||
three errors found
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
t5361.scala:2: error: only declarations allowed here
|
||||
val x : { val self = this } = new { self => }
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,3 @@
|
|||
class A {
|
||||
val x : { val self = this } = new { self => }
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
t5390.scala:7: error: forward reference extends over definition of value b
|
||||
val b = a.B("")
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,10 @@
|
|||
class A {
|
||||
object B { def apply(s: String) = 0}
|
||||
}
|
||||
|
||||
object X {
|
||||
def foo {
|
||||
val b = a.B("")
|
||||
val a = new A
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
t5390b.scala:7: error: forward reference extends over definition of value b
|
||||
val b = a.B("")
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,10 @@
|
|||
class A {
|
||||
case class B(s: String)
|
||||
}
|
||||
|
||||
object X {
|
||||
def foo {
|
||||
val b = a.B("")
|
||||
val a = new A
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
t5390c.scala:7: error: forward reference extends over definition of value b
|
||||
val b = new a.B("")
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,10 @@
|
|||
class A {
|
||||
case class B(s: String)
|
||||
}
|
||||
|
||||
object X {
|
||||
def foo {
|
||||
val b = new a.B("")
|
||||
val a = new A
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
t5390d.scala:7: error: forward reference extends over definition of value b
|
||||
val b = a.B.toString
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,10 @@
|
|||
class A {
|
||||
case class B(s: String)
|
||||
}
|
||||
|
||||
object X {
|
||||
def foo {
|
||||
val b = a.B.toString
|
||||
val a = new A
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
t6260.scala:3: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
|
||||
t6260.scala:3: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun
|
||||
which overrides method apply: (v1: T1)R in trait Function1
|
||||
clashes with definition of the member itself;
|
||||
both have erased type (v1: Object)Object
|
||||
((bx: Box[X]) => new Box(f(bx.x)))(this)
|
||||
^
|
||||
t6260.scala:8: error: bridge generated for member method apply: (x$1: Box[X])Box[Y] in anonymous class $anonfun
|
||||
t6260.scala:8: error: bridge generated for member method apply: (bx: Box[X])Box[Y] in anonymous class $anonfun
|
||||
which overrides method apply: (v1: T1)R in trait Function1
|
||||
clashes with definition of the member itself;
|
||||
both have erased type (v1: Object)Object
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
t6558.scala:19: error: not found: type classs
|
||||
t6558.scala:4: error: not found: type classs
|
||||
@classs
|
||||
^
|
||||
t6558.scala:22: error: not found: type typeparam
|
||||
t6558.scala:7: error: not found: type typeparam
|
||||
class D[@typeparam T]
|
||||
^
|
||||
t6558.scala:25: error: not found: type valueparam
|
||||
t6558.scala:10: error: not found: type valueparam
|
||||
@valueparam x: Any
|
||||
^
|
||||
three errors found
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
class AnnotNotFound {
|
||||
def foo(a: Any) = ()
|
||||
|
||||
foo {
|
||||
// Not yet issued in the context of this file, see SI-6758
|
||||
// This error is issued in t6558b.scala
|
||||
@inargument
|
||||
def foo = 0
|
||||
foo
|
||||
}
|
||||
|
||||
() => {
|
||||
// As per above
|
||||
@infunction
|
||||
def foo = 0
|
||||
()
|
||||
}
|
||||
|
||||
@classs
|
||||
class C
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
t6758.scala:5: error: not found: type inargument
|
||||
@inargument
|
||||
^
|
||||
t6758.scala:11: error: not found: type infunction
|
||||
@infunction
|
||||
^
|
||||
t6758.scala:18: error: not found: type nested
|
||||
@nested
|
||||
^
|
||||
t6758.scala:25: error: not found: type param
|
||||
def func(@param x: Int): Int = 0
|
||||
^
|
||||
t6758.scala:28: error: not found: type typealias
|
||||
@typealias
|
||||
^
|
||||
t6758.scala:32: error: not found: type classs
|
||||
@classs
|
||||
^
|
||||
t6758.scala:35: error: not found: type module
|
||||
@module
|
||||
^
|
||||
t6758.scala:38: error: not found: type typeparam
|
||||
class D[@typeparam T]
|
||||
^
|
||||
t6758.scala:41: error: not found: type valueparam
|
||||
@valueparam x: Any
|
||||
^
|
||||
9 errors found
|
|
@ -0,0 +1,43 @@
|
|||
class AnnotNotFound {
|
||||
def foo(a: Any) = ()
|
||||
|
||||
foo {
|
||||
@inargument
|
||||
def foo = 0
|
||||
foo
|
||||
}
|
||||
|
||||
() => {
|
||||
@infunction
|
||||
def foo = 0
|
||||
()
|
||||
}
|
||||
|
||||
() => {
|
||||
val bar: Int = {
|
||||
@nested
|
||||
val bar2: Int = 2
|
||||
2
|
||||
}
|
||||
()
|
||||
}
|
||||
|
||||
def func(@param x: Int): Int = 0
|
||||
|
||||
abstract class A {
|
||||
@typealias
|
||||
type B = Int
|
||||
}
|
||||
|
||||
@classs
|
||||
class C
|
||||
|
||||
@module
|
||||
object D
|
||||
|
||||
class D[@typeparam T]
|
||||
|
||||
class E(
|
||||
@valueparam x: Any
|
||||
)
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
t6795.scala:3: error: `abstract override' modifier not allowed for type members
|
||||
trait T1 extends T { abstract override type U = Int }
|
||||
^
|
||||
one error found
|
|
@ -0,0 +1,3 @@
|
|||
trait T { type U }
|
||||
// "abstract override" shouldn't be allowed on types
|
||||
trait T1 extends T { abstract override type U = Int }
|
|
@ -0,0 +1 @@
|
|||
-language:experimental.macros
|
|
@ -0,0 +1,53 @@
|
|||
import scala.language.experimental.macros
|
||||
import scala.reflect.macros.Context
|
||||
import collection.mutable.ListBuffer
|
||||
import collection.mutable.Stack
|
||||
|
||||
object Macros {
|
||||
trait TypedFunction {
|
||||
def tree: scala.reflect.runtime.universe.Tree
|
||||
val typeIn: String
|
||||
val typeOut: String
|
||||
}
|
||||
|
||||
def tree[T,U](f:Function1[T,U]): Function1[T,U] = macro tree_impl[T,U]
|
||||
|
||||
def tree_impl[T:c.WeakTypeTag,U:c.WeakTypeTag](c: Context)
|
||||
(f:c.Expr[Function1[T,U]]): c.Expr[Function1[T,U]] = {
|
||||
import c.universe._
|
||||
val ttag = c.weakTypeTag[U]
|
||||
f match {
|
||||
case Expr(Function(List(ValDef(_,n,tp,_)),b)) =>
|
||||
// normalize argument name
|
||||
var b1 = new Transformer {
|
||||
override def transform(tree: Tree): Tree = tree match {
|
||||
case Ident(x) if (x==n) => Ident(newTermName("_arg"))
|
||||
case tt @ TypeTree() if tt.original != null => TypeTree(tt.tpe) setOriginal transform(tt.original)
|
||||
// without the fix to LazyTreeCopier.Annotated, we would need to uncomment the line below to make the macro work
|
||||
// that's because the pattern match in the input expression gets expanded into Typed(<x>, TypeTree(<Int @unchecked>))
|
||||
// with the original of the TypeTree being Annotated(<@unchecked>, Ident(<x>))
|
||||
// then the macro tries to replace all Ident(<x>) trees with Ident(<_arg>), recurs into the original of the TypeTree, changes it,
|
||||
// but leaves the <@unchecked> part untouched. this signals the misguided LazyTreeCopier that the Annotated tree hasn't been modified,
|
||||
// so the original tree should be copied over and returned => crash when later <x: @unchecked> re-emerges from TypeTree.original
|
||||
// case Annotated(annot, arg) => treeCopy.Annotated(tree, transform(annot).duplicate, transform(arg))
|
||||
case _ => super.transform(tree)
|
||||
}
|
||||
}.transform(b)
|
||||
|
||||
val reifiedTree = c.reifyTree(treeBuild.mkRuntimeUniverseRef, EmptyTree, b1)
|
||||
val reifiedExpr = c.Expr[scala.reflect.runtime.universe.Expr[T => U]](reifiedTree)
|
||||
val template =
|
||||
c.universe.reify(new (T => U) with TypedFunction {
|
||||
override def toString = c.literal(tp+" => "+ttag.tpe+" { "+b1.toString+" } ").splice // DEBUG
|
||||
def tree = reifiedExpr.splice.tree
|
||||
val typeIn = c.literal(tp.toString).splice
|
||||
val typeOut = c.literal(ttag.tpe.toString).splice
|
||||
def apply(_arg: T): U = c.Expr[U](b1)(ttag.asInstanceOf[c.WeakTypeTag[U]]).splice
|
||||
})
|
||||
val untyped = c.resetLocalAttrs(template.tree)
|
||||
|
||||
c.Expr[T => U](untyped)
|
||||
case _ => sys.error("Bad function type")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
object Test extends App {
|
||||
import Macros._
|
||||
// tree { (x:((Int,Int,Int),(Int,Int,Int))) => { val y=x; val ((r1,m1,c1),(r2,m2,c2))=y; (r1, m1 + m2 + r1 * c1 * c2, c2) } }
|
||||
tree { (x:((Int,Int,Int),(Int,Int,Int))) => { val ((r1,m1,c1),(r2,m2,c2))=x; (r1, m1 + m2 + r1 * c1 * c2, c2) } }
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-language:experimental.macros
|
|
@ -0,0 +1,17 @@
|
|||
import scala.reflect.macros.Context
|
||||
import language.experimental.macros
|
||||
|
||||
object MyAttachment
|
||||
|
||||
object Macros {
|
||||
def impl(c: Context) = {
|
||||
import c.universe._
|
||||
val ident = Ident(newTermName("bar")) updateAttachment MyAttachment
|
||||
assert(ident.attachments.get[MyAttachment.type].isDefined, ident.attachments)
|
||||
val typed = c.typeCheck(ident)
|
||||
assert(typed.attachments.get[MyAttachment.type].isDefined, typed.attachments)
|
||||
c.Expr[Int](typed)
|
||||
}
|
||||
|
||||
def foo = macro impl
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
object Test extends App {
|
||||
def bar = 2
|
||||
Macros.foo
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
-feature -Xfatal-warnings
|
|
@ -0,0 +1,3 @@
|
|||
object O {
|
||||
implicit var x: Int = 0
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
object Test {
|
||||
|
||||
implicit final class EqualOps[T](val x: T) extends AnyVal {
|
||||
def ===[T1, Ph >: T <: T1, Ph2 >: Ph <: T1](other: T1): Boolean = x == other
|
||||
def !!![T1, Ph2 >: Ph <: T1, Ph >: T <: T1](other: T1): Boolean = x == other
|
||||
}
|
||||
|
||||
class A
|
||||
class B extends A
|
||||
class C extends A
|
||||
|
||||
val a = new A
|
||||
val b = new B
|
||||
val c = new C
|
||||
|
||||
val x1 = a === b
|
||||
val x2 = b === a
|
||||
val x3 = b === c // error, infers Object{} for T1
|
||||
val x4 = b.===[A, B, B](c)
|
||||
|
||||
val x5 = b !!! c // always compiled due to the order of Ph2 and Ph
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
class A {
|
||||
case class B[A](s: String)
|
||||
}
|
||||
|
||||
object X {
|
||||
def foo {
|
||||
val a = new A
|
||||
val b = new a.B[c.type]("") // not a forward reference
|
||||
val c = ""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:
|
||||
@since:
|
||||
@todo:
|
||||
@note:
|
||||
@see:
|
||||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
|
||||
@since:
|
||||
@todo:
|
||||
@note:
|
||||
@see:
|
||||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
|
||||
@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
|
||||
@todo:
|
||||
@note:
|
||||
@see:
|
||||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
|
||||
@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
|
||||
@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
|
||||
@note:
|
||||
@see:
|
||||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
|
||||
@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
|
||||
@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
|
||||
@note:Body(List(Paragraph(Chain(List(Summary(Text(Don't inherit!)))))))
|
||||
@see:
|
||||
body:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(This is a test comment), Text(.)))), Text(
|
||||
))))))
|
||||
@example:Body(List(Paragraph(Chain(List(Summary(Monospace(Text("abb".permutations = Iterator(abb, bab, bba)))))))))
|
||||
@version:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(1), Text(.)))), Text(0, 09/07/2012))))))
|
||||
@since:Body(List(Paragraph(Chain(List(Summary(Chain(List(Text(2), Text(.)))), Text(10))))))
|
||||
@todo:Body(List(Paragraph(Chain(List(Summary(Text(this method is unsafe)))))))
|
||||
@note:Body(List(Paragraph(Chain(List(Summary(Text(Don't inherit!)))))))
|
||||
@see:Body(List(Paragraph(Chain(List(Summary(Text(some other method)))))))
|
|
@ -0,0 +1,71 @@
|
|||
import scala.tools.nsc.doc
|
||||
import scala.tools.nsc.doc.base.LinkTo
|
||||
import scala.tools.nsc.doc.base.comment._
|
||||
import scala.tools.nsc.interactive._
|
||||
import scala.tools.nsc.interactive.tests._
|
||||
import scala.tools.nsc.util._
|
||||
import scala.tools.nsc.io._
|
||||
|
||||
object Test extends InteractiveTest {
|
||||
override val settings: doc.Settings = docSettings
|
||||
|
||||
val tags = Seq(
|
||||
"@example `\"abb\".permutations = Iterator(abb, bab, bba)`",
|
||||
"@version 1.0, 09/07/2012",
|
||||
"@since 2.10",
|
||||
"@todo this method is unsafe",
|
||||
"@note Don't inherit!",
|
||||
"@see some other method"
|
||||
)
|
||||
|
||||
val comment = "This is a test comment."
|
||||
val caret = "<caret>"
|
||||
|
||||
def text(nTags: Int) =
|
||||
"""|/** %s
|
||||
|
|
||||
| * %s */
|
||||
|trait Commented {}
|
||||
|class User(c: %sCommented)""".stripMargin.format(comment, tags take nTags mkString "\n", caret)
|
||||
|
||||
override def main(args: Array[String]) {
|
||||
val documenter = new Doc(settings) {
|
||||
val global: compiler.type = compiler
|
||||
|
||||
def chooseLink(links: List[LinkTo]): LinkTo = links.head
|
||||
}
|
||||
for (i <- 1 to tags.length) {
|
||||
val markedText = text(i)
|
||||
val idx = markedText.indexOf(caret)
|
||||
val fileText = markedText.substring(0, idx) + markedText.substring(idx + caret.length)
|
||||
val source = sourceFiles(0)
|
||||
val batch = new BatchSourceFile(source.file, fileText.toCharArray)
|
||||
val reloadResponse = new Response[Unit]
|
||||
compiler.askReload(List(batch), reloadResponse)
|
||||
reloadResponse.get.left.toOption match {
|
||||
case None =>
|
||||
reporter.println("Couldn't reload")
|
||||
case Some(_) =>
|
||||
val treeResponse = new compiler.Response[compiler.Tree]
|
||||
val pos = compiler.rangePos(batch, idx, idx, idx)
|
||||
compiler.askTypeAt(pos, treeResponse)
|
||||
treeResponse.get.left.toOption match {
|
||||
case Some(tree) =>
|
||||
val sym = tree.tpe.typeSymbol
|
||||
documenter.retrieve(sym, sym.owner) match {
|
||||
case Some(HtmlResult(comment)) =>
|
||||
import comment._
|
||||
val tags: List[(String, Iterable[Body])] =
|
||||
List(("@example", example), ("@version", version), ("@since", since.toList), ("@todo", todo), ("@note", note), ("@see", see))
|
||||
val str = ("body:" + body + "\n") +
|
||||
tags.map{ case (name, bodies) => name + ":" + bodies.mkString("\n") }.mkString("\n")
|
||||
reporter.println(str)
|
||||
case Some(_) => reporter.println("Got unexpected result")
|
||||
case None => reporter.println("Got no result")
|
||||
}
|
||||
case None => reporter.println("Couldn't find a typedTree")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
object Test
|
|
@ -5,6 +5,7 @@ import java.util.Calendar
|
|||
import scala.tools.nsc.interactive.tests._
|
||||
import scala.tools.nsc.util._
|
||||
import scala.tools.nsc.io._
|
||||
import scala.tools.nsc.doc
|
||||
|
||||
/** This test runs the presentation compiler on the Scala compiler project itself and records memory consumption.
|
||||
*
|
||||
|
@ -24,6 +25,8 @@ import scala.tools.nsc.io._
|
|||
object Test extends InteractiveTest {
|
||||
final val mega = 1024 * 1024
|
||||
|
||||
override val settings: doc.Settings = docSettings
|
||||
|
||||
override def execute(): Unit = memoryConsumptionTest()
|
||||
|
||||
def batchSource(name: String) =
|
||||
|
@ -120,4 +123,4 @@ object Test extends InteractiveTest {
|
|||
r.totalMemory() - r.freeMemory()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
< 106 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 106 CALL_METHOD MyException.message (dynamic)
|
||||
502c504
|
||||
< blocks: [1,2,3,4,6,7,8,9,10]
|
||||
---
|
||||
|
@ -162,12 +162,12 @@
|
|||
< 176 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 176 CALL_METHOD MyException.message (dynamic)
|
||||
783c833,834
|
||||
< 177 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 177 CALL_METHOD MyException.message (dynamic)
|
||||
785c836,837
|
||||
< 177 THROW(MyException)
|
||||
---
|
||||
|
@ -194,12 +194,12 @@
|
|||
< 181 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 181 CALL_METHOD MyException.message (dynamic)
|
||||
822c878,879
|
||||
< 182 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 182 CALL_METHOD MyException.message (dynamic)
|
||||
824c881,882
|
||||
< 182 THROW(MyException)
|
||||
---
|
||||
|
@ -260,7 +260,7 @@
|
|||
< 127 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 127 CALL_METHOD MyException.message (dynamic)
|
||||
966c1042
|
||||
< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3
|
||||
---
|
||||
|
@ -299,7 +299,7 @@
|
|||
< 154 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 154 CALL_METHOD MyException.message (dynamic)
|
||||
1275c1354
|
||||
< blocks: [1,2,3,4,5,7]
|
||||
---
|
||||
|
@ -354,22 +354,23 @@
|
|||
< 213 LOAD_LOCAL(value message)
|
||||
---
|
||||
> ? LOAD_LOCAL(value x5)
|
||||
> ? CALL_METHOD MyException.message (dynamic)
|
||||
> 213 CALL_METHOD MyException.message (dynamic)
|
||||
1470c1560
|
||||
< blocks: [1,2,3,4,5,7]
|
||||
---
|
||||
> blocks: [1,2,3,4,5,7,8]
|
||||
1494c1584,1591
|
||||
1494c1584,1585
|
||||
< 58 THROW(IllegalArgumentException)
|
||||
---
|
||||
> ? STORE_LOCAL(value e)
|
||||
> ? JUMP 8
|
||||
>
|
||||
1495a1587,1592
|
||||
> 8:
|
||||
> 62 LOAD_MODULE object Predef
|
||||
> 62 CONSTANT("RuntimeException")
|
||||
> 62 CALL_METHOD scala.Predef.println (dynamic)
|
||||
> 62 JUMP 2
|
||||
>
|
||||
1543c1640
|
||||
< blocks: [1,2,3,4]
|
||||
---
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
[[syntax trees at end of patmat]] // newSource1
|
||||
[7]package [7]<empty> {
|
||||
[7]object Case3 extends [13][106]scala.AnyRef {
|
||||
[106]def <init>(): [13]Case3.type = [106]{
|
||||
[106][106][106]Case3.super.<init>();
|
||||
[13]()
|
||||
};
|
||||
[21]def unapply([29]z: [32]<type: [32]scala.Any>): [21]Option[Int] = [56][52][52]scala.Some.apply[[52]Int]([58]-1);
|
||||
[64]{
|
||||
[64]case <synthetic> val x1: [64]Any = [64]"";
|
||||
[64]case5()[84]{
|
||||
[84]<synthetic> val o7: [84]Option[Int] = [84][84]Case3.unapply([84]x1);
|
||||
[84]if ([84]o7.isEmpty.unary_!)
|
||||
[84]{
|
||||
[90]val nr: [90]Int = [90]o7.get;
|
||||
[97][97]matchEnd4([97]())
|
||||
}
|
||||
else
|
||||
[84][84]case6()
|
||||
};
|
||||
[64]case6(){
|
||||
[64][64]matchEnd4([64]throw [64][64][64]new [64]MatchError([64]x1))
|
||||
};
|
||||
[64]matchEnd4(x: [NoPosition]Unit){
|
||||
[64]x
|
||||
}
|
||||
}
|
||||
};
|
||||
[113]object Case4 extends [119][217]scala.AnyRef {
|
||||
[217]def <init>(): [119]Case4.type = [217]{
|
||||
[217][217][217]Case4.super.<init>();
|
||||
[119]()
|
||||
};
|
||||
[127]def unapplySeq([138]z: [141]<type: [141]scala.Any>): [127]Option[List[Int]] = [167]scala.None;
|
||||
[175]{
|
||||
[175]case <synthetic> val x1: [175]Any = [175]"";
|
||||
[175]case5()[195]{
|
||||
[195]<synthetic> val o7: [195]Option[List[Int]] = [195][195]Case4.unapplySeq([195]x1);
|
||||
[195]if ([195]o7.isEmpty.unary_!)
|
||||
[195]if ([195][195][195][195]o7.get.!=([195]null).&&([195][195][195][195]o7.get.lengthCompare([195]1).==([195]0)))
|
||||
[195]{
|
||||
[201]val nr: [201]Int = [201][201]o7.get.apply([201]0);
|
||||
[208][208]matchEnd4([208]())
|
||||
}
|
||||
else
|
||||
[195][195]case6()
|
||||
else
|
||||
[195][195]case6()
|
||||
};
|
||||
[175]case6(){
|
||||
[175][175]matchEnd4([175]throw [175][175][175]new [175]MatchError([175]x1))
|
||||
};
|
||||
[175]matchEnd4(x: [NoPosition]Unit){
|
||||
[175]x
|
||||
}
|
||||
}
|
||||
};
|
||||
[224]object Case5 extends [230][312]scala.AnyRef {
|
||||
[312]def <init>(): [230]Case5.type = [312]{
|
||||
[312][312][312]Case5.super.<init>();
|
||||
[230]()
|
||||
};
|
||||
[238]def unapply([246]z: [249]<type: [249]scala.Any>): [238]Boolean = [265]true;
|
||||
[273]{
|
||||
[273]case <synthetic> val x1: [273]Any = [273]"";
|
||||
[273]case5()[293]{
|
||||
[293]<synthetic> val o7: [293]Option[List[Int]] = [293][293]Case4.unapplySeq([293]x1);
|
||||
[293]if ([293]o7.isEmpty.unary_!)
|
||||
[293]if ([293][293][293][293]o7.get.!=([293]null).&&([293][293][293][293]o7.get.lengthCompare([293]0).==([293]0)))
|
||||
[304][304]matchEnd4([304]())
|
||||
else
|
||||
[293][293]case6()
|
||||
else
|
||||
[293][293]case6()
|
||||
};
|
||||
[273]case6(){
|
||||
[273][273]matchEnd4([273]throw [273][273][273]new [273]MatchError([273]x1))
|
||||
};
|
||||
[273]matchEnd4(x: [NoPosition]Unit){
|
||||
[273]x
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import scala.tools.partest._
|
||||
import java.io.{Console => _, _}
|
||||
|
||||
object Test extends DirectTest {
|
||||
|
||||
override def extraSettings: String = "-usejavacp -Xprint:patmat -Xprint-pos -d " + testOutput.path
|
||||
|
||||
override def code =
|
||||
"""
|
||||
|object Case3 {
|
||||
| def unapply(z: Any): Option[Int] = Some(-1)
|
||||
|
|
||||
| "" match {
|
||||
| case Case3(nr) => ()
|
||||
| }
|
||||
|}
|
||||
|object Case4 {
|
||||
| def unapplySeq(z: Any): Option[List[Int]] = None
|
||||
|
|
||||
| "" match {
|
||||
| case Case4(nr) => ()
|
||||
| }
|
||||
|}
|
||||
|object Case5 {
|
||||
| def unapply(z: Any): Boolean = true
|
||||
|
|
||||
| "" match {
|
||||
| case Case4() => ()
|
||||
| }
|
||||
|}
|
||||
|
|
||||
|""".stripMargin.trim
|
||||
|
||||
override def show(): Unit = {
|
||||
// Now: [84][84]Case3.unapply([84]x1);
|
||||
// Was: [84][84]Case3.unapply([64]x1);
|
||||
Console.withErr(System.out) {
|
||||
compile()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
object Case3 extends Object {
|
||||
// fields:
|
||||
|
||||
// methods
|
||||
def unapply(z: Object (REF(class Object))): Option {
|
||||
locals: value z
|
||||
startBlock: 1
|
||||
blocks: [1]
|
||||
|
||||
1:
|
||||
2 NEW REF(class Some)
|
||||
2 DUP(REF(class Some))
|
||||
2 CONSTANT(-1)
|
||||
2 BOX INT
|
||||
2 CALL_METHOD scala.Some.<init> (static-instance)
|
||||
2 RETURN(REF(class Option))
|
||||
|
||||
}
|
||||
Exception handlers:
|
||||
|
||||
def main(args: Array[String] (ARRAY[REF(class String)])): Unit {
|
||||
locals: value args, value x1, value x2, value x
|
||||
startBlock: 1
|
||||
blocks: [1,2,3,6,7]
|
||||
|
||||
1:
|
||||
4 CONSTANT("")
|
||||
4 STORE_LOCAL(value x1)
|
||||
4 SCOPE_ENTER value x1
|
||||
4 JUMP 2
|
||||
|
||||
2:
|
||||
5 LOAD_LOCAL(value x1)
|
||||
5 IS_INSTANCE REF(class String)
|
||||
5 CZJUMP (BOOL)NE ? 3 : 6
|
||||
|
||||
3:
|
||||
5 LOAD_LOCAL(value x1)
|
||||
5 CHECK_CAST REF(class String)
|
||||
5 STORE_LOCAL(value x2)
|
||||
5 SCOPE_ENTER value x2
|
||||
6 LOAD_MODULE object Predef
|
||||
6 CONSTANT("case 0")
|
||||
6 CALL_METHOD scala.Predef.println (dynamic)
|
||||
6 LOAD_FIELD scala.runtime.BoxedUnit.UNIT
|
||||
6 STORE_LOCAL(value x)
|
||||
6 JUMP 7
|
||||
|
||||
6:
|
||||
8 LOAD_MODULE object Predef
|
||||
8 CONSTANT("default")
|
||||
8 CALL_METHOD scala.Predef.println (dynamic)
|
||||
8 LOAD_FIELD scala.runtime.BoxedUnit.UNIT
|
||||
8 STORE_LOCAL(value x)
|
||||
8 JUMP 7
|
||||
|
||||
7:
|
||||
10 LOAD_MODULE object Predef
|
||||
10 CONSTANT("done")
|
||||
10 CALL_METHOD scala.Predef.println (dynamic)
|
||||
10 RETURN(UNIT)
|
||||
|
||||
}
|
||||
Exception handlers:
|
||||
|
||||
def <init>(): Case3.type {
|
||||
locals:
|
||||
startBlock: 1
|
||||
blocks: [1]
|
||||
|
||||
1:
|
||||
12 THIS(Case3)
|
||||
12 CALL_METHOD java.lang.Object.<init> (super())
|
||||
12 RETURN(UNIT)
|
||||
|
||||
}
|
||||
Exception handlers:
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import scala.tools.partest.IcodeTest
|
||||
|
||||
object Test extends IcodeTest {
|
||||
override def code =
|
||||
"""object Case3 { // 01
|
||||
| def unapply(z: Any): Option[Int] = Some(-1) // 02
|
||||
| def main(args: Array[String]) { // 03
|
||||
| ("": Any) match { // 04
|
||||
| case x : String => // 05 Read: <linenumber> JUMP <target basic block id>
|
||||
| println("case 0") // 06 expecting "6 JUMP 7", was "8 JUMP 7"
|
||||
| case _ => // 07
|
||||
| println("default") // 08 expecting "8 JUMP 7"
|
||||
| } // 09
|
||||
| println("done") // 10
|
||||
| }
|
||||
|}""".stripMargin
|
||||
|
||||
override def show() {
|
||||
val lines1 = collectIcode("")
|
||||
println(lines1 mkString "\n")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
false
|
||||
List(JavaAnnotationWithNestedEnum(value = VALUE))
|
|
@ -0,0 +1,12 @@
|
|||
import scala.reflect.runtime.universe._
|
||||
import scala.reflect.runtime.{currentMirror => cm}
|
||||
|
||||
class Bean {
|
||||
@JavaAnnotationWithNestedEnum(JavaAnnotationWithNestedEnum.Value.VALUE)
|
||||
def value = 1
|
||||
}
|
||||
|
||||
object Test extends App {
|
||||
println(cm.staticClass("Bean").isCaseClass)
|
||||
println(typeOf[Bean].declaration(newTermName("value")).annotations)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
[[syntax trees at end of specialize]] // newSource1
|
||||
package <empty> {
|
||||
class Foo extends Object {
|
||||
def <init>(): Foo = {
|
||||
Foo.super.<init>();
|
||||
()
|
||||
};
|
||||
private[this] val f: Int => Int = {
|
||||
@SerialVersionUID(0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1$mcII$sp with Serializable {
|
||||
def <init>(): anonymous class $anonfun = {
|
||||
$anonfun.super.<init>();
|
||||
()
|
||||
};
|
||||
final def apply(param: Int): Int = $anonfun.this.apply$mcII$sp(param);
|
||||
<specialized> def apply$mcII$sp(param: Int): Int = param
|
||||
};
|
||||
(new anonymous class $anonfun(): Int => Int)
|
||||
};
|
||||
<stable> <accessor> def f(): Int => Int = Foo.this.f
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import scala.tools.partest._
|
||||
import java.io.{Console => _, _}
|
||||
|
||||
object Test extends DirectTest {
|
||||
|
||||
override def extraSettings: String = "-usejavacp -Xprint:specialize -d " + testOutput.path
|
||||
|
||||
override def code = "class Foo { val f = (param: Int) => param } "
|
||||
|
||||
override def show(): Unit = {
|
||||
Console.withErr(System.out) {
|
||||
compile()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import scala.tools.nsc.doc.model._
|
||||
import scala.tools.nsc.doc.model.comment._
|
||||
import scala.tools.nsc.doc.base._
|
||||
import scala.tools.nsc.doc.base.comment._
|
||||
import scala.tools.partest.ScaladocModelTest
|
||||
import java.net.{URI, URL}
|
||||
import java.io.File
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import scala.tools.nsc.doc.model._
|
||||
import scala.tools.nsc.doc.model.comment._
|
||||
import scala.tools.nsc.doc.base._
|
||||
import scala.tools.nsc.doc.base.comment._
|
||||
import scala.tools.partest.ScaladocModelTest
|
||||
import java.net.{URI, URL}
|
||||
import java.io.File
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import scala.tools.nsc.doc.base._
|
||||
import scala.tools.nsc.doc.model._
|
||||
import scala.tools.partest.ScaladocModelTest
|
||||
|
||||
|
@ -88,4 +89,4 @@ object Test extends ScaladocModelTest {
|
|||
assert(bar.valueParams(0)(0).resultType.name == "(AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]",
|
||||
bar.valueParams(0)(0).resultType.name + " == (AnyRef { type Lambda[X] <: Either[A,X] })#Lambda[String]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import scala.tools.nsc.doc.base._
|
||||
import scala.tools.nsc.doc.model._
|
||||
import scala.tools.nsc.doc.model.diagram._
|
||||
import scala.tools.partest.ScaladocModelTest
|
||||
|
@ -84,4 +85,4 @@ object Test extends ScaladocModelTest {
|
|||
assert(mcReverseType.refEntity(0)._1 == LinkToTpl(MyCollection),
|
||||
mcReverse.qualifiedName + "'s return type has a link to " + MyCollection.qualifiedName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue