mirror of https://github.com/sbt/sbt.git
**Problem** When `autoAPIMappings := true` is set on a Scala 3 project, running `sbt doc` emits warnings: ``` [warn] bad option '-doc-external-doc:/modules/java.base#https://docs.oracle.com/... ``` This happens because Scala 3's scaladoc doesn't recognize Scala 2's `-doc-external-doc` option. Fixes #6652 **Solution** - Added `Opts.doc.externalAPIScala3` that generates the Scala 3 format: `-external-mappings:regex::[scaladoc3|javadoc]::url` - Modified `Defaults.scala` to use the appropriate method based on Scala version - Added heuristics to detect javadoc vs scaladoc based on file/URL patterns
This commit is contained in:
parent
c099be5f18
commit
f4ab500d19
|
|
@ -2030,7 +2030,10 @@ object Defaults extends BuildCommon {
|
||||||
val xapisFiles = xapis.map { (k, v) =>
|
val xapisFiles = xapis.map { (k, v) =>
|
||||||
converter.toPath(k).toFile() -> v
|
converter.toPath(k).toFile() -> v
|
||||||
}
|
}
|
||||||
val options = sOpts ++ Opts.doc.externalAPI(xapisFiles)
|
val externalApiOpts =
|
||||||
|
if (ScalaArtifacts.isScala3(sv)) Opts.doc.externalAPIScala3(xapisFiles)
|
||||||
|
else Opts.doc.externalAPI(xapisFiles)
|
||||||
|
val options = sOpts ++ externalApiOpts
|
||||||
val scalac = cs.scalac match
|
val scalac = cs.scalac match
|
||||||
case ac: AnalyzingCompiler => ac.onArgs(exported(s, "scaladoc"))
|
case ac: AnalyzingCompiler => ac.onArgs(exported(s, "scaladoc"))
|
||||||
val docSrcFiles = if ScalaArtifacts.isScala3(sv) then tFiles else srcs
|
val docSrcFiles = if ScalaArtifacts.isScala3(sv) then tFiles else srcs
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,37 @@ object Opts {
|
||||||
mappings
|
mappings
|
||||||
.map { (f, u) => s"${f.getAbsolutePath}#${u.toURL().toExternalForm}" }
|
.map { (f, u) => s"${f.getAbsolutePath}#${u.toURL().toExternalForm}" }
|
||||||
.mkString("-doc-external-doc:", ",", "") :: Nil
|
.mkString("-doc-external-doc:", ",", "") :: Nil
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates Scala 3 scaladoc external mappings option.
|
||||||
|
* Format: -external-mappings:regex::[scaladoc3|scaladoc|javadoc]::url,...
|
||||||
|
*/
|
||||||
|
def externalAPIScala3(mappings: Iterable[(File, URI)]): Seq[String] =
|
||||||
|
if (mappings.isEmpty) Nil
|
||||||
|
else
|
||||||
|
mappings
|
||||||
|
.map { (f, u) =>
|
||||||
|
val fileName = f.getName
|
||||||
|
// Escape regex special characters in the filename
|
||||||
|
val escapedName = fileName.replaceAll("([\\[\\]{}()*+?.\\\\^$|])", "\\\\$1")
|
||||||
|
// Use a regex pattern that matches the file anywhere in the classpath
|
||||||
|
val regex = s".*$escapedName"
|
||||||
|
// Determine if this is javadoc or scaladoc based on the file/URL
|
||||||
|
val docType = if (isJavaDoc(f, u)) "javadoc" else "scaladoc3"
|
||||||
|
s"$regex::$docType::${u.toURL().toExternalForm}"
|
||||||
|
}
|
||||||
|
.mkString("-external-mappings:", ",", "") :: Nil
|
||||||
|
|
||||||
|
private def isJavaDoc(file: File, uri: URI): Boolean = {
|
||||||
|
val name = file.getName.toLowerCase
|
||||||
|
val url = uri.toString.toLowerCase
|
||||||
|
// Heuristics to detect Java documentation
|
||||||
|
name.startsWith("rt.jar") ||
|
||||||
|
name.contains("java") && !name.contains("scala") ||
|
||||||
|
url.contains("docs.oracle.com") ||
|
||||||
|
url.contains("javadoc") ||
|
||||||
|
url.contains("/java/") && !url.contains("scala")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
object resolver {
|
object resolver {
|
||||||
import sbt.io.syntax.*
|
import sbt.io.syntax.*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Test for issue #6652: Doc task fails with `bad option '-doc-external-doc'` for scala3 project
|
||||||
|
// This test verifies that autoAPIMappings works correctly with Scala 3's -external-mappings option
|
||||||
|
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
scalaVersion := "3.3.4",
|
||||||
|
autoAPIMappings := true,
|
||||||
|
libraryDependencies += "org.typelevel" %% "cats-core" % "2.12.0",
|
||||||
|
TaskKey[Unit]("checkDocGenerated") := {
|
||||||
|
val docDir = (Compile / doc / target).value
|
||||||
|
val indexFile = docDir / "index.html"
|
||||||
|
assert(indexFile.exists(), s"Expected $indexFile to exist after doc generation")
|
||||||
|
println(s"Documentation generated successfully at $docDir")
|
||||||
|
},
|
||||||
|
TaskKey[Unit]("checkApiMappings") := {
|
||||||
|
val mappings = (Compile / doc / apiMappings).value
|
||||||
|
println(s"API Mappings count: ${mappings.size}")
|
||||||
|
// With autoAPIMappings and cats-core dependency, we should have some mappings
|
||||||
|
// (cats-core publishes with apiURL)
|
||||||
|
println(s"API Mappings: ${mappings.take(3).mkString("\n ", "\n ", "")}")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package example
|
||||||
|
|
||||||
|
/** An example class to generate documentation for. */
|
||||||
|
class Example {
|
||||||
|
/** Returns a greeting */
|
||||||
|
def greet: String = "Hello"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
# Test for issue #6652: Doc task should use -external-mappings for Scala 3
|
||||||
|
# instead of -doc-external-doc which causes "bad option" warnings
|
||||||
|
|
||||||
|
# Show the API mappings that will be used
|
||||||
|
> checkApiMappings
|
||||||
|
|
||||||
|
# Run the doc task - this should succeed without "bad option" warnings
|
||||||
|
# Before the fix, this would emit a warning about bad option -doc-external-doc
|
||||||
|
> doc
|
||||||
|
|
||||||
|
# Verify documentation was actually generated
|
||||||
|
> checkDocGenerated
|
||||||
Loading…
Reference in New Issue