diff --git a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala index 1c62611210b6..f580a79ceb0d 100644 --- a/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala +++ b/compiler/src/dotty/tools/dotc/reporting/MessageRendering.scala @@ -9,7 +9,7 @@ import core.Decorators._ import printing.Highlighting.{Blue, Red, Yellow} import printing.SyntaxHighlighting import Diagnostic._ -import util.SourcePosition +import util.{ SourcePosition, NoSourcePosition } import util.Chars.{ LF, CR, FF, SU } import scala.annotation.switch @@ -112,9 +112,9 @@ trait MessageRendering { * @return separator containing error location and kind */ def posStr(pos: SourcePosition, diagnosticLevel: String, message: Message)(using Context): String = - if (pos.exists) hl(diagnosticLevel)({ + if (pos.source != NoSourcePosition.source) hl(diagnosticLevel)({ val pos1 = pos.nonInlined - val file = + val file = if !pos.exists then pos1.source.file.toString else s"${pos1.source.file.toString}:${pos1.line + 1}:${pos1.column}" val errId = if (message.errorId ne ErrorMessageID.NoExplanationID) { diff --git a/scala3doc/src/dotty/dokka/DocContext.scala b/scala3doc/src/dotty/dokka/DocContext.scala index c043f17ae761..8470b909b69d 100644 --- a/scala3doc/src/dotty/dokka/DocContext.scala +++ b/scala3doc/src/dotty/dokka/DocContext.scala @@ -1,5 +1,127 @@ package dotty.dokka +import org.jetbrains.dokka._ +import org.jetbrains.dokka.DokkaSourceSetImpl +import org.jetbrains.dokka.plugability.DokkaContext +import java.io.File +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + +import collection.JavaConverters._ +import dotty.dokka.site.StaticSiteContext import dotty.tools.dotc.core.Contexts._ +import dotty.tools.io.VirtualFile +import dotty.tools.dotc.util.SourceFile +import dotty.tools.dotc.util.SourcePosition +import dotty.tools.dotc.util.Spans +import java.io.ByteArrayOutputStream +import java.io.PrintStream +import scala.io.Codec + +type CompilerContext = dotty.tools.dotc.core.Contexts.Context + +given compilerContext(using docContext: DocContext) as CompilerContext = + docContext.compilerContext + +given docContextFromDokka(using dokkaContext: DokkaContext) as DocContext = + dokkaContext.getConfiguration.asInstanceOf[DocContext] + +val report = dotty.tools.dotc.report + +def relativePath(p: Path)(using Context): Path = + val root = Paths.get("").toAbsolutePath() + val absPath = p.toAbsolutePath + println(Seq(p, absPath, absPath.startsWith(root), root.relativize(absPath))) + if absPath.startsWith(root) then root.relativize(p.toAbsolutePath()) else p + + +def throwableToString(t: Throwable)(using CompilerContext): String = + val os = new ByteArrayOutputStream + t.printStackTrace(new PrintStream(os)) + val stLinkes = os.toString().linesIterator + if ctx.settings.verbose.value then stLinkes.mkString("\n") + else stLinkes.take(5).mkString("\n") + +private def sourcePostionFor(f: File)(using CompilerContext) = + val relPath = relativePath(f.toPath) + val virtualFile = new VirtualFile(relPath.toString, relPath.toString) + val sourceFile = new SourceFile(virtualFile, Codec.UTF8) + SourcePosition(sourceFile, Spans.NoSpan) + +// TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling +private def createMessage( + msg: String, file: File, e: Throwable | Null)(using CompilerContext): String = + val localizedMessage = s"$file: $msg" + e match + case null => localizedMessage + case throwable: Throwable => + s"$localizedMessage \ncaused by: ${throwableToString(throwable)}" + +extension (r: report.type): + def error(m: String, f: File, e: Throwable | Null = null)(using CompilerContext): Unit = + r.error(createMessage(m, f, e), sourcePostionFor(f)) + + def warn(m: String, f: File, e: Throwable)(using CompilerContext): Unit = + r.warning(createMessage(m, f, e), sourcePostionFor(f)) + + def warn(m: String, f: File)(using CompilerContext): Unit = + r.warning(createMessage(m, f, null), sourcePostionFor(f)) + + +case class DocContext(args: Scala3doc.Args, compilerContext: CompilerContext) + extends DokkaConfiguration: + override def getOutputDir: File = args.output + override def getCacheRoot: File = null + override def getOfflineMode: Boolean = false + override def getFailOnWarning: Boolean = false + override def getSourceSets: JList[DokkaSourceSet] = JList(mkSourceSet) + override def getModules: JList[DokkaConfiguration.DokkaModuleDescription] = JList() + override def getPluginsClasspath: JList[File] = JList() + override def getModuleName(): String = "ModuleName" + override def getModuleVersion(): String = "" + + lazy val sourceLinks: SourceLinks = SourceLinks.load(using this) + + lazy val displaySourceSets = getSourceSets.toDisplaySourceSet + + val logger = new Scala3DocDokkaLogger(using compilerContext) + + lazy val staticSiteContext = args.docsRoot.map(path => StaticSiteContext( + File(path).getAbsoluteFile(), + Set(mkSourceSet.asInstanceOf[SourceSetWrapper]), + args, + sourceLinks + )(using compilerContext)) + + override def getPluginsConfiguration: JList[DokkaConfiguration.PluginConfiguration] = + JList() + + val mkSourceSet: DokkaSourceSet = + new DokkaSourceSetImpl( + /*displayName=*/ args.name, + /*sourceSetID=*/ new DokkaSourceSetID(args.name, "main"), + /*classpath=*/ JList(), + /*sourceRoots=*/ JSet(), + /*dependentSourceSets=*/ JSet(), + /*samples=*/ JSet(), + /*includes=*/ JSet(), + /*includeNonPublic=*/ true, + /* changed because of exception in reportUndocumentedTransformer - there's 'when' which doesnt match because it contains only KotlinVisbility cases */ + /*reportUndocumented=*/ false, + // Now all our packages are empty from dokka perspective + /*skipEmptyPackages=*/ false, + /*skipDeprecated=*/ true, + /*jdkVersion=*/ 8, + /*sourceLinks=*/ JSet(), + /*perPackageOptions=*/ JList(), + /*externalDocumentationLinks=*/ JSet(), + /*languageVersion=*/ null, + /*apiVersion=*/ null, + /*noStdlibLink=*/ true, + /*noJdkLink=*/ true, + /*suppressedFiles=*/ JSet(), + /*suppressedFiles=*/ Platform.jvm + ).asInstanceOf[DokkaSourceSet] // Why I do need to cast here? Kotlin magic? -type DocContext = Context \ No newline at end of file + val sourceSet = mkSourceSet.asInstanceOf[SourceSetWrapper] diff --git a/scala3doc/src/dotty/dokka/DottyDokkaConfig.scala b/scala3doc/src/dotty/dokka/DottyDokkaConfig.scala deleted file mode 100644 index 88296f609074..000000000000 --- a/scala3doc/src/dotty/dokka/DottyDokkaConfig.scala +++ /dev/null @@ -1,55 +0,0 @@ -package dotty.dokka - -import org.jetbrains.dokka._ -import org.jetbrains.dokka.DokkaSourceSetImpl -import java.io.File -import collection.JavaConverters._ -import dotty.dokka.site.StaticSiteContext - -case class DottyDokkaConfig(args: Scala3doc.Args, docContext: DocContext) extends DokkaConfiguration: - override def getOutputDir: File = args.output - override def getCacheRoot: File = null - override def getOfflineMode: Boolean = false - override def getFailOnWarning: Boolean = false - override def getSourceSets: JList[DokkaSourceSet] = JList(mkSourceSet) - override def getModules: JList[DokkaConfiguration.DokkaModuleDescription] = JList() - override def getPluginsClasspath: JList[File] = JList() - override def getModuleName(): String = "ModuleName" - override def getModuleVersion(): String = "" - - lazy val sourceLinks: SourceLinks = SourceLinks.load(args) - - lazy val staticSiteContext = args.docsRoot.map(path => StaticSiteContext( - File(path).getAbsoluteFile(), - Set(mkSourceSet.asInstanceOf[SourceSetWrapper]), - args, - sourceLinks - )) - - override def getPluginsConfiguration: JList[DokkaConfiguration.PluginConfiguration] = JList() - - lazy val mkSourceSet: DokkaSourceSet = - new DokkaSourceSetImpl( - /*displayName=*/ args.name, - /*sourceSetID=*/ new DokkaSourceSetID(args.name, "main"), - /*classpath=*/ JList(), - /*sourceRoots=*/ JSet(), - /*dependentSourceSets=*/ JSet(), - /*samples=*/ JSet(), - /*includes=*/ JSet(), - /*includeNonPublic=*/ true, - /*reportUndocumented=*/ false, /* changed because of exception in reportUndocumentedTransformer - there's 'when' which doesnt match because it contains only KotlinVisbility cases */ - /*skipEmptyPackages=*/ false, // Now all our packages are empty from dokka perspective - /*skipDeprecated=*/ true, - /*jdkVersion=*/ 8, - /*sourceLinks=*/ JSet(), - /*perPackageOptions=*/ JList(), - /*externalDocumentationLinks=*/ JSet(), - /*languageVersion=*/ null, - /*apiVersion=*/ null, - /*noStdlibLink=*/ true, - /*noJdkLink=*/ true, - /*suppressedFiles=*/ JSet(), - /*suppressedFiles=*/ Platform.jvm - ).asInstanceOf[DokkaSourceSet] // Why I do need to cast here? Kotlin magic? - diff --git a/scala3doc/src/dotty/dokka/DottyDokkaPlugin.scala b/scala3doc/src/dotty/dokka/DottyDokkaPlugin.scala index 5612178b90ab..b62665f60176 100644 --- a/scala3doc/src/dotty/dokka/DottyDokkaPlugin.scala +++ b/scala3doc/src/dotty/dokka/DottyDokkaPlugin.scala @@ -23,9 +23,9 @@ import dotty.dokka.model.api._ import org.jetbrains.dokka.CoreExtensions import org.jetbrains.dokka.base.DokkaBase +import dotty.dokka.site.NavigationCreator import dotty.dokka.site.SitePagesCreator import dotty.dokka.site.StaticSiteContext -import dotty.dokka.site.RootIndexPageCreator import dotty.dokka.site.SiteResourceManager import dotty.dokka.site.StaticSiteLocationProviderFactory @@ -49,7 +49,7 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: // Just turn off another translator since multiple overrides does not work val disableDescriptorTranslator = extend( _.extensionPoint(CoreExtensions.INSTANCE.getSourceToDocumentableTranslator) - .fromRecipe(ctx => new ScalaModuleProvider(using ctx.docContext)) + .fromRecipe { case ctx @ given DokkaContext => new ScalaModuleProvider } .overrideExtension(dokkaBase.getDescriptorToDocumentableTranslator) .name("disableDescriptorTranslator") ) @@ -63,14 +63,14 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: val ourSignatureProvider = extend( _.extensionPoint(dokkaBase.getSignatureProvider) - .fromRecipe(ctx => - new ScalaSignatureProvider(ctx.single(dokkaBase.getCommentsToContentConverter), ctx.getLogger) - ).overrideExtension(dokkaBase.getKotlinSignatureProvider) + .fromRecipe{ case ctx @ given DokkaContext => + new ScalaSignatureProvider(ctx.single(dokkaBase.getCommentsToContentConverter)) + }.overrideExtension(dokkaBase.getKotlinSignatureProvider) ) val scalaResourceInstaller = extend( _.extensionPoint(dokkaBase.getHtmlPreprocessors) - .fromRecipe(ctx => new ScalaResourceInstaller(ctx.args)) + .fromRecipe{ case ctx @ given DokkaContext => new ScalaResourceInstaller } .after(dokkaBase.getCustomResourceInstaller) ) @@ -83,17 +83,14 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: val scalaDocumentableToPageTranslator = extend( _.extensionPoint(CoreExtensions.INSTANCE.getDocumentableToPageTranslator) - .fromRecipe(ctx => + .fromRecipe { case ctx @ given DokkaContext => new DocumentableToPageTranslator { override def invoke(module: DModule): ModulePageNode = ScalaPageCreator( ctx.single(dokkaBase.getCommentsToContentConverter), - ctx.single(dokkaBase.getSignatureProvider), - ctx.getConfiguration.asInstanceOf[DottyDokkaConfig].sourceLinks, - ctx.getLogger + ctx.single(dokkaBase.getSignatureProvider) ).pageForModule(module) } - ) - .overrideExtension(dokkaBase.getDocumentableToPageTranslator) + }.overrideExtension(dokkaBase.getDocumentableToPageTranslator) ) val packageHierarchyTransformer = extend( @@ -111,7 +108,7 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: val ourRenderer = extend( _.extensionPoint(CoreExtensions.INSTANCE.getRenderer) - .fromRecipe(ctx => ScalaHtmlRenderer(ctx, ctx.args)) + .fromRecipe { case ctx @ given DokkaContext => new ScalaHtmlRenderer } .overrideExtension(dokkaBase.getHtmlRenderer) ) @@ -129,7 +126,7 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: val customDocumentationProvider = extend( _.extensionPoint(dokkaBase.getHtmlPreprocessors) - .fromRecipe(c => SitePagesCreator(c.siteContext)) + .fromRecipe{ case c @ given DokkaContext => new SitePagesCreator } .name("customDocumentationProvider") .ordered( before = Seq( @@ -142,39 +139,36 @@ class DottyDokkaPlugin extends DokkaJavaPlugin: ) ) - val customIndexRootProvider = extend( + val customNavigation = extend( _.extensionPoint(dokkaBase.getHtmlPreprocessors) - .fromRecipe(c => RootIndexPageCreator(c.siteContext)) - .name("customIndexRootProvider") + .fromRecipe{ case c @ given DokkaContext => new NavigationCreator } + .name("customNavigation") .ordered( before = Seq( dokkaBase.getScriptsInstaller, dokkaBase.getStylesInstaller, ), - after = Seq(dokkaBase.getNavigationPageInstaller) + after = Seq(customDocumentationProvider.getValue) ) + .overrideExtension(dokkaBase.getNavigationPageInstaller) ) val customDocumentationResources = extend( _.extensionPoint(dokkaBase.getHtmlPreprocessors) - .fromRecipe(c => SiteResourceManager(c.siteContext)) + .fromRecipe{ case c @ given DokkaContext => new SiteResourceManager } .name("customDocumentationResources") .after( - scalaEmbeddedResourceAppender.getValue + scalaEmbeddedResourceAppender.getValue, + customDocumentationProvider.getValue ) ) val locationProvider = extend( _.extensionPoint(dokkaBase.getLocationProviderFactory) - .fromRecipe(StaticSiteLocationProviderFactory(_)) + .fromRecipe { case c @ given DokkaContext => new StaticSiteLocationProviderFactory } .overrideExtension(dokkaBase.getLocationProvider) ) -extension (ctx: DokkaContext): - def siteContext: Option[StaticSiteContext] = ctx.getConfiguration.asInstanceOf[DottyDokkaConfig].staticSiteContext - def args: Scala3doc.Args = ctx.getConfiguration.asInstanceOf[DottyDokkaConfig].args - def docContext = ctx.getConfiguration.asInstanceOf[DottyDokkaConfig].docContext - // TODO (https://github.com/lampepfl/scala3doc/issues/232): remove once problem is fixed in Dokka extension [T] (builder: ExtensionBuilder[T]): def ordered(before: Seq[Extension[_, _, _]], after: Seq[Extension[_, _, _]]): ExtensionBuilder[T] = diff --git a/scala3doc/src/dotty/dokka/Main.scala b/scala3doc/src/dotty/dokka/Main.scala index 491b05b677f9..b8fba83599a0 100644 --- a/scala3doc/src/dotty/dokka/Main.scala +++ b/scala3doc/src/dotty/dokka/Main.scala @@ -13,7 +13,6 @@ import java.nio.file.Files import dotty.tools.dotc.config.Settings._ import dotty.tools.dotc.config.CommonScalaSettings -import dotty.tools.dotc.report import dotty.tools.dotc.core.Contexts._ /** Main class for the doctool. @@ -25,13 +24,13 @@ import dotty.tools.dotc.core.Contexts._ * * - [](package.DottyDokkaPlugin) is our class that Dokka calls back and which * actually generates the documentation. - * - [](package.DottyDokkaConfig) is our config for Dokka. + * - [](package.DocContext) is our config for Dokka */ object Main: def main(args: Array[String]): Unit = try // We should create our own context here... - val reporter = Scala3doc.run(args)(using (new ContextBase).initialCtx) + val reporter = Scala3doc.run(args, (new ContextBase).initialCtx) // Sometimes jvm is hanging, so we want to be sure that we force shout down the jvm sys.exit(if reporter.hasErrors then 1 else 0) catch diff --git a/scala3doc/src/dotty/dokka/Scala3doc.scala b/scala3doc/src/dotty/dokka/Scala3doc.scala index ab6d5d48cfdc..df978a316a5a 100644 --- a/scala3doc/src/dotty/dokka/Scala3doc.scala +++ b/scala3doc/src/dotty/dokka/Scala3doc.scala @@ -13,10 +13,10 @@ import java.nio.file.Files import dotty.tools.dotc.config.Settings._ import dotty.tools.dotc.config.CommonScalaSettings -import dotty.tools.dotc.report import dotty.tools.dotc.reporting.Reporter -class Scala3DocDokkaLogger(using DocContext) extends DokkaLogger: + +class Scala3DocDokkaLogger(using CompilerContext) extends DokkaLogger: def debug(msg: String): Unit = report.debuglog(msg) // We do not want errors from dokka (that are) not critical to fail our runs @@ -67,8 +67,9 @@ object Scala3doc: revision: Option[String] = None ) - def run(args: Array[String])(using DocContext): Reporter = - val parsedArgs = Scala3docArgs.extract(args.toList) + def run(args: Array[String], rootContext: CompilerContext): Reporter = + val (parsedArgs, ctx) = Scala3docArgs.extract(args.toList, rootContext) + given CompilerContext = ctx def listTastyFiles(f: File): Seq[File] = val (files, dirs) = Option(f.listFiles()).toArray.flatten.partition(_.isFile) @@ -77,8 +78,7 @@ object Scala3doc: ) val tastyFiles = parsedArgs.tastyFiles ++ parsedArgs.tastyDirs.flatMap(listTastyFiles) - val reporter = summon[DocContext].reporter - if !reporter.hasErrors then + if !ctx.reporter.hasErrors then val updatedArgs = parsedArgs.copy(tastyDirs = Nil, tastyFiles = tastyFiles) if (parsedArgs.output.exists()) IO.delete(parsedArgs.output) @@ -86,9 +86,11 @@ object Scala3doc: run(updatedArgs) report.inform("Done") else report.error("Failure") - reporter + ctx.reporter + - private [dokka] def run(args: Args)(using DocContext) = - new DokkaGenerator(new DottyDokkaConfig(args, summon[DocContext]), new Scala3DocDokkaLogger).generate() + private [dokka] def run(args: Args)(using ctx: CompilerContext) = + val docContext = new DocContext(args, ctx) + new DokkaGenerator(docContext, docContext.logger).generate() diff --git a/scala3doc/src/dotty/dokka/Scala3docArgs.scala b/scala3doc/src/dotty/dokka/Scala3docArgs.scala index 2d5043d264c8..0951e845ac4f 100644 --- a/scala3doc/src/dotty/dokka/Scala3docArgs.scala +++ b/scala3doc/src/dotty/dokka/Scala3docArgs.scala @@ -13,8 +13,6 @@ import java.nio.file.Files import dotty.tools.dotc.config.Settings._ import dotty.tools.dotc.config.CommonScalaSettings -import dotty.tools.dotc.report -import dotty.tools.dotc.core.Contexts._ import dotty.dokka.Scala3doc._ class Scala3docArgs extends SettingGroup with CommonScalaSettings: @@ -36,17 +34,17 @@ class Scala3docArgs extends SettingGroup with CommonScalaSettings: val revision: Setting[String] = StringSetting("-revision", "revision", "Revision (branch or ref) used to build project project", "") + def scala3docSpecificSettings: Set[Setting[_]] = Set(sourceLinks, syntax, revision) + object Scala3docArgs: - def extract(args: List[String])(using Context) = + def extract(args: List[String], rootCtx: CompilerContext):(Scala3doc.Args, CompilerContext) = val inst = new Scala3docArgs import inst._ val initialSummary = ArgsSummary(defaultState, args, errors = Nil, warnings = Nil) val summary = processArguments(initialSummary, processAll = true, skipped = Nil) - - summary.warnings.foreach(report.warning(_)) - summary.errors.foreach(report.error(_)) + val newContext = rootCtx.fresh extension[T](arg: Setting[T]): def get = arg.valueIn(summary.sstate) @@ -55,6 +53,19 @@ object Scala3docArgs: def nonDefault = if arg.get == arg.default then None else Some(arg.get) + def setInGlobal[T](s: Setting[T]) = + s.nonDefault.foreach { newValue => + newContext.settings.allSettings.find(_ == s).fold( + report.warning(s"Unable to set ${s.name} in global context") + )(s => newContext.setSetting(s.asInstanceOf[Setting[T]], newValue)) + } + + allSettings.filterNot(scala3docSpecificSettings.contains).foreach(setInGlobal) + + given CompilerContext = newContext + summary.warnings.foreach(report.warning(_)) + summary.errors.foreach(report.error(_)) + def parseTastyRoots(roots: String) = roots.split(File.pathSeparatorChar).toList.map(new File(_)) @@ -93,7 +104,7 @@ object Scala3docArgs: report.inform( s"Generating documenation $printableProjectName in $destFile") - Args( + val docArgs = Args( projectName.withDefault("root"), dirs, validFiles, @@ -105,4 +116,5 @@ object Scala3docArgs: parseSyntax, sourceLinks.nonDefault.fold(Nil)(_.split(",").toList), revision.nonDefault - ) \ No newline at end of file + ) + (docArgs, newContext) \ No newline at end of file diff --git a/scala3doc/src/dotty/dokka/ScalaModuleCreator.scala b/scala3doc/src/dotty/dokka/ScalaModuleCreator.scala index 74e29af1569d..031d756eca00 100644 --- a/scala3doc/src/dotty/dokka/ScalaModuleCreator.scala +++ b/scala3doc/src/dotty/dokka/ScalaModuleCreator.scala @@ -13,27 +13,21 @@ import org.jetbrains.dokka.model._ import org.jetbrains.dokka.base.parsers.MarkdownParser import collection.JavaConverters._ import kotlin.coroutines.Continuation -import dotty.tools.dotc.core.Contexts._ -class ScalaModuleProvider(using DocContext) extends SourceToDocumentableTranslator: +class ScalaModuleProvider(using ctx: DocContext) extends SourceToDocumentableTranslator: override def invoke(sourceSet: DokkaSourceSet, cxt: DokkaContext, unused: Continuation[? >: DModule]) = - cxt.getConfiguration match - case dottyConfig: DottyDokkaConfig => - val parser = new MarkdownParser(_ => null) - val result = DokkaTastyInspector(sourceSet, parser, dottyConfig).result() + val result = DokkaTastyInspector(new MarkdownParser(_ => null)).result() - def flattenMember(m: Member): Seq[(DRI, Member)] = (m.dri -> m) +: m.allMembers.flatMap(flattenMember) + def flattenMember(m: Member): Seq[(DRI, Member)] = (m.dri -> m) +: m.allMembers.flatMap(flattenMember) - new DModule( - sourceSet.getDisplayName, - result.asJava, - JMap(), - null, - sourceSet.toSet, - PropertyContainer.Companion.empty() plus ModuleExtension(result.flatMap(flattenMember).toMap) - ) - case _ => - ??? + new DModule( + sourceSet.getDisplayName, + result.asJava, + JMap(), + null, + sourceSet.toSet, + PropertyContainer.Companion.empty() plus ModuleExtension(result.flatMap(flattenMember).toMap) + ) object EmptyModuleProvider extends SourceToDocumentableTranslator: override def invoke(sourceSet: DokkaSourceSet, cxt: DokkaContext, unused: Continuation[? >: DModule]) = diff --git a/scala3doc/src/dotty/dokka/SourceLinks.scala b/scala3doc/src/dotty/dokka/SourceLinks.scala index d64395737ac4..7dd8cadc9bac 100644 --- a/scala3doc/src/dotty/dokka/SourceLinks.scala +++ b/scala3doc/src/dotty/dokka/SourceLinks.scala @@ -4,6 +4,7 @@ import java.nio.file.Path import java.nio.file.Paths import liqp.Template import dotty.dokka.model.api._ +import dotty.tools.dotc.core.Contexts.Context case class SourceLink(val path: Option[Path], val urlTemplate: Template) @@ -113,7 +114,11 @@ object SourceLinks: | |Template can defined only by subset of sources defined by path prefix represented by ``""".stripMargin - def load(configs: Seq[String], revision: Option[String], projectRoot: Path): SourceLinks = + def load( + configs: Seq[String], + revision: Option[String], + projectRoot: Path)( + using Context): SourceLinks = // TODO ... val mappings = configs.map(str => str -> SourceLink.parse(str, revision)) @@ -122,7 +127,7 @@ object SourceLinks: s"'$template': $message" }.mkString("\n") - if errors.nonEmpty then println( + if errors.nonEmpty then report.warning( s"""Following templates has invalid format: |$errors | @@ -132,10 +137,10 @@ object SourceLinks: SourceLinks(mappings.collect {case (_, Right(link)) => link}, projectRoot) - def load(args: Scala3doc.Args): SourceLinks = + def load(using ctx: DocContext): SourceLinks = load( - args.sourceLinks, - args.revision, + ctx.args.sourceLinks, + ctx.args.revision, // TODO (https://github.com/lampepfl/scala3doc/issues/240): configure source root Paths.get("").toAbsolutePath ) \ No newline at end of file diff --git a/scala3doc/src/dotty/dokka/compat.scala b/scala3doc/src/dotty/dokka/compat.scala index f68476cb631c..8e0fde200ac9 100644 --- a/scala3doc/src/dotty/dokka/compat.scala +++ b/scala3doc/src/dotty/dokka/compat.scala @@ -29,6 +29,7 @@ type JHashMap[K, V] = java.util.HashMap[K, V] type JMapEntry[K, V] = java.util.Map.Entry[K, V] type DRI = org.jetbrains.dokka.links.DRI +val topLevelDri = org.jetbrains.dokka.links.DRI.Companion.getTopLevel type SourceSetWrapper = DokkaConfiguration$DokkaSourceSet type DokkaSourceSet = DokkaConfiguration.DokkaSourceSet diff --git a/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala b/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala index 8f4fdd6d5af8..604f27c5f0dc 100644 --- a/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala +++ b/scala3doc/src/dotty/dokka/preprocessors/ScalaResourceInstaller.scala @@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import dotty.dokka.translators.FilterAttributes import java.nio.file.Paths -class ScalaResourceInstaller(args: Scala3doc.Args) extends PageTransformer: +class ScalaResourceInstaller(using ctx: DocContext) extends PageTransformer: private def dottyRes(resourceName: String) = new RendererSpecificResourcePage(resourceName, java.util.ArrayList(), RenderingStrategy$Copy(s"/dotty_res/$resourceName")) @@ -23,7 +23,7 @@ class ScalaResourceInstaller(args: Scala3doc.Args) extends PageTransformer: new RendererSpecificResourcePage("scripts/data.js", java.util.ArrayList(), RenderingStrategy$Write(s"var scala3DocData = $str")) - private def projectLogo = args.projectLogo.toSeq.map { path => + private def projectLogo = ctx.args.projectLogo.toSeq.map { path => val fileName = Paths.get(path).getFileName() val strategy = new RenderingStrategy$Copy(path) new RendererSpecificResourcePage(s"project-logo/$fileName", JList(), strategy) diff --git a/scala3doc/src/dotty/dokka/site/LoadedTemplate.scala b/scala3doc/src/dotty/dokka/site/LoadedTemplate.scala index 163034ab75b6..c9f7fa289047 100644 --- a/scala3doc/src/dotty/dokka/site/LoadedTemplate.scala +++ b/scala3doc/src/dotty/dokka/site/LoadedTemplate.scala @@ -17,7 +17,10 @@ case class LazyEntry(getKey: String, value: () => String) extends JMapEntry[Stri lazy val getValue: Object = value() def setValue(x$0: Object): Object = ??? -case class LoadedTemplate(templateFile: TemplateFile, children: List[LoadedTemplate], file: File): +case class LoadedTemplate( + templateFile: TemplateFile, + children: List[LoadedTemplate], + file: File): private def brief(ctx: StaticSiteContext): String = try @@ -25,9 +28,8 @@ case class LoadedTemplate(templateFile: TemplateFile, children: List[LoadedTempl Option(code.select("p").first()).fold("...")(_.outerHtml()) catch case e: Throwable => - // TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling - println(s"[ERROR] Unable to process brief for ${templateFile.file}") - e.printStackTrace() + val msg = s"[ERROR] Unable to process brief for ${templateFile.file}" + report.error(msg, templateFile.file, e)(using ctx.outerCtx) "..." def lazyTemplateProperties(ctx: StaticSiteContext): JMap[String, Object] = new java.util.AbstractMap[String, Object](): diff --git a/scala3doc/src/dotty/dokka/site/NavigationCreator.scala b/scala3doc/src/dotty/dokka/site/NavigationCreator.scala new file mode 100644 index 000000000000..2207c59993bf --- /dev/null +++ b/scala3doc/src/dotty/dokka/site/NavigationCreator.scala @@ -0,0 +1,72 @@ +package dotty.dokka +package site + +import org.jetbrains.dokka.base.renderers.html.{NavigationNode, NavigationPage} +import org.jetbrains.dokka.model.DPackage +import org.jetbrains.dokka.model.DModule +import org.jetbrains.dokka.pages._ +import org.jetbrains.dokka.transformers.pages.PageTransformer + +import scala.collection.JavaConverters._ + +class NavigationCreator(using ctx: DocContext) extends PageTransformer: + + private def processApiPages(pages: List[PageNode]): JList[NavigationNode] = + def flatMapPackages(pn: PageNode): List[NavigationNode] = + def processChildren = pn.getChildren.asScala.flatMap(flatMapPackages).toList + pn match + case cp: ContentPage => cp.getDocumentable match + case null => + processChildren + // Left over package from dokka + case p: DPackage if p.getName == "" && p.getChildren.isEmpty => + Nil + case p: DPackage => + val ss = p.getSourceSets.asScala.toSet.toDisplay + List(new NavigationNode(p.getName, p.getDri, ss, JList())) ++ processChildren + case _: DModule => + processChildren + case _ => + Nil + case _ => + Nil + + pages.flatMap(flatMapPackages).sortBy(_.getName).asJava + + private def processStaticPages(input: PageNode)(staticSiteContext: StaticSiteContext) = + def toNavigationNode(page: StaticPageNode): NavigationNode = NavigationNode( + page.title(), + page.getDri.asScala.head, + ctx.displaySourceSets, + page.getChildren.asScala + .collect { case p: StaticPageNode => toNavigationNode(p)}.asJava + ) + + def singleContentPage(p: PageNode) = + p.getChildren.asScala.collectFirst { case c: ContentPage => c }.get + val pageRoot = singleContentPage(input) + val docsRoot = + if !pageRoot.getDri.contains(topLevelDri) then pageRoot + else singleContentPage(pageRoot) + val apiPages = docsRoot.getChildren.asScala.filterNot(_.isInstanceOf[StaticPageNode]) + val staticPages = staticSiteContext.mainPages.map(toNavigationNode).toList.asJava + val apiNodes = processApiPages(apiPages.toList) + staticPages ++ + JList(new NavigationNode("API", apiPageDRI, ctx.displaySourceSets, apiNodes)) + + private def emptyNavigationJson = + val strategy = new RenderingStrategy.Write("[]") + new RendererSpecificResourcePage("scripts/navigation-pane.json", JList(), strategy) + + final override def invoke(input: RootPageNode): RootPageNode = + def defaultApiPages = processApiPages(input.getChildren.asScala.toList) + val nodes = ctx.staticSiteContext.fold(defaultApiPages)(processStaticPages(input)) + + val navigationPage = new NavigationPage(new NavigationNode( + ctx.args.name, + ctx.staticSiteContext.fold(topLevelDri)(_ => docsRootDRI), + ctx.displaySourceSets, + nodes + )) + val newChildren = input.getChildren ++ JList(emptyNavigationJson, navigationPage) + input.modified(input.getName, newChildren) \ No newline at end of file diff --git a/scala3doc/src/dotty/dokka/site/SitePagesCreator.scala b/scala3doc/src/dotty/dokka/site/SitePagesCreator.scala new file mode 100644 index 000000000000..132c73730398 --- /dev/null +++ b/scala3doc/src/dotty/dokka/site/SitePagesCreator.scala @@ -0,0 +1,62 @@ +package dotty.dokka +package site + +import java.io.File +import java.nio.file.Files +import java.nio.file.FileVisitOption + +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.pages._ + +import scala.collection.JavaConverters._ + +class SitePagesCreator(using ctx: DocContext) extends BaseStaticSiteProcessor: + private def mkRootPage(input: RootPageNode, children: List[PageNode]): AContentPage = + input match + case input: ContentPage => + AContentPage( + input.getName, + children.asJava, + input.getContent, + JSet(apiPageDRI), + input.getEmbeddedResources + ) + case _: RendererSpecificRootPage => + children.filter(_.isInstanceOf[RootPageNode]) match + case List(nestedRoot: RootPageNode) => + mkRootPage(nestedRoot, children.filter { _ != nestedRoot } ++ + nestedRoot.getChildren.asScala) + case other => + throw new RuntimeException(s"Expected single nested roor but get: $other") + + case _ => throw new RuntimeException(s"UNSUPPORTED! ${input.getClass.getName}") + + + override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode = + val (contentPage, others) = + input.getChildren.asScala.toList.partition { _.isInstanceOf[ContentPage] } + + val apiRoot = mkRootPage(input, contentPage) + val (indexes, children) = ctx.allPages.partition(f => + f.template.isIndexPage() && f.template.file.toPath.getParent() == ctx.docsPath ) + + if (indexes.size > 1) + val msg = s"ERROR: Multiple index pages for doc found ${indexes.map(_.template.file)}" + report.error(msg) + + def emptyContent = ctx.asContent(Text(), mkDRI(extra = "root_content")).get(0) + + val root = ctx.indexPage().toList.map(_.copy(getDri = JSet(docsRootDRI))) + val docsRoot = AContentPage( + ctx.args.name, + (List(apiRoot.modified("API", apiRoot.getChildren)) ++ children ++ root).asJava, + indexes.headOption.fold(emptyContent)(_.getContent), + JSet(docsDRI), + JList() + ) + + new RendererSpecificRootPage( + apiRoot.getName, + (List(docsRoot) ++ others).asJava, + RenderingStrategy.DoNothing.INSTANCE + ) diff --git a/scala3doc/src/dotty/dokka/site/SiteResourceManager.scala b/scala3doc/src/dotty/dokka/site/SiteResourceManager.scala new file mode 100644 index 000000000000..489de9b3769a --- /dev/null +++ b/scala3doc/src/dotty/dokka/site/SiteResourceManager.scala @@ -0,0 +1,49 @@ +package dotty.dokka +package site + +import java.nio.file.Files +import java.nio.file.FileVisitOption + +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.pages._ + +import scala.collection.JavaConverters._ +import dotty.dokka.model.api._ + +class SiteResourceManager(using ctx: DocContext) extends BaseStaticSiteProcessor: + private def listResources(nodes: Seq[PageNode]): Set[String] = + nodes.flatMap { + case it: AContentPage => + listResources(it.getChildren.asScala.toList) + case it: StaticPageNode => + listResources(it.getChildren.asScala.toList) ++ it.resources() + case _ => Seq.empty + }.toSet + + override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode = + val rootPath = ctx.root.toPath + val imgPath = rootPath.resolve("images") + val images = + if !Files.exists(imgPath) then Nil + else + val allPaths = Files.walk(imgPath, FileVisitOption.FOLLOW_LINKS) + val files = allPaths.filter(Files.isRegularFile(_)).iterator().asScala + files.map(p => rootPath.relativize(p).toString).toList + + val resources = images ++ listResources(input.getChildren.asScala.toList) + + val resourcePages = resources.map { path => + val strategy = new RenderingStrategy.Copy(rootPath.resolve(path).toString) + new RendererSpecificResourcePage(path, JList(), strategy) + } + + val modified = input.transformContentPagesTree { + case it: StaticPageNode => + it.copy(getEmbeddedResources = + if it.template.hasFrame then it.getEmbeddedResources ++ it.resources().asJava + else it.resources().asJava + ) + case it => it + } + val newChildren = (resourcePages ++ modified.getChildren.asScala).asJava + modified.modified(modified.getName, newChildren) \ No newline at end of file diff --git a/scala3doc/src/dotty/dokka/site/StaticSiteContext.scala b/scala3doc/src/dotty/dokka/site/StaticSiteContext.scala index cd42f0a80c7d..630142fed440 100644 --- a/scala3doc/src/dotty/dokka/site/StaticSiteContext.scala +++ b/scala3doc/src/dotty/dokka/site/StaticSiteContext.scala @@ -20,14 +20,20 @@ import util.Try import scala.collection.JavaConverters._ -class StaticSiteContext(val root: File, sourceSets: Set[SourceSetWrapper], val args: Scala3doc.Args, val sourceLinks: SourceLinks): +class StaticSiteContext( + val root: File, + sourceSets: Set[SourceSetWrapper], + val args: Scala3doc.Args, val sourceLinks: SourceLinks)(using val outerCtx: CompilerContext): var memberLinkResolver: String => Option[DRI] = _ => None - def indexPage():Option[StaticPageNode] = + def indexPage(): Option[StaticPageNode] = val files = List(new File(root, "index.html"), new File(root, "index.md")).filter { _.exists() } - // TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling - if (files.size > 1) println(s"ERROR: Multiple root index pages found: ${files.map(_.getAbsolutePath)}") + + if files.size > 1 then + val msg = s"ERROR: Multiple root index pages found: ${files.map(_.getAbsolutePath)}" + report.error(msg) + files.flatMap(loadTemplate(_, isBlog = false)).headOption.map(templateToPage) lazy val layouts: Map[String, TemplateFile] = @@ -102,8 +108,9 @@ class StaticSiteContext(val root: File, sourceSets: Set[SourceSetWrapper], val a val processedTemplate = // Set provided name as arg in page for `docs` if from.getParentFile.toPath == docsPath && templateFile.isIndexPage() then - // TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling - if templateFile.title != "index" then println(s"[WARN] title in $from will be overriden") + if templateFile.title != "index" then + report.warn("Property `title` will be overriden by project name", from) + templateFile.copy(title = args.name) else templateFile diff --git a/scala3doc/src/dotty/dokka/site/StaticSiteLocationProvider.scala b/scala3doc/src/dotty/dokka/site/StaticSiteLocationProvider.scala index cfa1b9c6861e..1d5cdd68c642 100644 --- a/scala3doc/src/dotty/dokka/site/StaticSiteLocationProvider.scala +++ b/scala3doc/src/dotty/dokka/site/StaticSiteLocationProvider.scala @@ -7,30 +7,31 @@ import org.jetbrains.dokka.base.resolvers.local.LocationProviderFactory import org.jetbrains.dokka.pages.ContentPage import org.jetbrains.dokka.pages.PageNode import org.jetbrains.dokka.pages.RootPageNode +import org.jetbrains.dokka.pages.ModulePage import org.jetbrains.dokka.plugability.DokkaContext import scala.collection.JavaConverters._ import java.nio.file.Paths import java.nio.file.Path -class StaticSiteLocationProviderFactory(private val ctx: DokkaContext) extends LocationProviderFactory: +class StaticSiteLocationProviderFactory(using ctx: DokkaContext) extends LocationProviderFactory: override def getLocationProvider(pageNode: RootPageNode): LocationProvider = - try new StaticSiteLocationProvider(ctx, pageNode) - catch + try new StaticSiteLocationProvider(pageNode) + catch case e: Error => // TODO (https://github.com/lampepfl/scala3doc/issues/238) error handling e.printStackTrace() // We encounter bug in Kotlin coroutines (race) when this method throws exception // In such case we want to return null to trigger NPE in other piece of code to fail properly coroutine context - // Making generated DRIs not-unique will reproduce this behavior + // Making generated DRIs not-unique will reproduce this behavior null -class StaticSiteLocationProvider(ctx: DokkaContext, pageNode: RootPageNode) +class StaticSiteLocationProvider(pageNode: RootPageNode)(using ctx: DokkaContext) extends DokkaLocationProvider(pageNode, ctx, ".html"): private def updatePageEntry(page: PageNode, jpath: JList[String]): JList[String] = page match case page: StaticPageNode => - ctx.siteContext.fold(jpath) { context => + summon[DocContext].staticSiteContext.fold(jpath) { context => val rawFilePath = context.root.toPath.relativize(page.template.file.toPath) val pageName = page.template.file.getName val dotIndex = pageName.lastIndexOf('.') @@ -41,7 +42,8 @@ class StaticSiteLocationProvider(ctx: DokkaContext, pageNode: RootPageNode) case regex(year, month, day, name) => rawFilePath.getParent.resolveSibling(Paths.get(year, month, day, name)) case _ => - println(s"Blog file at path: $rawFilePath doesn't match desired format.") + val msg = s"Relative path for blog: $rawFilePath doesn't match `yyy-mm-dd-name.md` format." + report.warn(msg, page.template.file) rawFilePath.resolveSibling(pageName.substring(0, dotIndex)) } blogPostPath.iterator.asScala.map(_.toString).toList.asJava @@ -60,7 +62,7 @@ class StaticSiteLocationProvider(ctx: DokkaContext, pageNode: RootPageNode) case _ if jpath.size() > 1 && jpath.get(0) == "--root--" && jpath.get(1) == "-a-p-i" => (List("api") ++ jpath.asScala.drop(2)).asJava - case _: org.jetbrains.dokka.pages.ModulePage if ctx.siteContext.isEmpty => + case _: ModulePage if summon[DocContext].staticSiteContext.isEmpty => JList("index") case _ => jpath diff --git a/scala3doc/src/dotty/dokka/site/common.scala b/scala3doc/src/dotty/dokka/site/common.scala index 5fa9b8493f5a..70a5c9ca955f 100644 --- a/scala3doc/src/dotty/dokka/site/common.scala +++ b/scala3doc/src/dotty/dokka/site/common.scala @@ -14,7 +14,11 @@ import com.vladsch.flexmark.ext.yaml.front.matter.{AbstractYamlFrontMatterVisito import com.vladsch.flexmark.parser.{Parser, ParserEmulationProfile} import com.vladsch.flexmark.util.options.{DataHolder, MutableDataSet} import com.vladsch.flexmark.ext.wikilink.WikiLinkExtension + import org.jetbrains.dokka.model.doc.Text +import org.jetbrains.dokka.model.Documentable +import org.jetbrains.dokka.transformers.pages.PageTransformer +import org.jetbrains.dokka.pages._ import scala.collection.JavaConverters._ @@ -112,3 +116,31 @@ def loadTemplateFile(file: File): TemplateFile = { } def Text(msg: String = "") = new Text(msg, JList(), JMap()) + +abstract class BaseStaticSiteProcessor(using ctx: DocContext) + extends PageTransformer: + final override def invoke(input: RootPageNode): RootPageNode = + ctx.staticSiteContext.fold(input)(transform(input, _)) + + protected def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode + +case class AContentPage( + override val getName: String, + override val getChildren: JList[PageNode], + override val getContent: ContentNode, + override val getDri: JSet[DRI], + override val getEmbeddedResources: JList[String] = JList(), +) extends ContentPage: + override def getDocumentable: Documentable = null + + override def modified( + name: String, + content: ContentNode, + dri: JSet[DRI], + embeddedResources: JList[String], + children: JList[_ <: PageNode] + ): ContentPage = + copy(name, children.asInstanceOf[JList[PageNode]], content, dri, embeddedResources) + + override def modified(name: String, children: JList[_ <: PageNode]): PageNode = + copy(name, getChildren = children.asInstanceOf[JList[PageNode]]) diff --git a/scala3doc/src/dotty/dokka/site/processors.scala b/scala3doc/src/dotty/dokka/site/processors.scala deleted file mode 100644 index 19c1720b6b09..000000000000 --- a/scala3doc/src/dotty/dokka/site/processors.scala +++ /dev/null @@ -1,160 +0,0 @@ -package dotty.dokka -package site - -import java.io.File -import java.nio.file.Files -import java.nio.file.FileVisitOption - -import org.jetbrains.dokka.base.renderers.html.{NavigationNode, NavigationPage} -import org.jetbrains.dokka.model.Documentable -import org.jetbrains.dokka.model.DPackage -import org.jetbrains.dokka.model.DModule -import org.jetbrains.dokka.pages._ -import org.jetbrains.dokka.transformers.pages.PageTransformer - -import scala.collection.JavaConverters._ -import dotty.dokka.model.api._ - -abstract class BaseStaticSiteProcessor(staticSiteContext: Option[StaticSiteContext]) extends PageTransformer: - final override def invoke(input: RootPageNode): RootPageNode = staticSiteContext.fold(input)(transform(input, _)) - - protected def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode - -class SiteResourceManager(ctx: Option[StaticSiteContext]) extends BaseStaticSiteProcessor(ctx): - private def listResources(nodes: Seq[PageNode]): Set[String] = - nodes.flatMap { - case it: StaticPageNode => listResources(it.getChildren.asScala.toList) ++ it.resources() - case _ => Seq.empty - }.toSet - - override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode = - val rootPath = ctx.root.toPath - val imgPath = rootPath.resolve("images") - val images = - if !Files.exists(imgPath) then Nil - else - val allPaths = Files.walk(imgPath, FileVisitOption.FOLLOW_LINKS) - val files = allPaths.filter(Files.isRegularFile(_)).iterator().asScala - files.map(p => rootPath.relativize(p).toString).toList - - val resources = images ++ listResources(input.getChildren.asScala.toList) - val resourcePages = resources.map { path => - val strategy = new RenderingStrategy.Copy(rootPath.resolve(path).toString) - new RendererSpecificResourcePage(path, JList(), strategy) - } - - val modified = input.transformContentPagesTree { - case it: StaticPageNode => - it.copy(getEmbeddedResources = - if it.template.hasFrame then it.getEmbeddedResources ++ it.resources().asJava - else it.resources().asJava - ) - case it => it - } - modified.modified(modified.getName, (resourcePages ++ modified.getChildren.asScala).asJava) - -case class AContentPage( - override val getName: String, - override val getChildren: JList[PageNode], - override val getContent: ContentNode, - override val getDri: JSet[DRI], - override val getEmbeddedResources: JList[String] = JList(), -) extends ContentPage: - override def getDocumentable: Documentable = null - - override def modified( - name: String, - content: ContentNode, - dri: JSet[DRI], - embeddedResources: JList[String], - children: JList[_ <: PageNode] - ): ContentPage = copy(name, children.asInstanceOf[JList[PageNode]], content, dri, embeddedResources) - - override def modified(name: String, children: JList[_ <: PageNode]): PageNode = - copy(name, getChildren = children.asInstanceOf[JList[PageNode]]) - -class SitePagesCreator(ctx: Option[StaticSiteContext]) extends BaseStaticSiteProcessor(ctx): - private def processRootPage(input: RootPageNode, children: List[PageNode] = Nil): AContentPage = input match - case input: ContentPage => - AContentPage( - input.getName, - children.asJava, - input.getContent, - JSet(apiPageDRI), - input.getEmbeddedResources - ) - case _: RendererSpecificRootPage => - children.filter(_.isInstanceOf[RootPageNode]) match - case List(nestedRoot: RootPageNode) => - processRootPage(nestedRoot, children.filter { _ != nestedRoot } ++ nestedRoot.getChildren.asScala) - case other => - throw new RuntimeException(s"Expected single nested roor but get: $other") - - case _ => throw new RuntimeException(s"UNSUPPORTED! ${input.getClass.getName}") - - override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode = - val (contentPage, others) = input.getChildren.asScala.toList.partition { _.isInstanceOf[ContentPage] } - val modifiedModuleRoot = processRootPage(input, contentPage) - val (indexes, children) = ctx.allPages.partition(f => - f.template.isIndexPage() && f.template.file.toPath.getParent() == ctx.docsPath ) - // TODO (https://github.com/lampepfl/scala3doc/issues/238): provide proper error handling - if (indexes.size > 1) println(s"ERROR: Multiple index pages found ${indexes.map(_.template.file)}") - - val rootContent = indexes.headOption.fold(ctx.asContent(Text(), mkDRI(extra = "root_content")).get(0))(_.getContent) - - val root = AContentPage( - ctx.args.name, - (List(modifiedModuleRoot.modified("API", modifiedModuleRoot.getChildren)) ++ children).asJava, - rootContent, - JSet(docsDRI), - JList() - ) - - new RendererSpecificRootPage( - modifiedModuleRoot.getName, - (List(root) ++ others).asJava, - RenderingStrategy.DoNothing.INSTANCE - ) - -class RootIndexPageCreator(ctx: Option[StaticSiteContext]) extends BaseStaticSiteProcessor(ctx): - override def transform(input: RootPageNode, ctx: StaticSiteContext): RootPageNode = - ctx.indexPage().fold(input){ it => - val (contentNodes, nonContent) = input.getChildren.asScala.partition { _.isInstanceOf[ContentNode] } - val (navigations, rest) = nonContent.partition { _.isInstanceOf[NavigationPage] } - val modifiedNavigation = navigations.map { it => - val sourceSets = it.asInstanceOf[NavigationPage].getRoot.getSourceSets - def flatMapPackages(pn: PageNode): List[NavigationNode] = - def processChildren = pn.getChildren.asScala.flatMap(flatMapPackages).toList - pn match - case cp: ContentPage => cp.getDocumentable match - case null => - processChildren - case p: DPackage => - List(new NavigationNode(p.getName, p.getDri, sourceSets, JList())) ++ processChildren - case other => - Nil - case _ => - Nil - - val packagesNavigation = input.getChildren.asScala.flatMap(flatMapPackages).sortBy(_.getName) - val api = new NavigationNode("API", apiPageDRI, sourceSets, packagesNavigation.asJava) - - def toNavigationNode(page: StaticPageNode): NavigationNode = NavigationNode( - page.title(), - page.getDri.asScala.head, - sourceSets, - page.getChildren.asScala.collect { case p: StaticPageNode => toNavigationNode(p)}.asJava - ) - - new NavigationPage( - new NavigationNode( - input.getName, - docsRootDRI, - sourceSets, - (ctx.mainPages.map(toNavigationNode) ++ Seq(api)).asJava - ) - ) - } - val newRoot = it.copy(getDri = JSet(docsRootDRI), getChildren = contentNodes.asJava) - input.modified(input.getName, (List(newRoot) ++ rest ++ modifiedNavigation).asJava) - } diff --git a/scala3doc/src/dotty/dokka/tasty/BasicSupport.scala b/scala3doc/src/dotty/dokka/tasty/BasicSupport.scala index 24a27e15f18a..fd4293430c29 100644 --- a/scala3doc/src/dotty/dokka/tasty/BasicSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/BasicSupport.scala @@ -36,7 +36,7 @@ trait BasicSupport: extension (sym: Symbol): def documentation = sym.documentation match case Some(comment) => - Map(sourceSet -> parseComment(comment, sym.tree)) + Map(ctx.sourceSet -> parseComment(comment, sym.tree)) case None => Map.empty diff --git a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala index e40a81c913eb..842aaee1791a 100644 --- a/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/ClassLikeSupport.scala @@ -17,8 +17,8 @@ trait ClassLikeSupport: self: TastyParser => import qctx.reflect._ - private val placeholderVisibility = JMap(sourceSet -> KotlinVisibility.Public.INSTANCE) - private val placeholderModifier = JMap(sourceSet -> KotlinModifier.Empty.INSTANCE) + private val placeholderVisibility = JMap(ctx.sourceSet -> KotlinVisibility.Public.INSTANCE) + private val placeholderModifier = JMap(ctx.sourceSet -> KotlinModifier.Empty.INSTANCE) private def kindForClasslike(sym: Symbol): Kind = if sym.flags.is(Flags.Object) then Kind.Object @@ -90,7 +90,7 @@ trait ClassLikeSupport: classDef.symbol.documentation.asJava, null, placeholderModifier, - inspector.sourceSet.toSet, + ctx.sourceSet.toSet, /*isExpectActual =*/ false, fullExtra.asInstanceOf[PropertyContainer[DClass]] ) @@ -109,9 +109,9 @@ trait ClassLikeSupport: case dd: DefDef if !dd.symbol.isHiddenByVisibility && !dd.symbol.isSyntheticFunc && dd.symbol.isExtensionMethod => dd.symbol.extendedSymbol.map { extSym => val target = ExtensionTarget( - extSym.symbol.normalizedName, - extSym.tpt.dokkaType.asSignature, - extSym.tpt.symbol.dri, + extSym.symbol.normalizedName, + extSym.tpt.dokkaType.asSignature, + extSym.tpt.symbol.dri, extSym.symbol.pos.start ) parseMethod(dd.symbol, kind = Kind.Extension(target)) @@ -306,7 +306,7 @@ trait ClassLikeSupport: /*generics =*/ genericTypes.map(parseTypeArgument).asJava, /*receiver =*/ null, // Not used /*modifier =*/ placeholderModifier, - sourceSet.toSet, + ctx.sourceSet.toSet, /*isExpectActual =*/ false, PropertyContainer.Companion.empty() plus MethodExtension(paramLists.map(_.size)) @@ -327,7 +327,7 @@ trait ClassLikeSupport: argument.symbol.documentation.asJava, null, argument.tpt.dokkaType, - sourceSet.toSet, + ctx.sourceSet.toSet, PropertyContainer.Companion.empty() .plus(ParameterExtension(isExtendedSymbol, isGrouped)) .plus(MemberExtension.empty.copy(annotations = argument.symbol.getAnnotations())) @@ -345,7 +345,7 @@ trait ClassLikeSupport: argument.symbol.documentation.asJava, null, JList(argument.rhs.dokkaType), - sourceSet.toSet, + ctx.sourceSet.toSet, PropertyContainer.Companion.empty() ) @@ -374,7 +374,7 @@ trait ClassLikeSupport: /*setter =*/ null, /*getter =*/ null, /*modifier =*/ placeholderModifier, - sourceSet.toSet, + ctx.sourceSet.toSet, /*generics =*/ generics.asJava, // TODO /*isExpectActual =*/ false, PropertyContainer.Companion.empty() plus MemberExtension( @@ -405,7 +405,7 @@ trait ClassLikeSupport: /*setter =*/ null, /*getter =*/ null, /*modifier =*/ placeholderModifier, - sourceSet.toSet, + ctx.sourceSet.toSet, /*generics =*/ JList(), /*isExpectActual =*/ false, PropertyContainer.Companion.empty().plus(MemberExtension( diff --git a/scala3doc/src/dotty/dokka/tasty/PackageSupport.scala b/scala3doc/src/dotty/dokka/tasty/PackageSupport.scala index 5ebff3b556f0..8ad677911de9 100644 --- a/scala3doc/src/dotty/dokka/tasty/PackageSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/PackageSupport.scala @@ -25,7 +25,7 @@ trait PackageSupport: JList(), documentation.asJava, null, - sourceSet.toSet, + ctx.sourceSet.toSet, PropertyContainer.Companion.empty() ) } @@ -41,7 +41,7 @@ trait PackageSupport: JList(), pckObj.symbol.documentation.asJava, null, - sourceSet.toSet, + ctx.sourceSet.toSet, PropertyContainer.Companion.empty() .plus(clazz.get(CompositeMemberExtension)) ) diff --git a/scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala b/scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala index 377c471c2ff1..11cc07f3be37 100644 --- a/scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala +++ b/scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala @@ -35,11 +35,12 @@ trait ScaladocSupport { self: TastyParser => preparsed.syntax.headOption match { case Some(commentSetting) => CommentSyntax.parse(commentSetting).getOrElse { - println(s"WARN: not a valid comment syntax: $commentSetting") - println(s"WARN: Defaulting to Markdown syntax.") + val msg = s"not a valid comment syntax: $commentSetting, defaulting to Markdown syntax." + // we should update pos with span from documentation + report.warning(msg, tree.pos) CommentSyntax.default } - case None => self.config.args.defaultSyntax + case None => ctx.args.defaultSyntax } val parser = commentSyntax match { diff --git a/scala3doc/src/dotty/dokka/tasty/SymOps.scala b/scala3doc/src/dotty/dokka/tasty/SymOps.scala index b045d407d7e1..a33b8c4494af 100644 --- a/scala3doc/src/dotty/dokka/tasty/SymOps.scala +++ b/scala3doc/src/dotty/dokka/tasty/SymOps.scala @@ -96,8 +96,8 @@ class SymOps[Q <: Quotes](val q: Q): // TODO #22 make sure that DRIs are unique plus probably reuse semantic db code? def dri: DRI = - if sym == Symbol.noSymbol then emptyDRI - else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri + if sym == Symbol.noSymbol then topLevelDri + else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri else val pointsTo = if (!sym.isTypeDef) PointingToDeclaration.INSTANCE @@ -117,5 +117,3 @@ class SymOps[Q <: Quotes](val q: Q): // For some reason it contains `$$$` instrad of symbol name s"${sym.name}${sym.show}/${sym.signature.resultSig}/[${sym.signature.paramSigs.mkString("/")}]" ) - - private val emptyDRI = DRI.Companion.getTopLevel diff --git a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala index 5537240c0417..7ab56780182c 100644 --- a/scala3doc/src/dotty/dokka/tasty/TastyParser.scala +++ b/scala3doc/src/dotty/dokka/tasty/TastyParser.scala @@ -25,15 +25,12 @@ import scala.util.Try * * Delegates most of the work to [[TastyParser]] [[dotty.dokka.tasty.TastyParser]]. */ -case class DokkaTastyInspector( - sourceSet: SourceSetWrapper, - parser: Parser, - config: DottyDokkaConfig) extends DocTastyInspector: +case class DokkaTastyInspector(parser: Parser)(using ctx: DocContext) extends DocTastyInspector: private val topLevels = Seq.newBuilder[Documentable] def processCompilationUnit(using q: Quotes)(root: q.reflect.Tree): Unit = - val parser = new TastyParser(q, this, config) + val parser = new TastyParser(q, this) def driFor(link: String): Option[DRI] = val symOps = new SymOps[q.type](q) @@ -42,15 +39,15 @@ case class DokkaTastyInspector( MemberLookup.lookupOpt(q, None).map{ case (sym, _) => sym.dri} ) - config.staticSiteContext.foreach(_.memberLinkResolver = driFor) + ctx.staticSiteContext.foreach(_.memberLinkResolver = driFor) topLevels ++= parser.parseRootTree(root.asInstanceOf[parser.qctx.reflect.Tree]) def result(): List[DPackage] = topLevels.clear() - val filePaths = config.args.tastyFiles.map(_.getAbsolutePath).toList - val classpath = config.args.classpath.split(java.io.File.pathSeparator).toList + val filePaths = ctx.args.tastyFiles.map(_.getAbsolutePath).toList + val classpath = ctx.args.classpath.split(java.io.File.pathSeparator).toList - inspectFilesInContext(classpath, filePaths)(using config.docContext) + inspectFilesInContext(classpath, filePaths) val all = topLevels.result() val packages = all @@ -74,7 +71,7 @@ case class DokkaTastyInspector( JList(), f.getDocumentation, null, - sourceSet.toSet, + JSet(ctx.sourceSet), f.getExtra ).withNewMembers(entries.filterNot(_.isInstanceOf[DPackage]).toList).asInstanceOf[DPackage] ) @@ -83,7 +80,7 @@ case class DokkaTastyInspector( }.toList extension (self: DPackage) def mergeWith(other: DPackage): DPackage = - def nodes(p: DPackage): JList[TagWrapper] = p.getDocumentation.get(sourceSet) match + def nodes(p: DPackage): JList[TagWrapper] = p.getDocumentation.get(ctx.sourceSet) match case null => JList[TagWrapper]() case node => node.getChildren @@ -94,9 +91,9 @@ case class DokkaTastyInspector( (self.getProperties.asScala ++ other.getProperties.asScala).asJava, JList(), // WARNING Merging is done before collecting classlikes, if it changes it needs to be refactored JList(), - sourceSet.toMap(DocumentationNode(nodes(self) ++ nodes(other))), + ctx.sourceSet.toMap(DocumentationNode(nodes(self) ++ nodes(other))), null, - sourceSet.toSet, + ctx.sourceSet.toSet, PropertyContainer.Companion.empty() ), self, @@ -104,21 +101,25 @@ case class DokkaTastyInspector( ) /** Parses a single Tasty compilation unit. */ -case class TastyParser(qctx: Quotes, inspector: DokkaTastyInspector, config: DottyDokkaConfig) +case class TastyParser(qctx: Quotes, inspector: DokkaTastyInspector)(using val ctx: DocContext) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer: import qctx.reflect._ - def sourceSet = inspector.sourceSet - - def processTree[T](tree: Tree)(op: => T): Option[T] = try Option(op) catch case e: Throwable => errorMsg(tree, tree.symbol.show, e) - def processTreeOpt[T](tree: Tree)(op: => Option[T]): Option[T] = try op catch case e: Throwable => errorMsg(tree, tree.symbol.show, e) - def processSymbol[T](sym: Symbol)(op: => T): Option[T] = try Option(op) catch case e: Throwable => errorMsg(sym, sym.show, e) - - private def errorMsg[T](a: Any, m: => String, e: Throwable): Option[T] = - val msg = try m catch case e: Throwable => a.toString - println(s"ERROR: tree is faling: $msg") - e.printStackTrace() - throw e + def processTree[T](tree: Tree)(op: => T): Option[T] = try Option(op) catch + case e: Exception => + report.warning(throwableToString(e), tree.pos) + None + def processTreeOpt[T](tree: Tree)(op: => Option[T]): Option[T] = try op catch + case e: Exception => + report.warning(throwableToString(e), tree.pos) + None + + def processSymbol[T](sym: Symbol)(op: => T): Option[T] = try Option(op) catch + case t: Throwable => + try report.warning(throwableToString(t), sym.tree.pos) catch + case _: Throwable => + report.warning(s"Failed to process ${sym.show}:\n${throwableToString(t)}") + None def parseRootTree(root: Tree): Seq[Documentable] = val docs = Seq.newBuilder[Documentable] diff --git a/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala b/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala index 71d49b4a03b9..0a503135ce2c 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaContentBuilder.scala @@ -5,7 +5,6 @@ import org.jetbrains.dokka.base.translators.documentables.{DefaultPageCreator, P import org.jetbrains.dokka.base.signatures.SignatureProvider import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter import org.jetbrains.dokka.transformers.documentation.DocumentableToPageTranslator -import org.jetbrains.dokka.utilities.DokkaLogger import org.jetbrains.dokka.model._ import org.jetbrains.dokka.pages._ import collection.JavaConverters._ @@ -24,9 +23,8 @@ case class DocumentableGroup(name: Option[String | Documentable], documenables: class ScalaPageContentBuilder( val commentsConverter: CommentsToContentConverter, - val signatureProvider: SignatureProvider, - val logger: DokkaLogger -) { + val signatureProvider: SignatureProvider +)(using DocContext) { def contentForDRI( dri: DRI, diff --git a/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala b/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala index 55737a4ff25d..6f2f38b46719 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaPageCreator.scala @@ -26,11 +26,11 @@ type DocBuilder = ScalaPageContentBuilder#ScalaDocumentableContentBuilder class ScalaPageCreator( commentsToContentConverter: CommentsToContentConverter, signatureProvider: SignatureProvider, - sourceLinks: SourceLinks, - val logger: DokkaLogger -) extends DefaultPageCreator(commentsToContentConverter, signatureProvider, logger): +)(using ctx: DocContext) + extends DefaultPageCreator(commentsToContentConverter, signatureProvider, ctx.logger): - private val contentBuilder = ScalaPageContentBuilder(commentsToContentConverter, signatureProvider, logger) + private val contentBuilder = + ScalaPageContentBuilder(commentsToContentConverter, signatureProvider) override def pageForModule(m: DModule): ModulePageNode = super.pageForModule(m) @@ -316,7 +316,7 @@ class ScalaPageCreator( } val withExtensionInformation = d.kind match { - case Kind.Extension(on) => + case Kind.Extension(on) => val sourceSets = d.getSourceSets.asScala.toSet withCompanion.cell(sourceSets = sourceSets)(_.text("Extension")) .cell(sourceSets = sourceSets)(_.text(s"This function is an extension on (${on.name}: ").inlineSignature(d, on.signature).text(")")) @@ -326,7 +326,7 @@ class ScalaPageCreator( d match case null => withExtensionInformation case m: Member => - sourceLinks.pathTo(m).fold(withCompanion){ link => + ctx.sourceLinks.pathTo(m).fold(withCompanion){ link => val sourceSets = m.getSourceSets.asScala.toSet withExtensionInformation.cell(sourceSets = sourceSets)(_.text("Source")) .cell(sourceSets = sourceSets)(_.resolvedLink("(source)", link)) diff --git a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala index 83c614ab1b4b..30571bcd31a1 100644 --- a/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala +++ b/scala3doc/src/dotty/dokka/translators/ScalaSignatureProvider.scala @@ -15,10 +15,10 @@ import kotlin.jvm.functions.Function2 import dotty.dokka.model.api.{Kind, _} -class ScalaSignatureProvider(contentConverter: CommentsToContentConverter, logger: DokkaLogger) extends SignatureProvider with ScalaSignatureUtils: - private val default = new KotlinSignatureProvider(contentConverter, logger) +class ScalaSignatureProvider(contentConverter: CommentsToContentConverter)(using ctx: DocContext) + extends SignatureProvider with ScalaSignatureUtils: private val styles = Set(TextStyle.Monospace).asInstanceOf[Set[Style]] - private val contentBuilder = new ScalaPageContentBuilder(contentConverter, this, logger) + private val contentBuilder = new ScalaPageContentBuilder(contentConverter, this) private def signatureContent(d: Documentable)( func: ScalaPageContentBuilder#ScalaDocumentableContentBuilder => ScalaPageContentBuilder#ScalaDocumentableContentBuilder @@ -30,7 +30,7 @@ class ScalaSignatureProvider(contentConverter: CommentsToContentConverter, logge def driLink(text: String, dri: DRI): SignatureBuilder = ContentNodeBuilder(builder.driLink(text, dri)) } - def signature(d: Member, s: Signature) = signatureContent(d){ builder => + def signature(d: Member, s: Signature) = signatureContent(d){ builder => val res = ContentNodeBuilder(builder).signature(s) res.asInstanceOf[ContentNodeBuilder].builder } diff --git a/scala3doc/src/dotty/renderers/ScalaHtmlRenderer.scala b/scala3doc/src/dotty/renderers/ScalaHtmlRenderer.scala index 45415d448ae8..6d9915d66f4a 100644 --- a/scala3doc/src/dotty/renderers/ScalaHtmlRenderer.scala +++ b/scala3doc/src/dotty/renderers/ScalaHtmlRenderer.scala @@ -42,7 +42,8 @@ class SignatureRenderer(pageContext: ContentPage, sourceSetRestriciton: JSet[Dis def renderElement(e: String | (String, DRI) | Link) = renderElementWith(e) -class ScalaHtmlRenderer(ctx: DokkaContext, args: Scala3doc.Args) extends HtmlRenderer(ctx) { +class ScalaHtmlRenderer(using ctx: DokkaContext) extends HtmlRenderer(ctx) { + val args = summon[DocContext].args // TODO #239 val hackScalaSearchbarDataInstaller: SearchbarDataInstaller = { @@ -264,7 +265,7 @@ class ScalaHtmlRenderer(ctx: DokkaContext, args: Scala3doc.Args) extends HtmlRen .flatMap(dri => Option(getLocationProvider.resolve(dri, sourceSets, page))) .map(_ + prefix) .getOrElse { - println(s"[WARN] ${prc.template.file}: Unable to resolve link '$str'") + report.warn(s"Unable to resolve link '$str'", prc.template.file) str } diff --git a/scala3doc/src/dotty/tools/dottydoc/Main.scala b/scala3doc/src/dotty/tools/dottydoc/Main.scala index 069ca05f08a7..3a6089f5353c 100644 --- a/scala3doc/src/dotty/tools/dottydoc/Main.scala +++ b/scala3doc/src/dotty/tools/dottydoc/Main.scala @@ -22,4 +22,4 @@ object Main extends Driver: * how they're split). */ override def process(args: Array[String], rootCtx: Context): Reporter = - dotty.dokka.Scala3doc.run(args)(using rootCtx) + dotty.dokka.Scala3doc.run(args, rootCtx) diff --git a/scala3doc/test/dotty/dokka/RaportingTest.scala b/scala3doc/test/dotty/dokka/RaportingTest.scala index 99d31f6f5c5b..df9bad455696 100644 --- a/scala3doc/test/dotty/dokka/RaportingTest.scala +++ b/scala3doc/test/dotty/dokka/RaportingTest.scala @@ -8,24 +8,19 @@ import org.junit.Assert import org.jsoup.Jsoup import org.jsoup.nodes.Document import java.nio.charset.Charset -import dotty.tools.dotc.core.Contexts._ class ReportingTest: import Scala3doc.Args private def checkReportedDiagnostics( newArgs: Args => Args = identity, - ctx: Context = testContext)( + ctx: CompilerContext = testContext)( op: ReportedDiagnostics => Unit): Unit = val dest = Files.createTempDirectory("test-doc") try - val args = Args( - name = "Test Project Name", - output = dest.toFile, - tastyFiles = tastyFiles("nested") // Random package - ) - Scala3doc.run(newArgs(args))(using ctx) + // We are using random package + Scala3doc.run(newArgs(testArgs(tastyFiles("nested"), dest.toFile)))(using ctx) op(ctx.reportedDiagnostics) finally IO.delete(dest.toFile) diff --git a/scala3doc/test/dotty/dokka/ScaladocTest.scala b/scala3doc/test/dotty/dokka/ScaladocTest.scala index f9dc29a2b261..a57b322dbe3f 100644 --- a/scala3doc/test/dotty/dokka/ScaladocTest.scala +++ b/scala3doc/test/dotty/dokka/ScaladocTest.scala @@ -11,7 +11,6 @@ import scala.jdk.CollectionConverters.{ListHasAsScala, SeqHasAsJava} import org.junit.{Test, Rule} import org.junit.rules.{TemporaryFolder, ErrorCollector} import java.io.File -import dotty.tools.dotc.core.Contexts._ abstract class ScaladocTest(val name: String): def assertions: Seq[Assertion] @@ -36,7 +35,7 @@ abstract class ScaladocTest(val name: String): @Test def executeTest = DokkaTestGenerator( - DottyDokkaConfig(args, testContext), + DocContext(args, testContext), TestLogger(new Scala3DocDokkaLogger(using testContext)), assertions.asTestMethods, Nil.asJava diff --git a/scala3doc/test/dotty/dokka/SourceLinksTests.scala b/scala3doc/test/dotty/dokka/SourceLinksTests.scala index 9b72b9053f36..5d99c765ed5b 100644 --- a/scala3doc/test/dotty/dokka/SourceLinksTests.scala +++ b/scala3doc/test/dotty/dokka/SourceLinksTests.scala @@ -64,7 +64,7 @@ class SourceLinksTest: type Args = String | (String, Operation) | (String, Int) | (String, Int, Operation) private def testLink(config: Seq[String], revision: Option[String])(cases: (Args, String | None.type)*): Unit = - val links = SourceLinks.load(config, revision, projectRoot) + val links = SourceLinks.load(config, revision, projectRoot)(using testContext) cases.foreach { case (args, expected) => val res = args match case path: String => links.pathTo(projectRoot.resolve(path)) diff --git a/scala3doc/test/dotty/dokka/linking/DriTest.scala b/scala3doc/test/dotty/dokka/linking/DriTest.scala index fb2c0ac19e9b..a4ec18540263 100644 --- a/scala3doc/test/dotty/dokka/linking/DriTest.scala +++ b/scala3doc/test/dotty/dokka/linking/DriTest.scala @@ -1,8 +1,8 @@ -package dotty.dokka.linking +package dotty.dokka +package linking import scala.jdk.CollectionConverters._ import scala.Function.const -import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.model.DModule import dotty.dokka.model.api._ import dotty.dokka.{ScaladocTest, Assertion} diff --git a/scala3doc/test/dotty/dokka/linking/DriTestCases.scala b/scala3doc/test/dotty/dokka/linking/DriTestCases.scala index 8640374e2810..527415997c4d 100644 --- a/scala3doc/test/dotty/dokka/linking/DriTestCases.scala +++ b/scala3doc/test/dotty/dokka/linking/DriTestCases.scala @@ -1,6 +1,6 @@ -package dotty.dokka.linking +package dotty.dokka +package linking -import org.jetbrains.dokka.links.DRI import org.junit.Ignore class ExtensionTest extends DriTest("extensionDRIs") diff --git a/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala b/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala index f1e532d3f75d..8b6a5ca99a92 100644 --- a/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala +++ b/scala3doc/test/dotty/dokka/site/SiteGeneratationTest.scala @@ -9,7 +9,6 @@ import org.junit.Assert._ import org.jsoup.Jsoup import org.jsoup.nodes.Document import java.nio.charset.Charset -import dotty.tools.dotc.core.Contexts._ class SiteGeneratationTest: val projectName = "Test Project Name" @@ -60,7 +59,7 @@ class SiteGeneratationTest: content.assertTextsIn(".breadcrumbs a", (parents :+ title):_*) } - checkFile("index.html")(title = "Basic test", header = "Header") + checkFile("index.html")(title = "Basic test", header = "Header", parents = Seq(projectName)) checkFile("docs/Adoc.html")(title = "Adoc", header = "Header in Adoc", parents = Seq(projectName)) checkFile("docs/Adoc.html")(title = "Adoc", header = "Header in Adoc", parents = Seq(projectName)) checkFile("docs/dir/index.html")(title = "A directory", header = "A directory", parents = Seq(projectName)) diff --git a/scala3doc/test/dotty/dokka/testUtils.scala b/scala3doc/test/dotty/dokka/testUtils.scala index 23396356ade9..a5972edcad2d 100644 --- a/scala3doc/test/dotty/dokka/testUtils.scala +++ b/scala3doc/test/dotty/dokka/testUtils.scala @@ -13,7 +13,7 @@ case class ReportedDiagnostics(errors: List[Diagnostic], warnings: List[Diagnost def infoMsgs = infos.map(_.msg.rawMessage) -extension (c: Context) def reportedDiagnostics: ReportedDiagnostics = +extension (c: CompilerContext) def reportedDiagnostics: ReportedDiagnostics = val t = c.reporter.asInstanceOf[TestReporter] ReportedDiagnostics(t.errors.result, t.warnings.result, t.infos.result) @@ -48,8 +48,16 @@ class TestReporter extends ConsoleReporter: warnings += dia super.doReport(dia) +def testArgs(files: Seq[File] = Nil, dest: File = new File("notUsed")) = Scala3doc.Args( + name = "Test Project Name", + output = dest, + tastyFiles = files + ) + def testContext = (new ContextBase).initialCtx.fresh.setReporter(new TestReporter) +def testDocContext = DocContext(testArgs(), testContext) + def tastyFiles(name: String) = def listFilesSafe(dir: File) = Option(dir.listFiles).getOrElse { throw AssertionError(s"$dir not found. The test name is incorrect or scala3doc-testcases were not recompiled.")