diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index 916a5132e48e..71ac92a8d271 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -11,6 +11,9 @@ import collection.mutable import Denotations.SingleDenotation import util.{SimpleIdentityMap, SourceFile, NoSource} import typer.ImportInfo.RootRef +import Comments.CommentsContext +import Comments.Comment +import util.Spans.NoSpan import scala.annotation.tailrec @@ -1718,5 +1721,390 @@ class Definitions { isInitialized = true } + addSyntheticSymbolsComments } + + def addSyntheticSymbolsComments(using Context): Unit = + def add(sym: Symbol, doc: String) = ctx.docCtx.get.addDocstring(sym, Some(Comment(NoSpan, doc))) + + add(AnyClass, + """/** Class `Any` is the root of the Scala class hierarchy. Every class in a Scala + | * execution environment inherits directly or indirectly from this class. + | * + | * Starting with Scala 2.10 it is possible to directly extend `Any` using ''universal traits''. + | * A ''universal trait'' is a trait that extends `Any`, only has `def`s as members, and does no initialization. + | * + | * The main use case for universal traits is to allow basic inheritance of methods for [[scala.AnyVal value classes]]. + | * For example, + | * + | * {{{ + | * trait Printable extends Any { + | * def print(): Unit = println(this) + | * } + | * class Wrapper(val underlying: Int) extends AnyVal with Printable + | * + | * val w = new Wrapper(3) + | * w.print() + | * }}} + | * + | * See the [[https://docs.scala-lang.org/overviews/core/value-classes.html Value Classes and Universal Traits]] for more + | * details on the interplay of universal traits and value classes. + | */ + """.stripMargin) + + add(Any_==, + """/** Test two objects for equality. + | * The expression `x == that` is equivalent to `if (x eq null) that eq null else x.equals(that)`. + | * + | * @param that the object to compare against this object for equality. + | * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. + | */ + """.stripMargin) + + add(Any_!=, + """/** Test two objects for inequality. + | * + | * @param that the object to compare against this object for equality. + | * @return `true` if !(this == that), `false` otherwise. + | */ + """.stripMargin) + + add(Any_equals, + """/** Compares the receiver object (`this`) with the argument object (`that`) for equivalence. + | * + | * Any implementation of this method should be an [[https://en.wikipedia.org/wiki/Equivalence_relation equivalence relation]]: + | * + | * - It is reflexive: for any instance `x` of type `Any`, `x.equals(x)` should return `true`. + | * - It is symmetric: for any instances `x` and `y` of type `Any`, `x.equals(y)` should return `true` if and + | * only if `y.equals(x)` returns `true`. + | * - It is transitive: for any instances `x`, `y`, and `z` of type `Any` if `x.equals(y)` returns `true` and + | * `y.equals(z)` returns `true`, then `x.equals(z)` should return `true`. + | * + | * If you override this method, you should verify that your implementation remains an equivalence relation. + | * Additionally, when overriding this method it is usually necessary to override `hashCode` to ensure that + | * objects which are "equal" (`o1.equals(o2)` returns `true`) hash to the same [[scala.Int]]. + | * (`o1.hashCode.equals(o2.hashCode)`). + | * + | * @param that the object to compare against this object for equality. + | * @return `true` if the receiver object is equivalent to the argument; `false` otherwise. + | */ + """.stripMargin) + + add(Any_hashCode, + """/** Calculate a hash code value for the object. + | * + | * The default hashing algorithm is platform dependent. + | * + | * Note that it is allowed for two objects to have identical hash codes (`o1.hashCode.equals(o2.hashCode)`) yet + | * not be equal (`o1.equals(o2)` returns `false`). A degenerate implementation could always return `0`. + | * However, it is required that if two objects are equal (`o1.equals(o2)` returns `true`) that they have + | * identical hash codes (`o1.hashCode.equals(o2.hashCode)`). Therefore, when overriding this method, be sure + | * to verify that the behavior is consistent with the `equals` method. + | * + | * @return the hash code value for this object. + | */ + """.stripMargin) + + add(Any_toString, + """/** Returns a string representation of the object. + | * + | * The default representation is platform dependent. + | * + | * @return a string representation of the object. + | */ + """.stripMargin) + + add(Any_##, + """/** Equivalent to `x.hashCode` except for boxed numeric types and `null`. + | * For numerics, it returns a hash value which is consistent + | * with value equality: if two value type instances compare + | * as true, then ## will produce the same hash value for each + | * of them. + | * For `null` returns a hashcode where `null.hashCode` throws a + | * `NullPointerException`. + | * + | * @return a hash value consistent with == + | */ + """.stripMargin) + + add(Any_isInstanceOf, + """/** Test whether the dynamic type of the receiver object is `T0`. + | * + | * Note that the result of the test is modulo Scala's erasure semantics. + | * Therefore the expression `1.isInstanceOf[String]` will return `false`, while the + | * expression `List(1).isInstanceOf[List[String]]` will return `true`. + | * In the latter example, because the type argument is erased as part of compilation it is + | * not possible to check whether the contents of the list are of the specified type. + | * + | * @return `true` if the receiver object is an instance of erasure of type `T0`; `false` otherwise. + | */ + """.stripMargin) + + add(Any_asInstanceOf, + """/** Cast the receiver object to be of type `T0`. + | * + | * Note that the success of a cast at runtime is modulo Scala's erasure semantics. + | * Therefore the expression `1.asInstanceOf[String]` will throw a `ClassCastException` at + | * runtime, while the expression `List(1).asInstanceOf[List[String]]` will not. + | * In the latter example, because the type argument is erased as part of compilation it is + | * not possible to check whether the contents of the list are of the requested type. + | * + | * @throws ClassCastException if the receiver object is not an instance of the erasure of type `T0`. + | * @return the receiver object. + | */ + """.stripMargin) + + add(Any_getClass, + """/** Returns the runtime class representation of the object. + | * + | * @return a class object corresponding to the runtime type of the receiver. + | */ + """.stripMargin) + + add(MatchableClass, + """/** The base trait of types that can be safely pattern matched against. + | * + | * See [[https://dotty.epfl.ch/docs/reference/other-new-features/matchable.html]]. + | */ + """.stripMargin) + + add(AnyRefAlias, + """/** Class `AnyRef` is the root class of all ''reference types''. + | * All types except the value types descend from this class. + | */ + """.stripMargin) + + add(Object_eq, + """/** Tests whether the argument (`that`) is a reference to the receiver object (`this`). + | * + | * The `eq` method implements an [[https://en.wikipedia.org/wiki/Equivalence_relation equivalence relation]] on + | * non-null instances of `AnyRef`, and has three additional properties: + | * + | * - It is consistent: for any non-null instances `x` and `y` of type `AnyRef`, multiple invocations of + | * `x.eq(y)` consistently returns `true` or consistently returns `false`. + | * - For any non-null instance `x` of type `AnyRef`, `x.eq(null)` and `null.eq(x)` returns `false`. + | * - `null.eq(null)` returns `true`. + | * + | * When overriding the `equals` or `hashCode` methods, it is important to ensure that their behavior is + | * consistent with reference equality. Therefore, if two objects are references to each other (`o1 eq o2`), they + | * should be equal to each other (`o1 == o2`) and they should hash to the same value (`o1.hashCode == o2.hashCode`). + | * + | * @param that the object to compare against this object for reference equality. + | * @return `true` if the argument is a reference to the receiver object; `false` otherwise. + | */ + """.stripMargin) + + add(Object_ne, + """/** Equivalent to `!(this eq that)`. + | * + | * @param that the object to compare against this object for reference equality. + | * @return `true` if the argument is not a reference to the receiver object; `false` otherwise. + | */ + """.stripMargin) + + add(Object_synchronized, + """/** Executes the code in `body` with an exclusive lock on `this`. + | * + | * @param body the code to execute + | * @return the result of `body` + | */ + """.stripMargin) + + add(Object_clone, + """/** Create a copy of the receiver object. + | * + | * The default implementation of the `clone` method is platform dependent. + | * + | * @note not specified by SLS as a member of AnyRef + | * @return a copy of the receiver object. + | */ + """.stripMargin) + + add(Object_finalize, + """/** Called by the garbage collector on the receiver object when there + | * are no more references to the object. + | * + | * The details of when and if the `finalize` method is invoked, as + | * well as the interaction between `finalize` and non-local returns + | * and exceptions, are all platform dependent. + | * + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(Object_notify, + """/** Wakes up a single thread that is waiting on the receiver object's monitor. + | * + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(Object_notifyAll, + """/** Wakes up all threads that are waiting on the receiver object's monitor. + | * + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(Object_wait, + """/** See [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--]]. + | * + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(Object_waitL, + """/** See [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long-]]. + | * + | * @param timeout the maximum time to wait in milliseconds. + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(Object_waitLI, + """/** See [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait-long-int-]] + | * + | * @param timeout the maximum time to wait in milliseconds. + | * @param nanos additional time, in nanoseconds range 0-999999. + | * @note not specified by SLS as a member of AnyRef + | */ + """.stripMargin) + + add(AnyKindClass, + """/** The super-type of all types. + | * + | * See [[https://dotty.epfl.ch/docs/reference/other-new-features/kind-polymorphism.html]]. + | */ + """.stripMargin) + + add(andType, + """/** The intersection of two types. + | * + | * See [[https://dotty.epfl.ch/docs/reference/new-types/intersection-types.html]]. + | */ + """.stripMargin) + + add(orType, + """/** The union of two types. + | * + | * See [[https://dotty.epfl.ch/docs/reference/new-types/union-types.html]]. + | */ + """.stripMargin) + + add(AnyValClass, + """/** `AnyVal` is the root class of all ''value types'', which describe values + | * not implemented as objects in the underlying host system. Value classes + | * are specified in Scala Language Specification, section 12.2. + | * + | * The standard implementation includes nine `AnyVal` subtypes: + | * + | * [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]], + | * [[scala.Short]], and [[scala.Byte]] are the ''numeric value types''. + | * + | * [[scala.Unit]] and [[scala.Boolean]] are the ''non-numeric value types''. + | * + | * Other groupings: + | * + | * - The ''subrange types'' are [[scala.Byte]], [[scala.Short]], and [[scala.Char]]. + | * - The ''integer types'' include the subrange types as well as [[scala.Int]] and [[scala.Long]]. + | * - The ''floating point types'' are [[scala.Float]] and [[scala.Double]]. + | * + | * Prior to Scala 2.10, `AnyVal` was a sealed trait. Beginning with Scala 2.10, + | * however, it is possible to define a subclass of `AnyVal` called a ''user-defined value class'' + | * which is treated specially by the compiler. Properly-defined user value classes provide a way + | * to improve performance on user-defined types by avoiding object allocation at runtime, and by + | * replacing virtual method invocations with static method invocations. + | * + | * User-defined value classes which avoid object allocation... + | * + | * - must have a single `val` parameter that is the underlying runtime representation. + | * - can define `def`s, but no `val`s, `var`s, or nested `traits`s, `class`es or `object`s. + | * - typically extend no other trait apart from `AnyVal`. + | * - cannot be used in type tests or pattern matching. + | * - may not override `equals` or `hashCode` methods. + | * + | * A minimal example: + | * {{{ + | * class Wrapper(val underlying: Int) extends AnyVal { + | * def foo: Wrapper = new Wrapper(underlying * 19) + | * } + | * }}} + | * + | * It's important to note that user-defined value classes are limited, and in some circumstances, + | * still must allocate a value class instance at runtime. These limitations and circumstances are + | * explained in greater detail in the [[https://docs.scala-lang.org/overviews/core/value-classes.html Value Classes and Universal Traits]]. + | */ + """.stripMargin) + + add(NullClass, + """/** `Null` is - together with [[scala.Nothing]] - at the bottom of the Scala type hierarchy. + | * + | * `Null` is the type of the `null` literal. It is a subtype of every type + | * except those of value classes. Value classes are subclasses of [[AnyVal]], which includes + | * primitive types such as [[Int]], [[Boolean]], and user-defined value classes. + | * + | * Since `Null` is not a subtype of value types, `null` is not a member of any such type. + | * For instance, it is not possible to assign `null` to a variable of type [[scala.Int]]. + | */ + """.stripMargin) + + add(NothingClass, + """/** `Nothing` is - together with [[scala.Null]] - at the bottom of Scala's type hierarchy. + | * + | * `Nothing` is a subtype of every other type (including [[scala.Null]]); there exist + | * ''no instances'' of this type. Although type `Nothing` is uninhabited, it is + | * nevertheless useful in several ways. For instance, the Scala library defines a value + | * [[scala.collection.immutable.Nil]] of type `List[Nothing]`. Because lists are covariant in Scala, + | * this makes [[scala.collection.immutable.Nil]] an instance of `List[T]`, for any element of type `T`. + | * + | * Another usage for Nothing is the return type for methods which never return normally. + | * One example is method error in [[scala.sys]], which always throws an exception. + | */ + """.stripMargin) + + add(SingletonClass, + """/** `Singleton` is used by the compiler as a supertype for singleton types. This includes literal types, + | * as they are also singleton types. + | * + | * {{{ + | * scala> object A { val x = 42 } + | * defined object A + | * + | * scala> implicitly[A.type <:< Singleton] + | * res12: A.type <:< Singleton = generalized constraint + | * + | * scala> implicitly[A.x.type <:< Singleton] + | * res13: A.x.type <:< Singleton = generalized constraint + | * + | * scala> implicitly[42 <:< Singleton] + | * res14: 42 <:< Singleton = generalized constraint + | * + | * scala> implicitly[Int <:< Singleton] + | * ^ + | * error: Cannot prove that Int <:< Singleton. + | * }}} + | * + | * `Singleton` has a special meaning when it appears as an upper bound on a formal type + | * parameter. Normally, type inference in Scala widens singleton types to the underlying + | * non-singleton type. When a type parameter has an explicit upper bound of `Singleton`, + | * the compiler infers a singleton type. + | * + | * {{{ + | * scala> def check42[T](x: T)(implicit ev: T =:= 42): T = x + | * check42: [T](x: T)(implicit ev: T =:= 42)T + | * + | * scala> val x1 = check42(42) + | * ^ + | * error: Cannot prove that Int =:= 42. + | * + | * scala> def singleCheck42[T <: Singleton](x: T)(implicit ev: T =:= 42): T = x + | * singleCheck42: [T <: Singleton](x: T)(implicit ev: T =:= 42)T + | * + | * scala> val x2 = singleCheck42(42) + | * x2: Int = 42 + | * }}} + | * + | * See also [[https://docs.scala-lang.org/sips/42.type.html SIP-23 about Literal-based Singleton Types]]. + | */ + """.stripMargin) } diff --git a/project/Build.scala b/project/Build.scala index e8da4146fbbe..31fa59ebea7a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -790,6 +790,7 @@ object Build { ).mkString(File.pathSeparator), ) }, + Compile / doc / scalacOptions += "-Ydocument-synthetic-types", scalacOptions -= "-Xfatal-warnings", ivyConfigurations += SourceDeps.hide, transitiveClassifiers := Seq("sources"), @@ -1640,7 +1641,8 @@ object Build { s"-source-links:" + s"$stdLibRoot=github://scala/scala/v${stdlibVersion(Bootstrapped)}#src/library," + s"docs=github://lampepfl/dotty/master#docs", - "-doc-root-content", docRootFile.toString + "-doc-root-content", docRootFile.toString, + "-Ydocument-synthetic-types" ) )) }.evaluated, diff --git a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala index 1e900902c24f..3bafdba26d71 100644 --- a/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala +++ b/scaladoc/src/dotty/tools/scaladoc/Scaladoc.scala @@ -42,7 +42,8 @@ object Scaladoc: socialLinks: List[SocialLinks] = Nil, identifiersToSkip: List[String] = Nil, regexesToSkip: List[String] = Nil, - rootDocPath: Option[String] = None + rootDocPath: Option[String] = None, + documentSyntheticTypes: Boolean = false, ) def run(args: Array[String], rootContext: CompilerContext): Reporter = @@ -171,7 +172,8 @@ object Scaladoc: socialLinksParsed, skipById.get ++ deprecatedSkipPackages.get, skipByRegex.get, - docRootContent.nonDefault + docRootContent.nonDefault, + YdocumentSyntheticTypes.get ) (Some(docArgs), newContext) } diff --git a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala index 701e5f551e8e..538292929dad 100644 --- a/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala +++ b/scaladoc/src/dotty/tools/scaladoc/ScaladocSettings.scala @@ -57,5 +57,8 @@ class ScaladocSettings extends SettingGroup with CommonScalaSettings: val docRootContent: Setting[String] = StringSetting("-doc-root-content", "path", "The file from which the root package documentation should be imported.", "") + val YdocumentSyntheticTypes: Setting[Boolean] = + BooleanSetting("-Ydocument-synthetic-types", "Documents intrinsic types e. g. Any, Nothing. Setting is useful only for stdlib", false) + def scaladocSpecificSettings: Set[Setting[_]] = Set(sourceLinks, syntax, revision, externalDocumentationMappings, socialLinks, skipById, skipByRegex, deprecatedSkipPackages, docRootContent) diff --git a/scaladoc/src/dotty/tools/scaladoc/renderers/WikiDocRenderer.scala b/scaladoc/src/dotty/tools/scaladoc/renderers/WikiDocRenderer.scala index 8204039abd29..ccb94ffee3b5 100644 --- a/scaladoc/src/dotty/tools/scaladoc/renderers/WikiDocRenderer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/renderers/WikiDocRenderer.scala @@ -46,7 +46,7 @@ class DocRender(signatureRenderer: SignatureRenderer)(using DocContext): case 5 => h5(content) case 6 => h6(content) case Paragraph(text) => p(renderElement(text)) - case Code(data: String) => code(raw(data)) // TODO add classes + case Code(data: String) => pre(code(raw(data))) // TODO add classes case HorizontalRule => hr case UnorderedList(items) => ul(listItems(items)) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 1f28b561b3da..90b6eed98fbe 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -146,7 +146,7 @@ trait ClassLikeSupport: Some(parseMethod(c, dd.symbol)) case td: TypeDef if !td.symbol.flags.is(Flags.Synthetic) && (!td.symbol.flags.is(Flags.Case) || !td.symbol.flags.is(Flags.Enum)) => - Some(parseTypeDef(c, td)) + Some(parseTypeDef(td)) case vd: ValDef if !isSyntheticField(vd.symbol) && (!vd.symbol.flags.is(Flags.Case) || !vd.symbol.flags.is(Flags.Enum)) @@ -306,7 +306,7 @@ trait ClassLikeSupport: val enumTypes = companion.membersToDocument.collect { case td: TypeDef if !td.symbol.flags.is(Flags.Synthetic) && td.symbol.flags.is(Flags.Enum) && td.symbol.flags.is(Flags.Case) => td - }.toList.map(parseTypeDef(classDef, _)) + }.toList.map(parseTypeDef) val enumNested = companion.membersToDocument.collect { case c: ClassDef if c.symbol.flags.is(Flags.Case) && c.symbol.flags.is(Flags.Enum) => processTree(c)(parseClasslike(c)) @@ -405,7 +405,7 @@ trait ClassLikeSupport: memberInfo.get(name).fold(argument.rhs.asSignature)(_.asSignature) ) - def parseTypeDef(c: ClassDef, typeDef: TypeDef): Member = + def parseTypeDef(typeDef: TypeDef): Member = def isTreeAbstract(typ: Tree): Boolean = typ match { case TypeBoundsTree(_, _) => true case LambdaTypeTree(params, body) => isTreeAbstract(body) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index c3fa15cbb25c..c150a1b8e304 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -160,12 +160,13 @@ class SymOps[Q <: Quotes](val q: Q) extends JavadocAnchorCreator with Scaladoc2A else if (sym.maybeOwner.isDefDef) Some(sym.owner) else None - val className = sym.className + val (className, anchor) = if sym.fullName == "scala.AnyRef" then // hacking relocation for synthetic `type AnyRef` + (Some("AnyRef"), None) + else + (sym.className, sym.anchor) val location = sym.packageNameSplitted ++ className - val anchor = sym.anchor - val externalLink = { import q.reflect._ import dotty.tools.dotc diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index eadf63c70def..033321f0b0d1 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -116,6 +116,27 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe topLevels ++= parser.parseRootTree(treeRoot) } + val defn = ctx.compilerContext.definitions + + if ctx.args.documentSyntheticTypes then + val intrinsicClassDefs = Seq( + defn.AnyClass, + defn.MatchableClass, + defn.AnyKindClass, + defn.AnyValClass, + defn.NullClass, + defn.NothingClass, + defn.SingletonClass, + defn.andType, + defn.orType, + ).map { s => + "scala" -> s.asInstanceOf[parser.qctx.reflect.Symbol].tree.match { + case cd: parser.qctx.reflect.ClassDef => parser.parseClasslike(cd) + case td: parser.qctx.reflect.TypeDef => parser.parseTypeDef(td) + } + } + topLevels ++= intrinsicClassDefs + topLevels += mergeAnyRefAliasAndObject(parser) def result(): (List[Member], Option[Comment]) = topLevels.clear() @@ -134,6 +155,14 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe basePck.withMembers((basePck.members ++ rest).sortBy(_.name)) }.toList -> rootDoc + def mergeAnyRefAliasAndObject(parser: TastyParser) = + val defn = ctx.compilerContext.definitions + val oM = parser.parseClasslike(defn.ObjectClass.asInstanceOf[parser.qctx.reflect.Symbol].tree.asInstanceOf[parser.qctx.reflect.ClassDef]) + val aM = parser.parseTypeDef(defn.AnyRefAlias.asInstanceOf[parser.qctx.reflect.Symbol].tree.asInstanceOf[parser.qctx.reflect.TypeDef]) + "scala" -> aM.copy( + kind = oM.kind, + members = oM.members + ) /** Parses a single Tasty compilation unit. */ case class TastyParser( qctx: Quotes, @@ -154,13 +183,6 @@ case class TastyParser( 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.fullName}:\n${throwableToString(t)}") - None - def parseRootTree(root: Tree): Seq[(String, Member)] = val docs = Seq.newBuilder[(String, Member)] object Traverser extends TreeTraverser: @@ -186,4 +208,3 @@ case class TastyParser( e.printStackTrace() docs.result() - diff --git a/scaladoc/src/dotty/tools/scaladoc/util/html.scala b/scaladoc/src/dotty/tools/scaladoc/util/html.scala index f8a02a0d6e55..3c07222341b6 100644 --- a/scaladoc/src/dotty/tools/scaladoc/util/html.scala +++ b/scaladoc/src/dotty/tools/scaladoc/util/html.scala @@ -83,7 +83,7 @@ object HTML: val ol = Tag("ol") val li = Tag("li") val code = Tag("code") - + val pre = Tag("pre") val cls = Attr("class") val href = Attr("href")