<commit_before>package dotty.tools
package dottydoc
package core

/** Dotty and Dottydoc imports */
import dotc.ast.Trees._
import dotc.CompilationUnit
import dotc.config.Printers.dottydoc
import dotc.core.Contexts.Context
import dotc.core.Comments.ContextDocstrings
import dotc.core.Types.{PolyType, NoType}
import dotc.core.Phases.Phase
import dotc.core.Symbols.{ Symbol, NoSymbol }

class DocASTPhase extends Phase {
  import model._
  import model.factories._
  import model.internal._
  import model.comment.Comment
  import dotty.tools.dotc.core.Flags
  import dotty.tools.dotc.ast.tpd._
  import dotty.tools.dottydoc.util.syntax._
  import util.traversing._
  import util.internal.setters._

  def phaseName = "docASTPhase"

  /** Build documentation hierarchy from existing tree */
  def collect(tree: Tree)(implicit ctx: Context): Entity = {
    val implicitConversions = ctx.docbase.defs(tree.symbol)

    def collectList(xs: List[Tree]): List[Entity] =
      xs.map(collect).filter(_ != NonEntity)

    def collectEntityMembers(xs: List[Tree]) =
      collectList(xs).asInstanceOf[List[Entity with Members]]

    def collectMembers(tree: Tree)(implicit ctx: Context): List[Entity] = {
      val defs = (tree match {
        case t: Template => collectList(t.body)
        case _ => Nil
      })

      defs ++ implicitConversions.flatMap(membersFromSymbol)
    }

    def membersFromSymbol(sym: Symbol): List[Entity] = {
      if (sym.info.exists) {
        val defs = sym.info.bounds.hi.finalResultType.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private)
          .filterNot(_.symbol.owner.name.show == "Any")
          .map { meth =>
            DefImpl(
              meth.symbol,
              annotations(meth.symbol),
              meth.symbol.name.show,
              Nil,
              path(meth.symbol),
              returnType(meth.info),
              typeParams(meth.symbol),
              paramLists(meth.info),
              implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
            )
          }.toList

        // don't add privates, synthetics or class parameters (i.e. value class constructor val)
        val vals = sym.info.fields.filterNot(_.symbol.is(Flags.ParamAccessor | Flags.Private | Flags.Synthetic)).map { value =>
          val kind = if (value.symbol.is(Flags.Mutable)) "var" else "val"
          ValImpl(
            value.symbol,
            annotations(value.symbol),
            value.symbol.name.show,
            Nil, path(value.symbol),
            returnType(value.info),
            kind,
            implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
          )
        }

        defs ++ vals
      }
      else Nil
    }


    tree match {
      /** package */
      case pd @ PackageDef(pid, st) =>
        addPackage(PackageImpl(pd.symbol, annotations(pd.symbol), pd.symbol.showFullName, collectEntityMembers(st), path(pd.symbol)))

      /** type alias */
      case t: TypeDef if !t.isClassDef =>
        val sym = t.symbol
        if (sym.is(Flags.Synthetic | Flags.Param))
          NonEntity
        else {
          val tparams = t.rhs.tpe match {
            case tp: PolyType => tp.paramRefs.zip(tp.variances).map { case (tp, variance) =>
              val varianceSym = if (variance == 1) "+" else if (variance == -1) "-" else ""
              varianceSym + tp.paramName.show
            }
            case _ => Nil
          }
          TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams)
        }

      /** trait */
      case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
        //TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
        TraitImpl(t.symbol, annotations(t.symbol), n.show, collectMembers(rhs), flags(t), path(t.symbol), typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))

      /** objects, on the format "Object$" so drop the last letter */
      case o @ TypeDef(n, rhs) if o.symbol.is(Flags.Module) =><commit_msg>Fix dottydoc parameter printing<commit_after>package dotty.tools
package dottydoc
package core

/** Dotty and Dottydoc imports */
import dotc.ast.Trees._
import dotc.CompilationUnit
import dotc.config.Printers.dottydoc
import dotc.core.Contexts.Context
import dotc.core.Comments.ContextDocstrings
import dotc.core.Types.{PolyType, NoType}
import dotc.core.Phases.Phase
import dotc.core.Symbols.{ Symbol, NoSymbol }

class DocASTPhase extends Phase {
  import model._
  import model.factories._
  import model.internal._
  import model.comment.Comment
  import dotty.tools.dotc.core.Flags
  import dotty.tools.dotc.ast.tpd._
  import dotty.tools.dottydoc.util.syntax._
  import util.traversing._
  import util.internal.setters._

  def phaseName = "docASTPhase"

  /** Build documentation hierarchy from existing tree */
  def collect(tree: Tree)(implicit ctx: Context): Entity = {
    val implicitConversions = ctx.docbase.defs(tree.symbol)

    def collectList(xs: List[Tree]): List[Entity] =
      xs.map(collect).filter(_ != NonEntity)

    def collectEntityMembers(xs: List[Tree]) =
      collectList(xs).asInstanceOf[List[Entity with Members]]

    def collectMembers(tree: Tree)(implicit ctx: Context): List[Entity] = {
      val defs = (tree match {
        case t: Template => collectList(t.body)
        case _ => Nil
      })

      defs ++ implicitConversions.flatMap(membersFromSymbol)
    }

    def membersFromSymbol(sym: Symbol): List[Entity] = {
      if (sym.info.exists) {
        val defs = sym.info.bounds.hi.finalResultType.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private)
          .filterNot(_.symbol.owner.name.show == "Any")
          .map { meth =>
            DefImpl(
              meth.symbol,
              annotations(meth.symbol),
              meth.symbol.name.show,
              Nil,
              path(meth.symbol),
              returnType(meth.info),
              typeParams(meth.symbol),
              paramLists(meth.info),
              implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
            )
          }.toList

        // don't add privates, synthetics or class parameters (i.e. value class constructor val)
        val vals = sym.info.fields.filterNot(_.symbol.is(Flags.ParamAccessor | Flags.Private | Flags.Synthetic)).map { value =>
          val kind = if (value.symbol.is(Flags.Mutable)) "var" else "val"
          ValImpl(
            value.symbol,
            annotations(value.symbol),
            value.symbol.name.show,
            Nil, path(value.symbol),
            returnType(value.info),
            kind,
            implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
          )
        }

        defs ++ vals
      }
      else Nil
    }


    tree match {
      /** package */
      case pd @ PackageDef(pid, st) =>
        addPackage(PackageImpl(pd.symbol, annotations(pd.symbol), pd.symbol.showFullName, collectEntityMembers(st), path(pd.symbol)))

      /** type alias */
      case t: TypeDef if !t.isClassDef =>
        val sym = t.symbol
        if (sym.is(Flags.Synthetic | Flags.Param))
          NonEntity
        else {
          val tparams = t.rhs.tpe match {
            case tp: PolyType => tp.paramNames.map(_.show)
            case _ => Nil
          }
          TypeAliasImpl(sym, annotations(sym), flags(t), t.name.show.split("\\$\\$").last, path(sym), alias(t.rhs.tpe), tparams)
        }

      /** trait */
      case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
        //TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
        TraitImpl(t.symbol, annotations(t.symbol), n.show, collectMembers(rhs), flags(t), path(t.symbol), typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))

      /** objects, on the format "Object$" so drop the last letter */
      case o @ TypeDef(n, rhs) if o.symbol.is(Flags.Module) =>
{'fraction_non_alphanumeric': 0.12256857855361596, 'fraction_numerical': 0.00024937655860349125, 'mean_word_length': 2.4336472602739727, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1886093', 'n_tokens_mistral': 2463, 'n_tokens_neox': 2389, 'n_words': 532}