diff options
20 files changed, 561 insertions, 303 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 0fbd930ad7..58fcee4b30 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -1079,12 +1079,12 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * of what file was being compiled when it broke. Since I really * really want to know, this hack. */ - protected var lastSeenSourceFile: SourceFile = NoSourceFile + private var lastSeenSourceFile: SourceFile = NoSourceFile /** Let's share a lot more about why we crash all over the place. * People will be very grateful. */ - protected var lastSeenContext: analyzer.Context = null + private var lastSeenContext: analyzer.Context = null /** The currently active run */ diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala index dbbc573299..64a376b96e 100644 --- a/src/compiler/scala/tools/nsc/doc/Settings.scala +++ b/src/compiler/scala/tools/nsc/doc/Settings.scala @@ -194,6 +194,12 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) "Expand all type aliases and abstract types into full template pages. (locally this can be done with the @template annotation)" ) + val docExternalUrls = MultiStringSetting ( + "-external-urls", + "externalUrl(s)", + "comma-separated list of package_names=doc_URL for external dependencies, where package names are ':'-separated" + ) + val docGroups = BooleanSetting ( "-groups", "Group similar functions together (based on the @group annotation)" @@ -238,6 +244,22 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) } } + // TODO: Enable scaladoc to scoop up the package list from another scaladoc site, just as javadoc does + // -external-urls 'http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library' + // should trigger scaldoc to fetch the package-list file. The steps necessary: + // 1 - list all packages generated in scaladoc in the package-list file, exactly as javadoc: + // see http://docs.oracle.com/javase/6/docs/api/package-list for http://docs.oracle.com/javase/6/docs/api + // 2 - download the file and add the packages to the list + lazy val extUrlMapping: Map[String, String] = (Map.empty[String, String] /: docExternalUrls.value) { + case (map, binding) => + val idx = binding indexOf "=" + val pkgs = binding substring (0, idx) split ":" + var url = binding substring (idx + 1) + val index = "/index.html" + url = if (url.endsWith(index)) url else url + index + map ++ (pkgs map (_ -> url)) + } + /** * This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty, * but ultimately scaladoc has to be useful. :) diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala index f7c5611b8a..2c719e5d70 100644 --- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala @@ -138,7 +138,8 @@ abstract class HtmlPage extends Page { thisPage => <span class="extmbr" name={ mbr.qualifiedName }>{ inlineToHtml(text) }</span> case Tooltip(tooltip) => <span class="extype" name={ tooltip }>{ inlineToHtml(text) }</span> - // TODO: add case LinkToExternal here + case LinkToExternal(name, url) => + <a href={ url } class="extype" target="_top">{ inlineToHtml(text) }</a> case NoLink => inlineToHtml(text) } diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index d4e52ba120..919a45aefc 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -41,7 +41,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp <script type="text/javascript" src={ relativeLinkTo{List("jquery-ui.js", "lib")} }></script> <script type="text/javascript" src={ relativeLinkTo{List("template.js", "lib")} }></script> <script type="text/javascript" src={ relativeLinkTo{List("tools.tooltip.js", "lib")} }></script> - { if (universe.settings.docDiagrams.isSetByUser) { + { if (universe.settings.docDiagrams.value) { <script type="text/javascript" src={ relativeLinkTo{List("modernizr.custom.js", "lib")} }></script> <script type="text/javascript" src={ relativeLinkTo{List("diagrams.js", "lib")} } id="diagrams-js"></script> } else NodeSeq.Empty } @@ -289,6 +289,7 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp fullComment={ if(memberComment.filter(_.label=="div").isEmpty) "no" else "yes" } group={ mbr.group }> <a id={ mbr.signature }/> + <a id={ mbr.signatureCompat }/> { signature(mbr, false) } { memberComment } </li> @@ -645,17 +646,28 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp case _ => NodeSeq.Empty } - val typeHierarchy = if (s.docDiagrams.isSetByUser) mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced => - makeDiagramHtml(dtpl, dtpl.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram") - case _ => NodeSeq.Empty - } else NodeSeq.Empty // diagrams not generated + def createDiagram(f: DocTemplateEntity => Option[Diagram], description: String, id: String): NodeSeq = + if (s.docDiagrams.value) mbr match { + case dtpl: DocTemplateEntity if isSelf && !isReduced => + val diagram = f(dtpl) + if (diagram.isDefined) { + val s = universe.settings + val diagramSvg = generator.generate(diagram.get, tpl, this) + if (diagramSvg != NodeSeq.Empty) { + <div class="toggleContainer block diagram-container" id={ id + "-container"}> + <span class="toggle diagram-link">{ description }</span> + <a href="http://docs.scala-lang.org/overviews/scaladoc/usage.html#diagrams" target="_blank" class="diagram-help">Learn more about scaladoc diagrams</a> + <div class="diagram" id={ id }>{ + diagramSvg + }</div> + </div> + } else NodeSeq.Empty + } else NodeSeq.Empty + case _ => NodeSeq.Empty + } else NodeSeq.Empty // diagrams not generated - val contentHierarchy = if (s.docDiagrams.isSetByUser) mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced => - makeDiagramHtml(dtpl, dtpl.contentDiagram, "Content Hierarchy", "content-diagram") - case _ => NodeSeq.Empty - } else NodeSeq.Empty // diagrams not generated + val typeHierarchy = createDiagram(_.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram") + val contentHierarchy = createDiagram(_.contentDiagram, "Content Hierarchy", "content-diagram") memberComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy } @@ -946,22 +958,6 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp scala.xml.Text(ub.typeParamName + " is a subclass of " + ub.upperBound.name + " (" + ub.typeParamName + " <: ") ++ typeToHtml(ub.upperBound, true) ++ scala.xml.Text(")") } - - def makeDiagramHtml(tpl: DocTemplateEntity, diagram: Option[Diagram], description: String, id: String) = { - if (diagram.isDefined) { - val s = universe.settings - val diagramSvg = generator.generate(diagram.get, tpl, this) - if (diagramSvg != NodeSeq.Empty) { - <div class="toggleContainer block diagram-container" id={ id + "-container"}> - <span class="toggle diagram-link">{ description }</span> - <a href="http://docs.scala-lang.org/overviews/scaladoc/usage.html#diagrams" target="_blank" class="diagram-help">Learn more about scaladoc diagrams</a> - <div class="diagram" id={ id }>{ - diagramSvg - }</div> - </div> - } else NodeSeq.Empty - } else NodeSeq.Empty - } } object Template { diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index 6d193c30f7..a63849e3f6 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -196,6 +196,9 @@ trait MemberEntity extends Entity { /** The identity of this member, used for linking */ def signature: String + /** Compatibility signature, will be removed from future versions */ + def signatureCompat: String + /** Indicates whether the member is inherited by implicit conversion */ def isImplicitlyInherited: Boolean @@ -625,4 +628,4 @@ trait UpperBoundedTypeParamConstraint extends TypeParamConstraint { /** toString for debugging */ override def toString = typeParamName + " is a subclass of " + upperBound.name + " (" + typeParamName + " <: " + upperBound.name + ")" -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala index 664567872e..737c6a7577 100644 --- a/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala +++ b/src/compiler/scala/tools/nsc/doc/model/LinkTo.scala @@ -9,10 +9,10 @@ package model import scala.collection._ abstract sealed class LinkTo -case class LinkToTpl(tpl: DocTemplateEntity) extends LinkTo -case class LinkToMember(mbr: MemberEntity, inTpl: DocTemplateEntity) extends LinkTo -case class Tooltip(name: String) extends LinkTo { def this(tpl: TemplateEntity) = this(tpl.qualifiedName) } -// case class LinkToExternal(name: String, url: String) extends LinkTo // for SI-191, whenever Manohar will have time +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 { diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala index ab14498a7c..7ab73cceff 100644 --- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala +++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala @@ -11,6 +11,7 @@ trait MemberLookup { 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) } @@ -21,23 +22,44 @@ trait MemberLookup { var members = breakMembers(query) //println(query + " => " + members) - // (1) Lookup in the root package, as most of the links are qualified - var linkTo: List[LinkTo] = lookupInRootPackage(pos, members) + // (1) First look in the root package, as most of the links are qualified + val fromRoot = lookupInRootPackage(pos, members) - // (2) Recursively go into each - if (inTplOpt.isDefined) { - var currentTpl = inTplOpt.get - while (currentTpl != null && !currentTpl.isRootPackage && (linkTo.isEmpty)) { - linkTo = lookupInTemplate(pos, members, currentTpl) - currentTpl = currentTpl.inTemplate - } + // (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) } - // (3) Look at external links - if (linkTo.isEmpty) { - // TODO: IF THIS IS THE ROOT PACKAGE, LOOK AT EXTERNAL LINKS + 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(linkName(sym)) + else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage) + findExternalLink(linkName(owner) + "@" + externalSignature(sym)) + else + None + } + 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) @@ -97,9 +119,23 @@ trait MemberLookup { private object OnlyType extends SearchStrategy private object OnlyTerm extends SearchStrategy - private def lookupInRootPackage(pos: Position, members: List[String]) = lookupInTemplate(pos, members, makeRootPackage) + private def lookupInRootPackage(pos: Position, members: List[String]) = + if (members.length == 1) + lookupInTemplate(pos, members, EmptyPackage) ::: lookupInTemplate(pos, members, RootPackage) + else + lookupInTemplate(pos, members, RootPackage) - private def lookupInTemplate(pos: Position, members: List[String], inTpl: DocTemplateImpl): List[LinkTo] = { + private def createLinks(syms: List[(Symbol, Symbol)]): List[LinkTo] = + syms.flatMap { case (sym, owner) => + if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage) + findTemplateMaybe(sym) map (LinkToTpl(_)) + else + findTemplateMaybe(owner) flatMap { inTpl => + inTpl.members find (_.asInstanceOf[EntityImpl].sym == sym) map (LinkToMember(_, inTpl)) + } + } + + 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: @@ -108,53 +144,56 @@ trait MemberLookup { // * 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 Nil => Nil case mbrName::Nil => - var members = lookupInTemplate(pos, mbrName, inTpl, OnlyType) - if (members.isEmpty) - members = lookupInTemplate(pos, mbrName, inTpl, OnlyTerm) - - members.map(_ match { - case tpl: DocTemplateEntity => LinkToTpl(tpl) - case mbr => LinkToMember(mbr, inTpl) - }) + 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 filter {sym => sym.isPackage || sym.isClass || sym.isModule} flatMap (lookupInTemplate(pos, rest, _)) - def completeSearch(mbrs: List[MemberImpl]) = - mbrs.collect({case d:DocTemplateImpl => d}).flatMap(tpl => lookupInTemplate(pos, rest, tpl)) - - var members = completeSearch(lookupInTemplate(pos, tplName, inTpl, OnlyTerm)) - if (members.isEmpty) - members = completeSearch(lookupInTemplate(pos, tplName, inTpl, OnlyType)) - - members + completeSearch(lookupInTemplate(pos, tplName, container, OnlyTerm)) match { + case Nil => completeSearch(lookupInTemplate(pos, tplName, container, OnlyType)) + case syms => syms + } } - //println("lookupInTemplate(" + members + ", " + inTpl + ") => " + result) + //println("lookupInTemplate(" + members + ", " + container + ") => " + result) result } - private def lookupInTemplate(pos: Position, member: String, inTpl: DocTemplateImpl, strategy: SearchStrategy): List[MemberImpl] = { + 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).alternatives + def termSyms = cleanupBogusClasses(syms(newTermName(name))) + def typeSyms = cleanupBogusClasses(syms(newTypeName(name))) + val result = if (member.endsWith("$")) - inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isTerm)) + termSyms else if (member.endsWith("!")) - inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isType)) + typeSyms else if (member.endsWith("*")) - inTpl.members.filter(mbr => (mbr.signature.startsWith(name))) - else { + cleanupBogusClasses(container.info.nonPrivateDecls) filter signatureMatch + else if (strategy == BothTypeAndTerm) - inTpl.members.filter(_.name == name) + termSyms ::: typeSyms else if (strategy == OnlyType) - inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isType)) + typeSyms else if (strategy == OnlyTerm) - inTpl.members.filter(mbr => (mbr.name == name) && (mbr.isTerm)) + termSyms else Nil - } - //println("lookupInTemplate(" + member + ", " + inTpl + ") => " + result) + //println("lookupInTemplate(" + member + ", " + container + ") => " + result) result } @@ -170,7 +209,11 @@ trait MemberLookup { if ((query.charAt(index) == '.' || query.charAt(index) == '#') && ((index == 0) || (query.charAt(index-1) != '\\'))) { - members ::= query.substring(last_index, index).replaceAll("\\\\([#\\.])", "$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 @@ -184,4 +227,4 @@ trait MemberLookup { object MemberLookup { private[this] var _showExplanation = true def showExplanation: Boolean = if (_showExplanation) { _showExplanation = false; true } else false -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index a987da8ba6..07526a5608 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -209,7 +209,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) && (!isImplicitlyInherited)) || sym.isAbstractClass || sym.isAbstractType) && !sym.isSynthetic def isTemplate = false - lazy val signature = { + def signature = externalSignature(sym) + lazy val signatureCompat = { def defParams(mbr: Any): String = mbr match { case d: MemberEntity with Def => @@ -1082,5 +1083,17 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { (settings.docExpandAllTypes.value && (bSym.sourceFile != null)) || { val rawComment = global.expandedDocComment(bSym, inTpl.sym) rawComment.contains("@template") || rawComment.contains("@documentable") } + + def findExternalLink(name: String): Option[LinkTo] = + settings.extUrlMapping 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", "") + } } diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala index 6c80c85efe..c67a398bb7 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala @@ -30,7 +30,7 @@ trait ModelFactoryTypeSupport { import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass } import rootMirror.{ RootPackage, RootClass, EmptyPackage } - protected var typeCache = new mutable.LinkedHashMap[Type, TypeEntity] + protected val typeCache = new mutable.LinkedHashMap[Type, TypeEntity] /** */ def makeType(aType: Type, inTpl: TemplateImpl): TypeEntity = { @@ -77,7 +77,8 @@ trait ModelFactoryTypeSupport { // ===> in such cases we have two options: // (0) if there's no inheritance taking place (Enum#Value) we can link to the template directly // (1) if we generate the doc template for Day, we can link to the correct member - // (2) if we don't generate the doc template, we should at least indicate the correct prefix in the tooltip + // (2) If the symbol comes from an external library for which we know the documentation URL, point to it. + // (3) if we don't generate the doc template, we should at least indicate the correct prefix in the tooltip val bSym = normalizeTemplate(aSym) val owner = if ((preSym != NoSymbol) && /* it needs a prefix */ @@ -87,20 +88,27 @@ trait ModelFactoryTypeSupport { else bSym.owner - val bTpl = findTemplateMaybe(bSym) val link = - if (owner == bSym.owner && bTpl.isDefined) - // (0) the owner's class is linked AND has a template - lovely - LinkToTpl(bTpl.get) - else { - val oTpl = findTemplateMaybe(owner) - val bMbr = oTpl.map(findMember(bSym, _)) - if (oTpl.isDefined && bMbr.isDefined && bMbr.get.isDefined) - // (1) the owner's class - LinkToMember(bMbr.get.get, oTpl.get) //ugh - else - // (2) if we still couldn't find the owner, show a tooltip with the qualified name - Tooltip(makeQualifiedName(bSym)) + findTemplateMaybe(bSym) match { + case Some(bTpl) if owner == bSym.owner => + // (0) the owner's class is linked AND has a template - lovely + LinkToTpl(bTpl) + case _ => + val oTpl = findTemplateMaybe(owner) + (oTpl, oTpl flatMap (findMember(bSym, _))) match { + case (Some(oTpl), Some(bMbr)) => + // (1) the owner's class + LinkToMember(bMbr, oTpl) + case _ => + val name = makeQualifiedName(bSym) + if (!bSym.owner.isPackage) + Tooltip(name) + else + findExternalLink(name).getOrElse ( + // (3) if we couldn't find neither the owner nor external URL to link to, show a tooltip with the qualified name + Tooltip(name) + ) + } } // SI-4360 Showing prefixes when necessary @@ -308,16 +316,8 @@ trait ModelFactoryTypeSupport { // SI-4360: Entity caching depends on both the type AND the template it's in, as the prefixes might change for the // same type based on the template the type is shown in. - if (settings.docNoPrefixes.value) { - val cached = typeCache.get(aType) - cached match { - case Some(typeEntity) => - typeEntity - case None => - val typeEntity = createTypeEntity - typeCache += aType -> typeEntity - typeEntity - } - } else createTypeEntity + if (settings.docNoPrefixes.value) + typeCache.getOrElseUpdate(aType, createTypeEntity) + else createTypeEntity } -}
\ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index 47eea52095..1baa7f9831 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -760,7 +760,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory with Member } def link(): Inline = { - val SchemeUri = """([^:]+:.*)""".r + val SchemeUri = """([a-z]+:.*)""".r jump("[[") var parens = 1 readUntil { parens += 1; !check("[") } diff --git a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala index fa698afaa6..db2d0c0175 100644 --- a/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/diagram/DiagramFactory.scala @@ -150,7 +150,7 @@ trait DiagramFactory extends DiagramDirectiveParser { if (nodesShown.isEmpty) None else { - val nodes = nodesAll.filter(nodesShown.contains(_)).map(mapNodes(_)) + val nodes = nodesAll.filter(nodesShown.contains(_)).flatMap(mapNodes.get(_)) val edges = edgesAll.map(pair => (mapNodes(pair._1), pair._2.map(mapNodes(_)))).filterNot(pair => pair._2.isEmpty) val diagram = // TODO: Everyone should be able to use the @{inherit,content}Diagram annotation to change the diagrams. diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 072d823c60..5d5e150662 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -225,6 +225,24 @@ abstract class Erasure extends AddInterfaces } else { boxedSig(tp) } + def classSig = { + val preRebound = pre.baseType(sym.owner) // #2585 + dotCleanup( + ( + if (needsJavaSig(preRebound)) { + val s = jsig(preRebound, existentiallyBound) + if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName + else fullNameInSig(sym) + } + else fullNameInSig(sym) + ) + ( + if (args.isEmpty) "" else + "<"+(args map argSig).mkString+">" + ) + ( + ";" + ) + ) + } // If args isEmpty, Array is being used as a type constructor if (sym == ArrayClass && args.nonEmpty) { @@ -248,25 +266,21 @@ abstract class Erasure extends AddInterfaces else if (sym == UnitClass) jsig(BoxedUnitClass.tpe) else abbrvTag(sym).toString } - else if (sym.isClass) { - val preRebound = pre.baseType(sym.owner) // #2585 - dotCleanup( - ( - if (needsJavaSig(preRebound)) { - val s = jsig(preRebound, existentiallyBound) - if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName - else fullNameInSig(sym) - } - else fullNameInSig(sym) - ) + ( - if (args.isEmpty) "" else - "<"+(args map argSig).mkString+">" - ) + ( - ";" - ) - ) + else if (sym.isDerivedValueClass) { + val unboxed = sym.derivedValueClassUnbox.info.finalResultType + val unboxedSeen = (tp memberType sym.derivedValueClassUnbox).finalResultType + def unboxedMsg = if (unboxed == unboxedSeen) "" else s", seen within ${sym.simpleName} as $unboxedSeen" + logResult(s"Erasure of value class $sym (underlying type $unboxed$unboxedMsg) is") { + if (isPrimitiveValueType(unboxedSeen) && !primitiveOK) + classSig + else + jsig(unboxedSeen, existentiallyBound, toplevel, primitiveOK) + } } - else jsig(erasure(sym0)(tp), existentiallyBound, toplevel, primitiveOK) + else if (sym.isClass) + classSig + else + jsig(erasure(sym0)(tp), existentiallyBound, toplevel, primitiveOK) case PolyType(tparams, restpe) => assert(tparams.nonEmpty) val poly = if (toplevel) polyParamSig(tparams) else "" diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 790c78cbf5..f985eedf99 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -46,23 +46,6 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => newTermName("__wrapper$" + wrapCount + "$" + java.util.UUID.randomUUID.toString.replace("-", "")) } - // should be called after every use of ToolBoxGlobal in order to prevent leaks - // there's the `withCleanupCaches` method defined below, which provides a convenient interface for that - def cleanupCaches(): Unit = { - lub(List(IntTpe, IntTpe)) // indirectly clears lubResults and glbResults - // I didn't want to turn those caches from private to protected - // in order not to screw up the performance - perRunCaches.clearAll() - undoLog.clear() - analyzer.lastTreeToTyper = EmptyTree - lastSeenSourceFile = NoSourceFile - lastSeenContext = null - } - - def withCleanupCaches[T](body: => T): T = - try body - finally cleanupCaches() - def verify(expr: Tree): Unit = { // Previously toolboxes used to typecheck their inputs before compiling. // Actually, the initial demo by Martin first typechecked the reified tree, @@ -354,7 +337,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lazy val importer = compiler.mkImporter(u) lazy val exporter = importer.reverse - def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = compiler.withCleanupCaches { + def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = { if (compiler.settings.verbose.value) println("importing "+tree+", expectedType = "+expectedType) var ctree: compiler.Tree = importer.importTree(tree) var cexpectedType: compiler.Type = importer.importType(expectedType) @@ -374,7 +357,7 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) } - private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = compiler.withCleanupCaches { + private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = { if (compiler.settings.verbose.value) println("importing "+pt, ", tree = "+tree+", pos = "+pos) var ctree: compiler.Tree = importer.importTree(tree) var cpt: compiler.Type = importer.importType(pt) diff --git a/src/reflect/scala/reflect/internal/Importers.scala b/src/reflect/scala/reflect/internal/Importers.scala index 02209d0712..c116928d37 100644 --- a/src/reflect/scala/reflect/internal/Importers.scala +++ b/src/reflect/scala/reflect/internal/Importers.scala @@ -1,8 +1,6 @@ package scala.reflect package internal - import scala.collection.mutable.WeakHashMap -import scala.ref.WeakReference // SI-6241: move importers to a mirror trait Importers extends api.Importers { self: SymbolTable => @@ -28,20 +26,8 @@ trait Importers extends api.Importers { self: SymbolTable => val from: SymbolTable - protected lazy val symMap = new Cache[from.Symbol, Symbol]() - protected lazy val tpeMap = new Cache[from.Type, Type]() - protected class Cache[K <: AnyRef, V <: AnyRef] extends WeakHashMap[K, WeakReference[V]] { - def weakGet(key: K): Option[V] = this get key flatMap WeakReference.unapply - def weakUpdate(key: K, value: V) = this.update(key, WeakReference(value)) - def weakGetOrElseUpdate(key: K)(value: => V): V = - weakGet(key) match { - case Some(result) => result - case None => - val result = value - this(key) = WeakReference(result) - result - } - } + lazy val symMap: WeakHashMap[from.Symbol, Symbol] = new WeakHashMap + lazy val tpeMap: WeakHashMap[from.Type, Type] = new WeakHashMap // fixups and maps prevent stackoverflows in importer var pendingSyms = 0 @@ -58,10 +44,8 @@ trait Importers extends api.Importers { self: SymbolTable => object reverse extends from.StandardImporter { val from: self.type = self - // FIXME this and reverse should be constantly kept in sync - // not just synced once upon the first usage of reverse - for ((fromsym, WeakReference(mysym)) <- StandardImporter.this.symMap) symMap += ((mysym, WeakReference(fromsym))) - for ((fromtpe, WeakReference(mytpe)) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, WeakReference(fromtpe))) + for ((fromsym, mysym) <- StandardImporter.this.symMap) symMap += ((mysym, fromsym)) + for ((fromtpe, mytpe) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, fromtpe)) } // todo. careful import of positions @@ -69,70 +53,70 @@ trait Importers extends api.Importers { self: SymbolTable => pos.asInstanceOf[Position] def importSymbol(sym0: from.Symbol): Symbol = { - def doImport(sym: from.Symbol): Symbol = - symMap weakGet sym match { - case Some(result) => result - case _ => - val myowner = importSymbol(sym.owner) - val mypos = importPosition(sym.pos) - val myname = importName(sym.name).toTermName - val myflags = sym.flags - def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { - symMap.weakUpdate(x, mysym) - mysym.referenced = op(x.referenced) - mysym + def doImport(sym: from.Symbol): Symbol = { + if (symMap.contains(sym)) + return symMap(sym) + + val myowner = importSymbol(sym.owner) + val mypos = importPosition(sym.pos) + val myname = importName(sym.name).toTermName + val myflags = sym.flags + def linkReferenced(mysym: TermSymbol, x: from.TermSymbol, op: from.Symbol => Symbol): Symbol = { + symMap(x) = mysym + mysym.referenced = op(x.referenced) + mysym + } + val mysym = sym match { + case x: from.MethodSymbol => + linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol) + case x: from.ModuleSymbol => + linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) + case x: from.FreeTermSymbol => + newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info) + case x: from.FreeTypeSymbol => + newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin) + case x: from.TermSymbol => + linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol) + case x: from.TypeSkolem => + val origin = x.unpackLocation match { + case null => null + case y: from.Tree => importTree(y) + case y: from.Symbol => importSymbol(y) } - val mysym = sym match { - case x: from.MethodSymbol => - linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol) - case x: from.ModuleSymbol => - linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol) - case x: from.FreeTermSymbol => - newFreeTermSymbol(importName(x.name).toTermName, x.value, x.flags, x.origin) setInfo importType(x.info) - case x: from.FreeTypeSymbol => - newFreeTypeSymbol(importName(x.name).toTypeName, x.flags, x.origin) - case x: from.TermSymbol => - linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol) - case x: from.TypeSkolem => - val origin = x.unpackLocation match { - case null => null - case y: from.Tree => importTree(y) - case y: from.Symbol => importSymbol(y) - } - myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) - case x: from.ModuleClassSymbol => - val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags) - symMap.weakUpdate(x, mysym) - mysym.sourceModule = importSymbol(x.sourceModule) - mysym - case x: from.ClassSymbol => - val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags) - symMap.weakUpdate(x, mysym) - if (sym.thisSym != sym) { - mysym.typeOfThis = importType(sym.typeOfThis) - mysym.thisSym setName importName(sym.thisSym.name) - } - mysym - case x: from.TypeSymbol => - myowner.newTypeSymbol(myname.toTypeName, mypos, myflags) + myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags) + case x: from.ModuleClassSymbol => + val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags) + symMap(x) = mysym + mysym.sourceModule = importSymbol(x.sourceModule) + mysym + case x: from.ClassSymbol => + val mysym = myowner.newClassSymbol(myname.toTypeName, mypos, myflags) + symMap(x) = mysym + if (sym.thisSym != sym) { + mysym.typeOfThis = importType(sym.typeOfThis) + mysym.thisSym setName importName(sym.thisSym.name) } - symMap.weakUpdate(sym, mysym) - mysym setFlag Flags.LOCKED - mysym setInfo { - val mytypeParams = sym.typeParams map importSymbol - new LazyPolyType(mytypeParams) { - override def complete(s: Symbol) { - val result = sym.info match { - case from.PolyType(_, res) => res - case result => result - } - s setInfo GenPolyType(mytypeParams, importType(result)) - s setAnnotations (sym.annotations map importAnnotationInfo) - } + mysym + case x: from.TypeSymbol => + myowner.newTypeSymbol(myname.toTypeName, mypos, myflags) + } + symMap(sym) = mysym + mysym setFlag Flags.LOCKED + mysym setInfo { + val mytypeParams = sym.typeParams map importSymbol + new LazyPolyType(mytypeParams) { + override def complete(s: Symbol) { + val result = sym.info match { + case from.PolyType(_, res) => res + case result => result } + s setInfo GenPolyType(mytypeParams, importType(result)) + s setAnnotations (sym.annotations map importAnnotationInfo) } - mysym resetFlag Flags.LOCKED - } // end doImport + } + } + mysym resetFlag Flags.LOCKED + } // end doImport def importOrRelink: Symbol = { val sym = sym0 // makes sym visible in the debugger @@ -202,10 +186,14 @@ trait Importers extends api.Importers { self: SymbolTable => } // end importOrRelink val sym = sym0 - symMap.weakGetOrElseUpdate(sym) { + if (symMap contains sym) { + symMap(sym) + } else { pendingSyms += 1 - try importOrRelink - finally { + + try { + symMap getOrElseUpdate (sym, importOrRelink) + } finally { pendingSyms -= 1 tryFixup() } @@ -270,10 +258,14 @@ trait Importers extends api.Importers { self: SymbolTable => def importOrRelink: Type = doImport(tpe) - tpeMap.weakGetOrElseUpdate(tpe) { + if (tpeMap contains tpe) { + tpeMap(tpe) + } else { pendingTpes += 1 - try importOrRelink - finally { + + try { + tpeMap getOrElseUpdate (tpe, importOrRelink) + } finally { pendingTpes -= 1 tryFixup() } diff --git a/test/files/run/reflection-mem-typecheck.scala b/test/files/run/reflection-mem-typecheck.scala deleted file mode 100644 index a312c2c893..0000000000 --- a/test/files/run/reflection-mem-typecheck.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.tools.partest.MemoryTest - -trait A { type T <: A } -trait B { type T <: B } - -object Test extends MemoryTest { - lazy val tb = { - import scala.reflect.runtime.universe._ - import scala.reflect.runtime.{currentMirror => cm} - import scala.tools.reflect.ToolBox - cm.mkToolBox() - } - - override def maxDelta = 10 - override def calcsPerIter = 8 - override def calc() { - var snippet = """ - trait A { type T <: A } - trait B { type T <: B } - def foo[T](x: List[T]) = x - foo(List(new A {}, new B {})) - """.trim - snippet = snippet + "\n" + (List.fill(50)(snippet.split("\n").last) mkString "\n") - tb.typeCheck(tb.parse(snippet)) - } -}
\ No newline at end of file diff --git a/test/files/run/t6344.check b/test/files/run/t6344.check new file mode 100644 index 0000000000..5ac04d0320 --- /dev/null +++ b/test/files/run/t6344.check @@ -0,0 +1,132 @@ +C0 +public int C0.v1(int) +public <A> int C0.v1(int) +public int C0.v3() +public <A> int C0.v3() +public int C0.v4(int,scala.collection.immutable.List) +public <A> int C0.v4(int,scala.collection.immutable.List<Val<A>>) +public scala.collection.immutable.List C0.v2() +public <A> scala.collection.immutable.List<Val<A>> C0.v2() + +C1 +public java.lang.Object C1.v1(java.lang.Object) +public <A> java.lang.Object C1.v1(java.lang.Object) +public java.lang.Object C1.v3() +public <A> java.lang.Object C1.v3() +public java.lang.Object C1.v4(java.lang.Object,scala.collection.immutable.List) +public <A> java.lang.Object C1.v4(java.lang.Object,scala.collection.immutable.List<java.lang.Object>) +public scala.collection.immutable.List C1.v2() +public <A> scala.collection.immutable.List<java.lang.Object> C1.v2() + +C2 +public java.lang.String C2.v1(java.lang.String) +public <A> java.lang.String C2.v1(java.lang.String) +public java.lang.String C2.v3() +public <A> java.lang.String C2.v3() +public java.lang.String C2.v4(java.lang.String,scala.collection.immutable.List) +public <A> java.lang.String C2.v4(java.lang.String,scala.collection.immutable.List<java.lang.String>) +public scala.collection.immutable.List C2.v2() +public <A> scala.collection.immutable.List<java.lang.String> C2.v2() + +C3 +public java.lang.Object C3.v1(java.lang.Object) +public A C3.v1(A) +public java.lang.Object C3.v3() +public A C3.v3() +public java.lang.Object C3.v4(java.lang.Object,scala.collection.immutable.List) +public A C3.v4(A,scala.collection.immutable.List<A>) +public java.lang.Object C3.x() +public A C3.x() +public scala.collection.immutable.List C3.v2() +public scala.collection.immutable.List<A> C3.v2() + +C4 +public java.lang.Integer C4.v1(java.lang.Integer) +public int C4.v1(int) +public java.lang.Integer C4.v3() +public int C4.v3() +public java.lang.Integer C4.v4(java.lang.Integer,scala.collection.immutable.List) +public int C4.v4(int,scala.collection.immutable.List<ValA<java.lang.Object>>) +public scala.collection.immutable.List C4.v2() +public scala.collection.immutable.List<ValA<java.lang.Object>> C4.v2() + +C4B +public java.lang.String C4B.v1(java.lang.String) +public java.lang.String C4B.v1(java.lang.String) +public java.lang.String C4B.v3() +public java.lang.String C4B.v3() +public java.lang.String C4B.v4(java.lang.String,scala.collection.immutable.List) +public java.lang.String C4B.v4(java.lang.String,scala.collection.immutable.List<java.lang.String>) +public scala.collection.immutable.List C4B.v2() +public scala.collection.immutable.List<java.lang.String> C4B.v2() + +C5 +public double C5.f2(int,java.lang.Object,java.lang.String,double) +public double C5.f2(int,java.lang.Object,java.lang.String,double) +public int C5.f3(java.lang.Integer) +public int C5.f3(int) +public int C5.f4(java.lang.Integer) +public int C5.f4(int) +public int C5.f5(java.lang.Integer) +public int C5.f5(int) +public java.lang.Object C5.f1(int,java.lang.Object,java.lang.String,java.lang.Object) +public <A> A C5.f1(int,java.lang.Object,java.lang.String,A) + +C6 +public java.lang.Object C6.f1(int,java.lang.Object,java.lang.String,java.lang.Object) +public A C6.f1(int,java.lang.Object,java.lang.String,A) + +C7 +public java.lang.Integer C7.f1(int,java.lang.Object,java.lang.String,java.lang.Integer) +public int C7.f1(int,java.lang.Object,java.lang.String,int) +public java.lang.Object C7.f1(int,java.lang.Object,java.lang.String,java.lang.Object) +public java.lang.Object C7.f1(int,java.lang.Object,java.lang.String,java.lang.Object) + +Gen +public abstract Gen Gen.plus(Gen,Gen) +public abstract Gen<A> Gen.plus(Gen<A>,Gen<A>) +public abstract java.lang.Object Gen.x() +public abstract A Gen.x() + +ValueInt +public Gen ValueInt.plus(Gen,Gen) +public Gen<java.lang.Object> ValueInt.plus(Gen<java.lang.Object>,Gen<java.lang.Object>) +public boolean ValueInt.equals(java.lang.Object) +public boolean ValueInt.equals(java.lang.Object) +public int ValueInt.hashCode() +public int ValueInt.hashCode() +public int ValueInt.iplus(int,int) +public int ValueInt.iplus(int,int) +public int ValueInt.x() +public int ValueInt.x() +public java.lang.Object ValueInt.x() +public java.lang.Object ValueInt.x() +public static Gen ValueInt.extension$plus(int,Gen,Gen) +public static Gen<java.lang.Object> ValueInt.extension$plus(int,Gen<java.lang.Object>,Gen<java.lang.Object>) +public static boolean ValueInt.extension$equals(int,java.lang.Object) +public static boolean ValueInt.extension$equals(int,java.lang.Object) +public static int ValueInt.extension$hashCode(int) +public static int ValueInt.extension$hashCode(int) +public static int ValueInt.extension$iplus(int,int,int) +public static int ValueInt.extension$iplus(int,int,int) + +RefInt +public Gen RefInt.plus(Gen,Gen) +public Gen<java.lang.Object> RefInt.plus(Gen<java.lang.Object>,Gen<java.lang.Object>) +public RefInt RefInt.rplus(RefInt,RefInt) +public RefInt RefInt.rplus(RefInt,RefInt) +public int RefInt.x() +public int RefInt.x() +public java.lang.Object RefInt.x() +public java.lang.Object RefInt.x() + +RefInteger +public Gen RefInteger.plus(Gen,Gen) +public Gen<java.lang.Integer> RefInteger.plus(Gen<java.lang.Integer>,Gen<java.lang.Integer>) +public RefInteger RefInteger.bplus(RefInteger,RefInteger) +public RefInteger RefInteger.bplus(RefInteger,RefInteger) +public java.lang.Integer RefInteger.x() +public java.lang.Integer RefInteger.x() +public java.lang.Object RefInteger.x() +public java.lang.Object RefInteger.x() + diff --git a/test/files/run/t6344.scala b/test/files/run/t6344.scala new file mode 100644 index 0000000000..6f82e4ba51 --- /dev/null +++ b/test/files/run/t6344.scala @@ -0,0 +1,106 @@ +import scala.reflect.{ClassTag, classTag} +import java.lang.Integer + +trait Gen[A] extends Any { + def x: A + def plus(x1: Gen[A], x2: Gen[A]): Gen[A] +} +class ValueInt(val x: Int) extends AnyVal with Gen[Int] { + // Gen<java.lang.Object> ValueInt.extension$plus(int,Gen<java.lang.Object>,Gen<java.lang.Object>) + def plus(x1: Gen[Int], x2: Gen[Int]): Gen[Int] = new ValueInt(x + x1.x + x2.x) + // int ValueInt.extension$iplus(int,int,int) + def iplus(x1: ValueInt, x2: ValueInt): ValueInt = new ValueInt(x + x1.x + x2.x) +} +class RefInt(val x: Int) extends AnyRef with Gen[Int] { + def plus(x1: Gen[Int], x2: Gen[Int]): Gen[Int] = new RefInt(x + x1.x + x2.x) + def rplus(x1: RefInt, x2: RefInt): RefInt = new RefInt(x + x1.x + x2.x) +} +class RefInteger(val x: java.lang.Integer) extends AnyRef with Gen[Integer] { + def plus(x1: Gen[Integer], x2: Gen[Integer]): Gen[Integer] = new RefInteger(x + x1.x + x2.x) + def bplus(x1: RefInteger, x2: RefInteger): RefInteger = new RefInteger(x + x1.x + x2.x) +} + +class Val[Q](val value: Int) extends AnyVal +class ValAny[Q](val value: Any) extends AnyVal +class ValStr[Q](val value: String) extends AnyVal +class ValA[Q](val value: Q) extends AnyVal { + def f: Q = ??? +} +class ValB[Q, Q0 <: Q](val value: Q) extends AnyVal { + def f: Q0 = ??? +} + +class C0 { + def v1[A](in: Val[A]) = in + def v2[A]: List[Val[A]] = Nil + def v3[A]: Val[A] = new Val[A](0) + def v4[A <: String](x: Val[A], ys: List[Val[A]]) = ys.head +} +class C1 { + def v1[A](in: ValAny[A]) = in + def v2[A]: List[ValAny[A]] = Nil + def v3[A]: ValAny[A] = new ValAny[A]("") + def v4[A <: String](x: ValAny[A], ys: List[ValAny[A]]) = ys.head +} +class C2 { + def v1[A](in: ValStr[A]) = in + def v2[A]: List[ValStr[A]] = Nil + def v3[A]: ValStr[A] = new ValStr[A]("") + def v4[A <: String](x: ValStr[A], ys: List[ValStr[A]]) = ys.head +} +class C3[A](val x: A) { + def v1(in: ValA[A]) = in + def v2: List[ValA[A]] = Nil + def v3: ValA[A] = new ValA[A](x) + def v4(x: ValA[A], ys: List[ValA[A]]) = ys.head +} +class C4 { + def v1(in: ValA[Int]) = in + def v2: List[ValA[Int]] = Nil + def v3: ValA[Int] = new ValA(1) + def v4(x: ValA[Int], ys: List[ValA[Int]]) = ys.head +} +class C4B { + def v1(in: ValA[String]) = in + def v2: List[ValA[String]] = Nil + def v3: ValA[String] = new ValA("") + def v4(x: ValA[String], ys: List[ValA[String]]) = ys.head +} +class C5 { + def f1[A](x1: Val[A], x2: ValAny[A], x3: ValStr[A], x4: ValA[A]) = x4 + def f2(x1: Int, x2: Any, x3: String, x4: Double) = x4 + def f3(x: ValA[Int]) = x.f + def f4(x: ValB[Int, Int]) = x.f + def f5(x: ValB[Int, _ <: Int]) = x.f +} +class C6[A] { + def f1(x1: Val[A], x2: ValAny[A], x3: ValStr[A], x4: ValA[A]) = x4 +} +class C7 extends C6[Int] { + override def f1(x1: Val[Int], x2: ValAny[Int], x3: ValStr[Int], x4: ValA[Int]) = + super.f1(x1, x2, x3, x4) +} + +object Test { + def show[A: ClassTag] = { + println(classTag[A].runtimeClass.getName) + classTag[A].runtimeClass.getDeclaredMethods.toList.sortBy(_.toString).flatMap(m => List(m.toString, m.toGenericString)) foreach println + println("") + } + + def main(args: Array[String]): Unit = { + show[C0] + show[C1] + show[C2] + show[C3[_]] + show[C4] + show[C4B] + show[C5] + show[C6[_]] + show[C7] + show[Gen[_]] + show[ValueInt] + show[RefInt] + show[RefInteger] + } +} diff --git a/test/pending/run/reflection-mem-eval.scala b/test/pending/run/reflection-mem-eval.scala deleted file mode 100644 index 9045c44cd6..0000000000 --- a/test/pending/run/reflection-mem-eval.scala +++ /dev/null @@ -1,26 +0,0 @@ -import scala.tools.partest.MemoryTest - -trait A { type T <: A } -trait B { type T <: B } - -object Test extends MemoryTest { - lazy val tb = { - import scala.reflect.runtime.universe._ - import scala.reflect.runtime.{currentMirror => cm} - import scala.tools.reflect.ToolBox - cm.mkToolBox() - } - - override def maxDelta = 10 - override def calcsPerIter = 3 - override def calc() { - var snippet = """ - trait A { type T <: A } - trait B { type T <: B } - def foo[T](x: List[T]) = x - foo(List(new A {}, new B {})) - """.trim - snippet = snippet + "\n" + (List.fill(50)(snippet.split("\n").last) mkString "\n") - tb.eval(tb.parse(snippet)) - } -}
\ No newline at end of file diff --git a/test/scaladoc/resources/links.scala b/test/scaladoc/resources/links.scala index 679d0b0dce..09a52a4334 100644 --- a/test/scaladoc/resources/links.scala +++ b/test/scaladoc/resources/links.scala @@ -34,24 +34,29 @@ package scala.test.scaladoc.links { /** * Links to the trait: - * - [[scala.test.scaladoc.links.Target!.T trait Target -> type T]] - * - [[test.scaladoc.links.Target!.S trait Target -> type S]] - * - [[scaladoc.links.Target!.foo(Int)* trait Target -> def foo]] - * - [[links.Target!.bar trait Target -> def bar]] - * - [[[[Target!.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) - * - [[Target$.T object Target -> type T]] - * - [[Target$.S object Target -> type S]] - * - [[Target$.foo(Str* object Target -> def foo]] - * - [[Target$.bar object Target -> def bar]] - * - [[[[Target$.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) - * - [[Target.onlyInObject object Target -> def foo]] (should find the object) - * - [[Target$.C object Target -> class C]] (should link directly to C, not as a member) - * - [[Target!.C trait Target -> class C]] (should link directly to C, not as a member) - * - [[Target$.baz(links\.C)* object Target -> def baz]] (should use dots in prefix) - * - [[Target!.baz(links\.C)* trait Target -> def baz]] (should use dots in prefix) - * - [[localMethod object TEST -> localMethod]] (should use the current template to resolve link instead of inTpl, that's the package) + * - [[scala.test.scaladoc.links.Target$ object Test]] + * - [[scala.test package scala.test]] + * - [[scala.test.scaladoc.links.Target!.T trait Target -> type T]] + * - [[test.scaladoc.links.Target!.S trait Target -> type S]] + * - [[scaladoc.links.Target!.foo(i:Int)* trait Target -> def foo]] + * - [[links.Target!.bar trait Target -> def bar]] + * - [[[[Target!.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) + * - [[Target$.T object Target -> type T]] + * - [[Target$.S object Target -> type S]] + * - [[Target$.foo(z:Str* object Target -> def foo]] + * - [[Target$.bar object Target -> def bar]] + * - [[[[Target$.foo[A[_[_]]]* trait Target -> def foo with 3 nested tparams]]]] (should exercise nested parens) + * - [[Target.onlyInObject object Target -> def foo]] (should find the object) + * - [[Target$.C object Target -> class C]] (should link directly to C, not as a member) + * - [[Target!.C trait Target -> class C]] (should link directly to C, not as a member) + * - [[Target$.baz(c:scala\.test\.scaladoc\.links\.C)* object Target -> def baz]] (should use dots in prefix) + * - [[Target!.baz(c:scala\.test\.scaladoc\.links\.C)* trait Target -> def baz]] (should use dots in prefix) + * - [[localMethod object TEST -> localMethod]] (should use the current template to resolve link instead of inTpl, that's the package) + * - [[#localMethod object TEST -> localMethod]] (should exercise Java-style links to empty members) + * - [[ImOutside class ImOutside (check correct lookup in EmptyPackage)]] */ object TEST { def localMethod = 3 } } +class ImOutside
\ No newline at end of file diff --git a/test/scaladoc/run/links.scala b/test/scaladoc/run/links.scala index 40ce6368ce..de359539cf 100644 --- a/test/scaladoc/run/links.scala +++ b/test/scaladoc/run/links.scala @@ -22,7 +22,7 @@ object Test extends ScaladocModelTest { val memberLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToMember]) val templateLinks = countLinks(TEST.comment.get, _.link.isInstanceOf[LinkToTpl]) - assert(memberLinks == 14, memberLinks + " == 14 (the member links in object TEST)") - assert(templateLinks == 2, templateLinks + " == 2 (the template links in object TEST)") + assert(memberLinks == 15, memberLinks + " == 15 (the member links in object TEST)") + assert(templateLinks == 5, templateLinks + " == 5 (the template links in object TEST)") } }
\ No newline at end of file |