From eeec21312e3dd63ffc0aac0dafff46b19cb073f2 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 17:47:09 +0200 Subject: [PATCH 1/9] Clenup Scaladoc2AnchorCreator --- .../tasty/Scaladoc2AnchorCreator.scala | 21 +++++++------------ .../dotty/tools/scaladoc/tasty/SymOps.scala | 5 +++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala index 438fd9ed0153..dc791c7422fc 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala @@ -5,17 +5,12 @@ import scala.quoted._ import dotty.tools.scaladoc.util.Escape._ import scala.util.matching.Regex -trait Scaladoc2AnchorCreator: - self: SymOps[_] => +object Scaladoc2AnchorCreator: - import self.q.reflect._ - - implicit private val printer: Printer[Tree] = Printer.TreeShortCode - - def getScaladoc2Type(t: Tree) = { - (t match { - case d: DefDef => d.show.split("def", 2)(1) - case t: TypeDef => t.show.split("type", 2)(1) - case v: ValDef => v.show.split("val|var", 2)(1) - }).replace(" ","") -} \ No newline at end of file + def getScaladoc2Type(using Quotes)(t: quotes.reflect.Tree) = + import quotes.reflect.* + val regex = t match + case d: DefDef => "def" + case t: TypeDef => "type" + case v: ValDef => "val|var" + t.show(using Printer.TreeShortCode).split(regex, 2)(1).replace(" ","") diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 14b6c120b5b3..539866c603bb 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -5,11 +5,12 @@ import scala.quoted._ import dotty.tools.scaladoc.util.Escape._ import scala.collection.mutable.{ Map => MMap } import dotty.tools.io.AbstractFile +import Scaladoc2AnchorCreator.getScaladoc2Type -class SymOps[Q <: Quotes](val q: Q) extends JavadocAnchorCreator with Scaladoc2AnchorCreator: +class SymOps[Q <: Quotes](val q: Q) extends JavadocAnchorCreator: import q.reflect._ - given Q = q + given q.type = q private val externalLinkCache: scala.collection.mutable.Map[AbstractFile, Option[ExternalDocLink]] = MMap() From 48f0078186edcdbdc0204215b104340771e5758c Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 20:08:20 +0200 Subject: [PATCH 2/9] Cleanup JavadocAnchorCreator --- .../scaladoc/tasty/JavadocAnchorCreator.scala | 47 +++++++++---------- .../dotty/tools/scaladoc/tasty/SymOps.scala | 5 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala index 5f9751d0d8e3..c798e81a6a1e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala @@ -5,33 +5,32 @@ import scala.quoted._ import dotty.tools.scaladoc.util.Escape._ import scala.util.matching.Regex -trait JavadocAnchorCreator: - self: SymOps[_] => +object JavadocAnchorCreator: - import self.q.reflect._ + private def javadocPrimitives(using Quotes)(sym: quotes.reflect.Symbol) = + import quotes.reflect.* + if sym == defn.IntClass then Some("int") + else if sym == defn.FloatClass then Some("float") + else if sym == defn.DoubleClass then Some("double") + else if sym == defn.LongClass then Some("long") + else if sym == defn.ByteClass then Some("byte") + else if sym == defn.BooleanClass then Some("boolean") + else if sym == defn.CharClass then Some("char") + else if sym == defn.ShortClass then Some("short") + else if sym == defn.ObjectClass then Some("java.lang.Object") + else None - private val javadocPrimitivesMap = Map( - defn.IntClass -> "int", - defn.FloatClass -> "float", - defn.DoubleClass -> "double", - defn.LongClass -> "long", - defn.ByteClass -> "byte", - defn.BooleanClass -> "boolean", - defn.CharClass -> "char", - defn.ShortClass -> "short", - defn.ObjectClass -> "java.lang.Object" - ) - - private def transformPrimitiveType(tpe: TypeRepr): String = tpe.classSymbol - .flatMap(javadocPrimitivesMap.get) + private def transformPrimitiveType(using Quotes)(tpe: quotes.reflect.TypeRepr): String = tpe.classSymbol + .flatMap(javadocPrimitives) .filter(_ => !tpe.typeSymbol.isTypeParam) .getOrElse(tpe.show) - private def transformType(tpe: TypeRepr): String = tpe.simplified match { - case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.ArrayClass) => transformType(typeList.head) + ":A" - case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.RepeatedParamClass) => transformType(typeList.head) + "..." - case AppliedType(tpe, typeList) => transformPrimitiveType(tpe) - case other => transformPrimitiveType(other) - } + private def transformType(using Quotes)(tpe: quotes.reflect.TypeRepr): String = + import quotes.reflect.* + tpe.simplified match + case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.ArrayClass) => transformType(typeList.head) + ":A" + case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.RepeatedParamClass) => transformType(typeList.head) + "..." + case AppliedType(tpe, typeList) => transformPrimitiveType(tpe) + case other => transformPrimitiveType(other) - def getJavadocType(s: TypeRepr) = transformType(s) + def getJavadocType(using Quotes)(s: quotes.reflect.TypeRepr) = transformType(s) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 539866c603bb..9f648e328e41 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -6,8 +6,9 @@ import dotty.tools.scaladoc.util.Escape._ import scala.collection.mutable.{ Map => MMap } import dotty.tools.io.AbstractFile import Scaladoc2AnchorCreator.getScaladoc2Type +import JavadocAnchorCreator.getJavadocType -class SymOps[Q <: Quotes](val q: Q) extends JavadocAnchorCreator: +class SymOps[Q <: Quotes](val q: Q): import q.reflect._ given q.type = q @@ -129,7 +130,7 @@ class SymOps[Q <: Quotes](val q: Q) extends JavadocAnchorCreator: val javadocAnchor = if anchor.isDefined then { val paramSigs = sym.paramSymss.flatten.map(_.tree).collect { case v: ValDef => v.tpt.tpe - }.map(getJavadocType) + }.map(getJavadocType(using q)) "#" + sym.name + paramSigs.mkString("-","-","-") } else "" docURL + l + extension + javadocAnchor From af4390aa28de0ee35f0254016234782f3250ed38 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 20:44:42 +0200 Subject: [PATCH 3/9] Partial clenup of SymOps --- .../tools/scaladoc/tasty/BasicSupport.scala | 8 +- .../scaladoc/tasty/ClassLikeSupport.scala | 4 + .../tools/scaladoc/tasty/NameNormalizer.scala | 5 ++ .../tools/scaladoc/tasty/PackageSupport.scala | 4 + .../dotty/tools/scaladoc/tasty/SymOps.scala | 90 ++++++++++++------- .../tools/scaladoc/tasty/TastyParser.scala | 6 +- .../tools/scaladoc/tasty/TypesSupport.scala | 1 + .../scaladoc/tasty/comments/Comments.scala | 10 ++- 8 files changed, 90 insertions(+), 38 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala index 43d28a80606f..77d3f27d7d4a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala @@ -5,11 +5,15 @@ import collection.JavaConverters._ import dotty.tools.scaladoc._ import scala.quoted._ +import SymOps._ + trait BasicSupport: self: TastyParser => import qctx.reflect._ - object SymOps extends SymOps[qctx.type](qctx) - export SymOps._ + object SymOpsWithLinkCache extends SymOpsWithLinkCache + export SymOpsWithLinkCache._ + + private given qctx.type = qctx def parseAnnotation(annotTerm: Term): Annotation = import dotty.tools.dotc.ast.Trees.{SeqLiteral} diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index bcb87f2d5428..83c027c8f889 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -4,10 +4,14 @@ import collection.JavaConverters._ import dotty.tools.scaladoc._ import dotty.tools.scaladoc.{Signature => DSignature} +import SymOps._ + trait ClassLikeSupport: self: TastyParser => import qctx.reflect._ + private given qctx.type = qctx + private def bareClasslikeKind(symbol: Symbol): Kind = if symbol.flags.is(Flags.Module) then Kind.Object else if symbol.flags.is(Flags.Trait) then Kind.Trait(Nil, Nil) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala index 24366288557c..b080a91a22e8 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala @@ -4,8 +4,13 @@ import dotty.tools.scaladoc._ import dotty.tools.dotc.core.StdNames.nme.keywords import dotty.tools.dotc.core.Names.termName +import SymOps._ + trait NameNormalizer { self: TastyParser => import qctx.reflect._ + + private given qctx.type = qctx + extension (s: Symbol) def normalizedName: String = { val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name val withoutObjectSuffix = if s.flags.is(Flags.Module) then withoutGivenPrefix.stripSuffix("$") else withoutGivenPrefix diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/PackageSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/PackageSupport.scala index 04d4a66ff6cc..77ce9854620d 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/PackageSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/PackageSupport.scala @@ -3,10 +3,14 @@ package tasty import collection.JavaConverters._ +import SymOps._ + trait PackageSupport: self: TastyParser => import qctx.reflect._ + private given qctx.type = qctx + def parsePackage(pck: PackageClause): (String, Member) = val name = pck.symbol.fullName (name, Member(name, pck.symbol.dri, Kind.Package)) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 9f648e328e41..1cb1ff471d73 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -8,23 +8,19 @@ import dotty.tools.io.AbstractFile import Scaladoc2AnchorCreator.getScaladoc2Type import JavadocAnchorCreator.getJavadocType -class SymOps[Q <: Quotes](val q: Q): - import q.reflect._ +object SymOps: - given q.type = q + extension (using Quotes)(sym: quotes.reflect.Symbol) - private val externalLinkCache: scala.collection.mutable.Map[AbstractFile, Option[ExternalDocLink]] = MMap() - - extension (sym: Symbol) - def packageName: String = ( + def packageName: String = if (sym.isPackageDef) sym.fullName else sym.maybeOwner.packageName - ) def packageNameSplitted: Seq[String] = sym.packageName.split('.').toList def className: Option[String] = + import quotes.reflect._ if (sym.isClassDef && !sym.flags.is(Flags.Package)) Some( Some(sym.maybeOwner).filter(s => s.exists).flatMap(_.className).fold("")(cn => cn + "$") + sym.name ).filterNot(_.contains("package$")) @@ -44,7 +40,9 @@ class SymOps[Q <: Quotes](val q: Q): else None //TODO: Retrieve string that will match scaladoc anchors + def getVisibility(): Visibility = + import quotes.reflect._ import VisibilityScope._ def explicitScope(ownerType: TypeRepr): VisibilityScope = @@ -71,7 +69,9 @@ class SymOps[Q <: Quotes](val q: Q): // Order here determines order in documenation - def getExtraModifiers(): Seq[Modifier] = Seq( + def getExtraModifiers(): Seq[Modifier] = + import quotes.reflect._ + Seq( Flags.Final -> Modifier.Final, Flags.Sealed -> Modifier.Sealed, Flags.Erased -> Modifier.Erased, @@ -83,46 +83,73 @@ class SymOps[Q <: Quotes](val q: Q): Flags.Open -> Modifier.Open, Flags.Override -> Modifier.Override, Flags.Case -> Modifier.Case, - ).collect { case (flag, mod) if sym.flags.is(flag) => mod } + ).collect { case (flag, mod) if sym.flags.is(flag) => mod } def isHiddenByVisibility(using dctx: DocContext): Boolean = import VisibilityScope._ - !summon[DocContext].args.includePrivateAPI && getVisibility().match + !summon[DocContext].args.includePrivateAPI && sym.getVisibility().match case Visibility.Private(_) => true case Visibility.Protected(ThisScope | ImplicitModuleScope | _: ExplicitModuleScope) => true case _ => false - def shouldDocumentClasslike(using dctx: DocContext): Boolean = !isHiddenByVisibility - && !sym.flags.is(Flags.Synthetic) - && (!sym.flags.is(Flags.Case) || !sym.flags.is(Flags.Enum)) - && !(sym.companionModule.flags.is(Flags.Given)) - + def shouldDocumentClasslike(using dctx: DocContext): Boolean = + import quotes.reflect._ + !sym.isHiddenByVisibility + && !sym.flags.is(Flags.Synthetic) + && (!sym.flags.is(Flags.Case) || !sym.flags.is(Flags.Enum)) + && !(sym.companionModule.flags.is(Flags.Given)) - def getCompanionSymbol: Option[Symbol] = Some(sym.companionClass).filter(_.exists) + def getCompanionSymbol: Option[quotes.reflect.Symbol] = Some(sym.companionClass).filter(_.exists) - def isCompanionObject: Boolean = sym.flags.is(Flags.Module) && sym.companionClass.exists + def isCompanionObject: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.Module) && sym.companionClass.exists - def isGiven: Boolean = sym.flags.is(Flags.Given) + def isGiven: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.Given) - def isExported: Boolean = sym.flags.is(Flags.Exported) + def isExported: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.Exported) - def isOverridden: Boolean = sym.flags.is(Flags.Override) + def isOverridden: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.Override) - def isExtensionMethod: Boolean = sym.flags.is(Flags.ExtensionMethod) + def isExtensionMethod: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.ExtensionMethod) - def isArtifact: Boolean = sym.flags.is(Flags.Artifact) + def isArtifact: Boolean = + import quotes.reflect._ + sym.flags.is(Flags.Artifact) - def isLeftAssoc(d: Symbol): Boolean = !d.name.endsWith(":") + def isLeftAssoc: Boolean = !sym.name.endsWith(":") - def extendedSymbol: Option[ValDef] = + def extendedSymbol: Option[quotes.reflect.ValDef] = + import quotes.reflect.* Option.when(sym.isExtensionMethod){ val termParamss = sym.tree.asInstanceOf[DefDef].termParamss - if isLeftAssoc(sym) || termParamss.size == 1 then termParamss(0).params(0) + if sym.isLeftAssoc || termParamss.size == 1 then termParamss(0).params(0) else termParamss(1).params(0) } + end extension + +end SymOps + +// TODO find a better way to handle this cache and move the methods to SymOps +class SymOpsWithLinkCache: + import SymOps.* + + private val externalLinkCache: scala.collection.mutable.Map[AbstractFile, Option[ExternalDocLink]] = MMap() + + extension (using Quotes)(sym: quotes.reflect.Symbol) + private def constructPath(location: Seq[String], anchor: Option[String], link: ExternalDocLink): String = + import quotes.reflect.* val extension = ".html" val docURL = link.documentationUrl.toString def constructPathForJavadoc: String = @@ -130,7 +157,7 @@ class SymOps[Q <: Quotes](val q: Q): val javadocAnchor = if anchor.isDefined then { val paramSigs = sym.paramSymss.flatten.map(_.tree).collect { case v: ValDef => v.tpt.tpe - }.map(getJavadocType(using q)) + }.map(getJavadocType) "#" + sym.name + paramSigs.mkString("-","-","-") } else "" docURL + l + extension + javadocAnchor @@ -156,6 +183,7 @@ class SymOps[Q <: Quotes](val q: Q): // TODO #22 make sure that DRIs are unique plus probably reuse semantic db code? def dri(using dctx: DocContext): DRI = + import quotes.reflect.* if sym == Symbol.noSymbol then topLevelDri else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri else @@ -172,9 +200,9 @@ class SymOps[Q <: Quotes](val q: Q): val location = sym.packageNameSplitted ++ className val externalLink = { - import q.reflect._ + import quotes.reflect._ import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = q.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val csym = sym.asInstanceOf[dotc.core.Symbols.Symbol] val extLink = if externalLinkCache.contains(csym.associatedFile) then externalLinkCache(csym.associatedFile) else { @@ -183,7 +211,7 @@ class SymOps[Q <: Quotes](val q: Q): externalLinkCache += (csym.associatedFile -> calculatedLink) calculatedLink } - extLink.map(link => constructPath(location, anchor, link)) + extLink.map(link => sym.constructPath(location, anchor, link)) } DRI( @@ -195,7 +223,7 @@ class SymOps[Q <: Quotes](val q: Q): s"${sym.name}${sym.fullName}/${sym.signature.resultSig}/[${sym.signature.paramSigs.mkString("/")}]" ) - def driInContextOfInheritingParent(par: Symbol)(using dctx: DocContext): DRI = sym.dri.copy( + def driInContextOfInheritingParent(par: quotes.reflect.Symbol)(using dctx: DocContext): DRI = sym.dri.copy( location = par.dri.location, externalLink = None ) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index 0e5871138926..4fa58c263ee3 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -17,6 +17,8 @@ import dotty.tools.scaladoc.tasty.comments.Comment import java.nio.file.Paths import java.nio.file.Files +import SymOps._ + /** Responsible for collectively inspecting all the Tasty files we're interested in. * * Delegates most of the work to [[TastyParser]] [[dotty.tools.scaladoc.tasty.TastyParser]]. @@ -78,7 +80,7 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe val parser = new TastyParser(q, this)(isSkipped) def driFor(link: String): Option[DRI] = - val symOps = new SymOps[q.type](q) + val symOps = new SymOpsWithLinkCache import symOps._ Try(QueryParser(link).readQuery()).toOption.flatMap(query => MemberLookup.lookupOpt(query, None).map { @@ -178,6 +180,8 @@ case class TastyParser( ) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer: import qctx.reflect._ + private given qctx.type = qctx + def processTree[T](tree: Tree)(op: => T): Option[T] = try Option(op) catch case e: Exception => report.warning(throwableToString(e), tree.pos) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index af5509768aaa..c8e2fdf11453 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -6,6 +6,7 @@ import collection.JavaConverters._ trait TypesSupport: self: TastyParser => import qctx.reflect._ + private given qctx.type = qctx type DocSignaturePart = String | Link type DocSignature = List[DocSignaturePart] diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala index c60187c1b8b9..d9199864a407 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/Comments.scala @@ -12,7 +12,8 @@ import com.vladsch.flexmark.util.options.MutableDataSet import scala.quoted._ import dotty.tools.scaladoc.tasty.comments.wiki.Paragraph import dotty.tools.scaladoc.DocPart -import dotty.tools.scaladoc.tasty.SymOps +import dotty.tools.scaladoc.tasty.SymOpsWithLinkCache +import collection.JavaConverters._ import collection.JavaConverters._ class Repr(val qctx: Quotes)(val sym: qctx.reflect.Symbol) @@ -80,10 +81,11 @@ abstract class MarkupConversion[T](val repr: Repr)(using DocContext) { val qctx: repr.qctx.type = if repr == null then null else repr.qctx // TODO why we do need null? val owner: qctx.reflect.Symbol = if repr == null then null.asInstanceOf[qctx.reflect.Symbol] else repr.sym + private given qctx.type = qctx - object SymOps extends SymOps[qctx.type](qctx) - export SymOps.dri - export SymOps.driInContextOfInheritingParent + object SymOpsWithLinkCache extends SymOpsWithLinkCache + export SymOpsWithLinkCache.dri + export SymOpsWithLinkCache.driInContextOfInheritingParent def resolveLink(queryStr: String): DocLink = if SchemeUri.matches(queryStr) then DocLink.ToURL(queryStr) From cf990033b60c87f51e039bdf11d8e9f096fb65cb Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 20:52:27 +0200 Subject: [PATCH 4/9] Cleanup NameNormalizer --- .../dotty/tools/scaladoc/tasty/ClassLikeSupport.scala | 1 + .../src/dotty/tools/scaladoc/tasty/NameNormalizer.scala | 9 ++++----- .../src/dotty/tools/scaladoc/tasty/TastyParser.scala | 2 +- .../src/dotty/tools/scaladoc/tasty/TypesSupport.scala | 2 ++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 83c027c8f889..19a2d930357f 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -5,6 +5,7 @@ import dotty.tools.scaladoc._ import dotty.tools.scaladoc.{Signature => DSignature} import SymOps._ +import NameNormalizer._ trait ClassLikeSupport: self: TastyParser => diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala index b080a91a22e8..502a5ec62f9a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala @@ -4,14 +4,13 @@ import dotty.tools.scaladoc._ import dotty.tools.dotc.core.StdNames.nme.keywords import dotty.tools.dotc.core.Names.termName +import scala.quoted._ import SymOps._ -trait NameNormalizer { self: TastyParser => - import qctx.reflect._ +object NameNormalizer { - private given qctx.type = qctx - - extension (s: Symbol) def normalizedName: String = { + extension (using Quotes)(s: quotes.reflect.Symbol) def normalizedName: String = { + import quotes.reflect.* val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name val withoutObjectSuffix = if s.flags.is(Flags.Module) then withoutGivenPrefix.stripSuffix("$") else withoutGivenPrefix val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index 4fa58c263ee3..cb9f170151af 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -177,7 +177,7 @@ case class TastyParser( isSkipped: qctx.reflect.Symbol => Boolean )( using val ctx: DocContext -) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport with NameNormalizer: +) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport: import qctx.reflect._ private given qctx.type = qctx diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index c8e2fdf11453..a3f71a5dbe24 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -3,6 +3,8 @@ package tasty import collection.JavaConverters._ +import NameNormalizer._ + trait TypesSupport: self: TastyParser => import qctx.reflect._ From 4f4ff7d5cb75c88bbd6de627762976754fb2aa5e Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 22:13:11 +0200 Subject: [PATCH 5/9] Cleanup ScaladocSupport --- .../tools/scaladoc/tasty/BasicSupport.scala | 1 + .../scaladoc/tasty/ScalaDocSupport.scala | 20 +++++++++---------- .../tools/scaladoc/tasty/TastyParser.scala | 5 +++-- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala index 77d3f27d7d4a..11a46c1707da 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala @@ -6,6 +6,7 @@ import dotty.tools.scaladoc._ import scala.quoted._ import SymOps._ +import ScaladocSupport._ trait BasicSupport: self: TastyParser => diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala index 2a41c3251727..fb22a58ab3b7 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala @@ -6,10 +6,12 @@ import scala.jdk.CollectionConverters._ import dotty.tools.scaladoc.Scaladoc.CommentSyntax import dotty.tools.scaladoc.tasty.comments.Comment -trait ScaladocSupport { self: TastyParser => - import qctx.reflect._ +import scala.quoted._ - def parseCommentString(comment: String, sym: Symbol, pos: Option[Position]): Comment = +object ScaladocSupport: + + def parseCommentString(using Quotes, DocContext)(comment: String, sym: quotes.reflect.Symbol, pos: Option[quotes.reflect.Position]): Comment = + import quotes.reflect.report val preparsed = comments.Preparser.preparse(comments.Cleaner.clean(comment)) val commentSyntax = @@ -22,22 +24,22 @@ trait ScaladocSupport { self: TastyParser => CommentSyntax.default } - case None => ctx.args.defaultSyntax + case None => summon[DocContext].args.defaultSyntax } val parser = commentSyntax match { case CommentSyntax.Wiki => - comments.WikiCommentParser(comments.Repr(qctx)(sym)) + comments.WikiCommentParser(comments.Repr(quotes)(sym)) case CommentSyntax.Markdown => - comments.MarkdownCommentParser(comments.Repr(qctx)(sym)) + comments.MarkdownCommentParser(comments.Repr(quotes)(sym)) } parser.parse(preparsed) - def parseComment(docstring: String, tree: Tree): Comment = + def parseComment(using Quotes, DocContext)(docstring: String, tree: quotes.reflect.Tree): Comment = val commentString: String = if tree.symbol.isClassDef || tree.symbol.owner.isClassDef then import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = tree.symbol.asInstanceOf[dotc.core.Symbols.Symbol] @@ -47,5 +49,3 @@ trait ScaladocSupport { self: TastyParser => docstring parseCommentString(commentString, tree.symbol, Some(tree.pos)) - -} diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index cb9f170151af..cd834f162d22 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -18,6 +18,7 @@ import java.nio.file.Paths import java.nio.file.Files import SymOps._ +import ScaladocSupport._ /** Responsible for collectively inspecting all the Tasty files we're interested in. * @@ -112,7 +113,7 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe import parser.qctx.reflect._ def root(s: Symbol): Symbol = if s.owner.isNoSymbol then s else root(s.owner) val topLevelPck = root(tree.symbol) - rootDoc = Some(parser.parseCommentString(content, topLevelPck, None)) + rootDoc = Some(parseCommentString(using parser.qctx, summon[DocContext])(content, topLevelPck, None)) } hackForeachTree { root => @@ -177,7 +178,7 @@ case class TastyParser( isSkipped: qctx.reflect.Symbol => Boolean )( using val ctx: DocContext -) extends ScaladocSupport with BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport: +) extends BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport: import qctx.reflect._ private given qctx.type = qctx From 48bab6db49c3cbc7f16c94b1de90aa18c7d46954 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 22:46:43 +0200 Subject: [PATCH 6/9] Cleanup SyntheticsSupport --- .../scaladoc/tasty/ClassLikeSupport.scala | 22 +++-- .../scaladoc/tasty/SyntheticSupport.scala | 83 ++++++++++--------- .../tools/scaladoc/tasty/TastyParser.scala | 2 +- .../tools/scaladoc/tasty/TypesSupport.scala | 1 + 4 files changed, 60 insertions(+), 48 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 19a2d930357f..df959f192e8f 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -4,8 +4,11 @@ import collection.JavaConverters._ import dotty.tools.scaladoc._ import dotty.tools.scaladoc.{Signature => DSignature} +import scala.quoted._ + import SymOps._ import NameNormalizer._ +import SyntheticsSupport._ trait ClassLikeSupport: self: TastyParser => @@ -13,12 +16,13 @@ trait ClassLikeSupport: private given qctx.type = qctx - private def bareClasslikeKind(symbol: Symbol): Kind = - if symbol.flags.is(Flags.Module) then Kind.Object - else if symbol.flags.is(Flags.Trait) then Kind.Trait(Nil, Nil) - else if symbol.flags.is(Flags.Enum) then Kind.Enum(Nil, Nil) - else if symbol.flags.is(Flags.Enum) && symbol.flags.is(Flags.Case) then Kind.EnumCase(Kind.Object) - else Kind.Class(Nil, Nil) + private def bareClasslikeKind(using Quotes)(symbol: quotes.reflect.Symbol): Kind = + import quotes.reflect._ + if symbol.flags.is(Flags.Module) then Kind.Object + else if symbol.flags.is(Flags.Trait) then Kind.Trait(Nil, Nil) + else if symbol.flags.is(Flags.Enum) then Kind.Enum(Nil, Nil) + else if symbol.flags.is(Flags.Enum) && symbol.flags.is(Flags.Case) then Kind.EnumCase(Kind.Object) + else Kind.Class(Nil, Nil) private def kindForClasslike(classDef: ClassDef): Kind = def typeArgs = classDef.getTypeParams.map(mkTypeArgument(_)) @@ -213,7 +217,8 @@ trait ClassLikeSupport: } ).map(_.copy(inheritedFrom = inheritance)) - extension (c: ClassDef) + extension (using Quotes)(c: quotes.reflect.ClassDef) + def membersToDocument = c.body.filterNot(_.symbol.isHiddenByVisibility) def getNonTrivialInheritedMemberTrees = @@ -221,6 +226,7 @@ trait ClassLikeSupport: .filter(s => s.maybeOwner != defn.ObjectClass && s.maybeOwner != defn.AnyClass) .map(_.tree) + extension (c: ClassDef) def extractMembers: Seq[Member] = { val inherited = c.getNonTrivialInheritedMemberTrees.collect { case dd: DefDef if !dd.symbol.isClassConstructor && !(dd.symbol.isSuperBridgeMethod || dd.symbol.isDefaultHelperMethod) => dd @@ -270,7 +276,7 @@ trait ClassLikeSupport: if parentSymbol != defn.ObjectClass && parentSymbol != defn.AnyClass yield (parentTree, parentSymbol) - def getConstructors: List[Symbol] = membersToDocument.collect { + def getConstructors: List[Symbol] = c.membersToDocument.collect { case d: DefDef if d.symbol.isClassConstructor && c.constructor.symbol != d.symbol => d.symbol }.toList diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala index 28440b066fa7..e7a23fa0e01f 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala @@ -3,48 +3,53 @@ package tasty import scala.quoted._ -trait SyntheticsSupport: - self: TastyParser => +object SyntheticsSupport: - import qctx.reflect._ + extension (using Quotes)(t: quotes.reflect.TypeRepr) + def isTupleType: Boolean = t.hackIsTupleType(t) - extension (t: TypeRepr) - def isTupleType: Boolean = hackIsTupleType(using qctx)(t) + def isCompiletimeAppliedType: Boolean = t.hackIsCompiletimeAppliedType(t) - def isCompiletimeAppliedType: Boolean = hackIsCompiletimeAppliedType(using qctx)(t) - - def hackIsTupleType(using Quotes)(rtpe: qctx.reflect.TypeRepr): Boolean = + private def hackIsTupleType(rtpe: quotes.reflect.TypeRepr): Boolean = import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val tpe = rtpe.asInstanceOf[dotc.core.Types.Type] ctx.definitions.isTupleType(tpe) - def hackIsCompiletimeAppliedType(using Quotes)(rtpe: qctx.reflect.TypeRepr): Boolean = + private def hackIsCompiletimeAppliedType(rtpe: quotes.reflect.TypeRepr): Boolean = import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val tpe = rtpe.asInstanceOf[dotc.core.Types.Type] ctx.definitions.isCompiletimeAppliedType(tpe.typeSymbol) + end extension - extension (s: Symbol) - def isSyntheticFunc: Boolean = s.flags.is(Flags.Synthetic) || s.flags.is(Flags.FieldAccessor) || isDefaultHelperMethod + extension (using Quotes)(s: quotes.reflect.Symbol) + def isSyntheticFunc: Boolean = + import quotes.reflect._ + s.flags.is(Flags.Synthetic) || s.flags.is(Flags.FieldAccessor) || s.isDefaultHelperMethod def isSuperBridgeMethod: Boolean = s.name.contains("$super$") def isDefaultHelperMethod: Boolean = ".*\\$default\\$\\d+$".r.matches(s.name) - def isOpaque: Boolean = s.flags.is(Flags.Opaque) + def isOpaque: Boolean = + import quotes.reflect._ + s.flags.is(Flags.Opaque) + + def isInfix: Boolean = hackIsInfix(s) - def isInfix: Boolean = hackIsInfix(using qctx)(s) + def getmembers: List[quotes.reflect.Symbol] = hackGetmembers(s) - def getmembers: List[Symbol] = hackGetmembers(using qctx)(s) + end extension - def isValidPos(pos: Position) = - if hackExists(using qctx)(pos) then pos.start != pos.end else false + def isValidPos(using Quotes)(pos: quotes.reflect.Position) = + if hackExists(pos) then pos.start != pos.end else false - def isSyntheticField(c: Symbol) = + def isSyntheticField(using Quotes)(c: quotes.reflect.Symbol) = + import quotes.reflect._ c.flags.is(Flags.CaseAccessor) || (c.flags.is(Flags.Module) && !c.flags.is(Flags.Given)) - def constructorWithoutParamLists(c: ClassDef): Boolean = + def constructorWithoutParamLists(using Quotes)(c: quotes.reflect.ClassDef): Boolean = !isValidPos(c.constructor.pos) || { val end = c.constructor.pos.end val typesEnd = c.constructor.leadingTypeParams.lastOption.fold(end - 1)(_.pos.end) @@ -53,10 +58,10 @@ trait SyntheticsSupport: } // TODO: #49 Remove it after TASTY-Reflect release with published flag Extension - def hackIsInfix(using Quotes)(rsym: qctx.reflect.Symbol): Boolean = { - import qctx.reflect._ + private def hackIsInfix(using Quotes)(rsym: quotes.reflect.Symbol): Boolean = { + import quotes.reflect._ import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] ctx.definitions.isInfix(sym) } @@ -64,10 +69,10 @@ trait SyntheticsSupport: They are valdefs that describe case companion objects and cases from enum. TASTY crashed when calling _.tree on them. */ - def hackGetmembers(using Quotes)(rsym: qctx.reflect.Symbol): List[qctx.reflect.Symbol] = { - import qctx.reflect._ + private def hackGetmembers(using Quotes)(rsym: quotes.reflect.Symbol): List[quotes.reflect.Symbol] = { + import quotes.reflect._ import dotty.tools.dotc - given ctx: dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] sym.typeRef.appliedTo(sym.typeParams.map(_.typeRef)).allMembers.iterator.map(_.symbol) .collect { @@ -78,10 +83,10 @@ trait SyntheticsSupport: }.toList } - def hackGetSupertypes(using Quotes)(rdef: qctx.reflect.ClassDef) = { - import qctx.reflect._ + private def hackGetSupertypes(using Quotes)(rdef: quotes.reflect.ClassDef) = { + import quotes.reflect._ import dotty.tools.dotc - given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val classdef = rdef.asInstanceOf[dotc.ast.tpd.TypeDef] val ref = classdef.symbol.info.asInstanceOf[dotc.core.Types.ClassInfo].appliedRef val baseTypes: List[(dotc.core.Symbols.Symbol, dotc.core.Types.Type)] = @@ -89,28 +94,28 @@ trait SyntheticsSupport: baseTypes.asInstanceOf[List[(Symbol, TypeRepr)]] } - def hackExists(using Quotes)(rpos: qctx.reflect.Position) = { - import qctx.reflect._ + private def hackExists(using Quotes)(rpos: quotes.reflect.Position) = { + import quotes.reflect._ import dotty.tools.dotc import dotty.tools.dotc.util.Spans._ - given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val pos = rpos.asInstanceOf[dotc.util.SourcePosition] pos.exists } - def getSupertypes(using Quotes)(c: ClassDef) = hackGetSupertypes(c).tail + def getSupertypes(using Quotes)(c: quotes.reflect.ClassDef) = hackGetSupertypes(c).tail - def typeForClass(c: ClassDef): TypeRepr = - import qctx.reflect._ + def typeForClass(using Quotes)(c: quotes.reflect.ClassDef): quotes.reflect.TypeRepr = + import quotes.reflect._ import dotty.tools.dotc - given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val cSym = c.symbol.asInstanceOf[dotc.core.Symbols.Symbol] cSym.typeRef.appliedTo(cSym.typeParams.map(_.typeRef)).asInstanceOf[TypeRepr] - def memberInfo(c: ClassDef, symbol: Symbol): TypeRepr = - import qctx.reflect._ + def memberInfo(using Quotes)(c: quotes.reflect.ClassDef, symbol: quotes.reflect.Symbol): quotes.reflect.TypeRepr = + import quotes.reflect._ import dotty.tools.dotc - given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx typeForClass(c).asInstanceOf[dotc.core.Types.Type] .memberInfo(symbol.asInstanceOf[dotc.core.Symbols.Symbol]) .asInstanceOf[TypeRepr] diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index cd834f162d22..3b0479140a7d 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -178,7 +178,7 @@ case class TastyParser( isSkipped: qctx.reflect.Symbol => Boolean )( using val ctx: DocContext -) extends BasicSupport with TypesSupport with ClassLikeSupport with SyntheticsSupport with PackageSupport: +) extends BasicSupport with TypesSupport with ClassLikeSupport with PackageSupport: import qctx.reflect._ private given qctx.type = qctx diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index a3f71a5dbe24..71b4de3b4220 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -4,6 +4,7 @@ package tasty import collection.JavaConverters._ import NameNormalizer._ +import SyntheticsSupport._ trait TypesSupport: self: TastyParser => From 0348d4870b2383785e9dedec1085f640d779fa19 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 23:17:05 +0200 Subject: [PATCH 7/9] Partial cleanup of TypesSupport --- .../tools/scaladoc/tasty/TypesSupport.scala | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index 71b4de3b4220..f1e1da6c522e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -3,18 +3,21 @@ package tasty import collection.JavaConverters._ +import scala.quoted._ + import NameNormalizer._ import SyntheticsSupport._ trait TypesSupport: self: TastyParser => - import qctx.reflect._ - private given qctx.type = qctx type DocSignaturePart = String | Link type DocSignature = List[DocSignaturePart] - def getGivenInstance(method: DefDef): Option[DocSignature] = + def getGivenInstance(method: qctx.reflect.DefDef): Option[DocSignature] = + import qctx.reflect._ + given qctx.type = qctx + def extractTypeSymbol(t: Tree): Option[Symbol] = t match case tpeTree: TypeTree => inner(tpeTree.tpe) @@ -41,15 +44,16 @@ trait TypesSupport: }.flatten.map(_.asSignature) given TreeSyntax: AnyRef with - extension (tpeTree: Tree) + extension (using Quotes)(tpeTree: quotes.reflect.Tree) def asSignature: DocSignature = + import quotes.reflect._ tpeTree match case TypeBoundsTree(low, high) => typeBoundsTreeOfHigherKindedType(low.tpe, high.tpe) case tpeTree: TypeTree => inner(tpeTree.tpe) case term: Term => inner(term.tpe) given TypeSyntax: AnyRef with - extension (tpe: TypeRepr) + extension (using Quotes)(tpe: quotes.reflect.TypeRepr) def asSignature: DocSignature = inner(tpe) @@ -57,7 +61,7 @@ trait TypesSupport: private def texts(str: String): DocSignature = List(text(str)) - private def link(symbol: Symbol): DocSignature = + private def link(using Quotes)(symbol: quotes.reflect.Symbol): DocSignature = val suffix = if symbol.isValDef then texts(".type") else Nil Link(symbol.normalizedName, symbol.dri) :: suffix @@ -65,14 +69,16 @@ trait TypesSupport: case List(single) => single case other => other.reduce((r, e) => r ++ texts(", ") ++ e) - private def isRepeatedAnnotation(term: Term) = + private def isRepeatedAnnotation(using Quotes)(term: quotes.reflect.Term) = + import quotes.reflect._ term.tpe match case t: TypeRef => t.name == "Repeated" && t.qualifier.match case ThisType(tref: TypeRef) if tref.name == "internal" => true case _ => false case _ => false - private def isRepeated(typeRepr: TypeRepr) = + private def isRepeated(using Quotes)(typeRepr: quotes.reflect.TypeRepr) = + import quotes.reflect._ typeRepr match case t: TypeRef => t.name == "" && t.qualifier.match case ThisType(tref: TypeRef) if tref.name == "scala" => true @@ -80,7 +86,8 @@ trait TypesSupport: case _ => false // TODO #23 add support for all types signatures that makes sense - private def inner(tp: TypeRepr): DocSignature = + private def inner(using Quotes)(tp: quotes.reflect.TypeRepr): DocSignature = + import quotes.reflect._ def noSupported(name: String): DocSignature = println(s"WARN: Unsupported type: $name: ${tp.show}") List(text(s"Unsupported[$name]")) @@ -265,8 +272,9 @@ trait TypesSupport: case RecursiveType(tp) => inner(tp) - private def typeBound(t: TypeRepr, low: Boolean) = - val ignore = if(low) t.typeSymbol == defn.NothingClass else t.typeSymbol == defn.AnyClass + private def typeBound(using Quotes)(t: quotes.reflect.TypeRepr, low: Boolean) = + import quotes.reflect._ + val ignore = if (low) t.typeSymbol == defn.NothingClass else t.typeSymbol == defn.AnyClass val prefix = text(if low then " >: " else " <: ") t match { case l: TypeLambda => prefix :: texts("(") ++ inner(l) ++ texts(")") @@ -275,7 +283,8 @@ trait TypesSupport: case _ => Nil } - private def typeBoundsTreeOfHigherKindedType(low: TypeRepr, high: TypeRepr) = + private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: quotes.reflect.TypeRepr, high: quotes.reflect.TypeRepr) = + import quotes.reflect._ def regularTypeBounds(low: TypeRepr, high: TypeRepr) = typeBound(low, low = true) ++ typeBound(high, low = false) high.match From 4b734bf2b60f4bab8eb308570061496c96c3b982 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 23:23:47 +0200 Subject: [PATCH 8/9] Partially cleanup BasicSupport --- .../dotty/tools/scaladoc/tasty/BasicSupport.scala | 14 ++++++-------- .../tools/scaladoc/tasty/ClassLikeSupport.scala | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala index 11a46c1707da..fa5a958dc21a 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala @@ -10,13 +10,13 @@ import ScaladocSupport._ trait BasicSupport: self: TastyParser => - import qctx.reflect._ + object SymOpsWithLinkCache extends SymOpsWithLinkCache export SymOpsWithLinkCache._ - private given qctx.type = qctx - def parseAnnotation(annotTerm: Term): Annotation = + def parseAnnotation(using Quotes)(annotTerm: quotes.reflect.Term): Annotation = + import quotes.reflect._ import dotty.tools.dotc.ast.Trees.{SeqLiteral} val dri = annotTerm.tpe.typeSymbol.dri def inner(t: Term): List[Annotation.AnnotationParameter] = t match { @@ -29,7 +29,6 @@ trait BasicSupport: case other => List(Annotation.UnresolvedParameter(None, other.show)) } - val params = annotTerm match case Apply(target, appliedWith) => { appliedWith.flatMap(inner) @@ -37,10 +36,10 @@ trait BasicSupport: Annotation(dri, params) - extension (sym: Symbol) + extension (using Quotes)(sym: quotes.reflect.Symbol) def documentation = sym.docstring.map(parseComment(_, sym.tree)) - def source(using Quotes) = + def source = val path = sym.pos.map(_.sourceFile.jpath).filter(_ != null).map(_.toAbsolutePath) path.map(TastyMemberSource(_, sym.pos.get.startLine)) @@ -54,5 +53,4 @@ trait BasicSupport: }.map(parseAnnotation) def isLeftAssoc: Boolean = !sym.name.endsWith(":") - - + end extension diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index df959f192e8f..7c1d6a85b111 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -455,7 +455,7 @@ trait ClassLikeSupport: modifiers = modifiers, annotations = symbol.getAnnotations(), signature = signature, - sources = symbol.source(using qctx), + sources = symbol.source, origin = origin, inheritedFrom = inheritedFrom, graph = graph, From 0b0fafdbdf28c8f68994ee5a4ddc51fe3f1d4ace Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 4 May 2021 23:55:45 +0200 Subject: [PATCH 9/9] Add `refelct` shorthand for `quotes.reflect` --- .../tools/scaladoc/tasty/BasicSupport.scala | 6 +-- .../scaladoc/tasty/ClassLikeSupport.scala | 6 +-- .../scaladoc/tasty/JavadocAnchorCreator.scala | 12 ++--- .../tools/scaladoc/tasty/NameNormalizer.scala | 4 +- .../scaladoc/tasty/ScalaDocSupport.scala | 6 +-- .../tasty/Scaladoc2AnchorCreator.scala | 4 +- .../dotty/tools/scaladoc/tasty/SymOps.scala | 38 +++++++-------- .../scaladoc/tasty/SyntheticSupport.scala | 48 +++++++++---------- .../tools/scaladoc/tasty/TastyParser.scala | 24 +++++----- .../tools/scaladoc/tasty/TypesSupport.scala | 28 +++++------ .../tasty/comments/MemberLookup.scala | 39 +++++++-------- .../dotty/tools/scaladoc/tasty/reflect.scala | 7 +++ .../tasty/comments/CommentExpanderTests.scala | 20 ++++---- 13 files changed, 125 insertions(+), 117 deletions(-) create mode 100644 scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala index fa5a958dc21a..77cf553c82c9 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/BasicSupport.scala @@ -15,8 +15,8 @@ trait BasicSupport: export SymOpsWithLinkCache._ - def parseAnnotation(using Quotes)(annotTerm: quotes.reflect.Term): Annotation = - import quotes.reflect._ + def parseAnnotation(using Quotes)(annotTerm: reflect.Term): Annotation = + import reflect._ import dotty.tools.dotc.ast.Trees.{SeqLiteral} val dri = annotTerm.tpe.typeSymbol.dri def inner(t: Term): List[Annotation.AnnotationParameter] = t match { @@ -36,7 +36,7 @@ trait BasicSupport: Annotation(dri, params) - extension (using Quotes)(sym: quotes.reflect.Symbol) + extension (using Quotes)(sym: reflect.Symbol) def documentation = sym.docstring.map(parseComment(_, sym.tree)) def source = diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala index 7c1d6a85b111..c3a539af766e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ClassLikeSupport.scala @@ -16,8 +16,8 @@ trait ClassLikeSupport: private given qctx.type = qctx - private def bareClasslikeKind(using Quotes)(symbol: quotes.reflect.Symbol): Kind = - import quotes.reflect._ + private def bareClasslikeKind(using Quotes)(symbol: reflect.Symbol): Kind = + import reflect._ if symbol.flags.is(Flags.Module) then Kind.Object else if symbol.flags.is(Flags.Trait) then Kind.Trait(Nil, Nil) else if symbol.flags.is(Flags.Enum) then Kind.Enum(Nil, Nil) @@ -217,7 +217,7 @@ trait ClassLikeSupport: } ).map(_.copy(inheritedFrom = inheritance)) - extension (using Quotes)(c: quotes.reflect.ClassDef) + extension (using Quotes)(c: reflect.ClassDef) def membersToDocument = c.body.filterNot(_.symbol.isHiddenByVisibility) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala index c798e81a6a1e..ea7dc32a7e58 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/JavadocAnchorCreator.scala @@ -7,8 +7,8 @@ import scala.util.matching.Regex object JavadocAnchorCreator: - private def javadocPrimitives(using Quotes)(sym: quotes.reflect.Symbol) = - import quotes.reflect.* + private def javadocPrimitives(using Quotes)(sym: reflect.Symbol) = + import reflect.* if sym == defn.IntClass then Some("int") else if sym == defn.FloatClass then Some("float") else if sym == defn.DoubleClass then Some("double") @@ -20,17 +20,17 @@ object JavadocAnchorCreator: else if sym == defn.ObjectClass then Some("java.lang.Object") else None - private def transformPrimitiveType(using Quotes)(tpe: quotes.reflect.TypeRepr): String = tpe.classSymbol + private def transformPrimitiveType(using Quotes)(tpe: reflect.TypeRepr): String = tpe.classSymbol .flatMap(javadocPrimitives) .filter(_ => !tpe.typeSymbol.isTypeParam) .getOrElse(tpe.show) - private def transformType(using Quotes)(tpe: quotes.reflect.TypeRepr): String = - import quotes.reflect.* + private def transformType(using Quotes)(tpe: reflect.TypeRepr): String = + import reflect.* tpe.simplified match case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.ArrayClass) => transformType(typeList.head) + ":A" case AppliedType(tpe, typeList) if tpe.classSymbol.fold(false)(_ == defn.RepeatedParamClass) => transformType(typeList.head) + "..." case AppliedType(tpe, typeList) => transformPrimitiveType(tpe) case other => transformPrimitiveType(other) - def getJavadocType(using Quotes)(s: quotes.reflect.TypeRepr) = transformType(s) + def getJavadocType(using Quotes)(s: reflect.TypeRepr) = transformType(s) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala index 502a5ec62f9a..932d437353ab 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/NameNormalizer.scala @@ -9,8 +9,8 @@ import SymOps._ object NameNormalizer { - extension (using Quotes)(s: quotes.reflect.Symbol) def normalizedName: String = { - import quotes.reflect.* + extension (using Quotes)(s: reflect.Symbol) def normalizedName: String = { + import reflect.* val withoutGivenPrefix = if s.isGiven then s.name.stripPrefix("given_") else s.name val withoutObjectSuffix = if s.flags.is(Flags.Module) then withoutGivenPrefix.stripSuffix("$") else withoutGivenPrefix val constructorNormalizedName = if s.isClassConstructor then "this" else withoutObjectSuffix diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala index fb22a58ab3b7..1c634df8c918 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/ScalaDocSupport.scala @@ -10,8 +10,8 @@ import scala.quoted._ object ScaladocSupport: - def parseCommentString(using Quotes, DocContext)(comment: String, sym: quotes.reflect.Symbol, pos: Option[quotes.reflect.Position]): Comment = - import quotes.reflect.report + def parseCommentString(using Quotes, DocContext)(comment: String, sym: reflect.Symbol, pos: Option[reflect.Position]): Comment = + import reflect.report val preparsed = comments.Preparser.preparse(comments.Cleaner.clean(comment)) val commentSyntax = @@ -35,7 +35,7 @@ object ScaladocSupport: } parser.parse(preparsed) - def parseComment(using Quotes, DocContext)(docstring: String, tree: quotes.reflect.Tree): Comment = + def parseComment(using Quotes, DocContext)(docstring: String, tree: reflect.Tree): Comment = val commentString: String = if tree.symbol.isClassDef || tree.symbol.owner.isClassDef then import dotty.tools.dotc diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala index dc791c7422fc..ba59f77495b1 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/Scaladoc2AnchorCreator.scala @@ -7,8 +7,8 @@ import scala.util.matching.Regex object Scaladoc2AnchorCreator: - def getScaladoc2Type(using Quotes)(t: quotes.reflect.Tree) = - import quotes.reflect.* + def getScaladoc2Type(using Quotes)(t: reflect.Tree) = + import reflect.* val regex = t match case d: DefDef => "def" case t: TypeDef => "type" diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala index 1cb1ff471d73..cdb1e889b29c 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SymOps.scala @@ -10,7 +10,7 @@ import JavadocAnchorCreator.getJavadocType object SymOps: - extension (using Quotes)(sym: quotes.reflect.Symbol) + extension (using Quotes)(sym: reflect.Symbol) def packageName: String = if (sym.isPackageDef) sym.fullName @@ -20,7 +20,7 @@ object SymOps: sym.packageName.split('.').toList def className: Option[String] = - import quotes.reflect._ + import reflect._ if (sym.isClassDef && !sym.flags.is(Flags.Package)) Some( Some(sym.maybeOwner).filter(s => s.exists).flatMap(_.className).fold("")(cn => cn + "$") + sym.name ).filterNot(_.contains("package$")) @@ -42,7 +42,7 @@ object SymOps: def getVisibility(): Visibility = - import quotes.reflect._ + import reflect._ import VisibilityScope._ def explicitScope(ownerType: TypeRepr): VisibilityScope = @@ -70,7 +70,7 @@ object SymOps: // Order here determines order in documenation def getExtraModifiers(): Seq[Modifier] = - import quotes.reflect._ + import reflect._ Seq( Flags.Final -> Modifier.Final, Flags.Sealed -> Modifier.Sealed, @@ -94,42 +94,42 @@ object SymOps: case _ => false def shouldDocumentClasslike(using dctx: DocContext): Boolean = - import quotes.reflect._ + import reflect._ !sym.isHiddenByVisibility && !sym.flags.is(Flags.Synthetic) && (!sym.flags.is(Flags.Case) || !sym.flags.is(Flags.Enum)) && !(sym.companionModule.flags.is(Flags.Given)) - def getCompanionSymbol: Option[quotes.reflect.Symbol] = Some(sym.companionClass).filter(_.exists) + def getCompanionSymbol: Option[reflect.Symbol] = Some(sym.companionClass).filter(_.exists) def isCompanionObject: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.Module) && sym.companionClass.exists def isGiven: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.Given) def isExported: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.Exported) def isOverridden: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.Override) def isExtensionMethod: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.ExtensionMethod) def isArtifact: Boolean = - import quotes.reflect._ + import reflect._ sym.flags.is(Flags.Artifact) def isLeftAssoc: Boolean = !sym.name.endsWith(":") - def extendedSymbol: Option[quotes.reflect.ValDef] = - import quotes.reflect.* + def extendedSymbol: Option[reflect.ValDef] = + import reflect.* Option.when(sym.isExtensionMethod){ val termParamss = sym.tree.asInstanceOf[DefDef].termParamss if sym.isLeftAssoc || termParamss.size == 1 then termParamss(0).params(0) @@ -146,10 +146,10 @@ class SymOpsWithLinkCache: private val externalLinkCache: scala.collection.mutable.Map[AbstractFile, Option[ExternalDocLink]] = MMap() - extension (using Quotes)(sym: quotes.reflect.Symbol) + extension (using Quotes)(sym: reflect.Symbol) private def constructPath(location: Seq[String], anchor: Option[String], link: ExternalDocLink): String = - import quotes.reflect.* + import reflect.* val extension = ".html" val docURL = link.documentationUrl.toString def constructPathForJavadoc: String = @@ -183,7 +183,7 @@ class SymOpsWithLinkCache: // TODO #22 make sure that DRIs are unique plus probably reuse semantic db code? def dri(using dctx: DocContext): DRI = - import quotes.reflect.* + import reflect.* if sym == Symbol.noSymbol then topLevelDri else if sym.isValDef && sym.moduleClass.exists then sym.moduleClass.dri else @@ -200,7 +200,7 @@ class SymOpsWithLinkCache: val location = sym.packageNameSplitted ++ className val externalLink = { - import quotes.reflect._ + import reflect._ import dotty.tools.dotc given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val csym = sym.asInstanceOf[dotc.core.Symbols.Symbol] @@ -223,7 +223,7 @@ class SymOpsWithLinkCache: s"${sym.name}${sym.fullName}/${sym.signature.resultSig}/[${sym.signature.paramSigs.mkString("/")}]" ) - def driInContextOfInheritingParent(par: quotes.reflect.Symbol)(using dctx: DocContext): DRI = sym.dri.copy( + def driInContextOfInheritingParent(par: reflect.Symbol)(using dctx: DocContext): DRI = sym.dri.copy( location = par.dri.location, externalLink = None ) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala index e7a23fa0e01f..fe8b94817e3e 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/SyntheticSupport.scala @@ -5,27 +5,27 @@ import scala.quoted._ object SyntheticsSupport: - extension (using Quotes)(t: quotes.reflect.TypeRepr) + extension (using Quotes)(t: reflect.TypeRepr) def isTupleType: Boolean = t.hackIsTupleType(t) def isCompiletimeAppliedType: Boolean = t.hackIsCompiletimeAppliedType(t) - private def hackIsTupleType(rtpe: quotes.reflect.TypeRepr): Boolean = + private def hackIsTupleType(rtpe: reflect.TypeRepr): Boolean = import dotty.tools.dotc given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val tpe = rtpe.asInstanceOf[dotc.core.Types.Type] ctx.definitions.isTupleType(tpe) - private def hackIsCompiletimeAppliedType(rtpe: quotes.reflect.TypeRepr): Boolean = + private def hackIsCompiletimeAppliedType(rtpe: reflect.TypeRepr): Boolean = import dotty.tools.dotc given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val tpe = rtpe.asInstanceOf[dotc.core.Types.Type] ctx.definitions.isCompiletimeAppliedType(tpe.typeSymbol) end extension - extension (using Quotes)(s: quotes.reflect.Symbol) + extension (using Quotes)(s: reflect.Symbol) def isSyntheticFunc: Boolean = - import quotes.reflect._ + import reflect._ s.flags.is(Flags.Synthetic) || s.flags.is(Flags.FieldAccessor) || s.isDefaultHelperMethod def isSuperBridgeMethod: Boolean = s.name.contains("$super$") @@ -33,23 +33,23 @@ object SyntheticsSupport: def isDefaultHelperMethod: Boolean = ".*\\$default\\$\\d+$".r.matches(s.name) def isOpaque: Boolean = - import quotes.reflect._ + import reflect._ s.flags.is(Flags.Opaque) def isInfix: Boolean = hackIsInfix(s) - def getmembers: List[quotes.reflect.Symbol] = hackGetmembers(s) + def getmembers: List[reflect.Symbol] = hackGetmembers(s) end extension - def isValidPos(using Quotes)(pos: quotes.reflect.Position) = + def isValidPos(using Quotes)(pos: reflect.Position) = if hackExists(pos) then pos.start != pos.end else false - def isSyntheticField(using Quotes)(c: quotes.reflect.Symbol) = - import quotes.reflect._ + def isSyntheticField(using Quotes)(c: reflect.Symbol) = + import reflect._ c.flags.is(Flags.CaseAccessor) || (c.flags.is(Flags.Module) && !c.flags.is(Flags.Given)) - def constructorWithoutParamLists(using Quotes)(c: quotes.reflect.ClassDef): Boolean = + def constructorWithoutParamLists(using Quotes)(c: reflect.ClassDef): Boolean = !isValidPos(c.constructor.pos) || { val end = c.constructor.pos.end val typesEnd = c.constructor.leadingTypeParams.lastOption.fold(end - 1)(_.pos.end) @@ -58,8 +58,8 @@ object SyntheticsSupport: } // TODO: #49 Remove it after TASTY-Reflect release with published flag Extension - private def hackIsInfix(using Quotes)(rsym: quotes.reflect.Symbol): Boolean = { - import quotes.reflect._ + private def hackIsInfix(using Quotes)(rsym: reflect.Symbol): Boolean = { + import reflect._ import dotty.tools.dotc given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] @@ -69,8 +69,8 @@ object SyntheticsSupport: They are valdefs that describe case companion objects and cases from enum. TASTY crashed when calling _.tree on them. */ - private def hackGetmembers(using Quotes)(rsym: quotes.reflect.Symbol): List[quotes.reflect.Symbol] = { - import quotes.reflect._ + private def hackGetmembers(using Quotes)(rsym: reflect.Symbol): List[reflect.Symbol] = { + import reflect._ import dotty.tools.dotc given ctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] @@ -83,8 +83,8 @@ object SyntheticsSupport: }.toList } - private def hackGetSupertypes(using Quotes)(rdef: quotes.reflect.ClassDef) = { - import quotes.reflect._ + private def hackGetSupertypes(using Quotes)(rdef: reflect.ClassDef) = { + import reflect._ import dotty.tools.dotc given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val classdef = rdef.asInstanceOf[dotc.ast.tpd.TypeDef] @@ -94,8 +94,8 @@ object SyntheticsSupport: baseTypes.asInstanceOf[List[(Symbol, TypeRepr)]] } - private def hackExists(using Quotes)(rpos: quotes.reflect.Position) = { - import quotes.reflect._ + private def hackExists(using Quotes)(rpos: reflect.Position) = { + import reflect._ import dotty.tools.dotc import dotty.tools.dotc.util.Spans._ given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx @@ -103,17 +103,17 @@ object SyntheticsSupport: pos.exists } - def getSupertypes(using Quotes)(c: quotes.reflect.ClassDef) = hackGetSupertypes(c).tail + def getSupertypes(using Quotes)(c: reflect.ClassDef) = hackGetSupertypes(c).tail - def typeForClass(using Quotes)(c: quotes.reflect.ClassDef): quotes.reflect.TypeRepr = - import quotes.reflect._ + def typeForClass(using Quotes)(c: reflect.ClassDef): reflect.TypeRepr = + import reflect._ import dotty.tools.dotc given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val cSym = c.symbol.asInstanceOf[dotc.core.Symbols.Symbol] cSym.typeRef.appliedTo(cSym.typeParams.map(_.typeRef)).asInstanceOf[TypeRepr] - def memberInfo(using Quotes)(c: quotes.reflect.ClassDef, symbol: quotes.reflect.Symbol): quotes.reflect.TypeRepr = - import quotes.reflect._ + def memberInfo(using Quotes)(c: reflect.ClassDef, symbol: reflect.Symbol): reflect.TypeRepr = + import reflect._ import dotty.tools.dotc given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx typeForClass(c).asInstanceOf[dotc.core.Types.Type] diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala index 3b0479140a7d..69d83e126b36 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TastyParser.scala @@ -6,7 +6,7 @@ import java.util.regex.Pattern import scala.util.{Try, Success, Failure} import scala.tasty.inspector.DocTastyInspector -import scala.quoted.Quotes +import scala.quoted._ import dotty.tools.dotc @@ -29,22 +29,22 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe private val topLevels = Seq.newBuilder[(String, Member)] private var rootDoc: Option[Comment] = None - def processCompilationUnit(using quotes: Quotes)(root: quotes.reflect.Tree): Unit = () + def processCompilationUnit(using Quotes)(root: reflect.Tree): Unit = () - override def postProcess(using q: Quotes): Unit = + override def postProcess(using Quotes): Unit = // hack into the compiler to get a list of all top-level trees // in principle, to do this, one would collect trees in processCompilationUnit // however, path-dependent types disallow doing so w/o using casts - inline def hackForeachTree(thunk: q.reflect.Tree => Unit): Unit = - given dctx: dotc.core.Contexts.Context = q.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx + inline def hackForeachTree(thunk: reflect.Tree => Unit): Unit = + given dctx: dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx dctx.run.units.foreach { compilationUnit => // mirrors code from TastyInspector - thunk(compilationUnit.tpdTree.asInstanceOf[q.reflect.Tree]) + thunk(compilationUnit.tpdTree.asInstanceOf[reflect.Tree]) } - val symbolsToSkip: Set[q.reflect.Symbol] = + val symbolsToSkip: Set[reflect.Symbol] = ctx.args.identifiersToSkip.flatMap { ref => - val qrSymbol = q.reflect.Symbol + val qrSymbol = reflect.Symbol Try(qrSymbol.requiredPackage(ref)).orElse(Try(qrSymbol.requiredClass(ref))) match { case Success(sym) => Some(sym) case Failure(err) => @@ -68,18 +68,18 @@ case class ScaladocTastyInspector()(using ctx: DocContext) extends DocTastyInspe None } - def isSkipped(sym: q.reflect.Symbol): Boolean = - def isSkippedById(sym: q.reflect.Symbol): Boolean = + def isSkipped(sym: reflect.Symbol): Boolean = + def isSkippedById(sym: reflect.Symbol): Boolean = if !sym.exists then false else symbolsToSkip.contains(sym) || isSkipped(sym.owner) - def isSkippedByRx(sym: q.reflect.Symbol): Boolean = + def isSkippedByRx(sym: reflect.Symbol): Boolean = val symStr = sym.fullName patternsToSkip.exists(p => p.matcher(symStr).matches()) isSkippedById(sym) || isSkippedByRx(sym) - val parser = new TastyParser(q, this)(isSkipped) + val parser = new TastyParser(quotes, this)(isSkipped) def driFor(link: String): Option[DRI] = val symOps = new SymOpsWithLinkCache import symOps._ diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala index f1e1da6c522e..ca61a47ef5b7 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/TypesSupport.scala @@ -44,16 +44,16 @@ trait TypesSupport: }.flatten.map(_.asSignature) given TreeSyntax: AnyRef with - extension (using Quotes)(tpeTree: quotes.reflect.Tree) + extension (using Quotes)(tpeTree: reflect.Tree) def asSignature: DocSignature = - import quotes.reflect._ + import reflect._ tpeTree match case TypeBoundsTree(low, high) => typeBoundsTreeOfHigherKindedType(low.tpe, high.tpe) case tpeTree: TypeTree => inner(tpeTree.tpe) case term: Term => inner(term.tpe) given TypeSyntax: AnyRef with - extension (using Quotes)(tpe: quotes.reflect.TypeRepr) + extension (using Quotes)(tpe: reflect.TypeRepr) def asSignature: DocSignature = inner(tpe) @@ -61,7 +61,7 @@ trait TypesSupport: private def texts(str: String): DocSignature = List(text(str)) - private def link(using Quotes)(symbol: quotes.reflect.Symbol): DocSignature = + private def link(using Quotes)(symbol: reflect.Symbol): DocSignature = val suffix = if symbol.isValDef then texts(".type") else Nil Link(symbol.normalizedName, symbol.dri) :: suffix @@ -69,16 +69,16 @@ trait TypesSupport: case List(single) => single case other => other.reduce((r, e) => r ++ texts(", ") ++ e) - private def isRepeatedAnnotation(using Quotes)(term: quotes.reflect.Term) = - import quotes.reflect._ + private def isRepeatedAnnotation(using Quotes)(term: reflect.Term) = + import reflect._ term.tpe match case t: TypeRef => t.name == "Repeated" && t.qualifier.match case ThisType(tref: TypeRef) if tref.name == "internal" => true case _ => false case _ => false - private def isRepeated(using Quotes)(typeRepr: quotes.reflect.TypeRepr) = - import quotes.reflect._ + private def isRepeated(using Quotes)(typeRepr: reflect.TypeRepr) = + import reflect._ typeRepr match case t: TypeRef => t.name == "" && t.qualifier.match case ThisType(tref: TypeRef) if tref.name == "scala" => true @@ -86,8 +86,8 @@ trait TypesSupport: case _ => false // TODO #23 add support for all types signatures that makes sense - private def inner(using Quotes)(tp: quotes.reflect.TypeRepr): DocSignature = - import quotes.reflect._ + private def inner(using Quotes)(tp: reflect.TypeRepr): DocSignature = + import reflect._ def noSupported(name: String): DocSignature = println(s"WARN: Unsupported type: $name: ${tp.show}") List(text(s"Unsupported[$name]")) @@ -272,8 +272,8 @@ trait TypesSupport: case RecursiveType(tp) => inner(tp) - private def typeBound(using Quotes)(t: quotes.reflect.TypeRepr, low: Boolean) = - import quotes.reflect._ + private def typeBound(using Quotes)(t: reflect.TypeRepr, low: Boolean) = + import reflect._ val ignore = if (low) t.typeSymbol == defn.NothingClass else t.typeSymbol == defn.AnyClass val prefix = text(if low then " >: " else " <: ") t match { @@ -283,8 +283,8 @@ trait TypesSupport: case _ => Nil } - private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: quotes.reflect.TypeRepr, high: quotes.reflect.TypeRepr) = - import quotes.reflect._ + private def typeBoundsTreeOfHigherKindedType(using Quotes)(low: reflect.TypeRepr, high: reflect.TypeRepr) = + import reflect._ def regularTypeBounds(low: TypeRepr, high: TypeRepr) = typeBound(low, low = true) ++ typeBound(high, low = false) high.match diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/MemberLookup.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/MemberLookup.scala index da88f58eb9e8..14f14cbedbd1 100644 --- a/scaladoc/src/dotty/tools/scaladoc/tasty/comments/MemberLookup.scala +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/comments/MemberLookup.scala @@ -1,28 +1,29 @@ package dotty.tools.scaladoc -package tasty.comments +package tasty +package comments import scala.quoted._ trait MemberLookup { def memberLookupResult(using Quotes)( - symbol: quotes.reflect.Symbol, + symbol: reflect.Symbol, label: String, - inheritingParent: Option[quotes.reflect.Symbol] = None - ): (quotes.reflect.Symbol, String, Option[quotes.reflect.Symbol]) = + inheritingParent: Option[reflect.Symbol] = None + ): (reflect.Symbol, String, Option[reflect.Symbol]) = (symbol, label, inheritingParent) def lookup(using Quotes, DocContext)( query: Query, - owner: quotes.reflect.Symbol, - ): Option[(quotes.reflect.Symbol, String, Option[quotes.reflect.Symbol])] = lookupOpt(query, Some(owner)) + owner: reflect.Symbol, + ): Option[(reflect.Symbol, String, Option[reflect.Symbol])] = lookupOpt(query, Some(owner)) def lookupOpt(using Quotes, DocContext)( query: Query, - ownerOpt: Option[quotes.reflect.Symbol], - ): Option[(quotes.reflect.Symbol, String, Option[quotes.reflect.Symbol])] = + ownerOpt: Option[reflect.Symbol], + ): Option[(reflect.Symbol, String, Option[reflect.Symbol])] = try - import quotes.reflect._ + import reflect._ def nearestClass(sym: Symbol): Symbol = if sym.isClassDef then sym else nearestClass(sym.owner) @@ -90,8 +91,8 @@ trait MemberLookup { report.warn(msg, e) None - private def hackMembersOf(using Quotes)(rsym: quotes.reflect.Symbol) = { - import quotes.reflect._ + private def hackMembersOf(using Quotes)(rsym: reflect.Symbol) = { + import reflect._ import dotty.tools.dotc given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] @@ -103,7 +104,7 @@ trait MemberLookup { members.asInstanceOf[Iterator[Symbol]] } - private def hackIsNotAbsent(using Quotes)(rsym: quotes.reflect.Symbol) = + private def hackIsNotAbsent(using Quotes)(rsym: reflect.Symbol) = import dotty.tools.dotc given dotc.core.Contexts.Context = quotes.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx val sym = rsym.asInstanceOf[dotc.core.Symbols.Symbol] @@ -115,9 +116,9 @@ trait MemberLookup { private def localLookup(using Quotes)( sel: MemberLookup.Selector, - owner: quotes.reflect.Symbol - ): Iterator[quotes.reflect.Symbol] = { - import quotes.reflect._ + owner: reflect.Symbol + ): Iterator[reflect.Symbol] = { + import reflect._ def findMatch(syms: Iterator[Symbol]): Iterator[Symbol] = { def matches(s: Symbol): Boolean = @@ -173,9 +174,9 @@ trait MemberLookup { } private def downwardLookup(using Quotes)( - query: List[String], owner: quotes.reflect.Symbol - ): Option[(quotes.reflect.Symbol, Option[quotes.reflect.Symbol])] = { - import quotes.reflect._ + query: List[String], owner: reflect.Symbol + ): Option[(reflect.Symbol, Option[reflect.Symbol])] = { + import reflect._ query match { case Nil => None case q :: Nil => @@ -193,7 +194,7 @@ trait MemberLookup { res match { case None => None case Some(sym) => - val externalOwner: Option[quotes.reflect.Symbol] = + val externalOwner: Option[reflect.Symbol] = if owner eq sym.owner then None else if owner.flags.is(Flags.Module) then Some(owner.moduleClass) else if owner.isClassDef then Some(owner) diff --git a/scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala b/scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala new file mode 100644 index 000000000000..b48519e29d28 --- /dev/null +++ b/scaladoc/src/dotty/tools/scaladoc/tasty/reflect.scala @@ -0,0 +1,7 @@ +package dotty.tools.scaladoc +package tasty + +import scala.quoted._ + +/** Shorthand for `quotes.reflect` */ +transparent inline def reflect(using inline q: Quotes): q.reflect.type = q.reflect diff --git a/scaladoc/test/dotty/tools/scaladoc/tasty/comments/CommentExpanderTests.scala b/scaladoc/test/dotty/tools/scaladoc/tasty/comments/CommentExpanderTests.scala index 63bb4fb21f03..097401576069 100644 --- a/scaladoc/test/dotty/tools/scaladoc/tasty/comments/CommentExpanderTests.scala +++ b/scaladoc/test/dotty/tools/scaladoc/tasty/comments/CommentExpanderTests.scala @@ -1,5 +1,6 @@ package dotty.tools.scaladoc -package tasty.comments +package tasty +package comments import scala.quoted._ @@ -9,25 +10,25 @@ import dotty.tools.scaladoc.tasty.util._ import dotty.tools.scaladoc.tasty.TastyParser class CommentExpanderTests { - def check(using quoted.Quotes)(): Unit = + def check(using Quotes)(): Unit = assertCommentEquals( - qr.Symbol.requiredClass("tests.B").memberMethod("otherMethod").head, + reflect.Symbol.requiredClass("tests.B").memberMethod("otherMethod").head, "/** This is my foo: Bar, actually. */", ) assertCommentEquals( - qr.Symbol.requiredClass("tests.C"), + reflect.Symbol.requiredClass("tests.C"), "/** This is foo: Foo expanded. */", ) assertCommentEquals( - qr.Symbol.requiredModule("tests.O").memberMethod("method").head, + reflect.Symbol.requiredModule("tests.O").memberMethod("method").head, "/** This is foo: O's foo. */", ) def assertCommentEquals( - using quoted.Quotes + using Quotes )( - rsym: quotes.reflect.Symbol, + rsym: reflect.Symbol, str: String ): Unit = import dotty.tools.dotc @@ -41,13 +42,12 @@ class CommentExpanderTests { import scala.tasty.inspector.OldTastyInspector class Inspector extends OldTastyInspector: - def processCompilationUnit(using quoted.Quotes)(root: quotes.reflect.Tree): Unit = () + def processCompilationUnit(using Quotes)(root: reflect.Tree): Unit = () - override def postProcess(using quoted.Quotes): Unit = + override def postProcess(using Quotes): Unit = check() Inspector().inspectTastyFiles(TestUtils.listOurClasses()) } - private def qr(using quoted.Quotes): quotes.reflect.type = quotes.reflect }