Skip to content

Commit d22b74c

Browse files
committed
Scaladoc knows the package structure of the libraries,
so don't include them in external documentation setting.
1 parent 5691373 commit d22b74c

File tree

9 files changed

+199
-22
lines changed

9 files changed

+199
-22
lines changed

src/compiler/scala/tools/nsc/doc/Settings.scala

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package scala.tools.nsc
77
package doc
88

99
import java.io.File
10+
import java.net.URI
1011
import java.lang.System
1112
import scala.language.postfixOps
1213

@@ -71,6 +72,12 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
7172
""
7273
)
7374

75+
val docExternalUris = MultiStringSetting (
76+
"-doc-external-uris",
77+
"external-doc",
78+
"comma-separated list of file://classpath_entry_path#doc_URL URIs for external dependencies"
79+
)
80+
7481
val useStupidTypes = BooleanSetting (
7582
"-Yuse-stupid-types",
7683
"Print the types of inherited members as seen from their original definition context. Hint: you don't want to do that!"
@@ -197,7 +204,7 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
197204
val docExternalUrls = MultiStringSetting (
198205
"-external-urls",
199206
"externalUrl(s)",
200-
"comma-separated list of package_names=doc_URL for external dependencies, where package names are ':'-separated"
207+
"(deprecated) comma-separated list of package_names=doc_URL for external dependencies, where package names are ':'-separated"
201208
)
202209

203210
val docGroups = BooleanSetting (
@@ -244,22 +251,25 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_))
244251
}
245252
}
246253

247-
// TODO: Enable scaladoc to scoop up the package list from another scaladoc site, just as javadoc does
248-
// -external-urls 'http://www.scala-lang.org/archives/downloads/distrib/files/nightly/docs/library'
249-
// should trigger scaldoc to fetch the package-list file. The steps necessary:
250-
// 1 - list all packages generated in scaladoc in the package-list file, exactly as javadoc:
251-
// see http://docs.oracle.com/javase/6/docs/api/package-list for http://docs.oracle.com/javase/6/docs/api
252-
// 2 - download the file and add the packages to the list
253-
lazy val extUrlMapping: Map[String, String] = (Map.empty[String, String] /: docExternalUrls.value) {
254+
def appendIndex(url: String): String = {
255+
val index = "/index.html"
256+
if (url.endsWith(index)) url else url + index
257+
}
258+
259+
// Deprecated together with 'docExternalUrls' option.
260+
lazy val extUrlPackageMapping: Map[String, String] = (Map.empty[String, String] /: docExternalUrls.value) {
254261
case (map, binding) =>
255262
val idx = binding indexOf "="
256263
val pkgs = binding substring (0, idx) split ":"
257-
var url = binding substring (idx + 1)
258-
val index = "/index.html"
259-
url = if (url.endsWith(index)) url else url + index
264+
val url = appendIndex(binding substring (idx + 1))
260265
map ++ (pkgs map (_ -> url))
261266
}
262267

268+
lazy val extUrlMapping: Map[String, String] = docExternalUris.value map { s =>
269+
val uri = new URI(s)
270+
uri.getSchemeSpecificPart -> appendIndex(uri.getFragment)
271+
} toMap
272+
263273
/**
264274
* This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty,
265275
* but ultimately scaladoc has to be useful. :)

src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ trait MemberLookup {
4848
}
4949

5050
if (sym.isClass || sym.isModule || sym.isTrait || sym.isPackage)
51-
findExternalLink(linkName(sym))
51+
findExternalLink(sym, linkName(sym))
5252
else if (owner.isClass || owner.isModule || owner.isTrait || owner.isPackage)
53-
findExternalLink(linkName(owner) + "@" + externalSignature(sym))
53+
findExternalLink(sym, linkName(owner) + "@" + externalSignature(sym))
5454
else
5555
None
5656
}
@@ -173,7 +173,7 @@ trait MemberLookup {
173173
// and removing NoType classes
174174
def cleanupBogusClasses(syms: List[Symbol]) = { syms.filter(_.info != NoType) }
175175

176-
def syms(name: Name) = container.info.nonPrivateMember(name).alternatives
176+
def syms(name: Name) = container.info.nonPrivateMember(name.encodedName).alternatives
177177
def termSyms = cleanupBogusClasses(syms(newTermName(name)))
178178
def typeSyms = cleanupBogusClasses(syms(newTypeName(name)))
179179

src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
2828
with MemberLookup =>
2929

3030
import global._
31-
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
31+
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
3232
import rootMirror.{ RootPackage, RootClass, EmptyPackage }
3333

3434
def templatesCount = docTemplatesCache.count(_._2.isDocTemplate) - droppedPackages.size
@@ -1084,12 +1084,27 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
10841084
{ val rawComment = global.expandedDocComment(bSym, inTpl.sym)
10851085
rawComment.contains("@template") || rawComment.contains("@documentable") }
10861086

1087-
def findExternalLink(name: String): Option[LinkTo] =
1088-
settings.extUrlMapping find {
1089-
case (pkg, _) => name startsWith pkg
1090-
} map {
1091-
case (_, url) => LinkToExternal(name, url + "#" + name)
1087+
def findExternalLink(sym: Symbol, name: String): Option[LinkTo] = {
1088+
val sym1 =
1089+
if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
1090+
else if (sym.isPackage)
1091+
/* Get package object which has associatedFile ne null */
1092+
sym.info.member(newTermName("package"))
1093+
else sym
1094+
Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
1095+
val path = src.path
1096+
settings.extUrlMapping get path map { url =>
1097+
LinkToExternal(name, url + "#" + name)
1098+
}
1099+
} orElse {
1100+
// Deprecated option.
1101+
settings.extUrlPackageMapping find {
1102+
case (pkg, _) => name startsWith pkg
1103+
} map {
1104+
case (_, url) => LinkToExternal(name, url + "#" + name)
1105+
}
10921106
}
1107+
}
10931108

10941109
def externalSignature(sym: Symbol) = {
10951110
sym.info // force it, otherwise we see lazy types

src/compiler/scala/tools/nsc/doc/model/ModelFactoryTypeSupport.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ trait ModelFactoryTypeSupport {
104104
if (!bSym.owner.isPackage)
105105
Tooltip(name)
106106
else
107-
findExternalLink(name).getOrElse (
107+
findExternalLink(bSym, name).getOrElse (
108108
// (3) if we couldn't find neither the owner nor external URL to link to, show a tooltip with the qualified name
109109
Tooltip(name)
110110
)

src/manual/scala/man1/scaladoc.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ object scaladoc extends Command {
7575
"Define the overall version number of the documentation, typically the version of the library being documented."),
7676
Definition(
7777
CmdOption("doc-source-url", Argument("url")),
78-
"Define a URL to be concatenated with source locations for link to source files."))),
78+
"Define a URL to be concatenated with source locations for link to source files."),
79+
Definition(
80+
CmdOption("doc-external-uris", Argument("external-doc")),
81+
"Define comma-separated list of file://classpath_entry_path#doc_URL URIs for linking to external dependencies."))),
7982

8083
Section("Compiler Options",
8184
DefinitionList(
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Done.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import scala.tools.nsc.doc.model._
2+
import scala.tools.nsc.doc.model.comment._
3+
import scala.tools.partest.ScaladocModelTest
4+
import java.net.{URI, URL}
5+
import java.io.File
6+
7+
object Test extends ScaladocModelTest {
8+
9+
override def code =
10+
"""
11+
/** See:
12+
* - [[scala.collection.Map]] Simple linking
13+
* - [[scala.collection.immutable.::]] Linking with symbolic name
14+
* - [[scala.Int]].toLong Linking to a class
15+
* - [[scala.Predef]] Linking to an object
16+
* - [[scala.Int.toLong]] Linking to a method
17+
* - [[scala]] Linking to a package
18+
* - [[scala.AbstractMethodError]] Linking to a member in the package object
19+
* - [[scala.Predef.String]] Linking to a member in an object
20+
*
21+
* Don't look at:
22+
* - [[scala.NoLink]] Not linking :)
23+
*/
24+
object Test {
25+
def foo(param: Any) {}
26+
def barr(l: scala.collection.immutable.List[Any]) {}
27+
def bar(l: List[String]) {} // TODO: Should be able to link to type aliases
28+
def baz(d: java.util.Date) {} // Should not be resolved
29+
}
30+
"""
31+
32+
def scalaURL = "http://bog.us"
33+
34+
override def scaladocSettings = "-no-link-warnings -external-urls scala=" + scalaURL
35+
36+
def testModel(rootPackage: Package) {
37+
import access._
38+
val test = rootPackage._object("Test")
39+
40+
def check(memberDef: Def, expected: Int) {
41+
val externals = memberDef.valueParams(0)(0).resultType.refEntity collect {
42+
case (_, (LinkToExternal(name, url), _)) => assert(url.contains(scalaURL)); name
43+
}
44+
assert(externals.size == expected)
45+
}
46+
47+
check(test._method("foo"), 1)
48+
check(test._method("bar"), 0)
49+
check(test._method("barr"), 2)
50+
check(test._method("baz"), 0)
51+
52+
val expectedUrls = collection.mutable.Set[String](
53+
"scala.collection.Map",
54+
"scala.collection.immutable.::",
55+
"scala.Int",
56+
"scala.Predef$",
57+
"scala.Int@toLong:Long",
58+
"scala.package",
59+
"scala.package@AbstractMethodError=AbstractMethodError",
60+
"scala.Predef$@String=String"
61+
).map(scalaURL + "/index.html#" + _)
62+
63+
def isExpectedExternalLink(l: EntityLink) = l.link match {
64+
case LinkToExternal(name, url) => assert(expectedUrls contains url, url); true
65+
case _ => false
66+
}
67+
68+
assert(countLinks(test.comment.get, isExpectedExternalLink) == 8,
69+
countLinks(test.comment.get, isExpectedExternalLink) + " == 8")
70+
}
71+
}

test/scaladoc/run/SI-191.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Done.

test/scaladoc/run/SI-191.scala

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import scala.tools.nsc.doc.model._
2+
import scala.tools.nsc.doc.model.comment._
3+
import scala.tools.partest.ScaladocModelTest
4+
import java.net.{URI, URL}
5+
import java.io.File
6+
7+
object Test extends ScaladocModelTest {
8+
9+
override def code =
10+
"""
11+
/** See:
12+
* - [[scala.collection.Map]] Simple linking
13+
* - [[scala.collection.immutable.::]] Linking with symbolic name
14+
* - [[scala.Int]].toLong Linking to a class
15+
* - [[scala.Predef]] Linking to an object
16+
* - [[scala.Int.toLong]] Linking to a method
17+
* - [[scala]] Linking to a package
18+
* - [[scala.AbstractMethodError]] Linking to a member in the package object
19+
* - [[scala.Predef.String]] Linking to a member in an object
20+
*
21+
* Don't look at:
22+
* - [[scala.NoLink]] Not linking :)
23+
*/
24+
object Test {
25+
def foo(param: Any) {}
26+
def barr(l: scala.collection.immutable.List[Any]) {}
27+
def bar(l: List[String]) {} // TODO: Should be able to link to type aliases
28+
def baz(d: java.util.Date) {} // Should not be resolved
29+
}
30+
"""
31+
32+
def scalaURL = "http://bog.us"
33+
34+
override def scaladocSettings = {
35+
val scalaLibUri = getClass.getClassLoader.getResource("scala/Function1.class").toURI.getSchemeSpecificPart.split("!")(0)
36+
val scalaLib = new File(new URL(scalaLibUri).getPath).getPath
37+
val extArg = new URI("file", scalaLib, scalaURL).toString
38+
"-no-link-warnings -doc-external-uris " + extArg
39+
}
40+
41+
def testModel(rootPackage: Package) {
42+
import access._
43+
val test = rootPackage._object("Test")
44+
45+
def check(memberDef: Def, expected: Int) {
46+
val externals = memberDef.valueParams(0)(0).resultType.refEntity collect {
47+
case (_, (LinkToExternal(name, url), _)) => assert(url.contains(scalaURL)); name
48+
}
49+
assert(externals.size == expected)
50+
}
51+
52+
check(test._method("foo"), 1)
53+
check(test._method("bar"), 0)
54+
check(test._method("barr"), 2)
55+
check(test._method("baz"), 0)
56+
57+
val expectedUrls = collection.mutable.Set[String](
58+
"scala.collection.Map",
59+
"scala.collection.immutable.::",
60+
"scala.Int",
61+
"scala.Predef$",
62+
"scala.Int@toLong:Long",
63+
"scala.package",
64+
"scala.package@AbstractMethodError=AbstractMethodError",
65+
"scala.Predef$@String=String"
66+
).map(scalaURL + "/index.html#" + _)
67+
68+
def isExpectedExternalLink(l: EntityLink) = l.link match {
69+
case LinkToExternal(name, url) => assert(expectedUrls contains url, url); true
70+
case _ => false
71+
}
72+
73+
assert(countLinks(test.comment.get, isExpectedExternalLink) == 8,
74+
countLinks(test.comment.get, isExpectedExternalLink) + " == 8")
75+
}
76+
}

0 commit comments

Comments
 (0)